STDMETHODIMP CDecDXVA2::Flush() { CDecAvcodec::Flush(); FlushDisplayQueue(FALSE); #ifdef DEBUG int used = 0; for (int i = 0; i < m_NumSurfaces; i++) { d3d_surface_t *s = &m_pSurfaces[i]; if (s->used) { used++; } } if (used > 0) { DbgLog((LOG_TRACE, 10, L"WARNING! %d frames still in use after flush", used)); } #endif // This solves an issue with corruption after seeks on AMD systems, see JIRA LAV-5 if (m_dwVendorId == VEND_ID_ATI && m_nCodecId == AV_CODEC_ID_H264 && m_pDecoder) { if (m_bNative && m_pDXVA2Allocator) { // The allocator needs to be locked because flushes can happen async to other graph events // and in the worst case the allocator is decommited while we're using it. CAutoLock allocatorLock(m_pDXVA2Allocator); if (m_pDXVA2Allocator->IsCommited()) CreateDXVA2Decoder(m_NumSurfaces, m_pRawSurface); } else if(!m_bNative) CreateDXVA2Decoder(); } return S_OK; }
STDMETHODIMP CDecDXVA2::Flush() { CDecAvcodec::Flush(); FlushDisplayQueue(FALSE); #ifdef DEBUG int used = 0; for (int i = 0; i < m_NumSurfaces; i++) { d3d_surface_t *s = &m_pSurfaces[i]; if (s->used) { used++; } } if (used > 0) { DbgLog((LOG_TRACE, 10, L"WARNING! %d frames still in use after flush", used)); } #endif // This solves an issue with corruption after seeks on AMD systems, see JIRA LAV-5 if (m_dwVendorId == VEND_ID_ATI && m_nCodecId == AV_CODEC_ID_H264 && m_pDecoder) { if (m_bNative && m_pDXVA2Allocator && m_pDXVA2Allocator->IsCommited()) CreateDXVA2Decoder(m_NumSurfaces, m_pRawSurface); else if(!m_bNative) CreateDXVA2Decoder(); } return S_OK; }
HRESULT CDecDXVA2::ReInitDXVA2Decoder(AVCodecContext *c) { HRESULT hr = S_OK; // Don't allow decoder creation during first init if (m_bInInit) return S_FALSE; if (!m_pDecoder || GetAlignedDimension(c->coded_width) != m_dwSurfaceWidth || GetAlignedDimension(c->coded_height) != m_dwSurfaceHeight) { DbgLog((LOG_TRACE, 10, L"No DXVA2 Decoder or image dimensions changed -> Re-Allocating resources")); if (!m_pDecoder && m_bNative && !m_pDXVA2Allocator) { ASSERT(0); hr = E_FAIL; } else if (m_bNative) { avcodec_flush_buffers(c); m_dwSurfaceWidth = GetAlignedDimension(c->coded_width); m_dwSurfaceHeight = GetAlignedDimension(c->coded_height); // Re-Commit the allocator (creates surfaces and new decoder) hr = m_pDXVA2Allocator->Decommit(); if (m_pDXVA2Allocator->DecommitInProgress()) { DbgLog((LOG_TRACE, 10, L"WARNING! DXVA2 Allocator is still busy, trying to flush downstream")); m_pCallback->ReleaseAllDXVAResources(); m_pCallback->GetOutputPin()->GetConnected()->BeginFlush(); m_pCallback->GetOutputPin()->GetConnected()->EndFlush(); if (m_pDXVA2Allocator->DecommitInProgress()) { DbgLog((LOG_TRACE, 10, L"WARNING! Flush had no effect, decommit of the allocator still not complete")); } else { DbgLog((LOG_TRACE, 10, L"Flush was successfull, decommit completed!")); } } hr = m_pDXVA2Allocator->Commit(); } else if (!m_bNative) { if (SyncToProcessThread() == S_FALSE) FlushDisplayQueue(TRUE); hr = CreateDXVA2Decoder(); } } return hr; }