1 /*****************************************************************************
2 * dxva2.c: Video Acceleration helpers
3 *****************************************************************************
4 * Copyright (C) 2009 Geoffroy Couprie
5 * Copyright (C) 2009 Laurent Aimar
8 * Authors: Geoffroy Couprie <geal@videolan.org>
9 * Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_picture.h>
34 #include <vlc_plugin.h>
36 #define DXVA2API_USE_BITFIELDS
38 #include <libavcodec/dxva2.h>
39 #include "../../video_chroma/d3d9_fmt.h"
41 #define D3D_Device IDirect3DDevice9
42 #define D3D_DecoderType IDirectXVideoDecoder
43 #define D3D_DecoderDevice IDirectXVideoDecoderService
44 #define D3D_DecoderSurface IDirect3DSurface9
45 #include "directx_va.h"
47 static int Open(vlc_va_t
*, AVCodecContext
*, enum PixelFormat
,
48 const es_format_t
*, picture_sys_t
*p_sys
);
49 static void Close(vlc_va_t
*, void **);
52 set_description(N_("DirectX Video Acceleration (DXVA) 2.0"))
53 set_capability("hw decoder", 0)
54 set_category(CAT_INPUT
)
55 set_subcategory(SUBCAT_INPUT_VCODEC
)
56 set_callbacks(Open
, Close
)
59 #include <initguid.h> /* must be last included to not redefine existing GUIDs */
61 /* dxva2api.h GUIDs: http://msdn.microsoft.com/en-us/library/windows/desktop/ms697067(v=vs100).aspx
62 * assume that they are declared in dxva2api.h */
63 #define MS_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
68 # if !defined(__MINGW64_VERSION_MAJOR)
70 # define MS_GUID DEFINE_GUID /* dxva2api.h fails to declare those, redefine as static */
71 # define DXVA2_E_NEW_VIDEO_DEVICE MAKE_HRESULT(1, 4, 4097)
76 #endif /* __MINGW32__ */
78 MS_GUID(IID_IDirectXVideoDecoderService
, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
79 MS_GUID(IID_IDirectXVideoAccelerationService
, 0xfc51a550, 0xd5e7, 0x11d9, 0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
81 DEFINE_GUID(DXVA2_NoEncrypt
, 0x1b81bed0, 0xa0c7, 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);
83 DEFINE_GUID(DXVA_Intel_H264_NoFGT_ClearVideo
, 0x604F8E68, 0x4951, 0x4c54, 0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6);
92 /* XXX Prefered format must come first */
93 static const d3d_format_t d3d_formats
[] = {
94 { "YV12", MAKEFOURCC('Y','V','1','2'), VLC_CODEC_YV12
},
95 { "NV12", MAKEFOURCC('N','V','1','2'), VLC_CODEC_NV12
},
96 { "IMC3", MAKEFOURCC('I','M','C','3'), VLC_CODEC_YV12
},
97 { "P010", MAKEFOURCC('P','0','1','0'), VLC_CODEC_P010
},
102 static const d3d_format_t
*D3dFindFormat(D3DFORMAT format
)
104 for (unsigned i
= 0; d3d_formats
[i
].name
; i
++) {
105 if (d3d_formats
[i
].format
== format
)
106 return &d3d_formats
[i
];
113 directx_sys_t dx_sys
;
114 vlc_fourcc_t i_chroma
;
121 D3DADAPTER_IDENTIFIER9 d3dai
;
124 IDirect3DDeviceManager9
*devmng
;
131 DXVA2_ConfigPictureDecode cfg
;
133 /* avcodec internals */
134 struct dxva_context hw
;
139 static int D3dCreateDevice(vlc_va_t
*);
140 static void D3dDestroyDevice(vlc_va_t
*);
141 static char *DxDescribe(vlc_va_sys_t
*);
143 static int D3dCreateDeviceManager(vlc_va_t
*);
144 static void D3dDestroyDeviceManager(vlc_va_t
*);
146 static int DxCreateVideoService(vlc_va_t
*);
147 static void DxDestroyVideoService(vlc_va_t
*);
148 static int DxGetInputList(vlc_va_t
*, input_list_t
*);
149 static int DxSetupOutput(vlc_va_t
*, const GUID
*, const video_format_t
*);
151 static int DxCreateVideoDecoder(vlc_va_t
*,
152 int codec_id
, const video_format_t
*);
153 static void DxDestroyVideoDecoder(vlc_va_t
*);
154 static int DxResetVideoDecoder(vlc_va_t
*);
155 static void SetupAVCodecContext(vlc_va_t
*);
158 static void Setup(vlc_va_t
*va
, vlc_fourcc_t
*chroma
)
160 *chroma
= va
->sys
->i_chroma
;
163 void SetupAVCodecContext(vlc_va_t
*va
)
165 vlc_va_sys_t
*sys
= va
->sys
;
166 directx_sys_t
*dx_sys
= &sys
->dx_sys
;
168 sys
->hw
.decoder
= dx_sys
->decoder
;
169 sys
->hw
.cfg
= &sys
->cfg
;
170 sys
->hw
.surface_count
= dx_sys
->surface_count
;
171 sys
->hw
.surface
= dx_sys
->hw_surface
;
173 if (IsEqualGUID(&dx_sys
->input
, &DXVA_Intel_H264_NoFGT_ClearVideo
))
174 sys
->hw
.workaround
|= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO
;
177 static int Extract(vlc_va_t
*va
, picture_t
*picture
, uint8_t *data
)
179 VLC_UNUSED(va
); VLC_UNUSED(data
);
180 struct va_pic_context
*pic_ctx
= (struct va_pic_context
*)picture
->context
;
181 directx_va_AddRef(pic_ctx
->va_surface
);
185 static int CheckDevice(vlc_va_t
*va
)
187 vlc_va_sys_t
*sys
= va
->sys
;
189 /* Check the device */
190 HRESULT hr
= IDirect3DDeviceManager9_TestDevice(sys
->devmng
, sys
->device
);
191 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
) {
192 if (DxResetVideoDecoder(va
))
194 } else if (FAILED(hr
)) {
195 msg_Err(va
, "IDirect3DDeviceManager9_TestDevice %u", (unsigned)hr
);
201 static void d3d9_pic_context_destroy(struct picture_context_t
*opaque
)
203 struct va_pic_context
*pic_ctx
= (struct va_pic_context
*)opaque
;
204 if (pic_ctx
->va_surface
)
206 ReleasePictureSys(&pic_ctx
->picsys
);
207 directx_va_Release(pic_ctx
->va_surface
);
212 static struct picture_context_t
*CreatePicContext(vlc_va_surface_t
*);
214 static struct picture_context_t
*d3d9_pic_context_copy(struct picture_context_t
*ctx
)
216 struct va_pic_context
*src_ctx
= (struct va_pic_context
*)ctx
;
217 return CreatePicContext(src_ctx
->va_surface
);
220 static struct picture_context_t
*CreatePicContext(vlc_va_surface_t
*va_surface
)
222 struct va_pic_context
*pic_ctx
= calloc(1, sizeof(*pic_ctx
));
223 if (unlikely(pic_ctx
==NULL
))
225 pic_ctx
->va_surface
= va_surface
;
226 directx_va_AddRef(pic_ctx
->va_surface
);
227 pic_ctx
->s
.destroy
= d3d9_pic_context_destroy
;
228 pic_ctx
->s
.copy
= d3d9_pic_context_copy
;
229 pic_ctx
->picsys
.surface
= va_surface
->decoderSurface
;
230 AcquirePictureSys(&pic_ctx
->picsys
);
234 static int Get(vlc_va_t
*va
, picture_t
*pic
, uint8_t **data
)
236 vlc_va_surface_t
*va_surface
= directx_va_Get(va
, &va
->sys
->dx_sys
);
237 if (unlikely(va_surface
==NULL
))
239 pic
->context
= CreatePicContext(va_surface
);
240 directx_va_Release(va_surface
);
241 if (unlikely(pic
->context
==NULL
))
243 *data
= (uint8_t*)va_surface
->decoderSurface
;
247 static void Close(vlc_va_t
*va
, void **ctx
)
249 vlc_va_sys_t
*sys
= va
->sys
;
253 directx_va_Close(va
, &sys
->dx_sys
);
256 FreeLibrary(sys
->hd3d9_dll
);
258 free((char *)va
->description
);
262 static vlc_fourcc_t
d3d9va_fourcc(enum PixelFormat swfmt
)
266 case AV_PIX_FMT_YUV420P10LE
:
267 return VLC_CODEC_D3D9_OPAQUE_10B
;
268 case AV_PIX_FMT_YUVJ420P
:
269 case AV_PIX_FMT_YUV420P
:
270 return VLC_CODEC_D3D9_OPAQUE
;
272 return VLC_CODEC_D3D9_OPAQUE
;
276 static void ReleasePic(void *opaque
, uint8_t *data
)
279 picture_t
*pic
= opaque
;
280 struct va_pic_context
*pic_ctx
= (struct va_pic_context
*)pic
->context
;
281 directx_va_Release(pic_ctx
->va_surface
);
282 picture_Release(pic
);
285 static int Open(vlc_va_t
*va
, AVCodecContext
*ctx
, enum PixelFormat pix_fmt
,
286 const es_format_t
*fmt
, picture_sys_t
*p_sys
)
288 int err
= VLC_EGENERIC
;
289 directx_sys_t
*dx_sys
;
291 if (pix_fmt
!= AV_PIX_FMT_DXVA2_VLD
)
294 vlc_va_sys_t
*sys
= calloc(1, sizeof (*sys
));
295 if (unlikely(sys
== NULL
))
299 sys
->hd3d9_dll
= LoadLibrary(TEXT("D3D9.DLL"));
300 if (!sys
->hd3d9_dll
) {
301 msg_Warn(va
, "cannot load d3d9.dll");
305 dx_sys
= &sys
->dx_sys
;
307 dx_sys
->pf_check_device
= CheckDevice
;
308 dx_sys
->pf_create_device
= D3dCreateDevice
;
309 dx_sys
->pf_destroy_device
= D3dDestroyDevice
;
310 dx_sys
->pf_create_device_manager
= D3dCreateDeviceManager
;
311 dx_sys
->pf_destroy_device_manager
= D3dDestroyDeviceManager
;
312 dx_sys
->pf_create_video_service
= DxCreateVideoService
;
313 dx_sys
->pf_destroy_video_service
= DxDestroyVideoService
;
314 dx_sys
->pf_create_decoder_surfaces
= DxCreateVideoDecoder
;
315 dx_sys
->pf_destroy_surfaces
= DxDestroyVideoDecoder
;
316 dx_sys
->pf_setup_avcodec_ctx
= SetupAVCodecContext
;
317 dx_sys
->pf_get_input_list
= DxGetInputList
;
318 dx_sys
->pf_setup_output
= DxSetupOutput
;
319 dx_sys
->psz_decoder_dll
= TEXT("DXVA2.DLL");
323 dx_sys
->d3ddev
= NULL
;
327 if (SUCCEEDED(IDirect3DSurface9_GetDesc(p_sys
->surface
, &src
)))
328 sys
->render
= src
.Format
;
329 IDirect3DSurface9_GetDevice(p_sys
->surface
, &dx_sys
->d3ddev
);
332 sys
->i_chroma
= d3d9va_fourcc(ctx
->sw_pix_fmt
);
334 err
= directx_va_Open(va
, &sys
->dx_sys
, ctx
, fmt
, true);
335 if (err
!=VLC_SUCCESS
)
338 err
= directx_va_Setup(va
, &sys
->dx_sys
, ctx
);
339 if (err
!= VLC_SUCCESS
)
342 ctx
->hwaccel_context
= &sys
->hw
;
344 /* TODO print the hardware name/vendor for debugging purposes */
345 va
->description
= DxDescribe(sys
);
348 va
->release
= ReleasePic
;
349 va
->extract
= Extract
;
359 * It creates a Direct3D device usable for DXVA 2
361 static int D3dCreateDevice(vlc_va_t
*va
)
363 vlc_va_sys_t
*sys
= va
->sys
;
365 if (sys
->dx_sys
.d3ddev
) {
366 msg_Dbg(va
, "Reusing Direct3D9 device");
367 IDirect3DDevice9_AddRef(sys
->dx_sys
.d3ddev
);
372 LPDIRECT3D9 (WINAPI
*Create9
)(UINT SDKVersion
);
373 Create9
= (void *)GetProcAddress(sys
->hd3d9_dll
, "Direct3DCreate9");
375 msg_Err(va
, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
381 d3dobj
= Create9(D3D_SDK_VERSION
);
383 msg_Err(va
, "Direct3DCreate9 failed");
386 sys
->d3dobj
= d3dobj
;
389 D3DADAPTER_IDENTIFIER9
*d3dai
= &sys
->d3dai
;
390 if (FAILED(IDirect3D9_GetAdapterIdentifier(sys
->d3dobj
,
391 D3DADAPTER_DEFAULT
, 0, d3dai
))) {
392 msg_Warn(va
, "IDirect3D9_GetAdapterIdentifier failed");
393 ZeroMemory(d3dai
, sizeof(*d3dai
));
397 D3DPRESENT_PARAMETERS d3dpp
;
398 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
399 d3dpp
.Flags
= D3DPRESENTFLAG_VIDEO
;
400 d3dpp
.Windowed
= TRUE
;
401 d3dpp
.hDeviceWindow
= NULL
;
402 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
403 d3dpp
.MultiSampleType
= D3DMULTISAMPLE_NONE
;
404 d3dpp
.PresentationInterval
= D3DPRESENT_INTERVAL_DEFAULT
;
405 d3dpp
.BackBufferCount
= 0; /* FIXME what to put here */
406 d3dpp
.BackBufferFormat
= D3DFMT_X8R8G8B8
; /* FIXME what to put here */
407 d3dpp
.BackBufferWidth
= 0;
408 d3dpp
.BackBufferHeight
= 0;
409 d3dpp
.EnableAutoDepthStencil
= FALSE
;
411 /* Direct3D needs a HWND to create a device, even without using ::Present
412 this HWND is used to alert Direct3D when there's a change of focus window.
413 For now, use GetDesktopWindow, as it looks harmless */
414 LPDIRECT3DDEVICE9 d3ddev
;
415 if (FAILED(IDirect3D9_CreateDevice(d3dobj
, D3DADAPTER_DEFAULT
,
416 D3DDEVTYPE_HAL
, GetDesktopWindow(),
417 D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
418 D3DCREATE_MULTITHREADED
,
420 msg_Err(va
, "IDirect3D9_CreateDevice failed");
423 sys
->dx_sys
.d3ddev
= d3ddev
;
429 * It releases a Direct3D device and its resources.
431 static void D3dDestroyDevice(vlc_va_t
*va
)
434 IDirect3D9_Release(va
->sys
->d3dobj
);
437 * It describes our Direct3D object
439 static char *DxDescribe(vlc_va_sys_t
*va
)
441 static const struct {
446 { 0x10DE, "NVIDIA" },
449 { 0x5333, "S3 Graphics" },
452 D3DADAPTER_IDENTIFIER9
*id
= &va
->d3dai
;
454 const char *vendor
= "Unknown";
455 for (int i
= 0; vendors
[i
].id
!= 0; i
++) {
456 if (vendors
[i
].id
== id
->VendorId
) {
457 vendor
= vendors
[i
].name
;
463 if (asprintf(&description
, "DXVA2 (%.*s, vendor %lu(%s), device %lu, revision %lu)",
464 (int)sizeof(id
->Description
), id
->Description
,
465 id
->VendorId
, vendor
, id
->DeviceId
, id
->Revision
) < 0)
471 * It creates a Direct3D device manager
473 static int D3dCreateDeviceManager(vlc_va_t
*va
)
475 vlc_va_sys_t
*sys
= va
->sys
;
476 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
478 HRESULT (WINAPI
*CreateDeviceManager9
)(UINT
*pResetToken
,
479 IDirect3DDeviceManager9
**);
480 CreateDeviceManager9
=
481 (void *)GetProcAddress(dx_sys
->hdecoder_dll
,
482 "DXVA2CreateDirect3DDeviceManager9");
484 if (!CreateDeviceManager9
) {
485 msg_Err(va
, "cannot load function");
488 msg_Dbg(va
, "OurDirect3DCreateDeviceManager9 Success!");
491 IDirect3DDeviceManager9
*devmng
;
492 if (FAILED(CreateDeviceManager9(&token
, &devmng
))) {
493 msg_Err(va
, " OurDirect3DCreateDeviceManager9 failed");
496 sys
->devmng
= devmng
;
497 msg_Info(va
, "obtained IDirect3DDeviceManager9");
499 HRESULT hr
= IDirect3DDeviceManager9_ResetDevice(devmng
, dx_sys
->d3ddev
, token
);
501 msg_Err(va
, "IDirect3DDeviceManager9_ResetDevice failed: %08x", (unsigned)hr
);
507 * It destroys a Direct3D device manager
509 static void D3dDestroyDeviceManager(vlc_va_t
*va
)
512 IDirect3DDeviceManager9_Release(va
->sys
->devmng
);
516 * It creates a DirectX video service
518 static int DxCreateVideoService(vlc_va_t
*va
)
520 vlc_va_sys_t
*sys
= va
->sys
;
521 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
523 HRESULT (WINAPI
*CreateVideoService
)(IDirect3DDevice9
*,
527 (void *)GetProcAddress(dx_sys
->hdecoder_dll
, "DXVA2CreateVideoService");
529 if (!CreateVideoService
) {
530 msg_Err(va
, "cannot load function");
533 msg_Info(va
, "DXVA2CreateVideoService Success!");
538 hr
= IDirect3DDeviceManager9_OpenDeviceHandle(sys
->devmng
, &device
);
540 msg_Err(va
, "OpenDeviceHandle failed");
543 sys
->device
= device
;
546 hr
= IDirect3DDeviceManager9_GetVideoService(sys
->devmng
, device
,
547 &IID_IDirectXVideoDecoderService
, &pv
);
549 msg_Err(va
, "GetVideoService failed");
558 * It destroys a DirectX video service
560 static void DxDestroyVideoService(vlc_va_t
*va
)
563 IDirect3DDeviceManager9_CloseDeviceHandle(va
->sys
->devmng
, va
->sys
->device
);
566 static void ReleaseInputList(input_list_t
*p_list
)
568 CoTaskMemFree(p_list
->list
);
571 static int DxGetInputList(vlc_va_t
*va
, input_list_t
*p_list
)
573 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
574 UINT input_count
= 0;
575 GUID
*input_list
= NULL
;
576 if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(dx_sys
->d3ddec
,
579 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderDeviceGuids failed");
583 p_list
->count
= input_count
;
584 p_list
->list
= input_list
;
585 p_list
->pf_release
= ReleaseInputList
;
589 static int DxSetupOutput(vlc_va_t
*va
, const GUID
*input
, const video_format_t
*fmt
)
592 int err
= VLC_EGENERIC
;
593 UINT output_count
= 0;
594 D3DFORMAT
*output_list
= NULL
;
595 if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(va
->sys
->dx_sys
.d3ddec
,
599 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderRenderTargets failed");
603 for (unsigned j
= 0; j
< output_count
; j
++) {
604 const D3DFORMAT f
= output_list
[j
];
605 const d3d_format_t
*format
= D3dFindFormat(f
);
607 msg_Dbg(va
, "%s is supported for output", format
->name
);
609 msg_Dbg(va
, "%d is supported for output (%4.4s)", f
, (const char*)&f
);
614 for (unsigned pass
= 0; pass
< 2 && err
!= VLC_SUCCESS
; ++pass
)
616 for (unsigned j
= 0; d3d_formats
[j
].name
; j
++) {
617 const d3d_format_t
*format
= &d3d_formats
[j
];
620 bool is_supported
= false;
621 for (unsigned k
= 0; !is_supported
&& k
< output_count
; k
++) {
622 is_supported
= format
->format
== output_list
[k
];
626 if (pass
== 0 && format
->format
!= va
->sys
->render
)
629 /* We have our solution */
630 msg_Dbg(va
, "Using decoder output '%s'", format
->name
);
631 va
->sys
->render
= format
->format
;
636 CoTaskMemFree(output_list
);
641 * It creates a DXVA2 decoder using the given video format
643 static int DxCreateVideoDecoder(vlc_va_t
*va
, int codec_id
, const video_format_t
*fmt
)
645 vlc_va_sys_t
*p_sys
= va
->sys
;
646 directx_sys_t
*sys
= &va
->sys
->dx_sys
;
649 hr
= IDirectXVideoDecoderService_CreateSurface(sys
->d3ddec
,
652 sys
->surface_count
- 1,
656 DXVA2_VideoDecoderRenderTarget
,
660 msg_Err(va
, "IDirectXVideoAccelerationService_CreateSurface %d failed (hr=0x%0lx)", sys
->surface_count
- 1, hr
);
661 sys
->surface_count
= 0;
664 msg_Dbg(va
, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)",
665 sys
->surface_count
, sys
->surface_width
, sys
->surface_height
);
667 IDirect3DSurface9
*tstCrash
;
668 hr
= IDirectXVideoDecoderService_CreateSurface(sys
->d3ddec
,
675 DXVA2_VideoDecoderRenderTarget
,
679 msg_Err(va
, "extra buffer impossible, avoid a crash (hr=0x%0lx)", hr
);
680 for (unsigned i
= 0; i
< sys
->surface_count
; i
++)
681 IDirect3DSurface9_Release( sys
->hw_surface
[i
] );
682 sys
->surface_count
= 0;
685 IDirect3DSurface9_Release(tstCrash
);
689 ZeroMemory(&dsc
, sizeof(dsc
));
690 dsc
.SampleWidth
= fmt
->i_width
;
691 dsc
.SampleHeight
= fmt
->i_height
;
692 dsc
.Format
= p_sys
->render
;
693 if (fmt
->i_frame_rate
> 0 && fmt
->i_frame_rate_base
> 0) {
694 dsc
.InputSampleFreq
.Numerator
= fmt
->i_frame_rate
;
695 dsc
.InputSampleFreq
.Denominator
= fmt
->i_frame_rate_base
;
697 dsc
.InputSampleFreq
.Numerator
= 0;
698 dsc
.InputSampleFreq
.Denominator
= 0;
700 dsc
.OutputFrameFreq
= dsc
.InputSampleFreq
;
701 dsc
.UABProtectionLevel
= FALSE
;
704 /* FIXME I am unsure we can let unknown everywhere */
705 DXVA2_ExtendedFormat
*ext
= &dsc
.SampleFormat
;
706 ext
->SampleFormat
= 0;//DXVA2_SampleUnknown;
707 ext
->VideoChromaSubsampling
= 0;//DXVA2_VideoChromaSubsampling_Unknown;
708 ext
->NominalRange
= 0;//DXVA2_NominalRange_Unknown;
709 ext
->VideoTransferMatrix
= 0;//DXVA2_VideoTransferMatrix_Unknown;
710 ext
->VideoLighting
= 0;//DXVA2_VideoLighting_Unknown;
711 ext
->VideoPrimaries
= 0;//DXVA2_VideoPrimaries_Unknown;
712 ext
->VideoTransferFunction
= 0;//DXVA2_VideoTransFunc_Unknown;
714 /* List all configurations available for the decoder */
716 DXVA2_ConfigPictureDecode
*cfg_list
= NULL
;
717 if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(sys
->d3ddec
,
723 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderConfigurations failed");
724 for (unsigned i
= 0; i
< sys
->surface_count
; i
++)
725 IDirect3DSurface9_Release( sys
->hw_surface
[i
] );
726 sys
->surface_count
= 0;
729 msg_Dbg(va
, "we got %d decoder configurations", cfg_count
);
731 /* Select the best decoder configuration */
733 for (unsigned i
= 0; i
< cfg_count
; i
++) {
734 const DXVA2_ConfigPictureDecode
*cfg
= &cfg_list
[i
];
737 msg_Dbg(va
, "configuration[%d] ConfigBitstreamRaw %d",
738 i
, cfg
->ConfigBitstreamRaw
);
742 if (cfg
->ConfigBitstreamRaw
== 1)
744 else if (codec_id
== AV_CODEC_ID_H264
&& cfg
->ConfigBitstreamRaw
== 2)
748 if (IsEqualGUID(&cfg
->guidConfigBitstreamEncryption
, &DXVA2_NoEncrypt
))
751 if (cfg_score
< score
) {
756 CoTaskMemFree(cfg_list
);
757 if (cfg_score
<= 0) {
758 msg_Err(va
, "Failed to find a supported decoder configuration");
762 /* Create the decoder */
763 IDirectXVideoDecoder
*decoder
;
764 if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(sys
->d3ddec
,
771 msg_Err(va
, "IDirectXVideoDecoderService_CreateVideoDecoder failed");
772 for (unsigned i
= 0; i
< sys
->surface_count
; i
++)
773 IDirect3DSurface9_Release( sys
->hw_surface
[i
] );
774 sys
->surface_count
= 0;
777 sys
->decoder
= decoder
;
779 msg_Dbg(va
, "IDirectXVideoDecoderService_CreateVideoDecoder succeed");
783 static void DxDestroyVideoDecoder(vlc_va_t
*va
)
785 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
788 IDirectXVideoDecoder_Release(dx_sys
->decoder
);
789 dx_sys
->decoder
= NULL
;
793 static int DxResetVideoDecoder(vlc_va_t
*va
)
795 msg_Err(va
, "DxResetVideoDecoder unimplemented");