From 5d72cf0f64162aa130b4720f71e9249a6a34f08a Mon Sep 17 00:00:00 2001 From: rogerdpack Date: Fri, 23 Jan 2015 06:49:37 -0700 Subject: dshow: add options for allowing filter popup configuration dialogs to be presented to the user Signed-off-by: rogerdpack --- configure | 2 +- doc/indevs.texi | 26 +++++++++++++++++++ libavdevice/dshow.c | 62 +++++++++++++++++++++++++++++++++++++++++++- libavdevice/dshow_capture.h | 1 + libavdevice/dshow_crossbar.c | 7 +++++ 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/configure b/configure index a0dbafb1de..0b6be39c3d 100755 --- a/configure +++ b/configure @@ -2487,7 +2487,7 @@ decklink_outdev_extralibs="-lstdc++" decklink_indev_deps="decklink pthreads" decklink_indev_extralibs="-lstdc++" dshow_indev_deps="IBaseFilter" -dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid" +dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid -loleaut32" dv1394_indev_deps="dv1394" dv1394_indev_select="dv_demuxer" fbdev_indev_deps="linux_fb_h" diff --git a/doc/indevs.texi b/doc/indevs.texi index ec40c3400c..a9792fdab9 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -234,6 +234,25 @@ routed to the crossbar device's Video Decoder output pin. Select audio input pin number for crossbar device. This will be routed to the crossbar device's Audio Decoder output pin. +@item show_video_device_dialog +If set to @option{true}, before capture starts, popup a display dialog +to the end user, allowing them to change video filter properties +and configurations manually. +Note that for crossbar devices, this may be needed at times to toggle +between PAL and NTSC input frame rates and sizes, etc. Possibly +enabling different scan rates/frame rates and avoiding green bars at +the bottom, etc. + +@item show_audio_device_dialog +If set to @option{true}, before capture starts, popup a display dialog +to the end user, allowing them to change audio filter properties +and configurations manually. + +@item show_crossbar_connection_dialog +If set to @option{true}, before capture starts, popup a display +dialog to the end user, allowing them to manually +modify crossbar pin routings. + @end table @subsection Examples @@ -276,6 +295,13 @@ Specify pin names to capture by name or alternative name, specify alternative de $ ffmpeg -f dshow -audio_pin_name "Audio Out" -video_pin_name 2 -i video=video="@device_pnp_\\?\pci#ven_1a0a&dev_6200&subsys_62021461&rev_01#4&e2c7dd6&0&00e1#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{ca465100-deb0-4d59-818f-8c477184adf6}":audio="Microphone" @end example +@item +Configure a crossbar device, specifying crossbar pins, allow user to adjust video capture properties at startup: +@example +$ ffmpeg -f dshow -show_video_device_dialog true -crossbar_video_input_pin_number 0 + -crossbar_audio_input_pin_number 3 -i video="AVerMedia BDA Analog Capture":audio="AVerMedia BDA Analog Capture" +@end example + @end itemize @section dv1394 diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 634937734d..691250f3ac 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -502,6 +502,53 @@ end: return ret; } +/** + * Pops up a user dialog allowing them to adjust properties for the given filter, if possible. + */ +void +dshow_show_filter_properties(IBaseFilter *device_filter, AVFormatContext *avctx) { + ISpecifyPropertyPages *property_pages = NULL; + IUnknown *device_filter_iunknown = NULL; + HRESULT hr; + FILTER_INFO filter_info = {0}; /* a warning on this line is false positive GCC bug 53119 */ + CAUUID ca_guid = {0}; + + hr = IBaseFilter_QueryInterface(device_filter, &IID_ISpecifyPropertyPages, (void **)&property_pages); + if (hr != S_OK) { + av_log(avctx, AV_LOG_WARNING, "requested filter does not have a property page to show"); + goto end; + } + hr = IBaseFilter_QueryFilterInfo(device_filter, &filter_info); + if (hr != S_OK) { + goto fail; + } + hr = IBaseFilter_QueryInterface(device_filter, &IID_IUnknown, (void **)&device_filter_iunknown); + if (hr != S_OK) { + goto fail; + } + hr = ISpecifyPropertyPages_GetPages(property_pages, &ca_guid); + if (hr != S_OK) { + goto fail; + } + hr = OleCreatePropertyFrame(NULL, 0, 0, filter_info.achName, 1, &device_filter_iunknown, ca_guid.cElems, + ca_guid.pElems, 0, 0, NULL); + if (hr != S_OK) { + goto fail; + } + goto end; +fail: + av_log(avctx, AV_LOG_ERROR, "Failure showing property pages for filter"); +end: + if (property_pages) + ISpecifyPropertyPages_Release(property_pages); + if (device_filter_iunknown) + IUnknown_Release(device_filter_iunknown); + if (filter_info.pGraph) + IFilterGraph_Release(filter_info.pGraph); + if (ca_guid.pElems) + CoTaskMemFree(ca_guid.pElems); +} + /** * Cycle through available pins using the device_filter device, of type * devtype, retrieve the first output pin and return the pointer to the @@ -527,6 +574,10 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate)); int format_set = 0; + int should_show_properties = (devtype == VideoDevice) ? ctx->show_video_device_dialog : ctx->show_audio_device_dialog; + + if (should_show_properties) + dshow_show_filter_properties(device_filter, avctx); r = IBaseFilter_EnumPins(device_filter, &pins); if (r != S_OK) { @@ -975,7 +1026,7 @@ static int dshow_read_header(AVFormatContext *avctx) if (ctx->device_name[AudioDevice]) if ((r = dshow_list_device_options(avctx, devenum, AudioDevice))) { ret = r; - goto error; + goto error; } } @@ -1133,6 +1184,15 @@ static const AVOption options[] = { { "audio_pin_name", "select audio capture pin by name", OFFSET(audio_pin_name),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { "crossbar_video_input_pin_number", "set video input pin number for crossbar device", OFFSET(crossbar_video_input_pin_number), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, DEC }, { "crossbar_audio_input_pin_number", "set audio input pin number for crossbar device", OFFSET(crossbar_audio_input_pin_number), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, DEC }, + { "show_video_device_dialog", "display property dialog for video capture device", OFFSET(show_video_device_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_video_device_dialog" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_video_device_dialog" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_video_device_dialog" }, + { "show_audio_device_dialog", "display property dialog for audio capture device", OFFSET(show_audio_device_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_audio_device_dialog" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_audio_device_dialog" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_audio_device_dialog" }, + { "show_crossbar_connection_dialog", "display property dialog for crossbar connecting pins filter", OFFSET(show_crossbar_connection_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_crossbar_connection_dialog" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_crossbar_connection_dialog" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_crossbar_connection_dialog" }, { NULL }, }; diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 602969d8d7..c4f46812fb 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -298,6 +298,7 @@ struct dshow_ctx { char *audio_pin_name; int show_video_device_dialog; int show_audio_device_dialog; + int show_crossbar_connection_dialog; IBaseFilter *device_filter[2]; IPin *device_pin[2]; diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c index c4d1630533..1260428d2d 100644 --- a/libavdevice/dshow_crossbar.c +++ b/libavdevice/dshow_crossbar.c @@ -139,6 +139,7 @@ HRESULT dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx) { + struct dshow_ctx *ctx = avctx->priv_data; IAMCrossbar *cross_bar = NULL; IBaseFilter *cross_bar_filter = NULL; HRESULT hr; @@ -151,6 +152,12 @@ dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, goto end; } + if (ctx->show_crossbar_connection_dialog) { + hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void **) &cross_bar_filter); + if (hr != S_OK) + goto end; + dshow_show_filter_properties(cross_bar_filter, avctx); + } hr = setup_crossbar_options(cross_bar, devtype, avctx); if (hr != S_OK) goto end; -- cgit v1.2.3