2014-09-29 3 views
0

Я новичок в directshow и использую DirectShow Sample FrameGrabberDemo и сталкиваюсь с проблемой при получении изображения. Я пробовал с .avi и .mpg, обе дают такую ​​же проблему.ISampleGrabber :: GetCurrentBuffer() возвращает E_OUTOFMEMORY

Первой проблемой может быть возвращаемое значение S_FALSE из IMediaControl :: Run(). Однако, это не ошибка и заявляет, что:

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

Второе наблюдение ISampleGrabber :: GetCurrentBuffer() возвращает код E_OUTOFMEMORY, в котором говорится, что «указанный буфер недостаточно велик». Однако BITMAPINFO имеет biImageSize = 1244160, а также MediaType имеет ISampleSize = 1244160.

HRESULT CFrameGrabberDemoDlg::DoExtractFrame() 
{ 
WCHAR wFile[MAX_PATH]; 
MultiByteToWideChar(CP_ACP, 0, m_FilePath, -1, wFile, MAX_PATH); 

// Create the graph builder 
CComPtr<IGraphBuilder> pGraphBuilder; 
HRESULT hr = ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
           IID_IGraphBuilder, (void**)&pGraphBuilder); 
if (FAILED(hr)) 
    return hr; 
ASSERT(pGraphBuilder != NULL); 

// Create the "Grabber filter" 
CComPtr<IBaseFilter> pGrabberBaseFilter; 
CComPtr<ISampleGrabber> pSampleGrabber; 
AM_MEDIA_TYPE mt; 
hr = ::CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, 
         IID_IBaseFilter, (LPVOID *)&pGrabberBaseFilter); 
if (FAILED(hr)) 
    return hr; 
pGrabberBaseFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber); 
if (pSampleGrabber == NULL) 
    return E_NOINTERFACE; 
hr = pGraphBuilder->AddFilter(pGrabberBaseFilter,L"Grabber"); 
if (FAILED(hr)) 
    return hr; 

ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); 
mt.majortype = MEDIATYPE_Video; 
mt.subtype = MEDIASUBTYPE_RGB24; 
mt.formattype = FORMAT_VideoInfo; 
hr = pSampleGrabber->SetMediaType(&mt);   
if (FAILED(hr)) 
    return hr; 
hr = pGraphBuilder->RenderFile(wFile,NULL); 
if (FAILED(hr)) 
    return hr; 

CComPtr<IMediaControl> pMediaControl; 
CComPtr<IMediaEvent> pMediaEventEx; 
// QueryInterface for some basic interfaces 
pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl); 
pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pMediaEventEx); 

if (pMediaControl == NULL || pMediaEventEx == NULL) 
    return E_NOINTERFACE; 

// Set up one-shot mode. 
hr = pSampleGrabber->SetBufferSamples(TRUE); 
if (FAILED(hr)) 
    return hr; 

hr = pSampleGrabber->SetOneShot(TRUE); 
if (FAILED(hr)) 
    return hr; 

CComQIPtr<IMediaSeeking> pSeek = pMediaControl; 
if (pSeek == NULL) 
    return E_NOINTERFACE; 
LONGLONG Duration; 
hr = pSeek->GetDuration(&Duration); 
if (FAILED(hr)) 
    return hr; 
int NumSecs = int(Duration/10000000); 

REFERENCE_TIME rtStart = 1 * 10000000; 
if (NumSecs < 1) 
    rtStart = 0; 
REFERENCE_TIME rtStop = rtStart; 

hr = pSeek->SetPositions(&rtStart, AM_SEEKING_AbsolutePositioning, 
         &rtStop, AM_SEEKING_AbsolutePositioning); 
if (FAILED(hr)) 
    return hr; 

CComQIPtr<IVideoWindow> pVideoWindow = pGraphBuilder; 

hr = pVideoWindow->put_AutoShow(OAFALSE); 
if (FAILED(hr)) 
    return hr; 

// Run the graph and wait for completion. 
hr = pMediaControl->Run(); 
if (FAILED(hr)) 
    return hr; 

long evCode; 
hr = pMediaEventEx->WaitForCompletion(INFINITE, &evCode); 
if (FAILED(hr)) 
    return hr; 

AM_MEDIA_TYPE MediaType; 
ZeroMemory(&MediaType,sizeof(MediaType)); 
hr = pSampleGrabber->GetConnectedMediaType(&MediaType); 
if (FAILED(hr)) 
    return hr; 

// Get a pointer to the video header. 
VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)MediaType.pbFormat; 
if (pVideoHeader == NULL) 
    return E_FAIL; 

// The video header contains the bitmap information. 
// Copy it into a BITMAPINFO structure. 
BITMAPINFO BitmapInfo; 
ZeroMemory(&BitmapInfo, sizeof(BitmapInfo)); 
CopyMemory(&BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), sizeof(BITMAPINFOHEADER)); 

// Create a DIB from the bitmap header, and get a pointer to the buffer. 
void *buffer = NULL; 
HBITMAP hBitmap = ::CreateDIBSection(0, &BitmapInfo, DIB_RGB_COLORS, &buffer, NULL, 0); 
GdiFlush(); 

// Copy the image into the buffer. 
long size = 0; 
hr = pSampleGrabber->GetCurrentBuffer(&size, (long *)buffer); 
if (FAILED(hr)) 
    return hr; 

long Width = pVideoHeader->bmiHeader.biWidth; 
long Height = pVideoHeader->bmiHeader.biHeight; 

HBITMAP hOldBitmap = m_Image.SetBitmap(hBitmap); 
if (hOldBitmap != NULL) 
    ::DeleteObject(hOldBitmap); 

return S_OK; 
} 

:: CreateDIBSection также не возвращает NULL и буфер также был инициализирован.

Как это можно решить?

ответ

1

Вы запрашиваете данные в нулевой длины буфера:

long size = 0; 
hr = pSampleGrabber->GetCurrentBuffer(&size, (long *)buffer); 

Код ошибки выглядит уместным:

Если пиксельный буфер не NULL, установите этот параметр равным размеру буфера, в байтах.

E_OUTOFMEMORY Указанный буфер недостаточно велик.

Вам просто нужны правильные аргументы в соответствующем вызове (правильная длина буфера).