Playing Back Live Streams with DirectShow
To play back a live data source, you will need a source filter that introduces the mpeg data into the graph. This could be based on the CSource class, and might for example receive UDP Multicast data from a socket and send this data downstream.
Source filters are normally expected to supply data using the IAsyncReader interface. This allows random access to the entire data stream by the parser, even when not streaming. It is possible to implement this, but not very clean. You will probably want to make your source filter implement the push-model IMemInputPin instead.
The DirectShow-supplied splitters for MPEG-1 and 2 cannot easily be made to work with live data streams. They do two tasks in addition to separating out the individual elementary streams: they convert the embedded PTS times into DirectShow timestamps, and they create a media type including the sequence header. Both of these involved searching around in the file at pin-connection time, which is clearly not possible for live sources.
There are four possible solutions to this problem:
- Implement a pull-model source filter that supplies previously-prepared data at connection time. This will allow you to work with the existing parsers, but is complicated and hard to make work. In fact this is probably more work than developing a new splitter.
- Some MPEG decoders are supplied with a splitter filter that will support live streams. If you are happy to be tied to a specific decoder supplier, this is probably the simplest solution. However, not all of these splitter filters are written to the highest level of quality.
- DirectX8 contains an MPEG-2 Demultiplexer filter that does support live streaming of MPEG-2 program or transport stream. However, one drawback of this is that you need to know which elementary streams to extract, and what format the streams are. To use this filter, you will need know something about the stream you are receiving, and you will need to do some work in your application to configure the demultiplexor correctly.
- You can write your own splitter. This is not as hard as you might think, especially if you are just supporting live streams and not seeking about in the stream. You can start from the mpegparse sample code in the DirectShow 6 SDK (I'm afraid this has been removed from the DirectX 8 sdk but can still be found in some archives -- it has a number of bugs, and is pull-mode only, but it does demonstrate the basics of mpeg-1 and mpeg-2 parsing). Your source filter would supply data using the IMemInputPin transport rather than IAsyncReader (see the discussion of IAsyncReader elsewhere). The splitter filter would look for the first pts and first sequence header after any discontinuity, and would use these for the media type and as a base for timestamp conversion. A default media type would be needed at connection time, to be replaced by a dynamically detected media type when the first sequence header is detected.