Microsoft DirectX 9.0

Viewing World Standard Teletext

World Standard Teletext (WST) is encoded in the vertical blanking interval (VBI) of the analog television signal. The filter graph for previewing teletext is similar to the graph used to view closed captions.

WST Preview Graph

This graph uses the following filters for WST display:

The Capture Graph Builder's RenderStream method does not support the WST filters directly, so your application must do some extra work.

  1. Add the Overlay Mixer filter to the filter graph. The following code uses the AddFilterByCLSID function described in Add a Filter by CLSID. (AddFilter is not a DirectShow API.)
    IBaseFilter *pOvMix = NULL;  // Pointer to the Overlay Mixer filter.
    hr = AddFilterByCLSID(pGraph, CLSID_OverlayMixer, L"OVMix", &pOvMix);
    if (FAILED(hr)) 
    {
        // Handle the error ...
    }
    
  2. Connect the preview pin to the Video Renderer filter through the Overlay Mixer. You can use the RenderStream method, as follows:
    hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, 
        pCap, pOvMix, 0);
    
  3. Add the Tee/Sink-to-Sink Converter filter to the filter graph. The following code uses the CreateKernalFilter function described in Creating Kernel-Mode Filters. (CreateKernelFilter is not a DirectShow API.)
    IBaseFilter* pKernelTee = NULL;
    hr = CreateKernelFilter(AM_KSCATEGORY_SPLITTER, 
        OLESTR("Tee/Sink-to-Sink Converter"), &pKernelTee);
    if (SUCCEEDED(hr))
    {
        hr = pGraph->AddFilter(pKernelTee, L"Kernel Tee");
    }
    
  4. Add the WST Codec filter to the filter graph:
    IBaseFilter* pWstCodec = NULL;
    hr = CreateKernelFilter(AM_KSCATEGORY_VBICODEC, 
        OLESTR("WST Codec"), &pWstCodec);
    if (SUCCEEDED(hr))
    {
        hr = pGraph->AddFilter(pWstCodec, L"WST Codec");
    }
    
  5. Call RenderStream to connect the capture filter's VBI pin to the Tee/Sink-to-Sink Converter, and the Tee/Sink-to-Sink Converter to the WST Codec filter:
    hr = pBuild->RenderStream(&PIN_CATEGORY_VBI, 0, pCap, 
        pKernelTee, pWstCodec);
    
  6. Call RenderStream again to connect the WST Codec filter to the Overlay Mixer. The WST Decoder filter is automatically brought into the graph.
    hr = pBuild->RenderStream(0, 0, pWstCodec, 0, pOvMix);
    
  7. Remember to release all of the filter interfaces.
    pOvMix->Release();
    pKernelTee->Release();
    pWstCodec->Release();
    

Note   Currently, the WST Decoder filter does not support connections to the Video Mixing Renderer (VMR) filter. Therefore, you must use the legacy Video Renderer filter to view teletext.

If the capture filter has a video port VBI pin (PIN_CATEGPORY_VIDEOPORT_VBI), connect it to the VBI Surface Allocator filter. The graph will not run correctly otherwise. The following code example uses the AddFilterByCLSID function, described in Add a Filter by CLSID, and the FindPinByCategory function, described in Working with Pin Categories. (Neither function is a DirectShow API.)

// Look for a video port VBI pin on the capture filter.
IPin *pVPVBI = NULL;
hr = FindPinByCategory(pCap, PINDIR_OUTPUT, 
    PIN_CATEGORY_VIDEOPORT_VBI, &pVPVBI);
if (FAILED(hr))
{
    // No video port VBI pin; nothing else to do. OK to run the graph.
}
else
{
    // Found one. Connect it to the VBI Surface Allocator.
    IBaseFilter *pSurf = NULL;
    hr = AddFilterByCLSID(pGraph, CLSID_VBISurfaces, L"VBI Surf", &pSurf);
    if (SUCCEEDED(hr))
    {
        hr = pBuild->RenderStream(NULL, NULL, pVPVBI, 0, pSurf);
        pSurf->Release();
    }
    if (FAILED(hr))
    {
        // Handle the error (not shown). It is probably not safe to 
        // run the graph at this point.
    }
    pVPVBI->Release();
}