mirror of
https://github.com/ossrs/srs.git
synced 2025-02-12 19:31:53 +00:00
fix #108: disable the time jitter for encoder non-monotonical stream. 0.9.133
This commit is contained in:
parent
f173345e15
commit
1970e18ed6
13 changed files with 206 additions and 28 deletions
|
@ -241,6 +241,7 @@ Supported operating systems and hardware:
|
|||
* 2013-10-17, Created.<br/>
|
||||
|
||||
## 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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -41,6 +41,7 @@ using namespace std;
|
|||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_app_source.hpp>
|
||||
|
||||
#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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -42,6 +42,9 @@ class SrsSharedPtrMessage;
|
|||
class SrsFileStream;
|
||||
class SrsFlvEncoder;
|
||||
|
||||
#include <srs_app_source.hpp>
|
||||
#include <srs_app_reload.hpp>
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<SrsConsumer*> 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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue