From 50feaacdde1fc11e370c5c74384401067467231a Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 10 Jul 2015 13:45:21 +0800 Subject: [PATCH 01/10] refine code for http remux reload. --- trunk/src/app/srs_app_config.cpp | 1 + trunk/src/app/srs_app_http_stream.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index ff5da2d2e..f3b4bb33a 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -853,6 +853,7 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) } } + // TODO: reload new http_remux in on_vhost_add // http_remux, only one per vhost. if (get_vhost_http_remux_enabled(vhost)) { for (it = subscribes.begin(); it != subscribes.end(); ++it) { diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index cea0138af..8b633d1f2 100644 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -1228,7 +1228,9 @@ int SrsHttpStreamServer::initialize_flv_streaming() continue; } - initialize_flv_entry(conf->arg0()); + if ((ret = initialize_flv_entry(conf->arg0())) != ERROR_SUCCESS) { + return ret; + } } return ret; } From b3b6df365e4f8d42b1eedd8f76916f77d5e35c3e Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 10 Jul 2015 13:50:35 +0800 Subject: [PATCH 02/10] fix the stream caster build failed bug. --- trunk/src/app/srs_app_config.cpp | 15 +++++++++++++++ trunk/src/app/srs_app_config.hpp | 3 +++ trunk/src/app/srs_app_server.cpp | 6 +++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index f3b4bb33a..4d72336b6 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4418,3 +4418,18 @@ bool srs_config_dvr_is_plan_append(string plan) { return plan == SRS_CONF_DEFAULT_DVR_PLAN_APPEND; } + +bool srs_stream_caster_is_udp(string caster) +{ + return caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP; +} + +bool srs_stream_caster_is_rtsp(string caster) +{ + return caster == SRS_CONF_DEFAULT_STREAM_CASTER_RTSP; +} + +bool srs_stream_caster_is_flv(string caster) +{ + return caster == SRS_CONF_DEFAULT_STREAM_CASTER_FLV; +} diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 8b7f5b854..2378d1e65 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -1143,6 +1143,9 @@ extern bool srs_config_ingest_is_stream(std::string type); extern bool srs_config_dvr_is_plan_segment(std::string plan); extern bool srs_config_dvr_is_plan_session(std::string plan); extern bool srs_config_dvr_is_plan_append(std::string plan); +extern bool srs_stream_caster_is_udp(std::string caster); +extern bool srs_stream_caster_is_rtsp(std::string caster); +extern bool srs_stream_caster_is_flv(std::string caster); // global config extern SrsConfig* _srs_config; diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 0f2b3f960..3591c8289 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -1120,11 +1120,11 @@ int SrsServer::listen_stream_caster() SrsListener* listener = NULL; std::string caster = _srs_config->get_stream_caster_engine(stream_caster); - if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP) { + if (srs_stream_caster_is_udp(caster)) { listener = new SrsUdpCasterListener(this, SrsListenerMpegTsOverUdp, stream_caster); - } else if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_RTSP) { + } else if (srs_stream_caster_is_rtsp(caster)) { listener = new SrsRtspListener(this, SrsListenerRtsp, stream_caster); - } else if (caster == SRS_CONF_DEFAULT_STREAM_CASTER_FLV) { + } else if (srs_stream_caster_is_flv(caster)) { listener = new SrsHttpFlvListener(this, SrsListenerFlv, stream_caster); } else { ret = ERROR_STREAM_CASTER_ENGINE; From ef5ddd01e492abfb29979af4a7993a28b161e337 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Jul 2015 12:08:53 +0800 Subject: [PATCH 03/10] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 000332310..1c5434c19 100755 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ #Simple-RTMP-Server -SRS/2.0,开发代号:[ZhouGuowen][release2] +SRS/2.0, [ZhouGuowen][release2] SRS定位是运营级的互联网直播服务器集群,追求更好的概念完整性和最简单实现的代码。
SRS is industrial-strength live streaming cluster, for the best conceptual integrity and the simplest implementation. Download from github.io: [Centos6-x86_64][centos0], [more...][more0]
Download from ossrs.net: [Centos6-x86_64][centos1], [more...][more1]
-Contact by QQ or Skype, read [Contact][contact] +Website for SRS/2.0, read SRS 2.0 [Chinese][srs2_CN] or [English][srs2_EN]. ## Why SRS? @@ -1021,5 +1021,6 @@ Winlin [centos0]: http://winlinvip.github.io/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip [centos1]: http://www.ossrs.net/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip - +[srs2_CN]: https://github.com/simple-rtmp-server/srs/wiki/v2_CN_Home +[srs2_EN]: https://github.com/simple-rtmp-server/srs/wiki/v2_EN_Home From be342178c0e118d94e65d0885cbaf3232d9ee931 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Jul 2015 22:09:01 +0800 Subject: [PATCH 04/10] fix ingest flv tool, support non monotonically timestamp. --- trunk/research/librtmp/srs_ingest_flv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trunk/research/librtmp/srs_ingest_flv.c b/trunk/research/librtmp/srs_ingest_flv.c index 7afb2d3b7..cabb77c8d 100644 --- a/trunk/research/librtmp/srs_ingest_flv.c +++ b/trunk/research/librtmp/srs_ingest_flv.c @@ -38,6 +38,7 @@ int proxy(srs_flv_t flv, srs_rtmp_t ortmp); int connect_oc(srs_rtmp_t ortmp); #define RE_PULSE_MS 300 +#define RE_PULSE_JITTER_MS 3000 int64_t re_create(); void re_update(int64_t re, int32_t starttime, u_int32_t time); void re_cleanup(int64_t re, int32_t starttime, u_int32_t time); @@ -256,7 +257,7 @@ void re_update(int64_t re, int32_t starttime, u_int32_t time) // send by pulse algorithm. int64_t now = srs_utils_time_ms(); int64_t diff = time - starttime - (now -re); - if (diff > RE_PULSE_MS) { + if (diff > RE_PULSE_MS && diff < RE_PULSE_JITTER_MS) { usleep((useconds_t)(diff * 1000)); } } From 54bb42483b210cc4067493d64da7af5114d48425 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Jul 2015 10:03:15 +0800 Subject: [PATCH 05/10] change time jitter to off for hls and forward. --- trunk/src/app/srs_app_forward.cpp | 6 +++--- trunk/src/app/srs_app_hls.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_forward.cpp b/trunk/src/app/srs_app_forward.cpp index eab350a5c..c1c41c574 100644 --- a/trunk/src/app/srs_app_forward.cpp +++ b/trunk/src/app/srs_app_forward.cpp @@ -164,7 +164,7 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata) SrsSharedPtrMessage* metadata = shared_metadata->copy(); // TODO: FIXME: config the jitter of Forwarder. - if ((ret = jitter->correct(metadata, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(metadata, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { srs_freep(metadata); return ret; } @@ -183,7 +183,7 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio) SrsSharedPtrMessage* msg = shared_audio->copy(); // TODO: FIXME: config the jitter of Forwarder. - if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { srs_freep(msg); return ret; } @@ -207,7 +207,7 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video) SrsSharedPtrMessage* msg = shared_video->copy(); // TODO: FIXME: config the jitter of Forwarder. - if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { srs_freep(msg); return ret; } diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 54eb18566..6decfc113 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1335,7 +1335,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio) } // TODO: FIXME: config the jitter of HLS. - if ((ret = jitter->correct(audio, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(audio, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { srs_error("rtmp jitter correct audio failed. ret=%d", ret); return ret; } @@ -1393,7 +1393,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video) } // TODO: FIXME: config the jitter of HLS. - if ((ret = jitter->correct(video, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(video, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { srs_error("rtmp jitter correct video failed. ret=%d", ret); return ret; } From 40c264a316e81cb217b4be8a6db1a199ba62226e Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Jul 2015 10:31:42 +0800 Subject: [PATCH 06/10] always reset the max target duration for hls. --- trunk/src/app/srs_app_hls.cpp | 15 +++++++++------ trunk/src/app/srs_app_hls.hpp | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 6decfc113..1bf50813e 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -280,7 +280,7 @@ SrsHlsMuxer::SrsHlsMuxer() previous_floor_ts = 0; accept_floor_ts = 0; hls_ts_floor = false; - target_duration = 0; + max_td = 0; _sequence_no = 0; current = NULL; acodec = SrsCodecAudioReserved1; @@ -400,10 +400,8 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, m3u8_url = srs_path_build_stream(m3u8_file, req->vhost, req->app, req->stream); m3u8 = path + "/" + m3u8_url; - // we always keep the target duration increasing. - int max_td = srs_max(target_duration, (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost))); - srs_info("hls update target duration %d=>%d, aof=%.2f", target_duration, max_td, aof_ratio); - target_duration = max_td; + // when update config, reset the history target duration. + max_td = (int)(fragment * _srs_config->get_hls_td_ratio(r->vhost)); std::string storage = _srs_config->get_hls_storage(r->vhost); if (storage == "ram") { @@ -861,6 +859,9 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file) ss << "#EXT-X-MEDIA-SEQUENCE:" << first->sequence_no << SRS_CONSTS_LF; srs_verbose("write m3u8 sequence success."); + // iterator shared for td generation and segemnts wrote. + std::vector::iterator it; + // #EXT-X-TARGETDURATION:4294967295\n /** * @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 25 @@ -871,11 +872,13 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file) * typical target duration is 10 seconds. */ // @see https://github.com/simple-rtmp-server/srs/issues/304#issuecomment-74000081 - std::vector::iterator it; + int target_duration = 0; for (it = segments.begin(); it != segments.end(); ++it) { SrsHlsSegment* segment = *it; target_duration = srs_max(target_duration, (int)ceil(segment->duration)); } + target_duration = srs_max(target_duration, max_td); + ss << "#EXT-X-TARGETDURATION:" << target_duration << SRS_CONSTS_LF; srs_verbose("write m3u8 duration success."); diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 431a0fb3f..27ab1da01 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -233,7 +233,7 @@ private: int64_t previous_floor_ts; private: int _sequence_no; - int target_duration; + int max_td; std::string m3u8; std::string m3u8_url; private: From 99574bb77bac2a0a15f75055cb2596f4a5eae757 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Jul 2015 10:43:21 +0800 Subject: [PATCH 07/10] ignore when no segments for there must no m3u8 --- trunk/src/app/srs_app_hls.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 1bf50813e..5a4920e03 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -697,7 +697,9 @@ int SrsHlsMuxer::segment_close(string log_desc) srs_assert(it == segments.end()); // valid, add to segments if segment duration is ok - if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) { + // when too small, it maybe not enough data to play. + // when too large, it maybe timestamp corrupt. + if (current->duration * 1000 >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS && (int)current->duration <= max_td) { segments.push_back(current); // use async to call the http hooks, for it will cause thread switch. @@ -748,7 +750,6 @@ int SrsHlsMuxer::segment_close(string log_desc) // rename from tmp to real path std::string tmp_file = current->full_path + ".tmp"; if (should_write_file) { - unlink(tmp_file.c_str()); if (unlink(tmp_file.c_str()) < 0) { srs_warn("ignore unlink path failed, file=%s.", tmp_file.c_str()); } @@ -815,6 +816,11 @@ int SrsHlsMuxer::refresh_m3u8() { int ret = ERROR_SUCCESS; + // no segments, also no m3u8, return. + if (segments.size() == 0) { + return ret; + } + std::string temp_m3u8 = m3u8 + ".temp"; if ((ret = _refresh_m3u8(temp_m3u8)) == ERROR_SUCCESS) { if (should_write_file && rename(temp_m3u8.c_str(), m3u8.c_str()) < 0) { @@ -824,7 +830,9 @@ int SrsHlsMuxer::refresh_m3u8() } // remove the temp file. - unlink(temp_m3u8.c_str()); + if (unlink(temp_m3u8.c_str()) < 0) { + srs_warn("ignore remove m3u8 failed, %s", temp_m3u8.c_str()); + } return ret; } From 6fe36afcfac56b1e7b5f7b833ae8d85ac4e1053d Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Jul 2015 11:00:58 +0800 Subject: [PATCH 08/10] when hls timestamp jump, reset it. --- trunk/src/app/srs_app_hls.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 5a4920e03..526ff3b1e 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -53,6 +53,8 @@ using namespace std; // drop the segment when duration of ts too small. #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 +// when hls timestamp jump, reset it. +#define SRS_AUTO_HLS_SEGMENT_TIMESTAMP_JUMP_MS 300 // fragment plus the deviation percent. #define SRS_HLS_FLOOR_REAP_PERCENT 0.3 @@ -161,6 +163,11 @@ void SrsHlsSegment::update_duration(int64_t current_frame_dts) // update the segment duration, which is nagetive, // just ignore it. if (current_frame_dts < segment_start_dts) { + // for atc and timestamp jump, reset the start dts. + if (current_frame_dts < segment_start_dts - SRS_AUTO_HLS_SEGMENT_TIMESTAMP_JUMP_MS * 90) { + srs_warn("hls timestamp jump %"PRId64"=>%"PRId64, segment_start_dts, current_frame_dts); + segment_start_dts = current_frame_dts; + } return; } @@ -830,8 +837,10 @@ int SrsHlsMuxer::refresh_m3u8() } // remove the temp file. - if (unlink(temp_m3u8.c_str()) < 0) { - srs_warn("ignore remove m3u8 failed, %s", temp_m3u8.c_str()); + if (srs_path_exists(temp_m3u8)) { + if (unlink(temp_m3u8.c_str()) < 0) { + srs_warn("ignore remove m3u8 failed, %s", temp_m3u8.c_str()); + } } return ret; From 9743e025415b9306a3bebca99c76f1acda8e04f1 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Jul 2015 11:28:00 +0800 Subject: [PATCH 09/10] refine the mix correct algorithm. --- trunk/src/app/srs_app_source.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 4b25901f1..5dd98c204 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -55,8 +55,8 @@ using namespace std; // 115 packets is 3s. #define SRS_PURE_AUDIO_GUESS_COUNT 115 -// when got these videos or audios, mix ok. -#define SRS_MIX_CORRECT_MIX_AV 10 +// when got these videos or audios, pure audio or video, mix ok. +#define SRS_MIX_CORRECT_PURE_AV 10 int _srs_time_jitter_string2int(std::string time_jitter) { @@ -849,12 +849,25 @@ void SrsMixQueue::push(SrsSharedPtrMessage* msg) SrsSharedPtrMessage* SrsMixQueue::pop() { - // when got 10+ videos or audios, mix ok. - // when got 1 video and 1 audio, mix ok. - if (nb_videos < SRS_MIX_CORRECT_MIX_AV && nb_audios < SRS_MIX_CORRECT_MIX_AV) { - if (nb_videos < 1 || nb_audios < 1) { - return NULL; - } + bool mix_ok = false; + + // pure video + if (nb_videos >= SRS_MIX_CORRECT_PURE_AV && nb_audios == 0) { + mix_ok = true; + } + + // pure audio + if (nb_audios >= SRS_MIX_CORRECT_PURE_AV && nb_videos == 0) { + mix_ok = true; + } + + // got 1 video and 1 audio, mix ok. + if (nb_videos >= 1 && nb_audios >= 1) { + mix_ok = true; + } + + if (!mix_ok) { + return NULL; } // pop the first msg. From d995726feef1df7012e6669091147503412536bf Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Jul 2015 11:31:17 +0800 Subject: [PATCH 10/10] fix the http flv mount bug. --- trunk/src/app/srs_app_http_stream.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 8b633d1f2..5d99d9917 100644 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -805,7 +805,14 @@ int SrsHttpStreamServer::http_mount(SrsSource* s, SrsRequest* r) entry->cache = new SrsStreamCache(s, r); entry->stream = new SrsLiveStream(s, r, entry->cache); - srs_assert(!tmpl->req); + // TODO: FIXME: maybe refine the logic of http remux service. + // if user push streams followed: + // rtmp://test.com/live/stream1 + // rtmp://test.com/live/stream2 + // and they will using the same template, such as: [vhost]/[app]/[stream].flv + // so, need to free last request object, otherwise, it will cause memory leak. + srs_freep(tmpl->req); + tmpl->source = s; tmpl->req = r->copy(); @@ -1170,8 +1177,8 @@ int SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) std::string sid = r->get_stream_url(); // check if the stream is enabled. if (sflvs.find(sid) != sflvs.end()) { - SrsLiveEntry* entry = sflvs[sid]; - if (!entry->stream->entry->enabled) { + SrsLiveEntry* s_entry = sflvs[sid]; + if (!s_entry->stream->entry->enabled) { srs_error("stream is disabled, hijack failed. ret=%d", ret); return ret; }