Commit b4ac748f authored by Damien Fouilleul's avatar Damien Fouilleul

- the long awaited Windows BDA driver support for DVB/ATSC capture cards, courtesy of Ken Self.

parent cea447d3
......@@ -1970,6 +1970,22 @@ then
fi
fi
dnl
dnl Windows DirectShow BDA access module
dnl
AC_ARG_ENABLE(bda,
[ --enable-bda Win32 DirectShow BDA support (default enabled on Win32)])
if test "${enable_bda}" != "no"
then
if test "${SYS}" = "mingw32" -o "${SYS}" = "cygwin"
then
AC_CHECK_HEADERS(dshow.h,
[ VLC_ADD_PLUGINS([bda])
VLC_ADD_CXXFLAGS([bda],[])
VLC_ADD_LDFLAGS([bda],[-lole32 -loleaut32 -luuid]) ])
fi
fi
dnl
dnl OpenCV wrapper and example filters
......@@ -5794,6 +5810,7 @@ AC_CONFIG_FILES([
AC_CONFIG_FILES([
modules/access/Makefile
modules/access/bda/Makefile
modules/access/dshow/Makefile
modules/access/dvb/Makefile
modules/access/mms/Makefile
......
SOURCES_bda = bda.c bda.h bdagraph.h bdagraph.cpp bdadefs.h
/*****************************************************************************
* bda.c : BDA access module for vlc
*****************************************************************************
* Copyright (C) 2007 the VideoLAN team
*
* Author: Ken Self <kens@campoz.fslife.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vlc/vlc.h>
#include <vlc_input.h>
#include <vlc_access.h>
#include "bda.h"
/*****************************************************************************
* Access: local prototypes
*****************************************************************************/
static int Open( vlc_object_t *p_this );
static int ParsePath( access_t *p_access, const char* psz_module,
const int i_param_count, const char** psz_param, const int* i_type );
static void Close( vlc_object_t *p_this );
static block_t *Block( access_t * );
static int Control( access_t *, int, va_list );
#define CACHING_TEXT N_("Caching value in ms")
#define CACHING_LONGTEXT N_( \
"Caching value for DVB streams. This " \
"value should be set in milliseconds." )
#define ADAPTER_TEXT N_("Adapter card to tune")
#define ADAPTER_LONGTEXT N_("Adapter cards have a device file in directory " \
"named /dev/dvb/adapter[n] with n>=0.")
#define DEVICE_TEXT N_("Device number to use on adapter")
#define DEVICE_LONGTEXT ""
#define FREQ_TEXT N_("Transponder/multiplex frequency")
#define FREQ_LONGTEXT N_("In kHz for DVB-S or Hz for DVB-C/T")
#define INVERSION_TEXT N_("Inversion mode")
#define INVERSION_LONGTEXT N_("Inversion mode [0=off, 1=on, 2=auto]")
#define PROBE_TEXT N_("Probe DVB card for capabilities")
#define PROBE_LONGTEXT N_("Some DVB cards do not like to be probed for their " \
"capabilities, you can disable this feature if you experience some " \
"trouble.")
#define BUDGET_TEXT N_("Budget mode")
#define BUDGET_LONGTEXT N_("This allows you to stream an entire transponder " \
"with a \"budget\" card.")
/* Satellite */
#define SATNO_TEXT N_("Satellite number in the Diseqc system")
#define SATNO_LONGTEXT N_("[0=no diseqc, 1-4=satellite number].")
#define VOLTAGE_TEXT N_("LNB voltage")
#define VOLTAGE_LONGTEXT N_("In Volts [0, 13=vertical, 18=horizontal].")
#define HIGH_VOLTAGE_TEXT N_("High LNB voltage")
#define HIGH_VOLTAGE_LONGTEXT N_("Enable high voltage if your cables are " \
"particularly long. This is not supported by all frontends.")
#define TONE_TEXT N_("22 kHz tone")
#define TONE_LONGTEXT N_("[0=off, 1=on, -1=auto].")
#define FEC_TEXT N_("Transponder FEC")
#define FEC_LONGTEXT N_("FEC=Forward Error Correction mode [9=auto].")
#define SRATE_TEXT N_("Transponder symbol rate in kHz")
#define SRATE_LONGTEXT ""
#define LNB_LOF1_TEXT N_("Antenna lnb_lof1 (kHz)")
#define LNB_LOF1_LONGTEXT ""
#define LNB_LOF2_TEXT N_("Antenna lnb_lof2 (kHz)")
#define LNB_LOF2_LONGTEXT ""
#define LNB_SLOF_TEXT N_("Antenna lnb_slof (kHz)")
#define LNB_SLOF_LONGTEXT ""
/* Cable */
#define MODULATION_TEXT N_("Modulation type")
#define MODULATION_LONGTEXT N_("QAM constellation points " \
"[16, 32, 64, 128, 256]")
static const int i_qam_list[] = { -1, 16, 32, 64, 128, 256 };
static const char *ppsz_qam_text[] = { N_("Undefined"), N_("16"), N_("32"),
N_("64"), N_("128"), N_("256") };
/* Terrestrial */
#define CODE_RATE_HP_TEXT N_("Terrestrial high priority stream code rate (FEC)")
#define CODE_RATE_HP_LONGTEXT ""
#define CODE_RATE_LP_TEXT N_("Terrestrial low priority stream code rate (FEC)")
#define CODE_RATE_LP_LONGTEXT ""
#define BANDWIDTH_TEXT N_("Terrestrial bandwidth")
#define BANDWIDTH_LONGTEXT N_("Terrestrial bandwidth [0=auto,6,7,8 in MHz]")
static const int i_band_list[] = { -1, 6, 7, 8 };
static const char *ppsz_band_text[] = { N_("Undefined"), N_("6"), N_("7"),
N_("8") };
#define GUARD_TEXT N_("Terrestrial guard interval")
#define GUARD_LONGTEXT ""
#define TRANSMISSION_TEXT N_("Terrestrial transmission mode")
#define TRANSMISSION_LONGTEXT ""
#define HIERARCHY_TEXT N_("Terrestrial hierarchy mode")
#define HIERARCHY_LONGTEXT ""
/* BDA module additional DVB-S Parameters */
#define AZIMUTH_TEXT N_("Satellite Azimuth")
#define AZIMUTH_LONGTEXT N_("Satellite Azimuth in tenths of degree")
#define ELEVATION_TEXT N_("Satellite Elevation")
#define ELEVATION_LONGTEXT N_("Satellite Elevation in tenths of degree")
#define LONGITUDE_TEXT N_("Satellite Longitude")
#define LONGITUDE_LONGTEXT N_( \
"Satellite Longitude in 10ths of degree, -ve=West")
#define POLARISATION_TEXT N_("Satellite Polarisation")
#define POLARISATION_LONGTEXT N_("Satellite Polarisation [H/V/L/R]")
static const char *ppsz_polar_list[] = { "H", "V", "L", "R" };
static const char *ppsz_polar_text[] = { N_("Horizontal"), N_("Vertical"),
N_("Circular Left"), N_("Circular Right") };
vlc_module_begin();
set_shortname( _("DVB") );
set_description( _("DirectShow DVB input") );
set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_ACCESS );
add_integer( "dvb-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
CACHING_LONGTEXT, VLC_TRUE );
add_integer( "dvb-frequency", 11954000, NULL, FREQ_TEXT, FREQ_LONGTEXT,
VLC_FALSE );
# if defined(WIN32) || defined(WINCE)
# else
add_integer( "dvb-adapter", 0, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT,
VLC_FALSE );
add_integer( "dvb-device", 0, NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
VLC_TRUE );
add_integer( "dvb-inversion", 2, NULL, INVERSION_TEXT,
INVERSION_LONGTEXT, VLC_TRUE );
add_bool( "dvb-probe", 1, NULL, PROBE_TEXT, PROBE_LONGTEXT, VLC_TRUE );
add_bool( "dvb-budget-mode", 0, NULL, BUDGET_TEXT, BUDGET_LONGTEXT,
VLC_TRUE );
# endif
/* DVB-S (satellite) */
# if defined(WIN32) || defined(WINCE)
add_integer( "dvb-azimuth", 0, NULL, AZIMUTH_TEXT, AZIMUTH_LONGTEXT,
VLC_FALSE );
add_integer( "dvb-elevation", 0, NULL, ELEVATION_TEXT,
ELEVATION_LONGTEXT, VLC_FALSE );
add_integer( "dvb-longitude", 0, NULL, LONGITUDE_TEXT,
LONGITUDE_LONGTEXT, VLC_FALSE );
add_string( "dvb-polarisation", NULL, NULL, POLARISATION_TEXT,
POLARISATION_LONGTEXT, VLC_FALSE );
change_string_list( ppsz_polar_list, ppsz_polar_text, 0 );
/* Note: Polaristion H = voltage 18; V = voltage 13; */
# else
add_integer( "dvb-satno", 0, NULL, SATNO_TEXT, SATNO_LONGTEXT,
VLC_TRUE );
add_integer( "dvb-voltage", 13, NULL, VOLTAGE_TEXT, VOLTAGE_LONGTEXT,
VLC_TRUE );
add_bool( "dvb-high-voltage", 0, NULL, HIGH_VOLTAGE_TEXT,
HIGH_VOLTAGE_LONGTEXT, VLC_TRUE );
add_integer( "dvb-tone", -1, NULL, TONE_TEXT, TONE_LONGTEXT,
VLC_TRUE );
add_integer( "dvb-lnb-lof1", 0, NULL, LNB_LOF1_TEXT,
LNB_LOF1_LONGTEXT, VLC_TRUE );
add_integer( "dvb-lnb-lof2", 0, NULL, LNB_LOF2_TEXT,
LNB_LOF2_LONGTEXT, VLC_TRUE );
add_integer( "dvb-lnb-slof", 0, NULL, LNB_SLOF_TEXT,
LNB_SLOF_LONGTEXT, VLC_TRUE );
# endif
add_integer( "dvb-fec", 9, NULL, FEC_TEXT, FEC_LONGTEXT, VLC_TRUE );
add_integer( "dvb-srate", 27500000, NULL, SRATE_TEXT, SRATE_LONGTEXT,
VLC_FALSE );
/* DVB-C (cable) */
add_integer( "dvb-modulation", 0, NULL, MODULATION_TEXT,
MODULATION_LONGTEXT, VLC_TRUE );
change_integer_list( i_qam_list, ppsz_qam_text, 0 );
/* DVB-T (terrestrial) */
add_integer( "dvb-code-rate-hp", 9, NULL, CODE_RATE_HP_TEXT,
CODE_RATE_HP_LONGTEXT, VLC_TRUE );
add_integer( "dvb-code-rate-lp", 9, NULL, CODE_RATE_LP_TEXT,
CODE_RATE_LP_LONGTEXT, VLC_TRUE );
add_integer( "dvb-bandwidth", 0, NULL, BANDWIDTH_TEXT, BANDWIDTH_LONGTEXT,
VLC_TRUE );
change_integer_list( i_band_list, ppsz_band_text, 0 );
add_integer( "dvb-guard", 0, NULL, GUARD_TEXT, GUARD_LONGTEXT, VLC_TRUE );
add_integer( "dvb-transmission", 0, NULL, TRANSMISSION_TEXT,
TRANSMISSION_LONGTEXT, VLC_TRUE );
add_integer( "dvb-hierarchy", 0, NULL, HIERARCHY_TEXT, HIERARCHY_LONGTEXT,
VLC_TRUE );
set_capability( "access2", 0 );
add_shortcut( "dvb" ); /* Generic name */
add_shortcut( "dvb-s" ); /* Satellite */
add_shortcut( "qpsk" );
add_shortcut( "satellite" );
add_shortcut( "dvb-c" ); /* Cable */
add_shortcut( "cable" );
add_shortcut( "dvb-t" ); /* Terrestrial */
add_shortcut( "terrestrial" );
add_shortcut( "atsc" ); /* Atsc */
add_shortcut( "usdigital" );
set_callbacks( Open, Close );
vlc_module_end();
/*****************************************************************************
* Open: open direct show device as an access module
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
access_t *p_access = (access_t*)p_this;
access_sys_t *p_sys;
const char* psz_module = "dvb";
const int i_param_count = 8;
const char* psz_param[] = { "frequency", "bandwidth",
"srate", "azimuth", "elevation", "longitude", "polarisation",
"modulation" };
const int i_type[] = { VLC_VAR_INTEGER, VLC_VAR_INTEGER,
VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER,
VLC_VAR_STRING, VLC_VAR_INTEGER };
char psz_full_name[128];
int i_ret;
/* Only if selected */
if( *p_access->psz_access == '\0' )
return VLC_EGENERIC;
/* Setup Access */
p_access->pf_read = NULL;
p_access->pf_block = Block; /* Function to read compressed data */
p_access->pf_control = Control; /* Function to control the module */
p_access->pf_seek = NULL;
p_access->info.i_update = 0;
p_access->info.i_size = 0;
p_access->info.i_pos = 0;
p_access->info.b_eof = VLC_FALSE;
p_access->info.i_title = 0;
p_access->info.i_seekpoint = 0;
p_access->p_sys = p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) );
if( !p_sys )
return VLC_ENOMEM;
memset( p_sys, 0, sizeof( access_sys_t ) );
for( int i = 0; i < i_param_count; i++ )
{
snprintf( psz_full_name, 128, "%s-%s\0", psz_module,
psz_param[i] );
var_Create( p_access, psz_full_name, i_type[i] | VLC_VAR_DOINHERIT );
}
/* Parse the command line */
if( ParsePath( p_access, psz_module, i_param_count, psz_param, i_type ) )
{
free( p_sys );
return VLC_EGENERIC;
}
/* Build directshow graph */
dvb_newBDAGraph( p_access );
i_ret = VLC_EGENERIC;
if( strncmp( p_access->psz_access, "qpsk", 4 ) == 0 ||
strncmp( p_access->psz_access, "dvb-s", 5 ) == 0 ||
strncmp( p_access->psz_access, "satellite", 9 ) == 0 )
{
i_ret = dvb_SubmitDVBSTuneRequest( p_access );
}
if( strncmp( p_access->psz_access, "cable", 5 ) == 0 ||
strncmp( p_access->psz_access, "dvb-c", 5 ) == 0 )
{
i_ret = dvb_SubmitDVBCTuneRequest( p_access );
}
if( strncmp( p_access->psz_access, "terrestrial", 11 ) == 0 ||
strncmp( p_access->psz_access, "dvb-t", 5 ) == 0 )
{
i_ret = dvb_SubmitDVBTTuneRequest( p_access );
}
if( strncmp( p_access->psz_access, "usdigital", 9 ) == 0 ||
strncmp( p_access->psz_access, "atsc", 4 ) == 0 )
{
i_ret = dvb_SubmitATSCTuneRequest( p_access );
}
if( i_ret != VLC_SUCCESS )
msg_Warn( p_access, "DVB_Open: Unsupported Network %s",
p_access->psz_access);
return i_ret;
}
/*****************************************************************************
* ParsePath:
* Parses the path passed to VLC treating it as a MRL which
* is organized as a sequence of <key>=<value> pairs separated by a colon
* e.g. :key1=value1:key2=value2:key3=value3.
* Each <key> is matched to one of the parameters passed in psz_param using
* whatever characters are provided. e.g. fr = fre = frequency
*****************************************************************************/
static int ParsePath( access_t *p_access, const char* psz_module,
const int i_param_count, const char** psz_param, const int* i_type )
{
const int MAXPARAM = 20;
BOOL b_used[MAXPARAM];
char* psz_parser;
char* psz_token;
char* psz_value;
vlc_value_t v_value;
int i_token_len, i_param_len, i_this_param;
char psz_full_name[128];
if( i_param_count > MAXPARAM )
{
msg_Warn( p_access, "ParsePath: Too many parameters: %d > %d",
i_param_count, MAXPARAM );
return VLC_EGENERIC;
}
for( int i = 0; i < i_param_count; i++ )
b_used[i] = FALSE;
psz_parser = p_access->psz_path;
if( strlen( psz_parser ) <= 0 )
return VLC_SUCCESS;
i_token_len = strcspn( psz_parser, ":" );
if( i_token_len <= 0 )
i_token_len = strcspn( ++psz_parser, ":" );
do
{
psz_token = strndup( psz_parser, i_token_len );
i_param_len = strcspn( psz_token, "=" );
if( i_param_len <= 0 )
{
msg_Warn( p_access, "ParsePath: Unspecified parameter %s",
psz_token );
if( psz_token )
free( psz_token );
return VLC_EGENERIC;
}
i_this_param = -1;
for( int i = 0; i < i_param_count; i++ )
{
if( strncmp( psz_token, psz_param[i], i_param_len ) == 0 )
{
i_this_param = i;
break;
}
}
if( i_this_param < 0 )
{
msg_Warn( p_access, "ParsePath: Unknown parameter %s", psz_token );
if( psz_token )
free( psz_token );
return VLC_EGENERIC;
}
if( b_used[i_this_param] )
{
msg_Warn( p_access, "ParsePath: Duplicate parameter %s",
psz_token );
if( psz_token )
free( psz_token );
return VLC_EGENERIC;
}
b_used[i_this_param] = TRUE;
/* if "=" was found in token then value starts at
* psz_token + i_paramlen + 1
* else there is no value specified so we use an empty string */
psz_value = psz_token + i_param_len + 1;
if( i_param_len >= i_token_len )
psz_value--;
if( i_type[i_this_param] == VLC_VAR_STRING )
v_value.psz_string = strdup( psz_value );
if( i_type[i_this_param] == VLC_VAR_INTEGER )
v_value.i_int = atol( psz_value );
snprintf( psz_full_name, 128, "%s-%s\0", psz_module,
psz_param[i_this_param] );
var_Set( p_access, psz_full_name, v_value );
if( psz_token )
free( psz_token );
if( i_token_len >= strlen( psz_parser ) )
break;
psz_parser += i_token_len + 1;
i_token_len = strcspn( psz_parser, ":" );
}
while( TRUE );
return VLC_SUCCESS;
}
/*****************************************************************************
* AccessClose: close device
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{
access_t *p_access = (access_t *)p_this;
access_sys_t *p_sys = p_access->p_sys;
dvb_deleteBDAGraph( p_access );
vlc_mutex_destroy( &p_sys->lock );
vlc_cond_destroy( &p_sys->wait );
free( p_sys );
}
/*****************************************************************************
* Control:
*****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
vlc_bool_t *pb_bool, b_bool;
int *pi_int, i_int;
int64_t *pi_64;
switch( i_query )
{
case ACCESS_CAN_SEEK: /* 0 */
case ACCESS_CAN_FASTSEEK: /* 1 */
case ACCESS_CAN_PAUSE: /* 2 */
case ACCESS_CAN_CONTROL_PACE: /* 3 */
pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
*pb_bool = VLC_FALSE;
break;
case ACCESS_GET_MTU: /* 4 */
pi_int = (int*)va_arg( args, int * );
*pi_int = 0;
break;
case ACCESS_GET_PTS_DELAY: /* 5 */
pi_64 = (int64_t*)va_arg( args, int64_t * );
*pi_64 = var_GetInteger( p_access, "dvb-caching" ) * 1000;
break;
/* */
case ACCESS_GET_TITLE_INFO: /* 6 */
case ACCESS_GET_META: /* 7 */
case ACCESS_SET_PAUSE_STATE: /* 8 */
case ACCESS_SET_TITLE: /* 9 */
case ACCESS_SET_SEEKPOINT: /* 10 */
return VLC_EGENERIC;
case ACCESS_SET_PRIVATE_ID_STATE: /* 11 */
i_int = (int)va_arg( args, int );
b_bool = (vlc_bool_t)va_arg( args, vlc_bool_t );
break;
case ACCESS_SET_PRIVATE_ID_CA: /* 12 -From Demux */
break;
default:
msg_Warn( p_access,
"DVB_Control: Unimplemented query in control %d", i_query );
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
/*****************************************************************************
* Block:
*****************************************************************************/
static block_t *Block( access_t *p_access )
{
block_t *p_block;
long l_buffer_len;
if( p_access->b_die )
return NULL;
l_buffer_len = dvb_GetBufferSize( p_access );
if( l_buffer_len < 0 )
return NULL;
p_block = block_New( p_access, l_buffer_len );
if( dvb_ReadBuffer( p_access, &l_buffer_len, p_block->p_buffer )
< 0 )
return NULL;
return p_block;
}
/*****************************************************************************
* bda.h : DirectShow BDA access header for vlc
*****************************************************************************
* Copyright ( C ) 2007 the VideoLAN team
*
* Author: Ken Self <kens@campoz.fslife.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifndef _MSC_VER
# include <wtypes.h>
# include <unknwn.h>
# include <ole2.h>
# include <limits.h>
# ifdef _WINGDI_
# undef _WINGDI_
# endif
# define _WINGDI_ 1
# define AM_NOVTABLE
# define _OBJBASE_H_
# undef _X86_
# define _I64_MAX LONG_LONG_MAX
# define LONGLONG long long
#endif
#ifdef __cplusplus
class BDAGraph;
extern "C" {
#else
typedef struct BDAGraph BDAGraph;
#endif
void dvb_newBDAGraph( access_t* p_access );
void dvb_deleteBDAGraph( access_t* p_access );
int dvb_SubmitATSCTuneRequest( access_t* p_access );
int dvb_SubmitDVBTTuneRequest( access_t* p_access );
int dvb_SubmitDVBCTuneRequest( access_t* p_access );
int dvb_SubmitDVBSTuneRequest( access_t* p_access );
long dvb_GetBufferSize( access_t* p_access );
long dvb_ReadBuffer( access_t* p_access, long* l_buffer_len, BYTE* p_buff );
#ifdef __cplusplus
}
#endif
/****************************************************************************
* Access descriptor declaration
****************************************************************************/
struct access_sys_t
{
/* These 2 must be left at the beginning */
vlc_mutex_t lock;
vlc_cond_t wait;
BDAGraph *p_bda_module;
};
/*****************************************************************************
* bdadefs.h : DirectShow BDA headers for vlc
*****************************************************************************
* Copyright (C) 2007 the VideoLAN team
*
* Author: Ken Self <kens@campoz.fslife.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
class IATSCChannelTuneRequest;
class IATSCLocator;
class IChannelTuneRequest;
class IComponent;
class IComponents;
class IComponentType;
class IComponentTypes;
class IDVBCLocator;
class IDVBSLocator;
class IDVBTLocator;
class IDVBTuneRequest;
class IEnumComponents;
class IEnumComponentTypes;
class IEnumTuningSpaces;
class ILocator;
class ISampleGrabber;
class ISampleGrabberCB;
class IScanningTuner;
class ITuner;
class ITuneRequest;
class ITuningSpace;
class ITuningSpaceContainer;
class ITuningSpaces;
typedef enum BinaryConvolutionCodeRate
{
BDA_BCC_RATE_NOT_SET = -1,
BDA_BCC_RATE_NOT_DEFINED=0,
BDA_BCC_RATE_1_2 = 1,
BDA_BCC_RATE_2_3,
BDA_BCC_RATE_3_4,
BDA_BCC_RATE_3_5,
BDA_BCC_RATE_4_5,
BDA_BCC_RATE_5_6,
BDA_BCC_RATE_5_11,
BDA_BCC_RATE_7_8,
BDA_BCC_RATE_MAX,
} BinaryConvolutionCodeRate;
typedef enum ComponentCategory
{
CategoryNotSet = -1,
CategoryOther=0,
CategoryVideo,
CategoryAudio,
CategoryText,
CategoryData,
} ComponentCategory;
typedef enum ComponentStatus
{
StatusActive,
StatusInactive,
StatusUnavailable,
} ComponentStatus;
typedef enum FECMethod
{
BDA_FEC_METHOD_NOT_SET = -1,
BDA_FEC_METHOD_NOT_DEFINED=0,
BDA_FEC_VITERBI = 1,
BDA_FEC_RS_204_188,
BDA_FEC_MAX,
} FECMethod;
typedef enum GuardInterval
{
BDA_GUARD_NOT_SET = -1,
BDA_GUARD_NOT_DEFINED=0,
BDA_GUARD_1_32 = 1,
BDA_GUARD_1_16,
BDA_GUARD_1_8,
BDA_GUARD_1_4,
BDA_GUARD_MAX,
} GuardInterval;
typedef enum HierarchyAlpha
{
BDA_HALPHA_NOT_SET = -1,
BDA_HALPHA_NOT_DEFINED=0,
BDA_HALPHA_1 = 1,
BDA_HALPHA_2,
BDA_HALPHA_4,
BDA_HALPHA_MAX,
} HierarchyAlpha;
typedef enum ModulationType
{
BDA_MOD_NOT_SET = -1,
BDA_MOD_NOT_DEFINED=0,
BDA_MOD_16QAM = 1,
BDA_MOD_32QAM,
BDA_MOD_64QAM,
BDA_MOD_80QAM,
BDA_MOD_96QAM,
BDA_MOD_112QAM,
BDA_MOD_128QAM,
BDA_MOD_160QAM,
BDA_MOD_192QAM,
BDA_MOD_224QAM,
BDA_MOD_256QAM,
BDA_MOD_320QAM,
BDA_MOD_384QAM,
BDA_MOD_448QAM,
BDA_MOD_512QAM,
BDA_MOD_640QAM,
BDA_MOD_768QAM,
BDA_MOD_896QAM,
BDA_MOD_1024QAM,
BDA_MOD_QPSK,
BDA_MOD_BPSK,
BDA_MOD_OQPSK,
BDA_MOD_8VSB,
BDA_MOD_16VSB,
BDA_MOD_ANALOG_AMPLITUDE,
BDA_MOD_ANALOG_FREQUENCY,
BDA_MOD_MAX,
} ModulationType;
typedef enum Polarisation
{
BDA_POLARISATION_NOT_SET = -1,
BDA_POLARISATION_NOT_DEFINED = 0,
BDA_POLARISATION_LINEAR_H = 1,
BDA_POLARISATION_LINEAR_V = 2,
BDA_POLARISATION_CIRCULAR_L = 3,
BDA_POLARISATION_CIRCULAR_R = 4,
BDA_POLARISATION_MAX = 5
} Polarisation;
typedef enum TransmissionMode
{
BDA_XMIT_MODE_NOT_SET = -1,
BDA_XMIT_MODE_NOT_DEFINED=0,
BDA_XMIT_MODE_2K = 1,
BDA_XMIT_MODE_8K,
BDA_XMIT_MODE_MAX,
} TransmissionMode;
class IComponent : public IDispatch
{
public:
virtual HRESULT __stdcall get_Type( IComponentType** p_p_cpt_type )=0;
virtual HRESULT __stdcall put_Type( IComponentType* p_cpt_type )=0;
virtual HRESULT __stdcall get_DescLangID( long* p_l_language )=0;
virtual HRESULT __stdcall put_DescLangID( long l_language )=0;
virtual HRESULT __stdcall get_Status( ComponentStatus* p_status )=0;
virtual HRESULT __stdcall put_Status( ComponentStatus status )=0;
virtual HRESULT __stdcall get_Description( BSTR* p_bstr_desc )=0;
virtual HRESULT __stdcall put_Description( BSTR bstr_desc )=0;
virtual HRESULT __stdcall Clone( IComponent** p_p_component )=0;
};
class IComponents : public IDispatch
{
public:
virtual HRESULT __stdcall get_Count( long* pl_count )=0;
virtual HRESULT __stdcall get__NewEnum( IEnumVARIANT** p_p_enum )=0;
virtual HRESULT __stdcall EnumComponents( IEnumComponents** p_p_enum )=0;
virtual HRESULT __stdcall get_Item( VARIANT Index,
IComponent** p_p_component )=0;
virtual HRESULT __stdcall Add( IComponent* p_component,
VARIANT* v_index )=0;
virtual HRESULT __stdcall Remove( VARIANT v_index )=0;
virtual HRESULT __stdcall Clone( IComponents** p_p_cpts )=0;
};
class IComponentType : public IDispatch
{
public:
virtual HRESULT __stdcall get_Category( ComponentCategory* p_category )=0;
virtual HRESULT __stdcall put_Category( ComponentCategory category )=0;
virtual HRESULT __stdcall get_MediaMajorType( BSTR* p_bstr_major_type )=0;
virtual HRESULT __stdcall put_MediaMajorType( BSTR bstr_major_type )=0;
virtual HRESULT __stdcall get__MediaMajorType( GUID* p_guid_major_type )=0;
virtual HRESULT __stdcall put__MediaMajorType( REFCLSID guid_major_type )=0;
virtual HRESULT __stdcall get_MediaSubType( BSTR* p_bstr_sub_type )=0;
virtual HRESULT __stdcall put_MediaSubType( BSTR bstr_sub_type )=0;
virtual HRESULT __stdcall get__MediaSubType( GUID* p_guid_sub_type )=0;
virtual HRESULT __stdcall put__MediaSubType( REFCLSID guid_sub_type )=0;
virtual HRESULT __stdcall get_MediaFormatType( BSTR* p_bstr_format_type )=0;
virtual HRESULT __stdcall put_MediaFormatType( BSTR bstr_format_type )=0;
virtual HRESULT __stdcall get__MediaFormatType(
GUID* p_guid_format_type )=0;
virtual HRESULT __stdcall put__MediaFormatType(
REFCLSID guid_format_type )=0;
virtual HRESULT __stdcall get_MediaType( AM_MEDIA_TYPE* p_media_type )=0;
virtual HRESULT __stdcall put_MediaType( AM_MEDIA_TYPE* p_media_type )=0;
virtual HRESULT __stdcall Clone( IComponentType** p_p_cpt_type )=0;
};
class IComponentTypes : public IDispatch
{
public:
virtual HRESULT __stdcall get_Count( long* l_count )=0;
virtual HRESULT __stdcall get__NewEnum( IEnumVARIANT** p_p_enum )=0;
virtual HRESULT __stdcall EnumComponentTypes(
IEnumComponentTypes** p_p_enum )=0;
virtual HRESULT __stdcall get_Item( VARIANT v_index,
IComponentType** p_p_cpt_type )=0;
virtual HRESULT __stdcall put_Item( VARIANT v_index,
IComponentType* p_cpt_type )=0;
virtual HRESULT __stdcall Add( IComponentType* p_cpt_type,
VARIANT* v_index )=0;
virtual HRESULT __stdcall Remove( VARIANT v_index )=0;
virtual HRESULT __stdcall Clone( IComponentTypes** p_p_cpt_types )=0;
};
class IEnumComponents : public IUnknown
{
public:
virtual HRESULT __stdcall Next( ULONG num_elem, IComponent** p_p_elem,
ULONG* p_num_elem_fetch )=0;
virtual HRESULT __stdcall Skip( ULONG num_elem )=0;
virtual HRESULT __stdcall Reset( void )=0;
virtual HRESULT __stdcall Clone( IEnumComponents** p_p_enum )=0;
};
class IEnumComponentTypes : public IUnknown
{
public:
virtual HRESULT __stdcall Next( ULONG num_elem, IComponentType** p_p_elem,
ULONG* p_num_elem_fetch )=0;
virtual HRESULT __stdcall Skip( ULONG num_elem )=0;
virtual HRESULT __stdcall Reset( void )=0;
virtual HRESULT __stdcall Clone( IEnumComponentTypes** p_p_enum )=0;
};
class IEnumTuningSpaces : public IUnknown
{
public:
virtual HRESULT __stdcall Next( ULONG l_num_elem,
ITuningSpace** p_p_tuning_space, ULONG* pl_num_elem_fetched )=0;
virtual HRESULT __stdcall Skip( ULONG l_num_elem )=0;
virtual HRESULT __stdcall Reset( void )=0;
virtual HRESULT __stdcall Clone( IEnumTuningSpaces** p_p_enum )=0;
};
class ITuner : public IUnknown
{
public:
virtual HRESULT __stdcall get_TuningSpace(
ITuningSpace** p_p_tuning_space )=0;
virtual HRESULT __stdcall put_TuningSpace( ITuningSpace* p_tuning_space )=0;
virtual HRESULT __stdcall EnumTuningSpaces( IEnumTuningSpaces** p_p_enum )=0;
virtual HRESULT __stdcall get_TuneRequest(
ITuneRequest** p_p_tune_request )=0;
virtual HRESULT __stdcall put_TuneRequest( ITuneRequest* p_tune_request )=0;
virtual HRESULT __stdcall Validate( ITuneRequest* p_tune_request )=0;
virtual HRESULT __stdcall get_PreferredComponentTypes(
IComponentTypes** p_p_cpt_types )=0;
virtual HRESULT __stdcall put_PreferredComponentTypes(
IComponentTypes* p_cpt_types )=0;
virtual HRESULT __stdcall get_SignalStrength( long* l_sig_strength )=0;
virtual HRESULT __stdcall TriggerSignalEvents( long l_interval )=0;
};
class ISampleGrabber : public IUnknown
{
public:
virtual HRESULT __stdcall SetOneShot( BOOL b_one_shot )=0;
virtual HRESULT __stdcall SetMediaType(
const AM_MEDIA_TYPE* p_media_type )=0;
virtual HRESULT __stdcall GetConnectedMediaType(
AM_MEDIA_TYPE* p_media_type )=0;
virtual HRESULT __stdcall SetBufferSamples( BOOL b_buffer_samples )=0;
virtual HRESULT __stdcall GetCurrentBuffer( long* p_buff_size,
long* p_buffer )=0;
virtual HRESULT __stdcall GetCurrentSample( IMediaSample** p_p_sample )=0;
virtual HRESULT __stdcall SetCallback( ISampleGrabberCB* pf_callback,
long l_callback_type )=0;
};
class ISampleGrabberCB : public IUnknown
{
public:
virtual HRESULT __stdcall SampleCB( double d_sample_time,
IMediaSample* p_sample )=0;
virtual HRESULT __stdcall BufferCB( double d_sample_time, BYTE *p_buffer,
long l_bufferLen )=0;
};
class IScanningTuner : public ITuner
{
public:
virtual HRESULT __stdcall SeekUp( void )=0;
virtual HRESULT __stdcall SeekDown( void )=0;
virtual HRESULT __stdcall ScanDown( long l_pause )=0;
virtual HRESULT __stdcall ScanUp( long l_pause )=0;
virtual HRESULT __stdcall AutoProgram( void )=0;
};
class ITuneRequest : public IDispatch
{
public:
virtual HRESULT __stdcall get_TuningSpace(
ITuningSpace** p_p_tuning_space )=0;
virtual HRESULT __stdcall get_Components( IComponents** p_p_components )=0;
virtual HRESULT __stdcall Clone( ITuneRequest** p_p_tune_request )=0;
virtual HRESULT __stdcall get_Locator( ILocator** p_p_locator )=0;
virtual HRESULT __stdcall put_Locator( ILocator* p_locator )=0;
};
class IChannelTuneRequest : public ITuneRequest
{
public:
virtual HRESULT __stdcall get_Channel( long* pl_channel )=0;
virtual HRESULT __stdcall put_Channel( long l_channel )=0;
};
class IATSCChannelTuneRequest : public IChannelTuneRequest
{
public:
virtual HRESULT __stdcall get_MinorChannel( long* pl_minor_channel )=0;
virtual HRESULT __stdcall put_MinorChannel( long l_minor_channel )=0;
};
class IDVBTuneRequest : public ITuneRequest
{
public:
virtual HRESULT __stdcall get_ONID( long* pl_onid )=0;
virtual HRESULT __stdcall put_ONID( long l_onid )=0;
virtual HRESULT __stdcall get_TSID( long* pl_tsid )=0;
virtual HRESULT __stdcall put_TSID( long l_tsid )=0;
virtual HRESULT __stdcall get_SID( long* pl_sid )=0;
virtual HRESULT __stdcall put_SID( long l_sid )=0;
};
class ILocator : public IDispatch
{
public:
virtual HRESULT __stdcall get_CarrierFrequency( long* pl_frequency )=0;
virtual HRESULT __stdcall put_CarrierFrequency( long l_frequency )=0;
virtual HRESULT __stdcall get_InnerFEC( FECMethod* FEC )=0;
virtual HRESULT __stdcall put_InnerFEC( FECMethod FEC )=0;
virtual HRESULT __stdcall get_InnerFECRate(
BinaryConvolutionCodeRate* FEC )=0;
virtual HRESULT __stdcall put_InnerFECRate(
BinaryConvolutionCodeRate FEC )=0;
virtual HRESULT __stdcall get_OuterFEC( FECMethod* FEC )=0;
virtual HRESULT __stdcall put_OuterFEC( FECMethod FEC )=0;
virtual HRESULT __stdcall get_OuterFECRate(
BinaryConvolutionCodeRate* FEC )=0;
virtual HRESULT __stdcall put_OuterFECRate(
BinaryConvolutionCodeRate FEC )=0;
virtual HRESULT __stdcall get_Modulation( ModulationType* p_modulation )=0;
virtual HRESULT __stdcall put_Modulation( ModulationType modulation )=0;
virtual HRESULT __stdcall get_SymbolRate( long* pl_rate )=0;
virtual HRESULT __stdcall put_SymbolRate( long l_rate )=0;
virtual HRESULT __stdcall Clone( ILocator** p_p_locator )=0;
};
class IATSCLocator : public ILocator
{
public:
virtual HRESULT __stdcall get_PhysicalChannel( long* pl_phys_channel )=0;
virtual HRESULT __stdcall put_PhysicalChannel( long l_phys_channel )=0;
virtual HRESULT __stdcall get_TSID( long* pl_tsid )=0;
virtual HRESULT __stdcall put_TSID( long l_tsid )=0;
};
class IDVBCLocator : public ILocator
{
public:
};
class IDVBSLocator : public ILocator
{
public:
virtual HRESULT __stdcall get_SignalPolarisation(
Polarisation* p_polarisation )=0;
virtual HRESULT __stdcall put_SignalPolarisation(
Polarisation polarisation )=0;
virtual HRESULT __stdcall get_WestPosition( VARIANT_BOOL* pb_west )=0;
virtual HRESULT __stdcall put_WestPosition( VARIANT_BOOL b_west )=0;
virtual HRESULT __stdcall get_OrbitalPosition( long* pl_longitude )=0;
virtual HRESULT __stdcall put_OrbitalPosition( long l_longitude )=0;
virtual HRESULT __stdcall get_Azimuth( long* pl_azimuth )=0;
virtual HRESULT __stdcall put_Azimuth( long l_azimuth )=0;
virtual HRESULT __stdcall get_Elevation( long* pl_elevation )=0;
virtual HRESULT __stdcall put_Elevation( long l_elevation )=0;
};
class IDVBTLocator : public ILocator
{
public:
virtual HRESULT __stdcall get_Bandwidth( long* pl_bandwidth )=0;
virtual HRESULT __stdcall put_Bandwidth( long l_bandwidth )=0;
virtual HRESULT __stdcall get_LPInnerFEC( FECMethod* FEC )=0;
virtual HRESULT __stdcall put_LPInnerFEC( FECMethod FEC )=0;
virtual HRESULT __stdcall get_LPInnerFECRate(
BinaryConvolutionCodeRate* FEC )=0;
virtual HRESULT __stdcall put_LPInnerFECRate(
BinaryConvolutionCodeRate FEC )=0;
virtual HRESULT __stdcall get_HAlpha( HierarchyAlpha* Alpha )=0;
virtual HRESULT __stdcall put_HAlpha( HierarchyAlpha Alpha )=0;
virtual HRESULT __stdcall get_Guard( GuardInterval* GI )=0;
virtual HRESULT __stdcall put_Guard( GuardInterval GI )=0;
virtual HRESULT __stdcall get_Mode( TransmissionMode* mode )=0;
virtual HRESULT __stdcall put_Mode( TransmissionMode mode )=0;
virtual HRESULT __stdcall get_OtherFrequencyInUse(
VARIANT_BOOL* OtherFrequencyInUseVal )=0;
virtual HRESULT __stdcall put_OtherFrequencyInUse(
VARIANT_BOOL OtherFrequencyInUseVal )=0;
};
class ITuningSpace : public IDispatch
{
public:
virtual HRESULT __stdcall get_UniqueName( BSTR* p_bstr_name )=0;
virtual HRESULT __stdcall put_UniqueName( BSTR Name )=0;
virtual HRESULT __stdcall get_FriendlyName( BSTR* p_bstr_name )=0;
virtual HRESULT __stdcall put_FriendlyName( BSTR bstr_name )=0;
virtual HRESULT __stdcall get_CLSID( BSTR* bstr_clsid )=0;
virtual HRESULT __stdcall get_NetworkType( BSTR* p_bstr_network_guid )=0;
virtual HRESULT __stdcall put_NetworkType( BSTR bstr_network_guid )=0;
virtual HRESULT __stdcall get__NetworkType( GUID* p_guid_network_guid )=0;
virtual HRESULT __stdcall put__NetworkType( REFCLSID clsid_network_guid )=0;
virtual HRESULT __stdcall CreateTuneRequest(
ITuneRequest** p_p_tune_request )=0;
virtual HRESULT __stdcall EnumCategoryGUIDs( IEnumGUID** p_p_enum )=0;
virtual HRESULT __stdcall EnumDeviceMonikers( IEnumMoniker** p_p_enum )=0;
virtual HRESULT __stdcall get_DefaultPreferredComponentTypes(
IComponentTypes** p_p_cpt_types )=0;
virtual HRESULT __stdcall put_DefaultPreferredComponentTypes(
IComponentTypes* p_cpt_types )=0;
virtual HRESULT __stdcall get_FrequencyMapping( BSTR* p_bstr_mapping )=0;
virtual HRESULT __stdcall put_FrequencyMapping( BSTR bstr_mapping )=0;
virtual HRESULT __stdcall get_DefaultLocator( ILocator** p_p_locator )=0;
virtual HRESULT __stdcall put_DefaultLocator( ILocator* p_locator )=0;
virtual HRESULT __stdcall Clone( ITuningSpace** p_p_tuning_space )=0;
};
class ITuningSpaceContainer : public IDispatch
{
public:
virtual HRESULT __stdcall get_Count( long* l_count )=0;
virtual HRESULT __stdcall get__NewEnum( IEnumVARIANT** p_p_enum )=0;
virtual HRESULT __stdcall get_Item( VARIANT v_index,
ITuningSpace** p_p_tuning_space )=0;
virtual HRESULT __stdcall put_Item( VARIANT v_index,
ITuningSpace* p_tuning_space )=0;
virtual HRESULT __stdcall TuningSpacesForCLSID( BSTR bstr_clsid,
ITuningSpaces** p_p_tuning_spaces )=0;
virtual HRESULT __stdcall _TuningSpacesForCLSID( REFCLSID clsid,
ITuningSpaces** p_p_tuning_spaces )=0;
virtual HRESULT __stdcall TuningSpacesForName( BSTR bstr_name,
ITuningSpaces** p_p_tuning_spaces )=0;
virtual HRESULT __stdcall FindID( ITuningSpace* p_tuning_space,
long* l_id )=0;
virtual HRESULT __stdcall Add( ITuningSpace* p_tuning_space,
VARIANT* v_index )=0;
virtual HRESULT __stdcall get_EnumTuningSpaces(
IEnumTuningSpaces** p_p_enum )=0;
virtual HRESULT __stdcall Remove( VARIANT v_index )=0;
virtual HRESULT __stdcall get_MaxCount( long* l_maxcount )=0;
virtual HRESULT __stdcall put_MaxCount( long l_maxcount )=0;
};
class ITuningSpaces : public IDispatch
{
public:
virtual HRESULT __stdcall get_Count( long* l_count )=0;
virtual HRESULT __stdcall get__NewEnum( IEnumVARIANT** p_p_enum )=0;
virtual HRESULT __stdcall get_Item( VARIANT v_index,
ITuningSpace** p_p_tuning_space )=0;
virtual HRESULT __stdcall get_EnumTuningSpaces(
IEnumTuningSpaces** p_p_enum )=0;
};
/*****************************************************************************
* bdagraph.cpp : DirectShow BDA graph for vlc
*****************************************************************************
* Copyright( C ) 2007 the VideoLAN team
*
* Author: Ken Self <kens@campoz.fslife.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
*( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vlc/vlc.h>
#include <vlc_input.h>
#include <vlc_access.h>
/* Needed to call CoInitializeEx */
#define _WIN32_DCOM
/* Work-around a bug in w32api-2.5 */
/*#ifndef _MSC_VER
# define QACONTAINERFLAGS QACONTAINERFLAGS_SOMETHINGELSE
#endif */
#include "bdagraph.h"
const GUID CLSID_ATSCLocator =
{0x8872FF1B,0x98FA,0x4D7A,{0x8D,0x93,0xC9,0xF1,0x05,0x5F,0x85,0xBB}};
const GUID CLSID_ATSCNetworkProvider =
{0x0dad2fdd,0x5fd7,0x11d3,{0x8f,0x50,0x00,0xc0,0x4f,0x79,0x71,0xe2}};
const GUID CLSID_DVBCLocator =
{0xc531d9fd,0x9685,0x4028,{0x8b,0x68,0x6e,0x12,0x32,0x07,0x9f,0x1e}};
const GUID CLSID_DVBCNetworkProvider =
{0xdc0c0fe7,0x0485,0x4266,{0xb9,0x3f,0x68,0xfb,0xf8,0xe,0xd8,0x34}};
const GUID CLSID_DVBSLocator =
{0x1df7d126,0x4050,0x47f0,{0xa7,0xcf,0x4c,0x4c,0xa9,0x24,0x13,0x33}};
const GUID CLSID_DVBSNetworkProvider =
{0xfa4b375a,0x45b4,0x4d45,{0x84,0x40,0x26,0x39,0x57,0xb1,0x16,0x23}};
const GUID CLSID_DVBSTuningSpace =
{0xb64016f3,0xc9a2,0x4066,{0x96,0xf0,0xbd,0x95,0x63,0x31,0x47,0x26}};
const GUID CLSID_DVBTLocator =
{0x9cd64701,0xbdf3,0x4d14,{0x8e,0x03,0xf1,0x29,0x83,0xd8,0x66,0x64}};
const GUID CLSID_DVBTNetworkProvider =
{0x216c62df,0x6d7f,0x4e9a,{0x85,0x71,0x05,0xf1,0x4e,0xdb,0x76,0x6a}};
const GUID CLSID_FilterGraph =
{0xe436ebb3,0x524f,0x11ce,{0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID CLSID_InfTee =
{0xf8388a40,0xd5bb,0x11d0,{0xbe,0x5a,0x00,0x80,0xc7,0x06,0x56,0x8e}};
const GUID CLSID_MPEG2Demultiplexer =
{0xafb6c280,0x2c41,0x11d3,{0x8a,0x60,0x00,0x00,0xf8,0x1e,0x0e,0x4a}};
const GUID CLSID_NullRenderer =
{0xc1f400a4,0x3f08,0x11d3,{0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37}};
const GUID CLSID_SampleGrabber =
{0xc1f400a0,0x3f08,0x11d3,{0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37}};
const GUID CLSID_SystemDeviceEnum =
{0x62be5d10,0x60eb,0x11d0,{0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86}};
const GUID CLSID_SystemTuningSpaces =
{0xd02aac50,0x027e,0x11d3,{0x9d,0x8e,0x00,0xc0,0x4f,0x72,0xd9,0x80}};
const GUID IID_IATSCChannelTuneRequest =
{0x0369B4E1,0x45B6,0x11d3,{0xB6,0x50,0x00,0xC0,0x4F,0x79,0x49,0x8E}};
const GUID IID_IATSCLocator =
{0xbf8d986f,0x8c2b,0x4131,{0x94,0xd7,0x4d,0x3d,0x9f,0xcc,0x21,0xef}};
const GUID IID_IBaseFilter =
{0x56a86895,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID IID_ICreateDevEnum =
{0x29840822,0x5b84,0x11d0,{0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86}};
const GUID IID_IDVBTLocator =
{0x8664da16,0xdda2,0x42ac,{0x92,0x6a,0xc1,0x8f,0x91,0x27,0xc3,0x02}};
const GUID IID_IDVBCLocator =
{0x6e42f36e,0x1dd2,0x43c4,{0x9f,0x78,0x69,0xd2,0x5a,0xe3,0x90,0x34}};
const GUID IID_IDVBSLocator =
{0x3d7c353c,0x0d04,0x45f1,{0xa7,0x42,0xf9,0x7c,0xc1,0x18,0x8d,0xc8}};
const GUID IID_IDVBSTuningSpace =
{0xcdf7be60,0xd954,0x42fd,{0xa9,0x72,0x78,0x97,0x19,0x58,0xe4,0x70}};
const GUID IID_IDVBTuneRequest =
{0x0D6F567E,0xA636,0x42bb,{0x83,0xBA,0xCE,0x4C,0x17,0x04,0xAF,0xA2}};
const GUID IID_IGraphBuilder =
{0x56a868a9,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID IID_IMediaControl =
{0x56a868b1,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID IID_IMpeg2Demultiplexer =
{0x436eee9c,0x264f,0x4242,{0x90,0xe1,0x4e,0x33,0x0c,0x10,0x75,0x12}};
const GUID IID_ISampleGrabber =
{0x6b652fff,0x11fe,0x4fce,{0x92,0xad,0x02,0x66,0xb5,0xd7,0xc7,0x8f}};
const GUID IID_IScanningTuner =
{0x1dfd0a5c,0x0284,0x11d3,{0x9d,0x8e,0x00,0xc0,0x4f,0x72,0xd9,0x80}};
const GUID IID_ITuner =
{0x28C52640,0x018A,0x11d3,{0x9D,0x8E,0x00,0xC0,0x4F,0x72,0xD9,0x80}};
const GUID IID_ITuningSpace =
{0x061c6e30,0xe622,0x11d2,{0x94,0x93,0x00,0xc0,0x4f,0x72,0xd9,0x80}};
const GUID IID_ITuningSpaceContainer =
{0x5B692E84,0xE2F1,0x11d2,{0x94,0x93,0x00,0xC0,0x4F,0x72,0xD9,0x80}};
const GUID KSCATEGORY_BDA_TRANSPORT_INFORMATION =
{0xa2e3074f,0x6c3d,0x11d3,{0xb6,0x53,0x00,0xc0,0x4f,0x79,0x49,0x8e}};
const GUID KSCATEGORY_BDA_RECEIVER_COMPONENT =
{0xFD0A5AF4,0xB41D,0x11d2,{0x9c,0x95,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
const GUID KSCATEGORY_BDA_NETWORK_TUNER =
{0x71985f48,0x1ca1,0x11d3,{0x9c,0xc8,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
const GUID MEDIATYPE_MPEG2_SECTIONS =
{0x455f176c,0x4b06,0x47ce,{0x9a,0xef,0x8c,0xae,0xf7,0x3d,0xf7,0xb5}};
const GUID MEDIASUBTYPE_None =
{0xe436eb8e,0x524f,0x11ce,{0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID FORMAT_None =
{0x0f6417d6,0xc318,0x11d0,{0xa4,0x3f,0x00,0xa0,0xc9,0x22,0x31,0x96}};
/****************************************************************************
* Interfaces for calls from C
****************************************************************************/
extern "C" {
void dvb_newBDAGraph( access_t* p_access )
{
p_access->p_sys->p_bda_module = new BDAGraph( p_access );
};
void dvb_deleteBDAGraph( access_t* p_access )
{
delete p_access->p_sys->p_bda_module;
};
int dvb_SubmitATSCTuneRequest( access_t* p_access )
{
return p_access->p_sys->p_bda_module->SubmitATSCTuneRequest();
};
int dvb_SubmitDVBTTuneRequest( access_t* p_access )
{
return p_access->p_sys->p_bda_module->SubmitDVBTTuneRequest();
};
int dvb_SubmitDVBCTuneRequest( access_t* p_access )
{
return p_access->p_sys->p_bda_module->SubmitDVBCTuneRequest();
};
int dvb_SubmitDVBSTuneRequest( access_t* p_access )
{
return p_access->p_sys->p_bda_module->SubmitDVBSTuneRequest();
};
long dvb_GetBufferSize( access_t* p_access )
{
return p_access->p_sys->p_bda_module->GetBufferSize();
};
long dvb_ReadBuffer( access_t* p_access, long* l_buffer_len, BYTE* p_buff )
{
return p_access->p_sys->p_bda_module->ReadBuffer( l_buffer_len,
p_buff );
};
};
/*****************************************************************************
* Constructor
*****************************************************************************/
BDAGraph::BDAGraph( access_t* p_this ):
p_access( p_this ),
guid_network_type(GUID_NULL),
l_tuner_used(-1),
d_graph_register( 0 )
{
p_tuning_space = NULL;
p_tune_request = NULL;
p_media_control = NULL;
p_filter_graph = NULL;
p_system_dev_enum = NULL;
p_network_provider = p_tuner_device = p_capture_device = NULL;
p_sample_grabber = p_mpeg_demux = p_transport_info = NULL;
p_scanning_tuner = NULL;
p_grabber = NULL;
/* Initialize COM - MS says to use CoInitializeEx in preference to
* CoInitialize */
CoInitializeEx( 0, COINIT_APARTMENTTHREADED );
}
/*****************************************************************************
* Destructor
*****************************************************************************/
BDAGraph::~BDAGraph()
{
Destroy();
CoUninitialize();
}
/*****************************************************************************
* Submit an ATSC Tune Request
*****************************************************************************/
int BDAGraph::SubmitATSCTuneRequest()
{
HRESULT hr = S_OK;
class localComPtr
{
public:
IATSCChannelTuneRequest* p_atsc_tune_request;
IATSCLocator* p_atsc_locator;
localComPtr(): p_atsc_tune_request(NULL), p_atsc_locator(NULL) {};
~localComPtr()
{
if( p_atsc_tune_request )
p_atsc_tune_request->Release();
if( p_atsc_locator )
p_atsc_locator->Release();
}
} l;
long l_major_channel, l_minor_channel, l_physical_channel;
l_major_channel = l_minor_channel = l_physical_channel = -1;
/*
l_major_channel = var_GetInteger( p_access, "dvb-major-channel" );
l_minor_channel = var_GetInteger( p_access, "dvb-minor-channel" );
l_physical_channel = var_GetInteger( p_access, "dvb-physical-channel" );
*/
guid_network_type = CLSID_ATSCNetworkProvider;
hr = CreateTuneRequest();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitATSCTuneRequest: "\
"Cannot create Tuning Space: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->QueryInterface( IID_IATSCChannelTuneRequest,
(void**)&l.p_atsc_tune_request );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitATSCTuneRequest: "\
"Cannot QI for IATSCChannelTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = ::CoCreateInstance( CLSID_ATSCLocator, 0, CLSCTX_INPROC,
IID_IATSCLocator, (void**)&l.p_atsc_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitATSCTuneRequest: "\
"Cannot create the ATSC locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = S_OK;
if( l_major_channel > 0 )
hr = l.p_atsc_tune_request->put_Channel( l_major_channel );
if( SUCCEEDED( hr ) && l_minor_channel > 0 )
hr = l.p_atsc_tune_request->put_MinorChannel( l_minor_channel );
if( SUCCEEDED( hr ) && l_physical_channel > 0 )
hr = l.p_atsc_locator->put_PhysicalChannel( l_physical_channel );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitATSCTuneRequest: "\
"Cannot set tuning parameters: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->put_Locator( l.p_atsc_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitATSCTuneRequest: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
/* Build and Run the Graph. If a Tuner device is in use the graph will
* fail to run. Repeated calls to build will check successive tuner
* devices */
do
{
hr = Build();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitATSCTuneRequest: "\
"Cannot Build the Graph: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = Start();
}
while( hr != S_OK );
return VLC_SUCCESS;
}
/*****************************************************************************
* Submit a DVB-T Tune Request
******************************************************************************/
int BDAGraph::SubmitDVBTTuneRequest()
{
HRESULT hr = S_OK;
class localComPtr
{
public:
IDVBTuneRequest* p_dvbt_tune_request;
IDVBTLocator* p_dvbt_locator;
localComPtr(): p_dvbt_tune_request(NULL), p_dvbt_locator(NULL) {};
~localComPtr()
{
if( p_dvbt_tune_request )
p_dvbt_tune_request->Release();
if( p_dvbt_locator )
p_dvbt_locator->Release();
}
} l;
long l_frequency, l_bandwidth;
l_frequency = l_bandwidth = -1;
l_frequency = var_GetInteger( p_access, "dvb-frequency" );
l_bandwidth = var_GetInteger( p_access, "dvb-bandwidth" );
guid_network_type = CLSID_DVBTNetworkProvider;
hr = CreateTuneRequest();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
"Cannot create Tune Request: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
(void**)&l.p_dvbt_tune_request );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
"Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
l.p_dvbt_tune_request->put_ONID( -1 );
l.p_dvbt_tune_request->put_SID( -1 );
l.p_dvbt_tune_request->put_TSID( -1 );
hr = ::CoCreateInstance( CLSID_DVBTLocator, 0, CLSCTX_INPROC,
IID_IDVBTLocator, (void**)&l.p_dvbt_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
"Cannot create the DVBT Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = S_OK;
if( l_frequency > 0 )
hr = l.p_dvbt_locator->put_CarrierFrequency( l_frequency );
if( SUCCEEDED( hr ) && l_bandwidth > 0 )
hr = l.p_dvbt_locator->put_Bandwidth( l_bandwidth );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
"Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->put_Locator( l.p_dvbt_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
/* Build and Run the Graph. If a Tuner device is in use the graph will
* fail to run. Repeated calls to build will check successive tuner
* devices */
do
{
hr = Build();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
"Cannot Build the Graph: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = Start();
}
while( hr != S_OK );
return VLC_SUCCESS;
}
/*****************************************************************************
* Submit a DVB-C Tune Request
******************************************************************************/
int BDAGraph::SubmitDVBCTuneRequest()
{
HRESULT hr = S_OK;
class localComPtr
{
public:
IDVBTuneRequest* p_dvbc_tune_request;
IDVBCLocator* p_dvbc_locator;
localComPtr(): p_dvbc_tune_request(NULL), p_dvbc_locator(NULL) {};
~localComPtr()
{
if( p_dvbc_tune_request )
p_dvbc_tune_request->Release();
if( p_dvbc_locator )
p_dvbc_locator->Release();
}
} l;
long l_frequency, l_symbolrate;
int i_qam;
ModulationType i_qam_mod;
l_frequency = l_symbolrate = i_qam = -1;
l_frequency = var_GetInteger( p_access, "dvb-frequency" );
l_symbolrate = var_GetInteger( p_access, "dvb-srate" );
i_qam = var_GetInteger( p_access, "dvb-modulation" );
i_qam_mod = BDA_MOD_NOT_SET;
if( i_qam == 16 )
i_qam_mod = BDA_MOD_16QAM;
if( i_qam == 32 )
i_qam_mod = BDA_MOD_32QAM;
if( i_qam == 64 )
i_qam_mod = BDA_MOD_64QAM;
if( i_qam == 128 )
i_qam_mod = BDA_MOD_128QAM;
if( i_qam == 256 )
i_qam_mod = BDA_MOD_256QAM;
guid_network_type = CLSID_DVBCNetworkProvider;
hr = CreateTuneRequest();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot create Tune Request: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
(void**)&l.p_dvbc_tune_request );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
l.p_dvbc_tune_request->put_ONID( -1 );
l.p_dvbc_tune_request->put_SID( -1 );
l.p_dvbc_tune_request->put_TSID( -1 );
hr = ::CoCreateInstance( CLSID_DVBCLocator, 0, CLSCTX_INPROC,
IID_IDVBCLocator, (void**)&l.p_dvbc_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot create the DVB-C Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = S_OK;
if( l_frequency > 0 )
hr = l.p_dvbc_locator->put_CarrierFrequency( l_frequency );
if( SUCCEEDED( hr ) && l_symbolrate > 0 )
hr = l.p_dvbc_locator->put_SymbolRate( l_symbolrate );
if( SUCCEEDED( hr ) && i_qam_mod != BDA_MOD_NOT_SET )
hr = l.p_dvbc_locator->put_Modulation( i_qam_mod );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->put_Locator( l.p_dvbc_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
/* Build and Run the Graph. If a Tuner device is in use the graph will
* fail to run. Repeated calls to build will check successive tuner
* devices */
do
{
hr = Build();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot Build the Graph: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = Start();
}
while( hr != S_OK );
return VLC_SUCCESS;
}
/*****************************************************************************
* Submit a DVB-S Tune Request
******************************************************************************/
int BDAGraph::SubmitDVBSTuneRequest()
{
HRESULT hr = S_OK;
class localComPtr
{
public:
IDVBTuneRequest* p_dvbs_tune_request;
IDVBSLocator* p_dvbs_locator;
localComPtr(): p_dvbs_tune_request(NULL), p_dvbs_locator(NULL) {};
~localComPtr()
{
if( p_dvbs_tune_request )
p_dvbs_tune_request->Release();
if( p_dvbs_locator )
p_dvbs_locator->Release();
}
} l;
long l_frequency, l_symbolrate, l_azimuth, l_elevation, l_longitude;
char* psz_polarisation;
Polarisation i_polar;
VARIANT_BOOL b_west;
l_frequency = l_symbolrate = l_azimuth = l_elevation = l_longitude = -1;
l_frequency = var_GetInteger( p_access, "dvb-frequency" );
l_symbolrate = var_GetInteger( p_access, "dvb-srate" );
l_azimuth = var_GetInteger( p_access, "dvb-azimuth" );
l_elevation = var_GetInteger( p_access, "dvb-elevation" );
l_longitude = var_GetInteger( p_access, "dvb-longitude" );
psz_polarisation = var_GetString( p_access, "dvb-polarisation" );
b_west = ( l_longitude < 0 ) ? TRUE : FALSE;
i_polar = BDA_POLARISATION_NOT_SET;
if( *psz_polarisation == 'H' || *psz_polarisation == 'h' )
i_polar = BDA_POLARISATION_LINEAR_H;
if( *psz_polarisation == 'V' || *psz_polarisation == 'v' )
i_polar = BDA_POLARISATION_LINEAR_V;
if( *psz_polarisation == 'L' || *psz_polarisation == 'l' )
i_polar = BDA_POLARISATION_CIRCULAR_L;
if( *psz_polarisation == 'R' || *psz_polarisation == 'r' )
i_polar = BDA_POLARISATION_CIRCULAR_R;
guid_network_type = CLSID_DVBSNetworkProvider;
hr = CreateTuneRequest();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot create Tune Request: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
(void**)&l.p_dvbs_tune_request );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
l.p_dvbs_tune_request->put_ONID( -1 );
l.p_dvbs_tune_request->put_SID( -1 );
l.p_dvbs_tune_request->put_TSID( -1 );
hr = ::CoCreateInstance( CLSID_DVBSLocator, 0, CLSCTX_INPROC,
IID_IDVBSLocator, (void**)&l.p_dvbs_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot create the DVBS Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = S_OK;
if( l_frequency > 0 )
hr = l.p_dvbs_locator->put_CarrierFrequency( l_frequency );
if( SUCCEEDED( hr ) && l_symbolrate > 0 )
hr = l.p_dvbs_locator->put_SymbolRate( l_symbolrate );
if( SUCCEEDED( hr ) && l_azimuth > 0 )
hr = l.p_dvbs_locator->put_Azimuth( l_azimuth );
if( SUCCEEDED( hr ) && l_elevation > 0 )
hr = l.p_dvbs_locator->put_Elevation( l_elevation );
if( SUCCEEDED( hr ) )
hr = l.p_dvbs_locator->put_OrbitalPosition( labs( l_longitude ) );
if( SUCCEEDED( hr ) )
hr = l.p_dvbs_locator->put_WestPosition( b_west );
if( SUCCEEDED( hr ) && i_polar != BDA_POLARISATION_NOT_SET )
hr = l.p_dvbs_locator->put_SignalPolarisation( i_polar );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = p_tune_request->put_Locator( l.p_dvbs_locator );
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
/* Build and Run the Graph. If a Tuner device is in use the graph will
* fail to run. Repeated calls to build will check successive tuner
* devices */
do
{
hr = Build();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
"Cannot Build the Graph: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
hr = Start();
}
while( hr != S_OK );
return VLC_SUCCESS;
}
/*****************************************************************************
* Load the Tuning Space from System Tuning Spaces according to the
* Network Type requested
******************************************************************************/
HRESULT BDAGraph::CreateTuneRequest()
{
HRESULT hr = S_OK;
GUID guid_this_network_type;
class localComPtr
{
public:
ITuningSpaceContainer* p_tuning_space_container;
IEnumTuningSpaces* p_tuning_space_enum;
ITuningSpace* p_this_tuning_space;
localComPtr(): p_tuning_space_container(NULL),
p_tuning_space_enum(NULL), p_this_tuning_space(NULL) {};
~localComPtr()
{
if( p_tuning_space_container )
p_tuning_space_container->Release();
if( p_tuning_space_enum )
p_tuning_space_enum->Release();
if( p_this_tuning_space )
p_this_tuning_space->Release();
}
} l;
/* A Tuning Space may already have been set up. If it is for the same
* network type then all is well. Otherwise, reset the Tuning Space and get
* a new one */
if( p_tuning_space )
{
hr = p_tuning_space->get__NetworkType( &guid_this_network_type );
if( FAILED( hr ) ) guid_this_network_type = GUID_NULL;
if( guid_this_network_type == guid_network_type )
{
return S_OK;
}
else
{
p_tuning_space->Release();
p_tuning_space = NULL;
}
}
/* Force use of the first available Tuner Device during Build */
l_tuner_used = -1;
/* Get the SystemTuningSpaces container to enumerate through all the
* defined tuning spaces */
hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC,
IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container );
if( FAILED( hr ) )
{
msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot CoCreate SystemTuningSpaces: hr=0x%8lx", hr );
return hr;
}
hr = l.p_tuning_space_container->get_EnumTuningSpaces(
&l.p_tuning_space_enum );
if( FAILED( hr ) )
{
msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot create SystemTuningSpaces Enumerator: hr=0x%8lx", hr );
return hr;
}
while( l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL ) ==
S_OK )
{
hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type );
/* GUID_NULL means a non-BDA network was found e.g analog
* Ignore failures and non-BDA networks and keep looking */
if( FAILED( hr ) ) guid_this_network_type == GUID_NULL;
if( guid_this_network_type == guid_network_type )
{
hr = l.p_this_tuning_space->QueryInterface( IID_ITuningSpace,
(void**)&p_tuning_space );
if( FAILED( hr ) )
{
msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot QI Tuning Space: hr=0x%8lx", hr );
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;
}
/*****************************************************************************
* Connect is called from Build to enumerate and connect pins
*****************************************************************************/
HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
{
HRESULT hr = E_FAIL;
class localComPtr
{
public:
IPin* p_pin_upstream;
IPin* p_pin_downstream;
IEnumPins* p_pin_upstream_enum;
IEnumPins* p_pin_downstream_enum;
IPin* p_pin_temp;
localComPtr(): p_pin_upstream(NULL), p_pin_downstream(NULL),
p_pin_upstream_enum(NULL), p_pin_downstream_enum(NULL),
p_pin_temp(NULL) { };
~localComPtr()
{
if( p_pin_upstream )
p_pin_upstream->Release();
if( p_pin_downstream )
p_pin_downstream->Release();
if( p_pin_upstream_enum )
p_pin_upstream_enum->Release();
if( p_pin_downstream_enum )
p_pin_downstream_enum->Release();
if( p_pin_temp )
p_pin_temp->Release();
}
} l;
PIN_INFO pin_info_upstream;
PIN_INFO pin_info_downstream;
hr = p_upstream->EnumPins( &l.p_pin_upstream_enum );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Connect: "\
"Cannot get upstream filter enumerator: hr=0x%8lx", hr );
return hr;
}
while( l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 ) == S_OK )
{
hr = l.p_pin_upstream->QueryPinInfo( &pin_info_upstream );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Connect: "\
"Cannot get upstream filter pin information: hr=0x%8lx", hr );
return hr;
}
hr = l.p_pin_upstream->ConnectedTo( &l.p_pin_downstream );
if( hr == S_OK )
l.p_pin_downstream->Release();
if(FAILED( hr ) && hr != VFW_E_NOT_CONNECTED )
{
msg_Warn( p_access, "Connect: "\
"Cannot check upstream filter connection: hr=0x%8lx", hr );
return hr;
}
if(( pin_info_upstream.dir == PINDIR_OUTPUT ) &&
( hr == VFW_E_NOT_CONNECTED ) )
{
/* The upstream pin is not yet connected so check each pin on the
* downstream filter */
hr = p_downstream->EnumPins( &l.p_pin_downstream_enum );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Connect: Cannot get "\
"downstream filter enumerator: hr=0x%8lx", hr );
return hr;
}
while( l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 )
== S_OK )
{
hr = l.p_pin_downstream->QueryPinInfo( &pin_info_downstream );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Connect: Cannot get "\
"downstream filter pin information: hr=0x%8lx", hr );
return hr;
}
hr = l.p_pin_downstream->ConnectedTo( &l.p_pin_temp );
if( hr == S_OK ) l.p_pin_temp->Release();
if( hr != VFW_E_NOT_CONNECTED )
{
if( FAILED( hr ) )
{
msg_Warn( p_access, "Connect: Cannot check "\
"downstream filter connection: hr=0x%8lx", hr );
return hr;
}
}
if(( pin_info_downstream.dir == PINDIR_INPUT ) &&
( hr == VFW_E_NOT_CONNECTED ) )
{
hr = p_filter_graph->ConnectDirect( l.p_pin_upstream,
l.p_pin_downstream, NULL );
if( SUCCEEDED( hr ) )
{
pin_info_downstream.pFilter->Release();
pin_info_upstream.pFilter->Release();
return S_OK;
}
}
/* If we fall out here it means this downstream pin was not
* suitable so try the next downstream pin */
l.p_pin_downstream = NULL;
pin_info_downstream.pFilter->Release();
}
}
/* If we fall out here it means we did not find any suitable downstream
* pin so try the next upstream pin */
l.p_pin_upstream = NULL;
pin_info_upstream.pFilter->Release();
}
/* If we fall out here it means we did not find any pair of suitable pins */
return E_FAIL;
}
/*****************************************************************************
* Start uses MediaControl to start the graph
*****************************************************************************/
HRESULT BDAGraph::Start()
{
HRESULT hr = S_OK;
OAFilterState i_state; /* State_Stopped, State_Paused, State_Running */
if( !p_media_control )
{
msg_Dbg( p_access, "Start: Media Control has not been created" );
return E_FAIL;
}
hr = p_media_control->Run();
if( hr == S_OK )
return hr;
/* Query the state of the graph - timeout after 100 milliseconds */
while( hr = p_media_control->GetState( 100, &i_state ) != S_OK )
{
if( FAILED( hr ) )
{
msg_Warn( p_access,
"Start: Cannot get Graph state: hr=0x%8lx", hr );
return hr;
}
}
if( i_state == State_Running )
return hr;
/* The Graph is not running so stop it and return an error */
hr = p_media_control->Stop();
if( FAILED( hr ) )
{
msg_Warn( p_access,
"Start: Cannot stop Graph after Run failed: hr=0x%8lx", hr );
return hr;
}
return E_FAIL;
}
/*****************************************************************************
* Read the stream of data - query the buffer size required
*****************************************************************************/
long BDAGraph::GetBufferSize()
{
while( queue_sample.empty() )
Sleep( 50 );
long l_buffer_size = 0;
long l_queue_size;
/* Establish the length of the queue as it grows quickly. If the queue
* size is checked dynamically there is a risk of not exiting the loop */
l_queue_size = queue_sample.size();
for( long l_queue_count=0; l_queue_count < l_queue_size; l_queue_count++ )
{
l_buffer_size += queue_sample.front()->GetActualDataLength();
queue_buffer.push( queue_sample.front() );
queue_sample.pop();
}
return l_buffer_size;
}
/*****************************************************************************
* Read the stream of data - Retrieve from the buffer queue
******************************************************************************/
long BDAGraph::ReadBuffer( long* pl_buffer_len, BYTE* p_buffer )
{
HRESULT hr = S_OK;
*pl_buffer_len = 0;
BYTE *p_buff_temp;
while( !queue_buffer.empty() )
{
queue_buffer.front()->GetPointer( &p_buff_temp );
hr = queue_buffer.front()->IsDiscontinuity();
if( hr == S_OK )
msg_Warn( p_access,
"BDA ReadBuffer: Sample Discontinuity. 0x%8lx", hr );
memcpy( p_buffer + *pl_buffer_len, p_buff_temp,
queue_buffer.front()->GetActualDataLength() );
*pl_buffer_len += queue_buffer.front()->GetActualDataLength();
queue_buffer.front()->Release();
queue_buffer.pop();
}
return *pl_buffer_len;
}
/******************************************************************************
* SampleCB - Callback when the Sample Grabber has a sample
******************************************************************************/
STDMETHODIMP BDAGraph::SampleCB( double d_time, IMediaSample *p_sample )
{
p_sample->AddRef();
queue_sample.push( p_sample );
return S_OK;
}
STDMETHODIMP BDAGraph::BufferCB( double d_time, BYTE* p_buffer,
long l_buffer_len )
{
return E_FAIL;
}
/******************************************************************************
* removes each filter from the graph
******************************************************************************/
HRESULT BDAGraph::Destroy()
{
HRESULT hr = S_OK;
if( p_media_control )
hr = p_media_control->Stop();
if( p_transport_info )
{
p_filter_graph->RemoveFilter( p_transport_info );
p_transport_info->Release();
p_transport_info = NULL;
}
if( p_mpeg_demux )
{
p_filter_graph->RemoveFilter( p_mpeg_demux );
p_mpeg_demux->Release();
p_mpeg_demux = NULL;
}
if( p_sample_grabber )
{
p_filter_graph->RemoveFilter( p_sample_grabber );
p_sample_grabber->Release();
p_sample_grabber = NULL;
}
if( p_capture_device )
{
p_filter_graph->RemoveFilter( p_capture_device );
p_capture_device->Release();
p_capture_device = NULL;
}
if( p_tuner_device )
{
p_filter_graph->RemoveFilter( p_tuner_device );
p_tuner_device->Release();
p_tuner_device = NULL;
}
if( p_network_provider )
{
p_filter_graph->RemoveFilter( p_network_provider );
p_network_provider->Release();
p_network_provider = NULL;
}
if( p_scanning_tuner )
{
p_scanning_tuner->Release();
p_scanning_tuner = NULL;
}
if( p_media_control )
{
p_media_control->Release();
p_media_control = NULL;
}
if( p_scanning_tuner )
{
p_filter_graph->Release();
p_filter_graph = NULL;
}
if( d_graph_register )
{
Deregister();
}
return S_OK;
}
/*****************************************************************************
* Add/Remove a DirectShow filter graph to/from the Running Object Table.
* Allows GraphEdit to "spy" on a remote filter graph.
******************************************************************************/
HRESULT BDAGraph::Register()
{
class localComPtr
{
public:
IMoniker* p_moniker;
IRunningObjectTable* p_ro_table;
localComPtr(): p_moniker(NULL), p_ro_table(NULL) {};
~localComPtr()
{
if( p_moniker )
p_moniker->Release();
if( p_ro_table )
p_ro_table->Release();
}
} l;
WCHAR psz_w_graph_name[128];
HRESULT hr;
hr = ::GetRunningObjectTable( 0, &l.p_ro_table );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Register: Cannot get ROT: hr=0x%8lx", hr );
return hr;
}
wsprintfW( psz_w_graph_name, L"VLC BDA Graph %08x Pid %08x",
(DWORD_PTR) p_filter_graph, ::GetCurrentProcessId() );
hr = CreateItemMoniker( L"!", psz_w_graph_name, &l.p_moniker );
if( SUCCEEDED( hr ) )
hr = l.p_ro_table->Register( ROTFLAGS_REGISTRATIONKEEPSALIVE,
p_filter_graph, l.p_moniker, &d_graph_register );
return hr;
}
void BDAGraph::Deregister()
{
IRunningObjectTable* p_ro_table;
if( SUCCEEDED( ::GetRunningObjectTable( 0, &p_ro_table ) ) )
p_ro_table->Revoke( d_graph_register );
d_graph_register = 0;
p_ro_table->Release();
}
/*****************************************************************************
* bdagraph.h : DirectShow BDA graph builder header for vlc
*****************************************************************************
* Copyright ( C ) 2007 the VideoLAN team
*
* Author: Ken Self <kens@campoz.fslife.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <queue>
using namespace std;
#ifndef _MSC_VER
# include <wtypes.h>
# include <unknwn.h>
# include <ole2.h>
# include <limits.h>
# ifdef _WINGDI_
# undef _WINGDI_
# endif
# define _WINGDI_ 1
# define AM_NOVTABLE
# define _OBJBASE_H_
# undef _X86_
# define _I64_MAX LONG_LONG_MAX
# define LONGLONG long long
#endif
#include <dshow.h>
#include <comcat.h>
#include "bdadefs.h"
#include "bda.h"
/* The main class for building the filter graph */
class BDAGraph : public ISampleGrabberCB
{
public:
BDAGraph( access_t* p_access );
virtual ~BDAGraph();
int SubmitATSCTuneRequest();
int SubmitDVBTTuneRequest();
int SubmitDVBCTuneRequest();
int SubmitDVBSTuneRequest();
long GetBufferSize();
long ReadBuffer( long* l_buffer_len, BYTE* p_buff );
private:
/* ISampleGrabberCB methods */
STDMETHODIMP_( ULONG ) AddRef( ) { return 1; }
STDMETHODIMP_( ULONG ) Release( ) { return 2; }
STDMETHODIMP QueryInterface( REFIID riid, void** p_p_object )
{return E_NOTIMPL; }
STDMETHODIMP SampleCB( double d_time, IMediaSample* p_sample );
STDMETHODIMP BufferCB( double d_time, BYTE* p_buffer, long l_buffer_len );
access_t* p_access;
CLSID guid_network_type;
long l_tuner_used; /* Index of the Tuning Device */
/* registration number for the RunningObjectTable */
DWORD d_graph_register;
queue<IMediaSample*> queue_sample;
queue<IMediaSample*> queue_buffer;
IMediaControl* p_media_control;
IGraphBuilder* p_filter_graph;
ITuningSpace* p_tuning_space;
ITuneRequest* p_tune_request;
ICreateDevEnum* p_system_dev_enum;
IBaseFilter* p_network_provider;
IScanningTuner* p_scanning_tuner;
IBaseFilter* p_tuner_device;
IBaseFilter* p_capture_device;
IBaseFilter* p_sample_grabber;
IBaseFilter* p_mpeg_demux;
IBaseFilter* p_transport_info;
ISampleGrabber* p_grabber;
HRESULT CreateTuneRequest( );
HRESULT Build( );
HRESULT FindFilter( REFCLSID clsid, long* i_moniker_used,
IBaseFilter* p_upstream, IBaseFilter** p_p_downstream );
HRESULT Connect( IBaseFilter* p_filter_upstream,
IBaseFilter* p_filter_downstream );
HRESULT Start( );
HRESULT Destroy( );
HRESULT Register( );
void Deregister( );
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment