graph.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:34k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. //------------------------------------------------------------------------------
  2. // File: Graph.cpp
  3. //
  4. // Desc: Sample code for BDA graph building.
  5. //
  6. // Copyright (c) 2000-2002, Microsoft Corporation. All rights reserved.
  7. //------------------------------------------------------------------------------
  8. #include "graph.h"
  9. // 
  10. // NOTE: In this sample, text strings are hard-coded for 
  11. // simplicity and for readability.  For product code, you should
  12. // use string tables and LoadString().
  13. //
  14. //
  15. // An application can advertise the existence of its filter graph
  16. // by registering the graph with a global Running Object Table (ROT).
  17. // The GraphEdit application can detect and remotely view the running
  18. // filter graph, allowing you to 'spy' on the graph with GraphEdit.
  19. //
  20. // To enable registration in this sample, define REGISTER_FILTERGRAPH.
  21. //
  22. #define REGISTER_FILTERGRAPH
  23. // We use channel 46 internally for testing.  Change this constant to any value.
  24. #define DEFAULT_PHYSICAL_CHANNEL    46L
  25. // Constructor, initializes member variables
  26. // and calls InitializeGraphBuilder
  27. CBDAFilterGraph::CBDAFilterGraph() :
  28.     m_fGraphBuilt(FALSE),
  29.     m_fGraphRunning(FALSE),
  30.     m_NetworkType(ATSC),
  31.     m_lMajorChannel(-1), 
  32.     m_lMinorChannel(-1),
  33.     m_lPhysicalChannel(DEFAULT_PHYSICAL_CHANNEL),
  34.     m_dwGraphRegister (0)
  35. {
  36.     if(FAILED(InitializeGraphBuilder()))
  37.         m_fGraphFailure = TRUE;
  38.     else
  39.         m_fGraphFailure = FALSE;
  40. }
  41. // Destructor
  42. CBDAFilterGraph::~CBDAFilterGraph()
  43. {
  44.     if(m_fGraphRunning)
  45.     {
  46.         StopGraph();
  47.     }
  48.     if(m_fGraphBuilt || m_fGraphFailure)
  49.     {
  50.         TearDownGraph();
  51.     }
  52. }
  53. // Instantiate graph object for filter graph building
  54. HRESULT
  55. CBDAFilterGraph::InitializeGraphBuilder()
  56. {
  57.     HRESULT hr = S_OK;
  58.     
  59.     // we have a graph already
  60.     if (m_pFilterGraph)
  61.         return S_OK;
  62.     // create the filter graph
  63.     if (FAILED (hr = m_pFilterGraph.CoCreateInstance (CLSID_FilterGraph)))
  64.     {
  65.         ErrorMessageBox(TEXT("Couldn't CoCreate IGraphBuildern"));
  66.         m_fGraphFailure = true;
  67.         return hr;
  68.     }
  69.     
  70.     return hr;
  71. }
  72. // BuildGraph sets up devices, adds and connects filters
  73. HRESULT
  74. CBDAFilterGraph::BuildGraph(NETWORK_TYPE NetType)
  75. {
  76.     HRESULT hr = S_OK;
  77.     m_NetworkType = NetType;
  78.     // if we have already have a filter graph, tear it down
  79.     if(m_fGraphBuilt)
  80.     {
  81.         if(m_fGraphRunning)
  82.         {
  83.             hr = StopGraph ();
  84.         }
  85.         hr = TearDownGraph ();
  86.     }
  87.     // STEP 1: load network provider first so that it can configure other
  88.     // filters, such as configuring the demux to sprout output pins.
  89.     // We also need to submit a tune request to the Network Provider so it will
  90.     // tune to a channel
  91.     if(FAILED (hr = LoadNetworkProvider()))
  92.     {
  93.         ErrorMessageBox(TEXT("Cannot load network providern"));
  94.         TearDownGraph();
  95.         m_fGraphFailure = true;
  96.         return hr;
  97.     }
  98.     hr = m_pNetworkProvider->QueryInterface(__uuidof (ITuner), reinterpret_cast <void**> (&m_pITuner));
  99.     if(FAILED (hr))
  100.     {
  101.         ErrorMessageBox(TEXT("pNetworkProvider->QI: Can't QI for ITuner.n"));
  102.         TearDownGraph();
  103.         m_fGraphFailure = true;
  104.         return hr;
  105.     }
  106.     // create a tune request to initialize the network provider
  107.     // before connecting other filters
  108.     CComPtr <IATSCChannelTuneRequest>  pATSCTuneRequest;
  109.     if(FAILED (hr = CreateATSCTuneRequest(
  110.                                         m_lPhysicalChannel,
  111.                                         m_lMajorChannel, 
  112.                                         m_lMinorChannel,
  113.                                         &pATSCTuneRequest
  114.                                         )))
  115.     {
  116.         ErrorMessageBox(TEXT("Cannot create tune requestn"));
  117.         TearDownGraph();
  118.         m_fGraphFailure = true;
  119.         return hr;
  120.     }
  121.     //submit the tune request to the network provider
  122.     hr = m_pITuner->put_TuneRequest(pATSCTuneRequest);
  123.     if(FAILED(hr))
  124.     {
  125.         ErrorMessageBox(TEXT("Cannot submit the tune requestn"));
  126.         TearDownGraph();
  127.         m_fGraphFailure = true;
  128.         return hr;
  129.     }
  130.     // STEP2: Load tuner device and connect to network provider
  131.     if(FAILED (hr = LoadFilter (
  132.                                 KSCATEGORY_BDA_NETWORK_TUNER, 
  133.                                 &m_pTunerDevice,
  134.                                 m_pNetworkProvider, 
  135.                                 TRUE
  136.                                 )))
  137.     {
  138.         ErrorMessageBox(TEXT("Cannot load tuner device and connect network providern"));
  139.         TearDownGraph();
  140.         m_fGraphFailure = true;
  141.         return hr;
  142.     }
  143.     // STEP3: Load tuner device and connect to demodulator device
  144.     if(FAILED (hr = LoadFilter (
  145.                                 KSCATEGORY_BDA_RECEIVER_COMPONENT, 
  146.                                 &m_pDemodulatorDevice,
  147.                                 m_pTunerDevice, 
  148.                                 TRUE
  149.                                 )))
  150.     {
  151.         ErrorMessageBox(TEXT("Cannot load capture device and connect tunern"));
  152.         TearDownGraph();
  153.         m_fGraphFailure = true;
  154.         return hr;
  155.     }
  156.     // Step4: Load capture device and connect to tuner device
  157.     if(FAILED (hr = LoadFilter (
  158.                                 KSCATEGORY_BDA_RECEIVER_COMPONENT, 
  159.                                 &m_pCaptureDevice,
  160.                                 m_pDemodulatorDevice, 
  161.                                 TRUE
  162.                                 )))
  163.     {
  164.         ErrorMessageBox(TEXT("Cannot load capture device and connect tunern"));
  165.         TearDownGraph();
  166.         m_fGraphFailure = true;
  167.         return hr;
  168.     }
  169.     // Step5: Load demux
  170.     if(FAILED (hr = LoadDemux()))
  171.     {
  172.         ErrorMessageBox(TEXT("Cannot load demuxn"));
  173.         TearDownGraph();
  174.         m_fGraphFailure = true;
  175.         return hr;
  176.     }
  177.     //
  178.     // this next call loads and connects filters associated with
  179.     // the demultiplexor. if you want to manually load individual
  180.     // filters such as audio and video decoders, use the code at
  181.     // the bottom of this file
  182.     //
  183. #ifdef REGISTER_FILTERGRAPH
  184.     hr = AddGraphToRot (m_pFilterGraph, &m_dwGraphRegister);
  185.     if (FAILED(hr))
  186.     {
  187.         ///ErrorMessageBox(TEXT("Failed to register filter graph with ROT!  hr=0x%x"), hr);
  188.         m_dwGraphRegister = 0;
  189.     }
  190. #endif
  191.     // Step6: Render demux pins
  192.     if(FAILED (hr = RenderDemux()))
  193.     {
  194.         ErrorMessageBox(TEXT("Cannot load demuxn"));
  195.         TearDownGraph();
  196.         m_fGraphFailure = true;
  197.         return hr;
  198.     }
  199.     m_fGraphBuilt = true;
  200.     m_fGraphFailure = false;
  201.     
  202.     return S_OK;
  203. }
  204. // Loads the correct tuning space based on NETWORK_TYPE that got
  205. // passed into BuildGraph()
  206. HRESULT
  207. CBDAFilterGraph::LoadTuningSpace()
  208. {   
  209.     CComPtr <ITuningSpaceContainer>  pITuningSpaceContainer;
  210.     // get the tuningspace container for all the tuning spaces from SYSTEM_TUNING_SPACES
  211.     HRESULT hr = pITuningSpaceContainer.CoCreateInstance(CLSID_SystemTuningSpaces);
  212.     if (FAILED (hr))
  213.     {
  214.         ErrorMessageBox(TEXT("Could not CoCreate SystemTuningSpacesn"));
  215.         return hr;
  216.     }
  217.     CComVariant var (m_NetworkType);
  218.     hr = pITuningSpaceContainer->get_Item(var, &m_pITuningSpace);
  219.     if(FAILED(hr))
  220.     {
  221.         ErrorMessageBox(TEXT("Unable to retrieve Tuning Spacen"));
  222.     }
  223.     return hr;
  224. }
  225. // Creates an ATSC Tune Request
  226. HRESULT
  227. CBDAFilterGraph::CreateATSCTuneRequest(
  228.         LONG lPhysicalChannel,
  229.         LONG lMajorChannel, 
  230.         LONG lMinorChannel,
  231.         IATSCChannelTuneRequest**   pTuneRequest
  232.     )
  233. {
  234.     HRESULT hr = S_OK;
  235.     if (pTuneRequest == NULL)
  236.     {
  237.         ErrorMessageBox (TEXT("Invalid pointern"));
  238.         return E_POINTER;
  239.     }
  240.     // Making sure we have a valid tuning space
  241.     if (m_pITuningSpace == NULL)
  242.     {
  243.         ErrorMessageBox(TEXT("Tuning Space is NULLn"));
  244.         return E_FAIL;
  245.     }
  246.     //  Create an instance of the ATSC tuning space
  247.     CComQIPtr <IATSCTuningSpace> pATSCTuningSpace (m_pITuningSpace);
  248.     if (!pATSCTuningSpace)
  249.     {
  250.         ErrorMessageBox(TEXT("Cannot QI for an IATSCTuningSpacen"));
  251.         return E_FAIL;
  252.     }
  253.     //  Create an empty tune request.
  254.     CComPtr <ITuneRequest> pNewTuneRequest;
  255.     hr = pATSCTuningSpace->CreateTuneRequest(&pNewTuneRequest);
  256.     if (FAILED (hr))
  257.     {
  258.         ErrorMessageBox(TEXT("CreateTuneRequest: Can't create tune request.n"));
  259.         return hr;
  260.     }
  261.     //query for an IATSCChannelTuneRequest interface pointer
  262.     CComQIPtr <IATSCChannelTuneRequest> pATSCTuneRequest (pNewTuneRequest);
  263.     if (!pATSCTuneRequest)
  264.     {
  265.         ErrorMessageBox(TEXT("CreateATSCTuneRequest: Can't QI for IATSCChannelTuneRequest.n"));
  266.         return E_FAIL;
  267.     }
  268.     //  Set the initial major and minor channels
  269.     hr = pATSCTuneRequest->put_Channel(lMajorChannel);
  270.     if(FAILED(hr))
  271.     {
  272.         ErrorMessageBox(TEXT("put_Channel failedn"));
  273.         return hr;
  274.     }
  275.     hr = pATSCTuneRequest->put_MinorChannel(lMinorChannel);
  276.     if(FAILED(hr))
  277.     {
  278.         ErrorMessageBox(TEXT("put_MinorChannel failedn"));
  279.         return hr;
  280.     }
  281.     CComPtr <IATSCLocator> pATSCLocator;
  282.     hr = pATSCLocator.CoCreateInstance (CLSID_ATSCLocator);
  283.     if (FAILED( hr))
  284.     {
  285.         ErrorMessageBox(TEXT("Cannot create the ATSC locator failedn"));
  286.         return hr;
  287.     }
  288.     //  Set the initial physical channel.
  289.     //
  290.     hr = pATSCLocator->put_PhysicalChannel (lPhysicalChannel);
  291.     if (FAILED( hr))
  292.     {
  293.         ErrorMessageBox(TEXT("Cannot put the physical channeln"));
  294.         return hr;
  295.     }
  296.     hr = pATSCTuneRequest->put_Locator (pATSCLocator);
  297.     if (FAILED (hr))
  298.     {
  299.         ErrorMessageBox(TEXT("Cannot put the locatorn"));
  300.         return hr;
  301.     }
  302.     hr = pATSCTuneRequest.QueryInterface (pTuneRequest);
  303.     return hr;
  304. }
  305. // LoadNetworkProvider loads network provider
  306. HRESULT
  307. CBDAFilterGraph::LoadNetworkProvider()
  308. {
  309.     HRESULT     hr = S_OK;
  310.     CComBSTR    bstrNetworkType;
  311.     CLSID       CLSIDNetworkType;
  312.     // obtain tuning space then load network provider
  313.     if(m_pITuningSpace == NULL)
  314.     {
  315.         hr = LoadTuningSpace();
  316.         if(FAILED(hr))
  317.         {
  318.             ErrorMessageBox(TEXT("Cannot load TuningSpacen"));
  319.             return hr;
  320.         }
  321.     }
  322.     // Get the current Network Type clsid
  323.     hr = m_pITuningSpace->get_NetworkType(&bstrNetworkType);
  324.     if (FAILED (hr))
  325.     {
  326.         ErrorMessageBox(TEXT("ITuningSpace::Get Network Type failedn"));
  327.         return hr;
  328.     }
  329.     hr = CLSIDFromString(bstrNetworkType, &CLSIDNetworkType);
  330.     if (FAILED (hr))
  331.     {
  332.         ErrorMessageBox(TEXT("Couldn't get CLSIDFromStringn"));
  333.         return hr;
  334.     }
  335.     // create the network provider based on the clsid obtained from the tuning space
  336.     hr = CoCreateInstance(CLSIDNetworkType, NULL, CLSCTX_INPROC_SERVER,
  337.                           IID_IBaseFilter, 
  338.                           reinterpret_cast<void**>(&m_pNetworkProvider));
  339.     if (FAILED (hr))
  340.     {
  341.         ErrorMessageBox(TEXT("Couldn't CoCreate Network Providern"));
  342.         return hr;
  343.     }
  344.     //add the Network Provider filter to the graph
  345.     hr = m_pFilterGraph->AddFilter(m_pNetworkProvider, L"Network Provider");
  346.     return hr;
  347. }
  348. // enumerates through registered filters
  349. // instantiates the the filter object and adds it to the graph
  350. // it checks to see if it connects to upstream filter
  351. // if not,  on to the next enumerated filter
  352. // used for tuner, capture, MPE Data Filters and decoders that
  353. // could have more than one filter object
  354. // if pUpstreamFilter is NULL don't bother connecting
  355. HRESULT
  356. CBDAFilterGraph::LoadFilter(
  357.     REFCLSID clsid, 
  358.     IBaseFilter** ppFilter,
  359.     IBaseFilter* pConnectFilter, 
  360.     BOOL fIsUpstream
  361.     )
  362. {
  363.     HRESULT                 hr = S_OK;
  364.     BOOL                    fFoundFilter = FALSE;
  365.     CComPtr <IMoniker>      pIMoniker;
  366.     CComPtr <IEnumMoniker>  pIEnumMoniker;
  367.     if (!m_pICreateDevEnum)
  368.     {
  369.         hr = m_pICreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum);
  370.         if (FAILED (hr))
  371.         {
  372.             ErrorMessageBox(TEXT("LoadFilter(): Cannot CoCreate ICreateDevEnum"));
  373.             return hr;
  374.         }
  375.     }
  376.     // obtain the enumerator
  377.     hr = m_pICreateDevEnum->CreateClassEnumerator(clsid, &pIEnumMoniker, 0);
  378.     // the call can return S_FALSE if no moniker exists, so explicitly check S_OK
  379.     if (FAILED (hr))
  380.     {
  381.         ErrorMessageBox(TEXT("LoadFilter(): Cannot CreateClassEnumerator"));
  382.         return hr;
  383.     }
  384.     if (S_OK != hr)  // Class not found
  385.     {
  386.         ErrorMessageBox(TEXT("LoadFilter(): Class not found, CreateClassEnumerator returned S_FALSE"));
  387.         return E_UNEXPECTED;
  388.     }
  389.     // next filter
  390.     while(pIEnumMoniker->Next(1, &pIMoniker, 0) == S_OK)
  391.     {
  392.         // obtain filter's friendly name
  393.         CComPtr <IPropertyBag>  pBag;
  394.         hr = pIMoniker->BindToStorage(
  395.                                     NULL, 
  396.                                     NULL, 
  397.                                     IID_IPropertyBag,
  398.                                     reinterpret_cast<void**>(&pBag)
  399.                                     );
  400.         if(FAILED(hr))
  401.         {
  402.             OutputDebugString (TEXT("LoadFilter(): Cannot BindToStorage"));
  403.             return hr;
  404.         }
  405.         CComVariant varBSTR;
  406.         hr = pBag->Read(L"FriendlyName", &varBSTR, NULL);
  407.         if(FAILED(hr))
  408.         {
  409.             OutputDebugString (TEXT("LoadFilter(): IPropertyBag->Read method failed"));
  410.             pIMoniker = NULL;
  411.             continue;
  412.         }
  413.         // bind the filter
  414.         CComPtr <IBaseFilter>   pFilter;
  415.         hr = pIMoniker->BindToObject(
  416.                                     NULL, 
  417.                                     NULL, 
  418.                                     IID_IBaseFilter,
  419.                                     reinterpret_cast<void**>(&pFilter)
  420.                                     );
  421.         if (FAILED(hr))
  422.         {
  423.             pIMoniker = NULL;
  424.             pFilter = NULL;
  425.             continue;
  426.         }
  427.         hr = m_pFilterGraph->AddFilter (pFilter, varBSTR.bstrVal);
  428.         if (FAILED(hr))
  429.         {
  430.             OutputDebugString (TEXT("Cannot add filtern"));
  431.             return hr;
  432.         }
  433.         //MessageBox (NULL, _T(""), _T(""), MB_OK);
  434.         // test connections
  435.         // to upstream filter
  436.         if (pConnectFilter)
  437.         {
  438.             if(fIsUpstream)
  439.             {
  440.                 hr = ConnectFilters (pConnectFilter, pFilter);
  441.             }
  442.             else
  443.             {
  444.                 hr = ConnectFilters (pFilter, pConnectFilter);
  445.             }
  446.             if(SUCCEEDED(hr))
  447.             {
  448.                 //that's the filter we want
  449.                 fFoundFilter = TRUE;
  450.                 pFilter.QueryInterface (ppFilter);
  451.                 break;
  452.             }
  453.             else
  454.             {
  455.                 fFoundFilter = FALSE;
  456.                 // that wasn't the the filter we wanted
  457.                 // so unload and try the next one
  458.                 hr = m_pFilterGraph->RemoveFilter(pFilter);
  459.                 if(FAILED(hr))
  460.                 {
  461.                     OutputDebugString(TEXT("Failed unloading Filtern"));
  462.                     return hr;
  463.                 }
  464.             }
  465.         }
  466.         else
  467.         {
  468.             fFoundFilter = TRUE;
  469.             pFilter.QueryInterface (ppFilter);
  470.             break;
  471.         }
  472.         pIMoniker = NULL;
  473.         pFilter = NULL;
  474.     } // while
  475.     return S_OK;
  476. }
  477. // loads the demux into the FilterGraph
  478. HRESULT
  479. CBDAFilterGraph::LoadDemux()
  480. {
  481.     HRESULT hr = S_OK;
  482.     
  483.     hr = CoCreateInstance(
  484.                         CLSID_MPEG2Demultiplexer, 
  485.                         NULL, 
  486.                         CLSCTX_INPROC_SERVER,
  487.                         IID_IBaseFilter, 
  488.                         reinterpret_cast<void**>(&m_pDemux)
  489.                         );
  490.     if (FAILED (hr))
  491.     {
  492.         ErrorMessageBox(TEXT("Could not CoCreateInstance CLSID_MPEG2Demultiplexern"));
  493.         return hr;
  494.     }
  495.     hr = m_pFilterGraph->AddFilter(m_pDemux, L"Demux");
  496.     if(FAILED(hr))
  497.     {
  498.         ErrorMessageBox(TEXT("Unable to add demux filter to graphn"));
  499.         return hr;
  500.     }
  501.     return hr;
  502. }
  503. // renders demux output pins
  504. HRESULT
  505. CBDAFilterGraph::RenderDemux()
  506. {
  507.     HRESULT             hr = S_OK;
  508.     CComPtr <IPin>      pIPin;
  509.     CComPtr <IPin>      pDownstreamPin;
  510.     CComPtr <IEnumPins> pIEnumPins;
  511.     PIN_DIRECTION       direction;
  512.     if (!m_pDemux)
  513.     {
  514.         return E_FAIL;
  515.     }
  516.     // connect the demux to the capture device
  517.     hr = ConnectFilters (m_pCaptureDevice, m_pDemux);
  518.     if (FAILED (hr))
  519.     {
  520.         ErrorMessageBox(TEXT("Cannot connect demux to capture filtern"));
  521.         return hr;
  522.     }
  523.     // load transform information filter and connect it to the demux
  524.     hr = LoadFilter (
  525.                     KSCATEGORY_BDA_TRANSPORT_INFORMATION, 
  526.                     &m_pTIF, 
  527.                     m_pDemux, 
  528.                     TRUE
  529.                     );
  530.     if (FAILED (hr))
  531.     {
  532.         ErrorMessageBox(TEXT("Cannot load TIFn"));
  533.         return hr;
  534.     }
  535.     // load multi protocol encapsulator
  536.     hr = LoadFilter (
  537.                     KSCATEGORY_BDA_RECEIVER_COMPONENT, 
  538.                     &m_pMPE, 
  539.                     m_pDemux, 
  540.                     TRUE
  541.                     );
  542.     if (FAILED (hr))
  543.     {
  544.         ErrorMessageBox(TEXT("Cannot load MPEn"));
  545.         return hr;
  546.     }
  547.     // load IP Sink
  548.     hr = LoadFilter (
  549.                     KSCATEGORY_IP_SINK, 
  550.                     &m_pIPSink, 
  551.                     m_pMPE, 
  552.                     TRUE
  553.                     );
  554.     if (FAILED (hr))
  555.     {
  556.         ErrorMessageBox(TEXT("Cannot load IP Sinkn"));
  557.         return hr;
  558.     }
  559.     // render/connect the rest of the demux pins
  560.     hr = m_pDemux->EnumPins (&pIEnumPins);
  561.     if (FAILED (hr))
  562.     {
  563.         ErrorMessageBox(TEXT("Cannot get the enumpinsn"));
  564.         return hr;
  565.     }
  566.     while(pIEnumPins->Next(1, &pIPin, 0) == S_OK)
  567.     {
  568.         hr = pIPin->QueryDirection(&direction);
  569.         if(direction == PINDIR_OUTPUT)
  570.         {
  571.             pIPin->ConnectedTo (&pDownstreamPin);
  572.             if(pDownstreamPin == NULL)
  573.             {
  574.                 m_pFilterGraph->Render (pIPin);
  575.             }
  576.             pDownstreamPin = NULL;
  577.         }
  578.         pIPin = NULL;
  579.     }
  580.     return hr;
  581. }
  582. // removes each filter from the graph
  583. HRESULT
  584. CBDAFilterGraph::TearDownGraph()
  585. {
  586.     HRESULT hr = S_OK;
  587.     CComPtr <IBaseFilter> pFilter;
  588.     CComPtr <IEnumFilters> pIFilterEnum;
  589.     m_pITuningSpace = NULL;
  590.     if(m_fGraphBuilt || m_fGraphFailure)
  591.     {
  592.         // unload manually added filters
  593.         m_pFilterGraph->RemoveFilter(m_pIPSink);
  594.         m_pFilterGraph->RemoveFilter(m_pMPE);
  595.         m_pFilterGraph->RemoveFilter(m_pTIF);
  596.         m_pFilterGraph->RemoveFilter(m_pDemux);
  597.         m_pFilterGraph->RemoveFilter(m_pNetworkProvider);
  598.         m_pFilterGraph->RemoveFilter(m_pTunerDevice);
  599.         m_pFilterGraph->RemoveFilter(m_pCaptureDevice);
  600.         m_pIPSink = NULL;
  601.         m_pMPE = NULL;
  602.         m_pTIF = NULL;
  603.         m_pDemux = NULL;
  604.         m_pNetworkProvider = NULL;
  605.         m_pTunerDevice = NULL;
  606.         m_pDemodulatorDevice = NULL;
  607.         m_pCaptureDevice = NULL;
  608.         // now go unload rendered filters
  609.         hr = m_pFilterGraph->EnumFilters(&pIFilterEnum);
  610.         if(FAILED(hr))
  611.         {
  612.             ErrorMessageBox(TEXT("TearDownGraph: cannot EnumFiltersn"));
  613.             return E_FAIL;
  614.         }
  615.         pIFilterEnum->Reset();
  616.         while(pIFilterEnum->Next(1, &pFilter, 0) == S_OK) // addrefs filter
  617.         {
  618.             hr = m_pFilterGraph->RemoveFilter(pFilter);
  619.             if (FAILED (hr))
  620.                 return hr;
  621.             pIFilterEnum->Reset();
  622.             pFilter.Release ();
  623.         }
  624.     }
  625. #ifdef REGISTER_FILTERGRAPH
  626.     if (m_dwGraphRegister)
  627.     {
  628.         RemoveGraphFromRot(m_dwGraphRegister);
  629.         m_dwGraphRegister = 0;
  630.     }
  631. #endif
  632.     m_fGraphBuilt = FALSE;
  633.     return S_OK;
  634. }
  635. // ConnectFilters is called from BuildGraph
  636. // to enumerate and connect pins
  637. HRESULT
  638. CBDAFilterGraph::ConnectFilters(
  639.     IBaseFilter* pFilterUpstream, 
  640.     IBaseFilter* pFilterDownstream
  641.     )
  642. {
  643.     HRESULT         hr = E_FAIL;
  644.     CComPtr <IPin>  pIPinUpstream;
  645.     PIN_INFO        PinInfoUpstream;
  646.     PIN_INFO        PinInfoDownstream;
  647.     // validate passed in filters
  648.     ASSERT (pFilterUpstream);
  649.     ASSERT (pFilterDownstream);
  650.     // grab upstream filter's enumerator
  651.     CComPtr <IEnumPins> pIEnumPinsUpstream;
  652.     hr = pFilterUpstream->EnumPins(&pIEnumPinsUpstream);
  653.     if(FAILED(hr))
  654.     {
  655.         ErrorMessageBox(TEXT("Cannot Enumerate Upstream Filter's Pinsn"));
  656.         return hr;
  657.     }
  658.     // iterate through upstream filter's pins
  659.     while (pIEnumPinsUpstream->Next (1, &pIPinUpstream, 0) == S_OK)
  660.     {
  661.         hr = pIPinUpstream->QueryPinInfo (&PinInfoUpstream);
  662.         if(FAILED(hr))
  663.         {
  664.             ErrorMessageBox(TEXT("Cannot Obtain Upstream Filter's PIN_INFOn"));
  665.             return hr;
  666.         }
  667.         CComPtr <IPin>  pPinDown;
  668.         pIPinUpstream->ConnectedTo (&pPinDown);
  669.         // bail if pins are connected
  670.         // otherwise check direction and connect
  671.         if ((PINDIR_OUTPUT == PinInfoUpstream.dir) && (pPinDown == NULL))
  672.         {
  673.             // grab downstream filter's enumerator
  674.             CComPtr <IEnumPins> pIEnumPinsDownstream;
  675.             hr = pFilterDownstream->EnumPins (&pIEnumPinsDownstream);
  676.             if(FAILED(hr))
  677.             {
  678.                 ErrorMessageBox(TEXT("Cannot enumerate pins on downstream filter!n"));
  679.                 return hr;
  680.             }
  681.             // iterate through downstream filter's pins
  682.             CComPtr <IPin>  pIPinDownstream;
  683.             while (pIEnumPinsDownstream->Next (1, &pIPinDownstream, 0) == S_OK)
  684.             {
  685.                 // make sure it is an input pin
  686.                 hr = pIPinDownstream->QueryPinInfo(&PinInfoDownstream);
  687.                 if(SUCCEEDED(hr))
  688.                 {
  689.                     CComPtr <IPin>  pPinUp;
  690.                     // Determine if the pin is already connected.  Note that 
  691.                     // VFW_E_NOT_CONNECTED is expected if the pin isn't yet connected.
  692.                     hr = pIPinDownstream->ConnectedTo (&pPinUp);
  693.                     if(FAILED(hr) && hr != VFW_E_NOT_CONNECTED)
  694.                     {
  695.                         ErrorMessageBox(TEXT("Failed in pIPinDownstream->ConnectedTo()!n"));
  696.                         continue;
  697.                     }
  698.                     if ((PINDIR_INPUT == PinInfoDownstream.dir) && (pPinUp == NULL))
  699.                     {
  700.                         if (SUCCEEDED (m_pFilterGraph->Connect(
  701.                                         pIPinUpstream,
  702.                                         pIPinDownstream))
  703.                                         )
  704.                         {
  705.                             PinInfoDownstream.pFilter->Release();
  706.                             PinInfoUpstream.pFilter->Release();
  707.                             return S_OK;
  708.                         }
  709.                     }
  710.                 }
  711.                 PinInfoDownstream.pFilter->Release();
  712.                 pIPinDownstream = NULL;
  713.             } // while next downstream filter pin
  714.             //We are now back into the upstream pin loop
  715.         } // if output pin
  716.         pIPinUpstream = NULL;
  717.         PinInfoUpstream.pFilter->Release();
  718.     } // while next upstream filter pin
  719.     return E_FAIL;
  720. }
  721. // RunGraph checks to see if a graph has been built
  722. // if not it calls BuildGraph
  723. // RunGraph then calls MediaCtrl-Run
  724. HRESULT
  725. CBDAFilterGraph::RunGraph()
  726. {
  727.     // check to see if the graph is already running
  728.     if(m_fGraphRunning)
  729.         return S_OK;
  730.     HRESULT hr = S_OK;
  731.     if (m_pIMediaControl == NULL)
  732.         hr = m_pFilterGraph.QueryInterface (&m_pIMediaControl);
  733.     if (SUCCEEDED (hr))
  734.     {
  735.         // run the graph
  736.         hr = m_pIMediaControl->Run();
  737.         if(SUCCEEDED(hr))
  738.         {
  739.             m_fGraphRunning = true;
  740.         }
  741.         else
  742.         {
  743.             // stop parts of the graph that ran
  744.             m_pIMediaControl->Stop();
  745.             ErrorMessageBox(TEXT("Cannot run graphn"));
  746.         }
  747.     }
  748.     return hr;
  749. }
  750. // StopGraph calls MediaCtrl - Stop
  751. HRESULT
  752. CBDAFilterGraph::StopGraph()
  753. {
  754.     // check to see if the graph is already stopped
  755.     if(m_fGraphRunning == false)
  756.         return S_OK;
  757.     HRESULT hr = S_OK;
  758.     ASSERT (m_pIMediaControl);
  759.     // pause before stopping
  760.     hr = m_pIMediaControl->Pause();
  761.     // stop the graph
  762.     hr = m_pIMediaControl->Stop();
  763.     m_fGraphRunning = (FAILED (hr))?true:false;
  764.     return hr;
  765. }
  766. // Set our client area for viewing
  767. //
  768. // Note, what you're not seeing here is a call to
  769. // IAMSreamCconfig's GetFormat to obtain the video
  770. // format properties that would enable us to set
  771. // the viewing window's size
  772. HRESULT
  773. CBDAFilterGraph::SetVideoWindow(
  774.         HWND hwndMain
  775.         )
  776. {
  777.     CComPtr <IVideoWindow>  pVideoWindow;
  778.     RECT                    rc;
  779.     INT                     cyBorder;
  780.     INT                     cy;
  781.     HRESULT                 hr = S_OK;
  782.     // get IVideoWindow interface
  783.     hr = m_pFilterGraph->QueryInterface (&pVideoWindow);
  784.     if (FAILED (hr))
  785.     {
  786.         ErrorMessageBox(TEXT("QueryInterface IVideoWindow Failedn"));
  787.         return hr;
  788.     }
  789.     hr = pVideoWindow->put_Owner (reinterpret_cast <LONG> (hwndMain));
  790.     if (FAILED (hr))
  791.     {
  792.         ErrorMessageBox(TEXT("Unable to set video windown"));
  793.         return hr;
  794.     }
  795.     hr = pVideoWindow->put_WindowStyle (WS_CHILD);
  796.     if (FAILED (hr))
  797.     {
  798.         ErrorMessageBox(TEXT("Unable to set the style for the video windown"));
  799.         return hr;
  800.     }
  801.     GetClientRect(hwndMain, &rc);
  802.     cyBorder = GetSystemMetrics(SM_CYBORDER);
  803.     cy = cyBorder;
  804.     rc.bottom -= cy;
  805.     hr = pVideoWindow->SetWindowPosition(0, 0, rc.right, rc.bottom);
  806.     hr = pVideoWindow->put_Visible (OATRUE);
  807.     return hr;
  808. }
  809. HRESULT
  810. CBDAFilterGraph::ChangeChannel(
  811.         LONG lPhysicalChannel,
  812.         LONG lMajorChannel, 
  813.         LONG lMinorChannel
  814.         )
  815. {
  816.     HRESULT hr = S_OK;
  817.     m_lMajorChannel = lMajorChannel;
  818.     m_lMinorChannel = lMinorChannel;
  819.     m_lPhysicalChannel = lPhysicalChannel;
  820.     if (!m_pNetworkProvider)
  821.     {
  822.         ErrorMessageBox(TEXT("The FilterGraph is not yet built.n"));
  823.         return E_FAIL;
  824.     }
  825.     // create tune request
  826.     CComPtr <IATSCChannelTuneRequest> pTuneRequest;
  827.     hr = CreateATSCTuneRequest(
  828.                             m_lPhysicalChannel, 
  829.                             lMajorChannel, 
  830.                             lMinorChannel,
  831.                             &pTuneRequest
  832.                             );
  833.     if(SUCCEEDED(hr))
  834.     {
  835.         hr = m_pITuner->put_TuneRequest (pTuneRequest);
  836.         if (FAILED (hr))
  837.             ErrorMessageBox(TEXT("Cannot submit tune requestn"));
  838.     }
  839.     else
  840.     {
  841.         ErrorMessageBox(TEXT("Cannot Change Channelsn"));
  842.     }
  843.     return hr;
  844. }
  845. #ifdef REGISTER_FILTERGRAPH
  846. // Adds a DirectShow filter graph to the Running Object Table,
  847. // allowing GraphEdit to "spy" on a remote filter graph.
  848. HRESULT CBDAFilterGraph::AddGraphToRot(
  849.         IUnknown *pUnkGraph, 
  850.         DWORD *pdwRegister
  851.         ) 
  852. {
  853.     CComPtr <IMoniker>              pMoniker;
  854.     CComPtr <IRunningObjectTable>   pROT;
  855.     WCHAR wsz[128];
  856.     HRESULT hr;
  857.     if (FAILED(GetRunningObjectTable(0, &pROT)))
  858.         return E_FAIL;
  859.     wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR) pUnkGraph, 
  860.               GetCurrentProcessId());
  861.     hr = CreateItemMoniker(L"!", wsz, &pMoniker);
  862.     if (SUCCEEDED(hr)) 
  863.         hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, 
  864.                             pMoniker, pdwRegister);
  865.         
  866.     return hr;
  867. }
  868. // Removes a filter graph from the Running Object Table
  869. void CBDAFilterGraph::RemoveGraphFromRot(
  870.         DWORD pdwRegister
  871.         )
  872. {
  873.     CComPtr <IRunningObjectTable> pROT;
  874.     if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) 
  875.         pROT->Revoke(pdwRegister);
  876. }
  877. #endif
  878. //
  879. // USE THE CODE BELOW IF YOU WANT TO MANUALLY LOAD AND
  880. // CONNECT A/V DECODERS TO THE DEMUX OUTPUT PINS
  881. //
  882. /*
  883. To use this code:
  884. 1) in LoadAudioDecoder() and LoadVideoDecoder(), fill in decoder specific information (clsid)
  885. 2) goto BuildGraph() and replace RenderDemux() with BuildAVSegment()
  886. */
  887. /*
  888. // Builds the Audio, Video segment of the digital TV graph.
  889. // Demux -> AV Decoder -> OVMixer -> Video Renderer
  890. HRESULT
  891. CBDAFilterGraph::BuildAVSegment()
  892. {
  893.     HRESULT hr = E_FAIL;
  894.     // connect the demux to the capture device
  895.     hr = ConnectFilters(m_pCaptureDevice, m_pDemux);
  896.     hr = LoadVideoDecoder();
  897.     if(SUCCEEDED(hr) && m_pVideoDecoder)
  898.     {
  899.         // Connect the demux & video decoder
  900.         hr = ConnectFilters(m_pDemux, m_pVideoDecoder);
  901.         if(FAILED(hr))
  902.         {
  903.             ErrorMessageBox("Connecting Demux & Video Decoder Failedn");
  904.             goto err;
  905.         }
  906.     }
  907.     else
  908.     {
  909.         //ErrorMessageBox("Unable to load Video Decodern");
  910.         goto err;
  911.     }
  912.     //Audio
  913.     hr = LoadAudioDecoder();
  914.     if(SUCCEEDED(hr) && m_pAudioDecoder)
  915.     {
  916.         hr = ConnectFilters(m_pDemux, m_pAudioDecoder);
  917.         if(FAILED(hr))
  918.         {
  919.             ErrorMessageBox("Connecting Deumx & Audio Decoder Failedn");
  920.             goto err;
  921.         }
  922.     }
  923.     else
  924.     {
  925.         ErrorMessageBox("Unable to load Audio Decodern");
  926.         goto err;
  927.     }
  928.     // Create the OVMixer & Video Renderer for the video segment
  929.     hr = CoCreateInstance(CLSID_OverlayMixer, NULL, CLSCTX_INPROC_SERVER,
  930.             IID_IBaseFilter, reinterpret_cast<void**>(&m_pOVMixer));
  931.     if(SUCCEEDED(hr) && m_pOVMixer)
  932.     {
  933.         hr = m_pFilterGraph->AddFilter(m_pOVMixer, L"OVMixer");
  934.         if(FAILED(hr))
  935.         {
  936.             ErrorMessageBox("Adding OVMixer to the FilterGraph Failedn");
  937.             goto err;
  938.         }
  939.     }
  940.     else
  941.     {
  942.         ErrorMessageBox("Loading OVMixer Failedn");
  943.         goto err;
  944.     }
  945.     hr = CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER,
  946.             IID_IBaseFilter, reinterpret_cast<void**>(&m_pVRenderer));
  947.     if(SUCCEEDED(hr) && m_pVRenderer)
  948.     {
  949.         hr = m_pFilterGraph->AddFilter(m_pVRenderer, L"Video Renderer");
  950.         if(FAILED(hr))
  951.         {
  952.             ErrorMessageBox("Adding Video Renderer to the FilterGraph Failedn");
  953.             goto err;
  954.         }
  955.     }
  956.     else
  957.     {
  958.         ErrorMessageBox("Loading Video Renderer Failedn");
  959.         goto err;
  960.     }
  961.     // Split AV Decoder? Then add Default DirectSound Renderer to the filtergraph
  962.     if(m_pVideoDecoder != m_pAudioDecoder)
  963.     {
  964.         hr = CoCreateInstance(CLSID_DSoundRender, NULL,
  965.                         CLSCTX_INPROC_SERVER, IID_IBaseFilter,
  966.                         reinterpret_cast<void**>(&m_pDDSRenderer));
  967.         if(SUCCEEDED(hr) && m_pDDSRenderer)
  968.         {
  969.             hr = m_pFilterGraph->AddFilter(m_pDDSRenderer, L"Sound Renderer");
  970.             if(FAILED(hr))
  971.             {
  972.                 ErrorMessageBox("Adding DirectSound Device to the FilterGraph Failedn");
  973.                 goto err;
  974.             }
  975.         }
  976.         else
  977.         {
  978.             ErrorMessageBox("Loading DirectSound Device Failedn");
  979.             goto err;
  980.         }
  981.     }
  982.     hr = ConnectFilters(m_pVideoDecoder, m_pOVMixer);
  983.     if(FAILED(hr))
  984.     {
  985.         ErrorMessageBox("Connecting Capture & OVMixer Failedn");
  986.         goto err;
  987.     }
  988.     hr = ConnectFilters(m_pOVMixer, m_pVRenderer);
  989.     if(FAILED(hr))
  990.     {
  991.         ErrorMessageBox("Connecting OVMixer & Video Renderer Failedn");
  992.         goto err;
  993.     }
  994.     // Split AV Decoder & if you need audio too ?? then connect Audio decoder to Sound Renderer
  995.     if(m_pVideoDecoder != m_pAudioDecoder)
  996.     {
  997.         hr = ConnectFilters(m_pAudioDecoder, m_pDDSRenderer);
  998.         if(FAILED(hr))
  999.         {
  1000.             ErrorMessageBox("Connecting AudioDecoder & DirectSound Device Failedn");
  1001.             goto err;
  1002.         }
  1003.     }
  1004. err:
  1005.     return hr;
  1006. }
  1007. // placeholders for real decoders
  1008. DEFINE_GUID(CLSID_FILL_IN_NAME_AUDIO_DECODER, 0xFEEDFEED, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1009. 0x00);
  1010. DEFINE_GUID(CLSID_FILL_IN_NAME_VIDEO_DECODER, 0xFEEDFEED, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1011. 0x00);
  1012. HRESULT
  1013. CBDAFilterGraph::LoadVideoDecoder()
  1014. {
  1015.     HRESULT hr = E_FAIL;
  1016.     hr = CoCreateInstance(CLSID_FILL_IN_NAME_VIDEO_DECODER, NULL,
  1017.             CLSCTX_INPROC_SERVER, IID_IBaseFilter,
  1018.             reinterpret_cast<void**>(&m_pVideoDecoder));
  1019.     if(SUCCEEDED(hr) && m_pVideoDecoder)
  1020.     {
  1021.         hr = m_pFilterGraph->AddFilter(m_pVideoDecoder, L"Video Decoder");
  1022.         if(FAILED(hr))
  1023.         {
  1024.             ErrorMessageBox("Unable to add Video Decoder filter to graphn");
  1025.         }
  1026.     }
  1027.     return hr;
  1028. }
  1029. HRESULT
  1030. CBDAFilterGraph::LoadAudioDecoder()
  1031. {
  1032.     HRESULT hr = E_FAIL;
  1033.     hr = CoCreateInstance(CLSID_FILL_IN_NAME_AUDIO_DECODER, NULL,
  1034.             CLSCTX_INPROC_SERVER, IID_IBaseFilter,
  1035.             reinterpret_cast<void**>(&m_pAudioDecoder));
  1036.     if(SUCCEEDED(hr) && m_pAudioDecoder)
  1037.     {
  1038.         hr = m_pFilterGraph->AddFilter(m_pAudioDecoder, L"Audio Decoder");
  1039.         if(FAILED(hr))
  1040.         {
  1041.             ErrorMessageBox("Unable to add Audio filter to graphn");
  1042.         }
  1043.     }
  1044.     return hr;
  1045. }
  1046. */