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
*, int codec_id
,
152 const video_format_t
*, unsigned surface_count
);
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
->va_pool
.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 va_surface_AddRef(pic_ctx
->va_surface
);
185 static void d3d9_pic_context_destroy(struct picture_context_t
*opaque
)
187 struct va_pic_context
*pic_ctx
= (struct va_pic_context
*)opaque
;
188 if (pic_ctx
->va_surface
)
190 ReleasePictureSys(&pic_ctx
->picsys
);
191 va_surface_Release(pic_ctx
->va_surface
);
196 static struct va_pic_context
*CreatePicContext(IDirect3DSurface9
*);
198 static struct picture_context_t
*d3d9_pic_context_copy(struct picture_context_t
*ctx
)
200 struct va_pic_context
*src_ctx
= (struct va_pic_context
*)ctx
;
201 struct va_pic_context
*pic_ctx
= CreatePicContext(src_ctx
->picsys
.surface
);
202 if (unlikely(pic_ctx
==NULL
))
204 pic_ctx
->va_surface
= src_ctx
->va_surface
;
205 va_surface_AddRef(pic_ctx
->va_surface
);
209 static struct va_pic_context
*CreatePicContext(IDirect3DSurface9
*surface
)
211 struct va_pic_context
*pic_ctx
= calloc(1, sizeof(*pic_ctx
));
212 if (unlikely(pic_ctx
==NULL
))
214 pic_ctx
->s
.destroy
= d3d9_pic_context_destroy
;
215 pic_ctx
->s
.copy
= d3d9_pic_context_copy
;
216 pic_ctx
->picsys
.surface
= surface
;
217 AcquirePictureSys(&pic_ctx
->picsys
);
221 static struct va_pic_context
* NewSurfacePicContext(vlc_va_t
*va
, int surface_index
)
223 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
224 return CreatePicContext(dx_sys
->hw_surface
[surface_index
]);
227 static int Get(vlc_va_t
*va
, picture_t
*pic
, uint8_t **data
)
229 vlc_va_sys_t
*sys
= va
->sys
;
231 /* Check the device */
232 HRESULT hr
= IDirect3DDeviceManager9_TestDevice(sys
->devmng
, sys
->device
);
233 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
) {
234 if (DxResetVideoDecoder(va
))
236 } else if (FAILED(hr
)) {
237 msg_Err(va
, "IDirect3DDeviceManager9_TestDevice %u", (unsigned)hr
);
241 int res
= va_pool_Get(&sys
->dx_sys
.va_pool
, pic
);
242 if (likely(res
==VLC_SUCCESS
))
243 *data
= (uint8_t*)((struct va_pic_context
*)pic
->context
)->picsys
.surface
;
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 va_surface_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 ctx
->hwaccel_context
= NULL
;
296 vlc_va_sys_t
*sys
= calloc(1, sizeof (*sys
));
297 if (unlikely(sys
== NULL
))
301 sys
->hd3d9_dll
= LoadLibrary(TEXT("D3D9.DLL"));
302 if (!sys
->hd3d9_dll
) {
303 msg_Warn(va
, "cannot load d3d9.dll");
307 dx_sys
= &sys
->dx_sys
;
309 dx_sys
->va_pool
.pf_create_device
= D3dCreateDevice
;
310 dx_sys
->va_pool
.pf_destroy_device
= D3dDestroyDevice
;
311 dx_sys
->va_pool
.pf_create_device_manager
= D3dCreateDeviceManager
;
312 dx_sys
->va_pool
.pf_destroy_device_manager
= D3dDestroyDeviceManager
;
313 dx_sys
->va_pool
.pf_create_video_service
= DxCreateVideoService
;
314 dx_sys
->va_pool
.pf_destroy_video_service
= DxDestroyVideoService
;
315 dx_sys
->va_pool
.pf_create_decoder_surfaces
= DxCreateVideoDecoder
;
316 dx_sys
->va_pool
.pf_destroy_surfaces
= DxDestroyVideoDecoder
;
317 dx_sys
->va_pool
.pf_setup_avcodec_ctx
= SetupAVCodecContext
;
318 dx_sys
->va_pool
.pf_new_surface_context
= NewSurfacePicContext
;
319 dx_sys
->pf_get_input_list
= DxGetInputList
;
320 dx_sys
->pf_setup_output
= DxSetupOutput
;
321 dx_sys
->psz_decoder_dll
= TEXT("DXVA2.DLL");
325 dx_sys
->d3ddev
= NULL
;
329 if (SUCCEEDED(IDirect3DSurface9_GetDesc(p_sys
->surface
, &src
)))
330 sys
->render
= src
.Format
;
331 IDirect3DSurface9_GetDevice(p_sys
->surface
, &dx_sys
->d3ddev
);
334 sys
->i_chroma
= d3d9va_fourcc(ctx
->sw_pix_fmt
);
336 err
= directx_va_Open(va
, &sys
->dx_sys
, true);
337 if (err
!=VLC_SUCCESS
)
340 err
= directx_va_Setup(va
, &sys
->dx_sys
, ctx
, fmt
);
341 if (err
!= VLC_SUCCESS
)
344 ctx
->hwaccel_context
= &sys
->hw
;
346 /* TODO print the hardware name/vendor for debugging purposes */
347 va
->description
= DxDescribe(sys
);
350 va
->release
= ReleasePic
;
351 va
->extract
= Extract
;
361 * It creates a Direct3D device usable for DXVA 2
363 static int D3dCreateDevice(vlc_va_t
*va
)
365 vlc_va_sys_t
*sys
= va
->sys
;
367 if (sys
->dx_sys
.d3ddev
) {
368 msg_Dbg(va
, "Reusing Direct3D9 device");
369 IDirect3DDevice9_AddRef(sys
->dx_sys
.d3ddev
);
374 LPDIRECT3D9 (WINAPI
*Create9
)(UINT SDKVersion
);
375 Create9
= (void *)GetProcAddress(sys
->hd3d9_dll
, "Direct3DCreate9");
377 msg_Err(va
, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
383 d3dobj
= Create9(D3D_SDK_VERSION
);
385 msg_Err(va
, "Direct3DCreate9 failed");
388 sys
->d3dobj
= d3dobj
;
391 D3DADAPTER_IDENTIFIER9
*d3dai
= &sys
->d3dai
;
392 if (FAILED(IDirect3D9_GetAdapterIdentifier(sys
->d3dobj
,
393 D3DADAPTER_DEFAULT
, 0, d3dai
))) {
394 msg_Warn(va
, "IDirect3D9_GetAdapterIdentifier failed");
395 ZeroMemory(d3dai
, sizeof(*d3dai
));
399 D3DPRESENT_PARAMETERS d3dpp
;
400 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
401 d3dpp
.Flags
= D3DPRESENTFLAG_VIDEO
;
402 d3dpp
.Windowed
= TRUE
;
403 d3dpp
.hDeviceWindow
= NULL
;
404 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
405 d3dpp
.MultiSampleType
= D3DMULTISAMPLE_NONE
;
406 d3dpp
.PresentationInterval
= D3DPRESENT_INTERVAL_DEFAULT
;
407 d3dpp
.BackBufferCount
= 0; /* FIXME what to put here */
408 d3dpp
.BackBufferFormat
= D3DFMT_X8R8G8B8
; /* FIXME what to put here */
409 d3dpp
.BackBufferWidth
= 0;
410 d3dpp
.BackBufferHeight
= 0;
411 d3dpp
.EnableAutoDepthStencil
= FALSE
;
413 /* Direct3D needs a HWND to create a device, even without using ::Present
414 this HWND is used to alert Direct3D when there's a change of focus window.
415 For now, use GetDesktopWindow, as it looks harmless */
416 LPDIRECT3DDEVICE9 d3ddev
;
417 if (FAILED(IDirect3D9_CreateDevice(d3dobj
, D3DADAPTER_DEFAULT
,
418 D3DDEVTYPE_HAL
, GetDesktopWindow(),
419 D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
420 D3DCREATE_MULTITHREADED
,
422 msg_Err(va
, "IDirect3D9_CreateDevice failed");
425 sys
->dx_sys
.d3ddev
= d3ddev
;
431 * It releases a Direct3D device and its resources.
433 static void D3dDestroyDevice(vlc_va_t
*va
)
435 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
437 IDirect3D9_Release(va
->sys
->d3dobj
);
439 IDirect3DDevice9_Release(dx_sys
->d3ddev
);
442 * It describes our Direct3D object
444 static char *DxDescribe(vlc_va_sys_t
*va
)
446 static const struct {
451 { 0x10DE, "NVIDIA" },
454 { 0x5333, "S3 Graphics" },
457 D3DADAPTER_IDENTIFIER9
*id
= &va
->d3dai
;
459 const char *vendor
= "Unknown";
460 for (int i
= 0; vendors
[i
].id
!= 0; i
++) {
461 if (vendors
[i
].id
== id
->VendorId
) {
462 vendor
= vendors
[i
].name
;
468 if (asprintf(&description
, "DXVA2 (%.*s, vendor %lu(%s), device %lu, revision %lu)",
469 (int)sizeof(id
->Description
), id
->Description
,
470 id
->VendorId
, vendor
, id
->DeviceId
, id
->Revision
) < 0)
476 * It creates a Direct3D device manager
478 static int D3dCreateDeviceManager(vlc_va_t
*va
)
480 vlc_va_sys_t
*sys
= va
->sys
;
481 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
483 HRESULT (WINAPI
*CreateDeviceManager9
)(UINT
*pResetToken
,
484 IDirect3DDeviceManager9
**);
485 CreateDeviceManager9
=
486 (void *)GetProcAddress(dx_sys
->hdecoder_dll
,
487 "DXVA2CreateDirect3DDeviceManager9");
489 if (!CreateDeviceManager9
) {
490 msg_Err(va
, "cannot load function");
493 msg_Dbg(va
, "OurDirect3DCreateDeviceManager9 Success!");
496 IDirect3DDeviceManager9
*devmng
;
497 if (FAILED(CreateDeviceManager9(&token
, &devmng
))) {
498 msg_Err(va
, " OurDirect3DCreateDeviceManager9 failed");
501 sys
->devmng
= devmng
;
502 msg_Info(va
, "obtained IDirect3DDeviceManager9");
504 HRESULT hr
= IDirect3DDeviceManager9_ResetDevice(devmng
, dx_sys
->d3ddev
, token
);
506 msg_Err(va
, "IDirect3DDeviceManager9_ResetDevice failed: %08x", (unsigned)hr
);
512 * It destroys a Direct3D device manager
514 static void D3dDestroyDeviceManager(vlc_va_t
*va
)
517 IDirect3DDeviceManager9_Release(va
->sys
->devmng
);
521 * It creates a DirectX video service
523 static int DxCreateVideoService(vlc_va_t
*va
)
525 vlc_va_sys_t
*sys
= va
->sys
;
526 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
528 HRESULT (WINAPI
*CreateVideoService
)(IDirect3DDevice9
*,
532 (void *)GetProcAddress(dx_sys
->hdecoder_dll
, "DXVA2CreateVideoService");
534 if (!CreateVideoService
) {
535 msg_Err(va
, "cannot load function");
538 msg_Info(va
, "DXVA2CreateVideoService Success!");
543 hr
= IDirect3DDeviceManager9_OpenDeviceHandle(sys
->devmng
, &device
);
545 msg_Err(va
, "OpenDeviceHandle failed");
548 sys
->device
= device
;
551 hr
= IDirect3DDeviceManager9_GetVideoService(sys
->devmng
, device
,
552 &IID_IDirectXVideoDecoderService
, &pv
);
554 msg_Err(va
, "GetVideoService failed");
563 * It destroys a DirectX video service
565 static void DxDestroyVideoService(vlc_va_t
*va
)
567 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
569 IDirect3DDeviceManager9_CloseDeviceHandle(va
->sys
->devmng
, va
->sys
->device
);
571 IDirectXVideoDecoderService_Release(dx_sys
->d3ddec
);
574 static void ReleaseInputList(input_list_t
*p_list
)
576 CoTaskMemFree(p_list
->list
);
579 static int DxGetInputList(vlc_va_t
*va
, input_list_t
*p_list
)
581 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
582 UINT input_count
= 0;
583 GUID
*input_list
= NULL
;
584 if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(dx_sys
->d3ddec
,
587 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderDeviceGuids failed");
591 p_list
->count
= input_count
;
592 p_list
->list
= input_list
;
593 p_list
->pf_release
= ReleaseInputList
;
597 static int DxSetupOutput(vlc_va_t
*va
, const GUID
*input
, const video_format_t
*fmt
)
600 int err
= VLC_EGENERIC
;
601 UINT output_count
= 0;
602 D3DFORMAT
*output_list
= NULL
;
603 if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(va
->sys
->dx_sys
.d3ddec
,
607 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderRenderTargets failed");
611 for (unsigned j
= 0; j
< output_count
; j
++) {
612 const D3DFORMAT f
= output_list
[j
];
613 const d3d_format_t
*format
= D3dFindFormat(f
);
615 msg_Dbg(va
, "%s is supported for output", format
->name
);
617 msg_Dbg(va
, "%d is supported for output (%4.4s)", f
, (const char*)&f
);
622 for (unsigned pass
= 0; pass
< 2 && err
!= VLC_SUCCESS
; ++pass
)
624 for (unsigned j
= 0; d3d_formats
[j
].name
; j
++) {
625 const d3d_format_t
*format
= &d3d_formats
[j
];
628 bool is_supported
= false;
629 for (unsigned k
= 0; !is_supported
&& k
< output_count
; k
++) {
630 is_supported
= format
->format
== output_list
[k
];
634 if (pass
== 0 && format
->format
!= va
->sys
->render
)
637 /* We have our solution */
638 msg_Dbg(va
, "Using decoder output '%s'", format
->name
);
639 va
->sys
->render
= format
->format
;
644 CoTaskMemFree(output_list
);
649 * It creates a DXVA2 decoder using the given video format
651 static int DxCreateVideoDecoder(vlc_va_t
*va
, int codec_id
,
652 const video_format_t
*fmt
, unsigned surface_count
)
654 vlc_va_sys_t
*p_sys
= va
->sys
;
655 directx_sys_t
*sys
= &va
->sys
->dx_sys
;
658 hr
= IDirectXVideoDecoderService_CreateSurface(sys
->d3ddec
,
665 DXVA2_VideoDecoderRenderTarget
,
669 msg_Err(va
, "IDirectXVideoAccelerationService_CreateSurface %d failed (hr=0x%0lx)", surface_count
- 1, hr
);
672 msg_Dbg(va
, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)",
673 surface_count
, fmt
->i_width
, fmt
->i_height
);
675 IDirect3DSurface9
*tstCrash
;
676 hr
= IDirectXVideoDecoderService_CreateSurface(sys
->d3ddec
,
683 DXVA2_VideoDecoderRenderTarget
,
687 msg_Err(va
, "extra buffer impossible, avoid a crash (hr=0x%0lx)", hr
);
688 for (unsigned i
= 0; i
< surface_count
; i
++)
689 IDirect3DSurface9_Release( sys
->hw_surface
[i
] );
692 IDirect3DSurface9_Release(tstCrash
);
696 ZeroMemory(&dsc
, sizeof(dsc
));
697 dsc
.SampleWidth
= fmt
->i_width
;
698 dsc
.SampleHeight
= fmt
->i_height
;
699 dsc
.Format
= p_sys
->render
;
700 if (fmt
->i_frame_rate
> 0 && fmt
->i_frame_rate_base
> 0) {
701 dsc
.InputSampleFreq
.Numerator
= fmt
->i_frame_rate
;
702 dsc
.InputSampleFreq
.Denominator
= fmt
->i_frame_rate_base
;
704 dsc
.InputSampleFreq
.Numerator
= 0;
705 dsc
.InputSampleFreq
.Denominator
= 0;
707 dsc
.OutputFrameFreq
= dsc
.InputSampleFreq
;
708 dsc
.UABProtectionLevel
= FALSE
;
711 /* FIXME I am unsure we can let unknown everywhere */
712 DXVA2_ExtendedFormat
*ext
= &dsc
.SampleFormat
;
713 ext
->SampleFormat
= 0;//DXVA2_SampleUnknown;
714 ext
->VideoChromaSubsampling
= 0;//DXVA2_VideoChromaSubsampling_Unknown;
715 ext
->NominalRange
= 0;//DXVA2_NominalRange_Unknown;
716 ext
->VideoTransferMatrix
= 0;//DXVA2_VideoTransferMatrix_Unknown;
717 ext
->VideoLighting
= 0;//DXVA2_VideoLighting_Unknown;
718 ext
->VideoPrimaries
= 0;//DXVA2_VideoPrimaries_Unknown;
719 ext
->VideoTransferFunction
= 0;//DXVA2_VideoTransFunc_Unknown;
721 /* List all configurations available for the decoder */
723 DXVA2_ConfigPictureDecode
*cfg_list
= NULL
;
724 if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(sys
->d3ddec
,
730 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderConfigurations failed");
731 for (unsigned i
= 0; i
< surface_count
; i
++)
732 IDirect3DSurface9_Release( sys
->hw_surface
[i
] );
735 msg_Dbg(va
, "we got %d decoder configurations", cfg_count
);
737 /* Select the best decoder configuration */
739 for (unsigned i
= 0; i
< cfg_count
; i
++) {
740 const DXVA2_ConfigPictureDecode
*cfg
= &cfg_list
[i
];
743 msg_Dbg(va
, "configuration[%d] ConfigBitstreamRaw %d",
744 i
, cfg
->ConfigBitstreamRaw
);
748 if (cfg
->ConfigBitstreamRaw
== 1)
750 else if (codec_id
== AV_CODEC_ID_H264
&& cfg
->ConfigBitstreamRaw
== 2)
754 if (IsEqualGUID(&cfg
->guidConfigBitstreamEncryption
, &DXVA2_NoEncrypt
))
757 if (cfg_score
< score
) {
762 CoTaskMemFree(cfg_list
);
763 if (cfg_score
<= 0) {
764 msg_Err(va
, "Failed to find a supported decoder configuration");
768 /* Create the decoder */
769 IDirectXVideoDecoder
*decoder
;
770 if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(sys
->d3ddec
,
777 msg_Err(va
, "IDirectXVideoDecoderService_CreateVideoDecoder failed");
778 for (unsigned i
= 0; i
< surface_count
; i
++)
779 IDirect3DSurface9_Release( sys
->hw_surface
[i
] );
782 sys
->decoder
= decoder
;
784 msg_Dbg(va
, "IDirectXVideoDecoderService_CreateVideoDecoder succeed");
788 static void DxDestroyVideoDecoder(vlc_va_t
*va
)
790 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
793 IDirectXVideoDecoder_Release(dx_sys
->decoder
);
794 dx_sys
->decoder
= NULL
;
798 static int DxResetVideoDecoder(vlc_va_t
*va
)
800 msg_Err(va
, "DxResetVideoDecoder unimplemented");