1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <windows.h>
20
21 #ifdef _WIN32_WINNT
22 #undef _WIN32_WINNT
23 #endif
24 #define _WIN32_WINNT 0x0600
25 #define DXVA2API_USE_BITFIELDS
27
28 #include <stdint.h>
29
30 #include <d3d9.h>
31 #include <dxva2api.h>
32
34
36
42
43 /* define all the GUIDs used directly here,
44 to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
45 #include <initguid.h>
46 DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
47
48 DEFINE_GUID(DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);
49 DEFINE_GUID(DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
50 DEFINE_GUID(DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
51 DEFINE_GUID(DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
52 DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
53 DEFINE_GUID(DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
54 DEFINE_GUID(DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
55 DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
56 DEFINE_GUID(DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
57 DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
58
61
66
68 /* MPEG-2 */
71
72 /* H.264 */
75 /* Intel specific H.264 mode */
77
78 /* VC-1 / WMV3 */
83
84 /* HEVC/H.265 */
86
88 };
89
94
98
100
106
109
114
117
123
125 {
128 int i;
129
133 IDirect3DSurface9_Release(ctx->
surfaces[i]);
134 }
135 }
140
142 IDirectXVideoDecoder_Release(ctx->
decoder);
144 }
145 }
146
148 {
151
155
158
161
164
166 IDirect3DDeviceManager9_Release(ctx->
d3d9devmgr);
167
170
172 IDirect3D9_Release(ctx->
d3d9);
173
176
179
181
184 }
185
187 {
190 int i;
191
195 break;
196 }
197 }
198 IDirect3DSurface9_Release(w->
surface);
199 IDirectXVideoDecoder_Release(w->
decoder);
201 }
202
204 {
207 int i, old_unused = -1;
208 LPDIRECT3DSURFACE9 surface;
210
212
216 old_unused = i;
217 }
218 if (old_unused == -1) {
221 }
222 i = old_unused;
223
225
227 if (!w)
229
233 if (!frame->
buf[0]) {
236 }
237
240 IDirect3DSurface9_AddRef(w->
surface);
242 IDirectXVideoDecoder_AddRef(w->
decoder);
243
246
248
249 return 0;
250 }
251
253 {
254 LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)frame->
data[3];
257 D3DSURFACE_DESC surfaceDesc;
258 D3DLOCKED_RECT LockedRect;
261
262 IDirect3DSurface9_GetDesc(surface, &surfaceDesc);
263
264 ctx->tmp_frame->width = frame->
width;
265 ctx->tmp_frame->height = frame->
height;
267
271
272 hr = IDirect3DSurface9_LockRect(surface, &LockedRect,
NULL, D3DLOCK_READONLY);
276 }
277
281
283 (
uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height,
284 LockedRect.Pitch, frame->
width, frame->
height / 2);
285
286 IDirect3DSurface9_UnlockRect(surface);
287
290 goto fail;
291
294
295 return 0;
296 fail:
299 }
300
302 {
309 D3DPRESENT_PARAMETERS d3dpp = {0};
310 D3DDISPLAYMODE d3ddm;
311 unsigned resetToken = 0;
312 UINT adapter = D3DADAPTER_DEFAULT;
313
315 if (!ctx)
317
319
324
327 av_log(
NULL, loglevel,
"Failed to load D3D9 library\n");
328 goto fail;
329 }
332 av_log(
NULL, loglevel,
"Failed to load DXVA2 library\n");
333 goto fail;
334 }
335
337 if (!createD3D) {
338 av_log(
NULL, loglevel,
"Failed to locate Direct3DCreate9\n");
339 goto fail;
340 }
342 if (!createDeviceManager) {
343 av_log(
NULL, loglevel,
"Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
344 goto fail;
345 }
346
347 ctx->
d3d9 = createD3D(D3D_SDK_VERSION);
349 av_log(
NULL, loglevel,
"Failed to create IDirect3D object\n");
350 goto fail;
351 }
352
356 }
357
358 IDirect3D9_GetAdapterDisplayMode(ctx->
d3d9, adapter, &d3ddm);
359 d3dpp.Windowed =
TRUE;
360 d3dpp.BackBufferWidth = 640;
361 d3dpp.BackBufferHeight = 480;
362 d3dpp.BackBufferCount = 0;
363 d3dpp.BackBufferFormat = d3ddm.Format;
364 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
365 d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
366
367 hr = IDirect3D9_CreateDevice(ctx->
d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(),
368 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
371 av_log(
NULL, loglevel,
"Failed to create Direct3D device\n");
372 goto fail;
373 }
374
375 hr = createDeviceManager(&resetToken, &ctx->
d3d9devmgr);
377 av_log(
NULL, loglevel,
"Failed to create Direct3D device manager\n");
378 goto fail;
379 }
380
383 av_log(
NULL, loglevel,
"Failed to bind Direct3D device to device manager\n");
384 goto fail;
385 }
386
389 av_log(
NULL, loglevel,
"Failed to open device handle\n");
390 goto fail;
391 }
392
395 av_log(
NULL, loglevel,
"Failed to create IDirectXVideoDecoderService\n");
396 goto fail;
397 }
398
401 goto fail;
402
405 goto fail;
406
407 return 0;
408 fail:
411 }
412
414 const DXVA2_VideoDesc *desc,
415 DXVA2_ConfigPictureDecode *
config)
416 {
420 unsigned cfg_count = 0, best_score = 0;
421 DXVA2_ConfigPictureDecode *cfg_list =
NULL;
422 DXVA2_ConfigPictureDecode best_cfg = {{0}};
424 int i;
425
426 hr = IDirectXVideoDecoderService_GetDecoderConfigurations(ctx->
decoder_service, device_guid, desc,
NULL, &cfg_count, &cfg_list);
428 av_log(
NULL, loglevel,
"Unable to retrieve decoder configurations\n");
430 }
431
432 for (i = 0; i < cfg_count; i++) {
433 DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
434
435 unsigned score;
436 if (cfg->ConfigBitstreamRaw == 1)
437 score = 1;
439 score = 2;
440 else
441 continue;
442 if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt))
443 score += 16;
444 if (score > best_score) {
445 best_score = score;
446 best_cfg = *cfg;
447 }
448 }
449 CoTaskMemFree(cfg_list);
450
451 if (!best_score) {
452 av_log(
NULL, loglevel,
"No valid decoder configuration available\n");
454 }
455
456 *config = best_cfg;
457 return 0;
458 }
459
461 {
467 unsigned guid_count = 0, i, j;
468 GUID device_guid = GUID_NULL;
469 D3DFORMAT target_format = 0;
470 DXVA2_VideoDesc desc = { 0 };
471 DXVA2_ConfigPictureDecode
config;
473 int surface_alignment;
475
476 hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->
decoder_service, &guid_count, &guid_list);
478 av_log(
NULL, loglevel,
"Failed to retrieve decoder device GUIDs\n");
479 goto fail;
480 }
481
482 for (i = 0; dxva2_modes[i].
guid; i++) {
483 D3DFORMAT *target_list =
NULL;
484 unsigned target_count = 0;
487 continue;
488
489 for (j = 0; j < guid_count; j++) {
490 if (IsEqualGUID(mode->
guid, &guid_list[j]))
491 break;
492 }
493 if (j == guid_count)
494 continue;
495
496 hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(ctx->
decoder_service, mode->
guid, &target_count, &target_list);
498 continue;
499 }
500 for (j = 0; j < target_count; j++) {
501 const D3DFORMAT format = target_list[j];
502 if (format ==
MKTAG(
'N',
'V',
'1',
'2')) {
503 target_format = format;
504 break;
505 }
506 }
507 CoTaskMemFree(target_list);
508 if (target_format) {
509 device_guid = *mode->
guid;
510 break;
511 }
512 }
513 CoTaskMemFree(guid_list);
514
515 if (IsEqualGUID(&device_guid, &GUID_NULL)) {
516 av_log(
NULL, loglevel,
"No decoder device for codec found\n");
517 goto fail;
518 }
519
522 desc.Format = target_format;
523
525 if (ret < 0) {
526 goto fail;
527 }
528
529 /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
530 but it causes issues for H.264 on certain AMD GPUs..... */
532 surface_alignment = 32;
533 /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
534 all coding features have enough room to work with */
536 surface_alignment = 128;
537 else
538 surface_alignment = 16;
539
540 /* 4 base work surfaces */
542
543 /* add surfaces based on number of possible refs */
546 else
548
549 /* add extra surfaces for frame threading */
552
555
557 av_log(
NULL, loglevel,
"Unable to allocate surface arrays\n");
558 goto fail;
559 }
560
565 target_format, D3DPOOL_DEFAULT, 0,
566 DXVA2_VideoDecoderRenderTarget,
570 goto fail;
571 }
572
573 hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->
decoder_service, &device_guid,
577 av_log(
NULL, loglevel,
"Failed to create DXVA2 video decoder\n");
578 goto fail;
579 }
580
583
588
589 if (IsEqualGUID(&ctx->
decoder_guid, &DXVADDI_Intel_ModeH264_E))
591
592 return 0;
593 fail:
596 }
597
599 {
604
607 if (ret < 0)
609 }
611
614 av_log(
NULL, loglevel,
"Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->
profile);
616 }
617
620
622 if (ret < 0) {
623 av_log(
NULL, loglevel,
"Error creating the DXVA2 decoder\n");
625 }
626
627 return 0;
628 }