Original Post
Hi all, I'm trying to get some D3D+DirectShow video texture stuff working, but I don't seem to be getting anywhere. I'm trying to set up VMR-9 renderless rendering, by following the MSDN docs and platform SDK sample. So far I have the following code: I know there's no cleanup code or error handling, this is just to test the concept. My TextureRenderer class is derived from IVMRSurfaceAllocator9 and IVMRImagePresenter9, and its IVMRSurfaceAllocator9 functions are being called just fine. My implementation of IVMRSurfaceAllocator9::AdviseNotify is as follows: If I comment out the call to SetD3DDevice, then it doesn't crash. I get the video rendered in a seperate window. With the call to SetD3DDevice, I get "First-chance exception at 0xbaadf00d in VideoTexture.exe: 0xC0000005: Access violation", which is coming from another thread (Presumably a DirectShow spawned one) with a rather uninteresting call stack: baadf00d() ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes I'm deliberately not Release()ing any of the interfaces I have, and I'm not deleting my TextureRenderer class. I've zipped up my project, which you can download Here (VC2008 project). Does anyone know what could be causing this? I'm pulling my hair out trying to track it down [sad]
bool VideoTexture::Load(LPDIRECT3DDEVICE9 pDevice, const std::wstring& strFilename)
{
// Init COM
HRESULT hResult = CoInitialize(NULL);
if(FAILED(hResult))
{
m_strError = L"Failed to initialize COM. Error: " + Util::Win32ErrorToString(hResult);
return false;
}
// Create the filter graph
IGraphBuilder* pGraphBuilder;
hResult = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
__uuidof(IGraphBuilder), (void**)&pGraphBuilder);
if(FAILED(hResult))
return false;
// Create the VMR-9 filter
IBaseFilter* pVmr = NULL;
hResult = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pVmr);
if(FAILED(hResult))
return false;
// Get filter config interface
IVMRFilterConfig9* pConfig = NULL;
hResult = pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig);
if(FAILED(hResult))
return false;
// Set renderless mode
pConfig->SetNumberOfStreams(1);
hResult = pConfig->SetRenderingMode(VMR9Mode_Renderless);
if(FAILED(hResult))
return false;
IVMRSurfaceAllocatorNotify9* pAllocNotify = NULL;
hResult = pVmr->QueryInterface(IID_IVMRSurfaceAllocatorNotify9, (void**)&pAllocNotify);
if(FAILED(hResult))
return false;
// Create the Texture Renderer object
TextureRenderer* pTextureRenderer = new TextureRenderer(pDevice);
if(FAILED(hResult) || !pTextureRenderer)
return false;
// Let the allocator and the notify know about each other
hResult = pAllocNotify->AdviseSurfaceAllocator(0xcafef00d, pTextureRenderer);
if(FAILED(hResult))
return false;
hResult = pTextureRenderer->AdviseNotify(pAllocNotify);
if(FAILED(hResult))
return false;
hResult = pGraphBuilder->AddFilter(pVmr, L"VMR9");
if(FAILED(hResult))
return false;
IMediaControl* pControl = NULL;
hResult = pGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&pControl);
if(FAILED(hResult))
return false;
hResult = pGraphBuilder->RenderFile(strFilename.c_str(), NULL);
if(FAILED(hResult))
return false;
hResult = pControl->Run();
if(FAILED(hResult))
return false;
return true;
}
HRESULT STDMETHODCALLTYPE TextureRenderer::AdviseNotify(
IVMRSurfaceAllocatorNotify9* pIVMRSurfAllocNotify)
{
m_pSurfAllocNotify = pIVMRSurfAllocNotify;
if(m_pSurfAllocNotify)
{
// Get D3D interface
IDirect3D9* pD3D = NULL;
HRESULT hResult = m_pDevice->GetDirect3D(&pD3D);
if(FAILED(hResult))
return hResult;
// Get monitor for primary display adapter
HMONITOR hMonitor = pD3D->GetAdapterMonitor(D3DADAPTER_DEFAULT);
pD3D->Release();
return m_pSurfAllocNotify->SetD3DDevice(m_pDevice, hMonitor);
}
return S_OK;
}