ISampleGrabber::GetCurrentBuffer() returns E_OUTOFMEMORY
ISampleGrabber::GetCurrentBuffer() returns E_OUTOFMEMORY
我是directshow的新手,使用directshow示例"FrameGrabberDemo",在获取图像时遇到问题。我试过.avi和.mpg,两者都给出了相同的问题。
第一个问题可能是IMediaControl::Run()的S_FALSE返回值。然而,这不是一个错误,并指出:
图形正准备运行,但某些筛选器尚未完成转换到运行状态。
第二个观察结果是ISampleGrabber::GetCurrentBuffer()返回E_OUTOFMEMORY代码,该代码表示"指定的缓冲区不够大。"然而,BitmapInfo的biImageSize=1244160和MediaType的ISampleSize=124416。
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;
}
::CreateDIB部分也没有返回NULL,缓冲区也已初始化。
如何解决这一问题?
您正在向零长度缓冲区请求数据:
long size = 0;
hr = pSampleGrabber->GetCurrentBuffer(&size, (long *)buffer);
错误代码看起来很相关:
如果pBuffer不为NULL,请将此参数设置为等于缓冲区的大小(以字节为单位)。
E_OUTOFMEMORY
指定的缓冲区不够大。
您只需要在有问题的调用中使用适当的参数(适当的缓冲区长度)。
相关文章:
- CreateWICTextureFromFile returns E_NOINTERFACE
- cl::Event::waitForEvents returns -7 (CL_EXEC_STATUS_ERROR_ F
- vector[0].getPosition() returns 0
- CreateInputLayout returns E_INVALIDARG
- ldap_search_s returns LDAP_OPERATIONS_ERROR
- CreateCompatibleDC(IntPtr.Zero) returns IntPtr.Zero
- glUniformLocation returns -1
- DirectX9 CreateOffscreenPlainSurface returns D3DERR_INVALIDC
- OpenGL glReadPixels returns 0
- gdk_screen_get_default() returns null
- UIAutomation: AddAutomationEventHandler() returns E_INVALIDA
- C++ _snprintf returns -1
- CryptHashData returns ERROR_INVALID_PARAMETER (CAPI)
- FindClass returns null
- QEnableSharedFromThis::sharedFromThis() returns nullptr
- SDL_ttf TTF_OpenFont returns NULL
- QSslSocket and supportsSsl() returns false
- setData returns false for QAbstractProxyModel
- BluetoothGATTSetCharacteristicValue returns E_INVALIDARG or
- PKCS7_sign returns null