正在显示
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, |
-
请 注册 或 登录 后发表评论