HRESULT CDecDXVA2::CheckHWCompatConditions(GUID decoderGuid) { int width_mbs = m_dwSurfaceWidth / 16; int height_mbs = m_dwSurfaceHeight / 16; int max_ref_frames_dpb41 = min(11, 32768 / (width_mbs * height_mbs)); if (m_dwVendorId == VEND_ID_ATI) { if (m_dwSurfaceWidth > 1920 || m_dwSurfaceHeight > 1200) { DbgLog((LOG_TRACE, 10, L"-> UHD/4K resolutions blacklisted on AMD/ATI GPUs")); return E_FAIL; } else if (IsAMDUVD(m_dwDeviceId)) { if (m_pAVCtx->codec_id == AV_CODEC_ID_H264 && m_pAVCtx->refs > max_ref_frames_dpb41) { DbgLog((LOG_TRACE, 10, L"-> Too many reference frames for AMD UVD/UVD+ H.264 decoder")); return E_FAIL; } else if (m_pAVCtx->codec_id == AV_CODEC_ID_WMV3) { DbgLog((LOG_TRACE, 10, L"-> AMD UVD/UVD+ is currently not compatible with WMV3")); return E_FAIL; } } } else if (m_dwVendorId == VEND_ID_INTEL && decoderGuid == DXVADDI_Intel_ModeH264_E) { if (m_pAVCtx->codec_id == AV_CODEC_ID_H264 && m_pAVCtx->refs > max_ref_frames_dpb41) { DbgLog((LOG_TRACE, 10, L"-> Too many reference frames for Intel H.264 decoder implementation")); return E_FAIL; } } return S_OK; }
HRESULT CDecDXVA2::FillHWContext(dxva_context *ctx) { ctx->cfg = &m_DXVAVideoDecoderConfig; ctx->decoder = m_pDecoder; ctx->surface = m_pRawSurface; ctx->surface_count = m_NumSurfaces; if (m_dwVendorId == VEND_ID_INTEL && m_guidDecoderDevice == DXVADDI_Intel_ModeH264_E) ctx->workaround = FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; else if (m_dwVendorId == VEND_ID_ATI && IsAMDUVD(m_dwDeviceId)) ctx->workaround = FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG; else ctx->workaround = 0; return S_OK; }
HRESULT CDecDXVA2::CreateDXVA2Decoder(int nSurfaces, IDirect3DSurface9 **ppSurfaces) { DbgLog((LOG_TRACE, 10, L"-> CDecDXVA2::CreateDXVA2Decoder")); HRESULT hr = S_OK; LPDIRECT3DSURFACE9 pSurfaces[DXVA2_MAX_SURFACES]; if (!m_pDXVADecoderService) return E_FAIL; DestroyDecoder(false, true); GUID input = GUID_NULL; D3DFORMAT output; FindVideoServiceConversion(m_pAVCtx->codec_id, &input, &output); if (!nSurfaces) { m_dwSurfaceWidth = FFALIGN(m_pAVCtx->coded_width, 16); m_dwSurfaceHeight = FFALIGN(m_pAVCtx->coded_height, 16); m_NumSurfaces = GetBufferCount(); hr = m_pDXVADecoderService->CreateSurface(m_dwSurfaceWidth, m_dwSurfaceHeight, m_NumSurfaces - 1, output, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, pSurfaces, NULL); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Creation of surfaces failed with hr: %X", hr)); m_NumSurfaces = 0; return E_FAIL; } ppSurfaces = pSurfaces; } else { m_NumSurfaces = nSurfaces; for (int i = 0; i < m_NumSurfaces; i++) { ppSurfaces[i]->AddRef(); } } for (int i = 0; i < m_NumSurfaces; i++) { m_pSurfaces[i].index = i; m_pSurfaces[i].d3d = ppSurfaces[i]; m_pSurfaces[i].age = 0; m_pSurfaces[i].used = false; } DbgLog((LOG_TRACE, 10, L"-> Successfully created %d surfaces (%dx%d)", m_NumSurfaces, m_dwSurfaceWidth, m_dwSurfaceHeight)); DXVA2_VideoDesc desc; ZeroMemory(&desc, sizeof(desc)); desc.SampleWidth = m_pAVCtx->coded_width; desc.SampleHeight = m_pAVCtx->coded_height; desc.Format = output; hr = FindDecoderConfiguration(input, &desc, &m_DXVAVideoDecoderConfig); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> FindDecoderConfiguration failed with hr: %X", hr)); return hr; } IDirectXVideoDecoder *decoder = NULL; hr = m_pDXVADecoderService->CreateVideoDecoder(input, &desc, &m_DXVAVideoDecoderConfig, ppSurfaces, m_NumSurfaces, &decoder); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> CreateVideoDecoder failed with hr: %X", hr)); return E_FAIL; } m_pDecoder = decoder; /* fill hwaccel_context */ dxva_context *ctx = (dxva_context *)m_pAVCtx->hwaccel_context; ctx->cfg = &m_DXVAVideoDecoderConfig; ctx->decoder = m_pDecoder; ctx->surface = m_pRawSurface; ctx->surface_count = m_NumSurfaces; if (m_dwVendorId == VEND_ID_INTEL && input == DXVADDI_Intel_ModeH264_E) ctx->workaround = FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; else if (m_dwVendorId == VEND_ID_ATI && IsAMDUVD(m_dwDeviceId)) ctx->workaround = FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG; else ctx->workaround = 0; memset(m_pRawSurface, 0, sizeof(m_pRawSurface)); for (int i = 0; i < m_NumSurfaces; i++) { m_pRawSurface[i] = m_pSurfaces[i].d3d; } return S_OK; }