home :: video_parsing
Video Parsing
Each class in the coding element event hierarchy implements a static class method called GetNext(BitStream bs). This method assumes that the next bit in the bitstream passed as a parameter is the first bit of the coding element. The method then parses the coding element, constructs a new instance of the codinge element event, and publishes the event to all registered handlers (see here for more on the event mechanism).
While each coding element event class knows how to parse an instance of itself, determining the order of the coding elements to be parsed and managing the video parsing process is not provided by these methods per se. A helper class called VideoParser is provided for this task.
Creating a Video Parser
To create a new video parser, simply call the constructor, providing a BitStream object as the source of bits for the video stream like so:
VideoParser vp = new VideoParser(bs); // bs is an instance of BitStream
Using the Video Parser
The VideoParser object provides a very simple public interface. There are only two public methods which are:
public void parsePicture();
public void skipPicture();
These methods do pretty much what they say they do (i.e., parse the next picture or skip the next picture). When either is called for the first time, the parser skips over all bits until it encounters a MPEG-2 sequence header. These skipped bits are published as OpaqueBits events. The sequence header, sequence extension header, any user data and other extension headers, group of pictures header, picture header, and picture coding extension header are then parsed and published. If the picture is to be parsed (as opposed to skipped), the picture data is then parsed and published. If the picture is to be skipped, slice headers are parsed and published and all of the coding elements between the slice headers (i.e., the actual coded picture information) is simply parsed off as OpaqueBits. Parsing ends at the end of the picture data. Subsequent calls to either method picks up parsing where the last call left off.
The skipPicture() method is useful to avoid parsing and publishing the coding elements of a picture you know that you are not interested in. For example, if you are only interested in I-frames, then you can use skipPicture() to avoid parsing P and B frames and use parsePicture() only when the picture is an I frame.
Dealing with the End of the Stream
After the sequence end code has been encountered, both methods will simply return without doing anything. This condition can be checked using the EOF property of the VideoParser object. If the bitstream runs out of bits, the BitStream object will throw an exception which can be caught to detect this situation.
Typical Use Example
The following example shows the typical way of using the VideoParser object.
// Create and set up a BitStream object. Here we assume that
// input is a Stream object where the bytes are coming from.
BitStream bs = new BitStream(input);
// Create and register our event delegates that will process the
// coding elements we are interested in. Here we assume that
// we have methods for processing PictureHeader, PictureCoding,
// and Macroblock elements called my_pict_header_handler,
// my_pict_coding_handler, and my_mb_handler
PictureHeader.handlers += new PictureHeader.Handler(my_pict_header_handler);
PictureCoding.handlers += new PictureCoding.Handler(my_pict_coding_handler);
Macroblock.handlers += new Macroblock.Handler(my_mb_handler);
// Create a VideoParser object.
VideoParser vp = new VideoParser(vp);
// Parse the video stream until either end of sequence or an
// out of bits exception occurs.
try {while (!vp.EOF) {}vp.parsePicture();}
catch (OutOfBitsException e) {// Handle ungraceful end to stream here.}
