简体   繁体   English

Directshow-无法使用SetMode设置静止销

[英]Directshow - Cannot set still pin using SetMode

I am trying to get an image from the still pin of my camera using directshow (the framework the camera maker has suggested using). 我正在尝试使用DirectShow(相机制造商建议使用的框架)从相机的静止销中获取图像。

I've been following the DirectShow MS documentation on https://docs.microsoft.com/en-gb/windows/desktop/DirectShow/capturing-an-image-from-a-still-image-pin and although I can find a still pin using the ICaptureGraphBuilder2::FindPin method and have confirmed that the pin exists on the camera using graphedit app, I've hit a brick wall in using the IAMVideoControl::SetMode method to change pin. 我一直在关注https://docs.microsoft.com/zh-CN/g/windows/desktop/DirectShow/capturing-an-image-from-a-still-image-pin上的DirectShow MS文档,尽管可以找到使用ICaptureGraphBuilder2 :: FindPin方法创建一个静止的图钉,并使用graphedit应用程序确认该图钉存在于相机上,我在使用IAMVideoControl :: SetMode方法更改图钉时遇到了麻烦。

The code that I'm using is below: 我正在使用的代码如下:

HRESULT hr = CoInitializeEx(NULL, COINIT::COINIT_MULTITHREADED);
if (FAILED(hr))
    Console::WriteLine("Initialise Failed");
else
    Console::WriteLine("Initialise Success");


//Initalise graph builder
ICaptureGraphBuilder2 *pBuild;
IGraphBuilder *pGraph;

hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
    CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuild);
if (FAILED(hr))
    Console::WriteLine("Graph builder failed");
else
    Console::WriteLine("Graph builder success");

//Create filter graph
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
    IID_IGraphBuilder, (void**)&pGraph);
if (SUCCEEDED(hr))
{
    pBuild->SetFiltergraph(pGraph);
    Console::WriteLine("Set filter graph success");
}
else
{
    pBuild->Release();
    Console::WriteLine("Set filter graph failed");
}


// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum;
IEnumMoniker *pDevicesInfo;
HRESULT hr2 = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
    CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));

if (SUCCEEDED(hr2))
{
    Console::WriteLine("Device enum builder success");

    // Create an enumerator for the video category.
    hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pDevicesInfo, 0);
    if (hr == S_FALSE)
        Console::WriteLine("Retrieve video input devices failed");
    else
        Console::WriteLine("Retrieve video input devices success");
    pDevEnum->Release();
}

//loop over video devices and find see3cam_130

IMoniker *pMoniker = NULL;

while (pDevicesInfo->Next(1, &pMoniker, NULL) == S_OK)
{
    IPropertyBag *pPropBag;
    HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
    if (FAILED(hr))
    {
        pMoniker->Release();
        continue;
    }

    VARIANT var;
    VariantInit(&var);

    // Get description or friendly name.
    hr = pPropBag->Read(L"FriendlyName", &var, 0);
    if (SUCCEEDED(hr))
    {

        Console::WriteLine("Found video device");
        //If correct device, break loop
        if (0 == wcscmp(var.bstrVal, L"See3CAM_130"))
        {
            Console::WriteLine("See3CAM_130");
            break;
        }
        else
        {
            Console::WriteLine("Comparison failed");
        }

        printf("%S\n", var.bstrVal);
        VariantClear(&var);
    }
    else
    {
        Console::WriteLine("Vid Device failed");
    }

}
//Create filter for device
IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
    Console::WriteLine("Filter created");
    hr = pGraph->AddFilter(pCap, L"Capture Filter");
    if (SUCCEEDED(hr))
    {
        Console::WriteLine("Capture filter added to filter graph");
    }
    else
    {
        Console::WriteLine("Capture filter NOT added to filter graph");
    }
}
else
    Console::WriteLine("Filter failed");

//Render capture pin first before attempting to set still pin (setting still pin fails with ot without this step)
hr = pBuild->RenderStream(
    &PIN_CATEGORY_CAPTURE, // Pin category.
    &MEDIATYPE_Video,      // Media type.
    pCap,                  // Capture filter.
    NULL,                  // Intermediate filter (optional).
    NULL);                 // Mux or file sink filter.
if (SUCCEEDED(hr))
    Console::WriteLine("Stream Render success");
else
    Console::WriteLine("Stream Render failed");



//Create a control to run graph
IMediaControl *pControl;

hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
if (FAILED(hr))
    Console::WriteLine("Graph initalised - Failed");
else
    Console::WriteLine("Graph initalised - Success");


// Run the graph.
while (1)
{
    hr = pControl->Run(); 
    if (FAILED(hr))
        Console::WriteLine("Graph run - Failed");
    else
    {
        Console::WriteLine("Graph run - Success");
        break;
    }

}

//Find the still pin
IAMVideoControl *pAMVidControl = NULL;
hr = pCap->QueryInterface(IID_IAMVideoControl, (void**)&pAMVidControl);

if (SUCCEEDED(hr))
{
    Console::WriteLine("Video Control Initialised - Success");


    IPin *pPin = NULL;

    hr = pBuild->FindPin(
        pCap,                  // Filter.
        PINDIR_OUTPUT,         // Look for an output pin.
        &PIN_CATEGORY_STILL,   // Pin category.
        NULL,                  // Media type (don't care).
        FALSE,                 // Pin must be unconnected.
        0,                     // Get the 0'th pin.
        &pPin                  // Receives a pointer to thepin.
        );

    if (SUCCEEDED(hr))
    {
        Console::WriteLine("Find pin - Success");

        hr = pAMVidControl->SetMode(pPin, VideoControlFlag_Trigger);

        if (FAILED(hr))
            Console::WriteLine("Pin Mode Set - Failed");
        else
            Console::WriteLine("Pin Mode Set - Success");

        pPin->Release();
    }
    else
        Console::WriteLine("Find pin - Failed");

}
else
    Console::WriteLine("Video Control Initialised - Failed");

Everything succeeds until I try to use the SetMode method and I've no clue as to why... 一切都会成功,直到我尝试使用SetMode方法为止,而我不知道为什么...

I'm still a junior developer and quite inexperienced in c++ so I suspect I've missed a step somewhere. 我仍然是初级开发人员,并且对C ++经验不足,所以我怀疑我错过了某个地方。 I've considered using the directshow.net wrapper but I don't want to waste the time I've spent getting this far. 我已经考虑过使用directshow.net包装器,但是我不想浪费我花费的时间。

Any hints on why IAMVideoControl::SetMode method fails in my code? 关于IAMVideoControl :: SetMode方法为什么在我的代码中失败的任何提示?

Note: The HResult error is ERROR_GEN_FAILURE (May be used to indicate that the device has stopped responding (hung) or a general failure has occurred on the device. The device may need to be manually reset.) 注意:HResult错误为ERROR_GEN_FAILURE(可用于指示设备已停止响应(挂起)或设备发生一般故障。可能需要手动重置设备。)

i have seen you query and you have to do lot of work to capture still frame. 我看过您的查询,您必须做很多工作才能捕获静止帧。

After you enumerate the still pin, you should connect with sample grabber and null render into camera still pin. 枚举静止针后,应连接样本采集卡,并将渲染为空的值插入相机静止针。

After building and run the graph, you should trigger still mode and the frame will be received in the grabber. 构建并运行图形后,您应该触发静止模式,并且帧将在抓取器中接收。

then you can do with the frame whatever you wants. 那么您可以随心所欲地使用相框。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM