diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index d5d4424d81..0e14aa9987 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1108,6 +1108,26 @@ vhost play.srs.com { # if off, use time_jitter to correct the timestamp if required. # default: off mix_correct off; + + # vhost for atc for hls/hds/rtmp backup. + # generally, atc default to off, server delivery rtmp stream to client(flash) timestamp from 0. + # when atc is on, server delivery rtmp stream by absolute time. + # atc is used, for instance, encoder will copy stream to master and slave server, + # server use atc to delivery stream to edge/client, where stream time from master/slave server + # is always the same, client/tools can slice RTMP stream to HLS according to the same time, + # if the time not the same, the HLS stream cannot slice to support system backup. + # + # @see http://www.adobe.com/cn/devnet/adobe-media-server/articles/varnish-sample-for-failover.html + # @see http://www.baidu.com/#wd=hds%20hls%20atc + # + # default: off + atc off; + # whether enable the auto atc, + # if enabled, detect the bravo_atc="true" in onMetaData packet, + # set atc to on if matched. + # always ignore the onMetaData if atc_auto is off. + # default: off + atc_auto off; } } @@ -1121,24 +1141,9 @@ vhost jitter.srs.com { # vhost for atc. vhost atc.srs.com { - # vhost for atc for hls/hds/rtmp backup. - # generally, atc default to off, server delivery rtmp stream to client(flash) timestamp from 0. - # when atc is on, server delivery rtmp stream by absolute time. - # atc is used, for instance, encoder will copy stream to master and slave server, - # server use atc to delivery stream to edge/client, where stream time from master/slave server - # is always the same, client/tools can slice RTMP stream to HLS according to the same time, - # if the time not the same, the HLS stream cannot slice to support system backup. - # - # @see http://www.adobe.com/cn/devnet/adobe-media-server/articles/varnish-sample-for-failover.html - # @see http://www.baidu.com/#wd=hds%20hls%20atc - # - # default: off + # @see play.srs.com atc on; - # whether enable the auto atc, - # if enabled, detect the bravo_atc="true" in onMetaData packet, - # set atc to on if matched. - # always ignore the onMetaData if atc_auto is off. - # default: on + # @see play.srs.com atc_auto on; } diff --git a/trunk/conf/full.one.vhost.conf b/trunk/conf/full.one.vhost.conf index ffd669d541..8537323812 100644 --- a/trunk/conf/full.one.vhost.conf +++ b/trunk/conf/full.one.vhost.conf @@ -71,10 +71,10 @@ vhost vhost.srs.com { time_jitter full; mix_correct off; - # TODO atc on; atc_auto on; - + + # TODO min_latency on; mw_latency 100; diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 918ed2d6ab..df39ef0031 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -695,18 +695,6 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) // ENABLED => ENABLED (modified) if (get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { srs_trace("vhost %s maybe modified, reload its detail.", vhost.c_str()); - // atc, only one per vhost - if (!srs_directive_equals(new_vhost->get("atc"), old_vhost->get("atc"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_vhost_atc(vhost)) != ERROR_SUCCESS) { - srs_error("vhost %s notify subscribes atc failed. ret=%d", vhost.c_str(), ret); - return ret; - } - } - srs_trace("vhost %s reload atc success.", vhost.c_str()); - } - // gop_cache, only one per vhost if (!srs_directive_equals(new_vhost->get("gop_cache"), old_vhost->get("gop_cache"))) { for (it = subscribes.begin(); it != subscribes.end(); ++it) { @@ -1742,14 +1730,6 @@ int SrsConfig::vhost_to_json(SrsConfDirective* vhost, SrsAmf0Object* obj) obj->set("chunk_size", dir->dumps_arg0_to_number()); } - // atc - if ((dir = vhost->get("atc")) != NULL) { - obj->set("atc", dir->dumps_arg0_to_boolean()); - } - if ((dir = vhost->get("atc_auto")) != NULL) { - obj->set("atc_auto", dir->dumps_arg0_to_boolean()); - } - // mrw if ((dir = vhost->get("min_latency")) != NULL) { obj->set("min_latency", dir->dumps_arg0_to_boolean()); @@ -1789,6 +1769,10 @@ int SrsConfig::vhost_to_json(SrsConfDirective* vhost, SrsAmf0Object* obj) play->set("time_jitter", sdir->dumps_arg0_to_str()); } else if (sdir->name == "mix_correct") { play->set("mix_correct", sdir->dumps_arg0_to_boolean()); + } else if (sdir->name == "atc") { + play->set("atc", sdir->dumps_arg0_to_boolean()); + } else if (sdir->name == "atc_auto") { + play->set("atc_auto", sdir->dumps_arg0_to_boolean()); } } } @@ -2671,8 +2655,7 @@ int SrsConfig::check_config() && n != "dvr" && n != "ingest" && n != "hls" && n != "http_hooks" && n != "gop_cache" && n != "queue_length" && n != "refer" && n != "forward" && n != "transcode" && n != "bandcheck" - && n != "atc" && n != "atc_auto" && n != "debug_srs_upnode" - && n != "play" && n != "publish" && n != "mw_latency" && n != "min_latency" + && n != "debug_srs_upnode" && n != "play" && n != "publish" && n != "mw_latency" && n != "min_latency" && n != "tcp_nodelay" && n != "send_min_interval" && n != "reduce_sequence_header" && n != "security" && n != "http_remux" && n != "http_static" && n != "hds" && n != "exec" @@ -2714,7 +2697,7 @@ int SrsConfig::check_config() } else if (n == "play") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); - if (m != "time_jitter" && m != "mix_correct") { + if (m != "time_jitter" && m != "mix_correct" && m != "atc" && m != "atc_auto" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost play directive %s, ret=%d", m.c_str(), ret); return ret; @@ -3264,6 +3247,11 @@ bool SrsConfig::get_atc(string vhost) return DEFAULT; } + conf = conf->get("play"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + conf = conf->get("atc"); if (!conf || conf->arg0().empty()) { return DEFAULT; @@ -3281,6 +3269,11 @@ bool SrsConfig::get_atc_auto(string vhost) return DEFAULT; } + conf = conf->get("play"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + conf = conf->get("atc_auto"); if (!conf || conf->arg0().empty()) { return DEFAULT; @@ -5696,13 +5689,14 @@ int srs_config_transform_vhost(SrsConfDirective* root) std::vector::iterator it; for (it = dir->directives.begin(); it != dir->directives.end();) { SrsConfDirective* conf = *it; + string n = conf->name; // SRS2.0, rename vhost http to http_static // SRS1: // vhost { http {} } // SRS2+: // vhost { http_static {} } - if (conf->name == "http") { + if (n == "http") { conf->name = "http_static"; ++it; continue; @@ -5713,19 +5707,19 @@ int srs_config_transform_vhost(SrsConfDirective* root) // vhost { refer; refer_play; refer_publish; } // SRS3+: // vhost { refer { enabled; all; play; publish; } } - if ((conf->name == "refer" && conf->directives.empty()) || conf->name == "refer_play" || conf->name == "refer_publish") { + if ((n == "refer" && conf->directives.empty()) || n == "refer_play" || n == "refer_publish") { // remove the old one first, for name duplicated. it = dir->directives.erase(it); SrsConfDirective* refer = dir->get_or_create("refer"); refer->get_or_create("enabled", "on"); - if (conf->name == "refer") { + if (n == "refer") { SrsConfDirective* all = refer->get_or_create("all"); all->args = conf->args; - } else if (conf->name == "play") { + } else if (n == "play") { SrsConfDirective* play = refer->get_or_create("play"); play->args = conf->args; - } else if (conf->name == "publish") { + } else if (n == "publish") { SrsConfDirective* publish = refer->get_or_create("publish"); publish->args = conf->args; } @@ -5740,7 +5734,7 @@ int srs_config_transform_vhost(SrsConfDirective* root) // vhost { mr { enabled; latency; } } // SRS3+: // vhost { publish { mr; mr_latency; } } - if (conf->name == "mr") { + if (n == "mr") { it = dir->directives.erase(it); SrsConfDirective* publish = dir->get_or_create("publish"); @@ -5766,7 +5760,7 @@ int srs_config_transform_vhost(SrsConfDirective* root) // vhost { publish_1stpkt_timeout; } // SRS3+: // vhost { publish { firstpkt_timeout; } } - if (conf->name == "publish_1stpkt_timeout") { + if (n == "publish_1stpkt_timeout") { it = dir->directives.erase(it); SrsConfDirective* publish = dir->get_or_create("publish"); @@ -5783,7 +5777,7 @@ int srs_config_transform_vhost(SrsConfDirective* root) // vhost { publish_normal_timeout; } // SRS3+: // vhost { publish { normal_timeout; } } - if (conf->name == "publish_normal_timeout") { + if (n == "publish_normal_timeout") { it = dir->directives.erase(it); SrsConfDirective* publish = dir->get_or_create("publish"); @@ -5796,12 +5790,12 @@ int srs_config_transform_vhost(SrsConfDirective* root) } // SRS3.0, change the folowing like a shadow: - // time_jitter, mix_correct + // time_jitter, mix_correct, atc, atc_auto // SRS1/2: // vhost { shadow; } // SRS3+: // vhost { play { shadow; } } - if (conf->name == "time_jitter" || conf->name == "mix_correct") { + if (n == "time_jitter" || n == "mix_correct" || n == "atc" || n == "atc_auto") { it = dir->directives.erase(it); SrsConfDirective* play = dir->get_or_create("play"); diff --git a/trunk/src/app/srs_app_reload.cpp b/trunk/src/app/srs_app_reload.cpp index 6d07b596f6..79714646d7 100644 --- a/trunk/src/app/srs_app_reload.cpp +++ b/trunk/src/app/srs_app_reload.cpp @@ -125,11 +125,6 @@ int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/) return ERROR_SUCCESS; } -int ISrsReloadHandler::on_reload_vhost_atc(string /*vhost*/) -{ - return ERROR_SUCCESS; -} - int ISrsReloadHandler::on_reload_vhost_gop_cache(string /*vhost*/) { return ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_reload.hpp b/trunk/src/app/srs_app_reload.hpp index 7411ccc14d..e067ec1870 100644 --- a/trunk/src/app/srs_app_reload.hpp +++ b/trunk/src/app/srs_app_reload.hpp @@ -64,7 +64,6 @@ class ISrsReloadHandler virtual int on_reload_vhost_http_remux_updated(std::string vhost); virtual int on_reload_vhost_added(std::string vhost); virtual int on_reload_vhost_removed(std::string vhost); - virtual int on_reload_vhost_atc(std::string vhost); virtual int on_reload_vhost_gop_cache(std::string vhost); virtual int on_reload_vhost_queue_length(std::string vhost); virtual int on_reload_vhost_play(std::string vhost); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 5fe53978ea..7aa2b5182e 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1043,25 +1043,6 @@ int SrsSource::initialize(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* h return ret; } -int SrsSource::on_reload_vhost_atc(string vhost) -{ - int ret = ERROR_SUCCESS; - - if (_req->vhost != vhost) { - return ret; - } - - // atc changed. - bool enabled_atc = _srs_config->get_atc(vhost); - - srs_warn("vhost %s atc changed to %d, connected client may corrupt.", - vhost.c_str(), enabled_atc); - - gop_cache->clear(); - - return ret; -} - int SrsSource::on_reload_vhost_gop_cache(string vhost) { int ret = ERROR_SUCCESS; @@ -1133,13 +1114,26 @@ int SrsSource::on_reload_vhost_play(string vhost) jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(_req->vhost); // mix_correct - bool v = _srs_config->get_mix_correct(_req->vhost); + if (true) { + bool v = _srs_config->get_mix_correct(_req->vhost); + + // when changed, clear the mix queue. + if (v != mix_correct) { + mix_queue->clear(); + } + mix_correct = v; + } - // when changed, clear the mix queue. - if (v != mix_correct) { - mix_queue->clear(); + // atc changed. + if (true) { + bool v = _srs_config->get_atc(vhost); + + if (v != atc) { + srs_warn("vhost %s atc changed to %d, connected client may corrupt.", vhost.c_str(), v); + gop_cache->clear(); + } + atc = v; } - mix_correct = v; return ret; } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index 2c9abb8b56..45248467d5 100755 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -451,11 +451,20 @@ class SrsSource : public ISrsReloadHandler std::vector consumers; // the time jitter algorithm for vhost. SrsRtmpJitterAlgorithm jitter_algorithm; - // whether use interlaced/mixed algorithm to correct timestamp. + // for play, whether use interlaced/mixed algorithm to correct timestamp. bool mix_correct; + // the mix queue to implements the mix correct algorithm. SrsMixQueue* mix_queue; + /** + * for play, whether enabled atc. + * atc whether atc(use absolute time and donot adjust time), + * directly use msg time and donot adjust if atc is true, + * otherwise, adjust msg time to start from 0 to make flash happy. + */ + bool atc; // whether stream is monotonically increase. bool is_monotonically_increase; + // the time of the packet we just got. int64_t last_packet_time; // hls handler. #ifdef SRS_AUTO_HLS @@ -491,13 +500,6 @@ class SrsSource : public ISrsReloadHandler * can publish, true when is not streaming */ bool _can_publish; - /** - * atc whether atc(use absolute time and donot adjust time), - * directly use msg time and donot adjust if atc is true, - * otherwise, adjust msg time to start from 0 to make flash happy. - */ - // TODO: FIXME: to support reload atc. - bool atc; private: SrsSharedPtrMessage* cache_metadata; // the cached video sequence header. @@ -518,7 +520,6 @@ class SrsSource : public ISrsReloadHandler virtual int initialize(SrsRequest* r, ISrsSourceHandler* h, ISrsHlsHandler* hh); // interface ISrsReloadHandler public: - virtual int on_reload_vhost_atc(std::string vhost); virtual int on_reload_vhost_gop_cache(std::string vhost); virtual int on_reload_vhost_queue_length(std::string vhost); virtual int on_reload_vhost_play(std::string vhost); diff --git a/trunk/src/utest/srs_utest_reload.cpp b/trunk/src/utest/srs_utest_reload.cpp index a8e5b7c047..0e933a4c1c 100644 --- a/trunk/src/utest/srs_utest_reload.cpp +++ b/trunk/src/utest/srs_utest_reload.cpp @@ -230,12 +230,6 @@ int MockReloadHandler::on_reload_vhost_removed(string /*vhost*/) return ERROR_SUCCESS; } -int MockReloadHandler::on_reload_vhost_atc(string /*vhost*/) -{ - vhost_atc_reloaded = true; - return ERROR_SUCCESS; -} - int MockReloadHandler::on_reload_vhost_gop_cache(string /*vhost*/) { vhost_gop_cache_reloaded = true; diff --git a/trunk/src/utest/srs_utest_reload.hpp b/trunk/src/utest/srs_utest_reload.hpp index 4d5214bd5f..4bb4393d2f 100644 --- a/trunk/src/utest/srs_utest_reload.hpp +++ b/trunk/src/utest/srs_utest_reload.hpp @@ -85,7 +85,6 @@ class MockReloadHandler : public ISrsReloadHandler virtual int on_reload_vhost_http_updated(); virtual int on_reload_vhost_added(std::string vhost); virtual int on_reload_vhost_removed(std::string vhost); - virtual int on_reload_vhost_atc(std::string vhost); virtual int on_reload_vhost_gop_cache(std::string vhost); virtual int on_reload_vhost_queue_length(std::string vhost); virtual int on_reload_vhost_play(std::string vhost);