Directshow - Невозможно установить неподвижный контакт, используя SetMode - PullRequest
0 голосов
/ 30 августа 2018

Я пытаюсь получить изображение с неподвижного штифта моей камеры, используя directshow (рамки, которые производитель камеры предложил использовать).

Я следил за документацией DirectShow MS на https://docs.microsoft.com/en-gb/windows/desktop/DirectShow/capturing-an-image-from-a-still-image-pin и, хотя я могу найти неподвижный штифт, используя метод ICaptureGraphBuilder2 :: FindPin, и подтвердил, что этот штифт существует на камере с помощью приложения graphedit, я ' Мы ударили по кирпичной стене, используя метод IAMVideoControl :: SetMode, чтобы изменить пин-код.

Код, который я использую ниже:

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");

Все успешно, пока я не попытаюсь использовать метод SetMode, и я понятия не имею, почему ...

Я все еще начинающий разработчик и довольно неопытен в c ++, поэтому я подозреваю, что где-то пропустил шаг. Я подумал об использовании оболочки directshow.net, но не хочу тратить время, потраченное на это.

Любые подсказки о том, почему метод IAMVideoControl :: SetMode не работает в моем коде?

Примечание. Ошибка HResult: ERROR_GEN_FAILURE (может использоваться для указания того, что устройство перестало отвечать (зависло) или произошел общий сбой на устройстве. Возможно, потребуется сброс устройства вручную.)

1 Ответ

0 голосов
/ 18 сентября 2018

Я видел ваш запрос, и вам нужно проделать большую работу для захвата неподвижного кадра.

После того, как вы перечислите неподвижный вывод, вы должны соединиться с образцом захвата и нулевой рендеринг в неподвижный вывод камеры.

После построения и запуска графика вы должны активировать неподвижный режим, и кадр будет получен в граббере.

тогда вы можете делать с рамкой все, что захотите.

...