X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fdshow%2Fdshow.cpp;h=a12a76c3480ce5f6524688a4075f8126d49b82de;hb=81280de6423c72be46b693ff3c842803d2d2798e;hp=e15745d95ad8e4b181151a0aa888216b798466e8;hpb=ee45d753f6a9d888fa953da05551201d5b2a6d16;p=vlc diff --git a/modules/access/dshow/dshow.cpp b/modules/access/dshow/dshow.cpp index e15745d95a..a12a76c348 100644 --- a/modules/access/dshow/dshow.cpp +++ b/modules/access/dshow/dshow.cpp @@ -33,12 +33,13 @@ #define __STDC_FORMAT_MACROS 1 #include -#include +#include +#include #include #include #include #include -#include +#include #include "common.h" #include "filter.h" @@ -76,19 +77,19 @@ static void ConfigTuner( vlc_object_t *, ICaptureGraphBuilder2 *, /***************************************************************************** * Module descriptor *****************************************************************************/ -static const char *ppsz_vdev[] = { "", "none" }; -static const char *ppsz_vdev_text[] = { N_("Default"), N_("None") }; -static const char *ppsz_adev[] = { "", "none" }; -static const char *ppsz_adev_text[] = { N_("Default"), N_("None") }; -static int pi_tuner_input[] = { 0, 1, 2 }; -static const char *ppsz_tuner_input_text[] = +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 }; -static const char *ppsz_amtuner_mode_text[] = { N_("Default"), +static const char *const ppsz_amtuner_mode_text[] = { N_("Default"), N_("TV"), N_("FM radio"), N_("AM radio"), @@ -97,7 +98,7 @@ static const char *ppsz_amtuner_mode_text[] = { N_("Default"), #define CACHING_TEXT N_("Caching value in ms") #define CACHING_LONGTEXT N_( \ "Caching value for DirectShow streams. " \ - "This value should be set in millisecondss." ) + "This value should be set in milliseconds." ) #define VDEV_TEXT N_("Video device name") #define VDEV_LONGTEXT N_( \ "Name of the video device that will be used by the " \ @@ -157,7 +158,20 @@ static const char *ppsz_amtuner_mode_text[] = { N_("Default"), #define AMTUNER_MODE_TEXT N_("AM Tuner mode") #define AMTUNER_MODE_LONGTEXT N_( \ - "AM Tuner mode. Can be one of DEFAULT, TV, AM_RADIO, FM_RADIO or DSS.") + "AM Tuner mode. Can be one of Default (0), TV (1)," \ + "AM Radio (2), FM Radio (3) or DSS (4).") + +#define AUDIO_CHANNELS_TEXT N_("Number of audio channels") +#define AUDIO_CHANNELS_LONGTEXT N_( \ + "Select audio input format with the given number of audio channels (if non 0)" ) + +#define AUDIO_SAMPLERATE_TEXT N_("Audio sample rate") +#define AUDIO_SAMPLERATE_LONGTEXT N_( \ + "Select audio input format with the given sample rate (if non 0)" ) + +#define AUDIO_BITSPERSAMPLE_TEXT N_("Audio bits per sample") +#define AUDIO_BITSPERSAMPLE_LONGTEXT N_( \ + "Select audio input format with the given bits/sample (if non 0)" ) static int CommonOpen ( vlc_object_t *, access_sys_t *, bool ); static void CommonClose( vlc_object_t *, access_sys_t * ); @@ -168,74 +182,77 @@ static void AccessClose( vlc_object_t * ); static int DemuxOpen ( vlc_object_t * ); static void DemuxClose ( vlc_object_t * ); -vlc_module_begin(); - set_shortname( _("DirectShow") ); - set_description( _("DirectShow input") ); - set_category( CAT_INPUT ); - set_subcategory( SUBCAT_INPUT_ACCESS ); +vlc_module_begin () + set_shortname( N_("DirectShow") ) + 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, - CACHING_TEXT, CACHING_LONGTEXT, true ); + CACHING_TEXT, CACHING_LONGTEXT, true ) - add_string( "dshow-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-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); - 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-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( "dshow-size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, false) - add_string( "dshow-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, - true ); + add_string( "dshow-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true ) - add_float( "dshow-fps", 0.0f, NULL, FPS_TEXT, FPS_LONGTEXT, - true ); + add_float( "dshow-fps", 0.0f, NULL, FPS_TEXT, FPS_LONGTEXT, true ) - add_bool( "dshow-config", false, NULL, CONFIG_TEXT, CONFIG_LONGTEXT, - true ); + add_bool( "dshow-config", false, NULL, CONFIG_TEXT, CONFIG_LONGTEXT, true ) - add_bool( "dshow-tuner", false, NULL, TUNER_TEXT, TUNER_LONGTEXT, - true ); + add_bool( "dshow-tuner", false, NULL, TUNER_TEXT, TUNER_LONGTEXT, true ) - add_integer( "dshow-tuner-channel", 0, NULL, CHANNEL_TEXT, - CHANNEL_LONGTEXT, true ); + add_integer( "dshow-tuner-channel", 0, NULL, CHANNEL_TEXT, CHANNEL_LONGTEXT, + true ) - add_integer( "dshow-tuner-country", 0, NULL, COUNTRY_TEXT, - COUNTRY_LONGTEXT, true ); + add_integer( "dshow-tuner-country", 0, NULL, COUNTRY_TEXT, COUNTRY_LONGTEXT, + true ) add_integer( "dshow-tuner-input", 0, NULL, TUNER_INPUT_TEXT, - TUNER_INPUT_LONGTEXT, true ); - change_integer_list( pi_tuner_input, ppsz_tuner_input_text, 0 ); + 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, - VIDEO_IN_LONGTEXT, true ); - - add_integer( "dshow-audio-input", -1, NULL, AUDIO_IN_TEXT, - AUDIO_IN_LONGTEXT, true ); + VIDEO_IN_LONGTEXT, true ) add_integer( "dshow-video-output", -1, NULL, VIDEO_OUT_TEXT, - VIDEO_OUT_LONGTEXT, true ); + VIDEO_OUT_LONGTEXT, true ) + + add_integer( "dshow-audio-input", -1, NULL, AUDIO_IN_TEXT, + AUDIO_IN_LONGTEXT, true ) add_integer( "dshow-audio-output", -1, NULL, AUDIO_OUT_TEXT, - AUDIO_OUT_LONGTEXT, true ); + AUDIO_OUT_LONGTEXT, true ) add_integer( "dshow-amtuner-mode", AMTUNER_MODE_TV, NULL, - AMTUNER_MODE_TEXT, AMTUNER_MODE_LONGTEXT, false); - change_integer_list( pi_amtuner_mode, ppsz_amtuner_mode_text, 0 ); + 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, + AUDIO_CHANNELS_LONGTEXT, true ) + add_integer( "dshow-audio-samplerate", 0, NULL, AUDIO_SAMPLERATE_TEXT, + AUDIO_SAMPLERATE_LONGTEXT, true ) + add_integer( "dshow-audio-bitspersample", 0, NULL, AUDIO_BITSPERSAMPLE_TEXT, + AUDIO_BITSPERSAMPLE_LONGTEXT, true ) - add_shortcut( "dshow" ); - set_capability( "access_demux", 0 ); - set_callbacks( DemuxOpen, DemuxClose ); + add_shortcut( "dshow" ) + set_capability( "access_demux", 0 ) + set_callbacks( DemuxOpen, DemuxClose ) - add_submodule(); - set_description( _("DirectShow input") ); - set_capability( "access", 0 ); - set_callbacks( AccessOpen, AccessClose ); + add_submodule () + set_description( N_("DirectShow input") ) + set_capability( "access", 0 ) + set_callbacks( AccessOpen, AccessClose ) -vlc_module_end(); +vlc_module_end () /***************************************************************************** * DirectShow elementary stream descriptor @@ -258,6 +275,8 @@ typedef struct dshow_stream_t es_out_id_t *p_es; bool b_pts; + + deque samples_queue; } dshow_stream_t; /***************************************************************************** @@ -329,21 +348,41 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, /* Get/parse options and open device(s) */ string vdevname, adevname; int i_width = 0, i_height = 0, i_chroma = 0; - bool b_audio = true; + bool b_use_audio = true; + bool b_use_video = true; + + /* 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 ) vdevname = string( val.psz_string ); + if( val.psz_string ) + { + msg_Dbg( p_this, "dshow-vdev: %s", val.psz_string ) ; + /* skip none device */ + if ( strncasecmp( val.psz_string, "none", 4 ) != 0 ) + vdevname = string( val.psz_string ); + else + b_use_video = false ; + } free( val.psz_string ); var_Create( p_this, "dshow-adev", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_this, "dshow-adev", &val ); - if( val.psz_string ) adevname = string( val.psz_string ); + if( val.psz_string ) + { + msg_Dbg( p_this, "dshow-adev: %s", val.psz_string ) ; + /* skip none device */ + if ( strncasecmp( val.psz_string, "none", 4 ) != 0 ) + adevname = string( val.psz_string ); + else + b_use_audio = false ; + } free( val.psz_string ); - static struct {char *psz_size; int i_width; int i_height;} size_table[] = + 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 }, @@ -404,12 +443,9 @@ 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 OLE/COM */ - CoInitialize( 0 ); - /* Initialize some data */ p_sys->i_streams = 0; - p_sys->pp_streams = 0; + p_sys->pp_streams = NULL; p_sys->i_width = i_width; p_sys->i_height = i_height; p_sys->i_chroma = i_chroma; @@ -418,17 +454,30 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, p_sys->p_capture_graph_builder2 = NULL; p_sys->p_control = NULL; - vlc_mutex_init( p_this, &p_sys->lock ); - vlc_cond_init( p_this, &p_sys->wait ); - /* Build directshow graph */ CreateDirectShowGraph( p_sys ); - if( OpenDevice( p_this, p_sys, vdevname, 0 ) != VLC_SUCCESS ) + vlc_mutex_init( &p_sys->lock ); + vlc_cond_init( &p_sys->wait ); + + if( !b_use_video && !b_use_audio ) { - msg_Err( p_this, "can't open video"); + dialog_Fatal( p_this, _("Capture failed"), + _("No video or audio device selected.") ); + return VLC_EGENERIC ; } - else + + if( !b_use_video ) + msg_Dbg( p_this, "skipping video device" ) ; + bool b_err_video = false ; + + if( b_use_video && OpenDevice( p_this, p_sys, vdevname, 0 ) != VLC_SUCCESS ) + { + msg_Err( p_this, "can't open video device"); + b_err_video = true ; + } + + if ( b_use_video && !b_err_video ) { /* Check if we can handle the demuxing ourselves or need to spawn * a demuxer module */ @@ -443,7 +492,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, /* Raw MPEG video stream */ p_stream->i_fourcc == VLC_FOURCC('m','p','2','v') ) { - b_audio = false; + b_use_audio = false; if( b_access_demux ) { @@ -455,7 +504,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, if( p_stream->mt.majortype == MEDIATYPE_Stream ) { - b_audio = false; + b_use_audio = false; if( b_access_demux ) { @@ -474,9 +523,26 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, } } - if( b_audio && OpenDevice( p_this, p_sys, adevname, 1 ) != VLC_SUCCESS ) + if( !b_use_audio ) + msg_Dbg( p_this, "skipping audio device") ; + + bool b_err_audio = false ; + + if( b_use_audio && OpenDevice( p_this, p_sys, adevname, 1 ) != VLC_SUCCESS ) { - msg_Err( p_this, "can't open audio"); + msg_Err( p_this, "can't open audio device"); + b_err_audio = true ; + } + + if( ( b_use_video && b_err_video && b_use_audio && b_err_audio ) || + ( !b_use_video && b_use_audio && b_err_audio ) || + ( b_use_video && !b_use_audio && b_err_video ) ) + { + msg_Err( p_this, "FATAL: could not open ANY device" ) ; + dialog_Fatal( p_this, _("Capture failed"), + _("VLC cannot open ANY capture device." + "Check the error log for details.") ); + return VLC_EGENERIC ; } for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) @@ -517,6 +583,9 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, } } } + else + msg_Err( p_this, "crossbar at depth %d could not route video " + "output %ld to input %ld", i, VideoOutputIndex, VideoInputIndex ); } /* @@ -556,8 +625,9 @@ static int DemuxOpen( vlc_object_t *p_this ) access_sys_t *p_sys; int i; - p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) ); - memset( p_sys, 0, sizeof( access_sys_t ) ); + p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) ); + if( !p_sys ) + return VLC_ENOMEM; p_demux->p_sys = (demux_sys_t *)p_sys; if( CommonOpen( p_this, p_sys, true ) != VLC_SUCCESS ) @@ -638,8 +708,9 @@ static int AccessOpen( vlc_object_t *p_this ) access_t *p_access = (access_t*)p_this; access_sys_t *p_sys; - p_access->p_sys = p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) ); - memset( p_sys, 0, sizeof( access_sys_t ) ); + p_access->p_sys = p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) ); + if( !p_sys ) + return VLC_ENOMEM; if( CommonOpen( p_this, p_sys, false ) != VLC_SUCCESS ) { @@ -656,11 +727,13 @@ static int AccessOpen( vlc_object_t *p_this ) p_stream->i_fourcc == VLC_FOURCC('d','v','s','d') || p_stream->i_fourcc == VLC_FOURCC('d','v','h','d') ) { + free( p_access->psz_demux ); p_access->psz_demux = strdup( "rawdv" ); } else if( p_stream->i_fourcc == VLC_FOURCC('m','p','2','v') ) { - p_access->psz_demux = "mpgv"; + free( p_access->psz_demux ); + p_access->psz_demux = strdup( "mpgv" ); } } @@ -755,16 +828,16 @@ static bool ConnectFilters( vlc_object_t *p_this, access_sys_t *p_sys, // Sort out all the possible video inputs // The class needs to be given the capture filters ANALOGVIDEO input pin - IEnumPins *pins = 0; + IEnumPins *pins = NULL; if( ( mediaType.majortype == MEDIATYPE_Video || mediaType.majortype == MEDIATYPE_Stream ) && SUCCEEDED(p_filter->EnumPins(&pins)) ) { - IPin *pP = 0; + IPin *pP = NULL; ULONG n; PIN_INFO pinInfo; BOOL Found = FALSE; - IKsPropertySet *pKs=0; + IKsPropertySet *pKs = NULL; GUID guid; DWORD dw; @@ -796,6 +869,9 @@ static bool ConnectFilters( vlc_object_t *p_this, access_sys_t *p_sys, pP->Release(); } pins->Release(); + msg_Dbg( p_this, "ConnectFilters: graph_builder2 available.") ; + if ( !Found ) + msg_Warn( p_this, "ConnectFilters: No crossBar routes found (incobatible pin types)" ) ; } return true; } @@ -871,7 +947,6 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, /* Enumerate devices and display their names */ FindCaptureDevice( p_this, NULL, &list_devices, b_audio ); - if( !list_devices.size() ) return VLC_EGENERIC; @@ -882,20 +957,24 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, /* If no device name was specified, pick the 1st one */ if( devicename.size() == 0 ) { + /* When none selected */ devicename = *list_devices.begin(); + msg_Dbg( p_this, "asking for default device: %s", devicename.c_str() ) ; } - + else + msg_Dbg( p_this, "asking for device: %s", devicename.c_str() ) ; // Use the system device enumerator and class enumerator to find // a capture/preview device, such as a desktop USB video camera. IBaseFilter *p_device_filter = - FindCaptureDevice( p_this, &devicename, 0, b_audio ); + FindCaptureDevice( p_this, &devicename, NULL, b_audio ); + if( p_device_filter ) msg_Dbg( p_this, "using device: %s", devicename.c_str() ); else { msg_Err( p_this, "can't use device: %s, unsupported device type", devicename.c_str() ); - intf_UserFatal( p_this, false, _("Capturing failed"), + dialog_Fatal( p_this, _("Capture failed"), _("VLC cannot use the device \"%s\", because its " "type is not supported.") ); return VLC_EGENERIC; @@ -906,7 +985,10 @@ 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, - 0, 0, 0, media_types, MAX_MEDIA_TYPES ); + 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, + media_types, MAX_MEDIA_TYPES ); AM_MEDIA_TYPE *mt = NULL; @@ -945,7 +1027,7 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, else { /* capture device */ msg_Err( p_this, "capture device '%s' does not support required parameters !", devicename.c_str() ); - intf_UserFatal( p_this, false, _("Capturing failed"), + dialog_Fatal( p_this, _("Capture failed"), _("The capture device \"%s\" does not support the " "required parameters."), devicename.c_str() ); p_device_filter->Release(); @@ -1054,6 +1136,11 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys, return VLC_EGENERIC; } +/* FindCaptureDevices:: This Function had two purposes : + Returns the list of capture devices when p_listdevices != NULL + Creates an IBaseFilter when p_devicename corresponds to an existing devname + These actions *may* be requested whith a single call. +*/ static IBaseFilter * FindCaptureDevice( vlc_object_t *p_this, string *p_devicename, list *p_listdevices, bool b_audio ) @@ -1094,7 +1181,7 @@ FindCaptureDevice( vlc_object_t *p_this, string *p_devicename, * CreateClassEnumerator will succeed, but p_class_enum will be NULL */ if( p_class_enum == NULL ) { - msg_Err( p_this, "no capture device was detected" ); + msg_Err( p_this, "no %s capture device was detected", ( b_audio ? "audio" : "video" ) ); return NULL; } @@ -1126,32 +1213,35 @@ FindCaptureDevice( vlc_object_t *p_this, string *p_devicename, SysFreeString(var.bstrVal); p_buf[i_convert] = '\0'; - string devname = string(p_buf); + string devname = string(p_buf); - int dup = 0; - /* find out if this name is already used by a previously found device */ - list::const_iterator iter = devicelist.begin(); - list::const_iterator end = devicelist.end(); - while ( iter != end ) - { - if( 0 == (*iter).compare(0, devname.size(), devname) ) - ++dup; - ++iter; - } - if( dup ) - { - /* we have a duplicate device name, append a sequence number to name - to provive a unique list back to the user */ - char seq[16]; - sprintf(seq, " #%d", dup); - devname.append(seq); - } - devicelist.push_back( devname ); + free( p_buf) ; + + int dup = 0; + /* find out if this name is already used by a previously found device */ + list::const_iterator iter = devicelist.begin(); + list::const_iterator end = devicelist.end(); + string ordevname = devname ; + while ( iter != end ) + { + if( 0 == (*iter).compare( devname ) ) + { /* devname is on the list. Try another name with sequence + number apended and then rescan until a unique entry is found*/ + char seq[16]; + snprintf(seq, 16, " #%d", ++dup); + devname = ordevname + seq; + iter = devicelist.begin(); + } + else + ++iter; + } + devicelist.push_back( devname ); if( p_devicename && *p_devicename == devname ) { - /* Bind Moniker to a filter object */ - hr = p_moniker->BindToObject( 0, 0, IID_IBaseFilter, + msg_Dbg( p_this, "asked for %s, binding to %s", p_devicename->c_str() , devname.c_str() ) ; + /* NULL possibly means we don't need BindMoniker BindCtx ?? */ + hr = p_moniker->BindToObject( NULL, 0, IID_IBaseFilter, (void **)&p_base_filter ); if( FAILED(hr) ) { @@ -1288,9 +1378,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, if( i_width ) { - if( i_width % pVSCC->OutputGranularityX - || pVSCC->MinOutputSize.cx > i_width - || i_width > pVSCC->MaxOutputSize.cx ) + if(( !pVSCC->OutputGranularityX + && i_width != pVSCC->MinOutputSize.cx + && i_width != pVSCC->MaxOutputSize.cx) + || + ( pVSCC->OutputGranularityX + && ((i_width % pVSCC->OutputGranularityX) + || pVSCC->MinOutputSize.cx > i_width + || i_width > pVSCC->MaxOutputSize.cx ))) { // required width not compatible, try next media type FreeMediaType( *p_mt ); @@ -1302,9 +1397,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, if( i_height ) { - if( i_height % pVSCC->OutputGranularityY - || pVSCC->MinOutputSize.cy > i_height - || i_height > pVSCC->MaxOutputSize.cy ) + if(( !pVSCC->OutputGranularityY + && i_height != pVSCC->MinOutputSize.cy + && i_height != pVSCC->MaxOutputSize.cy) + || + ( pVSCC->OutputGranularityY + && ((i_height % pVSCC->OutputGranularityY) + || pVSCC->MinOutputSize.cy > i_height + || i_height > pVSCC->MaxOutputSize.cy ))) { // required height not compatible, try next media type FreeMediaType( *p_mt ); @@ -1345,9 +1445,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, if( ! val ) val = 2; - if( val % pASCC->ChannelsGranularity - || (unsigned int)val < pASCC->MinimumChannels - || (unsigned int)val > pASCC->MaximumChannels ) + if( ( !pASCC->ChannelsGranularity + && (unsigned int)val != pASCC->MinimumChannels + && (unsigned int)val != pASCC->MaximumChannels) + || + ( pASCC->ChannelsGranularity + && ((val % pASCC->ChannelsGranularity) + || (unsigned int)val < pASCC->MinimumChannels + || (unsigned int)val > pASCC->MaximumChannels))) { // required number channels not available, try next media type FreeMediaType( *p_mt ); @@ -1360,9 +1465,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, if( ! val ) val = 44100; - if( val % pASCC->SampleFrequencyGranularity - || (unsigned int)val < pASCC->MinimumSampleFrequency - || (unsigned int)val > pASCC->MaximumSampleFrequency ) + if( ( !pASCC->SampleFrequencyGranularity + && (unsigned int)val != pASCC->MinimumSampleFrequency + && (unsigned int)val != pASCC->MaximumSampleFrequency) + || + ( pASCC->SampleFrequencyGranularity + && ((val % pASCC->SampleFrequencyGranularity) + || (unsigned int)val < pASCC->MinimumSampleFrequency + || (unsigned int)val > pASCC->MaximumSampleFrequency ))) { // required sampling rate not available, try next media type FreeMediaType( *p_mt ); @@ -1380,9 +1490,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, val = 16; } - if( val % pASCC->BitsPerSampleGranularity - || (unsigned int)val < pASCC->MinimumBitsPerSample - || (unsigned int)val > pASCC->MaximumBitsPerSample ) + if( ( !pASCC->BitsPerSampleGranularity + && (unsigned int)val != pASCC->MinimumBitsPerSample + && (unsigned int)val != pASCC->MaximumBitsPerSample ) + || + ( pASCC->BitsPerSampleGranularity + && ((val % pASCC->BitsPerSampleGranularity) + || (unsigned int)val < pASCC->MinimumBitsPerSample + || (unsigned int)val > pASCC->MaximumBitsPerSample ))) { // required sample size not available, try next media type FreeMediaType( *p_mt ); @@ -1516,7 +1631,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, } else { - char *psz_type = "unknown"; + const char * psz_type = "unknown"; if( p_mt->majortype == MEDIATYPE_Video ) psz_type = "video"; if( p_mt->majortype == MEDIATYPE_Audio ) psz_type = "audio"; if( p_mt->majortype == MEDIATYPE_Stream ) psz_type = "stream"; @@ -1614,7 +1729,7 @@ static block_t *ReadCompressed( access_t *p_access ) while( 1 ) { - if( p_access->b_die || p_access->b_error ) return 0; + if( !vlc_object_alive (p_access) || p_access->b_error ) return 0; /* Get new sample/frame from the elementary stream (blocking). */ vlc_mutex_lock( &p_sys->lock ); @@ -1644,14 +1759,14 @@ static block_t *ReadCompressed( access_t *p_access ) } sample.p_sample->GetPointer( &p_data ); - p_access->p_libvlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size ); + vlc_memcpy( p_block->p_buffer, p_data, i_data_size ); sample.p_sample->Release(); /* The caller got what he wanted */ return p_block; } - return 0; /* never reached */ + return NULL; /* never reached */ } /**************************************************************************** @@ -1660,85 +1775,90 @@ 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; - dshow_stream_t *p_stream = NULL; - VLCMediaSample sample; - int i_data_size, i_stream; - uint8_t *p_data; - block_t *p_block; + int i_stream; + int i_found_samples; + i_found_samples = 0; vlc_mutex_lock( &p_sys->lock ); - /* Try to grab an audio sample (audio has a higher priority) */ - for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) - { - p_stream = p_sys->pp_streams[i_stream]; - if( p_stream->mt.majortype == MEDIATYPE_Audio && - p_stream->p_capture_filter && - p_stream->p_capture_filter->CustomGetPin() - ->CustomGetSample( &sample ) == S_OK ) - { - break; - } - } - /* Try to grab a video sample */ - if( i_stream == p_sys->i_streams ) + while ( !i_found_samples ) { + /* Try to grab samples from all streams */ for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) { - p_stream = p_sys->pp_streams[i_stream]; + dshow_stream_t *p_stream = p_sys->pp_streams[i_stream]; if( p_stream->p_capture_filter && p_stream->p_capture_filter->CustomGetPin() - ->CustomGetSample( &sample ) == S_OK ) + ->CustomGetSamples( p_stream->samples_queue ) == S_OK ) { - break; + i_found_samples = 1; } } + + if ( !i_found_samples) + { + /* Didn't find any audio nor video sample, just wait till the + * dshow thread pushes some samples */ + vlc_cond_wait( &p_sys->wait, &p_sys->lock ); + /* Some DShow thread pushed data, or the OS broke the wait all + * by itself. In all cases, it's *strongly* advised to test the + * condition again, so let the loop do the test again */ + } } vlc_mutex_unlock( &p_sys->lock ); - if( i_stream == p_sys->i_streams ) + for ( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) { - /* Sleep so we do not consume all the cpu, 10ms seems - * like a good value (100fps) */ - msleep( 10000 ); - return 1; - } + int i_samples; + dshow_stream_t *p_stream = p_sys->pp_streams[i_stream]; - /* - * We got our sample - */ - i_data_size = sample.p_sample->GetActualDataLength(); - sample.p_sample->GetPointer( &p_data ); + i_samples = p_stream->samples_queue.size(); + while ( i_samples > 0 ) + { + int i_data_size; + uint8_t *p_data; + block_t *p_block; + VLCMediaSample sample; - REFERENCE_TIME i_pts, i_end_date; - HRESULT hr = sample.p_sample->GetTime( &i_pts, &i_end_date ); - if( hr != VFW_S_NO_STOP_TIME && hr != S_OK ) i_pts = 0; + sample = p_stream->samples_queue.front(); + p_stream->samples_queue.pop_front(); - if( !i_pts ) - { - if( p_stream->mt.majortype == MEDIATYPE_Video || !p_stream->b_pts ) - { - /* Use our data timestamp */ - i_pts = sample.i_timestamp; - p_stream->b_pts = true; - } - } + i_data_size = sample.p_sample->GetActualDataLength(); + sample.p_sample->GetPointer( &p_data ); - i_pts /= 10; /* Dshow works with 100 nano-seconds resolution */ + REFERENCE_TIME i_pts, i_end_date; + HRESULT hr = sample.p_sample->GetTime( &i_pts, &i_end_date ); + if( hr != VFW_S_NO_STOP_TIME && hr != S_OK ) i_pts = 0; + + if( !i_pts ) + { + if( p_stream->mt.majortype == MEDIATYPE_Video || !p_stream->b_pts ) + { + /* Use our data timestamp */ + i_pts = sample.i_timestamp; + p_stream->b_pts = true; + } + } + + i_pts /= 10; /* Dshow works with 100 nano-seconds resolution */ #if 0 - msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: "I64Fd, - i_stream, i_data_size, i_pts ); + msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: %"PRId64, + i_stream, i_data_size, i_pts ); #endif - p_block = block_New( p_demux, i_data_size ); - p_demux->p_libvlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size ); - p_block->i_pts = p_block->i_dts = i_pts; - sample.p_sample->Release(); + p_block = block_New( p_demux, i_data_size ); + vlc_memcpy( p_block->p_buffer, p_data, i_data_size ); + p_block->i_pts = p_block->i_dts = i_pts; + sample.p_sample->Release(); - es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pts > 0 ? i_pts : 0 ); - es_out_Send( p_demux->out, p_stream->p_es, p_block ); + es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pts > 0 ? i_pts : 0 ); + es_out_Send( p_demux->out, p_stream->p_es, p_block ); + + i_samples--; + } + } return 1; } @@ -1764,11 +1884,6 @@ static int AccessControl( access_t *p_access, int i_query, va_list args ) break; /* */ - case ACCESS_GET_MTU: - pi_int = (int*)va_arg( args, int * ); - *pi_int = 0; - break; - 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; @@ -1950,6 +2065,7 @@ static int ConfigDevicesCallback( vlc_object_t *p_this, char const *psz_name, /***************************************************************************** * Properties *****************************************************************************/ + static void ShowPropertyPage( IUnknown *obj ) { ISpecifyPropertyPages *p_spec;