From patchwork Wed Jun 2 11:29:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Diederick C. Niehorster" X-Patchwork-Id: 28052 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:b214:0:0:0:0:0 with SMTP id b20csp457270iof; Wed, 2 Jun 2021 04:30:32 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyGnJpupI7e/KXbh3CGN8c1+ip8aTOzBkaOts3LEdbmhojVSeDjT7lKlA93urE/xGUUFT4c X-Received: by 2002:a17:906:b104:: with SMTP id u4mr33231581ejy.211.1622633432036; Wed, 02 Jun 2021 04:30:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622633432; cv=none; d=google.com; s=arc-20160816; b=y4crZt0GPwR01Hae1CcQ/qyv6T1PH8UAgvLZIMvbzUWlrC2pTXA8utPC4pbEHvNAIa igY/iqdla2AZZZD5icFAVrMlNnJ9cL8+hPXU6JpQtYluSZmrUXWKMze6c81P239iHGR7 J5mILfeTnAxj8q216ZRlPv03cCzXXn0O1Rl1yxLUy5qUEQU11nU3sQlNH2Lofs5YYWqk qhEtsqfaYeggdzHpA957n2dcaWsUaiV+wqryVtEYCyrHpdvS2qwqaaEeOs2pQoQ7PPta PP5lXW/dAYV4u91FCZJFROHjiOBUCNv0H4PPX2/ZbzYEnSJjv3Q+udrLBmncqIkSSfQA 598A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=n/KSRAtVKibI+1o9fN98gRSYIgH4Id+aQTpiaYpFvRs=; b=El61pZyKpZ4Taa32oVdwHN3C8RKSZA7wNVX31q2q7DvsaqnoA3LK75O8V1jZMNzjgv 4xIWbXJaNjD7axSeAAzW6IHcMd3yglAtdz9659R2EoKUKZ7aKUPgMvkvczFtCwWrDDla s/UbSeWYhjRWbo93M1uW/4K0DQJ7O73w5f+7kHv3IE8dO+O8tN0EFcDFNkd46vIqiCPp GKx+WgrOC8LyATR3lmsr83MpUnL/G6bwA4sgf8/NEyKbTytZIapknmrxtwHgjc19AF2A Q0paWn/xpTxyLY4hYGk0DKGBK6WroUtxVCzBHRyh5fd5tDugwVgRxG5405qeL1XKhVFQ ed6A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=SMPzhb26; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id f20si10604190eja.621.2021.06.02.04.30.31; Wed, 02 Jun 2021 04:30:32 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=SMPzhb26; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5727768A0DE; Wed, 2 Jun 2021 14:29:34 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f48.google.com (mail-lf1-f48.google.com [209.85.167.48]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 10F9E68A08E for ; Wed, 2 Jun 2021 14:29:25 +0300 (EEST) Received: by mail-lf1-f48.google.com with SMTP id a2so2804270lfc.9 for ; Wed, 02 Jun 2021 04:29:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0B7DBN06VjXWk8KdXvM9BrlyoiWkvsQlLXYZ/bhkCaQ=; b=SMPzhb26srljjhfytzBGsazTRVEd/vsEp5Rx7/3sPAn8a5letwBxW2uO5SmgekwaE0 5D79e7h+iSZuLYdt8pRQtyG6pe5tkt3Ps1BOhq6D7XM7f4lf1HsfZuyFbvVzpAvWjlex 4FgA2vQgehGIzV18RyhCrKyk1483lcqAI8jY5cLR1Ufdm5Ouel+kDP0xbVrR6uw3/V0L TLj6IZWmh70htGzjPBW1shxtTa8q1LeV7DkEH5jAixBqQNFsB63cnOc0b+yshQvY92iH anNnMZtMb+tajd8cXO4SwknyOjc1Zn3nr5hHraHHBkoNvQtDZFIbVUZR3KzXlhU1pO7+ PunQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0B7DBN06VjXWk8KdXvM9BrlyoiWkvsQlLXYZ/bhkCaQ=; b=AHJr/Qyh+OD91OnkFZVm0PCMiUpvQQEKwf+goEbqiHgsx6oATASaspSARlk5kbjttv tG6/ZYPKA1HhnNG9fTUODOLAeoBnZ9UtRBfPkTy9qmLM+gBana4MLyhGFa9qVw4FVKqm fKKGrxQLsDIzg/GZNVctHSMPfi54bS4NebfbH1KW+Qe8aTp9c2FIOzmI6ClKkhxtrJFg i71hjmE3aajKtYfa5A0YEjzTxLjQi2Q/d1re4+1acbU9N0xwQ9fQ9WNTUoyaX/APyTX1 CGGuR567Pv6WOxXLgR44XefKZHmiCNnbaX7O1ZgOCTiRF36oskQFkqLM1AzfOw4ts56U ATxg== X-Gm-Message-State: AOAM531UiXu1uFVMss/TcwOEDFlCfEEa15JZIs58QrtCEI71yKE0PSZq gnNgOdeghvoxLjOWbOq2NS3/ezJomCoXkQ== X-Received: by 2002:ac2:5edd:: with SMTP id d29mr602013lfq.57.1622633363912; Wed, 02 Jun 2021 04:29:23 -0700 (PDT) Received: from localhost.localdomain (deedock.humlab.lu.se. [130.235.135.183]) by smtp.gmail.com with ESMTPSA id v6sm1249497lfr.182.2021.06.02.04.29.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jun 2021 04:29:23 -0700 (PDT) From: Diederick Niehorster To: ffmpeg-devel@ffmpeg.org Date: Wed, 2 Jun 2021 13:29:01 +0200 Message-Id: <20210602112901.2163-7-dcnieho@gmail.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20210602112901.2163-1-dcnieho@gmail.com> References: <20210602112901.2163-1-dcnieho@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 6/6] avdevice/dshow: add config dialog command for crossbar and tv tuner X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Diederick Niehorster Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: IYRBDuIW3dNj The "show config dialog" command message can now also trigger dialog boxes for the crossbar connecting pins filter the analog tuner audio / analog tuner filters. _Untested_ as I do not have either device. Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 78 +++++++++++++++++++++++++------ libavdevice/dshow_capture.h | 10 ++++ libavdevice/dshow_crossbar.c | 91 +++++++++++++++++++++++------------- 3 files changed, 132 insertions(+), 47 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 561b85f4e0..d274d93dc3 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -60,6 +60,11 @@ dshow_read_close(AVFormatContext *s) struct dshow_ctx *ctx = s->priv_data; PacketList *pktl; + if (ctx->graph_builder2[VideoDevice]) + ICaptureGraphBuilder2_Release(ctx->graph_builder2[VideoDevice]); + if (ctx->graph_builder2[AudioDevice]) + ICaptureGraphBuilder2_Release(ctx->graph_builder2[AudioDevice]); + if (ctx->control) { IMediaControl_Stop(ctx->control); IMediaControl_Release(ctx->control); @@ -873,6 +878,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, av_log(avctx, AV_LOG_ERROR, "Could not create CaptureGraphBuilder2\n"); goto error; } + ctx->graph_builder2[devtype] = graph_builder2; ICaptureGraphBuilder2_SetFiltergraph(graph_builder2, graph); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not set graph for CaptureGraphBuilder2\n"); @@ -897,9 +903,6 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, ret = 0; error: - if (graph_builder2 != NULL) - ICaptureGraphBuilder2_Release(graph_builder2); - if (pers_stream) IPersistStream_Release(pers_stream); @@ -912,11 +915,11 @@ error: return ret; } -static int dshow_control_message(AVFormatContext* avctx, int type, void* data, size_t data_size) +static int dshow_control_message(AVFormatContext *avctx, int type, void *data, size_t data_size) { - struct dshow_ctx* ctx = avctx->priv_data; + struct dshow_ctx *ctx = avctx->priv_data; int run_state = ctx->is_running; - int r; + HRESULT hr; switch (type) { case AV_APP_TO_DEV_PAUSE: @@ -930,7 +933,14 @@ static int dshow_control_message(AVFormatContext* avctx, int type, void* data, s break; case AV_APP_TO_DEV_CONFIG: { - int dialog = *(int*)data; + /* + * Documentation of dialog variable: + * 1st bit: if set, audio device, if not set, video device + * 2nd bit: if set, show property dialog for audio/video capture device + * 3rd bit: if set, show property dialog for crossbar connecting pins filter on audio/video device + * 4th bit: if set, show property dialog for analog tuner audio / analog tuner filter + */ + int dialog = *(int *) data; enum dshowDeviceType devtype = (dialog & 1) ? AudioDevice : VideoDevice; if (dialog & 2) { // device_dialog @@ -939,27 +949,67 @@ static int dshow_control_message(AVFormatContext* avctx, int type, void* data, s } else if (dialog & 2) { // crossbar_connection_dialog - // TODO + if (ctx->device_filter[devtype] && ctx->graph_builder2[devtype]) { + IAMCrossbar *cross_bar = NULL; + IBaseFilter *cross_bar_base_filter = NULL; + hr = ff_dshow_get_crossbar_and_filter(ctx->graph_builder2[devtype], ctx->device_filter[devtype], cross_bar, &cross_bar_base_filter); + + if (hr == S_OK && cross_bar_base_filter) + ff_dshow_show_filter_properties(cross_bar_base_filter, avctx); + + if (cross_bar) + IAMCrossbar_Release(cross_bar); + if (cross_bar_base_filter) + IBaseFilter_Release(cross_bar_base_filter); + } } else if (dialog & 4) { // tv_tuner_dialog - // TODO + if (ctx->device_filter[devtype] && ctx->graph_builder2[devtype]) { + if (devtype == VideoDevice) { + IAMTVTuner *tv_tuner_filter = NULL; + IBaseFilter *tv_tuner_base_filter = NULL; + hr = ff_dshow_get_tvtuner_and_filter(ctx->graph_builder2[devtype], ctx->device_filter[devtype], tv_tuner_filter, tv_tuner_base_filter); + + if (hr == S_OK && tv_tuner_base_filter) + ff_dshow_show_filter_properties(tv_tuner_base_filter, avctx); + + if (tv_tuner_filter) + IAMTVTuner_Release(tv_tuner_filter); + if (tv_tuner_base_filter) + IBaseFilter_Release(tv_tuner_base_filter); + } + else { + IAMAudioInputMixer *tv_audio_filter = NULL; + IBaseFilter *tv_audio_base_filter = NULL; + hr = ff_dshow_get_audiomixer_and_filter(ctx->graph_builder2[devtype], ctx->device_filter[devtype], tv_audio_filter, tv_audio_base_filter); + + if (hr == S_OK && tv_audio_base_filter) + ff_dshow_show_filter_properties(tv_audio_base_filter, avctx); + + if (tv_audio_filter) + IAMAudioInputMixer_Release(tv_audio_filter); + if (tv_audio_base_filter) + IBaseFilter_Release(tv_audio_base_filter); + } + } } break; } } + // if play state change requested, apply if (run_state != ctx->is_running) { if (run_state) - r = IMediaControl_Run(ctx->control); + hr = IMediaControl_Run(ctx->control); else - r = IMediaControl_Pause(ctx->control); + hr = IMediaControl_Pause(ctx->control); - if (r == S_FALSE) { + if (hr == S_FALSE) { OAFilterState pfs; - r = IMediaControl_GetState(ctx->control, 0, &pfs); + hr = IMediaControl_GetState(ctx->control, 0, &pfs); } - if (r != S_OK) { + if (hr != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not run/pause graph\n"); return AVERROR(EIO); } diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index b7ef3770df..5a665d0ee0 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -317,6 +317,7 @@ struct dshow_ctx { IPin *device_pin[2]; DShowFilter *capture_filter[2]; DShowPin *capture_pin[2]; + ICaptureGraphBuilder2 *graph_builder2[2]; HANDLE mutex; HANDLE event[2]; /* event[0] is set by DirectShow @@ -351,6 +352,15 @@ struct dshow_ctx { HRESULT ff_dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx); +HRESULT ff_dshow_get_crossbar_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, + IAMCrossbar *cross_bar, IBaseFilter **cross_bar_base_filter); + +HRESULT ff_dshow_get_tvtuner_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, + IAMTVTuner *tv_tuner_filter, IBaseFilter *tv_tuner_base_filter); + +HRESULT ff_dshow_get_audiomixer_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, + IAMAudioInputMixer *tv_audio_filter, IBaseFilter *tv_audio_base_filter); + void ff_dshow_show_filter_properties(IBaseFilter *pFilter, AVFormatContext *avctx); #endif /* AVDEVICE_DSHOW_CAPTURE_H */ diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c index 961defe690..6b714e849c 100644 --- a/libavdevice/dshow_crossbar.c +++ b/libavdevice/dshow_crossbar.c @@ -133,6 +133,44 @@ setup_crossbar_options(IAMCrossbar *cross_bar, enum dshowDeviceType devtype, AVF return S_OK; } +HRESULT +ff_dshow_get_crossbar_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, + IAMCrossbar *cross_bar, IBaseFilter **cross_bar_base_filter) +{ + HRESULT hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, (const GUID *) NULL, + device_filter, &IID_IAMCrossbar, (void **) &cross_bar); + if (hr != S_OK) + /* no crossbar found */ + return hr; + + if (cross_bar_base_filter) + hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void**)cross_bar_base_filter); + + return hr; +} + +HRESULT +ff_dshow_get_tvtuner_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, + IAMTVTuner *tv_tuner_filter, IBaseFilter *tv_tuner_base_filter) +{ + HRESULT 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); + return hr; +} + +HRESULT +ff_dshow_get_audiomixer_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, + IAMAudioInputMixer *tv_audio_filter, IBaseFilter *tv_audio_base_filter) +{ + HRESULT 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); + return hr; +} + /** * Given a fully constructed graph, check if there is a cross bar filter, and configure its pins if so. */ @@ -140,55 +178,42 @@ HRESULT ff_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_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; + struct dshow_ctx *ctx = avctx->priv_data; + IAMCrossbar *cross_bar = 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; + int should_show_crossbar_properties = (devtype == VideoDevice) ? ctx->show_video_crossbar_connection_dialog : ctx->show_audio_crossbar_connection_dialog; - hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, (const GUID *) NULL, - device_filter, &IID_IAMCrossbar, (void**) &cross_bar); + hr = ff_dshow_get_crossbar_and_filter(graph_builder2, device_filter, cross_bar, should_show_crossbar_properties ? &cross_bar_base_filter : NULL); if (hr != S_OK) { - /* no crossbar found */ - hr = S_OK; + if (!cross_bar) + /* no crossbar found */ + hr = S_OK; goto end; } + /* TODO some TV tuners apparently have multiple crossbars? */ - 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; + if (should_show_crossbar_properties && cross_bar_base_filter) ff_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; + hr = ff_dshow_get_tvtuner_and_filter(graph_builder2, device_filter, tv_tuner_filter, tv_tuner_base_filter); + if (hr == S_OK && tv_tuner_base_filter) ff_dshow_show_filter_properties(tv_tuner_base_filter, avctx); - } else { + 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; + hr = ff_dshow_get_audiomixer_and_filter(graph_builder2, device_filter, tv_audio_filter, tv_audio_base_filter); + if (hr == S_OK && tv_audio_base_filter) ff_dshow_show_filter_properties(tv_audio_base_filter, avctx); - } else { + 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);