X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fdshow%2Fdshow.cpp;h=b61769ef5a1d46be691ed80c037f4e07ce6951b9;hb=d475b82a023d7016dba778ea1110999c8c953277;hp=9a6cf7cd3bfd3f63b2c5cea64f5615fc7546cf02;hpb=ec6a7b8ec1fc9f070d1d5242836b1d643f9f2dd8;p=vlc diff --git a/modules/access/dshow/dshow.cpp b/modules/access/dshow/dshow.cpp index 9a6cf7cd3b..b61769ef5a 100644 --- a/modules/access/dshow/dshow.cpp +++ b/modules/access/dshow/dshow.cpp @@ -1,7 +1,7 @@ /***************************************************************************** * dshow.cpp : DirectShow access module for vlc ***************************************************************************** - * Copyright (C) 2002, 2003 the VideoLAN team + * Copyright (C) 2002-2004, 2006, 2008, 2010 the VideoLAN team * $Id$ * * Author: Gildas Bazin @@ -30,6 +30,7 @@ # include "config.h" #endif +#define __STDC_CONSTANT_MACROS 1 #define __STDC_FORMAT_MACROS 1 #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include @@ -115,6 +115,8 @@ static const char *const ppsz_amtuner_mode_text[] = { N_("Default"), "Size of the video that will be displayed by the " \ "DirectShow plugin. If you don't specify anything the default size for " \ "your device will be used. You can specify a standard size (cif, d1, ...) or x.") +#define ASPECT_TEXT N_("Picture aspect-ratio n:m") +#define ASPECT_LONGTEXT N_("Define input picture aspect-ratio to use. Default is 4:3" ) #define CHROMA_TEXT N_("Video input chroma format") #define CHROMA_LONGTEXT N_( \ "Force the DirectShow video input to use a specific chroma format " \ @@ -134,6 +136,10 @@ static const char *const ppsz_amtuner_mode_text[] = { N_("Default"), #define CHANNEL_LONGTEXT N_( \ "Set the TV channel the tuner will set to " \ "(0 means default)." ) +#define TVFREQ_TEXT N_("Tuner Frequency") +#define TVFREQ_LONGTEXT N_( "This overrides the channel. Measured in Hz." ) +#define STANDARD_TEXT N_( "Standard" ) +#define STANDARD_LONGTEXT N_( "Video standard (Default, SECAM_D, PAL_B, NTSC_M, etc...)." ) #define COUNTRY_TEXT N_("Tuner country code") #define COUNTRY_LONGTEXT N_( \ "Set the tuner country code that establishes the current " \ @@ -174,6 +180,31 @@ static const char *const ppsz_amtuner_mode_text[] = { N_("Default"), #define AUDIO_BITSPERSAMPLE_LONGTEXT N_( \ "Select audio input format with the given bits/sample (if non 0)" ) +static const int i_standards_list[] = + { + KS_AnalogVideo_None, + KS_AnalogVideo_NTSC_M, KS_AnalogVideo_NTSC_M_J, KS_AnalogVideo_NTSC_433, + KS_AnalogVideo_PAL_B, KS_AnalogVideo_PAL_D, KS_AnalogVideo_PAL_G, + KS_AnalogVideo_PAL_H, KS_AnalogVideo_PAL_I, KS_AnalogVideo_PAL_M, + KS_AnalogVideo_PAL_N, KS_AnalogVideo_PAL_60, + KS_AnalogVideo_SECAM_B, KS_AnalogVideo_SECAM_D, KS_AnalogVideo_SECAM_G, + KS_AnalogVideo_SECAM_H, KS_AnalogVideo_SECAM_K, KS_AnalogVideo_SECAM_K1, + KS_AnalogVideo_SECAM_L, KS_AnalogVideo_SECAM_L1, + KS_AnalogVideo_PAL_N_COMBO + }; +static const char *const ppsz_standards_list_text[] = + { + N_("Default"), + "NTSC_M", "NTSC_M_J", "NTSC_443", + "PAL_B", "PAL_D", "PAL_G", + "PAL_H", "PAL_I", "PAL_M", + "PAL_N", "PAL_60", + "SECAM_B", "SECAM_D", "SECAM_G", + "SECAM_H", "SECAM_K", "SECAM_K1", + "SECAM_L", "SECAM_L1", + "PAL_N_COMBO" + }; + static int CommonOpen ( vlc_object_t *, access_sys_t *, bool ); static void CommonClose( vlc_object_t *, access_sys_t * ); @@ -203,6 +234,8 @@ vlc_module_begin () add_string( "dshow-size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, false) + add_string( "dshow-aspect-ratio", "4:3", NULL, ASPECT_TEXT, ASPECT_LONGTEXT, false) + add_string( "dshow-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true ) add_float( "dshow-fps", 0.0f, NULL, FPS_TEXT, FPS_LONGTEXT, true ) @@ -214,9 +247,16 @@ vlc_module_begin () add_integer( "dshow-tuner-channel", 0, NULL, CHANNEL_TEXT, CHANNEL_LONGTEXT, true ) + add_integer( "dshow-tuner-frequency", 0, NULL, TVFREQ_TEXT, TVFREQ_LONGTEXT, + true ) + add_integer( "dshow-tuner-country", 0, NULL, COUNTRY_TEXT, COUNTRY_LONGTEXT, true ) + add_integer( "dshow-tuner-standard", 0, NULL, STANDARD_TEXT, STANDARD_LONGTEXT, + false ) + change_integer_list( i_standards_list, ppsz_standards_list_text, NULL ) + add_integer( "dshow-tuner-input", 0, NULL, TUNER_INPUT_TEXT, TUNER_INPUT_LONGTEXT, true ) change_integer_list( pi_tuner_input, ppsz_tuner_input_text, NULL ) @@ -256,6 +296,7 @@ vlc_module_begin () vlc_module_end () + /***************************************************************************** * DirectShow elementary stream descriptor *****************************************************************************/ @@ -344,12 +385,13 @@ static void DeleteDirectShowGraph( access_sys_t *p_sys ) static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, bool b_access_demux ) { - vlc_value_t val; int i; + char *psz_val; /* Get/parse options and open device(s) */ string vdevname, adevname; - int i_width = 0, i_height = 0, i_chroma = 0; + int i_width = 0, i_height = 0; + vlc_fourcc_t i_chroma = 0; bool b_use_audio = true; bool b_use_video = true; @@ -358,31 +400,29 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, var_Create( p_this, "dshow-config", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_this, "dshow-tuner", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-vdev", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Get( p_this, "dshow-vdev", &val ); - if( val.psz_string ) + psz_val = var_CreateGetString( p_this, "dshow-vdev" ); + if( psz_val ) { - msg_Dbg( p_this, "dshow-vdev: %s", val.psz_string ) ; + msg_Dbg( p_this, "dshow-vdev: %s", psz_val ) ; /* skip none device */ - if ( strncasecmp( val.psz_string, "none", 4 ) != 0 ) - vdevname = string( val.psz_string ); + if ( strncasecmp( psz_val, "none", 4 ) != 0 ) + vdevname = string( psz_val ); else b_use_video = false ; } - free( val.psz_string ); + free( psz_val ); - var_Create( p_this, "dshow-adev", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Get( p_this, "dshow-adev", &val ); - if( val.psz_string ) + psz_val = var_CreateGetString( p_this, "dshow-adev" ); + if( psz_val ) { - msg_Dbg( p_this, "dshow-adev: %s", val.psz_string ) ; + msg_Dbg( p_this, "dshow-adev: %s", psz_val ) ; /* skip none device */ - if ( strncasecmp( val.psz_string, "none", 4 ) != 0 ) - adevname = string( val.psz_string ); + if ( strncasecmp( psz_val, "none", 4 ) != 0 ) + adevname = string( psz_val ); else b_use_audio = false ; } - free( val.psz_string ); + free( psz_val ); static struct {const char *psz_size; int i_width; int i_height;} size_table[] = { { "subqcif", 128, 96 }, { "qsif", 160, 120 }, { "qcif", 176, 144 }, @@ -390,13 +430,12 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, { 0, 0, 0 }, }; - var_Create( p_this, "dshow-size", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Get( p_this, "dshow-size", &val ); - if( val.psz_string && *val.psz_string ) + psz_val = var_CreateGetString( p_this, "dshow-size" ); + if( !EMPTY_STR(psz_val) ) { for( i = 0; size_table[i].psz_size; i++ ) { - if( !strcmp( val.psz_string, size_table[i].psz_size ) ) + if( !strcmp( psz_val, size_table[i].psz_size ) ) { i_width = size_table[i].i_width; i_height = size_table[i].i_height; @@ -406,7 +445,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, if( !size_table[i].psz_size ) /* Try to parse "WidthxHeight" */ { char *psz_parser; - i_width = strtol( val.psz_string, &psz_parser, 0 ); + i_width = strtol( psz_val, &psz_parser, 0 ); if( *psz_parser == 'x' || *psz_parser == 'X') { i_height = strtol( psz_parser + 1, &psz_parser, 0 ); @@ -414,23 +453,20 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, msg_Dbg( p_this, "width x height %dx%d", i_width, i_height ); } } - free( val.psz_string ); + free( psz_val ); - p_sys->b_chroma = false; - var_Create( p_this, "dshow-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Get( p_this, "dshow-chroma", &val ); - if( val.psz_string && strlen( val.psz_string ) >= 4 ) - { - i_chroma = vlc_fourcc_GetCodec( UNKNOWN_ES, - VLC_FOURCC( val.psz_string[0], val.psz_string[1], - val.psz_string[2], val.psz_string[3] ) ); - p_sys->b_chroma = true; - } - free( val.psz_string ); + psz_val = var_CreateGetString( p_this, "dshow-chroma" ); + i_chroma = vlc_fourcc_GetCodecFromString( UNKNOWN_ES, psz_val ); + p_sys->b_chroma = i_chroma != 0; + free( psz_val ); var_Create( p_this, "dshow-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); var_Create( p_this, "dshow-tuner-channel", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, "dshow-tuner-frequency", + VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, "dshow-tuner-standard", + VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_this, "dshow-tuner-country", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_this, "dshow-tuner-input", @@ -446,6 +482,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, var_Create( p_this, "dshow-video-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_this, "dshow-audio-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + /* Initialize some data */ p_sys->i_streams = 0; p_sys->pp_streams = NULL; @@ -513,8 +550,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, return VLC_EGENERIC; } - var_Get( p_this, "dshow-tuner", &val ); - if( val.b_bool ) + if( var_GetBool( p_this, "dshow-tuner" ) ) { /* FIXME: we do MEDIATYPE_Stream here so we don't do * it twice. */ @@ -548,18 +584,18 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) { - var_Get( p_this, "dshow-video-input", &val ); - if( val.i_int >= 0 ) - p_sys->crossbar_routes[i].VideoInputIndex=val.i_int; - var_Get( p_this, "dshow-video-output", &val ); - if( val.i_int >= 0 ) - p_sys->crossbar_routes[i].VideoOutputIndex=val.i_int; - var_Get( p_this, "dshow-audio-input", &val ); - if( val.i_int >= 0 ) - p_sys->crossbar_routes[i].AudioInputIndex=val.i_int; - var_Get( p_this, "dshow-audio-output", &val ); - if( val.i_int >= 0 ) - p_sys->crossbar_routes[i].AudioOutputIndex=val.i_int; + int i_val = var_GetInteger( p_this, "dshow-video-input" ); + if( i_val >= 0 ) + p_sys->crossbar_routes[i].VideoInputIndex = i_val; + i_val = var_GetInteger( p_this, "dshow-video-output" ); + if( i_val >= 0 ) + p_sys->crossbar_routes[i].VideoOutputIndex = i_val; + i_val = var_GetInteger( p_this, "dshow-audio-input" ); + if( i_val >= 0 ) + p_sys->crossbar_routes[i].AudioInputIndex = i_val; + i_val = var_GetInteger( p_this, "dshow-audio-output" ); + if( i_val >= 0 ) + p_sys->crossbar_routes[i].AudioOutputIndex = i_val; IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar; LONG VideoInputIndex = p_sys->crossbar_routes[i].VideoInputIndex; @@ -592,8 +628,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, /* ** Show properties pages from other filters in graph */ - var_Get( p_this, "dshow-config", &val ); - if( val.b_bool ) + if( var_GetBool( p_this, "dshow-config" ) ) { for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) { @@ -654,11 +689,25 @@ static int DemuxOpen( vlc_object_t *p_this ) if( p_stream->mt.majortype == MEDIATYPE_Video ) { + char *psz_aspect = var_CreateGetString( p_this, "dshow-aspect-ratio" ); + char *psz_delim = !EMPTY_STR( psz_aspect ) ? strchr( psz_aspect, ':' ) : NULL; + es_format_Init( &fmt, VIDEO_ES, p_stream->i_fourcc ); fmt.video.i_width = p_stream->header.video.bmiHeader.biWidth; fmt.video.i_height = p_stream->header.video.bmiHeader.biHeight; - fmt.video.i_aspect = 4 * VOUT_ASPECT_FACTOR / 3; + + if( psz_delim ) + { + fmt.video.i_sar_num = atoi( psz_aspect ) * fmt.video.i_height; + fmt.video.i_sar_den = atoi( psz_delim + 1 ) * fmt.video.i_width; + } + else + { + fmt.video.i_sar_num = 4 * fmt.video.i_height; + fmt.video.i_sar_den = 3 * fmt.video.i_width; + } + free( psz_aspect ); if( !p_stream->header.video.bmiHeader.biCompression ) { @@ -669,10 +718,12 @@ static int DemuxOpen( vlc_object_t *p_this ) /* Setup rgb mask for RGB formats */ if( p_stream->i_fourcc == VLC_CODEC_RGB24 ) { - /* This is in BGR format */ - fmt.video.i_bmask = 0x00ff0000; + /* This is in RGB format + http://msdn.microsoft.com/en-us/library/dd407253%28VS.85%29.aspx?ppud=4 + */ + fmt.video.i_rmask = 0x00ff0000; fmt.video.i_gmask = 0x0000ff00; - fmt.video.i_rmask = 0x000000ff; + fmt.video.i_bmask = 0x000000ff; } if( p_stream->header.video.AvgTimePerFrame ) @@ -1057,9 +1108,7 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, /* Show Device properties. Done here so the VLC stream is setup with * the proper parameters. */ - vlc_value_t val; - var_Get( p_this, "dshow-config", &val ); - if( val.b_bool ) + if( var_GetBool( p_this, "dshow-config" ) ) { ShowDeviceProperties( p_this, p_sys->p_capture_graph_builder2, p_device_filter, b_audio ); @@ -1068,8 +1117,8 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, ConfigTuner( p_this, p_sys->p_capture_graph_builder2, p_device_filter ); - var_Get( p_this, "dshow-tuner", &val ); - if( val.b_bool && dshow_stream.mt.majortype != MEDIATYPE_Stream ) + if( var_GetBool( p_this, "dshow-tuner" ) && + dshow_stream.mt.majortype != MEDIATYPE_Stream ) { /* FIXME: we do MEDIATYPE_Stream later so we don't do it twice. */ ShowTunerProperties( p_this, p_sys->p_capture_graph_builder2, @@ -1114,8 +1163,8 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, dshow_stream.p_device_filter = p_device_filter; dshow_stream.p_capture_filter = p_capture_filter; - p_sys->pp_streams = (dshow_stream_t **)realloc( p_sys->pp_streams, - sizeof(dshow_stream_t *) * (p_sys->i_streams + 1) ); + p_sys->pp_streams = (dshow_stream_t **)xrealloc( p_sys->pp_streams, + sizeof(dshow_stream_t *) * (p_sys->i_streams + 1) ); p_sys->pp_streams[p_sys->i_streams] = new dshow_stream_t; *p_sys->pp_streams[p_sys->i_streams++] = dshow_stream; @@ -1720,7 +1769,7 @@ static block_t *ReadCompressed( access_t *p_access ) while( 1 ) { - if( !vlc_object_alive (p_access) || p_access->b_error ) return 0; + if( !vlc_object_alive (p_access) ) return NULL; /* Get new sample/frame from the elementary stream (blocking). */ vlc_mutex_lock( &p_sys->lock ); @@ -1859,9 +1908,8 @@ static int Demux( demux_t *p_demux ) *****************************************************************************/ static int AccessControl( access_t *p_access, int i_query, va_list args ) { - bool *pb_bool; - int *pi_int; - int64_t *pi_64; + bool *pb_bool; + int64_t *pi_64; switch( i_query ) { @@ -1877,7 +1925,7 @@ static int AccessControl( access_t *p_access, int i_query, va_list args ) /* */ case ACCESS_GET_PTS_DELAY: pi_64 = (int64_t*)va_arg( args, int64_t * ); - *pi_64 = (int64_t)var_GetInteger( p_access, "dshow-caching" ) * 1000; + *pi_64 = var_GetInteger( p_access, "dshow-caching" ) * 1000; break; /* */ @@ -1901,8 +1949,8 @@ static int AccessControl( access_t *p_access, int i_query, va_list args ) ****************************************************************************/ static int DemuxControl( demux_t *p_demux, int i_query, va_list args ) { - bool *pb; - int64_t *pi64; + bool *pb; + int64_t *pi64; switch( i_query ) { @@ -1917,7 +1965,7 @@ static int DemuxControl( demux_t *p_demux, int i_query, va_list args ) case DEMUX_GET_PTS_DELAY: pi64 = (int64_t*)va_arg( args, int64_t * ); - *pi64 = (int64_t)var_GetInteger( p_demux, "dshow-caching" ) * 1000; + *pi64 = var_GetInteger( p_demux, "dshow-caching" ) * 1000; return VLC_SUCCESS; case DEMUX_GET_TIME: @@ -1974,13 +2022,11 @@ static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name, /* Uninitialize OLE/COM */ CoUninitialize(); - if( !list_devices.size() ) return VLC_SUCCESS; + if( list_devices.empty() ) return VLC_SUCCESS; - p_item->ppsz_list = - (char **)realloc( p_item->ppsz_list, + p_item->ppsz_list = (char**)xrealloc( p_item->ppsz_list, (list_devices.size()+3) * sizeof(char *) ); - p_item->ppsz_list_text = - (char **)realloc( p_item->ppsz_list_text, + p_item->ppsz_list_text = (char**)xrealloc( p_item->ppsz_list_text, (list_devices.size()+3) * sizeof(char *) ); list::iterator iter; @@ -2005,20 +2051,31 @@ static int ConfigDevicesCallback( vlc_object_t *p_this, char const *psz_name, { module_config_t *p_item; bool b_audio = false; + char *psz_device = NULL; + int i_ret = VLC_SUCCESS; + + if( !EMPTY_STR( newval.psz_string ) ) + psz_device = strdup( newval.psz_string ); /* Initialize OLE/COM */ CoInitialize( 0 ); p_item = config_FindConfig( p_this, psz_name ); - if( !p_item ) return VLC_SUCCESS; + + if( !p_item ) + { + free( psz_device ); + CoUninitialize(); + return VLC_SUCCESS; + } if( !strcmp( psz_name, "dshow-adev" ) ) b_audio = true; string devicename; - if( newval.psz_string && *newval.psz_string ) + if( psz_device ) { - devicename = newval.psz_string; + devicename = psz_device ; } else { @@ -2027,7 +2084,11 @@ static int ConfigDevicesCallback( vlc_object_t *p_this, char const *psz_name, /* Enumerate devices */ FindCaptureDevice( p_this, NULL, &list_devices, b_audio ); - if( !list_devices.size() ) return VLC_EGENERIC; + if( list_devices.empty() ) + { + CoUninitialize(); + return VLC_EGENERIC; + } devicename = *list_devices.begin(); } @@ -2040,17 +2101,15 @@ static int ConfigDevicesCallback( vlc_object_t *p_this, char const *psz_name, } else { - /* Uninitialize OLE/COM */ - CoUninitialize(); - msg_Err( p_this, "didn't find device: %s", devicename.c_str() ); - return VLC_EGENERIC; + i_ret = VLC_EGENERIC; } /* Uninitialize OLE/COM */ CoUninitialize(); - return VLC_SUCCESS; + free( psz_device ); + return i_ret; } /***************************************************************************** @@ -2198,7 +2257,7 @@ static void ShowTunerProperties( vlc_object_t *p_this, static void ConfigTuner( vlc_object_t *p_this, ICaptureGraphBuilder2 *p_graph, IBaseFilter *p_device_filter ) { - int i_channel, i_country, i_input, i_amtuner_mode; + int i_channel, i_country, i_input, i_amtuner_mode, i_standard, i_frequency; long l_modes = 0; IAMTVTuner *p_TV; HRESULT hr; @@ -2209,11 +2268,15 @@ static void ConfigTuner( vlc_object_t *p_this, ICaptureGraphBuilder2 *p_graph, i_country = var_GetInteger( p_this, "dshow-tuner-country" ); i_input = var_GetInteger( p_this, "dshow-tuner-input" ); i_amtuner_mode = var_GetInteger( p_this, "dshow-amtuner-mode" ); + i_frequency = var_GetInteger( p_this, "dshow-tuner-frequency" ); + i_standard = + i_standards_list[var_CreateGetInteger( p_this, "dshow-tuner-standard" )]; - if( !i_channel && !i_country && !i_input ) return; /* Nothing to do */ + if( !i_channel && !i_frequency && !i_country && !i_input ) return; /* Nothing to do */ + + msg_Dbg( p_this, "tuner config: channel %i, frequency %i, country %i, input type %i, standard %s", + i_channel, i_frequency, i_country, i_input, ppsz_standards_list_text[i_standard] ); - msg_Dbg( p_this, "tuner config: channel %i, country %i, input type %i", - i_channel, i_country, i_input ); hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, p_device_filter, IID_IAMTVTuner, @@ -2248,7 +2311,109 @@ static void ConfigTuner( vlc_object_t *p_this, ICaptureGraphBuilder2 *p_graph, else if( i_input == 2 ) p_TV->put_InputType( 0, TunerInputAntenna ); p_TV->put_CountryCode( i_country ); - p_TV->put_Channel( i_channel, AMTUNER_SUBCHAN_NO_TUNE, + + if( i_frequency <= 0 ) p_TV->put_Channel( i_channel, AMTUNER_SUBCHAN_NO_TUNE, AMTUNER_SUBCHAN_NO_TUNE ); + + if( i_frequency > 0 || i_standard > 0) { + IKsPropertySet *pKs = NULL; + DWORD dw_supported = 0; + KSPROPERTY_TUNER_MODE_CAPS_S ModeCaps; + KSPROPERTY_TUNER_FREQUENCY_S Frequency; + KSPROPERTY_TUNER_STANDARD_S Standard; + + hr = p_TV->QueryInterface(IID_IKsPropertySet,(void **)&pKs); + if (FAILED(hr)) + { + msg_Dbg( p_this, "Couldn't QI for IKsPropertySet" ); + p_TV->Release(); + return; + } + + memset(&ModeCaps,0,sizeof(KSPROPERTY_TUNER_MODE_CAPS_S)); + memset(&Frequency,0,sizeof(KSPROPERTY_TUNER_FREQUENCY_S)); + memset(&Standard,0,sizeof(KSPROPERTY_TUNER_STANDARD_S)); + ModeCaps.Mode = AMTUNER_MODE_TV; + + hr = pKs->QuerySupported(PROPSETID_TUNER, + KSPROPERTY_TUNER_MODE_CAPS,&dw_supported); + if(SUCCEEDED(hr) && dw_supported&KSPROPERTY_SUPPORT_GET) + { + DWORD cbBytes=0; + hr = pKs->Get(PROPSETID_TUNER,KSPROPERTY_TUNER_MODE_CAPS, + INSTANCEDATA_OF_PROPERTY_PTR(&ModeCaps), + INSTANCEDATA_OF_PROPERTY_SIZE(ModeCaps), + &ModeCaps, + sizeof(ModeCaps), + &cbBytes); + } + else + { + msg_Dbg( p_this, "KSPROPERTY_TUNER_MODE_CAPS not supported!" ); + goto free_on_error; + } + + msg_Dbg( p_this, "Frequency range supproted from %d to %d.", ModeCaps.MinFrequency, ModeCaps.MaxFrequency); + msg_Dbg( p_this, "Video standards supproted by the tuner: "); + for(int i = 0 ; i < ARRAY_SIZE(ppsz_standards_list_text); i++) { + if(ModeCaps.StandardsSupported & i_standards_list[i]) + msg_Dbg( p_this, "%s, ", ppsz_standards_list_text[i]); + } + + if(i_frequency > 0) { + Frequency.Frequency=i_frequency; + if(ModeCaps.Strategy==KS_TUNER_STRATEGY_DRIVER_TUNES) + Frequency.TuningFlags=KS_TUNER_TUNING_FINE; + else + Frequency.TuningFlags=KS_TUNER_TUNING_EXACT; + + if(i_frequency>=ModeCaps.MinFrequency && i_frequency<=ModeCaps.MaxFrequency) + { + + hr = pKs->Set(PROPSETID_TUNER, + KSPROPERTY_TUNER_FREQUENCY, + INSTANCEDATA_OF_PROPERTY_PTR(&Frequency), + INSTANCEDATA_OF_PROPERTY_SIZE(Frequency), + &Frequency, + sizeof(Frequency)); + if(FAILED(hr)) + { + msg_Dbg( p_this, "Couldn't set KSPROPERTY_TUNER_FREQUENCY!" ); + goto free_on_error; + } + } + else + { + msg_Dbg( p_this, "Requested frequency exceeds the supported range!" ); + goto free_on_error; + } + } + + if(i_standard > 0) { + if(i_standard & ModeCaps.StandardsSupported ) + { + Standard.Standard = i_standard; + hr = pKs->Set(PROPSETID_TUNER, + KSPROPERTY_TUNER_STANDARD, + INSTANCEDATA_OF_PROPERTY_PTR(&Standard), + INSTANCEDATA_OF_PROPERTY_SIZE(Standard), + &Standard, + sizeof(Standard)); + if(FAILED(hr)) + { + msg_Dbg( p_this, "Couldn't set KSPROPERTY_TUNER_STANDARD!" ); + goto free_on_error; + } + } + else + { + msg_Dbg( p_this, "Requested video standard is not supported by the tuner!" ); + goto free_on_error; + } + } +free_on_error: + pKs->Release(); + } + p_TV->Release(); }