2015-05-01 2 views
1

Я пытаюсь использовать SampleGrabber, чтобы захватить фрейм из веб-камеры и сохранить его как растровое изображение, но ему не повезло. Я использовал пример видеозахвата Directshow в MSDN, используя ICaptureGraphBuilder2, а также пример Sample grabber.Проблемы с использованием SampleGrabber с CaptureGraphBuilder2

Я намеревался мой граф фильтра выглядеть следующим образом:

Веб-камера (источник) -> Sample Grabber -> Null Renderer

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

План должен был найти мою веб-камеру, выполнив поиск определенного VID и PID (webcamCapture :: findWebCam()), создайте свой образец grabber, создайте нулевой рендерер, а затем соедините их все вместе, используя pGraphBuilder-> RenderStream(). Поскольку мне нужен только один кадр, я использовал метод OneShot, а затем использовал GetCurrentBuffer для извлечения кадра.

Проблема возникает в этой строке:

pEvent->WaitForCompletion(2000, &evCode); 

код HRESULT возвращено E_ABORT. Установка тайм-аута на INFINITE заставила программу замерзнуть, возможно, означая, что фильтр никогда не останавливается. HRESULT из pControl-> Run() был S_FALSE, что означает, что не все фильтры запущены. Я не уверен, почему это происходит, и я чувствую, что что-то пошло не так, когда вы строите эти фильтры.

Ниже приведена свалка моего источника. Я создал класс для обработки захвата веб-камеры. При использовании в основном две вещи дозвонились:

webcamCapture::buildFilterGraph() 
webcamCapture::runFilter() 

runFilter будет работать фильтр и сохранить кадр в виде файла растрового изображения. Я новичок в прямом шоу, и я уверен, что мне не хватает чего-то простого. Любое понимание было бы очень благодарно!

Источник

