mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
fix the timestamp bug. correct the audio diff by audiosamplerate
This commit is contained in:
parent
a1f97954f5
commit
3aa6be8645
3 changed files with 63 additions and 29 deletions
|
@ -817,19 +817,6 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
pp[0] = *p++;
|
pp[0] = *p++;
|
||||||
pp[3] = 0;
|
pp[3] = 0;
|
||||||
|
|
||||||
if (fmt == RTMP_FMT_TYPE0) {
|
|
||||||
// 6.1.2.1. Type 0
|
|
||||||
// For a type-0 chunk, the absolute timestamp of the message is sent
|
|
||||||
// here.
|
|
||||||
chunk->header.timestamp = chunk->header.timestamp_delta;
|
|
||||||
} else {
|
|
||||||
// 6.1.2.2. Type 1
|
|
||||||
// 6.1.2.3. Type 2
|
|
||||||
// For a type-1 or type-2 chunk, the difference between the previous
|
|
||||||
// chunk's timestamp and the current chunk's timestamp is sent here.
|
|
||||||
chunk->header.timestamp += chunk->header.timestamp_delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmt: 0
|
// fmt: 0
|
||||||
// timestamp: 3 bytes
|
// timestamp: 3 bytes
|
||||||
// If the timestamp is greater than or equal to 16777215
|
// If the timestamp is greater than or equal to 16777215
|
||||||
|
@ -845,7 +832,32 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
// the entire delta.
|
// the entire delta.
|
||||||
chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);
|
chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);
|
||||||
if (chunk->extended_timestamp) {
|
if (chunk->extended_timestamp) {
|
||||||
|
// Extended timestamp: 0 or 4 bytes
|
||||||
|
// This field MUST be sent when the normal timsestamp is set to
|
||||||
|
// 0xffffff, it MUST NOT be sent if the normal timestamp is set to
|
||||||
|
// anything else. So for values less than 0xffffff the normal
|
||||||
|
// timestamp field SHOULD be used in which case the extended timestamp
|
||||||
|
// MUST NOT be present. For values greater than or equal to 0xffffff
|
||||||
|
// the normal timestamp field MUST NOT be used and MUST be set to
|
||||||
|
// 0xffffff and the extended timestamp MUST be sent.
|
||||||
|
//
|
||||||
|
// if extended timestamp, the timestamp must >= RTMP_EXTENDED_TIMESTAMP
|
||||||
|
// we set the timestamp to RTMP_EXTENDED_TIMESTAMP to identify we
|
||||||
|
// got an extended timestamp.
|
||||||
chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP;
|
chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP;
|
||||||
|
} else {
|
||||||
|
if (fmt == RTMP_FMT_TYPE0) {
|
||||||
|
// 6.1.2.1. Type 0
|
||||||
|
// For a type-0 chunk, the absolute timestamp of the message is sent
|
||||||
|
// here.
|
||||||
|
chunk->header.timestamp = chunk->header.timestamp_delta;
|
||||||
|
} else {
|
||||||
|
// 6.1.2.2. Type 1
|
||||||
|
// 6.1.2.3. Type 2
|
||||||
|
// For a type-1 or type-2 chunk, the difference between the previous
|
||||||
|
// chunk's timestamp and the current chunk's timestamp is sent here.
|
||||||
|
chunk->header.timestamp += chunk->header.timestamp_delta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmt <= RTMP_FMT_TYPE1) {
|
if (fmt <= RTMP_FMT_TYPE1) {
|
||||||
|
@ -913,7 +925,10 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
pp[1] = *p++;
|
pp[1] = *p++;
|
||||||
pp[0] = *p++;
|
pp[0] = *p++;
|
||||||
|
|
||||||
if (chunk->header.timestamp > RTMP_EXTENDED_TIMESTAMP && chunk->header.timestamp != timestamp) {
|
// compare to the chunk timestamp, which is set by chunk message header
|
||||||
|
// type 0,1 or 2.
|
||||||
|
int32_t chunk_timestamp = chunk->header.timestamp;
|
||||||
|
if (chunk_timestamp > RTMP_EXTENDED_TIMESTAMP && chunk_timestamp != timestamp) {
|
||||||
mh_size -= 4;
|
mh_size -= 4;
|
||||||
srs_verbose("ignore the 4bytes extended timestamp. mh_size=%d", mh_size);
|
srs_verbose("ignore the 4bytes extended timestamp. mh_size=%d", mh_size);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -69,11 +69,11 @@ int SrsConsumer::get_time()
|
||||||
return (int)last_pkt_correct_time;
|
return (int)last_pkt_correct_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsConsumer::enqueue(SrsSharedPtrMessage* msg)
|
int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int audio_sample_rate)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ((ret = jitter_correct(msg)) != ERROR_SUCCESS) {
|
if ((ret = jitter_correct(msg, audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg)
|
int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -130,10 +130,15 @@ int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg)
|
||||||
|
|
||||||
// if jitter detected, reset the delta.
|
// if jitter detected, reset the delta.
|
||||||
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
|
if (delta < 0 || delta > CONST_MAX_JITTER_MS) {
|
||||||
delta = DEFAULT_FRAME_TIME_MS;
|
// calc the right diff by audio sample rate
|
||||||
|
if (msg->header.is_audio() && audio_sample_rate > 0) {
|
||||||
|
delta = (int32_t)(delta * 1000.0 / audio_sample_rate);
|
||||||
|
} else {
|
||||||
|
delta = DEFAULT_FRAME_TIME_MS;
|
||||||
|
}
|
||||||
|
|
||||||
srs_info("jitter detected, delta=%d, last_pkt=%d, time=%d, correct_to=%d",
|
srs_info("jitter detected, last_pts=%d, pts=%d, diff=%d, last_time=%d, time=%d, diff=%d",
|
||||||
delta, last_pkt_time, time, last_pkt_correct_time + delta);
|
last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta);
|
||||||
} else {
|
} else {
|
||||||
srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d",
|
srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d",
|
||||||
time, last_pkt_time, last_pkt_correct_time + delta);
|
time, last_pkt_time, last_pkt_correct_time + delta);
|
||||||
|
@ -155,6 +160,8 @@ SrsSource::SrsSource(std::string _stream_url)
|
||||||
|
|
||||||
cached_video_count = 0;
|
cached_video_count = 0;
|
||||||
enable_gop_cache = true;
|
enable_gop_cache = true;
|
||||||
|
|
||||||
|
audio_sample_rate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsSource::~SrsSource()
|
SrsSource::~SrsSource()
|
||||||
|
@ -182,6 +189,13 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
|
||||||
metadata->metadata->set("server", new SrsAmf0String(
|
metadata->metadata->set("server", new SrsAmf0String(
|
||||||
RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")"));
|
RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")"));
|
||||||
|
|
||||||
|
SrsAmf0Any* prop = NULL;
|
||||||
|
if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) {
|
||||||
|
if (prop->is_number()) {
|
||||||
|
audio_sample_rate = (int)(srs_amf0_convert<SrsAmf0Number>(prop)->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// encode the metadata to payload
|
// encode the metadata to payload
|
||||||
int size = metadata->get_payload_length();
|
int size = metadata->get_payload_length();
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
|
@ -214,7 +228,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
|
||||||
std::vector<SrsConsumer*>::iterator it;
|
std::vector<SrsConsumer*>::iterator it;
|
||||||
for (it = consumers.begin(); it != consumers.end(); ++it) {
|
for (it = consumers.begin(); it != consumers.end(); ++it) {
|
||||||
SrsConsumer* consumer = *it;
|
SrsConsumer* consumer = *it;
|
||||||
if ((ret = consumer->enqueue(cache_metadata->copy())) != ERROR_SUCCESS) {
|
if ((ret = consumer->enqueue(cache_metadata->copy(), audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch the metadata failed. ret=%d", ret);
|
srs_error("dispatch the metadata failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +258,7 @@ int SrsSource::on_audio(SrsCommonMessage* audio)
|
||||||
std::vector<SrsConsumer*>::iterator it;
|
std::vector<SrsConsumer*>::iterator it;
|
||||||
for (it = consumers.begin(); it != consumers.end(); ++it) {
|
for (it = consumers.begin(); it != consumers.end(); ++it) {
|
||||||
SrsConsumer* consumer = *it;
|
SrsConsumer* consumer = *it;
|
||||||
if ((ret = consumer->enqueue(msg->copy())) != ERROR_SUCCESS) {
|
if ((ret = consumer->enqueue(msg->copy(), audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch the audio failed. ret=%d", ret);
|
srs_error("dispatch the audio failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -288,7 +302,7 @@ int SrsSource::on_video(SrsCommonMessage* video)
|
||||||
std::vector<SrsConsumer*>::iterator it;
|
std::vector<SrsConsumer*>::iterator it;
|
||||||
for (it = consumers.begin(); it != consumers.end(); ++it) {
|
for (it = consumers.begin(); it != consumers.end(); ++it) {
|
||||||
SrsConsumer* consumer = *it;
|
SrsConsumer* consumer = *it;
|
||||||
if ((ret = consumer->enqueue(msg->copy())) != ERROR_SUCCESS) {
|
if ((ret = consumer->enqueue(msg->copy(), audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch the video failed. ret=%d", ret);
|
srs_error("dispatch the video failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -319,19 +333,19 @@ int SrsSource::on_video(SrsCommonMessage* video)
|
||||||
consumer = new SrsConsumer(this);
|
consumer = new SrsConsumer(this);
|
||||||
consumers.push_back(consumer);
|
consumers.push_back(consumer);
|
||||||
|
|
||||||
if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy())) != ERROR_SUCCESS) {
|
if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch metadata failed. ret=%d", ret);
|
srs_error("dispatch metadata failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("dispatch metadata success");
|
srs_info("dispatch metadata success");
|
||||||
|
|
||||||
if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy())) != ERROR_SUCCESS) {
|
if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch video sequence header failed. ret=%d", ret);
|
srs_error("dispatch video sequence header failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("dispatch video sequence header success");
|
srs_info("dispatch video sequence header success");
|
||||||
|
|
||||||
if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy())) != ERROR_SUCCESS) {
|
if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch audio sequence header failed. ret=%d", ret);
|
srs_error("dispatch audio sequence header failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -340,7 +354,7 @@ int SrsSource::on_video(SrsCommonMessage* video)
|
||||||
std::vector<SrsSharedPtrMessage*>::iterator it;
|
std::vector<SrsSharedPtrMessage*>::iterator it;
|
||||||
for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
|
for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
|
||||||
SrsSharedPtrMessage* msg = *it;
|
SrsSharedPtrMessage* msg = *it;
|
||||||
if ((ret = consumer->enqueue(msg->copy())) != ERROR_SUCCESS) {
|
if ((ret = consumer->enqueue(msg->copy(), audio_sample_rate)) != ERROR_SUCCESS) {
|
||||||
srs_error("dispatch cached gop failed. ret=%d", ret);
|
srs_error("dispatch cached gop failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* enqueue an shared ptr message.
|
* enqueue an shared ptr message.
|
||||||
*/
|
*/
|
||||||
virtual int enqueue(SrsSharedPtrMessage* msg);
|
virtual int enqueue(SrsSharedPtrMessage* msg, int audio_sample_rate);
|
||||||
/**
|
/**
|
||||||
* get packets in consumer queue.
|
* get packets in consumer queue.
|
||||||
* @pmsgs SrsMessages*[], output the prt array.
|
* @pmsgs SrsMessages*[], output the prt array.
|
||||||
|
@ -74,7 +74,7 @@ private:
|
||||||
* detect the time jitter and correct it.
|
* detect the time jitter and correct it.
|
||||||
* @doc update the README.cmd
|
* @doc update the README.cmd
|
||||||
*/
|
*/
|
||||||
virtual int jitter_correct(SrsSharedPtrMessage* msg);
|
virtual int jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,6 +112,11 @@ private:
|
||||||
* cached gop.
|
* cached gop.
|
||||||
*/
|
*/
|
||||||
std::vector<SrsSharedPtrMessage*> gop_cache;
|
std::vector<SrsSharedPtrMessage*> gop_cache;
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* the sample rate of audio in metadata.
|
||||||
|
*/
|
||||||
|
int audio_sample_rate;
|
||||||
private:
|
private:
|
||||||
SrsSharedPtrMessage* cache_metadata;
|
SrsSharedPtrMessage* cache_metadata;
|
||||||
// the cached video sequence header.
|
// the cached video sequence header.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue