From 3aa6be864573941042157b818ce46599bd3081af Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 29 Oct 2013 10:17:33 +0800 Subject: [PATCH] fix the timestamp bug. correct the audio diff by audiosamplerate --- trunk/src/core/srs_core_protocol.cpp | 43 +++++++++++++++++++--------- trunk/src/core/srs_core_source.cpp | 40 +++++++++++++++++--------- trunk/src/core/srs_core_source.hpp | 9 ++++-- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/trunk/src/core/srs_core_protocol.cpp b/trunk/src/core/srs_core_protocol.cpp index e0e44d3f0..7cfce70cd 100755 --- a/trunk/src/core/srs_core_protocol.cpp +++ b/trunk/src/core/srs_core_protocol.cpp @@ -817,19 +817,6 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz pp[0] = *p++; 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 // timestamp: 3 bytes // 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. chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_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; + } 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) { @@ -913,7 +925,10 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz pp[1] = *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; srs_verbose("ignore the 4bytes extended timestamp. mh_size=%d", mh_size); } else { diff --git a/trunk/src/core/srs_core_source.cpp b/trunk/src/core/srs_core_source.cpp index e9940e082..6df6e67e2 100755 --- a/trunk/src/core/srs_core_source.cpp +++ b/trunk/src/core/srs_core_source.cpp @@ -69,11 +69,11 @@ int SrsConsumer::get_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; - if ((ret = jitter_correct(msg)) != ERROR_SUCCESS) { + if ((ret = jitter_correct(msg, audio_sample_rate)) != ERROR_SUCCESS) { return ret; } @@ -111,7 +111,7 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c return ret; } -int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg) +int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate) { int ret = ERROR_SUCCESS; @@ -130,10 +130,15 @@ int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg) // if jitter detected, reset the delta. 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", - delta, last_pkt_time, time, last_pkt_correct_time + delta); + srs_info("jitter detected, last_pts=%d, pts=%d, diff=%d, last_time=%d, time=%d, diff=%d", + last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta); } else { srs_verbose("timestamp no jitter. time=%d, last_pkt=%d, correct_to=%d", time, last_pkt_time, last_pkt_correct_time + delta); @@ -155,6 +160,8 @@ SrsSource::SrsSource(std::string _stream_url) cached_video_count = 0; enable_gop_cache = true; + + audio_sample_rate = 0; } SrsSource::~SrsSource() @@ -182,6 +189,13 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata metadata->metadata->set("server", new SrsAmf0String( 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(prop)->value); + } + } + // encode the metadata to payload int size = metadata->get_payload_length(); if (size <= 0) { @@ -214,7 +228,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata std::vector::iterator it; for (it = consumers.begin(); it != consumers.end(); ++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); return ret; } @@ -244,7 +258,7 @@ int SrsSource::on_audio(SrsCommonMessage* audio) std::vector::iterator it; for (it = consumers.begin(); it != consumers.end(); ++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); return ret; } @@ -288,7 +302,7 @@ int SrsSource::on_video(SrsCommonMessage* video) std::vector::iterator it; for (it = consumers.begin(); it != consumers.end(); ++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); return ret; } @@ -319,19 +333,19 @@ int SrsSource::on_video(SrsCommonMessage* video) consumer = new SrsConsumer(this); 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); return ret; } 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); return ret; } 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); return ret; } @@ -340,7 +354,7 @@ int SrsSource::on_video(SrsCommonMessage* video) std::vector::iterator it; for (it = gop_cache.begin(); it != gop_cache.end(); ++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); return ret; } diff --git a/trunk/src/core/srs_core_source.hpp b/trunk/src/core/srs_core_source.hpp index b2737aeec..30f2cfa6f 100755 --- a/trunk/src/core/srs_core_source.hpp +++ b/trunk/src/core/srs_core_source.hpp @@ -61,7 +61,7 @@ public: /** * enqueue an shared ptr message. */ - virtual int enqueue(SrsSharedPtrMessage* msg); + virtual int enqueue(SrsSharedPtrMessage* msg, int audio_sample_rate); /** * get packets in consumer queue. * @pmsgs SrsMessages*[], output the prt array. @@ -74,7 +74,7 @@ private: * detect the time jitter and correct it. * @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. */ std::vector gop_cache; +private: + /** + * the sample rate of audio in metadata. + */ + int audio_sample_rate; private: SrsSharedPtrMessage* cache_metadata; // the cached video sequence header.