X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fdshow%2Fdshow.cpp;h=4dc2d95f6dc2f4793384a01c6f9fc40e7d9433fe;hb=bc09c365ab435fda0185e60a423f69d6dfa348c8;hp=79c77f642aaba39a94e9363db8a42e3d1455a057;hpb=7f12470415d98e9e0ac725f2bb96b5fa74ef27f1;p=vlc diff --git a/modules/access/dshow/dshow.cpp b/modules/access/dshow/dshow.cpp index 79c77f642a..4dc2d95f6d 100644 --- a/modules/access/dshow/dshow.cpp +++ b/modules/access/dshow/dshow.cpp @@ -1,7 +1,7 @@ /***************************************************************************** - * dshow.cpp : DirectShow access module for vlc + * dshow.cpp : DirectShow access and access_demux 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,16 +30,18 @@ # include "config.h" #endif +#define __STDC_CONSTANT_MACROS 1 #define __STDC_FORMAT_MACROS 1 +#define CFG_PREFIX "dshow-" #include #include #include -#include #include #include -#include -#include + +#include /* dialog_Fatal */ +#include /* FromWide */ #include "common.h" #include "filter.h" @@ -79,22 +81,50 @@ static void ConfigTuner( vlc_object_t *, ICaptureGraphBuilder2 *, *****************************************************************************/ static const char *const ppsz_vdev[] = { "", "none" }; static const char *const ppsz_vdev_text[] = { N_("Default"), N_("None") }; + static const char *const ppsz_adev[] = { "", "none" }; static const char *const ppsz_adev_text[] = { N_("Default"), N_("None") }; + static const int pi_tuner_input[] = { 0, 1, 2 }; static const char *const ppsz_tuner_input_text[] = {N_("Default"), N_("Cable"), N_("Antenna")}; + static const int pi_amtuner_mode[] = { AMTUNER_MODE_DEFAULT, - AMTUNER_MODE_TV, - AMTUNER_MODE_FM_RADIO, - AMTUNER_MODE_AM_RADIO, - AMTUNER_MODE_DSS }; + AMTUNER_MODE_TV, + AMTUNER_MODE_FM_RADIO, + AMTUNER_MODE_AM_RADIO, + AMTUNER_MODE_DSS }; static const char *const ppsz_amtuner_mode_text[] = { N_("Default"), N_("TV"), N_("FM radio"), N_("AM radio"), N_("DSS") }; +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" + }; + #define CACHING_TEXT N_("Caching value in ms") #define CACHING_LONGTEXT N_( \ "Caching value for DirectShow streams. " \ @@ -114,6 +144,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 " \ @@ -133,6 +165,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 " \ @@ -187,60 +223,69 @@ vlc_module_begin () set_description( N_("DirectShow input") ) set_category( CAT_INPUT ) set_subcategory( SUBCAT_INPUT_ACCESS ) - add_integer( "dshow-caching", (mtime_t)(0.2*CLOCK_FREQ) / 1000, NULL, + add_integer( CFG_PREFIX "caching", (mtime_t)(0.2*CLOCK_FREQ) / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, true ) - add_string( "dshow-vdev", NULL, NULL, VDEV_TEXT, VDEV_LONGTEXT, false) + add_string( CFG_PREFIX "vdev", NULL, NULL, VDEV_TEXT, VDEV_LONGTEXT, false) change_string_list( ppsz_vdev, ppsz_vdev_text, FindDevicesCallback ) change_action_add( FindDevicesCallback, N_("Refresh list") ) change_action_add( ConfigDevicesCallback, N_("Configure") ) - add_string( "dshow-adev", NULL, NULL, ADEV_TEXT, ADEV_LONGTEXT, false) + add_string( CFG_PREFIX "adev", NULL, NULL, ADEV_TEXT, ADEV_LONGTEXT, false) change_string_list( ppsz_adev, ppsz_adev_text, FindDevicesCallback ) change_action_add( FindDevicesCallback, N_("Refresh list") ) change_action_add( ConfigDevicesCallback, N_("Configure") ) - add_string( "dshow-size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, false) + add_string( CFG_PREFIX "size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, false) + + add_string( CFG_PREFIX "aspect-ratio", "4:3", NULL, ASPECT_TEXT, ASPECT_LONGTEXT, false) + + add_string( CFG_PREFIX "chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true ) - add_string( "dshow-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true ) + add_float( CFG_PREFIX "fps", 0.0f, NULL, FPS_TEXT, FPS_LONGTEXT, true ) - add_float( "dshow-fps", 0.0f, NULL, FPS_TEXT, FPS_LONGTEXT, true ) + add_bool( CFG_PREFIX "config", false, NULL, CONFIG_TEXT, CONFIG_LONGTEXT, true ) - add_bool( "dshow-config", false, NULL, CONFIG_TEXT, CONFIG_LONGTEXT, true ) + add_bool( CFG_PREFIX "tuner", false, NULL, TUNER_TEXT, TUNER_LONGTEXT, true ) - add_bool( "dshow-tuner", false, NULL, TUNER_TEXT, TUNER_LONGTEXT, true ) + add_integer( CFG_PREFIX "tuner-channel", 0, NULL, CHANNEL_TEXT, CHANNEL_LONGTEXT, + true ) - add_integer( "dshow-tuner-channel", 0, NULL, CHANNEL_TEXT, CHANNEL_LONGTEXT, + add_integer( CFG_PREFIX "tuner-frequency", 0, NULL, TVFREQ_TEXT, TVFREQ_LONGTEXT, true ) - add_integer( "dshow-tuner-country", 0, NULL, COUNTRY_TEXT, COUNTRY_LONGTEXT, + add_integer( CFG_PREFIX "tuner-country", 0, NULL, COUNTRY_TEXT, COUNTRY_LONGTEXT, true ) - add_integer( "dshow-tuner-input", 0, NULL, TUNER_INPUT_TEXT, + add_integer( CFG_PREFIX "tuner-standard", 0, NULL, STANDARD_TEXT, STANDARD_LONGTEXT, + false ) + change_integer_list( i_standards_list, ppsz_standards_list_text, NULL ) + + add_integer( CFG_PREFIX "tuner-input", 0, NULL, TUNER_INPUT_TEXT, TUNER_INPUT_LONGTEXT, true ) change_integer_list( pi_tuner_input, ppsz_tuner_input_text, NULL ) - add_integer( "dshow-video-input", -1, NULL, VIDEO_IN_TEXT, + add_integer( CFG_PREFIX "video-input", -1, NULL, VIDEO_IN_TEXT, VIDEO_IN_LONGTEXT, true ) - add_integer( "dshow-video-output", -1, NULL, VIDEO_OUT_TEXT, + add_integer( CFG_PREFIX "video-output", -1, NULL, VIDEO_OUT_TEXT, VIDEO_OUT_LONGTEXT, true ) - add_integer( "dshow-audio-input", -1, NULL, AUDIO_IN_TEXT, + add_integer( CFG_PREFIX "audio-input", -1, NULL, AUDIO_IN_TEXT, AUDIO_IN_LONGTEXT, true ) - add_integer( "dshow-audio-output", -1, NULL, AUDIO_OUT_TEXT, + add_integer( CFG_PREFIX "audio-output", -1, NULL, AUDIO_OUT_TEXT, AUDIO_OUT_LONGTEXT, true ) - add_integer( "dshow-amtuner-mode", AMTUNER_MODE_TV, NULL, + add_integer( CFG_PREFIX "amtuner-mode", AMTUNER_MODE_TV, NULL, AMTUNER_MODE_TEXT, AMTUNER_MODE_LONGTEXT, false) change_integer_list( pi_amtuner_mode, ppsz_amtuner_mode_text, NULL ) - add_integer( "dshow-audio-channels", 0, NULL, AUDIO_CHANNELS_TEXT, + add_integer( CFG_PREFIX "audio-channels", 0, NULL, AUDIO_CHANNELS_TEXT, AUDIO_CHANNELS_LONGTEXT, true ) - add_integer( "dshow-audio-samplerate", 0, NULL, AUDIO_SAMPLERATE_TEXT, + add_integer( CFG_PREFIX "audio-samplerate", 0, NULL, AUDIO_SAMPLERATE_TEXT, AUDIO_SAMPLERATE_LONGTEXT, true ) - add_integer( "dshow-audio-bitspersample", 0, NULL, AUDIO_BITSPERSAMPLE_TEXT, + add_integer( CFG_PREFIX "audio-bitspersample", 0, NULL, AUDIO_BITSPERSAMPLE_TEXT, AUDIO_BITSPERSAMPLE_LONGTEXT, true ) add_shortcut( "dshow" ) @@ -255,6 +300,7 @@ vlc_module_begin () vlc_module_end () + /***************************************************************************** * DirectShow elementary stream descriptor *****************************************************************************/ @@ -343,8 +389,7 @@ 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; @@ -356,47 +401,54 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, /* Initialize OLE/COM */ CoInitialize( 0 ); - 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 ) + var_Create( p_this, CFG_PREFIX "config", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "tuner", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); + psz_val = var_CreateGetString( p_this, CFG_PREFIX "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, CFG_PREFIX "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 ); - - static struct {const char *psz_size; int i_width; int i_height;} size_table[] = - { { "subqcif", 128, 96 }, { "qsif", 160, 120 }, { "qcif", 176, 144 }, - { "sif", 320, 240 }, { "cif", 352, 288 }, { "d1", 640, 480 }, + free( psz_val ); + + /* DShow Size */ + static struct { + const char *psz_size; + int i_width; + int i_height; + } size_table[] = + { { "subqcif", 128, 96 }, + { "qsif", 160, 120 }, + { "qcif", 176, 144 }, + { "sif", 320, 240 }, + { "cif", 352, 288 }, + { "d1", 640, 480 }, { 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, CFG_PREFIX "size" ); + if( !EMPTY_STR(psz_val) ) { + int i; 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 +458,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,33 +466,36 @@ 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 ); - - p_sys->b_chroma = false; - var_Create( p_this, "dshow-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Get( p_this, "dshow-chroma", &val ); + free( psz_val ); - i_chroma = vlc_fourcc_GetCodecFromString( UNKNOWN_ES, val.psz_string ); + /* Chroma */ + psz_val = var_CreateGetString( p_this, CFG_PREFIX "chroma" ); + i_chroma = vlc_fourcc_GetCodecFromString( UNKNOWN_ES, psz_val ); p_sys->b_chroma = i_chroma != 0; - free( val.psz_string ); + free( psz_val ); - var_Create( p_this, "dshow-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-tuner-channel", + var_Create( p_this, CFG_PREFIX "fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "tuner-channel", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-tuner-country", + var_Create( p_this, CFG_PREFIX "tuner-frequency", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-tuner-input", + var_Create( p_this, CFG_PREFIX "tuner-standard", + VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "tuner-country", + VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "tuner-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-amtuner-mode", + var_Create( p_this, CFG_PREFIX "amtuner-mode", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + + var_Create( p_this, CFG_PREFIX "video-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "audio-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "video-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Create( p_this, CFG_PREFIX "audio-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-video-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_this, "dshow-audio-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - 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; @@ -509,8 +564,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, CFG_PREFIX "tuner" ) ) { /* FIXME: we do MEDIATYPE_Stream here so we don't do * it twice. */ @@ -542,20 +596,20 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, return VLC_EGENERIC ; } - for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) + for( int 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, CFG_PREFIX "video-input" ); + if( i_val >= 0 ) + p_sys->crossbar_routes[i].VideoInputIndex = i_val; + i_val = var_GetInteger( p_this, CFG_PREFIX "video-output" ); + if( i_val >= 0 ) + p_sys->crossbar_routes[i].VideoOutputIndex = i_val; + i_val = var_GetInteger( p_this, CFG_PREFIX "audio-input" ); + if( i_val >= 0 ) + p_sys->crossbar_routes[i].AudioInputIndex = i_val; + i_val = var_GetInteger( p_this, CFG_PREFIX "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; @@ -588,10 +642,9 @@ 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, CFG_PREFIX "config" ) ) { - for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) + for( int i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) { IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar; IBaseFilter *p_XF; @@ -620,7 +673,6 @@ static int DemuxOpen( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t *)p_this; access_sys_t *p_sys; - int i; p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) ); if( !p_sys ) @@ -643,18 +695,32 @@ static int DemuxOpen( vlc_object_t *p_this ) p_demux->info.i_title = 0; p_demux->info.i_seekpoint = 0; - for( i = 0; i < p_sys->i_streams; i++ ) + for( int i = 0; i < p_sys->i_streams; i++ ) { dshow_stream_t *p_stream = p_sys->pp_streams[i]; es_format_t fmt; if( p_stream->mt.majortype == MEDIATYPE_Video ) { + char *psz_aspect = var_CreateGetString( p_this, CFG_PREFIX "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 ) { @@ -665,10 +731,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 ) @@ -980,9 +1048,9 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, size_t media_count = EnumDeviceCaps( p_this, p_device_filter, b_audio ? 0 : p_sys->i_chroma, p_sys->i_width, p_sys->i_height, - b_audio ? var_CreateGetInteger( p_this, "dshow-audio-channels" ) : 0, - b_audio ? var_CreateGetInteger( p_this, "dshow-audio-samplerate" ) : 0, - b_audio ? var_CreateGetInteger( p_this, "dshow-audio-bitspersample" ) : 0, + b_audio ? var_CreateGetInteger( p_this, CFG_PREFIX "audio-channels" ) : 0, + b_audio ? var_CreateGetInteger( p_this, CFG_PREFIX "audio-samplerate" ) : 0, + b_audio ? var_CreateGetInteger( p_this, CFG_PREFIX "audio-bitspersample" ) : 0, media_types, MAX_MEDIA_TYPES ); AM_MEDIA_TYPE *mt = NULL; @@ -1053,9 +1121,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, CFG_PREFIX "config" ) ) { ShowDeviceProperties( p_this, p_sys->p_capture_graph_builder2, p_device_filter, b_audio ); @@ -1064,8 +1130,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, CFG_PREFIX "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, @@ -1110,8 +1176,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; @@ -1251,8 +1317,8 @@ FindCaptureDevice( vlc_object_t *p_this, string *p_devicename, p_class_enum->Release(); if( p_listdevices ) { - devicelist.sort(); - *p_listdevices = devicelist; + devicelist.sort(); + *p_listdevices = devicelist; } return NULL; } @@ -1269,7 +1335,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, size_t mt_count = 0; LONGLONG i_AvgTimePerFrame = 0; - float r_fps = var_GetFloat( p_this, "dshow-fps" ); + float r_fps = var_GetFloat( p_this, CFG_PREFIX "fps" ); if( r_fps ) i_AvgTimePerFrame = 10000000000LL/(LONGLONG)(r_fps*1000.0f); @@ -1467,7 +1533,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, continue; } pWfx->nSamplesPerSec = val; - + val = i_bitspersample; if( ! val ) { @@ -1479,7 +1545,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, if( ( !pASCC->BitsPerSampleGranularity && (unsigned int)val != pASCC->MinimumBitsPerSample - && (unsigned int)val != pASCC->MaximumBitsPerSample ) + && (unsigned int)val != pASCC->MaximumBitsPerSample ) || ( pASCC->BitsPerSampleGranularity && ((val % pASCC->BitsPerSampleGranularity) @@ -1654,7 +1720,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, // return alternative media type AM_MEDIA_TYPE mtr; VIDEOINFOHEADER vh; - + mtr.majortype = MEDIATYPE_Video; mtr.subtype = MEDIASUBTYPE_I420; mtr.bFixedSizeSamples = TRUE; @@ -1663,9 +1729,9 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, mtr.formattype = FORMAT_VideoInfo; mtr.cbFormat = sizeof(vh); mtr.pbFormat = (BYTE *)&vh; - + memset(&vh, 0, sizeof(vh)); - + vh.bmiHeader.biSize = sizeof(vh.bmiHeader); vh.bmiHeader.biWidth = i_width > 0 ? i_width : ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biWidth; @@ -1677,7 +1743,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, vh.bmiHeader.biSizeImage = vh.bmiHeader.biWidth * 12 * vh.bmiHeader.biHeight / 8; mtr.lSampleSize = vh.bmiHeader.biSizeImage; - + msg_Dbg( p_this, "EnumDeviceCaps: input pin media: using 'I420' in place of unsupported format 'HCW2'"); if( SUCCEEDED(CopyMediaType(mt+mt_count, &mtr)) ) @@ -1716,7 +1782,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 ); @@ -1762,7 +1828,6 @@ static block_t *ReadCompressed( access_t *p_access ) static int Demux( demux_t *p_demux ) { access_sys_t *p_sys = (access_sys_t *)p_demux->p_sys; - int i_stream; int i_found_samples; i_found_samples = 0; @@ -1771,7 +1836,7 @@ static int Demux( demux_t *p_demux ) while ( !i_found_samples ) { /* Try to grab samples from all streams */ - for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) + for( int i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) { dshow_stream_t *p_stream = p_sys->pp_streams[i_stream]; if( p_stream->p_capture_filter && @@ -1795,7 +1860,7 @@ static int Demux( demux_t *p_demux ) vlc_mutex_unlock( &p_sys->lock ); - for ( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) + for ( int i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) { int i_samples; dshow_stream_t *p_stream = p_sys->pp_streams[i_stream]; @@ -1855,9 +1920,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 ) { @@ -1873,7 +1937,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, CFG_PREFIX "caching" ) * 1000; break; /* */ @@ -1897,8 +1961,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 ) { @@ -1913,7 +1977,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, CFG_PREFIX "caching" ) * 1000; return VLC_SUCCESS; case DEMUX_GET_TIME: @@ -1942,7 +2006,7 @@ static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name, p_item = config_FindConfig( p_this, psz_name ); if( !p_item ) return VLC_SUCCESS; - if( !strcmp( psz_name, "dshow-adev" ) ) b_audio = true; + if( !strcmp( psz_name, CFG_PREFIX "adev" ) ) b_audio = true; /* Clear-up the current list */ if( p_item->i_list ) @@ -1970,13 +2034,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; @@ -2001,20 +2063,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( !strcmp( psz_name, "dshow-adev" ) ) b_audio = true; + if( !p_item ) + { + free( psz_device ); + CoUninitialize(); + return VLC_SUCCESS; + } + + if( !strcmp( psz_name, CFG_PREFIX "adev" ) ) b_audio = true; string devicename; - if( newval.psz_string && *newval.psz_string ) + if( psz_device ) { - devicename = newval.psz_string; + devicename = psz_device ; } else { @@ -2023,7 +2096,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(); } @@ -2036,17 +2113,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; } /***************************************************************************** @@ -2194,22 +2269,25 @@ 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; if( !p_graph ) return; - i_channel = var_GetInteger( p_this, "dshow-tuner-channel" ); - 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_channel = var_GetInteger( p_this, CFG_PREFIX "tuner-channel" ); + i_country = var_GetInteger( p_this, CFG_PREFIX "tuner-country" ); + i_input = var_GetInteger( p_this, CFG_PREFIX "tuner-input" ); + i_amtuner_mode = var_GetInteger( p_this, CFG_PREFIX "amtuner-mode" ); + i_frequency = var_GetInteger( p_this, CFG_PREFIX "tuner-frequency" ); + i_standard = var_GetInteger( p_this, CFG_PREFIX "tuner-standard" ); + + if( !i_channel && !i_frequency && !i_country && !i_input ) return; /* Nothing to do */ - if( !i_channel && !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, @@ -2244,7 +2322,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(); }