HRESULT _stdcall InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo *lpAllocInfo, DWORD *lpNumBuffers) { HRESULT hr; //Set the device IDirect3D9* d3d; RealDevice->GetDirect3D(&d3d); hr = pAllocNotify->SetD3DDevice(RealDevice, d3d->GetAdapterMonitor(0)); d3d->Release(); //if(hr!=S_OK) return hr; lpAllocInfo->dwFlags |= VMR9AllocFlag_TextureSurface; lpAllocInfo->Pool = D3DPOOL_SYSTEMMEM; // Ask the VMR-9 to allocate the surfaces for us. hr = pAllocNotify->AllocateSurfaceHelper(lpAllocInfo, lpNumBuffers, &surface); if(hr!=S_OK) return hr; hr=surface->GetContainer(IID_IDirect3DTexture9,(void**)&ptex); if(hr!=S_OK) { TerminateDevice(0); return hr; } RealDevice->CreateTexture(lpAllocInfo->dwWidth,lpAllocInfo->dwHeight,1,0,lpAllocInfo->Format, D3DPOOL_DEFAULT,&tex,NULL); return S_OK; }
HRESULT D3DPresentEngine::PresentSample(IMFSample* pSample, LONGLONG llTarget) { HRESULT hr = S_OK; IMFMediaBuffer* pBuffer = NULL; IDirect3DSurface9* pSurface = NULL; IDirect3DSwapChain9* pSwapChain = NULL; if (pSample) { // Get the buffer from the sample. CHECK_HR(hr = pSample->GetBufferByIndex(0, &pBuffer)); // Get the surface from the buffer. CHECK_HR(hr = MFGetService(pBuffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), (void**)&pSurface)); } else if (m_pSurfaceRepaint) { // Redraw from the last surface. pSurface = m_pSurfaceRepaint; pSurface->AddRef(); } if (pSurface) { // Get the swap chain from the surface. CHECK_HR(hr = pSurface->GetContainer(__uuidof(IDirect3DSwapChain9), (LPVOID*)&pSwapChain)); // Present the swap chain. CHECK_HR(hr = PresentSwapChain(pSwapChain, pSurface)); // Store this pointer in case we need to repaint the surface. CopyComPointer(m_pSurfaceRepaint, pSurface); } done: SAFE_RELEASE(pSwapChain); SAFE_RELEASE(pSurface); SAFE_RELEASE(pBuffer); if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET || hr == D3DERR_DEVICEHUNG) { // Ignore. We need to reset or re-create the device, but this method // is probably being called from the scheduler thread, which is not the // same thread that created the device. The Reset(Ex) method must be // called from the thread that created the device. // The presenter will detect the state when it calls CheckDeviceState() // on the next sample. hr = S_OK; } } return hr; }
// Presents a video frame. HRESULT D3DPresentEngine::PresentSample(IMFSample* pSample, LONGLONG llTarget) { HRESULT hr = S_OK; IMFMediaBuffer* pBuffer = NULL; IDirect3DTexture9* pTexture = NULL; if (pSample) { // Get the buffer from the sample. hr = pSample->GetBufferByIndex(0, &pBuffer); if (SUCCEEDED(hr)) { // Get the surface from the buffer. IDirect3DSurface9* pSurface = NULL; hr = MFGetService(pBuffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), (void**)&pSurface); if (SUCCEEDED(hr)) { // Get the texture from the buffer. pSurface->GetContainer(IID_IDirect3DTexture9, (void**)&pTexture); } } if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET || hr == D3DERR_DEVICEHUNG) { // We failed because the device was lost. // This case is ignored. The Reset(Ex) method must be called from the thread that created the device. // The presenter will detect the state when it calls CheckDeviceState() on the next sample. hr = S_OK; } } else if (m_pTextureRepaint) { // Redraw from the last surface. pTexture = m_pTextureRepaint; pTexture->AddRef(); } hr = m_EVRCallback->PresentSurface(m_Width, m_Height, m_ArX, m_ArY, (DWORD)&pTexture); // Return reference, so C# side can modify the pointer after Dispose() to avoid duplicated releasing. SAFE_RELEASE(pTexture); SAFE_RELEASE(pBuffer); return hr; }