1 /*****************************************************************************
2 * bdagraph.cpp : DirectShow BDA graph for vlc
3 *****************************************************************************
4 * Copyright( C ) 2007 the VideoLAN team
6 * Author: Ken Self <kens@campoz.fslife.co.uk>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 *( at your option ) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
29 /****************************************************************************
30 * Interfaces for calls from C
31 ****************************************************************************/
34 void dvb_newBDAGraph( access_t* p_access )
36 p_access->p_sys->p_bda_module = new BDAGraph( p_access );
39 void dvb_deleteBDAGraph( access_t* p_access )
41 delete p_access->p_sys->p_bda_module;
44 int dvb_SubmitATSCTuneRequest( access_t* p_access )
46 if( p_access->p_sys->p_bda_module )
47 return p_access->p_sys->p_bda_module->SubmitATSCTuneRequest();
51 int dvb_SubmitDVBTTuneRequest( access_t* p_access )
53 if( p_access->p_sys->p_bda_module )
54 return p_access->p_sys->p_bda_module->SubmitDVBTTuneRequest();
58 int dvb_SubmitDVBCTuneRequest( access_t* p_access )
60 if( p_access->p_sys->p_bda_module )
61 return p_access->p_sys->p_bda_module->SubmitDVBCTuneRequest();
65 int dvb_SubmitDVBSTuneRequest( access_t* p_access )
67 if( p_access->p_sys->p_bda_module )
68 return p_access->p_sys->p_bda_module->SubmitDVBSTuneRequest();
72 long dvb_GetBufferSize( access_t* p_access )
74 if( p_access->p_sys->p_bda_module )
75 return p_access->p_sys->p_bda_module->GetBufferSize();
79 long dvb_ReadBuffer( access_t* p_access, long* l_buffer_len, BYTE* p_buff )
81 if( p_access->p_sys->p_bda_module )
82 return p_access->p_sys->p_bda_module->ReadBuffer( l_buffer_len,
88 /*****************************************************************************
90 *****************************************************************************/
91 BDAGraph::BDAGraph( access_t* p_this ):
93 guid_network_type(GUID_NULL),
98 p_tuning_space = NULL;
99 p_tune_request = NULL;
100 p_media_control = NULL;
101 p_filter_graph = NULL;
102 p_system_dev_enum = NULL;
103 p_network_provider = p_tuner_device = p_capture_device = NULL;
104 p_sample_grabber = p_mpeg_demux = p_transport_info = NULL;
105 p_scanning_tuner = NULL;
108 /* Initialize COM - MS says to use CoInitializeEx in preference to
110 CoInitializeEx( 0, COINIT_APARTMENTTHREADED );
113 /*****************************************************************************
115 *****************************************************************************/
116 BDAGraph::~BDAGraph()
122 /*****************************************************************************
123 * Submit an ATSC Tune Request
124 *****************************************************************************/
125 int BDAGraph::SubmitATSCTuneRequest()
131 IATSCChannelTuneRequest* p_atsc_tune_request;
132 IATSCLocator* p_atsc_locator;
133 localComPtr(): p_atsc_tune_request(NULL), p_atsc_locator(NULL) {};
136 if( p_atsc_tune_request )
137 p_atsc_tune_request->Release();
139 p_atsc_locator->Release();
142 long l_major_channel, l_minor_channel, l_physical_channel;
145 l_major_channel = var_GetInteger( p_access, "dvb-major-channel" );
146 l_minor_channel = var_GetInteger( p_access, "dvb-minor-channel" );
147 l_physical_channel = var_GetInteger( p_access, "dvb-physical-channel" );
148 l_frequency = var_GetInteger( p_access, "dvb-frequency" );
150 guid_network_type = CLSID_ATSCNetworkProvider;
151 hr = CreateTuneRequest();
154 msg_Warn( p_access, "SubmitATSCTuneRequest: "\
155 "Cannot create Tuning Space: hr=0x%8lx", hr );
159 hr = p_tune_request->QueryInterface( IID_IATSCChannelTuneRequest,
160 (void**)&l.p_atsc_tune_request );
163 msg_Warn( p_access, "SubmitATSCTuneRequest: "\
164 "Cannot QI for IATSCChannelTuneRequest: hr=0x%8lx", hr );
167 hr = ::CoCreateInstance( CLSID_ATSCLocator, 0, CLSCTX_INPROC,
168 IID_IATSCLocator, (void**)&l.p_atsc_locator );
171 msg_Warn( p_access, "SubmitATSCTuneRequest: "\
172 "Cannot create the ATSC locator: hr=0x%8lx", hr );
177 if( l_frequency > 0 )
178 hr = l.p_atsc_locator->put_CarrierFrequency( l_frequency );
179 if( l_major_channel > 0 )
180 hr = l.p_atsc_tune_request->put_Channel( l_major_channel );
181 if( SUCCEEDED( hr ) && l_minor_channel > 0 )
182 hr = l.p_atsc_tune_request->put_MinorChannel( l_minor_channel );
183 if( SUCCEEDED( hr ) && l_physical_channel > 0 )
184 hr = l.p_atsc_locator->put_PhysicalChannel( l_physical_channel );
187 msg_Warn( p_access, "SubmitATSCTuneRequest: "\
188 "Cannot set tuning parameters: hr=0x%8lx", hr );
192 hr = p_tune_request->put_Locator( l.p_atsc_locator );
195 msg_Warn( p_access, "SubmitATSCTuneRequest: "\
196 "Cannot put the locator: hr=0x%8lx", hr );
200 /* Build and Run the Graph. If a Tuner device is in use the graph will
201 * fail to run. Repeated calls to build will check successive tuner
208 msg_Warn( p_access, "SubmitATSCTuneRequest: "\
209 "Cannot Build the Graph: hr=0x%8lx", hr );
219 /*****************************************************************************
220 * Submit a DVB-T Tune Request
221 ******************************************************************************/
222 int BDAGraph::SubmitDVBTTuneRequest()
228 IDVBTuneRequest* p_dvbt_tune_request;
229 IDVBTLocator* p_dvbt_locator;
230 localComPtr(): p_dvbt_tune_request(NULL), p_dvbt_locator(NULL) {};
233 if( p_dvbt_tune_request )
234 p_dvbt_tune_request->Release();
236 p_dvbt_locator->Release();
239 long l_frequency, l_bandwidth, l_hp_fec, l_lp_fec, l_guard;
240 long l_transmission, l_hierarchy;
241 BinaryConvolutionCodeRate i_hp_fec, i_lp_fec;
242 GuardInterval i_guard;
243 TransmissionMode i_transmission;
244 HierarchyAlpha i_hierarchy;
246 l_frequency = var_GetInteger( p_access, "dvb-frequency" );
247 l_bandwidth = var_GetInteger( p_access, "dvb-bandwidth" );
248 l_hp_fec = var_GetInteger( p_access, "dvb-code-rate-hp" );
249 l_lp_fec = var_GetInteger( p_access, "dvb-code-rate-lp" );
250 l_guard = var_GetInteger( p_access, "dvb-guard" );
251 l_transmission = var_GetInteger( p_access, "dvb-transmission" );
252 l_hierarchy = var_GetInteger( p_access, "dvb-hierarchy" );
257 i_hp_fec = BDA_BCC_RATE_1_2; break;
259 i_hp_fec = BDA_BCC_RATE_2_3; break;
261 i_hp_fec = BDA_BCC_RATE_3_4; break;
263 i_hp_fec = BDA_BCC_RATE_5_6; break;
265 i_hp_fec = BDA_BCC_RATE_7_8;break;
267 i_hp_fec = BDA_BCC_RATE_NOT_SET;
273 i_lp_fec = BDA_BCC_RATE_1_2; break;
275 i_lp_fec = BDA_BCC_RATE_2_3; break;
277 i_lp_fec = BDA_BCC_RATE_3_4; break;
279 i_lp_fec = BDA_BCC_RATE_5_6; break;
281 i_lp_fec = BDA_BCC_RATE_7_8; break;
283 i_lp_fec = BDA_BCC_RATE_NOT_SET;
289 i_guard = BDA_GUARD_1_32; break,
291 i_guard = BDA_GUARD_1_16; break,
293 i_guard = BDA_GUARD_1_8; break;
295 i_guard = BDA_GUARD_1_4; break;
297 i_guard = BDA_GUARD_NOT_SET;
300 swicth( l_transmission )
303 i_transmission = BDA_XMIT_MODE_2K; break;
305 i_transmission = BDA_XMIT_MODE_8K; break;
307 i_transmission = BDA_XMIT_MODE_NOT_SET;
310 swicth( l_hierarchy )
313 i_hierarchy = BDA_HALPHA_1; break;
315 i_hierarchy = BDA_HALPHA_2; break;
317 i_hierarchy = BDA_HALPHA_4; break;
319 i_hierarchy = BDA_HALPHA_NOT_SET;
322 guid_network_type = CLSID_DVBTNetworkProvider;
323 hr = CreateTuneRequest();
326 msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
327 "Cannot create Tune Request: hr=0x%8lx", hr );
331 hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
332 (void**)&l.p_dvbt_tune_request );
335 msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
336 "Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
339 l.p_dvbt_tune_request->put_ONID( -1 );
340 l.p_dvbt_tune_request->put_SID( -1 );
341 l.p_dvbt_tune_request->put_TSID( -1 );
343 hr = ::CoCreateInstance( CLSID_DVBTLocator, 0, CLSCTX_INPROC,
344 IID_IDVBTLocator, (void**)&l.p_dvbt_locator );
347 msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
348 "Cannot create the DVBT Locator: hr=0x%8lx", hr );
353 if( l_frequency > 0 )
354 hr = l.p_dvbt_locator->put_CarrierFrequency( l_frequency );
355 if( SUCCEEDED( hr ) && l_bandwidth > 0 )
356 hr = l.p_dvbt_locator->put_Bandwidth( l_bandwidth );
357 if( SUCCEEDED( hr ) && i_hp_fec != BDA_BCC_RATE_NOT_SET )
358 hr = l.p_dvbt_locator->put_InnerFECRate( i_hp_fec );
359 if( SUCCEEDED( hr ) && i_lp_fec != BDA_BCC_RATE_NOT_SET )
360 hr = l.p_dvbt_locator->put_LPInnerFECRate( i_lp_fec );
361 if( SUCCEEDED( hr ) && i_guard != BDA_GUARD_NOT_SET )
362 hr = l.p_dvbt_locator->put_Guard( i_guard );
363 if( SUCCEEDED( hr ) && i_transmission != BDA_XMIT_MODE_NOT_SET )
364 hr = l.p_dvbt_locator->put_Mode( i_transmission );
365 if( SUCCEEDED( hr ) && i_hierarchy != BDA_HALPHA_NOT_SET )
366 hr = l.p_dvbt_locator->put_HAlpha( i_hierarchy );
369 msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
370 "Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
374 hr = p_tune_request->put_Locator( l.p_dvbt_locator );
377 msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
378 "Cannot put the locator: hr=0x%8lx", hr );
382 /* Build and Run the Graph. If a Tuner device is in use the graph will
383 * fail to run. Repeated calls to build will check successive tuner
390 msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
391 "Cannot Build the Graph: hr=0x%8lx", hr );
401 /*****************************************************************************
402 * Submit a DVB-C Tune Request
403 ******************************************************************************/
404 int BDAGraph::SubmitDVBCTuneRequest()
411 IDVBTuneRequest* p_dvbc_tune_request;
412 IDVBCLocator* p_dvbc_locator;
413 localComPtr(): p_dvbc_tune_request(NULL), p_dvbc_locator(NULL) {};
416 if( p_dvbc_tune_request )
417 p_dvbc_tune_request->Release();
419 p_dvbc_locator->Release();
423 long l_frequency, l_symbolrate;
425 ModulationType i_qam_mod;
427 l_frequency = var_GetInteger( p_access, "dvb-frequency" );
428 l_symbolrate = var_GetInteger( p_access, "dvb-srate" );
429 i_qam = var_GetInteger( p_access, "dvb-modulation" );
434 i_qam_mod = BDA_MOD_16QAM; break;
436 i_qam_mod = BDA_MOD_32QAM; break;
438 i_qam_mod = BDA_MOD_64QAM; break;
440 i_qam_mod = BDA_MOD_128QAM; break;
442 i_qam_mod = BDA_MOD_256QAM; break;
444 i_qam_mod = BDA_MOD_NOT_SET;
447 guid_network_type = CLSID_DVBCNetworkProvider;
448 hr = CreateTuneRequest();
451 msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
452 "Cannot create Tune Request: hr=0x%8lx", hr );
456 hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
457 (void**)&l.p_dvbc_tune_request );
460 msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
461 "Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
464 l.p_dvbc_tune_request->put_ONID( -1 );
465 l.p_dvbc_tune_request->put_SID( -1 );
466 l.p_dvbc_tune_request->put_TSID( -1 );
468 hr = ::CoCreateInstance( CLSID_DVBCLocator, 0, CLSCTX_INPROC,
469 IID_IDVBCLocator, (void**)&l.p_dvbc_locator );
472 msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
473 "Cannot create the DVB-C Locator: hr=0x%8lx", hr );
478 if( l_frequency > 0 )
479 hr = l.p_dvbc_locator->put_CarrierFrequency( l_frequency );
480 if( SUCCEEDED( hr ) && l_symbolrate > 0 )
481 hr = l.p_dvbc_locator->put_SymbolRate( l_symbolrate );
482 if( SUCCEEDED( hr ) && i_qam_mod != BDA_MOD_NOT_SET )
483 hr = l.p_dvbc_locator->put_Modulation( i_qam_mod );
486 msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
487 "Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
491 hr = p_tune_request->put_Locator( l.p_dvbc_locator );
494 msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
495 "Cannot put the locator: hr=0x%8lx", hr );
499 /* Build and Run the Graph. If a Tuner device is in use the graph will
500 * fail to run. Repeated calls to build will check successive tuner
507 msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
508 "Cannot Build the Graph: hr=0x%8lx", hr );
518 /*****************************************************************************
519 * Submit a DVB-S Tune Request
520 ******************************************************************************/
521 int BDAGraph::SubmitDVBSTuneRequest()
528 IDVBTuneRequest* p_dvbs_tune_request;
529 IDVBSLocator* p_dvbs_locator;
530 IDVBSTuningSpace* p_dvbs_tuning_space;
531 char* psz_polarisation;
532 char* psz_input_range;
533 BSTR bstr_input_range;
534 WCHAR* pwsz_input_range;
536 localComPtr(): p_dvbs_tune_request(NULL), p_dvbs_locator(NULL),
537 p_dvbs_tuning_space(NULL), bstr_input_range(NULL),
538 pwsz_input_range(NULL), i_range_len(0), psz_polarisation(NULL),
539 psz_input_range(NULL) {};
542 if( p_dvbs_tuning_space )
543 p_dvbs_tuning_space->Release();
544 if( p_dvbs_tune_request )
545 p_dvbs_tune_request->Release();
547 p_dvbs_locator->Release();
548 SysFreeString( bstr_input_range );
549 delete pwsz_input_range;
550 free( psz_input_range );
551 free( psz_polarisation );
554 long l_frequency, l_symbolrate, l_azimuth, l_elevation, l_longitude;
555 long l_lnb_lof1, l_lnb_lof2, l_lnb_slof, l_inversion, l_network_id;
558 Polarisation i_polar;
559 SpectralInversion i_inversion;
561 BinaryConvolutionCodeRate i_hp_fec;
562 ModulationType i_mod_typ;
564 l_frequency = var_GetInteger( p_access, "dvb-frequency" );
565 l_symbolrate = var_GetInteger( p_access, "dvb-srate" );
566 l_azimuth = var_GetInteger( p_access, "dvb-azimuth" );
567 l_elevation = var_GetInteger( p_access, "dvb-elevation" );
568 l_longitude = var_GetInteger( p_access, "dvb-longitude" );
569 l_lnb_lof1 = var_GetInteger( p_access, "dvb-lnb-lof1" );
570 l_lnb_lof2 = var_GetInteger( p_access, "dvb-lnb-lof2" );
571 l_lnb_slof = var_GetInteger( p_access, "dvb-lnb-slof" );
572 i_mod = var_GetInteger( p_access, "dvb-modulation" );
573 l_hp_fec = var_GetInteger( p_access, "dvb-code-rate-hp" );
574 l_inversion = var_GetInteger( p_access, "dvb-inversion" );
575 l_network_id = var_GetInteger( p_access, "dvb-network-id" );
577 l.psz_input_range = var_GetNonEmptyString( p_access, "dvb-range" );
578 l.psz_polarisation = var_GetNonEmptyString( p_access, "dvb-polarisation" );
580 b_west = ( l_longitude < 0 );
582 i_polar = BDA_POLARISATION_NOT_SET;
583 if( l.psz_polarisation != NULL )
585 switch( toupper( l.psz_polarisation[0] ) )
588 i_polar = BDA_POLARISATION_LINEAR_H;
591 i_polar = BDA_POLARISATION_LINEAR_V;
594 i_polar = BDA_POLARISATION_CIRCULAR_L;
597 i_polar = BDA_POLARISATION_CIRCULAR_R;
602 switch( l_inversion )
605 i_inversion = BDA_SPECTRAL_INVERSION_NORMAL; break,
607 i_inversion = BDA_SPECTRAL_INVERSION_INVERTED; break;
609 i_inversion = BDA_SPECTRAL_INVERSION_AUTOMATIC; break;
611 i_inversion = BDA_SPECTRAL_INVERSION_NOT_SET;
617 i_mod_typ = BDA_MOD_16QAM; break;
619 i_mod_typ = BDA_MOD_128QAM; break;
621 i_mod_typ = BDA_MOD_256QAM; break;
623 i_mod_typ = BDA_MOD_QPSK; break;
625 i_mod_typ = BDA_MOD_NOT_SET;
631 i_hp_fec = BDA_BCC_RATE_1_2; break;
633 i_hp_fec = BDA_BCC_RATE_2_3; break;
635 i_hp_fec = BDA_BCC_RATE_3_4; break;
637 i_hp_fec = BDA_BCC_RATE_5_6; break;
639 i_hp_fec = BDA_BCC_RATE_7_8; break;
641 i_hp_fec = BDA_BCC_RATE_NOT_SET;
644 l.i_range_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
645 l.psz_input_range, -1, l.pwsz_input_range, 0 );
646 if( l.i_range_len > 0 )
648 l.pwsz_input_range = new WCHAR[l.i_range_len];
649 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
650 l.psz_input_range, -1, l.pwsz_input_range, l.i_range_len );
651 l.bstr_input_range=SysAllocString( l.pwsz_input_range );
654 guid_network_type = CLSID_DVBSNetworkProvider;
655 hr = CreateTuneRequest();
658 msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
659 "Cannot create Tune Request: hr=0x%8lx", hr );
663 hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
664 (void**)&l.p_dvbs_tune_request );
667 msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
668 "Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
671 l.p_dvbs_tune_request->put_ONID( -1 );
672 l.p_dvbs_tune_request->put_SID( -1 );
673 l.p_dvbs_tune_request->put_TSID( -1 );
675 hr = ::CoCreateInstance( CLSID_DVBSLocator, 0, CLSCTX_INPROC,
676 IID_IDVBSLocator, (void**)&l.p_dvbs_locator );
679 msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
680 "Cannot create the DVBS Locator: hr=0x%8lx", hr );
684 hr = p_tuning_space->QueryInterface( IID_IDVBSTuningSpace,
685 (void**)&l.p_dvbs_tuning_space );
688 msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
689 "Cannot QI for IDVBSTuningSpace: hr=0x%8lx", hr );
695 hr = l.p_dvbs_tuning_space->put_LowOscillator( l_lnb_lof1 );
696 if( SUCCEEDED( hr ) && l_lnb_slof > 0 )
697 hr = l.p_dvbs_tuning_space->put_LNBSwitch( l_lnb_slof );
698 if( SUCCEEDED( hr ) && l_lnb_lof2 > 0 )
699 hr = l.p_dvbs_tuning_space->put_HighOscillator( l_lnb_lof2 );
700 if( SUCCEEDED( hr ) && i_inversion != BDA_SPECTRAL_INVERSION_NOT_SET )
701 hr = l.p_dvbs_tuning_space->put_SpectralInversion( i_inversion );
702 if( SUCCEEDED( hr ) && l_network_id > 0 )
703 hr = l.p_dvbs_tuning_space->put_NetworkID( l_network_id );
704 if( SUCCEEDED( hr ) && l.i_range_len > 0 )
705 hr = l.p_dvbs_tuning_space->put_InputRange( l.bstr_input_range );
707 if( SUCCEEDED( hr ) && l_frequency > 0 )
708 hr = l.p_dvbs_locator->put_CarrierFrequency( l_frequency );
709 if( SUCCEEDED( hr ) && l_symbolrate > 0 )
710 hr = l.p_dvbs_locator->put_SymbolRate( l_symbolrate );
711 if( SUCCEEDED( hr ) && i_polar != BDA_POLARISATION_NOT_SET )
712 hr = l.p_dvbs_locator->put_SignalPolarisation( i_polar );
713 if( SUCCEEDED( hr ) && i_mod_typ != BDA_MOD_NOT_SET )
714 hr = l.p_dvbs_locator->put_Modulation( i_mod_typ );
715 if( SUCCEEDED( hr ) && i_hp_fec != BDA_BCC_RATE_NOT_SET )
716 hr = l.p_dvbs_locator->put_InnerFECRate( i_hp_fec );
718 if( SUCCEEDED( hr ) && l_azimuth > 0 )
719 hr = l.p_dvbs_locator->put_Azimuth( l_azimuth );
720 if( SUCCEEDED( hr ) && l_elevation > 0 )
721 hr = l.p_dvbs_locator->put_Elevation( l_elevation );
722 if( SUCCEEDED( hr ) )
723 hr = l.p_dvbs_locator->put_WestPosition( b_west );
724 if( SUCCEEDED( hr ) )
725 hr = l.p_dvbs_locator->put_OrbitalPosition( labs( l_longitude ) );
728 msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
729 "Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
733 hr = p_tune_request->put_Locator( l.p_dvbs_locator );
736 msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
737 "Cannot put the locator: hr=0x%8lx", hr );
741 /* Build and Run the Graph. If a Tuner device is in use the graph will
742 * fail to run. Repeated calls to build will check successive tuner
749 msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
750 "Cannot Build the Graph: hr=0x%8lx", hr );
760 /*****************************************************************************
761 * Load the Tuning Space from System Tuning Spaces according to the
762 * Network Type requested
763 ******************************************************************************/
764 HRESULT BDAGraph::CreateTuneRequest()
767 GUID guid_this_network_type;
771 ITuningSpaceContainer* p_tuning_space_container;
772 IEnumTuningSpaces* p_tuning_space_enum;
773 ITuningSpace* p_this_tuning_space;
775 char * psz_network_name;
776 WCHAR * wpsz_network_name;
778 localComPtr(): p_tuning_space_container(NULL),
779 p_tuning_space_enum(NULL), p_this_tuning_space(NULL),
780 i_name_len(0), psz_network_name(NULL), wpsz_network_name(NULL),
784 if( p_tuning_space_container )
785 p_tuning_space_container->Release();
786 if( p_tuning_space_enum )
787 p_tuning_space_enum->Release();
788 if( p_this_tuning_space )
789 p_this_tuning_space->Release();
790 SysFreeString( bstr_name );
791 delete[] wpsz_network_name;
792 free( psz_network_name );
796 /* We shall test for a specific Tuning space name supplied on the command
797 * line as dvb-networkname=xxx.
798 * For some users with multiple cards and/or multiple networks this could
799 * be useful. This allows us to reasonably safely apply updates to the
800 * System Tuning Space in the registry without disrupting other streams. */
801 l.psz_network_name = var_GetNonEmptyString( p_access, "dvb-network-name" );
802 if( l.psz_network_name )
804 l.i_name_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
805 l.psz_network_name, -1, l.wpsz_network_name, 0 );
806 if( l.i_name_len > 0 )
808 l.wpsz_network_name = new WCHAR[l.i_name_len];
809 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, l.psz_network_name, -1,
810 l.wpsz_network_name, l.i_name_len );
811 msg_Dbg( p_access, "CreateTuneRequest: Find Tuning Space: %S",
812 l.wpsz_network_name );
816 /* A Tuning Space may already have been set up. If it is for the same
817 * network type then all is well. Otherwise, reset the Tuning Space and get
821 hr = p_tuning_space->get__NetworkType( &guid_this_network_type );
822 if( FAILED( hr ) ) guid_this_network_type = GUID_NULL;
823 if( guid_this_network_type == guid_network_type )
825 hr = p_tuning_space->get_UniqueName( &l.bstr_name );
828 msg_Warn( p_access, "CreateTuneRequest: "\
829 "Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
832 /* Test for a specific Tuning space name supplied on the command
833 * line as dvb-networkname=xxx */
834 if( l.i_name_len == 0 ||
835 lstrcmpW( l.wpsz_network_name, l.bstr_name ) == 0 )
837 msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %S",
843 p_tuning_space->Release();
844 p_tuning_space = NULL;
847 /* Force use of the first available Tuner Device during Build */
850 /* Get the SystemTuningSpaces container to enumerate through all the
851 * defined tuning spaces */
852 hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC,
853 IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container );
856 msg_Warn( p_access, "CreateTuneRequest: "\
857 "Cannot CoCreate SystemTuningSpaces: hr=0x%8lx", hr );
861 hr = l.p_tuning_space_container->get_EnumTuningSpaces(
862 &l.p_tuning_space_enum );
865 msg_Warn( p_access, "CreateTuneRequest: "\
866 "Cannot create SystemTuningSpaces Enumerator: hr=0x%8lx", hr );
870 while( l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL ) ==
873 hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type );
875 /* GUID_NULL means a non-BDA network was found e.g analog
876 * Ignore failures and non-BDA networks and keep looking */
877 if( FAILED( hr ) ) guid_this_network_type == GUID_NULL;
879 if( guid_this_network_type == guid_network_type )
881 hr = l.p_this_tuning_space->QueryInterface( IID_ITuningSpace,
882 (void**)&p_tuning_space );
885 msg_Warn( p_access, "CreateTuneRequest: "\
886 "Cannot QI Tuning Space: hr=0x%8lx", hr );
889 hr = p_tuning_space->get_UniqueName( &l.bstr_name );
892 msg_Warn( p_access, "CreateTuneRequest: "\
893 "Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
897 /* Test for a specific Tuning space name supplied on the command
898 * line as dvb-networkname=xxx */
899 if( l.i_name_len == 0 ||
900 lstrcmpW( l.wpsz_network_name, l.bstr_name ) == 0 )
902 msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %S",
904 hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
906 msg_Warn( p_access, "CreateTuneRequest: "\
907 "Cannot Create Tune Request: hr=0x%8lx", hr );
912 /* No tune request was found. If the create-name parameter was set then
913 * create a tuning space. By rights should use the same name used in
915 * Also would be nice to copy a tuning space but we only come here if we do
917 free( l.psz_network_name );
918 l.psz_network_name = var_GetNonEmptyString( p_access, "dvb-create-name" );
919 if( !l.psz_network_name )
922 msg_Warn( p_access, "CreateTuneRequest: "\
923 "Cannot find a suitable System Tuning Space: hr=0x%8lx", hr );
927 /* Need to use DVBSTuningSpace for DVB-S and ATSCTuningSpace for ATSC */
929 CLSID cls_tuning_space;
931 if( IsEqualCLSID( guid_network_type, CLSID_ATSCNetworkProvider ) )
932 cls_tuning_space = CLSID_ATSCTuningSpace;
933 if( IsEqualCLSID( guid_network_type, CLSID_DVBTNetworkProvider ) )
934 cls_tuning_space = CLSID_DVBTuningSpace;
935 if( IsEqualCLSID( guid_network_type, CLSID_DVBCNetworkProvider ) )
936 cls_tuning_space = CLSID_DVBTuningSpace;
937 if( IsEqualCLSID( guid_network_type, CLSID_DVBSNetworkProvider ) )
938 cls_tuning_space = CLSID_DVBSTuningSpace;
940 delete[] l.wpsz_network_name;
941 l.i_name_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
942 l.psz_network_name, -1, l.wpsz_network_name, 0 );
943 if( l.i_name_len > 0 )
945 l.wpsz_network_name = new WCHAR[l.i_name_len];
946 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, l.psz_network_name, -1,
947 l.wpsz_network_name, l.i_name_len );
949 SysFreeString( l.bstr_name );
950 l.bstr_name = SysAllocString( l.wpsz_network_name );
951 msg_Dbg( p_access, "CreateTuneRequest: Create Tuning Space: %S",
954 hr = ::CoCreateInstance( cls_tuning_space, 0, CLSCTX_INPROC,
955 IID_ITuningSpace, (void**)&p_tuning_space );
957 msg_Warn( p_access, "CreateTuneRequest: "\
958 "Cannot CoCreate new TuningSpace: hr=0x%8lx", hr );
959 if( SUCCEEDED( hr ) )
960 hr = p_tuning_space->put__NetworkType( guid_network_type );
962 msg_Warn( p_access, "CreateTuneRequest: "\
963 "Cannot Put Network Type: hr=0x%8lx", hr );
964 if( SUCCEEDED( hr ) )
965 hr = p_tuning_space->put_UniqueName( l.bstr_name );
967 msg_Warn( p_access, "CreateTuneRequest: "\
968 "Cannot Put Unique Name: hr=0x%8lx", hr );
969 if( SUCCEEDED( hr ) )
970 hr = p_tuning_space->put_FriendlyName( l.bstr_name );
972 msg_Warn( p_access, "CreateTuneRequest: "\
973 "Cannot Put Friendly Name: hr=0x%8lx", hr );
974 if( SUCCEEDED( hr ) )
975 hr = l.p_tuning_space_container->Add( p_tuning_space, &var_id );
978 msg_Warn( p_access, "CreateTuneRequest: "\
979 "Cannot Create new TuningSpace: hr=0x%8lx", hr );
982 hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
984 msg_Warn( p_access, "CreateTuneRequest: "\
985 "Cannot Create Tune Request: hr=0x%8lx", hr );
989 /******************************************************************************
991 * Step 4: Build the Filter Graph
992 * Build sets up devices, adds and connects filters
993 ******************************************************************************/
994 HRESULT BDAGraph::Build()
997 long l_capture_used, l_tif_used;
998 VARIANT l_tuning_space_id;
999 AM_MEDIA_TYPE grabber_media_type;
1003 ITuningSpaceContainer* p_tuning_space_container;
1004 localComPtr(): p_tuning_space_container(NULL) {};
1007 if( p_tuning_space_container )
1008 p_tuning_space_container->Release();
1012 /* Get the SystemTuningSpaces container to save the Tuning space */
1013 l_tuning_space_id.vt = VT_I4;
1014 l_tuning_space_id.lVal = 0L;
1015 hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC,
1016 IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container );
1019 msg_Warn( p_access, "Build: "\
1020 "Cannot CoCreate SystemTuningSpaces: hr=0x%8lx", hr );
1023 hr = l.p_tuning_space_container->FindID( p_tuning_space,
1024 &l_tuning_space_id.lVal );
1027 msg_Warn( p_access, "Build: "\
1028 "Cannot Find Tuning Space ID: hr=0x%8lx", hr );
1031 msg_Dbg( p_access, "Build: Using Tuning Space ID %d",
1032 l_tuning_space_id.lVal );
1033 hr = l.p_tuning_space_container->put_Item( l_tuning_space_id,
1037 msg_Warn( p_access, "Build: "\
1038 "Cannot save Tuning Space: hr=0x%8lx", hr );
1042 /* If we have already have a filter graph, rebuild it*/
1045 hr = ::CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC,
1046 IID_IGraphBuilder, (void**)&p_filter_graph );
1049 msg_Warn( p_access, "Build: "\
1050 "Cannot CoCreate IFilterGraph: hr=0x%8lx", hr );
1054 /* First filter in the graph is the Network Provider and
1055 * its Scanning Tuner which takes the Tune Request*/
1056 hr = ::CoCreateInstance( guid_network_type, NULL, CLSCTX_INPROC_SERVER,
1057 IID_IBaseFilter, (void**)&p_network_provider);
1060 msg_Warn( p_access, "Build: "\
1061 "Cannot CoCreate Network Provider: hr=0x%8lx", hr );
1064 hr = p_filter_graph->AddFilter( p_network_provider, L"Network Provider" );
1067 msg_Warn( p_access, "Build: "\
1068 "Cannot load network provider: hr=0x%8lx", hr );
1072 hr = p_network_provider->QueryInterface( IID_IScanningTuner,
1073 (void**)&p_scanning_tuner );
1076 msg_Warn( p_access, "Build: "\
1077 "Cannot QI Network Provider for Scanning Tuner: hr=0x%8lx", hr );
1081 hr = p_scanning_tuner->Validate( p_tune_request );
1084 msg_Warn( p_access, "Build: "\
1085 "Tune Request is invalid: hr=0x%8lx", hr );
1088 hr = p_scanning_tuner->put_TuneRequest( p_tune_request );
1091 msg_Warn( p_access, "Build: "\
1092 "Cannot submit the tune request: hr=0x%8lx", hr );
1096 /* Add the Network Tuner to the Network Provider. On subsequent calls,
1097 * l_tuner_used will cause a different tuner to be selected */
1098 hr = FindFilter( KSCATEGORY_BDA_NETWORK_TUNER, &l_tuner_used,
1099 p_network_provider, &p_tuner_device );
1102 msg_Warn( p_access, "Build: "\
1103 "Cannot load tuner device and connect network provider: "\
1108 /* Always look for all capture devices to match the Network Tuner */
1109 l_capture_used = -1;
1110 hr = FindFilter( KSCATEGORY_BDA_RECEIVER_COMPONENT, &l_capture_used,
1111 p_tuner_device, &p_capture_device );
1114 /* Some BDA drivers do not provide a Capture Device Filter so force
1115 * the Sample Grabber to connect directly to the Tuner Device */
1116 p_capture_device = p_tuner_device;
1117 p_tuner_device = NULL;
1118 msg_Warn( p_access, "Build: "\
1119 "Cannot find Capture device. Connecting to tuner: hr=0x%8lx", hr );
1122 /* Insert the Sample Grabber to tap into the Transport Stream. */
1123 hr = ::CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
1124 IID_IBaseFilter, (void**)&p_sample_grabber );
1127 msg_Warn( p_access, "Build: "\
1128 "Cannot load Sample Grabber Filter: hr=0x%8lx", hr );
1131 hr = p_filter_graph->AddFilter( p_sample_grabber, L"Sample Grabber" );
1134 msg_Warn( p_access, "Build: "\
1135 "Cannot add Sample Grabber Filter to graph: hr=0x%8lx", hr );
1139 hr = p_sample_grabber->QueryInterface( IID_ISampleGrabber,
1140 (void**)&p_grabber );
1143 msg_Warn( p_access, "Build: "\
1144 "Cannot QI Sample Grabber Filter: hr=0x%8lx", hr );
1148 ZeroMemory( &grabber_media_type, sizeof( AM_MEDIA_TYPE ) );
1149 grabber_media_type.majortype == MEDIATYPE_Stream;
1150 grabber_media_type.subtype == MEDIASUBTYPE_MPEG2_TRANSPORT;
1151 hr = p_grabber->SetMediaType( &grabber_media_type );
1154 msg_Warn( p_access, "Build: "\
1155 "Cannot set media type on grabber filter: hr=0x%8lx", hr );
1158 hr = Connect( p_capture_device, p_sample_grabber );
1161 msg_Warn( p_access, "Build: "\
1162 "Cannot connect Sample Grabber to Capture device: hr=0x%8lx", hr );
1166 /* We need the MPEG2 Demultiplexer even though we are going to use the VLC
1167 * TS demuxer. The TIF filter connects to the MPEG2 demux and works with
1168 * the Network Provider filter to set up the stream */
1169 hr = ::CoCreateInstance( CLSID_MPEG2Demultiplexer, NULL,
1170 CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&p_mpeg_demux );
1173 msg_Warn( p_access, "Build: "\
1174 "Cannot CoCreateInstance MPEG2 Demultiplexer: hr=0x%8lx", hr );
1177 hr = p_filter_graph->AddFilter( p_mpeg_demux, L"Demux" );
1180 msg_Warn( p_access, "Build: "\
1181 "Cannot add demux filter to graph: hr=0x%8lx", hr );
1185 hr = Connect( p_sample_grabber, p_mpeg_demux );
1188 msg_Warn( p_access, "Build: "\
1189 "Cannot connect demux to grabber: hr=0x%8lx", hr );
1193 /* Always look for the Transform Information Filter from the start
1194 * of the collection*/
1196 hr = FindFilter( KSCATEGORY_BDA_TRANSPORT_INFORMATION, &l_tif_used,
1197 p_mpeg_demux, &p_transport_info );
1200 msg_Warn( p_access, "Build: "\
1201 "Cannot load TIF onto demux: hr=0x%8lx", hr );
1205 /* Configure the Sample Grabber to buffer the samples continuously */
1206 hr = p_grabber->SetBufferSamples( true );
1209 msg_Warn( p_access, "Build: "\
1210 "Cannot set Sample Grabber to buffering: hr=0x%8lx", hr );
1213 hr = p_grabber->SetOneShot( false );
1216 msg_Warn( p_access, "Build: "\
1217 "Cannot set Sample Grabber to multi shot: hr=0x%8lx", hr );
1220 hr = p_grabber->SetCallback( this, 0 );
1223 msg_Warn( p_access, "Build: "\
1224 "Cannot set SampleGrabber Callback: hr=0x%8lx", hr );
1231 d_graph_register = 0;
1234 /* The Media Control is used to Run and Stop the Graph */
1235 hr = p_filter_graph->QueryInterface( IID_IMediaControl,
1236 (void**)&p_media_control );
1239 msg_Warn( p_access, "Build: "\
1240 "Cannot QI Media Control: hr=0x%8lx", hr );
1246 /******************************************************************************
1248 * Looks up all filters in a category and connects to the upstream filter until
1249 * a successful match is found. The index of the connected filter is returned.
1250 * On subsequent calls, this can be used to start from that point to find
1252 * This is used when the graph does not run because a tuner device is in use so
1253 * another one needs to be selected.
1254 ******************************************************************************/
1255 HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
1256 IBaseFilter* p_upstream, IBaseFilter** p_p_downstream )
1259 int i_moniker_index = -1;
1263 IMoniker* p_moniker;
1264 IEnumMoniker* p_moniker_enum;
1265 IBaseFilter* p_filter;
1266 IPropertyBag* p_property_bag;
1270 p_moniker_enum(NULL),
1272 p_property_bag(NULL)
1273 { ::VariantInit(&var_bstr); };
1277 p_moniker->Release();
1278 if( p_moniker_enum )
1279 p_moniker_enum->Release();
1281 p_filter->Release();
1282 if( p_property_bag )
1283 p_property_bag->Release();
1284 ::VariantClear(&var_bstr);
1288 if( !p_system_dev_enum )
1290 hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC,
1291 IID_ICreateDevEnum, (void**)&p_system_dev_enum );
1294 msg_Warn( p_access, "FindFilter: "\
1295 "Cannot CoCreate SystemDeviceEnum: hr=0x%8lx", hr );
1300 hr = p_system_dev_enum->CreateClassEnumerator( clsid,
1301 &l.p_moniker_enum, 0 );
1304 msg_Warn( p_access, "FindFilter: "\
1305 "Cannot CreateClassEnumerator: hr=0x%8lx", hr );
1308 while( l.p_moniker_enum->Next( 1, &l.p_moniker, 0 ) == S_OK )
1312 /* Skip over devices already found on previous calls */
1313 if( i_moniker_index <= *i_moniker_used ) continue;
1314 *i_moniker_used = i_moniker_index;
1316 hr = l.p_moniker->BindToObject( NULL, NULL, IID_IBaseFilter,
1317 (void**)&l.p_filter );
1321 l.p_moniker->Release();
1324 l.p_filter->Release();
1329 hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag,
1330 (void**)&l.p_property_bag );
1333 msg_Warn( p_access, "FindFilter: "\
1334 "Cannot Bind to Property Bag: hr=0x%8lx", hr );
1338 hr = l.p_property_bag->Read( L"FriendlyName", &l.var_bstr, NULL );
1341 msg_Warn( p_access, "FindFilter: "\
1342 "Cannot read filter friendly name: hr=0x%8lx", hr );
1346 hr = p_filter_graph->AddFilter( l.p_filter, l.var_bstr.bstrVal );
1349 msg_Warn( p_access, "FindFilter: "\
1350 "Cannot add filter: hr=0x%8lx", hr );
1354 hr = Connect( p_upstream, l.p_filter );
1355 if( SUCCEEDED( hr ) )
1357 msg_Dbg( p_access, "FindFilter: Connected %S", l.var_bstr.bstrVal );
1358 l.p_filter->QueryInterface( IID_IBaseFilter,
1359 (void**)p_p_downstream );
1362 /* Not the filter we want so unload and try the next one */
1363 hr = p_filter_graph->RemoveFilter( l.p_filter );
1366 msg_Warn( p_access, "FindFilter: "\
1367 "Failed unloading Filter: hr=0x%8lx", hr );
1372 l.p_moniker->Release();
1375 l.p_filter->Release();
1380 msg_Warn( p_access, "FindFilter: No filter connected: hr=0x%8lx", hr );
1384 /*****************************************************************************
1385 * Connect is called from Build to enumerate and connect pins
1386 *****************************************************************************/
1387 HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
1389 HRESULT hr = E_FAIL;
1393 IPin* p_pin_upstream;
1394 IPin* p_pin_downstream;
1395 IEnumPins* p_pin_upstream_enum;
1396 IEnumPins* p_pin_downstream_enum;
1398 localComPtr(): p_pin_upstream(NULL), p_pin_downstream(NULL),
1399 p_pin_upstream_enum(NULL), p_pin_downstream_enum(NULL),
1400 p_pin_temp(NULL) { };
1403 if( p_pin_upstream )
1404 p_pin_upstream->Release();
1405 if( p_pin_downstream )
1406 p_pin_downstream->Release();
1407 if( p_pin_upstream_enum )
1408 p_pin_upstream_enum->Release();
1409 if( p_pin_downstream_enum )
1410 p_pin_downstream_enum->Release();
1412 p_pin_temp->Release();
1416 PIN_INFO pin_info_upstream;
1417 PIN_INFO pin_info_downstream;
1419 hr = p_upstream->EnumPins( &l.p_pin_upstream_enum );
1422 msg_Warn( p_access, "Connect: "\
1423 "Cannot get upstream filter enumerator: hr=0x%8lx", hr );
1426 while( l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 ) == S_OK )
1428 hr = l.p_pin_upstream->QueryPinInfo( &pin_info_upstream );
1431 msg_Warn( p_access, "Connect: "\
1432 "Cannot get upstream filter pin information: hr=0x%8lx", hr );
1435 hr = l.p_pin_upstream->ConnectedTo( &l.p_pin_downstream );
1437 l.p_pin_downstream->Release();
1438 if(FAILED( hr ) && hr != VFW_E_NOT_CONNECTED )
1440 msg_Warn( p_access, "Connect: "\
1441 "Cannot check upstream filter connection: hr=0x%8lx", hr );
1444 if(( pin_info_upstream.dir == PINDIR_OUTPUT ) &&
1445 ( hr == VFW_E_NOT_CONNECTED ) )
1447 /* The upstream pin is not yet connected so check each pin on the
1448 * downstream filter */
1449 hr = p_downstream->EnumPins( &l.p_pin_downstream_enum );
1452 msg_Warn( p_access, "Connect: Cannot get "\
1453 "downstream filter enumerator: hr=0x%8lx", hr );
1456 while( l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 )
1459 hr = l.p_pin_downstream->QueryPinInfo( &pin_info_downstream );
1462 msg_Warn( p_access, "Connect: Cannot get "\
1463 "downstream filter pin information: hr=0x%8lx", hr );
1467 hr = l.p_pin_downstream->ConnectedTo( &l.p_pin_temp );
1468 if( hr == S_OK ) l.p_pin_temp->Release();
1469 if( hr != VFW_E_NOT_CONNECTED )
1473 msg_Warn( p_access, "Connect: Cannot check "\
1474 "downstream filter connection: hr=0x%8lx", hr );
1478 if(( pin_info_downstream.dir == PINDIR_INPUT ) &&
1479 ( hr == VFW_E_NOT_CONNECTED ) )
1481 hr = p_filter_graph->ConnectDirect( l.p_pin_upstream,
1482 l.p_pin_downstream, NULL );
1483 if( SUCCEEDED( hr ) )
1485 pin_info_downstream.pFilter->Release();
1486 pin_info_upstream.pFilter->Release();
1490 /* If we fall out here it means this downstream pin was not
1491 * suitable so try the next downstream pin */
1492 l.p_pin_downstream = NULL;
1493 pin_info_downstream.pFilter->Release();
1497 /* If we fall out here it means we did not find any suitable downstream
1498 * pin so try the next upstream pin */
1499 l.p_pin_upstream = NULL;
1500 pin_info_upstream.pFilter->Release();
1503 /* If we fall out here it means we did not find any pair of suitable pins */
1507 /*****************************************************************************
1508 * Start uses MediaControl to start the graph
1509 *****************************************************************************/
1510 HRESULT BDAGraph::Start()
1513 OAFilterState i_state; /* State_Stopped, State_Paused, State_Running */
1515 if( !p_media_control )
1517 msg_Dbg( p_access, "Start: Media Control has not been created" );
1520 hr = p_media_control->Run();
1524 /* Query the state of the graph - timeout after 100 milliseconds */
1525 while( hr = p_media_control->GetState( 100, &i_state ) != S_OK )
1530 "Start: Cannot get Graph state: hr=0x%8lx", hr );
1534 if( i_state == State_Running )
1537 /* The Graph is not running so stop it and return an error */
1538 msg_Warn( p_access, "Start: Graph not started: %d", i_state );
1539 hr = p_media_control->Stop();
1543 "Start: Cannot stop Graph after Run failed: hr=0x%8lx", hr );
1549 /*****************************************************************************
1550 * Read the stream of data - query the buffer size required
1551 *****************************************************************************/
1552 long BDAGraph::GetBufferSize()
1554 long l_buffer_size = 0;
1559 for( int i_timer = 0; queue_sample.empty() && i_timer < 200; i_timer++ )
1562 l_queue_size = queue_sample.size();
1563 if( l_queue_size <= 0 )
1565 msg_Warn( p_access, "BDA GetBufferSize: Timed Out waiting for sample" );
1569 /* Establish the length of the queue as it grows quickly. If the queue
1570 * size is checked dynamically there is a risk of not exiting the loop */
1571 for( long l_queue_count=0; l_queue_count < l_queue_size; l_queue_count++ )
1573 l_buffer_size += queue_sample.front()->GetActualDataLength();
1574 queue_buffer.push( queue_sample.front() );
1577 return l_buffer_size;
1580 /*****************************************************************************
1581 * Read the stream of data - Retrieve from the buffer queue
1582 ******************************************************************************/
1583 long BDAGraph::ReadBuffer( long* pl_buffer_len, BYTE* p_buffer )
1590 while( !queue_buffer.empty() )
1592 queue_buffer.front()->GetPointer( &p_buff_temp );
1593 hr = queue_buffer.front()->IsDiscontinuity();
1596 "BDA ReadBuffer: Sample Discontinuity. 0x%8lx", hr );
1597 memcpy( p_buffer + *pl_buffer_len, p_buff_temp,
1598 queue_buffer.front()->GetActualDataLength() );
1599 *pl_buffer_len += queue_buffer.front()->GetActualDataLength();
1600 queue_buffer.front()->Release();
1604 return *pl_buffer_len;
1607 /******************************************************************************
1608 * SampleCB - Callback when the Sample Grabber has a sample
1609 ******************************************************************************/
1610 STDMETHODIMP BDAGraph::SampleCB( double d_time, IMediaSample *p_sample )
1615 queue_sample.push( p_sample );
1619 msg_Warn( p_access, "BDA SampleCB: Not ready - dropped sample" );
1624 STDMETHODIMP BDAGraph::BufferCB( double d_time, BYTE* p_buffer,
1630 /******************************************************************************
1631 * removes each filter from the graph
1632 ******************************************************************************/
1633 HRESULT BDAGraph::Destroy()
1637 if( p_media_control )
1638 hr = p_media_control->Stop();
1640 if( p_transport_info )
1642 p_filter_graph->RemoveFilter( p_transport_info );
1643 p_transport_info->Release();
1644 p_transport_info = NULL;
1648 p_filter_graph->RemoveFilter( p_mpeg_demux );
1649 p_mpeg_demux->Release();
1650 p_mpeg_demux = NULL;
1652 if( p_sample_grabber )
1654 p_filter_graph->RemoveFilter( p_sample_grabber );
1655 p_sample_grabber->Release();
1656 p_sample_grabber = NULL;
1658 if( p_capture_device )
1660 p_filter_graph->RemoveFilter( p_capture_device );
1661 p_capture_device->Release();
1662 p_capture_device = NULL;
1664 if( p_tuner_device )
1666 p_filter_graph->RemoveFilter( p_tuner_device );
1667 p_tuner_device->Release();
1668 p_tuner_device = NULL;
1670 if( p_network_provider )
1672 p_filter_graph->RemoveFilter( p_network_provider );
1673 p_network_provider->Release();
1674 p_network_provider = NULL;
1677 if( p_scanning_tuner )
1679 p_scanning_tuner->Release();
1680 p_scanning_tuner = NULL;
1682 if( p_media_control )
1684 p_media_control->Release();
1685 p_media_control = NULL;
1687 if( p_filter_graph )
1689 p_filter_graph->Release();
1690 p_filter_graph = NULL;
1693 if( d_graph_register )
1701 /*****************************************************************************
1702 * Add/Remove a DirectShow filter graph to/from the Running Object Table.
1703 * Allows GraphEdit to "spy" on a remote filter graph.
1704 ******************************************************************************/
1705 HRESULT BDAGraph::Register()
1710 IMoniker* p_moniker;
1711 IRunningObjectTable* p_ro_table;
1712 localComPtr(): p_moniker(NULL), p_ro_table(NULL) {};
1716 p_moniker->Release();
1718 p_ro_table->Release();
1721 WCHAR psz_w_graph_name[128];
1724 hr = ::GetRunningObjectTable( 0, &l.p_ro_table );
1727 msg_Warn( p_access, "Register: Cannot get ROT: hr=0x%8lx", hr );
1731 wsprintfW( psz_w_graph_name, L"VLC BDA Graph %08x Pid %08x",
1732 (DWORD_PTR) p_filter_graph, ::GetCurrentProcessId() );
1733 hr = CreateItemMoniker( L"!", psz_w_graph_name, &l.p_moniker );
1736 msg_Warn( p_access, "Register: Cannot Create Moniker: hr=0x%8lx", hr );
1739 hr = l.p_ro_table->Register( ROTFLAGS_REGISTRATIONKEEPSALIVE,
1740 p_filter_graph, l.p_moniker, &d_graph_register );
1743 msg_Warn( p_access, "Register: Cannot Register Graph: hr=0x%8lx", hr );
1746 msg_Dbg( p_access, "Register: registered Graph: %S", psz_w_graph_name );
1750 void BDAGraph::Deregister()
1753 IRunningObjectTable* p_ro_table;
1754 hr = ::GetRunningObjectTable( 0, &p_ro_table );
1755 if( SUCCEEDED( hr ) )
1756 p_ro_table->Revoke( d_graph_register );
1757 d_graph_register = 0;
1758 p_ro_table->Release();