Microsoft DirectX 9.0

PSI Parser Filter Sample

The PSI Parser filter receives Program Specific Information (PSI) from an MPEG-2 transport stream and extracts program information from the Program Association Table (PAT) and Program Map Tables (PMT). This information enables an application to configure the MPEG-2 Demultiplexer. The filter supports a custom interface, IMpeg2PsiParser, for retrieving the PSI information.

This filter is designed for MPEG-2 devices, such as IEEE 1394 MPEG-2 camcorders and D-VHS devices. See MSTape Driver for more information. Digital television broadcast sources should use a TIF filter to get program information.

User's Guide

You can test the PSI Parser filter in GraphEdit as follows:

  1. Launch GraphEdit.
  2. Insert an MPEG-2 transport source. MPEG-2 camcorders and D-VHS devices appear as "Microsoft AV/C Tape Subunit Device" in the Video Capture Sources category.
  3. Connect the source filter to the MPEG-2 Demultiplexer filter.
  4. Use the property page on the demux to create an output pin with media type MPEG-2 PSI. This pin will deliver the PAT and PMT sections.
  5. Use the demux property page to map PID 0x00 to the output pin. Set the content type to MPEG2 PSI Sections.
  6. Connect the demux output pin to PSI Parser.

    PSI Parser filter graph

  7. Run the graph, in order to feed PSI data to the PSI Parser filter. As the filter decodes the PAT sections, it automatically maps the PMT PIDs to the same output pin on the demux, so that it receives the PMT sections.
  8. Use the PSI Parser property page to select a program number. The elementary stream list in the property page will show the PID and stream type associated with each elementary stream in the selected program. The property page is designed to recognize stream types defined in ISO/IEC 13818-1.
  9. Enter the audio PID number in the Audio PID edit box, and the video PID number in the Video PID edit box.
  10. Click the View Program button. The PSI Parser will configure the output pins on the demux to match the program stream information and render the pins. 

Note   The PSI Parser property page is provided to make testing easier, and to provide sample code that configures the MPEG-2 Demultiplexer. It is not recommended for applications to use. Applications should configure the demux programmatically.

To use the PSI Parser filter in an application, start by building the filter graph from the MPEG-2 source to the MPEG-2 demux. Code for this step is not shown here, because the exact graph configuration will depend on the source.

Next, create an output pin on the demux for the PSI data. Map PID 0x00, which is reserved for PAT sections, to this pin, as shown in the following code:

// Set the media type to MPEG-2 table sections.
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = KSDATAFORMAT_TYPE_MPEG2_SECTIONS;

// Create the pin.
IPin *pPsiPin;
hr = pDemux->CreateOutputPin(&mt, L"PSI", &pPsiPin);
if (SUCCEEDED(hr))
{
    // Map to PID 0.
    ULONG Pid = 0x00;
    hr = pPid->MapPID(1, &Pid, MEDIA_MPEG2_PSI);
}

For more information, see Using the MPEG-2 Demultiplexer.

Add the PSI Parser filter to the graph and connect it to the output pin on the demux. Query the PSI Parser for the IMpeg2PsiParser interface. Now run the graph and wait for EC_PROGRAM_CHANGED events, which signal a new PAT or PMT section. This event is a custom event defined by the PSI Parser filter. When you receive an EC_PROGRAM_CHANGED event, you can get the available PSI information by calling IMpeg2PsiParser methods. This section describes the methods you will need most often.

To get the number of programs, use the GetCountOfPrograms method:

int NumProgs = 0;
hr = pPsi->GetCountOfPrograms(&NumProgs);

To get the program number for a specific program, use the GetRecordProgramNumber method:

WORD ProgNum = 0;
for (int i = 0; iProgram < NumProgs; i++)
{
    hr = pPsi->GetRecordProgramNumber(i, &ProgNum);
    ...
}

The program number is used to obtain the PMT entries for individual programs. To get the number of elementary streams in a program, use the GetCountOfElementaryStreams method:

ULONG cElemStreams = 0;
hr = pPsi->GetCountOfElementaryStreams(ProgNum, &cElemStreams);

For each elementary stream, the GetRecordElementaryPid method returns the PID, and the GetRecordStreamType method returns the stream type:

BYTE ESType = 0;
WORD ESPid = 0;
for (ULONG j = 0; j < cElemStreams; j++)
{
    hr = pPsi->GetRecordElementaryPid(ProgNum, j, &ESPid);
    hr = pPsi->GetRecordStreamType(ProgNum, j, &ESType);
}

The PID and the stream type enable you to configure new output pins on the MPEG-2 Demultiplexer. This may require some knowledge of the original source. For example, ISO/IEC 13818-1 defines stream types 0x80 through 0xFF as "user private," but other standards that are based on MPEG-2 may assign other meanings to these types. 

The MPEG-2 Demultiplexer can create new pins and new PID mappings while the graph is running, but you must stop the graph to connect pins.

See Also