[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