[Speex-dev] Jitter Buffer fix for frozen sender

Thorvald Natvig thorvald at natvig.com
Fri Apr 11 04:25:04 PDT 2008


On substandard hardware (read: "cheapest possible" commodity stuff) 
installed on a fairly popular OS, but without any updated drivers, the 
machine will frequently freeze in kernel mode for 100-200ms. It will 
infrequently freeze in kernel mode for 2-3 seconds. The users, for some 
reason unknown to me, accept this as quite common on PCs. So the 
frequency of the problem is inversely proportional to the computer savvy 
of the user.

As for how to fix it, I'm not really sure. Perhaps an idea would be to 
add a ctl to indicate "I might have frozen; I'm going to need 80 ms of 
data in total to refill my buffers, please update accordingly."? The 
problem with that though is that once you unfreeze, you don't know if 
it's the audio output thread or your network thread that gets called first.

There's an alternate idea; instead of discarding late packets etc, 
insert them too into the jitter buffer, and discard the packets with the 
lowest sequence instead of the lowest timestamp. Then, at any time the 
user calls _get, if there are more "useless" packets in the buffer then 
"usefull" ones, scan for the longest semi-continous sequence and switch. 
This will also allow the jitter buffer to quickly adapt to timestamp 
rollover, freezes at either end and most other oddities I can think of. 
It is computationally complex though, and a rather drastic change. .. 
Perhaps something for the 1.3 timeframe?

Jean-Marc Valin wrote:
> Patch applied offline (I'm in the plane), remind me if I forget to push
> it. About the "resync on burst" issue, I was aware of it, but I'm not
> sure how to fix it. Any idea? Also, do you see the problem happening often?
> 	Jean-Marc
> Thorvald Natvig a écrit :
>> The jitter buffer would "freeze" under the following condition:
>> - The sender and receiver are in sync.
>> - The sender machine freezes for a few seconds while the receiver does not.
>> - This causes all the packets sent by the sender to have a timestamp
>> that is too low to be considered, meaning jitter_buffer_put ditches it
>> before it checks if lost_count > 20 to reset.
>> - The jitter buffer will never reset on its own and will discard all
>> incoming packets.
>> The patch moves the check for lost_count > 20 before the check if the
>> packet is "hopelessly late". If lost_count > 20, something is very wrong
>> and we want this packet to be the start of our new synchronized stream.
>> Also included is a testcase.
>> Note that I found a related problem if the receiver is frozen. Once it
>> unfreezes, you may have a hundred speex_jitter_put before a _get. _get
>> will then still return the very first packet, even if there are suddenly
>> 100 unplayed packets in the buffer (so it's playing old data).
>> Similarily, if more than 300 packets are suddenly inserted, the buffer
>> is full, and the call to _get actually fails, even if there are 300
>> consecutive packets in the buffer. After a few _get calls, the buffer
>> will reset, and the next packet inserted will be in sync again.
>> However, this is a rather unusual case, and the jitter buffer does
>> recover from it, so I do not consider it critical.
>> ------------------------------------------------------------------------
>> _______________________________________________
>> Speex-dev mailing list
>> Speex-dev at xiph.org
>> http://lists.xiph.org/mailman/listinfo/speex-dev
> _______________________________________________
> Speex-dev mailing list
> Speex-dev at xiph.org
> http://lists.xiph.org/mailman/listinfo/speex-dev

More information about the Speex-dev mailing list