Summary:ASTERISK-01365: IAX jitter buffer reorder problem [diagnosis/description]
Reporter:stevekstevek (stevekstevek)Labels:
Date Opened:2004-04-07 10:16:33Date Closed:2011-06-07 14:05:04
Versions:Frequency of
Description: We've recently uncovered a problem with the jitter buffer code in IAX2 (probably also 1, for what it's worth).  We see this mostly on the chan_iax2 side, but it's also incorrect in libiax2 and iaxclient.

For discussion, let's say there's a call between machines A and B.  We'll describe the problem here with the jitter buffer on B:

The problem occurs when:

&ASTERISK-8005; The jitter buffer on B is currently shrinking (so it's getting set 2ms smaller each time it processes a frame from A).
&ASTERISK-8005; A is sending a sequence of frames that are timed 2ms or less apart.  This can happen if scheduling difficulties on A cause it to get temporarily behind.  For example, on Win98, we get generally get scheduled once every 50-60ms, so we end up sending frames in bunches of 2 or 3.
&ASTERISK-8005; The sequentially-timestamped frames from A arrive roughly at the same time to B.

What happens here is that in this case, the frames get scheduled out-of-order, and the result is very bad voice quality.  The rough sequence of processing (at B) is as follows:

Start/First Packet:  Jitter buffer is set to size J, first packet with timestamp "TS" is scheduled for delivery in M ms.

Second Packet: Jitter buffer is set to size J-2; second packet with timestamp TS+1 is scheduled for delivery in M-1 ms.

Third Packet:  Jitter buffer is set to size J-4; third packet with timestamp TS+2 is scheduled for delivery in M-2ms.

(etc, for as many consecutive packets there are).

The out-of-order delivery of packets is really a problem, regardless of what's on the other side of the channel:  Whether it's bridged to another channel, or in an application.

Possible solutions:

&ASTERISK-8005; Cheap/simple solution: Instead of enforcing a 1ms difference between consecutive frames, enforce a 3ms difference (i.e. the "shrink-interval"  +1).   This seems like it would work OK in the cases we see.  A partial drawback seems to be that it restricts the number of frames from 1000/sec to 333/sec, but I don't see that actually being a problem.  I'm not sure if this holds up in the case where packets actually arrive out-of-order.
&ASTERISK-8005; More complicated (and expensive) solutions require looking around at the queue of scheduled packets when shrinking, and either:
&ASTERISK-9416; Just looking to see if there is a frame scheduled for the time range where the shrinking would cause out-of-orderedness, and if so, delaying the frame in hand until after that one.
&ASTERISK-9416; Actually re-scheduling the queue to account for the jitter buffer size change.

We have implemented the Cheap Solution, in iaxclient, to see as it solves our observed and reported problem.  As it stood, calls from Win9x to us are relatively unintelligible because of this, and I suspect that this also affects other platforms when they're busy.

Either of these solutions, however, really needs to be implemented in both chan_iax2 as well as in iaxclient, because the error can happen on either end.  The cheap solution, of course, is actually a [backwards compatible] change to the protocol, while the "more complicated" solutions actually correct the implementation.
Comments:By: Mark Spencer (markster) 2004-04-07 10:28:16

I think the right thing might be to forge the timestamps to what they *should* be based upon the number of samples.  That will allow other end devices to accomodate the jitter properly (especially SIP ones if there are iAX2 to SIP transitions).  Audio frames should *never* have timestamps which are within just a few milliseconds of one another.  Full frames will be handled in the Seqno order, so I don't see how this is a bug.  If you feel differently let me know soon.