📄 bdagraph.cpp
字号:
return hr; } hr = p_tuning_space->CreateTuneRequest( &p_tune_request ); if( FAILED( hr ) ) { msg_Warn( p_access, "CreateTuneRequest: "\ "Cannot Create Tune Request: hr=0x%8lx", hr ); return hr; } return hr; } } hr = E_FAIL; if( FAILED( hr ) ) { msg_Warn( p_access, "CreateTuneRequest: "\ "Cannot find a suitable System Tuning Space: hr=0x%8lx", hr ); return hr; } return hr;}/******************************************************************************* Build* Step 4: Build the Filter Graph* Build sets up devices, adds and connects filters******************************************************************************/HRESULT BDAGraph::Build(){ HRESULT hr = S_OK; long l_capture_used, l_tif_used; AM_MEDIA_TYPE grabber_media_type; /* If we have already have a filter graph, rebuild it*/ Destroy(); hr = ::CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void**)&p_filter_graph ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot CoCreate IFilterGraph: hr=0x%8lx", hr ); return hr; } /* First filter in the graph is the Network Provider and * its Scanning Tuner which takes the Tune Request*/ hr = ::CoCreateInstance( guid_network_type, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&p_network_provider); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot CoCreate Network Provider: hr=0x%8lx", hr ); return hr; } hr = p_filter_graph->AddFilter( p_network_provider, L"Network Provider" ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot load network provider: hr=0x%8lx", hr ); return hr; } hr = p_network_provider->QueryInterface( IID_IScanningTuner, (void**)&p_scanning_tuner ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot QI Network Provider for Scanning Tuner: hr=0x%8lx", hr ); return hr; } hr = p_scanning_tuner->Validate( p_tune_request ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Tune Request is invalid: hr=0x%8lx", hr ); return hr; } hr = p_scanning_tuner->put_TuneRequest( p_tune_request ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot submit the tune request: hr=0x%8lx", hr ); return hr; } /* Add the Network Tuner to the Network Provider. On subsequent calls, * l_tuner_used will cause a different tuner to be selected */ hr = FindFilter( KSCATEGORY_BDA_NETWORK_TUNER, &l_tuner_used, p_network_provider, &p_tuner_device ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot load tuner device and connect network provider: "\ "hr=0x%8lx", hr ); return hr; } /* Always look for all capture devices to match the Network Tuner */ l_capture_used = -1; hr = FindFilter( KSCATEGORY_BDA_RECEIVER_COMPONENT, &l_capture_used, p_tuner_device, &p_capture_device ); if( FAILED( hr ) ) { /* Some BDA drivers do not provide a Capture Device Filter so force * the Sample Grabber to connect directly to the Tuner Device */ p_capture_device = p_tuner_device; p_tuner_device = NULL; msg_Warn( p_access, "Build: "\ "Cannot find Capture device. Connecting to tuner: hr=0x%8lx", hr ); } /* Insert the Sample Grabber to tap into the Transport Stream. */ hr = ::CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&p_sample_grabber ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot load Sample Grabber Filter: hr=0x%8lx", hr ); return hr; } hr = p_filter_graph->AddFilter( p_sample_grabber, L"Sample Grabber" ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot add Sample Grabber Filter to graph: hr=0x%8lx", hr ); return hr; } hr = p_sample_grabber->QueryInterface( IID_ISampleGrabber, (void**)&p_grabber ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot QI Sample Grabber Filter: hr=0x%8lx", hr ); return hr; } ZeroMemory( &grabber_media_type, sizeof( AM_MEDIA_TYPE ) ); grabber_media_type.majortype == MEDIATYPE_Stream; grabber_media_type.subtype == MEDIASUBTYPE_MPEG2_TRANSPORT; hr = p_grabber->SetMediaType( &grabber_media_type ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot set media type on grabber filter: hr=0x%8lx", hr ); return hr; } hr = Connect( p_capture_device, p_sample_grabber ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot connect Sample Grabber to Capture device: hr=0x%8lx", hr ); return hr; } /* We need the MPEG2 Demultiplexer even though we are going to use the VLC * TS demuxer. The TIF filter connects to the MPEG2 demux and works with * the Network Provider filter to set up the stream */ hr = ::CoCreateInstance( CLSID_MPEG2Demultiplexer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&p_mpeg_demux ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot CoCreateInstance MPEG2 Demultiplexer: hr=0x%8lx", hr ); return hr; } hr = p_filter_graph->AddFilter( p_mpeg_demux, L"Demux" ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot add demux filter to graph: hr=0x%8lx", hr ); return hr; } hr = Connect( p_sample_grabber, p_mpeg_demux ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot connect demux to grabber: hr=0x%8lx", hr ); return hr; } /* Always look for the Transform Information Filter from the start * of the collection*/ l_tif_used = -1; hr = FindFilter( KSCATEGORY_BDA_TRANSPORT_INFORMATION, &l_tif_used, p_mpeg_demux, &p_transport_info ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot load TIF onto demux: hr=0x%8lx", hr ); return hr; } /* Configure the Sample Grabber to buffer the samples continuously */ hr = p_grabber->SetBufferSamples( TRUE ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot set Sample Grabber to buffering: hr=0x%8lx", hr ); return hr; } hr = p_grabber->SetOneShot( FALSE ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot set Sample Grabber to multi shot: hr=0x%8lx", hr ); return hr; } hr = p_grabber->SetCallback( this, 0 ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot set SampleGrabber Callback: hr=0x%8lx", hr ); return hr; } hr = Register(); if( FAILED( hr ) ) { d_graph_register = 0; } /* The Media Control is used to Run and Stop the Graph */ hr = p_filter_graph->QueryInterface( IID_IMediaControl, (void**)&p_media_control ); if( FAILED( hr ) ) { msg_Warn( p_access, "Build: "\ "Cannot QI Media Control: hr=0x%8lx", hr ); return hr; } return hr;}/******************************************************************************* FindFilter* Looks up all filters in a category and connects to the upstream filter until* a successful match is found. The index of the connected filter is returned.* On subsequent calls, this can be used to start from that point to find* another match.* This is used when the graph does not run because a tuner device is in use so* another one needs to be slected.******************************************************************************/HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used, IBaseFilter* p_upstream, IBaseFilter** p_p_downstream ){ HRESULT hr = S_OK; int i_moniker_index = -1; class localComPtr { public: IMoniker* p_moniker; IEnumMoniker* p_moniker_enum; IBaseFilter* p_filter; IPropertyBag* p_property_bag; VARIANT var_bstr; localComPtr(): p_moniker(NULL), p_moniker_enum(NULL), p_filter(NULL), p_property_bag(NULL) { ::VariantInit(&var_bstr); }; ~localComPtr() { if( p_moniker ) p_moniker->Release(); if( p_moniker_enum ) p_moniker_enum->Release(); if( p_filter ) p_filter->Release(); if( p_property_bag ) p_property_bag->Release(); ::VariantClear(&var_bstr); } } l; if( !p_system_dev_enum ) { hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void**)&p_system_dev_enum ); if( FAILED( hr ) ) { msg_Warn( p_access, "FindFilter: "\ "Cannot CoCreate SystemDeviceEnum: hr=0x%8lx", hr ); return hr; } } hr = p_system_dev_enum->CreateClassEnumerator( clsid, &l.p_moniker_enum, 0 ); if( hr != S_OK ) { msg_Warn( p_access, "FindFilter: "\ "Cannot CreateClassEnumerator: hr=0x%8lx", hr ); return E_FAIL; } while( l.p_moniker_enum->Next( 1, &l.p_moniker, 0 ) == S_OK ) { i_moniker_index++; /* Skip over devices already found on previous calls */ if( i_moniker_index <= *i_moniker_used ) continue; *i_moniker_used = i_moniker_index; hr = l.p_moniker->BindToObject( NULL, NULL, IID_IBaseFilter, (void**)&l.p_filter ); if( FAILED( hr ) ) { if( l.p_moniker ) l.p_moniker->Release(); l.p_moniker = NULL; if( l.p_filter) l.p_filter->Release(); l.p_filter = NULL; continue; } hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag, (void**)&l.p_property_bag ); if( FAILED( hr ) ) { msg_Warn( p_access, "FindFilter: "\ "Cannot Bind to Property Bag: hr=0x%8lx", hr ); return hr; } hr = l.p_property_bag->Read( L"FriendlyName", &l.var_bstr, NULL ); if( FAILED( hr ) ) { msg_Warn( p_access, "FindFilter: "\ "Cannot read filter friendly name: hr=0x%8lx", hr ); return hr; } hr = p_filter_graph->AddFilter( l.p_filter, l.var_bstr.bstrVal ); if( FAILED( hr ) ) { msg_Warn( p_access, "FindFilter: "\ "Cannot add filter: hr=0x%8lx", hr ); return hr; } hr = Connect( p_upstream, l.p_filter ); if( SUCCEEDED( hr ) ) { msg_Dbg( p_access, "FindFilter: Connected %S", l.var_bstr.bstrVal ); l.p_filter->QueryInterface( IID_IBaseFilter, (void**)p_p_downstream ); return S_OK; } /* Not the filter we want so unload and try the next one */ hr = p_filter_graph->RemoveFilter( l.p_filter ); if( FAILED( hr ) ) { msg_Warn( p_access, "FindFilter: "\ "Failed unloading Filter: hr=0x%8lx", hr ); return hr; } if( l.p_moniker ) l.p_moniker->Release(); l.p_moniker = NULL; if( l.p_filter) l.p_filter->Release(); l.p_filter = NULL; } hr = E_FAIL; msg_Warn( p_access, "FindFilter: No filter connected: hr=0x%8lx", hr ); return hr;}/*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -