bool DXVA2Decoder::Init(MythRenderD3D9* render) { bool ok = true; CREATE_CHECK(m_width > 0, "Invalid width.") CREATE_CHECK(m_height > 0, "Invalid height.") CREATE_CHECK(CreateVideoService(render), "Failed to create video service.") CREATE_CHECK(GetInputOutput(), "Failed to find input/output combination.") InitFormat(); CREATE_CHECK(GetDecoderConfig(), "Failed to find a raw input bitstream.") CREATE_CHECK(CreateSurfaces(), "Failed to create surfaces.") CREATE_CHECK(CreateDecoder(), "Failed to create decoder.") return ok; }
static int Open(vlc_object_t *obj) { filter_t *filter = (filter_t *)obj; filter_sys_t *sys = NULL; HINSTANCE hdecoder_dll = NULL; HINSTANCE d3d9_dll = NULL; HRESULT hr; picture_t *dst = NULL; GUID *processorGUIDs = NULL; GUID *processorGUID = NULL; IDirectXVideoProcessorService *processor = NULL; if (filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE && filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B) return VLC_EGENERIC; if (!video_format_IsSimilar(&filter->fmt_in.video, &filter->fmt_out.video)) return VLC_EGENERIC; d3d9_dll = LoadLibrary(TEXT("D3D9.DLL")); if (!d3d9_dll) goto error; hdecoder_dll = LoadLibrary(TEXT("DXVA2.DLL")); if (!hdecoder_dll) goto error; dst = filter_NewPicture(filter); if (dst == NULL) goto error; if (!dst->p_sys) { msg_Dbg(filter, "D3D9 opaque without a texture"); goto error; } sys = calloc(1, sizeof (*sys)); if (unlikely(sys == NULL)) goto error; HRESULT (WINAPI *CreateVideoService)(IDirect3DDevice9 *, REFIID riid, void **ppService); CreateVideoService = (void *)GetProcAddress(hdecoder_dll, "DXVA2CreateVideoService"); if (CreateVideoService == NULL) goto error; hr = IDirect3DSurface9_GetDevice( dst->p_sys->surface, &sys->d3ddev ); if (FAILED(hr)) goto error; D3DSURFACE_DESC dstDesc; hr = IDirect3DSurface9_GetDesc( dst->p_sys->surface, &dstDesc ); if (unlikely(FAILED(hr))) goto error; hr = CreateVideoService( sys->d3ddev, &IID_IDirectXVideoProcessorService, (void**)&processor); if (FAILED(hr)) goto error; DXVA2_VideoDesc dsc; ZeroMemory(&dsc, sizeof(dsc)); dsc.SampleWidth = dstDesc.Width; dsc.SampleHeight = dstDesc.Height; dsc.Format = dstDesc.Format; if (filter->fmt_in.video.i_frame_rate && filter->fmt_in.video.i_frame_rate_base) { dsc.InputSampleFreq.Numerator = filter->fmt_in.video.i_frame_rate; dsc.InputSampleFreq.Denominator = filter->fmt_in.video.i_frame_rate_base; } else { dsc.InputSampleFreq.Numerator = 0; dsc.InputSampleFreq.Denominator = 0; } dsc.OutputFrameFreq = dsc.InputSampleFreq; DXVA2_ExtendedFormat *pFormat = &dsc.SampleFormat; pFormat->SampleFormat = dst->b_top_field_first ? DXVA2_SampleFieldInterleavedEvenFirst : DXVA2_SampleFieldInterleavedOddFirst; UINT count = 0; hr = IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids( processor, &dsc, &count, &processorGUIDs); if (FAILED(hr)) goto error; char *psz_mode = var_InheritString( filter, "deinterlace-mode" ); const struct filter_mode_t *p_mode = GetFilterMode(psz_mode); if (p_mode == NULL) { msg_Dbg(filter, "unknown mode %s, trying blend", psz_mode); p_mode = GetFilterMode("blend"); } if (strcmp(p_mode->psz_mode, psz_mode)) msg_Dbg(filter, "using %s deinterlacing mode", p_mode->psz_mode); DXVA2_VideoProcessorCaps caps, best_caps; unsigned best_score = 0; for (UINT i=0; i<count; ++i) { hr = IDirectXVideoProcessorService_GetVideoProcessorCaps( processor, processorGUIDs+i, &dsc, dsc.Format, &caps); if ( FAILED(hr) || !caps.DeinterlaceTechnology ) continue; unsigned score = (caps.DeinterlaceTechnology & p_mode->i_mode) ? 10 : 1; if (best_score < score) { best_score = score; best_caps = caps; processorGUID = processorGUIDs + i; } } if (processorGUID == NULL) { msg_Dbg(filter, "Could not find a filter to output the required format"); goto error; } hr = IDirectXVideoProcessorService_CreateVideoProcessor( processor, processorGUID, &dsc, dsc.Format, 1, &sys->processor ); if (FAILED(hr)) goto error; hr = IDirectXVideoProcessorService_CreateSurface( processor, dstDesc.Width, dstDesc.Height, 0, dstDesc.Format, D3DPOOL_DEFAULT, 0, DXVA2_VideoProcessorRenderTarget, &sys->hw_surface, NULL); if (FAILED(hr)) goto error; sys->hdecoder_dll = hdecoder_dll; sys->d3d9_dll = d3d9_dll; sys->decoder_caps = best_caps; InitDeinterlacingContext( &sys->context ); sys->context.settings = p_mode->settings; sys->context.settings.b_use_frame_history = best_caps.NumBackwardRefSamples != 0 || best_caps.NumForwardRefSamples != 0; if (sys->context.settings.b_use_frame_history != p_mode->settings.b_use_frame_history) msg_Dbg( filter, "deinterlacing not using frame history as requested"); if (sys->context.settings.b_double_rate) sys->context.pf_render_ordered = RenderPic; else sys->context.pf_render_single_pic = RenderSinglePic; video_format_t out_fmt; GetDeinterlacingOutput( &sys->context, &out_fmt, &filter->fmt_in.video ); if( !filter->b_allow_fmt_out_change && out_fmt.i_height != filter->fmt_in.video.i_height ) { goto error; } CoTaskMemFree(processorGUIDs); IDirectXVideoProcessorService_Release(processor); picture_Release(dst); sys->buffer_new = filter->owner.video.buffer_new; filter->owner.video.buffer_new = NewOutputPicture; filter->fmt_out.video = out_fmt; filter->pf_video_filter = Deinterlace; filter->pf_flush = Flush; filter->p_sys = sys; return VLC_SUCCESS; error: CoTaskMemFree(processorGUIDs); if (sys && sys->processor) IDirectXVideoProcessor_Release( sys->processor ); if (processor) IDirectXVideoProcessorService_Release(processor); if (sys && sys->d3ddev) IDirect3DDevice9_Release( sys->d3ddev ); if (hdecoder_dll) FreeLibrary(hdecoder_dll); if (d3d9_dll) FreeLibrary(d3d9_dll); if (dst) picture_Release(dst); free(sys); return VLC_EGENERIC; }