Проблемы с использованием SampleGrabber с CaptureGraphBuilder2

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

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

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

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

План состоял в том, чтобы найти мою веб-камеру путем поиска определенного VID и PID (webcamCapture :: findWebCam ()), создать мой samplegrabber, создать нулевой рендер и затем соединить их все вместе, используя 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;
}

1

Решение

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

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

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

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

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

0

Другие решения


По вопросам рекламы [email protected]