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