From c55fa2f09bdab7c0655bbf2a5cbdac5fda939494 Mon Sep 17 00:00:00 2001 From: rogerdpack Date: Sat, 24 Jan 2015 19:56:02 -0700 Subject: [PATCH 1/4] dshow: add properties dialog for tv tuners Signed-off-by: rogerdpack --- doc/indevs.texi | 10 ++++++++ libavdevice/dshow.c | 6 +++++ libavdevice/dshow_capture.h | 2 ++ libavdevice/dshow_crossbar.c | 47 +++++++++++++++++++++++++++++++----- 4 files changed, 59 insertions(+), 6 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 75ad76f5e7..c3d0827ec9 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -253,6 +253,16 @@ If set to @option{true}, before capture starts, popup a display dialog to the end user, allowing them to manually modify crossbar pin routings. +@item show_analog_tv_tuner_dialog +If set to @option{true}, before capture starts, popup a display +dialog to the end user, allowing them to manually +modify TV channels and frequencies. + +@item show_analog_tv_tuner_audio_dialog +If set to @option{true}, before capture starts, popup a display +dialog to the end user, allowing them to manually +modify TV audio (like mono vs. stereo, Language A,B or C). + @end table @subsection Examples diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index e34b77c084..d881bfa522 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1202,6 +1202,12 @@ static const AVOption options[] = { { "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" }, + { "show_analog_tv_tuner_dialog", "display property dialog for analog tuner filter", OFFSET(show_analog_tv_tuner_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_analog_tv_tuner_dialog" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_analog_tv_tuner_dialog" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_analog_tv_tuner_dialog" }, + { "show_analog_tv_tuner_audio_dialog", "display property dialog for analog tuner audio filter", OFFSET(show_analog_tv_tuner_audio_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_analog_tv_tuner_dialog" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_analog_tv_tuner_audio_dialog" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_analog_tv_tuner_audio_dialog" }, { NULL }, }; diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 2e64776563..11ab23c7e9 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -304,6 +304,8 @@ struct dshow_ctx { int show_video_device_dialog; int show_audio_device_dialog; int show_crossbar_connection_dialog; + int show_analog_tv_tuner_dialog; + int show_analog_tv_tuner_audio_dialog; IBaseFilter *device_filter[2]; IPin *device_pin[2]; diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c index 9c6301977b..e3012dfe17 100644 --- a/libavdevice/dshow_crossbar.c +++ b/libavdevice/dshow_crossbar.c @@ -142,23 +142,54 @@ dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, { struct dshow_ctx *ctx = avctx->priv_data; IAMCrossbar *cross_bar = NULL; - IBaseFilter *cross_bar_filter = NULL; + IBaseFilter *cross_bar_base_filter = NULL; + IAMTVTuner *tv_tuner_filter = NULL; + IBaseFilter *tv_tuner_base_filter = NULL; + IAMAudioInputMixer *tv_audio_filter = NULL; + IBaseFilter *tv_audio_base_filter = NULL; HRESULT hr; hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, (const GUID *) NULL, - (IBaseFilter *) device_filter, &IID_IAMCrossbar, (void**) &cross_bar); + device_filter, &IID_IAMCrossbar, (void**) &cross_bar); if (hr != S_OK) { /* no crossbar found */ hr = S_OK; goto end; } + /* TODO some TV tuners apparently have multiple crossbars? */ if (ctx->show_crossbar_connection_dialog) { - hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void **) &cross_bar_filter); + hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void **) &cross_bar_base_filter); if (hr != S_OK) goto end; - dshow_show_filter_properties(cross_bar_filter, avctx); + dshow_show_filter_properties(cross_bar_base_filter, avctx); } + + if (devtype == VideoDevice && ctx->show_analog_tv_tuner_dialog) { + hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL, + device_filter, &IID_IAMTVTuner, (void**) &tv_tuner_filter); + if (hr == S_OK) { + hr = IAMCrossbar_QueryInterface(tv_tuner_filter, &IID_IBaseFilter, (void **) &tv_tuner_base_filter); + if (hr != S_OK) + goto end; + dshow_show_filter_properties(tv_tuner_base_filter, avctx); + } else { + av_log(avctx, AV_LOG_WARNING, "unable to find a tv tuner to display dialog for!"); + } + } + if (devtype == AudioDevice && ctx->show_analog_tv_tuner_audio_dialog) { + hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL, + device_filter, &IID_IAMTVAudio, (void**) &tv_audio_filter); + if (hr == S_OK) { + hr = IAMCrossbar_QueryInterface(tv_audio_filter, &IID_IBaseFilter, (void **) &tv_audio_base_filter); + if (hr != S_OK) + goto end; + dshow_show_filter_properties(tv_audio_base_filter, avctx); + } else { + av_log(avctx, AV_LOG_WARNING, "unable to find a tv audio tuner to display dialog for!"); + } + } + hr = setup_crossbar_options(cross_bar, devtype, avctx); if (hr != S_OK) goto end; @@ -166,7 +197,11 @@ dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, end: if (cross_bar) IAMCrossbar_Release(cross_bar); - if (cross_bar_filter) - IBaseFilter_Release(cross_bar_filter); + if (cross_bar_base_filter) + IBaseFilter_Release(cross_bar_base_filter); + if (tv_tuner_filter) + IAMTVTuner_Release(tv_tuner_filter); + if (tv_tuner_base_filter) + IBaseFilter_Release(tv_tuner_base_filter); return hr; } From ce1bbb08f127ecb724c2c62791cad70c30dd270b Mon Sep 17 00:00:00 2001 From: rogerdpack Date: Mon, 26 Jan 2015 01:08:04 -0700 Subject: [PATCH 2/4] dshow: alert as to ramifications of switching crossbar routing Signed-off-by: rogerdpack --- doc/indevs.texi | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index c3d0827ec9..a35c7a65e4 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -229,19 +229,26 @@ Select audio capture pin to use by name or alternative name. @item crossbar_video_input_pin_number Select video input pin number for crossbar device. This will be routed to the crossbar device's Video Decoder output pin. +Note that changing this value can affect future invocations +(sets a new default) until system reboot occurs. @item crossbar_audio_input_pin_number Select audio input pin number for crossbar device. This will be routed to the crossbar device's Audio Decoder output pin. +Note that changing this value can affect future invocations +(sets a new default) until system reboot occurs. @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. +Note that for crossbar devices, adjusting values in this dialog +may be needed at times to toggle between PAL (25 fps) and NTSC (29.97) +input frame rates, sizes, interlacing, etc. Changing these values can +enable different scan rates/frame rates and avoiding green bars at +the bottom, flickering scan lines, etc. +Note that with some devices, changing these properties can also affect future +invocations (sets new defaults) until system reboot occurs. @item show_audio_device_dialog If set to @option{true}, before capture starts, popup a display dialog From 7c2e26270124fc81babcfc7b9d070bb8bd8ab6fa Mon Sep 17 00:00:00 2001 From: rogerdpack Date: Mon, 26 Jan 2015 01:29:58 -0700 Subject: [PATCH 3/4] dshow: crossbar dialog was frequently being displayed twice, split up option so it can be just once Signed-off-by: rogerdpack --- doc/indevs.texi | 9 +++++++-- libavdevice/dshow.c | 9 ++++++--- libavdevice/dshow_capture.h | 3 ++- libavdevice/dshow_crossbar.c | 3 ++- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index a35c7a65e4..ae61331a6f 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -255,10 +255,15 @@ 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 +@item show_video_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. +modify crossbar pin routings, when it opens a video device. + +@item show_audio_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, when it opens an audio device. @item show_analog_tv_tuner_dialog If set to @option{true}, before capture starts, popup a display diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index d881bfa522..9ca2519dd7 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1199,9 +1199,12 @@ static const AVOption options[] = { { "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" }, + { "show_video_crossbar_connection_dialog", "display property dialog for crossbar connecting pins filter on video device", OFFSET(show_video_crossbar_connection_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_video_crossbar_connection_dialog" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_video_crossbar_connection_dialog" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_video_crossbar_connection_dialog" }, + { "show_audio_crossbar_connection_dialog", "display property dialog for crossbar connecting pins filter on audio device", OFFSET(show_audio_crossbar_connection_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_audio_crossbar_connection_dialog" }, + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_audio_crossbar_connection_dialog" }, + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_audio_crossbar_connection_dialog" }, { "show_analog_tv_tuner_dialog", "display property dialog for analog tuner filter", OFFSET(show_analog_tv_tuner_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_analog_tv_tuner_dialog" }, { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_analog_tv_tuner_dialog" }, { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_analog_tv_tuner_dialog" }, diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 11ab23c7e9..f258476099 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -303,7 +303,8 @@ struct dshow_ctx { char *audio_pin_name; int show_video_device_dialog; int show_audio_device_dialog; - int show_crossbar_connection_dialog; + int show_video_crossbar_connection_dialog; + int show_audio_crossbar_connection_dialog; int show_analog_tv_tuner_dialog; int show_analog_tv_tuner_audio_dialog; diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c index e3012dfe17..c0739da318 100644 --- a/libavdevice/dshow_crossbar.c +++ b/libavdevice/dshow_crossbar.c @@ -158,7 +158,8 @@ dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, } /* TODO some TV tuners apparently have multiple crossbars? */ - if (ctx->show_crossbar_connection_dialog) { + if (devtype == VideoDevice && ctx->show_video_crossbar_connection_dialog || + devtype == AudioDevice && ctx->show_audio_crossbar_connection_dialog) { hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void **) &cross_bar_base_filter); if (hr != S_OK) goto end; From 61974c7dcca833687d4f3834c7e8200a63a7b4af Mon Sep 17 00:00:00 2001 From: rogerdpack Date: Mon, 26 Jan 2015 02:03:48 -0700 Subject: [PATCH 4/4] dshow: tweak logging Signed-off-by: rogerdpack --- libavdevice/dshow.c | 4 ++-- libavdevice/dshow_pin.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 9ca2519dd7..d03670e36f 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1044,7 +1044,7 @@ static int dshow_read_header(AVFormatContext *avctx) if (ctx->device_name[AudioDevice]) { if ((r = dshow_open_device(avctx, devenum, AudioDevice, AudioSourceDevice)) < 0 || (r = dshow_add_device(avctx, AudioDevice)) < 0) { - av_log(avctx, AV_LOG_INFO, "Searching for audio device within video devices %s\n", ctx->device_name[AudioDevice]); + av_log(avctx, AV_LOG_INFO, "Searching for audio device within video devices for %s\n", ctx->device_name[AudioDevice]); /* 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) { @@ -1104,7 +1104,7 @@ static int dshow_read_header(AVFormatContext *avctx) r = IMediaControl_GetState(control, 0, &pfs); } if (r != S_OK) { - av_log(avctx, AV_LOG_ERROR, "Could not run filter\n"); + av_log(avctx, AV_LOG_ERROR, "Could not run graph (sometimes caused by a device already in use by other application)\n"); goto error; } diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 5904c28b86..4f719a660e 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -304,21 +304,25 @@ libAVMemInputPin_Receive(libAVMemInputPin *this, IMediaSample *sample) enum dshowDeviceType devtype = pin->filter->type; void *priv_data; uint8_t *buf; - int buf_size; + int buf_size; /* todo should be a long? */ int index; int64_t curtime; + int64_t orig_curtime; + const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; + IReferenceClock *clock = pin->filter->clock; + int64_t dummy; dshowdebug("libAVMemInputPin_Receive(%p)\n", this); if (!sample) return E_POINTER; + IMediaSample_GetTime(sample, &orig_curtime, &dummy); + orig_curtime += pin->filter->start_time; if (devtype == VideoDevice) { /* PTS from video devices is unreliable. */ - IReferenceClock *clock = pin->filter->clock; IReferenceClock_GetTime(clock, &curtime); } else { - int64_t dummy; IMediaSample_GetTime(sample, &curtime, &dummy); if(curtime > 400000000000000000LL) { /* initial frames sometimes start < 0 (shown as a very large number here, @@ -336,6 +340,8 @@ libAVMemInputPin_Receive(libAVMemInputPin *this, IMediaSample *sample) priv_data = pin->filter->priv_data; index = pin->filter->stream_index; + av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %6d timestamp %"PRId64" orig timestamp %"PRId64"\n", + devtypename, buf_size, curtime, orig_curtime); pin->filter->callback(priv_data, index, buf, buf_size, curtime, devtype); return S_OK;