diff --git a/README.md b/README.md index 5f2b3181c..0905b7677 100755 --- a/README.md +++ b/README.md @@ -241,6 +241,7 @@ Supported operating systems and hardware: * 2013-10-17, Created.
## History +* v1.0, 2014-06-25, fix [#108](https://github.com/winlinvip/simple-rtmp-server/issues/108), disable the time jitter for encoder non-monotonical stream. 0.9.133 * v1.0, 2014-06-23, support report summaries in heartbeat. 0.9.132 * v1.0, 2014-06-22, performance refine, support [3k+](https://github.com/winlinvip/simple-rtmp-server/wiki/Performance#%E6%80%A7%E8%83%BD%E4%BE%8B%E8%A1%8C%E6%8A%A5%E5%91%8A4k) connections(270kbps). 0.9.130 * v1.0, 2014-06-21, support edge [token traverse](https://github.com/winlinvip/simple-rtmp-server/wiki/DRM#tokentraverse), fix [#104](https://github.com/winlinvip/simple-rtmp-server/issues/104). 0.9.129 diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 782822311..4e4870c12 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -187,6 +187,18 @@ vhost dvr.srs.com { # the param for plan(segment), in seconds. # default: 30 dvr_duration 30; + # about the stream monotonically increasing: + # 1. video timestamp is monotonically increasing, + # 2. audio timestamp is monotonically increasing, + # 3. video and audio timestamp is interleaved monotonically increasing. + # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format + # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. + # the time jitter algorithm: + # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. + # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. + # 3. off, disable the time jitter algorithm, like atc. + # default: full + time_jitter full; } } @@ -906,6 +918,22 @@ vhost chunksize.srs.com { chunk_size 128; } +# vhost for time jitter +vhost jitter.srs.com { + # about the stream monotonically increasing: + # 1. video timestamp is monotonically increasing, + # 2. audio timestamp is monotonically increasing, + # 3. video and audio timestamp is interleaved monotonically increasing. + # it's specified by RTMP specification, @see 3. Byte Order, Alignment, and Time Format + # however, some encoder cannot provides this feature, please set this to off to ignore time jitter. + # the time jitter algorithm: + # 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. + # 2. zero, only ensure sttream start at zero, ignore timestamp jitter. + # 3. off, disable the time jitter algorithm, like atc. + # default: full + time_jitter full; +} + # vhost for atc. vhost atc.srs.com { # vhost for atc for hls/hds/rtmp backup. diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 1ae191a7d..9aa331557 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -41,6 +41,7 @@ using namespace std; #include #include #include +#include #define SRS_WIKI_URL_LOG "https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLog" @@ -947,6 +948,17 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root) } srs_trace("vhost %s reload queue_length success.", vhost.c_str()); } + // time_jitter, only one per vhost + if (!srs_directive_equals(new_vhost->get("time_jitter"), old_vhost->get("time_jitter"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_vhost_time_jitter(vhost)) != ERROR_SUCCESS) { + srs_error("vhost %s notify subscribes time_jitter failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("vhost %s reload time_jitter success.", vhost.c_str()); + } // forward, only one per vhost if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) { for (it = subscribes.begin(); it != subscribes.end(); ++it) { @@ -1788,6 +1800,23 @@ bool SrsConfig::get_atc_auto(string vhost) return true; } +int SrsConfig::get_time_jitter(string vhost) +{ + SrsConfDirective* dvr = get_vhost(vhost); + + std::string time_jitter = SRS_CONF_DEFAULT_TIME_JITTER; + + if (dvr) { + SrsConfDirective* conf = dvr->get("time_jitter"); + + if (conf) { + time_jitter = conf->arg0(); + } + } + + return _srs_time_jitter_string2int(time_jitter); +} + double SrsConfig::get_queue_length(string vhost) { SrsConfDirective* conf = get_vhost(vhost); @@ -2636,6 +2665,23 @@ int SrsConfig::get_dvr_duration(string vhost) return ::atoi(conf->arg0().c_str()); } +int SrsConfig::get_dvr_time_jitter(string vhost) +{ + SrsConfDirective* dvr = get_dvr(vhost); + + std::string time_jitter = SRS_CONF_DEFAULT_TIME_JITTER; + + if (dvr) { + SrsConfDirective* conf = dvr->get("time_jitter"); + + if (conf) { + time_jitter = conf->arg0(); + } + } + + return _srs_time_jitter_string2int(time_jitter); +} + SrsConfDirective* SrsConfig::get_http_api() { return root->get("http_api"); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 3d8df3c93..883948952 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -49,6 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CONF_DEFAULT_DVR_PLAN_HSS "hss" #define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION #define SRS_CONF_DEFAULT_DVR_DURATION 30 +#define SRS_CONF_DEFAULT_TIME_JITTER "full" // in ms, for HLS aac sync time. #define SRS_CONF_DEFAULT_AAC_SYNC 100 // in ms, for HLS aac flush the audio @@ -200,6 +201,7 @@ public: virtual bool get_gop_cache(std::string vhost); virtual bool get_atc(std::string vhost); virtual bool get_atc_auto(std::string vhost); + virtual int get_time_jitter(std::string vhost); virtual double get_queue_length(std::string vhost); virtual SrsConfDirective* get_forward(std::string vhost); virtual SrsConfDirective* get_refer(std::string vhost); @@ -272,6 +274,7 @@ public: virtual std::string get_dvr_path(std::string vhost); virtual std::string get_dvr_plan(std::string vhost); virtual int get_dvr_duration(std::string vhost); + virtual int get_dvr_time_jitter(std::string vhost); // http api section private: virtual SrsConfDirective* get_http_api(); diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index f605e4372..6ffb10f06 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -70,10 +70,15 @@ SrsDvrPlan::SrsDvrPlan() fs = new SrsFileStream(); enc = new SrsFlvEncoder(); segment = new SrsFlvSegment(); + jitter_algorithm = SrsRtmpJitterAlgorithmOFF; + + _srs_config->subscribe(this); } SrsDvrPlan::~SrsDvrPlan() { + _srs_config->unsubscribe(this); + srs_freep(jitter); srs_freep(fs); srs_freep(enc); @@ -86,6 +91,8 @@ int SrsDvrPlan::initialize(SrsSource* source, SrsRequest* req) _source = source; _req = req; + + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(_req->vhost); return ret; } @@ -198,7 +205,7 @@ int SrsDvrPlan::on_audio(SrsSharedPtrMessage* audio) return ret; } - if ((jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { + if ((jitter->correct(audio, 0, 0, jitter_algorithm)) != ERROR_SUCCESS) { return ret; } @@ -240,7 +247,7 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video) srs_verbose("dvr video is key: %d", is_key_frame); #endif - if ((jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { + if ((jitter->correct(video, 0, 0, jitter_algorithm)) != ERROR_SUCCESS) { return ret; } @@ -256,6 +263,15 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video) return ret; } +int SrsDvrPlan::on_reload_vhost_dvr(std::string vhost) +{ + int ret = ERROR_SUCCESS; + + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_dvr_time_jitter(_req->vhost); + + return ret; +} + int SrsDvrPlan::flv_open(string stream, string path) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_dvr.hpp b/trunk/src/app/srs_app_dvr.hpp index eeb57c36c..1a05fe9b2 100644 --- a/trunk/src/app/srs_app_dvr.hpp +++ b/trunk/src/app/srs_app_dvr.hpp @@ -42,6 +42,9 @@ class SrsSharedPtrMessage; class SrsFileStream; class SrsFlvEncoder; +#include +#include + /** * a piece of flv segment. */ @@ -93,21 +96,23 @@ public: * 2. reap flv: when to reap the flv and start new piece. */ // TODO: FIXME: the plan is too fat, refine me. -class SrsDvrPlan +class SrsDvrPlan : public ISrsReloadHandler { -protected: +private: /** * the underlayer dvr stream. * if close, the flv is reap and closed. * if open, new flv file is crote. */ - SrsFileStream* fs; SrsFlvEncoder* enc; - bool dvr_enabled; SrsSource* _source; - SrsRequest* _req; SrsRtmpJitter* jitter; + SrsRtmpJitterAlgorithm jitter_algorithm; +protected: SrsFlvSegment* segment; + SrsRequest* _req; + bool dvr_enabled; + SrsFileStream* fs; public: SrsDvrPlan(); virtual ~SrsDvrPlan(); @@ -118,6 +123,9 @@ public: virtual int on_meta_data(SrsOnMetaDataPacket* metadata); virtual int on_audio(SrsSharedPtrMessage* audio); virtual int on_video(SrsSharedPtrMessage* video); +// interface ISrsReloadHandler +public: + virtual int on_reload_vhost_dvr(std::string vhost); protected: virtual int flv_open(std::string stream, std::string path); virtual int flv_close(); diff --git a/trunk/src/app/srs_app_forward.cpp b/trunk/src/app/srs_app_forward.cpp index d4db40e38..fce33a4fa 100644 --- a/trunk/src/app/srs_app_forward.cpp +++ b/trunk/src/app/srs_app_forward.cpp @@ -162,7 +162,7 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) { int ret = ERROR_SUCCESS; - if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(metadata, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { srs_freep(metadata); return ret; } @@ -178,7 +178,7 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) { int ret = ERROR_SUCCESS; - if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(msg, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { srs_freep(msg); return ret; } @@ -194,7 +194,7 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* msg) { int ret = ERROR_SUCCESS; - if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(msg, 0, 0, SrsRtmpJitterAlgorithmFULL)) != 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 6d91026d4..c93bb0276 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1411,7 +1411,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) return hls_cache->on_sequence_header(muxer); } - if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(audio, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { srs_error("rtmp jitter correct audio failed. ret=%d", ret); return ret; } @@ -1456,7 +1456,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) return hls_cache->on_sequence_header(muxer); } - if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(video, 0, 0, SrsRtmpJitterAlgorithmFULL)) != ERROR_SUCCESS) { srs_error("rtmp jitter correct video failed. ret=%d", ret); return ret; } diff --git a/trunk/src/app/srs_app_reload.cpp b/trunk/src/app/srs_app_reload.cpp index b640162d6..b3ddfadb8 100644 --- a/trunk/src/app/srs_app_reload.cpp +++ b/trunk/src/app/srs_app_reload.cpp @@ -120,6 +120,11 @@ int ISrsReloadHandler::on_reload_vhost_queue_length(string /*vhost*/) return ERROR_SUCCESS; } +int ISrsReloadHandler::on_reload_vhost_time_jitter(string /*vhost*/) +{ + return ERROR_SUCCESS; +} + int ISrsReloadHandler::on_reload_vhost_forward(string /*vhost*/) { return ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_reload.hpp b/trunk/src/app/srs_app_reload.hpp index 798a11ab2..a7eb1e9aa 100644 --- a/trunk/src/app/srs_app_reload.hpp +++ b/trunk/src/app/srs_app_reload.hpp @@ -61,6 +61,7 @@ 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_time_jitter(std::string vhost); virtual int on_reload_vhost_forward(std::string vhost); virtual int on_reload_vhost_hls(std::string vhost); virtual int on_reload_vhost_dvr(std::string vhost); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index ed86e9147..58542672e 100644 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -45,6 +45,17 @@ using namespace std; #define CONST_MAX_JITTER_MS 500 #define DEFAULT_FRAME_TIME_MS 40 +int _srs_time_jitter_string2int(std::string time_jitter) +{ + if (time_jitter == "full") { + return SrsRtmpJitterAlgorithmFULL; + } else if (time_jitter == "zero") { + return SrsRtmpJitterAlgorithmZERO; + } else { + return SrsRtmpJitterAlgorithmOFF; + } +} + SrsRtmpJitter::SrsRtmpJitter() { last_pkt_correct_time = last_pkt_time = 0; @@ -54,10 +65,27 @@ SrsRtmpJitter::~SrsRtmpJitter() { } -int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) +int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJitterAlgorithm ag) { int ret = ERROR_SUCCESS; + + // all jitter correct features is disabled, ignore. + if (ag == SrsRtmpJitterAlgorithmOFF) { + return ret; + } + + // start at zero, but donot ensure monotonically increasing. + if (ag == SrsRtmpJitterAlgorithmZERO) { + if (last_pkt_correct_time <= 0) { + last_pkt_correct_time = msg->header.timestamp; + } + msg->header.timestamp -= last_pkt_correct_time; + return ret; + } + + // full jitter algorithm, do jitter correct. + // set to 0 for metadata. if (!msg->header.is_video() && !msg->header.is_audio()) { msg->header.timestamp = 0; @@ -266,12 +294,12 @@ int SrsConsumer::get_time() return jitter->get_time(); } -int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv) +int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm ag) { int ret = ERROR_SUCCESS; if (!atc) { - if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { + if ((ret = jitter->correct(msg, tba, tbv, ag)) != ERROR_SUCCESS) { srs_freep(msg); return ret; } @@ -384,7 +412,7 @@ void SrsGopCache::clear() cached_video_count = 0; } -int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv) +int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm jitter_algorithm) { int ret = ERROR_SUCCESS; @@ -392,7 +420,7 @@ int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv) for (it = gop_cache.begin(); it != gop_cache.end(); ++it) { SrsSharedPtrMessage* msg = *it; SrsSharedPtrMessage* copy = msg->copy(); - if ((ret = consumer->enqueue(copy, atc, tba, tbv)) != ERROR_SUCCESS) { + if ((ret = consumer->enqueue(copy, atc, tba, tbv, jitter_algorithm)) != ERROR_SUCCESS) { srs_error("dispatch cached gop failed. ret=%d", ret); return ret; } @@ -464,6 +492,7 @@ void SrsSource::destroy() SrsSource::SrsSource(SrsRequest* req) { _req = req->copy(); + jitter_algorithm = SrsRtmpJitterAlgorithmOFF; #ifdef SRS_AUTO_HLS hls = new SrsHls(this); @@ -549,6 +578,8 @@ int SrsSource::initialize() double queue_size = _srs_config->get_queue_length(_req->vhost); publish_edge->set_queue_size(queue_size); + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(_req->vhost); + return ret; } @@ -630,6 +661,19 @@ int SrsSource::on_reload_vhost_queue_length(string vhost) return ret; } +int SrsSource::on_reload_vhost_time_jitter(string vhost) +{ + int ret = ERROR_SUCCESS; + + if (_req->vhost != vhost) { + return ret; + } + + jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(_req->vhost); + + return ret; +} + int SrsSource::on_reload_vhost_forward(string vhost) { int ret = ERROR_SUCCESS; @@ -928,7 +972,7 @@ int SrsSource::on_meta_data(SrsMessage* msg, SrsOnMetaDataPacket* metadata) for (it = consumers.begin(); it != consumers.end(); ++it) { SrsConsumer* consumer = *it; SrsSharedPtrMessage* copy = cache_metadata->copy(); - if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { + if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { srs_error("dispatch the metadata failed. ret=%d", ret); return ret; } @@ -992,7 +1036,7 @@ int SrsSource::on_audio(SrsMessage* audio) for (int i = 0; i < (int)consumers.size(); i++) { SrsConsumer* consumer = consumers.at(i); SrsSharedPtrMessage* copy = msg->copy(); - if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { + if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { srs_error("dispatch the audio failed. ret=%d", ret); return ret; } @@ -1082,7 +1126,7 @@ int SrsSource::on_video(SrsMessage* video) for (int i = 0; i < (int)consumers.size(); i++) { SrsConsumer* consumer = consumers.at(i); SrsSharedPtrMessage* copy = msg->copy(); - if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { + if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { srs_error("dispatch the video failed. ret=%d", ret); return ret; } @@ -1328,28 +1372,32 @@ void SrsSource::on_unpublish() } } + int tba = sample_rate; + int tbv = frame_rate; + SrsRtmpJitterAlgorithm ag = jitter_algorithm; + // copy metadata. - if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { + if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), atc, tba, tbv, ag)) != ERROR_SUCCESS) { srs_error("dispatch metadata failed. ret=%d", ret); return ret; } srs_info("dispatch metadata success"); // copy sequence header - if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { + if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), atc, tba, tbv, ag)) != ERROR_SUCCESS) { srs_error("dispatch video sequence header failed. ret=%d", ret); return ret; } srs_info("dispatch video sequence header success"); - if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { + if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), atc, tba, tbv, ag)) != ERROR_SUCCESS) { srs_error("dispatch audio sequence header failed. ret=%d", ret); return ret; } srs_info("dispatch audio sequence header success"); // copy gop cache to client. - if ((ret = gop_cache->dump(consumer, atc, sample_rate, frame_rate)) != ERROR_SUCCESS) { + if ((ret = gop_cache->dump(consumer, atc, tba, tbv, ag)) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index e35296d06..ef3731740 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -59,6 +59,20 @@ class SrsEncoder; #endif class SrsStream; +/** +* the time jitter algorithm: +* 1. full, to ensure stream start at zero, and ensure stream monotonically increasing. +* 2. zero, only ensure sttream start at zero, ignore timestamp jitter. +* 3. off, disable the time jitter algorithm, like atc. +*/ +enum SrsRtmpJitterAlgorithm +{ + SrsRtmpJitterAlgorithmFULL = 0x01, + SrsRtmpJitterAlgorithmZERO, + SrsRtmpJitterAlgorithmOFF +}; +int _srs_time_jitter_string2int(std::string time_jitter); + /** * time jitter detect and correct, * to ensure the rtmp stream is monotonically. @@ -74,8 +88,12 @@ public: public: /** * detect the time jitter and correct it. + * @param tba, the audio timebase, used to calc the "right" delta if jitter detected. + * @param tbv, the video timebase, used to calc the "right" delta if jitter detected. + * @param start_at_zero whether ensure stream start at zero. + * @param mono_increasing whether ensure stream is monotonically inscreasing. */ - virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv); + virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJitterAlgorithm ag); /** * get current client time, the last packet time. */ @@ -160,8 +178,9 @@ public: * used to calc the audio time delta if time-jitter detected. * @param tbv timebase of video. * used to calc the video time delta if time-jitter detected. + * @param ag the algorithm of time jitter. */ - virtual int enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv); + virtual int enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm ag); /** * get packets in consumer queue. * @pmsgs SrsMessages*[], used to store the msgs, user must alloc it. @@ -209,7 +228,7 @@ public: */ virtual int cache(SrsSharedPtrMessage* msg); virtual void clear(); - virtual int dump(SrsConsumer* consumer, bool atc, int tba, int tbv); + virtual int dump(SrsConsumer* consumer, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm jitter_algorithm); /** * used for atc to get the time of gop cache, * the atc will adjust the sequence header timestamp to gop cache. @@ -249,6 +268,8 @@ private: SrsRequest* _req; // to delivery stream to clients. std::vector consumers; + // the time jitter algorithm for vhost. + SrsRtmpJitterAlgorithm jitter_algorithm; // hls handler. #ifdef SRS_AUTO_HLS SrsHls* hls; @@ -310,6 +331,7 @@ 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_time_jitter(std::string vhost); virtual int on_reload_vhost_forward(std::string vhost); virtual int on_reload_vhost_hls(std::string vhost); virtual int on_reload_vhost_dvr(std::string vhost); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index aa2cc5ae9..a90ab17fe 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR "0" #define VERSION_MINOR "9" -#define VERSION_REVISION "132" +#define VERSION_REVISION "133" #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION // server info. #define RTMP_SIG_SRS_KEY "SRS"