[Shtoom] playout alg works!

Zooko O'Whielacronx zooko at zooko.com
Mon Feb 21 22:05:58 CET 2005


This passes its self-tests.  See "test_playout.py" for details.  It 
means that it handles the following four cases nicely:

1.  A nearly perfect even flow of input packets.  It correctly plays 
them all out to the speaker.
2.  A flow of packets way too fast to play out.  It correctly "catches 
up" by dropping the oldest ones and playing out the newest ones.
3.  Out of order packets, where packets arrive in the following order: 
2, 1, 4, 3, 6, 5, 8, 7, etc.  It correctly re-orders them all.
4.  Jittery packets, where 40 ms pass with no packets arriving, 
followed by two packets arriving at once, followed by 40 ms of nothing, 
etc. (where each packet contains 20 ms worth of audio).  It correctly 
evens out the jitter and plays smooth audio.

This algorithm isn't perfect, but it is better than the two that are 
currently in Shtoom SVN head -- BraindeadPlayout and BacklogPlayout.

This algorithm evolved from BacklogPlayout.

Unfortunately there are a few shallow merge conflicts which break 
Shtoom's unit tests.  These arose within the last two weeks.  I'll fix 
them tomorrow.

Also I haven't actually run Shtoom with this patch and listened to the 
result.

Also there are some changes that this patch makes to Shtoom which are 
not really necessary -- namely that it introduces a MediaSample class 
which has a sample and a Content-Type instead of using RTPPacket for 
the same purpose.  However, the MediaSample class is somewhat useful as 
it helped me understand what parts of the code did what.  If you 
(Anthony) don't want that part, I'll help make a patch which doesn't do 
that part.

class Playout:
     """
     Theory of operation: you have two modes: "playout" mode and 
"refill" mode.
     When you are in playout mode then you play out sequential audio 
packets from
     your jitter buffer to the audio output device's FIFO as needed.  Do 
the
     obvious right thing with out-of-order packets.

     You switch to refill mode when you have a buffer underrun -- that 
is not
     enough in-order data came in from the network so the audio output 
device
     (i.e., the speaker) ran dry.  When you are in refill mode, you 
don't send
     any packets to the audio output device, but instead hoard them 
until you
     have JITTER_BUFFER_SECONDS worth of sequential, in-order data 
ready, and
     then switch to playout mode.

     There's an added complication because this code doesn't currently 
have a
     nice clean way to say "write this 20 milliseconds worth of audio to 
the
     output device\'s FIFO, and then run the following method *just* 
before those
     20 milliseconds are all used up".  This complication is called the 
"playout
     buffer", and it is a way to stuff way more than 20 milliseconds 
worth of
     audio into the audio output device's FIFO, so that we'll get a 
chance to add
     more packets before it underruns, even when reactor.callLater() 
sometimes
     gets called 110 milliseconds later than we wanted.  This happens on 
Mac.
     See TODO item about playout buffer in comments above.
     """

Zooko

-------------- next part --------------
A non-text attachment was scrubbed...
Name: playout.patch
Type: application/octet-stream
Size: 50391 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/shtoom/attachments/20050221/d0efb423/attachment.obj>


More information about the Shtoom mailing list