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_filter.h> /* need for the DXA9 to YV12 conversion */
35 #include <vlc_modules.h>
36 #include <vlc_plugin.h>
38 #include "directx_va.h"
40 #define DXVA2API_USE_BITFIELDS
42 #include <libavcodec/dxva2.h>
44 static int Open(vlc_va_t
*, AVCodecContext
*, enum PixelFormat
,
45 const es_format_t
*, picture_sys_t
*p_sys
);
46 static void Close(vlc_va_t
*, AVCodecContext
*);
49 set_description(N_("DirectX Video Acceleration (DXVA) 2.0"))
50 set_capability("hw decoder", 0)
51 set_category(CAT_INPUT
)
52 set_subcategory(SUBCAT_INPUT_VCODEC
)
53 set_callbacks(Open
, Close
)
56 #include <initguid.h> /* must be last included to not redefine existing GUIDs */
58 /* dxva2api.h GUIDs: http://msdn.microsoft.com/en-us/library/windows/desktop/ms697067(v=vs100).aspx
59 * assume that they are declared in dxva2api.h */
60 #define MS_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
65 # if !defined(__MINGW64_VERSION_MAJOR)
67 # define MS_GUID DEFINE_GUID /* dxva2api.h fails to declare those, redefine as static */
68 # define DXVA2_E_NEW_VIDEO_DEVICE MAKE_HRESULT(1, 4, 4097)
73 #endif /* __MINGW32__ */
75 MS_GUID(IID_IDirectXVideoDecoderService
, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
76 MS_GUID(IID_IDirectXVideoAccelerationService
, 0xfc51a550, 0xd5e7, 0x11d9, 0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
78 DEFINE_GUID(DXVA2_NoEncrypt
, 0x1b81bed0, 0xa0c7, 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);
80 DEFINE_GUID(DXVA_Intel_H264_NoFGT_ClearVideo
, 0x604F8E68, 0x4951, 0x4c54, 0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6);
89 /* XXX Prefered format must come first */
90 static const d3d_format_t d3d_formats
[] = {
91 { "YV12", MAKEFOURCC('Y','V','1','2'), VLC_CODEC_YV12
},
92 { "NV12", MAKEFOURCC('N','V','1','2'), VLC_CODEC_NV12
},
93 { "IMC3", MAKEFOURCC('I','M','C','3'), VLC_CODEC_YV12
},
94 { "P010", MAKEFOURCC('P','0','1','0'), VLC_CODEC_P010
},
99 static const d3d_format_t
*D3dFindFormat(D3DFORMAT format
)
101 for (unsigned i
= 0; d3d_formats
[i
].name
; i
++) {
102 if (d3d_formats
[i
].format
== format
)
103 return &d3d_formats
[i
];
110 directx_sys_t dx_sys
;
111 vlc_fourcc_t i_chroma
;
118 D3DADAPTER_IDENTIFIER9 d3dai
;
121 IDirect3DDeviceManager9
*devmng
;
128 DXVA2_ConfigPictureDecode cfg
;
130 /* Option conversion */
133 /* avcodec internals */
134 struct dxva_context hw
;
139 LPDIRECT3DSURFACE9 surface
;
142 static picture_t
*DxAllocPicture(vlc_va_t
*, const video_format_t
*, unsigned index
);
146 static int D3dCreateDevice(vlc_va_t
*);
147 static void D3dDestroyDevice(vlc_va_t
*);
148 static char *DxDescribe(vlc_va_sys_t
*);
150 static int D3dCreateDeviceManager(vlc_va_t
*);
151 static void D3dDestroyDeviceManager(vlc_va_t
*);
153 static int DxCreateVideoService(vlc_va_t
*);
154 static void DxDestroyVideoService(vlc_va_t
*);
155 static int DxGetInputList(vlc_va_t
*, input_list_t
*);
156 static int DxSetupOutput(vlc_va_t
*, const GUID
*, const video_format_t
*);
158 static int DxCreateVideoDecoder(vlc_va_t
*,
159 int codec_id
, const video_format_t
*);
160 static void DxDestroyVideoDecoder(vlc_va_t
*);
161 static int DxResetVideoDecoder(vlc_va_t
*);
162 static void SetupAVCodecContext(vlc_va_t
*);
164 static void DeleteFilter( filter_t
* p_filter
)
166 if( p_filter
->p_module
)
167 module_unneed( p_filter
, p_filter
->p_module
);
169 es_format_Clean( &p_filter
->fmt_in
);
170 es_format_Clean( &p_filter
->fmt_out
);
172 vlc_object_release( p_filter
);
175 static picture_t
*video_new_buffer(filter_t
*p_filter
)
177 return p_filter
->owner
.sys
;
180 static filter_t
*CreateFilter( vlc_object_t
*p_this
, const es_format_t
*p_fmt_in
,
181 vlc_fourcc_t src_chroma
)
185 p_filter
= vlc_object_create( p_this
, sizeof(filter_t
) );
186 if (unlikely(p_filter
== NULL
))
189 p_filter
->owner
.video
.buffer_new
= (picture_t
*(*)(filter_t
*))video_new_buffer
;
191 vlc_fourcc_t fmt_out
;
194 case VLC_CODEC_D3D9_OPAQUE_10B
:
195 fmt_out
= VLC_CODEC_P010
;
197 case VLC_CODEC_D3D9_OPAQUE
:
198 fmt_out
= VLC_CODEC_YV12
;
202 es_format_InitFromVideo( &p_filter
->fmt_in
, &p_fmt_in
->video
);
203 es_format_InitFromVideo( &p_filter
->fmt_out
, &p_fmt_in
->video
);
204 p_filter
->fmt_in
.i_codec
= p_filter
->fmt_in
.video
.i_chroma
= src_chroma
;
205 p_filter
->fmt_out
.i_codec
= p_filter
->fmt_out
.video
.i_chroma
= fmt_out
;
206 p_filter
->p_module
= module_need( p_filter
, "video converter", NULL
, false );
208 if( !p_filter
->p_module
)
210 msg_Dbg( p_filter
, "no video converter found" );
211 DeleteFilter( p_filter
);
219 static void Setup(vlc_va_t
*va
, vlc_fourcc_t
*chroma
)
221 vlc_va_sys_t
*sys
= va
->sys
;
223 *chroma
= sys
->filter
== NULL
? sys
->i_chroma
: VLC_CODEC_YV12
;
226 void SetupAVCodecContext(vlc_va_t
*va
)
228 vlc_va_sys_t
*sys
= va
->sys
;
229 directx_sys_t
*dx_sys
= &sys
->dx_sys
;
231 sys
->hw
.decoder
= (IDirectXVideoDecoder
*) dx_sys
->decoder
;
232 sys
->hw
.cfg
= &sys
->cfg
;
233 sys
->hw
.surface_count
= dx_sys
->surface_count
;
234 sys
->hw
.surface
= (LPDIRECT3DSURFACE9
*) dx_sys
->hw_surface
;
236 if (IsEqualGUID(&dx_sys
->input
, &DXVA_Intel_H264_NoFGT_ClearVideo
))
237 sys
->hw
.workaround
|= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO
;
240 static int Extract(vlc_va_t
*va
, picture_t
*picture
, uint8_t *data
)
242 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
243 LPDIRECT3DSURFACE9 d3d
= (LPDIRECT3DSURFACE9
)(uintptr_t)data
;
244 if ( picture
->format
.i_chroma
== VLC_CODEC_D3D9_OPAQUE
||
245 picture
->format
.i_chroma
== VLC_CODEC_D3D9_OPAQUE_10B
)
247 picture_sys_t
*p_sys
= picture
->p_sys
;
248 LPDIRECT3DSURFACE9 output
= p_sys
->surface
;
250 assert(d3d
!= output
);
252 LPDIRECT3DDEVICE9 srcDevice
, dstDevice
;
253 IDirect3DSurface9_GetDevice(d3d
, &srcDevice
);
254 IDirect3DSurface9_GetDevice(output
, &dstDevice
);
255 assert(srcDevice
== dstDevice
);
260 visibleSource
.left
= 0;
261 visibleSource
.top
= 0;
262 visibleSource
.right
= picture
->format
.i_visible_width
;
263 visibleSource
.bottom
= picture
->format
.i_visible_height
;
264 hr
= IDirect3DDevice9_StretchRect( (IDirect3DDevice9
*) dx_sys
->d3ddev
, d3d
, &visibleSource
, output
, &visibleSource
, D3DTEXF_NONE
);
266 msg_Err(va
, "Failed to copy the hw surface to the decoder surface (hr=0x%0lx)", hr
);
270 else if (va
->sys
->filter
!= NULL
) {
271 va
->sys
->filter
->owner
.sys
= picture
;
272 vlc_va_surface_t
*surface
= picture
->context
;
273 picture_Hold( surface
->p_pic
);
274 va
->sys
->filter
->pf_video_filter( va
->sys
->filter
, surface
->p_pic
);
276 msg_Err(va
, "Unsupported output picture format %08X", picture
->format
.i_chroma
);
283 static int CheckDevice(vlc_va_t
*va
)
285 vlc_va_sys_t
*sys
= va
->sys
;
287 /* Check the device */
288 HRESULT hr
= IDirect3DDeviceManager9_TestDevice(sys
->devmng
, sys
->device
);
289 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
) {
290 if (DxResetVideoDecoder(va
))
292 } else if (FAILED(hr
)) {
293 msg_Err(va
, "IDirect3DDeviceManager9_TestDevice %u", (unsigned)hr
);
299 static int Get(vlc_va_t
*va
, picture_t
*pic
, uint8_t **data
)
301 return directx_va_Get(va
, &va
->sys
->dx_sys
, pic
, data
);
304 static void Close(vlc_va_t
*va
, AVCodecContext
*ctx
)
306 vlc_va_sys_t
*sys
= va
->sys
;
312 DeleteFilter( sys
->filter
);
316 directx_va_Close(va
, &sys
->dx_sys
);
319 FreeLibrary(sys
->hd3d9_dll
);
321 free((char *)va
->description
);
325 static vlc_fourcc_t
d3d9va_fourcc(enum PixelFormat swfmt
)
329 case AV_PIX_FMT_YUV420P10LE
:
330 return VLC_CODEC_D3D9_OPAQUE_10B
;
331 case AV_PIX_FMT_YUVJ420P
:
332 case AV_PIX_FMT_YUV420P
:
333 return VLC_CODEC_D3D9_OPAQUE
;
335 return VLC_CODEC_D3D9_OPAQUE
;
339 static int Open(vlc_va_t
*va
, AVCodecContext
*ctx
, enum PixelFormat pix_fmt
,
340 const es_format_t
*fmt
, picture_sys_t
*p_sys
)
342 int err
= VLC_EGENERIC
;
343 directx_sys_t
*dx_sys
;
345 if (pix_fmt
!= AV_PIX_FMT_DXVA2_VLD
)
348 vlc_va_sys_t
*sys
= calloc(1, sizeof (*sys
));
349 if (unlikely(sys
== NULL
))
353 sys
->hd3d9_dll
= LoadLibrary(TEXT("D3D9.DLL"));
354 if (!sys
->hd3d9_dll
) {
355 msg_Warn(va
, "cannot load d3d9.dll");
359 dx_sys
= &sys
->dx_sys
;
361 dx_sys
->pf_check_device
= CheckDevice
;
362 dx_sys
->pf_create_device
= D3dCreateDevice
;
363 dx_sys
->pf_destroy_device
= D3dDestroyDevice
;
364 dx_sys
->pf_create_device_manager
= D3dCreateDeviceManager
;
365 dx_sys
->pf_destroy_device_manager
= D3dDestroyDeviceManager
;
366 dx_sys
->pf_create_video_service
= DxCreateVideoService
;
367 dx_sys
->pf_destroy_video_service
= DxDestroyVideoService
;
368 dx_sys
->pf_create_decoder_surfaces
= DxCreateVideoDecoder
;
369 dx_sys
->pf_destroy_surfaces
= DxDestroyVideoDecoder
;
370 dx_sys
->pf_setup_avcodec_ctx
= SetupAVCodecContext
;
371 dx_sys
->pf_get_input_list
= DxGetInputList
;
372 dx_sys
->pf_setup_output
= DxSetupOutput
;
373 dx_sys
->pf_alloc_surface_pic
= DxAllocPicture
;
374 dx_sys
->psz_decoder_dll
= TEXT("DXVA2.DLL");
378 dx_sys
->d3ddev
= NULL
;
380 IDirect3DSurface9_GetDevice(p_sys
->surface
, (IDirect3DDevice9
**) &dx_sys
->d3ddev
);
382 sys
->i_chroma
= d3d9va_fourcc(ctx
->sw_pix_fmt
);
384 err
= directx_va_Open(va
, &sys
->dx_sys
, ctx
, fmt
, true);
385 if (err
!=VLC_SUCCESS
)
390 sys
->filter
= CreateFilter( VLC_OBJECT(va
), fmt
, sys
->i_chroma
);
391 if (sys
->filter
== NULL
)
395 err
= directx_va_Setup(va
, &sys
->dx_sys
, ctx
);
396 if (err
!= VLC_SUCCESS
)
399 ctx
->hwaccel_context
= &sys
->hw
;
401 /* TODO print the hardware name/vendor for debugging purposes */
402 va
->description
= DxDescribe(sys
);
405 va
->release
= directx_va_Release
;
406 va
->extract
= Extract
;
416 * It creates a Direct3D device usable for DXVA 2
418 static int D3dCreateDevice(vlc_va_t
*va
)
420 vlc_va_sys_t
*sys
= va
->sys
;
422 if (sys
->dx_sys
.d3ddev
) {
423 msg_Dbg(va
, "Reusing Direct3D9 device");
424 IDirect3DDevice9_AddRef(sys
->dx_sys
.d3ddev
);
429 LPDIRECT3D9 (WINAPI
*Create9
)(UINT SDKVersion
);
430 Create9
= (void *)GetProcAddress(sys
->hd3d9_dll
, "Direct3DCreate9");
432 msg_Err(va
, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
438 d3dobj
= Create9(D3D_SDK_VERSION
);
440 msg_Err(va
, "Direct3DCreate9 failed");
443 sys
->d3dobj
= d3dobj
;
446 D3DADAPTER_IDENTIFIER9
*d3dai
= &sys
->d3dai
;
447 if (FAILED(IDirect3D9_GetAdapterIdentifier(sys
->d3dobj
,
448 D3DADAPTER_DEFAULT
, 0, d3dai
))) {
449 msg_Warn(va
, "IDirect3D9_GetAdapterIdentifier failed");
450 ZeroMemory(d3dai
, sizeof(*d3dai
));
454 D3DPRESENT_PARAMETERS d3dpp
;
455 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
456 d3dpp
.Flags
= D3DPRESENTFLAG_VIDEO
;
457 d3dpp
.Windowed
= TRUE
;
458 d3dpp
.hDeviceWindow
= NULL
;
459 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
460 d3dpp
.MultiSampleType
= D3DMULTISAMPLE_NONE
;
461 d3dpp
.PresentationInterval
= D3DPRESENT_INTERVAL_DEFAULT
;
462 d3dpp
.BackBufferCount
= 0; /* FIXME what to put here */
463 d3dpp
.BackBufferFormat
= D3DFMT_X8R8G8B8
; /* FIXME what to put here */
464 d3dpp
.BackBufferWidth
= 0;
465 d3dpp
.BackBufferHeight
= 0;
466 d3dpp
.EnableAutoDepthStencil
= FALSE
;
468 /* Direct3D needs a HWND to create a device, even without using ::Present
469 this HWND is used to alert Direct3D when there's a change of focus window.
470 For now, use GetDesktopWindow, as it looks harmless */
471 LPDIRECT3DDEVICE9 d3ddev
;
472 if (FAILED(IDirect3D9_CreateDevice(d3dobj
, D3DADAPTER_DEFAULT
,
473 D3DDEVTYPE_HAL
, GetDesktopWindow(),
474 D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
475 D3DCREATE_MULTITHREADED
,
477 msg_Err(va
, "IDirect3D9_CreateDevice failed");
480 sys
->dx_sys
.d3ddev
= (IUnknown
*) d3ddev
;
486 * It releases a Direct3D device and its resources.
488 static void D3dDestroyDevice(vlc_va_t
*va
)
491 IDirect3D9_Release(va
->sys
->d3dobj
);
494 * It describes our Direct3D object
496 static char *DxDescribe(vlc_va_sys_t
*va
)
498 static const struct {
503 { 0x10DE, "NVIDIA" },
506 { 0x5333, "S3 Graphics" },
509 D3DADAPTER_IDENTIFIER9
*id
= &va
->d3dai
;
511 const char *vendor
= "Unknown";
512 for (int i
= 0; vendors
[i
].id
!= 0; i
++) {
513 if (vendors
[i
].id
== id
->VendorId
) {
514 vendor
= vendors
[i
].name
;
520 if (asprintf(&description
, "DXVA2 (%.*s, vendor %lu(%s), device %lu, revision %lu)",
521 (int)sizeof(id
->Description
), id
->Description
,
522 id
->VendorId
, vendor
, id
->DeviceId
, id
->Revision
) < 0)
528 * It creates a Direct3D device manager
530 static int D3dCreateDeviceManager(vlc_va_t
*va
)
532 vlc_va_sys_t
*sys
= va
->sys
;
533 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
535 HRESULT (WINAPI
*CreateDeviceManager9
)(UINT
*pResetToken
,
536 IDirect3DDeviceManager9
**);
537 CreateDeviceManager9
=
538 (void *)GetProcAddress(dx_sys
->hdecoder_dll
,
539 "DXVA2CreateDirect3DDeviceManager9");
541 if (!CreateDeviceManager9
) {
542 msg_Err(va
, "cannot load function");
545 msg_Dbg(va
, "OurDirect3DCreateDeviceManager9 Success!");
548 IDirect3DDeviceManager9
*devmng
;
549 if (FAILED(CreateDeviceManager9(&token
, &devmng
))) {
550 msg_Err(va
, " OurDirect3DCreateDeviceManager9 failed");
553 sys
->devmng
= devmng
;
554 msg_Info(va
, "obtained IDirect3DDeviceManager9");
556 HRESULT hr
= IDirect3DDeviceManager9_ResetDevice(devmng
, (IDirect3DDevice9
*) dx_sys
->d3ddev
, token
);
558 msg_Err(va
, "IDirect3DDeviceManager9_ResetDevice failed: %08x", (unsigned)hr
);
564 * It destroys a Direct3D device manager
566 static void D3dDestroyDeviceManager(vlc_va_t
*va
)
569 IDirect3DDeviceManager9_Release(va
->sys
->devmng
);
573 * It creates a DirectX video service
575 static int DxCreateVideoService(vlc_va_t
*va
)
577 vlc_va_sys_t
*sys
= va
->sys
;
578 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
580 HRESULT (WINAPI
*CreateVideoService
)(IDirect3DDevice9
*,
584 (void *)GetProcAddress(dx_sys
->hdecoder_dll
, "DXVA2CreateVideoService");
586 if (!CreateVideoService
) {
587 msg_Err(va
, "cannot load function");
590 msg_Info(va
, "DXVA2CreateVideoService Success!");
595 hr
= IDirect3DDeviceManager9_OpenDeviceHandle(sys
->devmng
, &device
);
597 msg_Err(va
, "OpenDeviceHandle failed");
600 sys
->device
= device
;
603 hr
= IDirect3DDeviceManager9_GetVideoService(sys
->devmng
, device
,
604 &IID_IDirectXVideoDecoderService
, &pv
);
606 msg_Err(va
, "GetVideoService failed");
615 * It destroys a DirectX video service
617 static void DxDestroyVideoService(vlc_va_t
*va
)
620 IDirect3DDeviceManager9_CloseDeviceHandle(va
->sys
->devmng
, va
->sys
->device
);
623 static void ReleaseInputList(input_list_t
*p_list
)
625 CoTaskMemFree(p_list
->list
);
628 static int DxGetInputList(vlc_va_t
*va
, input_list_t
*p_list
)
630 directx_sys_t
*dx_sys
= &va
->sys
->dx_sys
;
631 UINT input_count
= 0;
632 GUID
*input_list
= NULL
;
633 if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids((IDirectXVideoDecoderService
*) dx_sys
->d3ddec
,
636 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderDeviceGuids failed");
640 p_list
->count
= input_count
;
641 p_list
->list
= input_list
;
642 p_list
->pf_release
= ReleaseInputList
;
646 static int DxSetupOutput(vlc_va_t
*va
, const GUID
*input
, const video_format_t
*fmt
)
649 int err
= VLC_EGENERIC
;
650 UINT output_count
= 0;
651 D3DFORMAT
*output_list
= NULL
;
652 if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets((IDirectXVideoDecoderService
*) va
->sys
->dx_sys
.d3ddec
,
656 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderRenderTargets failed");
660 for (unsigned j
= 0; j
< output_count
; j
++) {
661 const D3DFORMAT f
= output_list
[j
];
662 const d3d_format_t
*format
= D3dFindFormat(f
);
664 msg_Dbg(va
, "%s is supported for output", format
->name
);
666 msg_Dbg(va
, "%d is supported for output (%4.4s)", f
, (const char*)&f
);
671 for (unsigned j
= 0; d3d_formats
[j
].name
; j
++) {
672 const d3d_format_t
*format
= &d3d_formats
[j
];
675 bool is_supported
= false;
676 for (unsigned k
= 0; !is_supported
&& k
< output_count
; k
++) {
677 is_supported
= format
->format
== output_list
[k
];
682 /* We have our solution */
683 msg_Dbg(va
, "Using decoder output '%s'", format
->name
);
684 va
->sys
->render
= format
->format
;
688 CoTaskMemFree(output_list
);
693 * It creates a DXVA2 decoder using the given video format
695 static int DxCreateVideoDecoder(vlc_va_t
*va
, int codec_id
, const video_format_t
*fmt
)
697 vlc_va_sys_t
*p_sys
= va
->sys
;
698 directx_sys_t
*sys
= &va
->sys
->dx_sys
;
701 hr
= IDirectXVideoDecoderService_CreateSurface((IDirectXVideoDecoderService
*) sys
->d3ddec
,
704 sys
->surface_count
- 1,
708 DXVA2_VideoDecoderRenderTarget
,
709 (LPDIRECT3DSURFACE9
*) sys
->hw_surface
,
712 msg_Err(va
, "IDirectXVideoAccelerationService_CreateSurface %d failed (hr=0x%0lx)", sys
->surface_count
- 1, hr
);
713 sys
->surface_count
= 0;
716 msg_Dbg(va
, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)",
717 sys
->surface_count
, sys
->surface_width
, sys
->surface_height
);
719 IDirect3DSurface9
*tstCrash
;
720 hr
= IDirectXVideoDecoderService_CreateSurface((IDirectXVideoDecoderService
*) sys
->d3ddec
,
727 DXVA2_VideoDecoderRenderTarget
,
731 msg_Err(va
, "extra buffer impossible, avoid a crash (hr=0x%0lx)", hr
);
732 for (int i
= 0; i
< sys
->surface_count
; i
++)
733 IDirect3DSurface9_Release( (IDirect3DSurface9
*) sys
->hw_surface
[i
] );
734 sys
->surface_count
= 0;
737 IDirect3DSurface9_Release(tstCrash
);
741 ZeroMemory(&dsc
, sizeof(dsc
));
742 dsc
.SampleWidth
= fmt
->i_width
;
743 dsc
.SampleHeight
= fmt
->i_height
;
744 dsc
.Format
= p_sys
->render
;
745 if (fmt
->i_frame_rate
> 0 && fmt
->i_frame_rate_base
> 0) {
746 dsc
.InputSampleFreq
.Numerator
= fmt
->i_frame_rate
;
747 dsc
.InputSampleFreq
.Denominator
= fmt
->i_frame_rate_base
;
749 dsc
.InputSampleFreq
.Numerator
= 0;
750 dsc
.InputSampleFreq
.Denominator
= 0;
752 dsc
.OutputFrameFreq
= dsc
.InputSampleFreq
;
753 dsc
.UABProtectionLevel
= FALSE
;
756 /* FIXME I am unsure we can let unknown everywhere */
757 DXVA2_ExtendedFormat
*ext
= &dsc
.SampleFormat
;
758 ext
->SampleFormat
= 0;//DXVA2_SampleUnknown;
759 ext
->VideoChromaSubsampling
= 0;//DXVA2_VideoChromaSubsampling_Unknown;
760 ext
->NominalRange
= 0;//DXVA2_NominalRange_Unknown;
761 ext
->VideoTransferMatrix
= 0;//DXVA2_VideoTransferMatrix_Unknown;
762 ext
->VideoLighting
= 0;//DXVA2_VideoLighting_Unknown;
763 ext
->VideoPrimaries
= 0;//DXVA2_VideoPrimaries_Unknown;
764 ext
->VideoTransferFunction
= 0;//DXVA2_VideoTransFunc_Unknown;
766 /* List all configurations available for the decoder */
768 DXVA2_ConfigPictureDecode
*cfg_list
= NULL
;
769 if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations((IDirectXVideoDecoderService
*) sys
->d3ddec
,
775 msg_Err(va
, "IDirectXVideoDecoderService_GetDecoderConfigurations failed");
776 for (int i
= 0; i
< sys
->surface_count
; i
++)
777 IDirect3DSurface9_Release( (IDirect3DSurface9
*) sys
->hw_surface
[i
] );
778 sys
->surface_count
= 0;
781 msg_Dbg(va
, "we got %d decoder configurations", cfg_count
);
783 /* Select the best decoder configuration */
785 for (unsigned i
= 0; i
< cfg_count
; i
++) {
786 const DXVA2_ConfigPictureDecode
*cfg
= &cfg_list
[i
];
789 msg_Dbg(va
, "configuration[%d] ConfigBitstreamRaw %d",
790 i
, cfg
->ConfigBitstreamRaw
);
794 if (cfg
->ConfigBitstreamRaw
== 1)
796 else if (codec_id
== AV_CODEC_ID_H264
&& cfg
->ConfigBitstreamRaw
== 2)
800 if (IsEqualGUID(&cfg
->guidConfigBitstreamEncryption
, &DXVA2_NoEncrypt
))
803 if (cfg_score
< score
) {
808 CoTaskMemFree(cfg_list
);
809 if (cfg_score
<= 0) {
810 msg_Err(va
, "Failed to find a supported decoder configuration");
814 /* Create the decoder */
815 IDirectXVideoDecoder
*decoder
;
816 if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder((IDirectXVideoDecoderService
*) sys
->d3ddec
,
820 (LPDIRECT3DSURFACE9
*) sys
->hw_surface
,
823 msg_Err(va
, "IDirectXVideoDecoderService_CreateVideoDecoder failed");
824 for (int i
= 0; i
< sys
->surface_count
; i
++)
825 IDirect3DSurface9_Release( (IDirect3DSurface9
*) sys
->hw_surface
[i
] );
826 sys
->surface_count
= 0;
829 sys
->decoder
= (IUnknown
*) decoder
;
831 msg_Dbg(va
, "IDirectXVideoDecoderService_CreateVideoDecoder succeed");
835 static void DxDestroyVideoDecoder(vlc_va_t
*va
)
840 static int DxResetVideoDecoder(vlc_va_t
*va
)
842 msg_Err(va
, "DxResetVideoDecoder unimplemented");
846 static picture_t
*DxAllocPicture(vlc_va_t
*va
, const video_format_t
*fmt
, unsigned index
)
848 video_format_t src_fmt
= *fmt
;
849 src_fmt
.i_chroma
= va
->sys
->i_chroma
;
850 picture_sys_t
*pic_sys
= calloc(1, sizeof(*pic_sys
));
851 if (unlikely(pic_sys
== NULL
))
853 pic_sys
->surface
= (LPDIRECT3DSURFACE9
) va
->sys
->dx_sys
.hw_surface
[index
];
855 picture_resource_t res
= {
858 picture_t
*pic
= picture_NewFromResource(&src_fmt
, &res
);
859 if (unlikely(pic
== NULL
))