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; }
HRESULT Scheduler::StartScheduler(IMFClock *pClock) { if (m_hSchedulerThread != NULL) { return E_UNEXPECTED; } HRESULT hr = S_OK; DWORD dwID = 0; CopyComPointer(m_pClock, pClock); // Set a high the timer resolution (ie, short timer period). timeBeginPeriod(1); // Create an event to wait for the thread to start. m_hThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hThreadReadyEvent == NULL) { CHECK_HR(hr = HRESULT_FROM_WIN32(GetLastError())); } // Create an event to wait for flush commands to complete. m_hFlushEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hFlushEvent == NULL) { CHECK_HR(hr = HRESULT_FROM_WIN32(GetLastError())); } // Create the scheduler thread. m_hSchedulerThread = CreateThread(NULL, 0, SchedulerThreadProc, (LPVOID)this, 0, &dwID); if (m_hSchedulerThread == NULL) { CHECK_HR(hr = HRESULT_FROM_WIN32(GetLastError())); } HANDLE hObjects[] = { m_hThreadReadyEvent, m_hSchedulerThread }; DWORD dwWait = 0; // Wait for the thread to signal the "thread ready" event. dwWait = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE); // Wait for EITHER of these handles. if (WAIT_OBJECT_0 != dwWait) { // The thread terminated early for some reason. This is an error condition. CloseHandle(m_hSchedulerThread); m_hSchedulerThread = NULL; CHECK_HR(hr = E_UNEXPECTED); } m_dwThreadID = dwID; done: // Regardless success/failure, we are done using the "thread ready" event. if (m_hThreadReadyEvent) { CloseHandle(m_hThreadReadyEvent); m_hThreadReadyEvent = NULL; } return hr; }
HRESULT D3DPresentEngine::PresentSample(IMFSample* pSample, LONGLONG llTarget) { HRESULT hr = S_OK; IMFMediaBuffer* pBuffer = NULL; IDirect3DSurface9* pSurface = NULL; // IDirect3DSwapChain9* pSwapChain = NULL; IDirect3DSurface9 * back_buffer = 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)); CHECK_HR(hr = m_pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer)); CHECK_HR(hr = m_pDevice->StretchRect(pSurface, NULL, back_buffer, NULL, D3DTEXF_LINEAR)); CHECK_HR(hr = m_pDevice->Present(NULL, NULL, NULL, NULL)); // Store this pointer in case we need to repaint the surface. CopyComPointer(m_pSurfaceRepaint, pSurface); } else { // No surface. All we can do is paint a black rectangle. PaintFrameWithGDI(); } done: // SAFE_RELEASE(pSwapChain); SAFE_RELEASE(pSurface); SAFE_RELEASE(pBuffer); SAFE_RELEASE(back_buffer); if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET || hr == D3DERR_DEVICEHUNG) { // We failed because the device was lost. Fill the destination rectangle. PaintFrameWithGDI(); // 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; }