int directx_va_Open(vlc_va_t *va, directx_sys_t *dx_sys, AVCodecContext *ctx, const es_format_t *fmt) { // TODO va->sys = sys; dx_sys->codec_id = ctx->codec_id; vlc_mutex_init( &dx_sys->surface_lock ); /* Load dll*/ dx_sys->hdecoder_dll = LoadLibrary(dx_sys->psz_decoder_dll); if (!dx_sys->hdecoder_dll) { msg_Warn(va, "cannot load DirectX decoder DLL"); goto error; } msg_Dbg(va, "DLLs loaded"); if (dx_sys->d3ddev) { msg_Dbg(va, "Reusing DirectX device"); } else { /* */ if (dx_sys->pf_create_device(va)) { msg_Err(va, "Failed to create DirectX device"); goto error; } msg_Dbg(va, "CreateDevice succeed"); } if (dx_sys->pf_create_device_manager(va)) { msg_Err(va, "D3dCreateDeviceManager failed"); goto error; } if (dx_sys->pf_create_video_service(va)) { msg_Err(va, "DxCreateVideoService failed"); goto error; } /* */ if (FindVideoServiceConversion(va, dx_sys, fmt)) { msg_Err(va, "FindVideoServiceConversion failed"); goto error; } dx_sys->thread_count = ctx->thread_count; return VLC_SUCCESS; error: return VLC_EGENERIC; }
STDMETHODIMP CDecDXVA2::InitDecoder(AVCodecID codec, const CMediaType *pmt) { HRESULT hr = S_OK; DbgLog((LOG_TRACE, 10, L"CDecDXVA2::InitDecoder(): Initializing DXVA2 decoder")); DestroyDecoder(false); m_DisplayDelay = DXVA2_QUEUE_SURFACES; // Reduce display delay for DVD decoding for lower decode latency if (m_pCallback->GetDecodeFlags() & LAV_VIDEO_DEC_FLAG_DVD) m_DisplayDelay /= 2; // If we have a DXVA Decoder, check if its capable // If we don't have one yet, it may be handed to us later, and compat is checked at that point GUID input = GUID_NULL; if (m_pDXVADecoderService) { D3DFORMAT output; hr = FindVideoServiceConversion(codec, &input, &output); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> No decoder device available that can decode codec '%S' to NV12", avcodec_get_name(codec))); return E_FAIL; } } m_bFailHWDecode = FALSE; DbgLog((LOG_TRACE, 10, L"-> Creation of DXVA2 decoder successfull, initializing ffmpeg")); hr = CDecAvcodec::InitDecoder(codec, pmt); if (FAILED(hr)) { return hr; } if (((codec == AV_CODEC_ID_H264 || codec == AV_CODEC_ID_MPEG2VIDEO) && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUV420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUVJ420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_DXVA2_VLD && m_pAVCtx->pix_fmt != AV_PIX_FMT_NONE) || (codec == AV_CODEC_ID_H264 && m_pAVCtx->profile != FF_PROFILE_UNKNOWN && !H264_CHECK_PROFILE(m_pAVCtx->profile))) { DbgLog((LOG_TRACE, 10, L"-> Incompatible profile detected, falling back to software decoding")); return E_FAIL; } m_dwSurfaceWidth = FFALIGN(m_pAVCtx->coded_width, 16); m_dwSurfaceHeight = FFALIGN(m_pAVCtx->coded_height, 16); if (FAILED(CheckHWCompatConditions(input))) { return E_FAIL; } return S_OK; }
int directx_va_Setup(vlc_va_t *va, directx_sys_t *dx_sys, const AVCodecContext *avctx, const es_format_t *fmt) { /* */ if (FindVideoServiceConversion(va, dx_sys, fmt, avctx)) { msg_Err(va, "FindVideoServiceConversion failed"); return VLC_EGENERIC; } int surface_alignment = 16; unsigned surface_count = 2; switch ( avctx->codec_id ) { case AV_CODEC_ID_MPEG2VIDEO: /* decoding MPEG-2 requires additional alignment on some Intel GPUs, but it causes issues for H.264 on certain AMD GPUs..... */ surface_alignment = 32; surface_count += 2; break; case AV_CODEC_ID_HEVC: /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure all coding features have enough room to work with */ surface_alignment = 128; surface_count += 16; break; case AV_CODEC_ID_H264: surface_count += 16; break; default: surface_count += 2; } if ( avctx->active_thread_type & FF_THREAD_FRAME ) surface_count += avctx->thread_count; int err = va_pool_SetupDecoder(va, &dx_sys->va_pool, avctx, surface_count, surface_alignment); if (err != VLC_SUCCESS) return err; if (dx_sys->can_extern_pool) return VLC_SUCCESS; return va_pool_SetupSurfaces(va, &dx_sys->va_pool, surface_count); }
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; }
/** * Called from both native and non-native mode * Initialize all the common DXVA2 interfaces and device handles */ HRESULT CDecDXVA2::SetD3DDeviceManager(IDirect3DDeviceManager9 *pDevManager) { HRESULT hr = S_OK; ASSERT(pDevManager); m_pD3DDevMngr = pDevManager; RetrieveVendorId(pDevManager); // This should really be null here, but since we're overwriting it, make sure its actually released SafeRelease(&m_pDXVADecoderService); hr = CreateDXVAVideoService(m_pD3DDevMngr, &m_pDXVADecoderService); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Creation of DXVA2 Decoder Service failed with hr: %X", hr)); goto done; } // If the decoder was initialized already, check if we can use this device if (m_pAVCtx) { DbgLog((LOG_TRACE, 10, L"-> Checking hardware for format support...")); GUID input = GUID_NULL; D3DFORMAT output; hr = FindVideoServiceConversion(m_pAVCtx->codec_id, &input, &output); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> No decoder device available that can decode codec '%S' to NV12", avcodec_get_name(m_pAVCtx->codec_id))); goto done; } if (FAILED(CheckHWCompatConditions(input))) { hr = E_FAIL; goto done; } DXVA2_VideoDesc desc; ZeroMemory(&desc, sizeof(desc)); desc.SampleWidth = m_pAVCtx->coded_width; desc.SampleHeight = m_pAVCtx->coded_height; desc.Format = output; DXVA2_ConfigPictureDecode config; hr = FindDecoderConfiguration(input, &desc, &config); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> No decoder configuration available for codec '%S'", avcodec_get_name(m_pAVCtx->codec_id))); goto done; } LPDIRECT3DSURFACE9 pSurfaces[DXVA2_MAX_SURFACES] = {0}; UINT numSurfaces = max(config.ConfigMinRenderTargetBuffCount, 1); hr = m_pDXVADecoderService->CreateSurface(m_dwSurfaceWidth, m_dwSurfaceHeight, numSurfaces, output, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, pSurfaces, NULL); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Creation of surfaces failed with hr: %X", hr)); goto done; } IDirectXVideoDecoder *decoder = NULL; hr = m_pDXVADecoderService->CreateVideoDecoder(input, &desc, &config, pSurfaces, numSurfaces, &decoder); // Release resources, decoder and surfaces SafeRelease(&decoder); int i = DXVA2_MAX_SURFACES; while (i > 0) { SafeRelease(&pSurfaces[--i]); } if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Creation of decoder failed with hr: %X", hr)); goto done; } } done: return hr; }
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 = GetAlignedDimension(m_pAVCtx->coded_width); m_dwSurfaceHeight = GetAlignedDimension(m_pAVCtx->coded_height); m_NumSurfaces = GetBufferCount(); hr = m_pDXVADecoderService->CreateSurface(m_dwSurfaceWidth, m_dwSurfaceHeight, m_NumSurfaces - 1, output, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, pSurfaces, nullptr); 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(); } } if (m_NumSurfaces <= 0) { DbgLog((LOG_TRACE, 10, L"-> No surfaces? No good!")); return E_FAIL; } // get the device, for ColorFill() to init the surfaces in black IDirect3DDevice9 *pDev = nullptr; ppSurfaces[0]->GetDevice(&pDev); 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; // fill the surface in black, to avoid the "green screen" in case the first frame fails to decode. if (pDev) pDev->ColorFill(ppSurfaces[i], NULL, D3DCOLOR_XYUV(0, 128, 128)); } // and done with the device SafeRelease(&pDev); 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 = nullptr; 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; m_guidDecoderDevice = input; /* fill hwaccel_context */ FillHWContext((dxva_context *)m_pAVCtx->hwaccel_context); 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; }
STDMETHODIMP CDecDXVA2::InitDecoder(AVCodecID codec, const CMediaType *pmt) { HRESULT hr = S_OK; DbgLog((LOG_TRACE, 10, L"CDecDXVA2::InitDecoder(): Initializing DXVA2 decoder")); // Hack-ish check to avoid re-creating the full decoder when only the aspect ratio changes. // Re-creating the DXVA2 decoder can lead to issues like missing frames or a several second delay if (m_pDecoder) { CMediaType mediaTypeCheck = m_MediaType; if (mediaTypeCheck.formattype == FORMAT_VideoInfo2 && pmt->formattype == FORMAT_VideoInfo2) { VIDEOINFOHEADER2 *vih2Old = (VIDEOINFOHEADER2 *)mediaTypeCheck.Format(); VIDEOINFOHEADER2 *vih2New = (VIDEOINFOHEADER2 *)pmt->Format(); vih2Old->dwPictAspectRatioX = vih2New->dwPictAspectRatioX; vih2Old->dwPictAspectRatioY = vih2New->dwPictAspectRatioY; if (mediaTypeCheck == *pmt) { DbgLog((LOG_TRACE, 10, L"-> Skipping re-init because media type is unchanged.")); m_MediaType = *pmt; return S_OK; } } } DestroyDecoder(false); m_DisplayDelay = DXVA2_QUEUE_SURFACES; // Intel GPUs don't like the display and performance goes way down, so disable it. if (m_dwVendorId == VEND_ID_INTEL) m_DisplayDelay = 0; // Reduce display delay for DVD decoding for lower decode latency if (m_pCallback->GetDecodeFlags() & LAV_VIDEO_DEC_FLAG_DVD) m_DisplayDelay /= 2; // If we have a DXVA Decoder, check if its capable // If we don't have one yet, it may be handed to us later, and compat is checked at that point GUID input = GUID_NULL; if (m_pDXVADecoderService) { D3DFORMAT output; hr = FindVideoServiceConversion(codec, &input, &output); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> No decoder device available that can decode codec '%S' to NV12", avcodec_get_name(codec))); return E_FAIL; } } m_bFailHWDecode = FALSE; DbgLog((LOG_TRACE, 10, L"-> Creation of DXVA2 decoder successfull, initializing ffmpeg")); hr = CDecAvcodec::InitDecoder(codec, pmt); if (FAILED(hr)) { return hr; } if (((codec == AV_CODEC_ID_H264 || codec == AV_CODEC_ID_MPEG2VIDEO || codec == AV_CODEC_ID_HEVC) && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUV420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUVJ420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_DXVA2_VLD && m_pAVCtx->pix_fmt != AV_PIX_FMT_NONE) || (codec == AV_CODEC_ID_H264 && m_pAVCtx->profile != FF_PROFILE_UNKNOWN && !H264_CHECK_PROFILE(m_pAVCtx->profile)) || ((codec == AV_CODEC_ID_WMV3 || codec == AV_CODEC_ID_VC1) && m_pAVCtx->profile == FF_PROFILE_VC1_COMPLEX) || (codec == AV_CODEC_ID_HEVC && !HEVC_CHECK_PROFILE(m_pAVCtx->profile))) { DbgLog((LOG_TRACE, 10, L"-> Incompatible profile detected, falling back to software decoding")); return E_FAIL; } m_dwSurfaceWidth = GetAlignedDimension(m_pAVCtx->coded_width); m_dwSurfaceHeight = GetAlignedDimension(m_pAVCtx->coded_height); if (FAILED(CheckHWCompatConditions(input))) { return E_FAIL; } m_MediaType = *pmt; return S_OK; }
STDMETHODIMP CDecD3D11::CreateD3D11Decoder() { HRESULT hr = S_OK; AVD3D11VADeviceContext *pDeviceContext = (AVD3D11VADeviceContext *)((AVHWDeviceContext *)m_pDevCtx->data)->hwctx; // release the old decoder, it needs to be re-created SafeRelease(&m_pDecoder); // find a decoder configuration GUID profileGUID = GUID_NULL; DXGI_FORMAT surface_format = d3d11va_map_sw_to_hw_format(m_pAVCtx->sw_pix_fmt); hr = FindVideoServiceConversion(m_pAVCtx->codec_id, m_pAVCtx->profile, surface_format, &profileGUID); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"-> No video service profile found")); return hr; } // get decoder configuration D3D11_VIDEO_DECODER_DESC desc = { 0 }; desc.Guid = profileGUID; desc.OutputFormat = surface_format; desc.SampleWidth = m_pAVCtx->coded_width; desc.SampleHeight = m_pAVCtx->coded_height; D3D11_VIDEO_DECODER_CONFIG decoder_config = { 0 }; hr = FindDecoderConfiguration(&desc, &decoder_config); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"-> No valid video decoder configuration found")); return hr; } m_DecoderConfig = decoder_config; // update surface properties m_dwSurfaceWidth = dxva_align_dimensions(m_pAVCtx->codec_id, m_pAVCtx->coded_width); m_dwSurfaceHeight = dxva_align_dimensions(m_pAVCtx->codec_id, m_pAVCtx->coded_height); m_DecodePixelFormat = m_pAVCtx->sw_pix_fmt; m_SurfaceFormat = surface_format; if (m_bReadBackFallback == false && m_pAllocator) { ALLOCATOR_PROPERTIES properties; hr = m_pAllocator->GetProperties(&properties); if (FAILED(hr)) return hr; m_dwSurfaceCount = properties.cBuffers; } else { m_dwSurfaceCount = GetBufferCount(); } // allocate a new frames context for the dimensions and format hr = AllocateFramesContext(m_dwSurfaceWidth, m_dwSurfaceHeight, m_DecodePixelFormat, m_dwSurfaceCount, &m_pFramesCtx); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"-> Error allocating frames context")); return hr; } // release any old output views and allocate memory for the new ones if (m_pOutputViews) { for (int i = 0; i < m_nOutputViews; i++) { SafeRelease(&m_pOutputViews[i]); } av_freep(&m_pOutputViews); } m_pOutputViews = (ID3D11VideoDecoderOutputView **)av_mallocz_array(m_dwSurfaceCount, sizeof(*m_pOutputViews)); m_nOutputViews = m_dwSurfaceCount; // allocate output views for the frames AVD3D11VAFramesContext *pFramesContext = (AVD3D11VAFramesContext *)((AVHWFramesContext *)m_pFramesCtx->data)->hwctx; for (int i = 0; i < m_nOutputViews; i++) { D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc = { 0 }; viewDesc.DecodeProfile = profileGUID; viewDesc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D; viewDesc.Texture2D.ArraySlice = i; hr = pDeviceContext->video_device->CreateVideoDecoderOutputView(pFramesContext->texture, &viewDesc, &m_pOutputViews[i]); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"-> Failed to create video decoder output views")); return E_FAIL; } } // create the decoder hr = pDeviceContext->video_device->CreateVideoDecoder(&desc, &decoder_config, &m_pDecoder); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"-> Failed to create video decoder object")); return E_FAIL; } FillHWContext((AVD3D11VAContext *)m_pAVCtx->hwaccel_context); return S_OK; }
STDMETHODIMP CDecD3D11::PostConnect(IPin *pPin) { DbgLog((LOG_TRACE, 10, L"CDecD3D11::PostConnect()")); HRESULT hr = S_OK; ID3D11DecoderConfiguration *pD3D11DecoderConfiguration = nullptr; hr = pPin->QueryInterface(&pD3D11DecoderConfiguration); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"-> ID3D11DecoderConfiguration not available, using fallback mode")); } // Release old D3D resources, we're about to re-init m_pCallback->ReleaseAllDXVAResources(); // free the decoder to force a re-init down the line SafeRelease(&m_pDecoder); // and the old device av_buffer_unref(&m_pDevCtx); // device id UINT nDevice = m_pSettings->GetHWAccelDeviceIndex(HWAccel_D3D11, nullptr); // in automatic mode use the device the renderer gives us if (nDevice == LAVHWACCEL_DEVICE_DEFAULT && pD3D11DecoderConfiguration) { nDevice = pD3D11DecoderConfiguration->GetD3D11AdapterIndex(); } else { // if a device is specified manually, fallback to copy-back and use the selected device SafeRelease(&pD3D11DecoderConfiguration); // use the configured device if (nDevice == LAVHWACCEL_DEVICE_DEFAULT) nDevice = 0; } // create the device ID3D11Device *pD3D11Device = nullptr; hr = CreateD3D11Device(nDevice, &pD3D11Device, &m_AdapterDesc); if (FAILED(hr)) { goto fail; } // allocate and fill device context m_pDevCtx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA); AVD3D11VADeviceContext *pDeviceContext = (AVD3D11VADeviceContext *)((AVHWDeviceContext *)m_pDevCtx->data)->hwctx; pDeviceContext->device = pD3D11Device; // finalize the context int ret = av_hwdevice_ctx_init(m_pDevCtx); if (ret < 0) { av_buffer_unref(&m_pDevCtx); goto fail; } // check if the connection supports native mode if (pD3D11DecoderConfiguration) { CMediaType mt = m_pCallback->GetOutputMediaType(); if ((m_SurfaceFormat == DXGI_FORMAT_NV12 && mt.subtype != MEDIASUBTYPE_NV12) || (m_SurfaceFormat == DXGI_FORMAT_P010 && mt.subtype != MEDIASUBTYPE_P010) || (m_SurfaceFormat == DXGI_FORMAT_P016 && mt.subtype != MEDIASUBTYPE_P016)) { DbgLog((LOG_ERROR, 10, L"-> Connection is not the appropriate pixel format for D3D11 Native")); SafeRelease(&pD3D11DecoderConfiguration); } } // verify hardware support { GUID guidConversion = GUID_NULL; hr = FindVideoServiceConversion(m_pAVCtx->codec_id, m_pAVCtx->profile, m_SurfaceFormat, &guidConversion); if (FAILED(hr)) { goto fail; } // get decoder configuration D3D11_VIDEO_DECODER_DESC desc = { 0 }; desc.Guid = guidConversion; desc.OutputFormat = m_SurfaceFormat; desc.SampleWidth = m_pAVCtx->coded_width; desc.SampleHeight = m_pAVCtx->coded_height; D3D11_VIDEO_DECODER_CONFIG decoder_config = { 0 }; hr = FindDecoderConfiguration(&desc, &decoder_config); if (FAILED(hr)) { goto fail; } // test creating a texture D3D11_TEXTURE2D_DESC texDesc = { 0 }; texDesc.Width = m_pAVCtx->coded_width; texDesc.Height = m_pAVCtx->coded_height; texDesc.MipLevels = 1; texDesc.ArraySize = 10; texDesc.Format = m_SurfaceFormat; texDesc.SampleDesc.Count = 1; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE; texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; ID3D11Texture2D *pTexture2D = nullptr; hr = pD3D11Device->CreateTexture2D(&texDesc, nullptr, &pTexture2D); if (FAILED(hr)) { goto fail; } SafeRelease(&pTexture2D); } // Notice the connected pin that we're sending D3D11 textures if (pD3D11DecoderConfiguration) { hr = pD3D11DecoderConfiguration->ActivateD3D11Decoding(pDeviceContext->device, pDeviceContext->device_context, pDeviceContext->lock_ctx, 0); SafeRelease(&pD3D11DecoderConfiguration); m_bReadBackFallback = FAILED(hr); } else { m_bReadBackFallback = true; } return S_OK; fail: SafeRelease(&pD3D11DecoderConfiguration); return E_FAIL; }