1 /*
2 * DXVA2 HW acceleration.
3 *
4 * copyright (c) 2010 Laurent Aimar
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <string.h>
24 #include <initguid.h>
25
31
35
36 /* define all the GUIDs used directly here,
37 to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
38 DEFINE_GUID(ff_DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);
39 DEFINE_GUID(ff_DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
40 DEFINE_GUID(ff_DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
41 DEFINE_GUID(ff_DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
42 DEFINE_GUID(ff_DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
43 DEFINE_GUID(ff_DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
44 DEFINE_GUID(ff_DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
45 DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
46 DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13);
47 DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x83,0xaa,0x6d,0x60,0xb8,0x9e);
48 DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_10bit_Profile2,0xa4c749ef,0x6ecf,0x48aa,0x84,0x48,0x50,0xa7,0xa1,0x16,0x5f,0xf7);
49 DEFINE_GUID(ff_DXVA2_ModeAV1_VLD_Profile0,0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0xb8,0xa6,0xda,0x5d,0x2a);
50 DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
51 DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
52 DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
53
57 // List of supported profiles, terminated by a AV_PROFILE_UNKNOWN entry.
58 // If NULL, don't check profile.
61
79
81 /* MPEG-2 */
84
85 /* H.264 */
88 /* Intel specific H.264 mode */
90
91 /* VC-1 / WMV3 */
96
97 /* HEVC/H.265 */
100
101 /* VP8/9 */
104
105 /* AV1 */
107
109 };
110
112 const void *cfg_list,
113 unsigned cfg_count)
114 {
116 unsigned i, best_score = 0;
117 int best_cfg = -1;
118
119 for (
i = 0;
i < cfg_count;
i++) {
120 unsigned score;
121 UINT ConfigBitstreamRaw = 0;
122 GUID guidConfigBitstreamEncryption;
123
124 #if CONFIG_D3D11VA
126 D3D11_VIDEO_DECODER_CONFIG *cfg = &((D3D11_VIDEO_DECODER_CONFIG *)cfg_list)[
i];
127 ConfigBitstreamRaw = cfg->ConfigBitstreamRaw;
128 guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption;
129 }
130 #endif
131 #if CONFIG_DXVA2
133 DXVA2_ConfigPictureDecode *cfg = &((DXVA2_ConfigPictureDecode *)cfg_list)[
i];
134 ConfigBitstreamRaw = cfg->ConfigBitstreamRaw;
135 guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption;
136 }
137 #endif
138
139 if (ConfigBitstreamRaw == 1)
140 score = 1;
142 score = 2;
143 else
144 continue;
145 if (IsEqualGUID(&guidConfigBitstreamEncryption, &ff_DXVA2_NoEncrypt))
146 score += 16;
147 if (score > best_score) {
148 best_score = score;
150 }
151 }
152
153 if (!best_score) {
156 }
157
158 return best_cfg;
159 }
160
161 #if CONFIG_D3D11VA
162 static int d3d11va_validate_output(void *service, GUID guid, const void *surface_format)
163 {
164 HRESULT hr;
166 hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice *)service,
167 &guid,
168 *(DXGI_FORMAT *)surface_format,
171 }
172 #endif
173
174 #if CONFIG_DXVA2
175 static int dxva2_validate_output(void *decoder_service, GUID guid, const void *surface_format)
176 {
177 HRESULT hr;
179 unsigned j, target_count;
180 D3DFORMAT *target_list;
181 hr = IDirectXVideoDecoderService_GetDecoderRenderTargets((IDirectXVideoDecoderService *)decoder_service, &guid, &target_count, &target_list);
182 if (SUCCEEDED(hr)) {
183 for (j = 0; j < target_count; j++) {
184 const D3DFORMAT
format = target_list[j];
185 if (
format == *(D3DFORMAT *)surface_format) {
187 break;
188 }
189 }
190 CoTaskMemFree(target_list);
191 }
193 }
194 #endif
195
197 {
199 return 0;
200
205 found = 1;
206 break;
207 }
208 }
209 if (!found)
210 return 0;
211 }
212
213 return 1;
214 }
215
217 unsigned guid_count, const GUID *guid_list)
218 {
221
223
224 for (
i = 0;
i < guid_count;
i++) {
225 const GUID *guid = &guid_list[
i];
226
228 "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
229 (unsigned) guid->Data1, guid->Data2, guid->Data3,
230 guid->Data4[0], guid->Data4[1],
231 guid->Data4[2], guid->Data4[3],
232 guid->Data4[4], guid->Data4[5],
233 guid->Data4[6], guid->Data4[7]);
234
235 #if CONFIG_D3D11VA
238 // We don't know the maximum valid DXGI_FORMAT, so use 200 as
239 // arbitrary upper bound (that could become outdated).
241 if (d3d11va_validate_output(service, *guid, &
format))
243 }
244 }
245 #endif
246 #if CONFIG_DXVA2
249 MKTAG(
'P',
'0',
'1',
'0')};
252 if (dxva2_validate_output(service, *guid, &
formats[
i]))
254 }
255 }
256 #endif
258 }
259 }
260
262 unsigned guid_count, const GUID *guid_list, GUID *decoder_guid)
263 {
266
268
269 *decoder_guid = ff_GUID_NULL;
272 int validate = 0;
274 continue;
275
276 for (j = 0; j < guid_count; j++) {
277 if (IsEqualGUID(
mode->guid, &guid_list[j]))
278 break;
279 }
280 if (j == guid_count)
281 continue;
282
283 #if CONFIG_D3D11VA
285 validate = d3d11va_validate_output(service, *
mode->guid, surface_format);
286 #endif
287 #if CONFIG_DXVA2
289 validate = dxva2_validate_output(service, *
mode->guid, surface_format);
290 #endif
291 if (validate) {
292 *decoder_guid = *
mode->guid;
293 break;
294 }
295 }
296
297 if (IsEqualGUID(decoder_guid, &ff_GUID_NULL)) {
300 }
301
302 if (IsEqualGUID(decoder_guid, &ff_DXVADDI_Intel_ModeH264_E))
304
305 return 0;
306 }
307
309 {
310 IUnknown_Release((IUnknown *)opaque);
311 }
312
314 {
316 }
317
318 #if CONFIG_DXVA2
319
320 static int dxva2_get_decoder_configuration(
AVCodecContext *avctx,
const GUID *device_guid,
321 const DXVA2_VideoDesc *
desc,
322 DXVA2_ConfigPictureDecode *
config)
323 {
325 unsigned cfg_count;
326 DXVA2_ConfigPictureDecode *cfg_list;
327 HRESULT hr;
329
330 hr = IDirectXVideoDecoderService_GetDecoderConfigurations(sctx->dxva2_service, device_guid,
desc,
NULL, &cfg_count, &cfg_list);
331 if (FAILED(hr)) {
334 }
335
339 CoTaskMemFree(cfg_list);
341 }
342
344 {
346 GUID *guid_list;
347 unsigned guid_count;
348 GUID device_guid;
350 MKTAG(
'P',
'0',
'1',
'0') :
MKTAG(
'N',
'V',
'1',
'2');
351 DXVA2_VideoDesc
desc = { 0 };
352 DXVA2_ConfigPictureDecode
config;
353 HRESULT hr;
355 HANDLE device_handle;
359
360 hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
361 &device_handle);
362 if (FAILED(hr)) {
365 }
366
367 hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle,
368 &ff_IID_IDirectXVideoDecoderService,
369 (void **)&sctx->dxva2_service);
370 IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle);
371 if (FAILED(hr)) {
374 }
375
376 hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(sctx->dxva2_service, &guid_count, &guid_list);
377 if (FAILED(hr)) {
380 }
381
383 guid_count, guid_list, &device_guid);
384 CoTaskMemFree(guid_list);
387 }
388
391 desc.Format = surface_format;
392
393 ret = dxva2_get_decoder_configuration(avctx, &device_guid, &
desc, &
config);
396 }
397
398 hr = IDirectXVideoDecoderService_CreateVideoDecoder(sctx->dxva2_service, &device_guid,
400 frames_hwctx->nb_surfaces, &sctx->dxva2_decoder);
401 if (FAILED(hr)) {
404 }
405
406 sctx->dxva2_config =
config;
407
411
412 return 0;
415 }
416
417 #endif
418
419 #if CONFIG_D3D11VA
420
421 static int d3d11va_get_decoder_configuration(
AVCodecContext *avctx,
422 ID3D11VideoDevice *video_device,
423 const D3D11_VIDEO_DECODER_DESC *
desc,
424 D3D11_VIDEO_DECODER_CONFIG *
config)
425 {
426 unsigned cfg_count = 0;
427 D3D11_VIDEO_DECODER_CONFIG *cfg_list =
NULL;
428 HRESULT hr;
430
431 hr = ID3D11VideoDevice_GetVideoDecoderConfigCount(video_device,
desc, &cfg_count);
432 if (FAILED(hr)) {
435 }
436
437 cfg_list =
av_malloc_array(cfg_count,
sizeof(D3D11_VIDEO_DECODER_CONFIG));
438 if (cfg_list ==
NULL)
440 for (
i = 0;
i < cfg_count;
i++) {
441 hr = ID3D11VideoDevice_GetVideoDecoderConfig(video_device,
desc,
i, &cfg_list[
i]);
442 if (FAILED(hr)) {
443 av_log(avctx,
AV_LOG_ERROR,
"Unable to retrieve decoder configurations. (hr=0x%lX)\n", hr);
446 }
447 }
448
454 }
455
457 {
462 default: return DXGI_FORMAT_UNKNOWN;
463 }
464 }
465
467 {
469 GUID *guid_list;
470 unsigned guid_count,
i;
471 GUID decoder_guid;
472 D3D11_VIDEO_DECODER_DESC
desc = { 0 };
473 D3D11_VIDEO_DECODER_CONFIG
config;
477 DXGI_FORMAT surface_format = d3d11va_map_sw_to_hw_format(frames_ctx->
sw_format);
478 D3D11_TEXTURE2D_DESC texdesc;
479 HRESULT hr;
481
482 if (!frames_hwctx->texture) {
485 }
486 ID3D11Texture2D_GetDesc(frames_hwctx->texture, &texdesc);
487
488 guid_count = ID3D11VideoDevice_GetVideoDecoderProfileCount(device_hwctx->video_device);
490 if (guid_list ==
NULL || guid_count == 0) {
494 }
495 for (
i = 0;
i < guid_count;
i++) {
496 hr = ID3D11VideoDevice_GetVideoDecoderProfile(device_hwctx->video_device,
i, &guid_list[
i]);
497 if (FAILED(hr)) {
501 }
502 }
503
505 guid_count, guid_list, &decoder_guid);
509
512 desc.OutputFormat = surface_format;
513 desc.Guid = decoder_guid;
514
515 ret = d3d11va_get_decoder_configuration(avctx, device_hwctx->video_device, &
desc, &
config);
518
519 sctx->d3d11_views =
av_calloc(texdesc.ArraySize,
sizeof(sctx->d3d11_views[0]));
520 if (!sctx->d3d11_views)
522 sctx->nb_d3d11_views = texdesc.ArraySize;
523
524 for (
i = 0;
i < sctx->nb_d3d11_views;
i++) {
525 D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc = {
526 .DecodeProfile = decoder_guid,
527 .ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D,
528 .Texture2D = {
530 }
531 };
532 hr = ID3D11VideoDevice_CreateVideoDecoderOutputView(device_hwctx->video_device,
533 (ID3D11Resource*) frames_hwctx->texture,
534 &viewDesc,
535 (ID3D11VideoDecoderOutputView**) &sctx->d3d11_views[
i]);
536 if (FAILED(hr)) {
539 }
540 }
541
542 hr = ID3D11VideoDevice_CreateVideoDecoder(device_hwctx->video_device, &
desc,
543 &
config, &sctx->d3d11_decoder);
544 if (FAILED(hr)) {
547 }
548
549 sctx->d3d11_config =
config;
550 sctx->d3d11_texture = frames_hwctx->texture;
551
555
556 return 0;
557 }
558
559 #endif
560
562 {
563 #if CONFIG_D3D11VA
572 }
573 }
574 #endif
575 }
576
578 {
579 #if CONFIG_D3D11VA
588 }
589 }
590 #endif
591 }
592
595 {
598 int surface_alignment, num_surfaces;
599
604 } else {
606 }
607
608 /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
609 but it causes issues for H.264 on certain AMD GPUs..... */
611 surface_alignment = 32;
612 /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
613 all coding features have enough room to work with */
615 surface_alignment = 128;
616 else
617 surface_alignment = 16;
618
619 /* 1 base work surface */
620 num_surfaces = 1;
621
622 /* add surfaces based on number of possible refs */
624 num_surfaces += 16;
626 num_surfaces += 8;
627 else
628 num_surfaces += 2;
629
635
636
637 #if CONFIG_DXVA2
640
641 frames_hwctx->
surface_type = DXVA2_VideoDecoderRenderTarget;
642 }
643 #endif
644
645 #if CONFIG_D3D11VA
648
649 frames_hwctx->
BindFlags |= D3D11_BIND_DECODER;
650 }
651 #endif
652
653 return 0;
654 }
655
657 {
663
664 // Old API.
666 return 0;
667
668 // (avctx->pix_fmt is not updated yet at this point)
670
674
677
682 }
683
684 #if CONFIG_D3D11VA
688
690 ret = d3d11va_create_decoder(avctx);
694
695 d3d11_ctx->
decoder = sctx->d3d11_decoder;
697 d3d11_ctx->
cfg = &sctx->d3d11_config;
699 d3d11_ctx->
surface = sctx->d3d11_views;
702 }
703 #endif
704
705 #if CONFIG_DXVA2
709
711 ret = dxva2_create_decoder(avctx);
715
716 dxva_ctx->
decoder = sctx->dxva2_decoder;
717 dxva_ctx->
cfg = &sctx->dxva2_config;
721 }
722 #endif
723
724 return 0;
725
729 }
730
732 {
735
737
738 #if CONFIG_D3D11VA
739 for (
i = 0;
i < sctx->nb_d3d11_views;
i++) {
740 if (sctx->d3d11_views[
i])
741 ID3D11VideoDecoderOutputView_Release(sctx->d3d11_views[
i]);
742 }
744 #endif
745
746 #if CONFIG_DXVA2
747 if (sctx->dxva2_service)
748 IDirectXVideoDecoderService_Release(sctx->dxva2_service);
749 #endif
750
751 return 0;
752 }
753
755 {
756 #if CONFIG_D3D11VA
760 if (index < 0 || index >= sctx->nb_d3d11_views ||
761 sctx->d3d11_texture != (ID3D11Texture2D *)
frame->data[0]) {
764 }
765 return sctx->d3d11_views[
index];
766 }
767 #endif
768 return frame->data[3];
769 }
770
773 int curr)
774 {
777
778 #if CONFIG_D3D12VA
781 }
782 #endif
783 #if CONFIG_D3D11VA
785 return (intptr_t)
frame->data[1];
787 D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
788 ID3D11VideoDecoderOutputView_GetDesc((ID3D11VideoDecoderOutputView*)
surface, &viewDesc);
789 return viewDesc.Texture2D.ArraySlice;
790 }
791 #endif
792 #if CONFIG_DXVA2
796 }
797 #endif
798
800 return 0;
801 }
802
807 unsigned mb_count)
808 {
809 void *dxva_data =
NULL;
810 unsigned dxva_size;
812 HRESULT hr = 0;
813
814 #if CONFIG_D3D11VA
819 &dxva_size, &dxva_data);
820 #endif
821 #if CONFIG_DXVA2
824 &dxva_data, &dxva_size);
825 #endif
826 if (FAILED(hr)) {
829 return -1;
830 }
831 if (dxva_data &&
size <= dxva_size) {
833
834 #if CONFIG_D3D11VA
836 D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc;
837 memset(dsc11, 0, sizeof(*dsc11));
838 dsc11->BufferType =
type;
839 dsc11->DataSize =
size;
840 dsc11->NumMBsInBuffer = mb_count;
841 }
842 #endif
843 #if CONFIG_DXVA2
845 DXVA2_DecodeBufferDesc *dsc2 = dsc;
846 memset(dsc2, 0, sizeof(*dsc2));
847 dsc2->CompressedBufferType =
type;
848 dsc2->DataSize =
size;
849 dsc2->NumMBsInBuffer = mb_count;
850 }
851 #endif
852
854 } else {
857 }
858
859 #if CONFIG_D3D11VA
862 #endif
863 #if CONFIG_DXVA2
866 #endif
867 if (FAILED(hr)) {
869 "Failed to release buffer type %u: 0x%x\n",
872 }
874 }
875
877 {
879
884 }
885 }
886
887 // For now we expect that the caller does not use more than
888 // AV_NUM_DATA_POINTERS-1 buffers if the user uses a custom pool.
890 }
891
893 const void *pp, unsigned pp_size,
894 const void *qm, unsigned qm_size,
898 {
900 unsigned buffer_count = 0;
901 #if CONFIG_D3D11VA
902 D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4];
903 #endif
904 #if CONFIG_DXVA2
905 DXVA2_DecodeBufferDesc buffer2[4];
906 #endif
909 HRESULT hr = -1;
912
917 }
918
919 do {
921 #if CONFIG_D3D11VA
926 #endif
927 #if CONFIG_DXVA2
932 #endif
933 if (hr != E_PENDING || ++runs > 50)
934 break;
937 } while(1);
938
939 if (FAILED(hr)) {
942 return -1;
943 }
944
945 #if CONFIG_D3D11VA
947 buffer = &buffer11[buffer_count];
948 type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
949 }
950 #endif
951 #if CONFIG_DXVA2
953 buffer = &buffer2[buffer_count];
954 type = DXVA2_PictureParametersBufferType;
955 }
956 #endif
959 pp, pp_size, 0);
962 "Failed to add picture parameter buffer\n");
963 goto end;
964 }
965 buffer_count++;
966
967 if (qm_size > 0) {
968 #if CONFIG_D3D11VA
970 buffer = &buffer11[buffer_count];
971 type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX;
972 }
973 #endif
974 #if CONFIG_DXVA2
976 buffer = &buffer2[buffer_count];
977 type = DXVA2_InverseQuantizationMatrixBufferType;
978 }
979 #endif
982 qm, qm_size, 0);
985 "Failed to add inverse quantization matrix buffer\n");
986 goto end;
987 }
988 buffer_count++;
989 }
990
991 #if CONFIG_D3D11VA
993 buffer = &buffer11[buffer_count + 0];
994 buffer_slice = &buffer11[buffer_count + 1];
995 }
996 #endif
997 #if CONFIG_DXVA2
999 buffer = &buffer2[buffer_count + 0];
1000 buffer_slice = &buffer2[buffer_count + 1];
1001 }
1002 #endif
1003
1004 result = commit_bs_si(avctx,
1006 buffer_slice);
1009 "Failed to add bitstream or slice control buffer\n");
1010 goto end;
1011 }
1012 buffer_count += 2;
1013
1014 /* TODO Film Grain when possible */
1015
1016 av_assert0(buffer_count == 1 + (qm_size > 0) + 2);
1017
1018 #if CONFIG_D3D11VA
1022 buffer_count, buffer11);
1023 #endif
1024 #if CONFIG_DXVA2
1026 DXVA2_DecodeExecuteParams exec = {
1027 .NumCompBuffers = buffer_count,
1028 .pCompressedBuffers = buffer2,
1029 .pExtensionData =
NULL,
1030 };
1032 }
1033 #endif
1034 if (FAILED(hr)) {
1037 }
1038
1039 end:
1040 #if CONFIG_D3D11VA
1043 #endif
1044 #if CONFIG_DXVA2
1047 #endif
1049 if (FAILED(hr)) {
1052 }
1053
1055 }
1056
1058 {
1059 if (CONFIG_D3D11VA)
1062 else
1063 return 0;
1064 }
1065
1067 {
1069
1070 #if CONFIG_D3D12VA
1073 #endif
1074 #if CONFIG_D3D11VA
1077 #endif
1078 #if CONFIG_DXVA2
1081 #endif
1082
1084 }