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
sayer/1.4-spce2.6
Maxim Sobolev 19 years ago
parent e6fa3fd711
commit 1bebb118d9

@ -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

@ -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);

@ -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
}

Loading…
Cancel
Save