Summary:ASTERISK-04149: [patch] new jb - improve scheduling and jitter handling in new jitter buffer
Reporter:grolloj (grolloj)Labels:
Date Opened:2005-05-12 13:40:39Date Closed:2011-06-07 14:10:35
Versions:Frequency of
Environment:Attachments:( 0) jb_updates.patch.txt
Description:This patch addresses

1) The jitterbuffer made incorrect assumptions about the duration of voice frames.  In particular, it assumed that all frames that it sees will be the same duration, and that when it requests interpolation, the interpolated frame will _also_ be the same duration.   This would occur when calls have been transcoded through asterisk, and they get frames with durations of 20 40 20 40 ...

2)  The jitterbuffer also didn't deal with cases where silence begins while the jitterbuffer is planning to grow or shrink.  Ideally, it should grow or shrink more quickly during silence [since growing or shrinking during silence has little effect on percieved quality], but it should also not completely collapse the silence period.   Also, in some cases, jb_next was returning an incorrect value here, which could lead to jb_get being scheduled too early or too late, causing not so good results (not catastrophic, though).

3) The jitterbuffer may not have [and, in the process of implementing these changes, did not] deal very well with situations where the timebase of incoming timestamps changed by a very small amount:  i.e. if we got 0, 20, 40, 63, 83, 103, etc.  We'd end up considering the frame expected at time 60 to be lost, and interpolate, then expect a frame at time 80, and consider the frame at time 63 to be late, etc.  

4) chan_iax2 would sometimes spin trying to get the next frame from the jitterbuffer. We weren't pulling frames scheduled for the same millisecond we were asking, and because of an optimization in ast_sched_runq, our scheduled get  was run a little early.

These are solved by:

1a) Adding a new parameter that is passed into jb_get, called "interpl", which tells the jitterbuffer the duration of an interpolated frame.  We put this code to look up this value into asterisk proper as static inline, since it's just a simple case statement (presently, it's just a conditional, but perhaps some g.xxx might also use something other than 20).

1b) Changed the jb to move forward it's "pointer" until further down in the decision tree.  Also, renamed "last_voice_ts" to "next_voice_ts" to properly reflect what it (now) does.

2) Handle the silence case [when we want to shrink] a bit differently;  We basically will shrink by an interpolation frame length at a time every 10ms.

3) Allowing frames that are less than last_voice_ms late to be considered "on-time".  (note:  Whenever this happens, we always end up sending out "too much" audio, as opposed to "not enough" -- we have to choose one or another.  We don't keep track of the "excess" we send over a session though; that might be something to consider later).

4) In get_from_jb, we add the same fudge factor to our notion of now as does ast_sched_runq. Additionally, we make sure to process when the next frame is scheduled for now.

There's a few more issues we'll address in upcoming patches [these are already in iaxclient, we're just repackaging them for mantis].

a) Automatic resyncing:  We will try to detect huge discontinuities in timestamps which are not readily explainable by network effects.  When we see these, we'll try to resyncronize ourselves to the new timestamp base.  This is, in effect, a workaround for buggy senders.  

b) "Automatic silence mode":    Given that:
   i) The jitterbuffer really wants to know when silence begins and ends.  It wants to know this, because when it doesn't see frames, it considers them lost, and it tells codecs to interpolate, and it also makes statistics and so forth.  
   ii) Presently, asterisk has little support for CNG/DTX:  It might stop sending frames at any time, for any reason:  for example, if you're in an IVR, you'll get frames for announcements, and then asterisk will just send nothing while waiting for responses.
  iii) Interpolating more than 3-10 times in a row, or so, ends up generating silence.

"automatic silence mode" will cause the jitterbuffer to assume that a CNG frame has been received, and that we're in "silent mode" after it's found some reasonable number (like 10) of contiguous frames to be lost.

c) update_jbsched is being called after every put to and get from the jitterbuffer. It doesn't need to reschedule after every put; only put's that insert a frame at the head of the jb's scheduling queue.


Disclaimer on file
Comments:By: Mark Spencer (markster) 2005-05-12 14:47:11

This should go in, but please be sure that clients which don't send us contiguous timestamps (as per your example) are fixed.  It might be helpful to print a warning that such a situation has occured.

By: Russell Bryant (russell) 2005-05-12 14:57:40

added to CVS HEAD, Thanks!

By: Digium Subversion (svnbot) 2008-01-15 15:34:10.000-0600

Repository: asterisk
Revision: 5639

U   trunk/channels/chan_iax2.c
U   trunk/include/asterisk/frame.h
U   trunk/jitterbuf.c
U   trunk/jitterbuf.h

r5639 | russell | 2008-01-15 15:34:10 -0600 (Tue, 15 Jan 2008) | 2 lines

fixes for the new jitter buffer (bug ASTERISK-4149)