dxva: add support for new dxva2 and d3d11 hwaccel APIs
[ffmpeg.git] / libavcodec / dxva2.c
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 <assert.h>
24 #include <string.h>
25 #include <initguid.h>
26
27 #include "libavutil/common.h"
28 #include "libavutil/log.h"
29 #include "libavutil/time.h"
30
31 #include "avcodec.h"
32 #include "dxva2_internal.h"
33
34 /* define all the GUIDs used directly here,
35  to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
36 DEFINE_GUID(ff_DXVA2_ModeMPEG2_VLD,      0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);
37 DEFINE_GUID(ff_DXVA2_ModeMPEG2and1_VLD,  0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
38 DEFINE_GUID(ff_DXVA2_ModeH264_E,         0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
39 DEFINE_GUID(ff_DXVA2_ModeH264_F,         0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
40 DEFINE_GUID(ff_DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
41 DEFINE_GUID(ff_DXVA2_ModeVC1_D,          0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
42 DEFINE_GUID(ff_DXVA2_ModeVC1_D2010,      0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
43 DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main,  0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
44 DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13);
45 DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x83,0xaa,0x6d,0x60,0xb8,0x9e);
46 DEFINE_GUID(ff_DXVA2_NoEncrypt,          0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
47 DEFINE_GUID(ff_GUID_NULL,                0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
48 DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
49
50 typedef struct dxva_mode {
51     const GUID     *guid;
52     enum AVCodecID codec;
53 } dxva_mode;
54
55 static const dxva_mode dxva_modes[] = {
56     /* MPEG-2 */
57     { &ff_DXVA2_ModeMPEG2_VLD,       AV_CODEC_ID_MPEG2VIDEO },
58     { &ff_DXVA2_ModeMPEG2and1_VLD,   AV_CODEC_ID_MPEG2VIDEO },
59
60     /* H.264 */
61     { &ff_DXVA2_ModeH264_F,          AV_CODEC_ID_H264 },
62     { &ff_DXVA2_ModeH264_E,          AV_CODEC_ID_H264 },
63     /* Intel specific H.264 mode */
64     { &ff_DXVADDI_Intel_ModeH264_E,  AV_CODEC_ID_H264 },
65
66     /* VC-1 / WMV3 */
67     { &ff_DXVA2_ModeVC1_D2010,       AV_CODEC_ID_VC1 },
68     { &ff_DXVA2_ModeVC1_D2010,       AV_CODEC_ID_WMV3 },
69     { &ff_DXVA2_ModeVC1_D,           AV_CODEC_ID_VC1 },
70     { &ff_DXVA2_ModeVC1_D,           AV_CODEC_ID_WMV3 },
71
72     /* HEVC/H.265 */
73     { &ff_DXVA2_ModeHEVC_VLD_Main,   AV_CODEC_ID_HEVC },
74     { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC },
75
76     /* VP8/9 */
77     { &ff_DXVA2_ModeVP9_VLD_Profile0,AV_CODEC_ID_VP9 },
78
79     { NULL,                          0 },
80 };
81
82 static int dxva_get_decoder_configuration(AVCodecContext *avctx,
83                                           const void *cfg_list,
84                                           unsigned cfg_count)
85 {
86     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
87     unsigned i, best_score = 0;
88     int best_cfg = -1;
89
90     for (i = 0; i < cfg_count; i++) {
91         unsigned score;
92         UINT ConfigBitstreamRaw;
93         GUID guidConfigBitstreamEncryption;
94
95 #if CONFIG_D3D11VA
96         if (sctx->pix_fmt == AV_PIX_FMT_D3D11) {
97             D3D11_VIDEO_DECODER_CONFIG *cfg = &((D3D11_VIDEO_DECODER_CONFIG *)cfg_list)[i];
98             ConfigBitstreamRaw = cfg->ConfigBitstreamRaw;
99             guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption;
100         }
101 #endif
102 #if CONFIG_DXVA2
103         if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
104             DXVA2_ConfigPictureDecode *cfg = &((DXVA2_ConfigPictureDecode *)cfg_list)[i];
105             ConfigBitstreamRaw = cfg->ConfigBitstreamRaw;
106             guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption;
107         }
108 #endif
109
110         if (ConfigBitstreamRaw == 1)
111             score = 1;
112         else if (avctx->codec_id == AV_CODEC_ID_H264 && ConfigBitstreamRaw == 2)
113             score = 2;
114         else
115             continue;
116         if (IsEqualGUID(&guidConfigBitstreamEncryption, &ff_DXVA2_NoEncrypt))
117             score += 16;
118         if (score > best_score) {
119             best_score = score;
120             best_cfg = i;
121         }
122     }
123
124     if (!best_score) {
125         av_log(avctx, AV_LOG_VERBOSE, "No valid decoder configuration available\n");
126         return AVERROR(EINVAL);
127     }
128
129     return best_cfg;
130 }
131
132 #if CONFIG_D3D11VA
133 static int d3d11va_validate_output(void *service, GUID guid, const void *surface_format)
134 {
135     HRESULT hr;
136     BOOL is_supported = FALSE;
137     hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice *)service,
138                                                    &guid,
139                                                    *(DXGI_FORMAT *)surface_format,
140                                                    &is_supported);
141     return SUCCEEDED(hr) && is_supported;
142 }
143 #endif
144
145 #if CONFIG_DXVA2
146 static int dxva2_validate_output(void *decoder_service, GUID guid, const void *surface_format)
147 {
148     HRESULT hr;
149     int ret = 0;
150     unsigned j, target_count;
151     D3DFORMAT *target_list;
152     hr = IDirectXVideoDecoderService_GetDecoderRenderTargets((IDirectXVideoDecoderService *)decoder_service, &guid, &target_count, &target_list);
153     if (SUCCEEDED(hr)) {
154         for (j = 0; j < target_count; j++) {
155             const D3DFORMAT format = target_list[j];
156             if (format == *(D3DFORMAT *)surface_format) {
157                 ret = 1;
158                 break;
159             }
160         }
161         CoTaskMemFree(target_list);
162     }
163     return ret;
164 }
165 #endif
166
167 static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format,
168                                  unsigned guid_count, const GUID *guid_list, GUID *decoder_guid)
169 {
170     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
171     unsigned i, j;
172
173     *decoder_guid = ff_GUID_NULL;
174     for (i = 0; dxva_modes[i].guid; i++) {
175         const dxva_mode *mode = &dxva_modes[i];
176         int validate;
177         if (mode->codec != avctx->codec_id)
178             continue;
179
180         for (j = 0; j < guid_count; j++) {
181             if (IsEqualGUID(mode->guid, &guid_list[j]))
182                 break;
183         }
184         if (j == guid_count)
185             continue;
186
187 #if CONFIG_D3D11VA
188         if (sctx->pix_fmt == AV_PIX_FMT_D3D11)
189             validate = d3d11va_validate_output(service, *mode->guid, surface_format);
190 #endif
191 #if CONFIG_DXVA2
192         if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
193             validate = dxva2_validate_output(service, *mode->guid, surface_format);
194 #endif
195         if (validate) {
196             *decoder_guid = *mode->guid;
197             break;
198         }
199     }
200
201     if (IsEqualGUID(decoder_guid, &ff_GUID_NULL)) {
202         av_log(avctx, AV_LOG_VERBOSE, "No decoder device for codec found\n");
203         return AVERROR(EINVAL);
204     }
205
206     if (IsEqualGUID(decoder_guid, &ff_DXVADDI_Intel_ModeH264_E))
207         sctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
208
209     return 0;
210 }
211
212 static void bufref_free_interface(void *opaque, uint8_t *data)
213 {
214     IUnknown_Release((IUnknown *)opaque);
215 }
216
217 static AVBufferRef *bufref_wrap_interface(IUnknown *iface)
218 {
219     return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0);
220 }
221
222 #if CONFIG_DXVA2
223
224 static int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *device_guid,
225                                            const DXVA2_VideoDesc *desc,
226                                            DXVA2_ConfigPictureDecode *config)
227 {
228     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
229     unsigned cfg_count;
230     DXVA2_ConfigPictureDecode *cfg_list;
231     HRESULT hr;
232     int ret;
233
234     hr = IDirectXVideoDecoderService_GetDecoderConfigurations(sctx->dxva2_service, device_guid, desc, NULL, &cfg_count, &cfg_list);
235     if (FAILED(hr)) {
236         av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n");
237         return AVERROR(EINVAL);
238     }
239
240     ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count);
241     if (ret >= 0)
242         *config = cfg_list[ret];
243     CoTaskMemFree(cfg_list);
244     return ret;
245 }
246
247 static int dxva2_create_decoder(AVCodecContext *avctx)
248 {
249     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
250     GUID *guid_list;
251     unsigned guid_count;
252     GUID device_guid;
253     D3DFORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
254                                MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2');
255     DXVA2_VideoDesc desc = { 0 };
256     DXVA2_ConfigPictureDecode config;
257     HRESULT hr;
258     int ret;
259     HANDLE device_handle;
260     AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
261     AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
262     AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
263
264     hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
265                                                   &device_handle);
266     if (FAILED(hr)) {
267         av_log(avctx, AV_LOG_ERROR, "Failed to open a device handle\n");
268         goto fail;
269     }
270
271     hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle,
272                                                  &ff_IID_IDirectXVideoDecoderService,
273                                                  (void **)&sctx->dxva2_service);
274     IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle);
275     if (FAILED(hr)) {
276         av_log(avctx, AV_LOG_ERROR, "Failed to create IDirectXVideoDecoderService\n");
277         goto fail;
278     }
279
280     hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(sctx->dxva2_service, &guid_count, &guid_list);
281     if (FAILED(hr)) {
282         av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder device GUIDs\n");
283         goto fail;
284     }
285
286     ret = dxva_get_decoder_guid(avctx, sctx->dxva2_service, &surface_format,
287                                 guid_count, guid_list, &device_guid);
288     CoTaskMemFree(guid_list);
289     if (ret < 0) {
290         goto fail;
291     }
292
293     desc.SampleWidth  = avctx->coded_width;
294     desc.SampleHeight = avctx->coded_height;
295     desc.Format       = surface_format;
296
297     ret = dxva2_get_decoder_configuration(avctx, &device_guid, &desc, &config);
298     if (ret < 0) {
299         goto fail;
300     }
301
302     hr = IDirectXVideoDecoderService_CreateVideoDecoder(sctx->dxva2_service, &device_guid,
303                                                         &desc, &config, frames_hwctx->surfaces,
304                                                         frames_hwctx->nb_surfaces, &sctx->dxva2_decoder);
305     if (FAILED(hr)) {
306         av_log(avctx, AV_LOG_ERROR, "Failed to create DXVA2 video decoder\n");
307         goto fail;
308     }
309
310     sctx->dxva2_config = config;
311
312     sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->dxva2_decoder);
313     if (!sctx->decoder_ref)
314         return AVERROR(ENOMEM);
315
316     return 0;
317 fail:
318     return AVERROR(EINVAL);
319 }
320
321 #endif
322
323 #if CONFIG_D3D11VA
324
325 static int d3d11va_get_decoder_configuration(AVCodecContext *avctx,
326                                              ID3D11VideoDevice *video_device,
327                                              const D3D11_VIDEO_DECODER_DESC *desc,
328                                              D3D11_VIDEO_DECODER_CONFIG *config)
329 {
330     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
331     unsigned cfg_count = 0;
332     D3D11_VIDEO_DECODER_CONFIG *cfg_list = NULL;
333     HRESULT hr;
334     int i, ret;
335
336     hr = ID3D11VideoDevice_GetVideoDecoderConfigCount(video_device, desc, &cfg_count);
337     if (FAILED(hr)) {
338         av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n");
339         return AVERROR(EINVAL);
340     }
341
342     cfg_list = av_malloc_array(cfg_count, sizeof(D3D11_VIDEO_DECODER_CONFIG));
343     if (cfg_list == NULL)
344         return AVERROR(ENOMEM);
345     for (i = 0; i < cfg_count; i++) {
346         hr = ID3D11VideoDevice_GetVideoDecoderConfig(video_device, desc, i, &cfg_list[i]);
347         if (FAILED(hr)) {
348             av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations. (hr=0x%lX)\n", hr);
349             av_free(cfg_list);
350             return AVERROR(EINVAL);
351         }
352     }
353
354     ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count);
355     if (ret >= 0)
356         *config = cfg_list[ret];
357     av_free(cfg_list);
358     return ret;
359 }
360
361 static int d3d11va_create_decoder(AVCodecContext *avctx)
362 {
363     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
364     GUID *guid_list;
365     unsigned guid_count, i;
366     GUID decoder_guid;
367     DXGI_FORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
368                                  DXGI_FORMAT_P010 : DXGI_FORMAT_NV12;
369     D3D11_VIDEO_DECODER_DESC desc = { 0 };
370     D3D11_VIDEO_DECODER_CONFIG config;
371     AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
372     AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
373     AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
374     D3D11_TEXTURE2D_DESC texdesc;
375     HRESULT hr;
376     int ret;
377
378     if (!frames_hwctx->texture) {
379         av_log(avctx, AV_LOG_ERROR, "AVD3D11VAFramesContext.texture not set.\n");
380         return AVERROR(EINVAL);
381     }
382     ID3D11Texture2D_GetDesc(frames_hwctx->texture, &texdesc);
383
384     guid_count = ID3D11VideoDevice_GetVideoDecoderProfileCount(device_hwctx->video_device);
385     guid_list = av_malloc_array(guid_count, sizeof(*guid_list));
386     if (guid_list == NULL || guid_count == 0) {
387         av_log(avctx, AV_LOG_ERROR, "Failed to get the decoder GUIDs\n");
388         av_free(guid_list);
389         return AVERROR(EINVAL);
390     }
391     for (i = 0; i < guid_count; i++) {
392         hr = ID3D11VideoDevice_GetVideoDecoderProfile(device_hwctx->video_device, i, &guid_list[i]);
393         if (FAILED(hr)) {
394             av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder GUID %d\n", i);
395             av_free(guid_list);
396             return AVERROR(EINVAL);
397         }
398     }
399
400     ret = dxva_get_decoder_guid(avctx, device_hwctx->video_device, &surface_format,
401                                 guid_count, guid_list, &decoder_guid);
402     av_free(guid_list);
403     if (ret < 0)
404         return AVERROR(EINVAL);
405
406     desc.SampleWidth  = avctx->coded_width;
407     desc.SampleHeight = avctx->coded_height;
408     desc.OutputFormat = surface_format;
409     desc.Guid         = decoder_guid;
410
411     ret = d3d11va_get_decoder_configuration(avctx, device_hwctx->video_device, &desc, &config);
412     if (ret < 0)
413         return AVERROR(EINVAL);
414
415     sctx->d3d11_views = av_mallocz_array(texdesc.ArraySize, sizeof(sctx->d3d11_views[0]));
416     if (!sctx->d3d11_views)
417         return AVERROR(ENOMEM);
418     sctx->nb_d3d11_views = texdesc.ArraySize;
419
420     for (i = 0; i < sctx->nb_d3d11_views; i++) {
421         D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc = {
422             .DecodeProfile = decoder_guid,
423             .ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D,
424             .Texture2D = {
425                 .ArraySlice = i,
426             }
427         };
428         hr = ID3D11VideoDevice_CreateVideoDecoderOutputView(device_hwctx->video_device,
429                                                             (ID3D11Resource*) frames_hwctx->texture,
430                                                             &viewDesc,
431                                                             (ID3D11VideoDecoderOutputView**) &sctx->d3d11_views[i]);
432         if (FAILED(hr)) {
433             av_log(avctx, AV_LOG_ERROR, "Could not create the decoder output view %d\n", i);
434             return AVERROR_UNKNOWN;
435         }
436     }
437
438     hr = ID3D11VideoDevice_CreateVideoDecoder(device_hwctx->video_device, &desc,
439                                               &config, &sctx->d3d11_decoder);
440     if (FAILED(hr)) {
441         av_log(avctx, AV_LOG_ERROR, "Failed to create D3D11VA video decoder\n");
442         return AVERROR(EINVAL);
443     }
444
445     sctx->d3d11_config = config;
446     sctx->d3d11_texture = frames_hwctx->texture;
447
448     sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->d3d11_decoder);
449     if (!sctx->decoder_ref)
450         return AVERROR(ENOMEM);
451
452     return 0;
453 }
454
455 #endif
456
457 static void ff_dxva2_lock(AVCodecContext *avctx)
458 {
459 #if CONFIG_D3D11VA
460     if (ff_dxva2_is_d3d11(avctx)) {
461         FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
462         AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
463         if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
464             WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE);
465         if (sctx->device_ctx) {
466             AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx;
467             hwctx->lock(hwctx->lock_ctx);
468         }
469     }
470 #endif
471 }
472
473 static void ff_dxva2_unlock(AVCodecContext *avctx)
474 {
475 #if CONFIG_D3D11VA
476     if (ff_dxva2_is_d3d11(avctx)) {
477         FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
478         AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
479         if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
480             ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
481         if (sctx->device_ctx) {
482             AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx;
483             hwctx->unlock(hwctx->lock_ctx);
484         }
485     }
486 #endif
487 }
488
489 // This must work before the decoder is created.
490 // This somehow needs to be exported to the user.
491 static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frames_ctx)
492 {
493     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
494     int surface_alignment, num_surfaces;
495
496     frames_ctx->format = sctx->pix_fmt;
497
498     /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
499     but it causes issues for H.264 on certain AMD GPUs..... */
500     if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO)
501         surface_alignment = 32;
502     /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
503     all coding features have enough room to work with */
504     else if (avctx->codec_id == AV_CODEC_ID_HEVC)
505         surface_alignment = 128;
506     else
507         surface_alignment = 16;
508
509     /* 4 base work surfaces */
510     num_surfaces = 4;
511
512     /* add surfaces based on number of possible refs */
513     if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC)
514         num_surfaces += 16;
515     else if (avctx->codec_id == AV_CODEC_ID_VP9)
516         num_surfaces += 8;
517     else
518         num_surfaces += 2;
519
520     /* add extra surfaces for frame threading */
521     if (avctx->active_thread_type & FF_THREAD_FRAME)
522         num_surfaces += avctx->thread_count;
523
524     frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
525                             AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
526     frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
527     frames_ctx->height = FFALIGN(avctx->coded_height, surface_alignment);
528     frames_ctx->initial_pool_size = num_surfaces;
529
530
531 #if CONFIG_DXVA2
532     if (frames_ctx->format == AV_PIX_FMT_DXVA2_VLD) {
533         AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
534
535         frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
536     }
537 #endif
538
539 #if CONFIG_D3D11VA
540     if (frames_ctx->format == AV_PIX_FMT_D3D11) {
541         AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
542
543         frames_hwctx->BindFlags |= D3D11_BIND_DECODER;
544     }
545 #endif
546 }
547
548 int ff_dxva2_decode_init(AVCodecContext *avctx)
549 {
550     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
551     AVHWFramesContext *frames_ctx = NULL;
552     int ret = 0;
553
554     // Old API.
555     if (avctx->hwaccel_context)
556         return 0;
557
558     // (avctx->pix_fmt is not updated yet at this point)
559     sctx->pix_fmt = avctx->hwaccel->pix_fmt;
560
561     if (avctx->codec_id == AV_CODEC_ID_H264 &&
562         (avctx->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) {
563         av_log(avctx, AV_LOG_VERBOSE, "Unsupported H.264 profile for DXVA HWAccel: %d\n",avctx->profile);
564         return AVERROR(ENOTSUP);
565     }
566
567     if (avctx->codec_id == AV_CODEC_ID_HEVC &&
568         avctx->profile != FF_PROFILE_HEVC_MAIN && avctx->profile != FF_PROFILE_HEVC_MAIN_10) {
569         av_log(avctx, AV_LOG_VERBOSE, "Unsupported HEVC profile for DXVA HWAccel: %d\n", avctx->profile);
570         return AVERROR(ENOTSUP);
571     }
572
573     if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) {
574         av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a hw_device_ctx needs to be set for hardware decoding.\n");
575         return AVERROR(EINVAL);
576     }
577
578     if (avctx->hw_frames_ctx) {
579         frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
580     } else {
581         avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
582         if (!avctx->hw_frames_ctx)
583             return AVERROR(ENOMEM);
584
585         frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
586
587         dxva_adjust_hwframes(avctx, frames_ctx);
588
589         ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
590         if (ret < 0)
591             goto fail;
592     }
593
594     sctx->device_ctx = frames_ctx->device_ctx;
595
596     if (frames_ctx->format != sctx->pix_fmt ||
597         !((sctx->pix_fmt == AV_PIX_FMT_D3D11 && CONFIG_D3D11VA) ||
598           (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && CONFIG_DXVA2))) {
599         av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n");
600         ret = AVERROR(EINVAL);
601         goto fail;
602     }
603
604 #if CONFIG_D3D11VA
605     if (sctx->pix_fmt == AV_PIX_FMT_D3D11) {
606         AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
607         AVD3D11VAContext *d3d11_ctx = &sctx->ctx.d3d11va;
608         HRESULT hr;
609
610         ff_dxva2_lock(avctx);
611         ret = d3d11va_create_decoder(avctx);
612         ff_dxva2_unlock(avctx);
613         if (ret < 0)
614             goto fail;
615
616         d3d11_ctx->decoder       = sctx->d3d11_decoder;
617         d3d11_ctx->video_context = device_hwctx->video_context;
618         d3d11_ctx->cfg           = &sctx->d3d11_config;
619         d3d11_ctx->surface_count = sctx->nb_d3d11_views;
620         d3d11_ctx->surface       = sctx->d3d11_views;
621         d3d11_ctx->workaround    = sctx->workaround;
622         d3d11_ctx->context_mutex = INVALID_HANDLE_VALUE;
623     }
624 #endif
625
626 #if CONFIG_DXVA2
627     if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
628         AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
629         struct dxva_context *dxva_ctx = &sctx->ctx.dxva2;
630
631         ff_dxva2_lock(avctx);
632         ret = dxva2_create_decoder(avctx);
633         ff_dxva2_unlock(avctx);
634         if (ret < 0)
635             goto fail;
636
637         dxva_ctx->decoder       = sctx->dxva2_decoder;
638         dxva_ctx->cfg           = &sctx->dxva2_config;
639         dxva_ctx->surface       = frames_hwctx->surfaces;
640         dxva_ctx->surface_count = frames_hwctx->nb_surfaces;
641         dxva_ctx->workaround    = sctx->workaround;
642     }
643 #endif
644
645     return 0;
646
647 fail:
648     ff_dxva2_decode_uninit(avctx);
649     return ret;
650 }
651
652 int ff_dxva2_decode_uninit(AVCodecContext *avctx)
653 {
654     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
655     int i;
656
657     av_buffer_unref(&sctx->decoder_ref);
658
659 #if CONFIG_D3D11VA
660     for (i = 0; i < sctx->nb_d3d11_views; i++) {
661         if (sctx->d3d11_views[i])
662             ID3D11VideoDecoderOutputView_Release(sctx->d3d11_views[i]);
663     }
664     av_freep(&sctx->d3d11_views);
665 #endif
666
667 #if CONFIG_DXVA2
668     if (sctx->dxva2_service)
669         IDirectXVideoDecoderService_Release(sctx->dxva2_service);
670 #endif
671
672     return 0;
673 }
674
675 static void *get_surface(AVCodecContext *avctx, const AVFrame *frame)
676 {
677 #if CONFIG_D3D11VA
678     if (frame->format == AV_PIX_FMT_D3D11) {
679         FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
680         intptr_t index = (intptr_t)frame->data[1];
681         if (index < 0 || index >= sctx->nb_d3d11_views ||
682             sctx->d3d11_texture != (ID3D11Texture2D *)frame->data[0]) {
683             av_log(avctx, AV_LOG_ERROR, "get_buffer frame is invalid!\n");
684             return NULL;
685         }
686         return sctx->d3d11_views[index];
687     }
688 #endif
689     return frame->data[3];
690 }
691
692 unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
693                                     const AVDXVAContext *ctx,
694                                     const AVFrame *frame)
695 {
696     void *surface = get_surface(avctx, frame);
697     unsigned i;
698
699 #if CONFIG_D3D11VA
700     if (avctx->pix_fmt == AV_PIX_FMT_D3D11)
701         return (intptr_t)frame->data[1];
702     if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
703         D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
704         ID3D11VideoDecoderOutputView_GetDesc((ID3D11VideoDecoderOutputView*) surface, &viewDesc);
705         return viewDesc.Texture2D.ArraySlice;
706     }
707 #endif
708 #if CONFIG_DXVA2
709     for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) {
710         if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface)
711             return i;
712     }
713 #endif
714
715     assert(0);
716     return 0;
717 }
718
719 int ff_dxva2_commit_buffer(AVCodecContext *avctx,
720                            AVDXVAContext *ctx,
721                            DECODER_BUFFER_DESC *dsc,
722                            unsigned type, const void *data, unsigned size,
723                            unsigned mb_count)
724 {
725     void     *dxva_data;
726     unsigned dxva_size;
727     int      result;
728     HRESULT hr = 0;
729
730 #if CONFIG_D3D11VA
731     if (ff_dxva2_is_d3d11(avctx))
732         hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
733                                                  D3D11VA_CONTEXT(ctx)->decoder,
734                                                  type,
735                                                  &dxva_size, &dxva_data);
736 #endif
737 #if CONFIG_DXVA2
738     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
739         hr = IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, type,
740                                             &dxva_data, &dxva_size);
741 #endif
742     if (FAILED(hr)) {
743         av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%x\n",
744                type, hr);
745         return -1;
746     }
747     if (size <= dxva_size) {
748         memcpy(dxva_data, data, size);
749
750 #if CONFIG_D3D11VA
751         if (ff_dxva2_is_d3d11(avctx)) {
752             D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc;
753             memset(dsc11, 0, sizeof(*dsc11));
754             dsc11->BufferType           = type;
755             dsc11->DataSize             = size;
756             dsc11->NumMBsInBuffer       = mb_count;
757         }
758 #endif
759 #if CONFIG_DXVA2
760         if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
761             DXVA2_DecodeBufferDesc *dsc2 = dsc;
762             memset(dsc2, 0, sizeof(*dsc2));
763             dsc2->CompressedBufferType = type;
764             dsc2->DataSize             = size;
765             dsc2->NumMBsInBuffer       = mb_count;
766         }
767 #endif
768
769         result = 0;
770     } else {
771         av_log(avctx, AV_LOG_ERROR, "Buffer for type %u was too small\n", type);
772         result = -1;
773     }
774
775 #if CONFIG_D3D11VA
776     if (ff_dxva2_is_d3d11(avctx))
777         hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type);
778 #endif
779 #if CONFIG_DXVA2
780     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
781         hr = IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type);
782 #endif
783     if (FAILED(hr)) {
784         av_log(avctx, AV_LOG_ERROR,
785                "Failed to release buffer type %u: 0x%x\n",
786                type, hr);
787         result = -1;
788     }
789     return result;
790 }
791
792 static int frame_add_buf(AVFrame *frame, AVBufferRef *ref)
793 {
794     int i;
795
796     for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
797         if (!frame->buf[i]) {
798             frame->buf[i] = av_buffer_ref(ref);
799             return frame->buf[i] ? 0 : AVERROR(ENOMEM);
800         }
801     }
802
803     // For now we expect that the caller does not use more than
804     // AV_NUM_DATA_POINTERS-1 buffers if the user uses a custom pool.
805     return AVERROR(EINVAL);
806 }
807
808 int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
809                               const void *pp, unsigned pp_size,
810                               const void *qm, unsigned qm_size,
811                               int (*commit_bs_si)(AVCodecContext *,
812                                                   DECODER_BUFFER_DESC *bs,
813                                                   DECODER_BUFFER_DESC *slice))
814 {
815     AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
816     unsigned               buffer_count = 0;
817 #if CONFIG_D3D11VA
818     D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4];
819 #endif
820 #if CONFIG_DXVA2
821     DXVA2_DecodeBufferDesc          buffer2[4];
822 #endif
823     DECODER_BUFFER_DESC             *buffer = NULL, *buffer_slice = NULL;
824     int result, runs = 0;
825     HRESULT hr;
826     unsigned type;
827     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
828
829     if (sctx->decoder_ref) {
830         result = frame_add_buf(frame, sctx->decoder_ref);
831         if (result < 0)
832             return result;
833     }
834
835     do {
836         ff_dxva2_lock(avctx);
837 #if CONFIG_D3D11VA
838         if (ff_dxva2_is_d3d11(avctx))
839             hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder,
840                                                       get_surface(avctx, frame),
841                                                       0, NULL);
842 #endif
843 #if CONFIG_DXVA2
844         if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
845             hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder,
846                                                  get_surface(avctx, frame),
847                                                  NULL);
848 #endif
849         if (hr != E_PENDING || ++runs > 50)
850             break;
851         ff_dxva2_unlock(avctx);
852         av_usleep(2000);
853     } while(1);
854
855     if (FAILED(hr)) {
856         av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%x\n", hr);
857         ff_dxva2_unlock(avctx);
858         return -1;
859     }
860
861 #if CONFIG_D3D11VA
862     if (ff_dxva2_is_d3d11(avctx)) {
863         buffer = &buffer11[buffer_count];
864         type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
865     }
866 #endif
867 #if CONFIG_DXVA2
868     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
869         buffer = &buffer2[buffer_count];
870         type = DXVA2_PictureParametersBufferType;
871     }
872 #endif
873     result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
874                                     type,
875                                     pp, pp_size, 0);
876     if (result) {
877         av_log(avctx, AV_LOG_ERROR,
878                "Failed to add picture parameter buffer\n");
879         goto end;
880     }
881     buffer_count++;
882
883     if (qm_size > 0) {
884 #if CONFIG_D3D11VA
885         if (ff_dxva2_is_d3d11(avctx)) {
886             buffer = &buffer11[buffer_count];
887             type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX;
888         }
889 #endif
890 #if CONFIG_DXVA2
891         if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
892             buffer = &buffer2[buffer_count];
893             type = DXVA2_InverseQuantizationMatrixBufferType;
894         }
895 #endif
896         result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
897                                         type,
898                                         qm, qm_size, 0);
899         if (result) {
900             av_log(avctx, AV_LOG_ERROR,
901                    "Failed to add inverse quantization matrix buffer\n");
902             goto end;
903         }
904         buffer_count++;
905     }
906
907 #if CONFIG_D3D11VA
908     if (ff_dxva2_is_d3d11(avctx)) {
909         buffer       = &buffer11[buffer_count + 0];
910         buffer_slice = &buffer11[buffer_count + 1];
911     }
912 #endif
913 #if CONFIG_DXVA2
914     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
915         buffer       = &buffer2[buffer_count + 0];
916         buffer_slice = &buffer2[buffer_count + 1];
917     }
918 #endif
919
920     result = commit_bs_si(avctx,
921                           buffer,
922                           buffer_slice);
923     if (result) {
924         av_log(avctx, AV_LOG_ERROR,
925                "Failed to add bitstream or slice control buffer\n");
926         goto end;
927     }
928     buffer_count += 2;
929
930     /* TODO Film Grain when possible */
931
932     assert(buffer_count == 1 + (qm_size > 0) + 2);
933
934 #if CONFIG_D3D11VA
935     if (ff_dxva2_is_d3d11(avctx))
936         hr = ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context,
937                                                      D3D11VA_CONTEXT(ctx)->decoder,
938                                                      buffer_count, buffer11);
939 #endif
940 #if CONFIG_DXVA2
941     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
942         DXVA2_DecodeExecuteParams exec = {
943             .NumCompBuffers     = buffer_count,
944             .pCompressedBuffers = buffer2,
945             .pExtensionData     = NULL,
946         };
947         hr = IDirectXVideoDecoder_Execute(DXVA2_CONTEXT(ctx)->decoder, &exec);
948     }
949 #endif
950     if (FAILED(hr)) {
951         av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%x\n", hr);
952         result = -1;
953     }
954
955 end:
956 #if CONFIG_D3D11VA
957     if (ff_dxva2_is_d3d11(avctx))
958         hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder);
959 #endif
960 #if CONFIG_DXVA2
961     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
962         hr = IDirectXVideoDecoder_EndFrame(DXVA2_CONTEXT(ctx)->decoder, NULL);
963 #endif
964     ff_dxva2_unlock(avctx);
965     if (FAILED(hr)) {
966         av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%x\n", hr);
967         result = -1;
968     }
969
970     return result;
971 }
972
973 int ff_dxva2_is_d3d11(const AVCodecContext *avctx)
974 {
975     if (CONFIG_D3D11VA)
976         return avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ||
977                avctx->pix_fmt == AV_PIX_FMT_D3D11;
978     else
979         return 0;
980 }