@ -203,7 +203,7 @@ fail:
*/
*/
static int
static int
dshow_cycle_devices ( AVFormatContext * avctx , ICreateDevEnum * devenum ,
dshow_cycle_devices ( AVFormatContext * avctx , ICreateDevEnum * devenum ,
enum dshowDeviceType devtype , IBaseFilter * * pfilter )
enum dshowDeviceType devtype , enum dshowSourceFilterType sourcetype , IBaseFilter * * pfilter )
{
{
struct dshow_ctx * ctx = avctx - > priv_data ;
struct dshow_ctx * ctx = avctx - > priv_data ;
IBaseFilter * device_filter = NULL ;
IBaseFilter * device_filter = NULL ;
@ -216,12 +216,13 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
const GUID * device_guid [ 2 ] = { & CLSID_VideoInputDeviceCategory ,
const GUID * device_guid [ 2 ] = { & CLSID_VideoInputDeviceCategory ,
& CLSID_AudioInputDeviceCategory } ;
& CLSID_AudioInputDeviceCategory } ;
const char * devtypename = ( devtype = = VideoDevice ) ? " video " : " audio " ;
const char * devtypename = ( devtype = = VideoDevice ) ? " video " : " audio only " ;
const char * sourcetypename = ( sourcetype = = VideoSourceDevice ) ? " video " : " audio " ;
r = ICreateDevEnum_CreateClassEnumerator ( devenum , device_guid [ dev type] ,
r = ICreateDevEnum_CreateClassEnumerator ( devenum , device_guid [ source type] ,
( IEnumMoniker * * ) & classenum , 0 ) ;
( IEnumMoniker * * ) & classenum , 0 ) ;
if ( r ! = S_OK ) {
if ( r ! = S_OK ) {
av_log ( avctx , AV_LOG_ERROR , " Could not enumerate %s devices. \n " ,
av_log ( avctx , AV_LOG_ERROR , " Could not enumerate %s devices (or none found) . \n " ,
devtypename ) ;
devtypename ) ;
return AVERROR ( EIO ) ;
return AVERROR ( EIO ) ;
}
}
@ -253,7 +254,6 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
unique_name [ i ] = ' _ ' ;
unique_name [ i ] = ' _ ' ;
}
}
r = IMoniker_BindToStorage ( m , 0 , 0 , & IID_IPropertyBag , ( void * ) & bag ) ;
r = IMoniker_BindToStorage ( m , 0 , 0 , & IID_IPropertyBag , ( void * ) & bag ) ;
if ( r ! = S_OK )
if ( r ! = S_OK )
goto fail1 ;
goto fail1 ;
@ -262,10 +262,9 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
r = IPropertyBag_Read ( bag , L " FriendlyName " , & var , NULL ) ;
r = IPropertyBag_Read ( bag , L " FriendlyName " , & var , NULL ) ;
if ( r ! = S_OK )
if ( r ! = S_OK )
goto fail1 ;
goto fail1 ;
friendly_name = dup_wchar_to_utf8 ( var . bstrVal ) ;
friendly_name = dup_wchar_to_utf8 ( var . bstrVal ) ;
if ( pfilter ) {
if ( pfilter ) {
if ( strcmp ( device_name , friendly_name ) & & strcmp ( device_name , unique_name ) )
if ( strcmp ( device_name , friendly_name ) & & strcmp ( device_name , unique_name ) )
goto fail1 ;
goto fail1 ;
@ -291,15 +290,14 @@ fail1:
if ( bag )
if ( bag )
IPropertyBag_Release ( bag ) ;
IPropertyBag_Release ( bag ) ;
IMoniker_Release ( m ) ;
IMoniker_Release ( m ) ;
}
}
IEnumMoniker_Release ( classenum ) ;
IEnumMoniker_Release ( classenum ) ;
if ( pfilter ) {
if ( pfilter ) {
if ( ! device_filter ) {
if ( ! device_filter ) {
av_log ( avctx , AV_LOG_ERROR , " Could not find %s device. \n " ,
av_log ( avctx , AV_LOG_ERROR , " Could not find %s device with name [%s] among source devices of type %s . \n " ,
devtypename ) ;
devtypename , device_name , sourcetypename ) ;
return AVERROR ( EIO ) ;
return AVERROR ( EIO ) ;
}
}
* pfilter = device_filter ;
* pfilter = device_filter ;
@ -510,7 +508,7 @@ dshow_show_filter_properties(IBaseFilter *device_filter, AVFormatContext *avctx)
ISpecifyPropertyPages * property_pages = NULL ;
ISpecifyPropertyPages * property_pages = NULL ;
IUnknown * device_filter_iunknown = NULL ;
IUnknown * device_filter_iunknown = NULL ;
HRESULT hr ;
HRESULT hr ;
FILTER_INFO filter_info = { 0 } ; /* a warning on this line is false positive GCC bug 53119 */
FILTER_INFO filter_info = { 0 } ; /* a warning on this line is false positive GCC bug 53119 AFAICT */
CAUUID ca_guid = { 0 } ;
CAUUID ca_guid = { 0 } ;
hr = IBaseFilter_QueryInterface ( device_filter , & IID_ISpecifyPropertyPages , ( void * * ) & property_pages ) ;
hr = IBaseFilter_QueryInterface ( device_filter , & IID_ISpecifyPropertyPages , ( void * * ) & property_pages ) ;
@ -557,7 +555,7 @@ end:
*/
*/
static int
static int
dshow_cycle_pins ( AVFormatContext * avctx , enum dshowDeviceType devtype ,
dshow_cycle_pins ( AVFormatContext * avctx , enum dshowDeviceType devtype ,
IBaseFilter * device_filter , IPin * * ppin )
enum dshowSourceFilterType sourcetype , IBaseFilter * device_filter , IPin * * ppin )
{
{
struct dshow_ctx * ctx = avctx - > priv_data ;
struct dshow_ctx * ctx = avctx - > priv_data ;
IEnumPins * pins = 0 ;
IEnumPins * pins = 0 ;
@ -566,7 +564,8 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
int r ;
int r ;
const GUID * mediatype [ 2 ] = { & MEDIATYPE_Video , & MEDIATYPE_Audio } ;
const GUID * mediatype [ 2 ] = { & MEDIATYPE_Video , & MEDIATYPE_Audio } ;
const char * devtypename = ( devtype = = VideoDevice ) ? " video " : " audio " ;
const char * devtypename = ( devtype = = VideoDevice ) ? " video " : " audio only " ;
const char * sourcetypename = ( sourcetype = = VideoSourceDevice ) ? " video " : " audio " ;
int set_format = ( devtype = = VideoDevice & & ( ctx - > framerate | |
int set_format = ( devtype = = VideoDevice & & ( ctx - > framerate | |
( ctx - > requested_width & & ctx - > requested_height ) | |
( ctx - > requested_width & & ctx - > requested_height ) | |
@ -586,9 +585,10 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
}
}
if ( ! ppin ) {
if ( ! ppin ) {
av_log ( avctx , AV_LOG_INFO , " DirectShow %s device options \n " ,
av_log ( avctx , AV_LOG_INFO , " DirectShow %s device options (from %s devices) \n " ,
devtypename ) ;
devtypename , sourcetypename ) ;
}
}
while ( ! device_pin & & IEnumPins_Next ( pins , 1 , & pin , NULL ) = = S_OK ) {
while ( ! device_pin & & IEnumPins_Next ( pins , 1 , & pin , NULL ) = = S_OK ) {
IKsPropertySet * p = NULL ;
IKsPropertySet * p = NULL ;
IEnumMediaTypes * types = NULL ;
IEnumMediaTypes * types = NULL ;
@ -622,12 +622,12 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
}
}
pin_buf = dup_wchar_to_utf8 ( pin_id ) ;
pin_buf = dup_wchar_to_utf8 ( pin_id ) ;
if ( ! ppin ) {
if ( ! ppin ) {
av_log ( avctx , AV_LOG_INFO , " Pin \" %s \" (alternative pin name \" %s \" ) \n " , name_buf , pin_buf ) ;
av_log ( avctx , AV_LOG_INFO , " Pin \" %s \" (alternative pin name \" %s \" ) \n " , name_buf , pin_buf ) ;
dshow_cycle_formats ( avctx , devtype , pin , NULL ) ;
dshow_cycle_formats ( avctx , devtype , pin , NULL ) ;
goto next ;
goto next ;
}
}
if ( desired_pin_name ) {
if ( desired_pin_name ) {
if ( strcmp ( name_buf , desired_pin_name ) & & strcmp ( pin_buf , desired_pin_name ) ) {
if ( strcmp ( name_buf , desired_pin_name ) & & strcmp ( pin_buf , desired_pin_name ) ) {
av_log ( avctx , AV_LOG_DEBUG , " skipping pin \" %s \" ( \" %s \" ) != requested \" %s \" \n " ,
av_log ( avctx , AV_LOG_DEBUG , " skipping pin \" %s \" ( \" %s \" ) != requested \" %s \" \n " ,
@ -694,29 +694,30 @@ next:
}
}
/**
/**
* List options for device with type devtype .
* List options for device with type devtype , source filter type sourcetype
*
*
* @ param devenum device enumerator used for accessing the device
* @ param devenum device enumerator used for accessing the device
*/
*/
static int
static int
dshow_list_device_options ( AVFormatContext * avctx , ICreateDevEnum * devenum ,
dshow_list_device_options ( AVFormatContext * avctx , ICreateDevEnum * devenum ,
enum dshowDeviceType devtype )
enum dshowDeviceType devtype , enum dshowSourceFilterType sourcetype )
{
{
struct dshow_ctx * ctx = avctx - > priv_data ;
struct dshow_ctx * ctx = avctx - > priv_data ;
IBaseFilter * device_filter = NULL ;
IBaseFilter * device_filter = NULL ;
int r ;
int r ;
if ( ( r = dshow_cycle_devices ( avctx , devenum , devtype , & device_filter ) ) < 0 )
if ( ( r = dshow_cycle_devices ( avctx , devenum , devtype , sourcetype , & device_filter ) ) < 0 )
return r ;
return r ;
ctx - > device_filter [ devtype ] = device_filter ;
ctx - > device_filter [ devtype ] = device_filter ;
if ( ( r = dshow_cycle_pins ( avctx , devtype , device_filter , NULL ) ) < 0 )
if ( ( r = dshow_cycle_pins ( avctx , devtype , sourcetype , device_filter , NULL ) ) < 0 )
return r ;
return r ;
return 0 ;
return 0 ;
}
}
static int
static int
dshow_open_device ( AVFormatContext * avctx , ICreateDevEnum * devenum , enum dshowDeviceType devtype )
dshow_open_device ( AVFormatContext * avctx , ICreateDevEnum * devenum ,
enum dshowDeviceType devtype , enum dshowSourceFilterType sourcetype )
{
{
struct dshow_ctx * ctx = avctx - > priv_data ;
struct dshow_ctx * ctx = avctx - > priv_data ;
IBaseFilter * device_filter = NULL ;
IBaseFilter * device_filter = NULL ;
@ -730,7 +731,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDev
const wchar_t * filter_name [ 2 ] = { L " Audio capture filter " , L " Video capture filter " } ;
const wchar_t * filter_name [ 2 ] = { L " Audio capture filter " , L " Video capture filter " } ;
if ( ( r = dshow_cycle_devices ( avctx , devenum , devtype , & device_filter ) ) < 0 ) {
if ( ( r = dshow_cycle_devices ( avctx , devenum , devtype , sourcetype , & device_filter ) ) < 0 ) {
ret = r ;
ret = r ;
goto error ;
goto error ;
}
}
@ -743,7 +744,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDev
goto error ;
goto error ;
}
}
if ( ( r = dshow_cycle_pins ( avctx , devtype , device_filter , & device_pin ) ) < 0 ) {
if ( ( r = dshow_cycle_pins ( avctx , devtype , sourcetype , device_filter , & device_pin ) ) < 0 ) {
ret = r ;
ret = r ;
goto error ;
goto error ;
}
}
@ -1010,38 +1011,46 @@ static int dshow_read_header(AVFormatContext *avctx)
}
}
if ( ctx - > list_devices ) {
if ( ctx - > list_devices ) {
av_log ( avctx , AV_LOG_INFO , " DirectShow video devices \n " ) ;
av_log ( avctx , AV_LOG_INFO , " DirectShow video devices (some may be both video and audio devices) \n " ) ;
dshow_cycle_devices ( avctx , devenum , VideoDevice , NULL ) ;
dshow_cycle_devices ( avctx , devenum , VideoDevice , VideoSourceDevice , NULL ) ;
av_log ( avctx , AV_LOG_INFO , " DirectShow audio devices \n " ) ;
av_log ( avctx , AV_LOG_INFO , " DirectShow audio devices \n " ) ;
dshow_cycle_devices ( avctx , devenum , AudioDevice , NULL ) ;
dshow_cycle_devices ( avctx , devenum , AudioDevice , AudioSourceDevice , NULL ) ;
ret = AVERROR_EXIT ;
ret = AVERROR_EXIT ;
goto error ;
goto error ;
}
}
if ( ctx - > list_options ) {
if ( ctx - > list_options ) {
if ( ctx - > device_name [ VideoDevice ] )
if ( ctx - > device_name [ VideoDevice ] )
if ( ( r = dshow_list_device_options ( avctx , devenum , VideoDevice ) ) ) {
if ( ( r = dshow_list_device_options ( avctx , devenum , VideoDevice , VideoSourceDevice ) ) ) {
ret = r ;
ret = r ;
goto error ;
goto error ;
}
}
if ( ctx - > device_name [ AudioDevice ] )
if ( ctx - > device_name [ AudioDevice ] ) {
if ( ( r = dshow_list_device_options ( avctx , devenum , AudioDevice ) ) ) {
if ( dshow_list_device_options ( avctx , devenum , AudioDevice , AudioSourceDevice ) ) {
ret = r ;
/* show audio options from combined video+audio sources as fallback */
goto error ;
if ( ( r = dshow_list_device_options ( avctx , devenum , AudioDevice , VideoSourceDevice ) ) ) {
ret = r ;
goto error ;
}
}
}
}
}
}
if ( ctx - > device_name [ VideoDevice ] ) {
if ( ctx - > device_name [ VideoDevice ] ) {
if ( ( r = dshow_open_device ( avctx , devenum , VideoDevice ) ) < 0 | |
if ( ( r = dshow_open_device ( avctx , devenum , VideoDevice , VideoSourceDevice ) ) < 0 | |
( r = dshow_add_device ( avctx , VideoDevice ) ) < 0 ) {
( r = dshow_add_device ( avctx , VideoDevice ) ) < 0 ) {
ret = r ;
ret = r ;
goto error ;
goto error ;
}
}
}
}
if ( ctx - > device_name [ AudioDevice ] ) {
if ( ctx - > device_name [ AudioDevice ] ) {
if ( ( r = dshow_open_device ( avctx , devenum , AudioDevice ) ) < 0 | |
if ( ( r = dshow_open_device ( avctx , devenum , AudioDevice , AudioSourceDevice ) ) < 0 | |
( r = dshow_add_device ( avctx , AudioDevice ) ) < 0 ) {
( r = dshow_add_device ( avctx , AudioDevice ) ) < 0 ) {
ret = r ;
av_log ( avctx , AV_LOG_INFO , " Searching for audio device within video devices %s \n " , ctx - > device_name [ AudioDevice ] ) ;
goto error ;
/* see if there's a video source with an audio pin with the given audio name */
if ( ( r = dshow_open_device ( avctx , devenum , AudioDevice , VideoSourceDevice ) ) < 0 | |
( r = dshow_add_device ( avctx , AudioDevice ) ) < 0 ) {
ret = r ;
goto error ;
}
}
}
}
}
if ( ctx - > list_options ) {
if ( ctx - > list_options ) {