HRESULT webcamCapture::buildFilterGraph(void){ 
    HRESULT hr; 

    if (FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { 
     return hr; 
    } 

    createCOMInstances(); 

    // Use findWebCam() to find the webcam and add it to our capture graph 
    hr = findWebCam(); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Add the sample grabber to the graph 
    hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber"); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pGrabber)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Set media type for the sample grabber (24-bit RGB Uncompressed video) 
    ZeroMemory(&mt, sizeof(mt)); 
    mt.majortype = MEDIATYPE_Video; 
    mt.subtype = MEDIASUBTYPE_RGB24; 

    hr = pGrabber->SetMediaType(&mt); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    hr = pGraph->AddFilter(pNullF, L"Null Filter"); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Connect source (pCapF), sample grabber (pGrabberF) and null renderer (pNullF) 
    pGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCapF,pGrabberF, pNullF); 

    hr = pGrabber->SetOneShot(TRUE); 
    hr = pGrabber->SetBufferSamples(TRUE); 


    return S_OK; 
    } 

    HRESULT webcamCapture::runFilter(){ 
    HRESULT hr; 
    FILTER_STATE filterState; 

    pBuffer = NULL; 



    hr = pControl->Run(); 
    if(FAILED(hr)){ 
     goto done; 
    } 

    pControl->GetState(1000, (OAFilterState*)&filterState); 

    long evCode; 
    hr = pEvent->WaitForCompletion(2000, &evCode); 
    if(FAILED(hr)){ 
     goto done; 
    } 

    long cbBuffer; 
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL); 
    if(FAILED(hr)){ 
     goto done; 
    } 

    pBuffer = (BYTE*)CoTaskMemAlloc(cbBuffer); 
    if(!pBuffer){ 
     hr = E_OUTOFMEMORY; 
     goto done; 
    } 

    hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer); 
    if(FAILED(hr)){ 
     goto done; 
    } 

    hr = pGrabber->GetConnectedMediaType(&mt); 
    if(FAILED(hr)){ 
     goto done; 
    } 

    if((mt.formattype == FORMAT_VideoInfo) && (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) && (mt.pbFormat != NULL)){ 

     VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat; 
     writeBitmap(L"test_image.bmp", &pVih->bmiHeader, mt.cbFormat - SIZE_PREHEADER, pBuffer, cbBuffer); 
    } 

    //FreeMediaType(mt); 

    done: 
     CoTaskMemFree(pBuffer); 
     pNullF->Release(); 
     pNullF = NULL; 
     pCapF->Release(); 
     pCapF = NULL; 
     pGrabber->Release(); 
     pGrabber = NULL; 
     pGrabberF->Release(); 
     pGrabberF = NULL; 
     pControl->Release(); 
     pControl = NULL; 
     pEvent->Release(); 
     pEvent = NULL; 
     pGraph->Release(); 
     pGraph = NULL; 
     CoUninitialize(); 


    return hr; 
    } 

    HRESULT webcamCapture::createCOMInstances(void){ 
    HRESULT hr; 

    // Instructions to create a Capture Graph using CaptureGraphBuilder2 can be found at https://msdn.microsoft.com/en-us/library/windows/desktop/dd373396(v=vs.85).aspx 

    // Create Capture Graph Builder 
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraphBuilder)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Create Graph Manager 
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraph)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Initialize Capture Graph Builder by referencing pGraph (Graph Manager) 
    hr = pGraphBuilder->SetFiltergraph(pGraph); 
    if(FAILED(hr)){ 
     pGraphBuilder->Release(); 
     return hr; 
    } 

    // Set pointer to Media Control Interface 
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Set pointer to Media Event Interface 
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Create Sample Grabber 
    // NOTE: ISampleGrabber is depreciated and may not be supported in later versions of Windows! 
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGrabberF)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    // Create the null renderer filter. We don't be previewing the camera feed so we can just drop the frames when we've converted them to bitmaps 
    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pNullF)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    TRACE(_T("Interface Creation Successful\n")); 
    return S_OK; 
    } 

    // Function to find the MS HD3000 webcam (VID=0x045E PID=0x0779) 
    // For more info on finding devices for Video/Audio capture, see https://msdn.microsoft.com/en-us/library/windows/desktop/dd377566(v=vs.85).aspx 
    HRESULT webcamCapture::findWebCam(void){ 

    HRESULT hr; 
    ICreateDevEnum *pDevEnum; 
    IEnumMoniker *pEnum; 
    IMoniker *pMoniker; 
    BOOL isDeviceFound = FALSE; 

    WORD wNumCameras = 0; 

    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum)); 
    if(FAILED(hr)){ 
     return hr; 
    } 

    hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0); 
    if(hr == S_FALSE){ 
     return VFW_E_NOT_FOUND; 
    } 

    pDevEnum->Release(); 

    // Go through each device moniker and read their Device Path properties. This is how we will find our webcam of interest 
    while(pEnum->Next(1, &pMoniker, NULL) == S_OK){ 

     IPropertyBag *pPropBag; 
     VARIANT var; 

     hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag)); 

     if(FAILED(hr)){ 
      pMoniker->Release(); 
      continue; 
     } 

     VariantInit(&var); 

     hr = pPropBag->Read(L"DevicePath", &var, 0); 
     if(SUCCEEDED(hr)){ 
      // String search variables 
      CString csVidToCompare = _T(""); 
      CString csPidToCompare = _T(""); 
      WORD wVidSearchIndex = 0; 
      WORD wPidSearchIndex = 0; 

      CString csDevPath = var.bstrVal; 
      csDevPath.MakeLower(); 

      wVidSearchIndex = csDevPath.Find(_T("vid_"), 0); 
      wPidSearchIndex = csDevPath.Find(_T("pid_"), 0); 

      csVidToCompare = csDevPath.Mid(wVidSearchIndex + 4, 4); 
      csPidToCompare = csDevPath.Mid(wPidSearchIndex + 4, 4); 

      // If MS Device is found 
      if(!csVidToCompare.Compare(_T("045e"))){ 
       // If the 3000HD camera is found 
       if((!csPidToCompare.Compare(_T("0779"))) && (wNumCameras == 0)){ 
        wNumCameras++; 
        hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCapF); 
        if(FAILED(hr)){ 
         return hr; 
        } 

        isDeviceFound = TRUE; 
        // Add the webcam to the filter graph 
        hr = pGraph->AddFilter(pCapF, L"Capture Filter"); 

        if(FAILED(hr)){ 
         TRACE(_T("Failed to add webcam to filter graph\n")); 
         return hr; 
        } 

        TRACE(_T("Webcam found and added to filter!\n")); 

       } 

       else if((!csPidToCompare.Compare(_T("0779"))) && (wNumCameras > 0)){ 
        TRACE(_T("More than one HD3000 camera found!\n")); 
        continue; 
       } 

       else{ 
        TRACE(_T("MS Device found, but not the camera\n")); 
        continue; 
       } 
      } 
     } 

     pPropBag->Release(); 
     pMoniker->Release(); 
    } 

    if(isDeviceFound == FALSE){ 
     TRACE(_T("Webcam was not found\n")); 
     pEnum->Release(); 
     return E_FAIL; 
    } 

    pEnum->Release(); 

    return S_OK; 
} 

ответ

0

Код о праве. Да, вы можете построить такой граф, и образец grabber в режиме одного снимка принимает видеокадр и указывает на завершение.

Контрольный список потенциальных вопросов включает в себя:

  1. видеоустройство не доставляет кадров, образец граббер ждет навсегда
  2. вы запросили преобразование 24 бит RGB и камера, скорее всего, для поддержки других видео форматы, поэтому у вас, возможно, есть другой фильтр фильтра, вставленный для вас - видеокадры могут оставить фильтр камеры и потеряны в конвертере; вы заинтересованы в рассмотрении эффективного графика вы построили
  3. вы построили график неправильно и ваш образец граббер не подключен правильно

В любом случае ваша первая вещь, которую нужно сделать, это просто ворваться с отладчиком и проверить темы, вы можете увидеть что-то неправильно прямо на месте. Тогда ваша вторая задача - узнать, как review your filter graphs. Это необходимо для любой разработки DirectShow.

S_FALSE возврат типичен для графиков, имеющих источник в топологии. Это отлично.

 Смежные вопросы

  • Нет связанных вопросов^_^