winlin

refine source, extract gop cache, add srs forwarder.

@@ -5,6 +5,10 @@ help=no @@ -5,6 +5,10 @@ help=no
5 SRS_HLS=RESERVED 5 SRS_HLS=RESERVED
6 SRS_SSL=RESERVED 6 SRS_SSL=RESERVED
7 7
  8 +# TODO: remove the default to yes.
  9 +SRS_HLS=YES
  10 +SRS_SSL=YES
  11 +
8 opt= 12 opt=
9 13
10 for option 14 for option
@@ -6,14 +6,14 @@ SRS_AUTO_HEADERS_H="${SRS_OBJS}/srs_auto_headers.hpp" @@ -6,14 +6,14 @@ SRS_AUTO_HEADERS_H="${SRS_OBJS}/srs_auto_headers.hpp"
6 6
7 mkdir -p ${SRS_OBJS} 7 mkdir -p ${SRS_OBJS}
8 8
  9 +# parse user options.
  10 +. auto/options.sh
  11 +
9 # clean the exists 12 # clean the exists
10 if [[ -f Makefile ]]; then 13 if [[ -f Makefile ]]; then
11 make clean 14 make clean
12 fi 15 fi
13 16
14 -# parse user options.  
15 -. auto/options.sh  
16 -  
17 # generate the audo headers file. 17 # generate the audo headers file.
18 echo "#define SRS_CONFIGURE \"${SRS_CONFIGURE}\"" > $SRS_AUTO_HEADERS_H 18 echo "#define SRS_CONFIGURE \"${SRS_CONFIGURE}\"" > $SRS_AUTO_HEADERS_H
19 19
@@ -92,7 +92,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" @@ -92,7 +92,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server"
92 "srs_core_stream" "srs_core_source" "srs_core_codec" 92 "srs_core_stream" "srs_core_source" "srs_core_codec"
93 "srs_core_handshake" "srs_core_pithy_print" 93 "srs_core_handshake" "srs_core_pithy_print"
94 "srs_core_config" "srs_core_refer" "srs_core_reload" 94 "srs_core_config" "srs_core_refer" "srs_core_reload"
95 - "srs_core_hls") 95 + "srs_core_hls" "srs_core_forward")
96 MODULE_DIR="src/core" . auto/modules.sh 96 MODULE_DIR="src/core" . auto/modules.sh
97 CORE_OBJS="${MODULE_OBJS[@]}" 97 CORE_OBJS="${MODULE_OBJS[@]}"
98 98
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_core_forward.hpp>
  25 +
  26 +SrsForwarder::SrsForwarder()
  27 +{
  28 +}
  29 +
  30 +SrsForwarder::~SrsForwarder()
  31 +{
  32 +}
  33 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_CORE_FORWARD_HPP
  25 +#define SRS_CORE_FORWARD_HPP
  26 +
  27 +/*
  28 +#include <srs_core_forward.hpp>
  29 +*/
  30 +#include <srs_core.hpp>
  31 +
  32 +/**
  33 +* forward the stream to other servers.
  34 +*/
  35 +class SrsForwarder
  36 +{
  37 +public:
  38 + SrsForwarder();
  39 + virtual ~SrsForwarder();
  40 +public:
  41 +};
  42 +
  43 +#endif
@@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <srs_core_amf0.hpp> 31 #include <srs_core_amf0.hpp>
32 #include <srs_core_codec.hpp> 32 #include <srs_core_codec.hpp>
33 #include <srs_core_hls.hpp> 33 #include <srs_core_hls.hpp>
  34 +#include <srs_core_forward.hpp>
34 35
35 #define CONST_MAX_JITTER_MS 500 36 #define CONST_MAX_JITTER_MS 500
36 #define DEFAULT_FRAME_TIME_MS 10 37 #define DEFAULT_FRAME_TIME_MS 10
@@ -49,8 +50,8 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) @@ -49,8 +50,8 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv)
49 { 50 {
50 int ret = ERROR_SUCCESS; 51 int ret = ERROR_SUCCESS;
51 52
52 - int audio_sample_rate = tba;  
53 - int video_frame_rate = tbv; 53 + int sample_rate = tba;
  54 + int frame_rate = tbv;
54 55
55 /** 56 /**
56 * we use a very simple time jitter detect/correct algorithm: 57 * we use a very simple time jitter detect/correct algorithm:
@@ -68,10 +69,10 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) @@ -68,10 +69,10 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv)
68 // if jitter detected, reset the delta. 69 // if jitter detected, reset the delta.
69 if (delta < 0 || delta > CONST_MAX_JITTER_MS) { 70 if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
70 // calc the right diff by audio sample rate 71 // calc the right diff by audio sample rate
71 - if (msg->header.is_audio() && audio_sample_rate > 0) {  
72 - delta = (int32_t)(delta * 1000.0 / audio_sample_rate);  
73 - } else if (msg->header.is_video() && video_frame_rate > 0) {  
74 - delta = (int32_t)(delta * 1.0 / video_frame_rate); 72 + if (msg->header.is_audio() && sample_rate > 0) {
  73 + delta = (int32_t)(delta * 1000.0 / sample_rate);
  74 + } else if (msg->header.is_video() && frame_rate > 0) {
  75 + delta = (int32_t)(delta * 1.0 / frame_rate);
75 } else { 76 } else {
76 delta = DEFAULT_FRAME_TIME_MS; 77 delta = DEFAULT_FRAME_TIME_MS;
77 } 78 }
@@ -129,6 +130,7 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv) @@ -129,6 +130,7 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv)
129 return ret; 130 return ret;
130 } 131 }
131 132
  133 + // TODO: check the queue size and drop packets if overflow.
132 msgs.push_back(msg); 134 msgs.push_back(msg);
133 135
134 return ret; 136 return ret;
@@ -242,6 +244,96 @@ void SrsConsumer::clear() @@ -242,6 +244,96 @@ void SrsConsumer::clear()
242 msgs.clear(); 244 msgs.clear();
243 } 245 }
244 246
  247 +SrsGopCache::SrsGopCache()
  248 +{
  249 + cached_video_count = 0;
  250 + enable_gop_cache = true;
  251 +}
  252 +
  253 +SrsGopCache::~SrsGopCache()
  254 +{
  255 + clear();
  256 +}
  257 +
  258 +void SrsGopCache::set(bool enabled)
  259 +{
  260 + enable_gop_cache = enabled;
  261 +
  262 + if (!enabled) {
  263 + srs_info("disable gop cache, clear %d packets.", (int)gop_cache.size());
  264 + clear();
  265 + return;
  266 + }
  267 +
  268 + srs_info("enable gop cache");
  269 +}
  270 +
  271 +int SrsGopCache::cache(SrsSharedPtrMessage* msg)
  272 +{
  273 + int ret = ERROR_SUCCESS;
  274 +
  275 + if (!enable_gop_cache) {
  276 + srs_verbose("gop cache is disabled.");
  277 + return ret;
  278 + }
  279 +
  280 + // got video, update the video count if acceptable
  281 + if (msg->header.is_video()) {
  282 + cached_video_count++;
  283 + }
  284 +
  285 + // no acceptable video or pure audio, disable the cache.
  286 + if (cached_video_count == 0) {
  287 + srs_verbose("ignore any frame util got a h264 video frame.");
  288 + return ret;
  289 + }
  290 +
  291 + // clear gop cache when got key frame
  292 + if (msg->header.is_video() && SrsCodec::video_is_keyframe(msg->payload, msg->size)) {
  293 + srs_info("clear gop cache when got keyframe. vcount=%d, count=%d",
  294 + cached_video_count, (int)gop_cache.size());
  295 +
  296 + clear();
  297 +
  298 + // curent msg is video frame, so we set to 1.
  299 + cached_video_count = 1;
  300 + }
  301 +
  302 + // cache the frame.
  303 + gop_cache.push_back(msg->copy());
  304 +
  305 + return ret;
  306 +}
  307 +
  308 +void SrsGopCache::clear()
  309 +{
  310 + std::vector<SrsSharedPtrMessage*>::iterator it;
  311 + for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
  312 + SrsSharedPtrMessage* msg = *it;
  313 + srs_freep(msg);
  314 + }
  315 + gop_cache.clear();
  316 +
  317 + cached_video_count = 0;
  318 +}
  319 +
  320 +int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv)
  321 +{
  322 + int ret = ERROR_SUCCESS;
  323 +
  324 + std::vector<SrsSharedPtrMessage*>::iterator it;
  325 + for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
  326 + SrsSharedPtrMessage* msg = *it;
  327 + if ((ret = consumer->enqueue(msg->copy(), tba, tbv)) != ERROR_SUCCESS) {
  328 + srs_error("dispatch cached gop failed. ret=%d", ret);
  329 + return ret;
  330 + }
  331 + }
  332 + srs_trace("dispatch cached gop success. count=%d, duration=%d", (int)gop_cache.size(), consumer->get_time());
  333 +
  334 + return ret;
  335 +}
  336 +
245 std::map<std::string, SrsSource*> SrsSource::pool; 337 std::map<std::string, SrsSource*> SrsSource::pool;
246 338
247 SrsSource* SrsSource::find(std::string stream_url) 339 SrsSource* SrsSource::find(std::string stream_url)
@@ -264,11 +356,10 @@ SrsSource::SrsSource(std::string _stream_url) @@ -264,11 +356,10 @@ SrsSource::SrsSource(std::string _stream_url)
264 356
265 cache_metadata = cache_sh_video = cache_sh_audio = NULL; 357 cache_metadata = cache_sh_video = cache_sh_audio = NULL;
266 358
267 - cached_video_count = 0;  
268 - enable_gop_cache = true;  
269 -  
270 - video_frame_rate = audio_sample_rate = 0; 359 + frame_rate = sample_rate = 0;
271 _can_publish = true; 360 _can_publish = true;
  361 +
  362 + gop_cache = new SrsGopCache();
272 } 363 }
273 364
274 SrsSource::~SrsSource() 365 SrsSource::~SrsSource()
@@ -280,12 +371,12 @@ SrsSource::~SrsSource() @@ -280,12 +371,12 @@ SrsSource::~SrsSource()
280 } 371 }
281 consumers.clear(); 372 consumers.clear();
282 373
283 - clear_gop_cache();  
284 -  
285 srs_freep(cache_metadata); 374 srs_freep(cache_metadata);
286 srs_freep(cache_sh_video); 375 srs_freep(cache_sh_video);
287 srs_freep(cache_sh_audio); 376 srs_freep(cache_sh_audio);
288 377
  378 + srs_freep(gop_cache);
  379 +
289 #ifdef SRS_HLS 380 #ifdef SRS_HLS
290 srs_freep(hls); 381 srs_freep(hls);
291 #endif 382 #endif
@@ -313,12 +404,12 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata @@ -313,12 +404,12 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
313 SrsAmf0Any* prop = NULL; 404 SrsAmf0Any* prop = NULL;
314 if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) { 405 if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) {
315 if (prop->is_number()) { 406 if (prop->is_number()) {
316 - audio_sample_rate = (int)(srs_amf0_convert<SrsAmf0Number>(prop)->value); 407 + sample_rate = (int)(srs_amf0_convert<SrsAmf0Number>(prop)->value);
317 } 408 }
318 } 409 }
319 if ((prop = metadata->metadata->get_property("framerate")) != NULL) { 410 if ((prop = metadata->metadata->get_property("framerate")) != NULL) {
320 if (prop->is_number()) { 411 if (prop->is_number()) {
321 - video_frame_rate = (int)(srs_amf0_convert<SrsAmf0Number>(prop)->value); 412 + frame_rate = (int)(srs_amf0_convert<SrsAmf0Number>(prop)->value);
322 } 413 }
323 } 414 }
324 415
@@ -354,7 +445,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata @@ -354,7 +445,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
354 std::vector<SrsConsumer*>::iterator it; 445 std::vector<SrsConsumer*>::iterator it;
355 for (it = consumers.begin(); it != consumers.end(); ++it) { 446 for (it = consumers.begin(); it != consumers.end(); ++it) {
356 SrsConsumer* consumer = *it; 447 SrsConsumer* consumer = *it;
357 - if ((ret = consumer->enqueue(cache_metadata->copy(), audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) { 448 + if ((ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
358 srs_error("dispatch the metadata failed. ret=%d", ret); 449 srs_error("dispatch the metadata failed. ret=%d", ret);
359 return ret; 450 return ret;
360 } 451 }
@@ -387,7 +478,7 @@ int SrsSource::on_audio(SrsCommonMessage* audio) @@ -387,7 +478,7 @@ int SrsSource::on_audio(SrsCommonMessage* audio)
387 std::vector<SrsConsumer*>::iterator it; 478 std::vector<SrsConsumer*>::iterator it;
388 for (it = consumers.begin(); it != consumers.end(); ++it) { 479 for (it = consumers.begin(); it != consumers.end(); ++it) {
389 SrsConsumer* consumer = *it; 480 SrsConsumer* consumer = *it;
390 - if ((ret = consumer->enqueue(msg->copy(), audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) { 481 + if ((ret = consumer->enqueue(msg->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
391 srs_error("dispatch the audio failed. ret=%d", ret); 482 srs_error("dispatch the audio failed. ret=%d", ret);
392 return ret; 483 return ret;
393 } 484 }
@@ -403,7 +494,7 @@ int SrsSource::on_audio(SrsCommonMessage* audio) @@ -403,7 +494,7 @@ int SrsSource::on_audio(SrsCommonMessage* audio)
403 } 494 }
404 495
405 // cache the last gop packets 496 // cache the last gop packets
406 - if ((ret = cache_last_gop(msg)) != ERROR_SUCCESS) { 497 + if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) {
407 srs_error("shrink gop cache failed. ret=%d", ret); 498 srs_error("shrink gop cache failed. ret=%d", ret);
408 return ret; 499 return ret;
409 } 500 }
@@ -435,7 +526,7 @@ int SrsSource::on_video(SrsCommonMessage* video) @@ -435,7 +526,7 @@ int SrsSource::on_video(SrsCommonMessage* video)
435 std::vector<SrsConsumer*>::iterator it; 526 std::vector<SrsConsumer*>::iterator it;
436 for (it = consumers.begin(); it != consumers.end(); ++it) { 527 for (it = consumers.begin(); it != consumers.end(); ++it) {
437 SrsConsumer* consumer = *it; 528 SrsConsumer* consumer = *it;
438 - if ((ret = consumer->enqueue(msg->copy(), audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) { 529 + if ((ret = consumer->enqueue(msg->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
439 srs_error("dispatch the video failed. ret=%d", ret); 530 srs_error("dispatch the video failed. ret=%d", ret);
440 return ret; 531 return ret;
441 } 532 }
@@ -451,7 +542,7 @@ int SrsSource::on_video(SrsCommonMessage* video) @@ -451,7 +542,7 @@ int SrsSource::on_video(SrsCommonMessage* video)
451 } 542 }
452 543
453 // cache the last gop packets 544 // cache the last gop packets
454 - if ((ret = cache_last_gop(msg)) != ERROR_SUCCESS) { 545 + if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) {
455 srs_error("shrink gop cache failed. ret=%d", ret); 546 srs_error("shrink gop cache failed. ret=%d", ret);
456 return ret; 547 return ret;
457 } 548 }
@@ -480,10 +571,10 @@ void SrsSource::on_unpublish() @@ -480,10 +571,10 @@ void SrsSource::on_unpublish()
480 hls->on_unpublish(); 571 hls->on_unpublish();
481 #endif 572 #endif
482 573
483 - clear_gop_cache(); 574 + gop_cache->clear();
484 575
485 srs_freep(cache_metadata); 576 srs_freep(cache_metadata);
486 - video_frame_rate = audio_sample_rate = 0; 577 + frame_rate = sample_rate = 0;
487 578
488 srs_freep(cache_sh_video); 579 srs_freep(cache_sh_video);
489 srs_freep(cache_sh_audio); 580 srs_freep(cache_sh_audio);
@@ -500,33 +591,27 @@ void SrsSource::on_unpublish() @@ -500,33 +591,27 @@ void SrsSource::on_unpublish()
500 consumer = new SrsConsumer(this); 591 consumer = new SrsConsumer(this);
501 consumers.push_back(consumer); 592 consumers.push_back(consumer);
502 593
503 - if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) { 594 + if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
504 srs_error("dispatch metadata failed. ret=%d", ret); 595 srs_error("dispatch metadata failed. ret=%d", ret);
505 return ret; 596 return ret;
506 } 597 }
507 srs_info("dispatch metadata success"); 598 srs_info("dispatch metadata success");
508 599
509 - if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) { 600 + if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
510 srs_error("dispatch video sequence header failed. ret=%d", ret); 601 srs_error("dispatch video sequence header failed. ret=%d", ret);
511 return ret; 602 return ret;
512 } 603 }
513 srs_info("dispatch video sequence header success"); 604 srs_info("dispatch video sequence header success");
514 605
515 - if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) { 606 + if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) {
516 srs_error("dispatch audio sequence header failed. ret=%d", ret); 607 srs_error("dispatch audio sequence header failed. ret=%d", ret);
517 return ret; 608 return ret;
518 } 609 }
519 srs_info("dispatch audio sequence header success"); 610 srs_info("dispatch audio sequence header success");
520 611
521 - std::vector<SrsSharedPtrMessage*>::iterator it;  
522 - for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {  
523 - SrsSharedPtrMessage* msg = *it;  
524 - if ((ret = consumer->enqueue(msg->copy(), audio_sample_rate, video_frame_rate)) != ERROR_SUCCESS) {  
525 - srs_error("dispatch cached gop failed. ret=%d", ret);  
526 - return ret;  
527 - } 612 + if ((ret = gop_cache->dump(consumer, sample_rate, frame_rate)) != ERROR_SUCCESS) {
  613 + return ret;
528 } 614 }
529 - srs_trace("dispatch cached gop success. count=%d, duration=%d", (int)gop_cache.size(), consumer->get_time());  
530 615
531 return ret; 616 return ret;
532 } 617 }
@@ -543,63 +628,6 @@ void SrsSource::on_consumer_destroy(SrsConsumer* consumer) @@ -543,63 +628,6 @@ void SrsSource::on_consumer_destroy(SrsConsumer* consumer)
543 628
544 void SrsSource::set_cache(bool enabled) 629 void SrsSource::set_cache(bool enabled)
545 { 630 {
546 - enable_gop_cache = enabled;  
547 -  
548 - if (!enabled) {  
549 - srs_info("disable gop cache, clear %d packets.", (int)gop_cache.size());  
550 - clear_gop_cache();  
551 - return;  
552 - }  
553 -  
554 - srs_info("enable gop cache");  
555 -}  
556 -  
557 -int SrsSource::cache_last_gop(SrsSharedPtrMessage* msg)  
558 -{  
559 - int ret = ERROR_SUCCESS;  
560 -  
561 - if (!enable_gop_cache) {  
562 - srs_verbose("gop cache is disabled.");  
563 - return ret;  
564 - }  
565 -  
566 - // got video, update the video count if acceptable  
567 - if (msg->header.is_video()) {  
568 - cached_video_count++;  
569 - }  
570 -  
571 - // no acceptable video or pure audio, disable the cache.  
572 - if (cached_video_count == 0) {  
573 - srs_verbose("ignore any frame util got a h264 video frame.");  
574 - return ret;  
575 - }  
576 -  
577 - // clear gop cache when got key frame  
578 - if (msg->header.is_video() && SrsCodec::video_is_keyframe(msg->payload, msg->size)) {  
579 - srs_info("clear gop cache when got keyframe. vcount=%d, count=%d",  
580 - cached_video_count, (int)gop_cache.size());  
581 -  
582 - clear_gop_cache();  
583 -  
584 - // curent msg is video frame, so we set to 1.  
585 - cached_video_count = 1;  
586 - }  
587 -  
588 - // cache the frame.  
589 - gop_cache.push_back(msg->copy());  
590 -  
591 - return ret;  
592 -}  
593 -  
594 -void SrsSource::clear_gop_cache()  
595 -{  
596 - std::vector<SrsSharedPtrMessage*>::iterator it;  
597 - for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {  
598 - SrsSharedPtrMessage* msg = *it;  
599 - srs_freep(msg);  
600 - }  
601 - gop_cache.clear();  
602 -  
603 - cached_video_count = 0; 631 + gop_cache->set(enabled);
604 } 632 }
605 633
@@ -38,6 +38,7 @@ class SrsSource; @@ -38,6 +38,7 @@ class SrsSource;
38 class SrsCommonMessage; 38 class SrsCommonMessage;
39 class SrsOnMetaDataPacket; 39 class SrsOnMetaDataPacket;
40 class SrsSharedPtrMessage; 40 class SrsSharedPtrMessage;
  41 +class SrsForwarder;
41 #ifdef SRS_HLS 42 #ifdef SRS_HLS
42 class SrsHls; 43 class SrsHls;
43 #endif 44 #endif
@@ -112,6 +113,43 @@ private: @@ -112,6 +113,43 @@ private:
112 }; 113 };
113 114
114 /** 115 /**
  116 +* cache a gop of video/audio data,
  117 +* delivery at the connect of flash player,
  118 +* to enable it to fast startup.
  119 +*/
  120 +class SrsGopCache
  121 +{
  122 +private:
  123 + /**
  124 + * if disabled the gop cache,
  125 + * the client will wait for the next keyframe for h264,
  126 + * and will be black-screen.
  127 + */
  128 + bool enable_gop_cache;
  129 + /**
  130 + * the video frame count, avoid cache for pure audio stream.
  131 + */
  132 + int cached_video_count;
  133 + /**
  134 + * cached gop.
  135 + */
  136 + std::vector<SrsSharedPtrMessage*> gop_cache;
  137 +public:
  138 + SrsGopCache();
  139 + virtual ~SrsGopCache();
  140 +public:
  141 + virtual void set(bool enabled);
  142 + /**
  143 + * only for h264 codec
  144 + * 1. cache the gop when got h264 video packet.
  145 + * 2. clear gop when got keyframe.
  146 + */
  147 + virtual int cache(SrsSharedPtrMessage* msg);
  148 + virtual void clear();
  149 + virtual int dump(SrsConsumer* consumer, int tba, int tbv);
  150 +};
  151 +
  152 +/**
115 * live streaming source. 153 * live streaming source.
116 */ 154 */
117 class SrsSource 155 class SrsSource
@@ -127,36 +165,24 @@ public: @@ -127,36 +165,24 @@ public:
127 */ 165 */
128 static SrsSource* find(std::string stream_url); 166 static SrsSource* find(std::string stream_url);
129 private: 167 private:
130 -#ifdef SRS_HLS  
131 - SrsHls* hls;  
132 -#endif  
133 std::string stream_url; 168 std::string stream_url;
134 std::vector<SrsConsumer*> consumers; 169 std::vector<SrsConsumer*> consumers;
135 -// gop cache for client fast startup.  
136 private: 170 private:
137 - /**  
138 - * if disabled the gop cache,  
139 - * the client will wait for the next keyframe for h264,  
140 - * and will be black-screen.  
141 - */  
142 - bool enable_gop_cache;  
143 - /**  
144 - * the video frame count, avoid cache for pure audio stream.  
145 - */  
146 - int cached_video_count;  
147 - /**  
148 - * cached gop.  
149 - */  
150 - std::vector<SrsSharedPtrMessage*> gop_cache; 171 + // hls handler.
  172 +#ifdef SRS_HLS
  173 + SrsHls* hls;
  174 +#endif
  175 + // gop cache for client fast startup.
  176 + SrsGopCache* gop_cache;
151 private: 177 private:
152 /** 178 /**
153 * the sample rate of audio in metadata. 179 * the sample rate of audio in metadata.
154 */ 180 */
155 - int audio_sample_rate; 181 + int sample_rate;
156 /** 182 /**
157 * the video frame rate in metadata. 183 * the video frame rate in metadata.
158 */ 184 */
159 - int video_frame_rate; 185 + int frame_rate;
160 /** 186 /**
161 * can publish, true when is not streaming 187 * can publish, true when is not streaming
162 */ 188 */
@@ -181,14 +207,6 @@ public: @@ -181,14 +207,6 @@ public:
181 virtual int create_consumer(SrsConsumer*& consumer); 207 virtual int create_consumer(SrsConsumer*& consumer);
182 virtual void on_consumer_destroy(SrsConsumer* consumer); 208 virtual void on_consumer_destroy(SrsConsumer* consumer);
183 virtual void set_cache(bool enabled); 209 virtual void set_cache(bool enabled);
184 -private:  
185 - /**  
186 - * only for h264 codec  
187 - * 1. cache the gop when got h264 video packet.  
188 - * 2. clear gop when got keyframe.  
189 - */  
190 - virtual int cache_last_gop(SrsSharedPtrMessage* msg);  
191 - virtual void clear_gop_cache();  
192 }; 210 };
193 211
194 #endif 212 #endif
@@ -24,6 +24,8 @@ file @@ -24,6 +24,8 @@ file
24 ..\core\srs_core_client.cpp, 24 ..\core\srs_core_client.cpp,
25 ..\core\srs_core_source.hpp, 25 ..\core\srs_core_source.hpp,
26 ..\core\srs_core_source.cpp, 26 ..\core\srs_core_source.cpp,
  27 + ..\core\srs_core_forward.hpp,
  28 + ..\core\srs_core_forward.cpp,
27 ..\core\srs_core_hls.hpp, 29 ..\core\srs_core_hls.hpp,
28 ..\core\srs_core_hls.cpp, 30 ..\core\srs_core_hls.cpp,
29 ..\core\srs_core_codec.hpp, 31 ..\core\srs_core_codec.hpp,