[Live-devel] Layered video with Live555

Tim Stabrawa stabrawa at stanford.edu
Sat Mar 3 16:10:28 PST 2007


Ross Finlayson wrote:
>> For an academic demonstration, I'm planning on extending Live555 to
>> support RTP transport of scalable H.264 video and was hoping someone
>> with a reasonable amount of experience with Live555 could help steer me
>> in the direction of least pain ...
>>
>> Basically, I'll be using the reference codec for H.264 SVC (currently in
>> development) to generate a file containing H.264 NAL units.  The
>> important difference between the output of this codec and a standard
>> H.264 stream is the addition of two NAL unit types (20 & 21), which
>> carry information about which layer of video is described in the
>> preceding/current NAL unit.  For now, assume I know how to parse this
>> file and determine which NAL units belong to which layers.  My intention
>> is to send each layer out either multiplexed in the same RTP stream (the
>> easy way) or in separate RTP streams (the hard / interesting way),
>> according to this draft RFC:
>> http://www.ietf.org/internet-drafts/draft-ietf-avt-rtp-svc-00.txt
>>     
>
> This is interesting.  I suggest proceeding in three steps (with each 
> step requiring additional work building on the previous steps):
> 1/ Stream regular (non-SVC) H.264 video from a file.  You will be 
> able to test this using VLC.
> 2/ Add additional SVC layers, multiplexed in the same RTP stream as 
> the base layer.
> 3/ Use separate RTP streams for separate SVC layers.
>
> If you're streaming on a single RTP stream (steps 1/ or 2/), then 
> it's fairly straightforward: You'll need to write your own subclass 
> of "H264VideoStreamFramer"; that subclass will parse the input stream 
> (from a "ByteStreamFileSource").  You'll then 'play' this to a 
> "H264VideoRTPSink" object
Ok, I think I have the StreamFramer class basically working except for 
one small problem.  To parse the file, I created a subclass of 
MPEGVideoStreamParser (purely out of convenience), and defined a parse() 
routine that has two states: PARSING_START_SEQUENCE and 
PARSING_NAL_UNIT.  The parser basically alternates between these two 
states either throwing data out (to find the first sequence), or saving 
it (until it finds the next).

So naturally, there is no start sequence at the end of the file.  It 
just sorta ends.  So what I'm seeing when I play from my Framer source 
class to a H264VideoFileSink class is that all the NAL units are copied 
over to the output file except the last one.
  What I think is happening is, for the last NAL unit, my call to 
test4Bytes() is throwing an exception once it gets to the end of the 
file .. causing parse() to return 0.  Meanwhile, the StreamParser class 
goes off and tries to read more from the file, sees that the file is at 
EOF, and closes the file, etc.

I peeked around at some of the mechanisms for handling what to do when a 
stream gets closed, thinking this would afford me the opportunity to 
tell my stream parser to give me what it has left it its buffer, but I 
haven't been able to wrap my mind around it completely yet.  Do you 
think this is the Right Way to do it?  Any other suggestions?

Below is the code for my parse routines .. there's not much to 'em.

- Tim

- snip -

void H264JSVMVideoStreamParser :: parseStartSequence()
{
    // Find start sequence (0001)
    u_int32_t test = test4Bytes();
    while (test != 0x00000001)
    {
        skipBytes(1);
        test = test4Bytes();
    }
    setParseState(PARSING_NAL_UNIT);
    skipBytes(4);
}

unsigned H264JSVMVideoStreamParser :: parseNALUnit()
{
    // Find next start sequence (0001) or end of stream
    u_int32_t test = test4Bytes();
    while (test != 0x00000001)
    {
        saveByte(get1Byte());
        test = test4Bytes();
    }
    setParseState(PARSING_START_SEQUENCE);

    return curFrameSize();
}


More information about the live-devel mailing list