From 1bebb118d96d93faa0c8d9327f07ff8412daa361 Mon Sep 17 00:00:00 2001 From: Maxim Sobolev Date: Mon, 19 Feb 2007 23:02:09 +0000 Subject: [PATCH] Improve jitter bufering a bit: 1. Use more aggressive resyncronization algorithm. 2. Respect the marker bit in RTP packets and do immediate resync on such packets without increasing the jitter delay. This makes the jitter buffer work well with UAs that use silence suppression. Tested with Cisco and X-Lite. 3. The AmPlayoutBuffer has been modified to allow the audio data be put directly in the audio buffer by real timestamp from RTP. This change can possibly break the adaptive playout buffer so it has been put in "#ifdef USE_ADAPTIVE_JB" blocks. The last change is required due to the fact that internal audio packet size (in timestamp units) can differ from RTP packet size and so the internal audio packet can be overlapped by several RTP packets or vice versa. While the original playout buffer is generally ok but the problem is in the loss concealments that can break the buffer as the concealment algorithm can refuse to return any data and so breaking the timestamp monotony and thus causing the voice corruption. Sponsored by: Digifonica Canada Limited Work done by: Sippy Software, Inc. git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@234 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- core/AmJitterBuffer.cpp | 17 +++++++++++------ core/AmJitterBuffer.h | 3 ++- core/AmPlayoutBuffer.cpp | 9 +++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/core/AmJitterBuffer.cpp b/core/AmJitterBuffer.cpp index c1468dba..9363047e 100644 --- a/core/AmJitterBuffer.cpp +++ b/core/AmJitterBuffer.cpp @@ -66,14 +66,17 @@ void PacketAllocator::free(Packet *p) AmJitterBuffer::AmJitterBuffer(AmRtpStream *owner) : m_tsInited(false), m_tsDeltaInited(false), m_delayCount(0), m_jitter(INITIAL_JITTER), m_owner(owner), - m_tail(NULL), m_head(NULL) + m_tail(NULL), m_head(NULL), m_forceResync(false) { } void AmJitterBuffer::put(const AmRtpPacket *p) { m_mutex.lock(); - if (m_tsInited && ts_less()(m_lastTs + m_jitter, p->timestamp)) { + if (p->marker) + m_forceResync = true; + if (m_tsInited && !m_forceResync && ts_less()(m_lastTs + m_jitter, p->timestamp)) + { unsigned int delay = p->timestamp - m_lastTs; if (delay > m_jitter && m_jitter < MAX_JITTER) { @@ -124,7 +127,7 @@ void AmJitterBuffer::put(const AmRtpPacket *p) m_lastTs = p->timestamp; m_tsInited = true; } - else if (ts_less()(m_lastTs, p->timestamp)) { + else if (ts_less()(m_lastTs, p->timestamp) || m_forceResync) { m_lastTs = p->timestamp; } @@ -145,10 +148,11 @@ bool AmJitterBuffer::get(AmRtpPacket& p, unsigned int ts, unsigned int ms) m_mutex.unlock(); return false; } - if (!m_tsDeltaInited) { + if (!m_tsDeltaInited || m_forceResync) { m_tsDelta = m_lastTs - ts + ms; m_tsDeltaInited = true; m_lastAudioTs = ts; + m_forceResync = true; } else if (m_lastAudioTs != ts && m_lastResyncTs != m_lastTs) { if (ts_less()(ts + m_tsDelta, m_lastTs)) { @@ -156,14 +160,15 @@ bool AmJitterBuffer::get(AmRtpPacket& p, unsigned int ts, unsigned int ms) * New packet arrived earlier than expected - * immediate resync required */ - m_tsDelta += ms; + m_tsDelta += m_lastTs - ts + ms; // DBG("Jitter buffer resynced forward (-> %u)\n", m_tsDelta); m_delayCount = 0; } else if (ts_less()(m_lastTs, ts + m_tsDelta - m_jitter / 2)) { /* New packet hasn't arrived yet */ if (m_delayCount > RESYNC_THRESHOLD) { - m_tsDelta -= 80; // 10ms + unsigned int d = m_tsDelta -(m_lastTs - ts + ms); + m_tsDelta -= d / 2; // DBG("Jitter buffer resynced backward (-> %u)\n", m_tsDelta); } else diff --git a/core/AmJitterBuffer.h b/core/AmJitterBuffer.h index a46c62a2..17d59c68 100644 --- a/core/AmJitterBuffer.h +++ b/core/AmJitterBuffer.h @@ -35,7 +35,7 @@ class AmRtpStream; #define INITIAL_JITTER 640 // 80 miliseconds #define MAX_JITTER 16000 // 2 seconds -#define RESYNC_THRESHOLD 10 +#define RESYNC_THRESHOLD 2 class Packet { public: @@ -74,6 +74,7 @@ private: int m_delayCount; unsigned int m_jitter; AmRtpStream *m_owner; + bool m_forceResync; public: AmJitterBuffer(AmRtpStream *owner); diff --git a/core/AmPlayoutBuffer.cpp b/core/AmPlayoutBuffer.cpp index f502a0a7..6ec56257 100644 --- a/core/AmPlayoutBuffer.cpp +++ b/core/AmPlayoutBuffer.cpp @@ -23,7 +23,11 @@ AmPlayoutBuffer::AmPlayoutBuffer() void AmPlayoutBuffer::direct_write(unsigned int ts, ShortSample* buf, unsigned int len) { +#ifndef USE_ADAPTIVE_JB buffer_put(w_ts,buf,len); +#else + buffer_put(ts, buf, len); +#endif // USE_ADAPTIVE_JB } void AmPlayoutBuffer::write(u_int32_t ref_ts, u_int32_t ts, int16_t* buf, u_int32_t len) @@ -33,6 +37,7 @@ void AmPlayoutBuffer::write(u_int32_t ref_ts, u_int32_t ts, int16_t* buf, u_int3 u_int32_t AmPlayoutBuffer::read(u_int32_t ts, int16_t* buf, u_int32_t len) { +#ifndef USE_ADAPTIVE_JB if(ts_less()(r_ts,w_ts)){ u_int32_t rlen=0; @@ -46,6 +51,10 @@ u_int32_t AmPlayoutBuffer::read(u_int32_t ts, int16_t* buf, u_int32_t len) } return 0; +#else + buffer_get(ts, buf, len); + return len; +#endif // USE_ADAPTIVE_JB }