/** * It creates a DXVA2 decoder using the given video format */ static int DxCreateVideoDecoder(vlc_va_t *va, int codec_id, const video_format_t *fmt) { vlc_va_sys_t *sys = va->sys; /* */ msg_Dbg(va, "DxCreateVideoDecoder id %d %dx%d", codec_id, fmt->i_width, fmt->i_height); sys->width = fmt->i_width; sys->height = fmt->i_height; /* Allocates all surfaces needed for the decoder */ sys->surface_width = (fmt->i_width + 15) & ~15; sys->surface_height = (fmt->i_height + 15) & ~15; int surface_count; switch (codec_id) { case AV_CODEC_ID_H264: surface_count = 16 + sys->thread_count + 2; break; case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: surface_count = 2 + 2; break; default: surface_count = 2 + 1; break; } if (surface_count > VA_DXVA2_MAX_SURFACE_COUNT) return VLC_EGENERIC; sys->surface_count = surface_count; if (FAILED(IDirectXVideoDecoderService_CreateSurface(sys->vs, sys->surface_width, sys->surface_height, sys->surface_count - 1, sys->render, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, sys->hw_surface, NULL))) { msg_Err(va, "IDirectXVideoAccelerationService_CreateSurface failed"); sys->surface_count = 0; return VLC_EGENERIC; } for (unsigned i = 0; i < sys->surface_count; i++) { vlc_va_surface_t *surface = &sys->surface[i]; surface->d3d = sys->hw_surface[i]; surface->refcount = 0; surface->order = 0; } msg_Dbg(va, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)", sys->surface_count, fmt->i_width, fmt->i_height); /* */ DXVA2_VideoDesc dsc; ZeroMemory(&dsc, sizeof(dsc)); dsc.SampleWidth = fmt->i_width; dsc.SampleHeight = fmt->i_height; dsc.Format = sys->render; if (fmt->i_frame_rate > 0 && fmt->i_frame_rate_base > 0) { dsc.InputSampleFreq.Numerator = fmt->i_frame_rate; dsc.InputSampleFreq.Denominator = fmt->i_frame_rate_base; } else { dsc.InputSampleFreq.Numerator = 0; dsc.InputSampleFreq.Denominator = 0; } dsc.OutputFrameFreq = dsc.InputSampleFreq; dsc.UABProtectionLevel = FALSE; dsc.Reserved = 0; /* FIXME I am unsure we can let unknown everywhere */ DXVA2_ExtendedFormat *ext = &dsc.SampleFormat; ext->SampleFormat = 0;//DXVA2_SampleUnknown; ext->VideoChromaSubsampling = 0;//DXVA2_VideoChromaSubsampling_Unknown; ext->NominalRange = 0;//DXVA2_NominalRange_Unknown; ext->VideoTransferMatrix = 0;//DXVA2_VideoTransferMatrix_Unknown; ext->VideoLighting = 0;//DXVA2_VideoLighting_Unknown; ext->VideoPrimaries = 0;//DXVA2_VideoPrimaries_Unknown; ext->VideoTransferFunction = 0;//DXVA2_VideoTransFunc_Unknown; /* List all configurations available for the decoder */ UINT cfg_count = 0; DXVA2_ConfigPictureDecode *cfg_list = NULL; if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(sys->vs, &sys->input, &dsc, NULL, &cfg_count, &cfg_list))) { msg_Err(va, "IDirectXVideoDecoderService_GetDecoderConfigurations failed"); return VLC_EGENERIC; } msg_Dbg(va, "we got %d decoder configurations", cfg_count); /* Select the best decoder configuration */ int cfg_score = 0; for (unsigned i = 0; i < cfg_count; i++) { const DXVA2_ConfigPictureDecode *cfg = &cfg_list[i]; /* */ msg_Dbg(va, "configuration[%d] ConfigBitstreamRaw %d", i, cfg->ConfigBitstreamRaw); /* */ int score; if (cfg->ConfigBitstreamRaw == 1) score = 1; else if (codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2) score = 2; else continue; if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA_NoEncrypt)) score += 16; if (cfg_score < score) { sys->cfg = *cfg; cfg_score = score; } } CoTaskMemFree(cfg_list); if (cfg_score <= 0) { msg_Err(va, "Failed to find a supported decoder configuration"); return VLC_EGENERIC; } /* Create the decoder */ IDirectXVideoDecoder *decoder; if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(sys->vs, &sys->input, &dsc, &sys->cfg, sys->hw_surface, sys->surface_count, &decoder))) { msg_Err(va, "IDirectXVideoDecoderService_CreateVideoDecoder failed"); return VLC_EGENERIC; } sys->decoder = decoder; msg_Dbg(va, "IDirectXVideoDecoderService_CreateVideoDecoder succeed"); return VLC_SUCCESS; }
/** * It creates a DXVA2 decoder using the given video format */ static int DxCreateVideoDecoder(vlc_va_t *va, int codec_id, const video_format_t *fmt, bool b_threading) { VLC_UNUSED(b_threading); vlc_va_sys_t *p_sys = va->sys; directx_sys_t *sys = &va->sys->dx_sys; HRESULT hr; hr = IDirectXVideoDecoderService_CreateSurface((IDirectXVideoDecoderService*) sys->d3ddec, sys->surface_width, sys->surface_height, sys->surface_count - 1, p_sys->render, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, (LPDIRECT3DSURFACE9*) sys->hw_surface, NULL); if (FAILED(hr)) { msg_Err(va, "IDirectXVideoAccelerationService_CreateSurface %d failed (hr=0x%0lx)", sys->surface_count - 1, hr); sys->surface_count = 0; return VLC_EGENERIC; } msg_Dbg(va, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)", sys->surface_count, sys->surface_width, sys->surface_height); IDirect3DSurface9 *tstCrash; hr = IDirectXVideoDecoderService_CreateSurface((IDirectXVideoDecoderService*) sys->d3ddec, sys->surface_width, sys->surface_height, 0, p_sys->render, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, &tstCrash, NULL); if (FAILED(hr)) { msg_Err(va, "extra buffer impossible, avoid a crash (hr=0x%0lx)", hr); for (int i = 0; i < sys->surface_count; i++) IDirect3DSurface9_Release( (IDirect3DSurface9*) sys->hw_surface[i] ); sys->surface_count = 0; return VLC_EGENERIC; } IDirect3DSurface9_Release(tstCrash); /* */ DXVA2_VideoDesc dsc; ZeroMemory(&dsc, sizeof(dsc)); dsc.SampleWidth = fmt->i_width; dsc.SampleHeight = fmt->i_height; dsc.Format = p_sys->render; if (fmt->i_frame_rate > 0 && fmt->i_frame_rate_base > 0) { dsc.InputSampleFreq.Numerator = fmt->i_frame_rate; dsc.InputSampleFreq.Denominator = fmt->i_frame_rate_base; } else { dsc.InputSampleFreq.Numerator = 0; dsc.InputSampleFreq.Denominator = 0; } dsc.OutputFrameFreq = dsc.InputSampleFreq; dsc.UABProtectionLevel = FALSE; dsc.Reserved = 0; /* FIXME I am unsure we can let unknown everywhere */ DXVA2_ExtendedFormat *ext = &dsc.SampleFormat; ext->SampleFormat = 0;//DXVA2_SampleUnknown; ext->VideoChromaSubsampling = 0;//DXVA2_VideoChromaSubsampling_Unknown; ext->NominalRange = 0;//DXVA2_NominalRange_Unknown; ext->VideoTransferMatrix = 0;//DXVA2_VideoTransferMatrix_Unknown; ext->VideoLighting = 0;//DXVA2_VideoLighting_Unknown; ext->VideoPrimaries = 0;//DXVA2_VideoPrimaries_Unknown; ext->VideoTransferFunction = 0;//DXVA2_VideoTransFunc_Unknown; /* List all configurations available for the decoder */ UINT cfg_count = 0; DXVA2_ConfigPictureDecode *cfg_list = NULL; if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations((IDirectXVideoDecoderService*) sys->d3ddec, &sys->input, &dsc, NULL, &cfg_count, &cfg_list))) { msg_Err(va, "IDirectXVideoDecoderService_GetDecoderConfigurations failed"); for (int i = 0; i < sys->surface_count; i++) IDirect3DSurface9_Release( (IDirect3DSurface9*) sys->hw_surface[i] ); sys->surface_count = 0; return VLC_EGENERIC; } msg_Dbg(va, "we got %d decoder configurations", cfg_count); /* Select the best decoder configuration */ int cfg_score = 0; for (unsigned i = 0; i < cfg_count; i++) { const DXVA2_ConfigPictureDecode *cfg = &cfg_list[i]; /* */ msg_Dbg(va, "configuration[%d] ConfigBitstreamRaw %d", i, cfg->ConfigBitstreamRaw); /* */ int score; if (cfg->ConfigBitstreamRaw == 1) score = 1; else if (codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2) score = 2; else continue; if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt)) score += 16; if (cfg_score < score) { p_sys->cfg = *cfg; cfg_score = score; } } CoTaskMemFree(cfg_list); if (cfg_score <= 0) { msg_Err(va, "Failed to find a supported decoder configuration"); return VLC_EGENERIC; } /* Create the decoder */ IDirectXVideoDecoder *decoder; if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder((IDirectXVideoDecoderService*) sys->d3ddec, &sys->input, &dsc, &p_sys->cfg, (LPDIRECT3DSURFACE9*) sys->hw_surface, sys->surface_count, &decoder))) { msg_Err(va, "IDirectXVideoDecoderService_CreateVideoDecoder failed"); for (int i = 0; i < sys->surface_count; i++) IDirect3DSurface9_Release( (IDirect3DSurface9*) sys->hw_surface[i] ); sys->surface_count = 0; return VLC_EGENERIC; } sys->decoder = (IUnknown*) decoder; msg_Dbg(va, "IDirectXVideoDecoderService_CreateVideoDecoder succeed"); return VLC_SUCCESS; }
/** * It creates a DXVA2 decoder using the given video format */ static int hb_dx_create_video_decoder( hb_va_dxva2_t *dxva2, int codec_id, const hb_title_t* fmt ) { dxva2->width = fmt->width; dxva2->height = fmt->height; dxva2->surface_width = (fmt->width + 15) & ~15; dxva2->surface_height = (fmt->height + 15) & ~15; switch( codec_id ) { case AV_CODEC_ID_H264: dxva2->surface_count = 16 + 1; break; default: dxva2->surface_count = 2 + 1; break; } LPDIRECT3DSURFACE9 surface_list[VA_DXVA2_MAX_SURFACE_COUNT]; if( FAILED( IDirectXVideoDecoderService_CreateSurface( dxva2->vs, dxva2->surface_width, dxva2->surface_height, dxva2->surface_count - 1, dxva2->render, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, surface_list, NULL ))) { hb_log( "dxva2:IDirectXVideoAccelerationService_CreateSurface failed" ); dxva2->surface_count = 0; return HB_WORK_ERROR; } unsigned i; for( i = 0; i<dxva2->surface_count; i++ ) { hb_va_surface_t *surface = &dxva2->surface[i]; surface->d3d = surface_list[i]; surface->refcount = 0; surface->order = 0; } hb_log( "dxva2:CreateSurface succeed with %d, fmt (%dx%d) surfaces (%dx%d)", dxva2->surface_count, fmt->width, fmt->height, dxva2->surface_width, dxva2->surface_height ); DXVA2_VideoDesc dsc; memset( &dsc, 0, sizeof(dsc)); dsc.SampleWidth = fmt->width; dsc.SampleHeight = fmt->height; dsc.Format = dxva2->render; if( fmt->rate> 0 && fmt->rate_base> 0 ) { dsc.InputSampleFreq.Numerator = fmt->rate; dsc.InputSampleFreq.Denominator = fmt->rate_base; } else { dsc.InputSampleFreq.Numerator = 0; dsc.InputSampleFreq.Denominator = 0; } dsc.OutputFrameFreq = dsc.InputSampleFreq; dsc.UABProtectionLevel = FALSE; dsc.Reserved = 0; /* FIXME I am unsure we can let unknown everywhere */ DXVA2_ExtendedFormat *ext = &dsc.SampleFormat; ext->SampleFormat = 0; //DXVA2_SampleUnknown; ext->VideoChromaSubsampling = 0; //DXVA2_VideoChromaSubsampling_Unknown; ext->NominalRange = 0; //DXVA2_NominalRange_Unknown; ext->VideoTransferMatrix = 0; //DXVA2_VideoTransferMatrix_Unknown; ext->VideoLighting = 0; //DXVA2_VideoLighting_Unknown; ext->VideoPrimaries = 0; //DXVA2_VideoPrimaries_Unknown; ext->VideoTransferFunction = 0; //DXVA2_VideoTransFunc_Unknown; /* List all configurations available for the decoder */ UINT cfg_count = 0; DXVA2_ConfigPictureDecode *cfg_list = NULL; if( FAILED( IDirectXVideoDecoderService_GetDecoderConfigurations( dxva2->vs, &dxva2->input, &dsc, NULL, &cfg_count, &cfg_list ))) { hb_log( "dxva2:IDirectXVideoDecoderService_GetDecoderConfigurations failed" ); return HB_WORK_ERROR; } hb_log( "dxva2:we got %d decoder configurations", cfg_count ); /* Select the best decoder configuration */ int cfg_score = 0; for( i = 0; i < cfg_count; i++ ) { const DXVA2_ConfigPictureDecode *cfg = &cfg_list[i]; hb_log( "dxva2:configuration[%d] ConfigBitstreamRaw %d", i, cfg->ConfigBitstreamRaw ); int score; if( cfg->ConfigBitstreamRaw == 1 ) score = 1; else if( codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2 ) score = 2; else continue; if( IsEqualGUID( &cfg->guidConfigBitstreamEncryption, &DXVA_NoEncrypt )) score += 16; if( cfg_score < score ) { dxva2->cfg = *cfg; cfg_score = score; } } //my_release(cfg_list); if( cfg_score <= 0 ) { hb_log( "dxva2:Failed to find a supported decoder configuration" ); return HB_WORK_ERROR; } /* Create the decoder */ IDirectXVideoDecoder *decoder; if( FAILED( IDirectXVideoDecoderService_CreateVideoDecoder( dxva2->vs, &dxva2->input, &dsc, &dxva2->cfg, surface_list, dxva2->surface_count, &decoder ))) { hb_log( "dxva2:IDirectXVideoDecoderService_CreateVideoDecoder failed" ); return HB_WORK_ERROR; } dxva2->decoder = decoder; hb_log( "dxva2:IDirectXVideoDecoderService_CreateVideoDecoder succeed" ); return HB_WORK_OK; }
static int dxva2_init_decoder(struct lavc_ctx *s, int w, int h) { HRESULT hr; int ret = -1; struct priv *p = s->hwdec_priv; TA_FREEP(&p->decoder_pool); int n_surfaces = hwdec_get_max_refs(s) + ADDITIONAL_SURFACES; IDirect3DSurface9 **surfaces = NULL; IDirectXVideoDecoder *decoder = NULL; void *tmp = talloc_new(NULL); UINT n_guids; GUID *device_guids; hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids( p->decoder_service, &n_guids, &device_guids); if (FAILED(hr)) { MP_ERR(p, "Failed to retrieve decoder device GUIDs: %s\n", mp_HRESULT_to_str(hr)); goto done; } dump_decoder_info(s, device_guids, n_guids); struct d3d_decoder_fmt fmt = d3d_select_decoder_mode(s, device_guids, n_guids, get_dxfmt_cb); CoTaskMemFree(device_guids); if (fmt.mpfmt_decoded == IMGFMT_NONE) { MP_ERR(p, "Failed to find a suitable decoder\n"); goto done; } p->mpfmt_decoded = fmt.mpfmt_decoded; struct mp_image_pool *decoder_pool = talloc_steal(tmp, mp_image_pool_new(n_surfaces)); DXVA2_ConfigPictureDecode *decoder_config = talloc_zero(decoder_pool, DXVA2_ConfigPictureDecode); int w_align = w, h_align = h; d3d_surface_align(s, &w_align, &h_align); DXVA2_VideoDesc video_desc ={ .SampleWidth = w, .SampleHeight = h, .Format = fmt.dxfmt_decoded, }; UINT n_configs = 0; DXVA2_ConfigPictureDecode *configs = NULL; hr = IDirectXVideoDecoderService_GetDecoderConfigurations( p->decoder_service, fmt.guid, &video_desc, NULL, &n_configs, &configs); if (FAILED(hr)) { MP_ERR(p, "Unable to retrieve decoder configurations: %s\n", mp_HRESULT_to_str(hr)); goto done; } unsigned max_score = 0; for (UINT i = 0; i < n_configs; i++) { unsigned score = d3d_decoder_config_score( s, &configs[i].guidConfigBitstreamEncryption, configs[i].ConfigBitstreamRaw); if (score > max_score) { max_score = score; *decoder_config = configs[i]; } } CoTaskMemFree(configs); if (!max_score) { MP_ERR(p, "Failed to find a suitable decoder configuration\n"); goto done; } surfaces = talloc_zero_array(decoder_pool, IDirect3DSurface9*, n_surfaces); hr = IDirectXVideoDecoderService_CreateSurface( p->decoder_service, w_align, h_align, n_surfaces - 1, fmt.dxfmt_decoded, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, surfaces, NULL); if (FAILED(hr)) { MP_ERR(p, "Failed to create %d video surfaces: %s\n", n_surfaces, mp_HRESULT_to_str(hr)); goto done; } hr = IDirectXVideoDecoderService_CreateVideoDecoder( p->decoder_service, fmt.guid, &video_desc, decoder_config, surfaces, n_surfaces, &decoder); if (FAILED(hr)) { MP_ERR(p, "Failed to create DXVA2 video decoder: %s\n", mp_HRESULT_to_str(hr)); goto done; } for (int i = 0; i < n_surfaces; i++) { struct mp_image *img = dxva2_new_ref(decoder, surfaces[i], w, h); if (!img) { MP_ERR(p, "Failed to create DXVA2 image\n"); goto done; } mp_image_pool_add(decoder_pool, img); // transferred to pool } // Pass required information on to ffmpeg. struct dxva_context *dxva_ctx = s->avctx->hwaccel_context; dxva_ctx->cfg = decoder_config; dxva_ctx->decoder = decoder; dxva_ctx->surface_count = n_surfaces; dxva_ctx->surface = surfaces; dxva_ctx->workaround = is_clearvideo(fmt.guid) ? FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO : 0; p->decoder_pool = talloc_steal(NULL, decoder_pool); ret = 0; done: // On success, `p->decoder_pool` mp_images still hold refs to `surfaces` and // `decoder`, so the pointers in the ffmpeg `dxva_context` strcture remain // valid for the lifetime of the pool. if (surfaces) { for (int i = 0; i < n_surfaces; i++) IDirect3DSurface9_Release(surfaces[i]); } if (decoder) IDirectXVideoDecoder_Release(decoder); talloc_free(tmp); return ret; } static void destroy_device(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; if (p->device) IDirect3DDevice9_Release(p->device); if (p->d3d9) IDirect3D9_Release(p->d3d9); if (p->d3d9_dll) FreeLibrary(p->d3d9_dll); if (p->dxva2_dll) FreeLibrary(p->dxva2_dll); } static bool create_device(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; p->d3d9_dll = LoadLibrary(L"d3d9.dll"); if (!p->d3d9_dll) { MP_ERR(p, "Failed to load D3D9 library\n"); return false; } IDirect3D9* (WINAPI *Direct3DCreate9)(UINT) = (void *)GetProcAddress(p->d3d9_dll, "Direct3DCreate9"); if (!Direct3DCreate9) { MP_ERR(p, "Failed to locate Direct3DCreate9\n"); return false; } p->d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if (!p->d3d9) { MP_ERR(p, "Failed to create IDirect3D object\n"); return false; } UINT adapter = D3DADAPTER_DEFAULT; D3DDISPLAYMODE display_mode; IDirect3D9_GetAdapterDisplayMode(p->d3d9, adapter, &display_mode); D3DPRESENT_PARAMETERS present_params = { .Windowed = TRUE, .BackBufferWidth = 640, .BackBufferHeight = 480, .BackBufferCount = 0, .BackBufferFormat = display_mode.Format, .SwapEffect = D3DSWAPEFFECT_DISCARD, .Flags = D3DPRESENTFLAG_VIDEO, }; HRESULT hr = IDirect3D9_CreateDevice(p->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, &present_params, &p->device); if (FAILED(hr)) { MP_ERR(p, "Failed to create Direct3D device: %s\n", mp_HRESULT_to_str(hr)); return false; } return true; } static void dxva2_uninit(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; if (!p) return; av_freep(&s->avctx->hwaccel_context); talloc_free(p->decoder_pool); if (p->decoder_service) IDirectXVideoDecoderService_Release(p->decoder_service); if (p->device_manager && p->device_handle != INVALID_HANDLE_VALUE) IDirect3DDeviceManager9_CloseDeviceHandle(p->device_manager, p->device_handle); if (p->device_manager) IDirect3DDeviceManager9_Release(p->device_manager); destroy_device(s); TA_FREEP(&s->hwdec_priv); } static int dxva2_init(struct lavc_ctx *s) { HRESULT hr; struct priv *p = talloc_zero(NULL, struct priv); if (!p) return -1; s->hwdec_priv = p; p->device_handle = INVALID_HANDLE_VALUE; p->log = mp_log_new(s, s->log, "dxva2"); if (s->hwdec->type == HWDEC_DXVA2_COPY) { mp_check_gpu_memcpy(p->log, NULL); p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); } if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx) p->device = s->hwdec_info->hwctx->d3d_ctx->d3d9_device; if (p->device) { IDirect3D9_AddRef(p->device); MP_VERBOSE(p, "Using VO-supplied device %p.\n", p->device); } else if (s->hwdec->type == HWDEC_DXVA2) { MP_ERR(p, "No Direct3D device provided for native dxva2 decoding\n"); goto fail; } else { if (!create_device(s)) goto fail; } p->dxva2_dll = LoadLibrary(L"dxva2.dll"); if (!p->dxva2_dll) { MP_ERR(p, "Failed to load DXVA2 library\n"); goto fail; } HRESULT (WINAPI *CreateDeviceManager9)(UINT *, IDirect3DDeviceManager9 **) = (void *)GetProcAddress(p->dxva2_dll, "DXVA2CreateDirect3DDeviceManager9"); if (!CreateDeviceManager9) { MP_ERR(p, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); goto fail; } unsigned reset_token = 0; hr = CreateDeviceManager9(&reset_token, &p->device_manager); if (FAILED(hr)) { MP_ERR(p, "Failed to create Direct3D device manager: %s\n", mp_HRESULT_to_str(hr)); goto fail; } hr = IDirect3DDeviceManager9_ResetDevice(p->device_manager, p->device, reset_token); if (FAILED(hr)) { MP_ERR(p, "Failed to bind Direct3D device to device manager: %s\n", mp_HRESULT_to_str(hr)); goto fail; } hr = IDirect3DDeviceManager9_OpenDeviceHandle(p->device_manager, &p->device_handle); if (FAILED(hr)) { MP_ERR(p, "Failed to open device handle: %s\n", mp_HRESULT_to_str(hr)); goto fail; } hr = IDirect3DDeviceManager9_GetVideoService( p->device_manager, p->device_handle, &IID_IDirectXVideoDecoderService, (void **)&p->decoder_service); if (FAILED(hr)) { MP_ERR(p, "Failed to create IDirectXVideoDecoderService: %s\n", mp_HRESULT_to_str(hr)); goto fail; } s->avctx->hwaccel_context = av_mallocz(sizeof(struct dxva_context)); if (!s->avctx->hwaccel_context) goto fail; return 0; fail: dxva2_uninit(s); return -1; } static int dxva2_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, const char *codec) { hwdec_request_api(info, "dxva2"); // dxva2-copy can do without external context; dxva2 requires it. if (hwdec->type != HWDEC_DXVA2_COPY) { if (!info || !info->hwctx || !info->hwctx->d3d_ctx || info->hwctx->type == HWDEC_DXVA2_COPY || !info->hwctx->d3d_ctx->d3d9_device) return HWDEC_ERR_NO_CTX; } return d3d_probe_codec(codec); }