如何显示“视频捕获过滤器”对话框(摄像机设置,例如亮度,曝光)?

时间:2019-02-15 10:34:12

标签: c++ windows opencv directshow vfw

我正在做一个基于Windows的应用程序,在其中我使用了相机。我想允许用户更改相机设置(VfwCaptureDialog_Source),因为它在Skype或amcap应用程序中很常见。现在,我发现该对话框来自vfw,可以从dshow api激活它。当我从AmCap进行操作时,它正在工作。您能否帮助我使此代码适用于给定的网络摄像头(需要多个摄像头支持)?我在使用相机时使用Qt和OpenCV。在opencv中,仅使用摄像机索引来选择合适的摄像机。索引来自Qt,在这里我可以得到很好的摄像机名称列表。我从此代码中得到的错误是1170:“指定的属性集在对象上不存在”

//libs -lDxva2 -lstrmiids -lvfw32 -lole32 -loleaut32
#include <Windows.h>
#include "strmif.h"
#include "dshow.h"
#include "Vfw.h"

...

HRESULT hr ;
IGraphBuilder*  graph= nullptr;
hr = CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&graph );
IMediaControl*  ctrl = nullptr;
hr = graph->QueryInterface( IID_IMediaControl, (void **)&ctrl );
IMediaEventEx*  mediaEvent=nullptr;
hr = graph->QueryInterface(IID_IMediaEvent, (LPVOID *) &mediaEvent);
ICreateDevEnum* devs = nullptr;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, nullptr, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
IEnumMoniker*   cams = nullptr;
hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0;
IMoniker*       mon  = nullptr;
hr = cams?cams->Next (1, &mon, nullptr):0;
IBaseFilter*    cam  = nullptr;
hr = mon?mon->BindToObject(nullptr,nullptr,IID_IBaseFilter, (void**)&cam):0;
IEnumPins*      pins = nullptr;
hr = cam?cam->EnumPins(&pins):0;
IPin*           cap  = nullptr;
hr = pins?pins->Next(1,&cap, nullptr):0;

IAMVfwCaptureDialogs *pVfw = nullptr;
hr = cap->QueryInterface(IID_IAMVfwCaptureDialogs, (void**)&pVfw);

if (SUCCEEDED(hr))
{
    // Check if the device supports this dialog box.
    if (S_OK == pVfw->HasDialog(VfwCaptureDialog_Source))
    {
        // Show the dialog box.
        hr = pVfw->ShowDialog(VfwCaptureDialog_Source, HWND(this->winId()));
    }
}
else
{
    error("cap->QueryInterface");
} 

1 个答案:

答案 0 :(得分:0)

首先,您跳过了一个非常重要的部分。在您的Qt / OpenCV应用程序中,使用的API是什么,对于给定的网络摄像机,您到底拥有什么。如果是Windows视频,则应在对话框界面上查看VFW API。如果是DirectShow,那么您基本上对VFW对话框不感兴趣。

大概是通过DirectShow与摄像机进行交互(嗯,对于多台摄像机使用VFW并没有多大意义)。然后我怀疑AMCap是否完全使用了您在问题中提到的代码路径。注意AMCap来源注释:

// we use this interface to bring up the 3 dialogs
// NOTE:  Only the VfW capture filter supports this.  This app only brings
// up dialogs for legacy VfW capture drivers, since only those have dialogs
hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
                                  &MEDIATYPE_Video, gcap.pVCap,
                                  IID_IAMVfwCaptureDialogs, (void **)&gcap.pDlg);

使用DirectShow时,通常会弹出带有ISpecifyPropertyPagesOleCreatePropertyFrame的配置界面。 AMCap也有与此相关的代码:

        else if(id - MENU_DIALOG0 == gcap.iVCapDialogPos)
        {
            ISpecifyPropertyPages *pSpec;
            CAUUID cauuid;

            hr = gcap.pVCap->QueryInterface(IID_ISpecifyPropertyPages,
                (void **)&pSpec);
            if(hr == S_OK)
            {
                hr = pSpec->GetPages(&cauuid);

                hr = OleCreatePropertyFrame(ghwndApp, 30, 30, NULL, 1,
                    (IUnknown **)&gcap.pVCap, cauuid.cElems,
                    (GUID *)cauuid.pElems, 0, 0, NULL);

                CoTaskMemFree(cauuid.pElems);
                pSpec->Release();
            }
        }

Displaying a Filter's Property Pages在MSDN上应该为您提供更多帮助(问题中的代码段中已经包含IBaseFilter接口指针)。