1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

fix #425, refine the time jitter, correct (-inf,-250)+(250,+inf) to 10ms. 2.0.175

This commit is contained in:
winlin 2015-06-10 15:38:13 +08:00
parent 6941f2c072
commit 56938efdbd
9 changed files with 71 additions and 106 deletions

View file

@ -47,8 +47,9 @@ using namespace std;
#include <srs_core_autofree.hpp>
#include <srs_rtmp_utility.hpp>
#define CONST_MAX_JITTER_MS 500
#define DEFAULT_FRAME_TIME_MS 40
#define CONST_MAX_JITTER_MS 250
#define CONST_MAX_JITTER_MS_NEG -250
#define DEFAULT_FRAME_TIME_MS 10
// for 26ms per audio packet,
// 115 packets is 3s.
@ -70,14 +71,15 @@ int _srs_time_jitter_string2int(std::string time_jitter)
SrsRtmpJitter::SrsRtmpJitter()
{
last_pkt_correct_time = last_pkt_time = 0;
last_pkt_correct_time = -1;
last_pkt_time = 0;
}
SrsRtmpJitter::~SrsRtmpJitter()
{
}
int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJitterAlgorithm ag)
int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, SrsRtmpJitterAlgorithm ag)
{
int ret = ERROR_SUCCESS;
@ -90,9 +92,8 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJi
// start at zero, but donot ensure monotonically increasing.
if (ag == SrsRtmpJitterAlgorithmZERO) {
// for the first time, last_pkt_correct_time is zero.
// while when timestamp overflow, the timestamp become smaller, reset the last_pkt_correct_time.
if (last_pkt_correct_time <= 0 || msg->timestamp < last_pkt_correct_time) {
// for the first time, last_pkt_correct_time is -1.
if (last_pkt_correct_time == -1) {
last_pkt_correct_time = msg->timestamp;
}
msg->timestamp -= last_pkt_correct_time;
@ -104,16 +105,12 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJi
}
// full jitter algorithm, do jitter correct.
// set to 0 for metadata.
if (!msg->is_av()) {
msg->timestamp = 0;
return ret;
}
int sample_rate = tba;
int frame_rate = tbv;
/**
* we use a very simple time jitter detect/correct algorithm:
* 1. delta: ensure the delta is positive and valid,
@ -128,20 +125,10 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv, SrsRtmpJi
int64_t delta = time - last_pkt_time;
// if jitter detected, reset the delta.
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
// calc the right diff by audio sample rate
if (msg->is_audio() && sample_rate > 0) {
delta = (int64_t)(delta * 1000.0 / sample_rate);
} else if (msg->is_video() && frame_rate > 0) {
delta = (int64_t)(delta * 1.0 / frame_rate);
} else {
delta = DEFAULT_FRAME_TIME_MS;
}
// sometimes, the time is absolute time, so correct it again.
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
delta = DEFAULT_FRAME_TIME_MS;
}
if (delta < CONST_MAX_JITTER_MS_NEG || delta > CONST_MAX_JITTER_MS) {
// use default 10ms to notice the problem of stream.
// @see https://github.com/simple-rtmp-server/srs/issues/425
delta = DEFAULT_FRAME_TIME_MS;
srs_info("jitter detected, last_pts=%"PRId64", pts=%"PRId64", diff=%"PRId64", last_time=%"PRId64", time=%"PRId64", diff=%"PRId64"",
last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta);
@ -338,7 +325,7 @@ int SrsMessageQueue::dump_packets(int max_count, SrsSharedPtrMessage** pmsgs, in
return ret;
}
int SrsMessageQueue::dump_packets(SrsConsumer* consumer, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm ag)
int SrsMessageQueue::dump_packets(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag)
{
int ret = ERROR_SUCCESS;
@ -350,7 +337,7 @@ int SrsMessageQueue::dump_packets(SrsConsumer* consumer, bool atc, int tba, int
SrsSharedPtrMessage** omsgs = msgs.data();
for (int i = 0; i < nb_msgs; i++) {
SrsSharedPtrMessage* msg = omsgs[i];
if ((ret = consumer->enqueue(msg, atc, tba, tbv, ag)) != ERROR_SUCCESS) {
if ((ret = consumer->enqueue(msg, atc, ag)) != ERROR_SUCCESS) {
return ret;
}
}
@ -473,14 +460,14 @@ int SrsConsumer::get_time()
return jitter->get_time();
}
int SrsConsumer::enqueue(SrsSharedPtrMessage* shared_msg, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm ag)
int SrsConsumer::enqueue(SrsSharedPtrMessage* shared_msg, bool atc, SrsRtmpJitterAlgorithm ag)
{
int ret = ERROR_SUCCESS;
SrsSharedPtrMessage* msg = shared_msg->copy();
if (!atc) {
if ((ret = jitter->correct(msg, tba, tbv, ag)) != ERROR_SUCCESS) {
if ((ret = jitter->correct(msg, ag)) != ERROR_SUCCESS) {
srs_freep(msg);
return ret;
}
@ -683,14 +670,14 @@ void SrsGopCache::clear()
audio_after_last_video_count = 0;
}
int SrsGopCache::dump(SrsConsumer* consumer, bool atc, int tba, int tbv, SrsRtmpJitterAlgorithm jitter_algorithm)
int SrsGopCache::dump(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm jitter_algorithm)
{
int ret = ERROR_SUCCESS;
std::vector<SrsSharedPtrMessage*>::iterator it;
for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
SrsSharedPtrMessage* msg = *it;
if ((ret = consumer->enqueue(msg, atc, tba, tbv, jitter_algorithm)) != ERROR_SUCCESS) {
if ((ret = consumer->enqueue(msg, atc, jitter_algorithm)) != ERROR_SUCCESS) {
srs_error("dispatch cached gop failed. ret=%d", ret);
return ret;
}
@ -906,7 +893,6 @@ SrsSource::SrsSource()
cache_metadata = cache_sh_video = cache_sh_audio = NULL;
frame_rate = sample_rate = 0;
_can_publish = true;
_source_id = -1;
@ -1413,17 +1399,6 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
// add version to metadata, please donot remove it, for debug.
metadata->metadata->set("server_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION));
if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) {
if (prop->is_number()) {
sample_rate = (int)prop->to_number();
}
}
if ((prop = metadata->metadata->get_property("framerate")) != NULL) {
if (prop->is_number()) {
frame_rate = (int)prop->to_number();
}
}
// if allow atc_auto and bravo-atc detected, open atc for vhost.
atc = _srs_config->get_atc(_req->vhost);
if (_srs_config->get_atc_auto(_req->vhost)) {
@ -1466,7 +1441,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
std::vector<SrsConsumer*>::iterator it;
for (it = consumers.begin(); it != consumers.end(); ++it) {
SrsConsumer* consumer = *it;
if ((ret = consumer->enqueue(cache_metadata, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) {
if ((ret = consumer->enqueue(cache_metadata, atc, jitter_algorithm)) != ERROR_SUCCESS) {
srs_error("dispatch the metadata failed. ret=%d", ret);
return ret;
}
@ -1600,7 +1575,7 @@ int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
SrsConsumer** pconsumer = consumers.data();
for (int i = 0; i < nb_consumers; i++) {
SrsConsumer* consumer = pconsumer[i];
if ((ret = consumer->enqueue(msg, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) {
if ((ret = consumer->enqueue(msg, atc, jitter_algorithm)) != ERROR_SUCCESS) {
srs_error("dispatch the audio failed. ret=%d", ret);
return ret;
}
@ -1802,7 +1777,7 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
if (true) {
for (int i = 0; i < (int)consumers.size(); i++) {
SrsConsumer* consumer = consumers.at(i);
if ((ret = consumer->enqueue(msg, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) {
if ((ret = consumer->enqueue(msg, atc, jitter_algorithm)) != ERROR_SUCCESS) {
srs_error("dispatch the video failed. ret=%d", ret);
return ret;
}
@ -2091,8 +2066,6 @@ void SrsSource::on_unpublish()
gop_cache->clear();
srs_freep(cache_metadata);
frame_rate = sample_rate = 0;
srs_freep(cache_sh_video);
srs_freep(cache_sh_audio);
@ -2131,13 +2104,9 @@ int SrsSource::create_consumer(SrsConsumer*& consumer, bool ds, bool dm, bool dg
cache_sh_audio->timestamp = gop_cache->start_time();
}
}
int tba = sample_rate;
int tbv = frame_rate;
SrsRtmpJitterAlgorithm ag = jitter_algorithm;
// copy metadata.
if (dm && cache_metadata && (ret = consumer->enqueue(cache_metadata, atc, tba, tbv, ag)) != ERROR_SUCCESS) {
if (dm && cache_metadata && (ret = consumer->enqueue(cache_metadata, atc, jitter_algorithm)) != ERROR_SUCCESS) {
srs_error("dispatch metadata failed. ret=%d", ret);
return ret;
}
@ -2146,28 +2115,28 @@ int SrsSource::create_consumer(SrsConsumer*& consumer, bool ds, bool dm, bool dg
// copy sequence header
// copy audio sequence first, for hls to fast parse the "right" audio codec.
// @see https://github.com/simple-rtmp-server/srs/issues/301
if (ds && cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio, atc, tba, tbv, ag)) != ERROR_SUCCESS) {
if (ds && cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio, atc, jitter_algorithm)) != ERROR_SUCCESS) {
srs_error("dispatch audio sequence header failed. ret=%d", ret);
return ret;
}
srs_info("dispatch audio sequence header success");
if (ds && cache_sh_video && (ret = consumer->enqueue(cache_sh_video, atc, tba, tbv, ag)) != ERROR_SUCCESS) {
if (ds && cache_sh_video && (ret = consumer->enqueue(cache_sh_video, atc, jitter_algorithm)) != ERROR_SUCCESS) {
srs_error("dispatch video sequence header failed. ret=%d", ret);
return ret;
}
srs_info("dispatch video sequence header success");
// copy gop cache to client.
if (dg && (ret = gop_cache->dump(consumer, atc, tba, tbv, ag)) != ERROR_SUCCESS) {
if (dg && (ret = gop_cache->dump(consumer, atc, jitter_algorithm)) != ERROR_SUCCESS) {
return ret;
}
// print status.
if (dg) {
srs_trace("create consumer, queue_size=%.2f, tba=%d, tbv=%d", queue_size, sample_rate, frame_rate);
srs_trace("create consumer, queue_size=%.2f, jitter=%d", queue_size, jitter_algorithm);
} else {
srs_trace("create consumer, ignore gop cache, tba=%d, tbv=%d", sample_rate, frame_rate);
srs_trace("create consumer, ignore gop cache, jitter=%d", jitter_algorithm);
}
return ret;
@ -2192,6 +2161,11 @@ void SrsSource::set_cache(bool enabled)
gop_cache->set(enabled);
}
SrsRtmpJitterAlgorithm SrsSource::jitter()
{
return jitter_algorithm;
}
int SrsSource::on_edge_start_play()
{
return play_edge->on_client_play();