正在显示
7 个修改的文件
包含
250 行增加
和
122 行删除
trunk/auto/options.sh
100644 → 100755
| @@ -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 |
trunk/src/core/srs_core_forward.cpp
0 → 100644
| 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 | + |
trunk/src/core/srs_core_forward.hpp
0 → 100644
| 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, |
-
请 注册 或 登录 后发表评论