Search code examples
visual-c++directshowtv-tuner

What user inputs are required for a Digital TV Device Selection?


In the process of building a Digital TV graph, I need:

Network Provider -> Tuner -> Capture -> MPEG2-Demux -> MPEG2 TIF
                                                    -> MPEG2 Sections
                                                    -> Video Decoder -> VMR9
                                                    -> Audio Decoder -> DirectSound

It's obvious to me that I can hard-code in the name of the provider (Microsoft Network Provider), but do I need to prompt the user to select both a tuner and a capture device from the list of available devices, or can I somehow query for the tuner that corresponds to the capture device that the user has selected?

Basically I'm asking whether an API call exists similar to:

IMoniker *pTuner = GetTunerForCaptureDevice(pIMonikerSelectedCaptureDevice);

or whether it's standard to make the user choose both the tuner and the capture devices in their config.


Solution

  • The way that it seems that most applications deal with this problem is to go in the reverse direction. For the purposes of configuration, they provide list of all devices in the category KSCATEGORY_BDA_NETWORK_TUNER and allow the user to select one of the tuners.

    After that device has been added to the graph, all devices are enumerated for the category of KSCATEGORY_BDA_RECEIVER_COMPONENT. For each item returned, the capture device item is added to the graph, and connect is called between the tuner output pin and capture input pin. Rough code: (without the necessary Releases()'s)

    for (fFound=FALSE; !fFound; )
    {
         IMoniker *pIMoniker;
         IBaseFilter *ppIBaseFilter;
         hr = pIEnumMoniker->Next(1, &pIMoniker, NULL);
         if (hr!=S_OK)
               break;
    
         hr = pIMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), 
                      (void **)&ppIBaseFilter);
         hr = m_pIGraphBuilder->AddFilter(*ppIBaseFilter, L"Capture filter");
         hr = ConnectFilters(m_pIGraphBuilder, pITunerFilter, ppIBaseFilter)));
         if (hr != S_OK)
         {
              m_pIGraphBuilder->RemoveFilter(ppIBaseFilter);
              goto NextMoniker;
         }
    
         fFound = TRUE;
    NextMoniker:
       // release things here.
    }
    

    If any of the capture devices successfully connect pins, then the loop ends and that capture filter is used in the graph.

    I went this direction of starting with a user selection of a tuner because I was seeing several products that returned more than one tuner device, and when attempting connections in the reverse order (capture, then tuner), I seemed to always be successfully connecting the wrong tuner.