OSDN Git Service

Merge commit 'b651c9139e1ab222d5aab9151dcd7d6e40e49885'
[android-x86/external-ffmpeg.git] / ffmpeg_dxva2.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <windows.h>
20
21 #ifdef _WIN32_WINNT
22 #undef _WIN32_WINNT
23 #endif
24 #define _WIN32_WINNT 0x0600
25 #define DXVA2API_USE_BITFIELDS
26 #define COBJMACROS
27
28 #include <stdint.h>
29
30 #include <d3d9.h>
31 #include <dxva2api.h>
32
33 #include "ffmpeg.h"
34
35 #include "libavcodec/dxva2.h"
36
37 #include "libavutil/avassert.h"
38 #include "libavutil/buffer.h"
39 #include "libavutil/frame.h"
40 #include "libavutil/imgutils.h"
41 #include "libavutil/pixfmt.h"
42
43 /* define all the GUIDs used directly here,
44    to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
45 #include <initguid.h>
46 DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
47
48 DEFINE_GUID(DXVA2_ModeMPEG2_VLD,      0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);
49 DEFINE_GUID(DXVA2_ModeMPEG2and1_VLD,  0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
50 DEFINE_GUID(DXVA2_ModeH264_E,         0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
51 DEFINE_GUID(DXVA2_ModeH264_F,         0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
52 DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
53 DEFINE_GUID(DXVA2_ModeVC1_D,          0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
54 DEFINE_GUID(DXVA2_ModeVC1_D2010,      0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
55 DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main,  0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
56 DEFINE_GUID(DXVA2_NoEncrypt,          0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
57 DEFINE_GUID(GUID_NULL,                0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
58
59 typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
60 typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **);
61
62 typedef struct dxva2_mode {
63   const GUID     *guid;
64   enum AVCodecID codec;
65 } dxva2_mode;
66
67 static const dxva2_mode dxva2_modes[] = {
68     /* MPEG-2 */
69     { &DXVA2_ModeMPEG2_VLD,      AV_CODEC_ID_MPEG2VIDEO },
70     { &DXVA2_ModeMPEG2and1_VLD,  AV_CODEC_ID_MPEG2VIDEO },
71
72     /* H.264 */
73     { &DXVA2_ModeH264_F,         AV_CODEC_ID_H264 },
74     { &DXVA2_ModeH264_E,         AV_CODEC_ID_H264 },
75     /* Intel specific H.264 mode */
76     { &DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 },
77
78     /* VC-1 / WMV3 */
79     { &DXVA2_ModeVC1_D2010,      AV_CODEC_ID_VC1  },
80     { &DXVA2_ModeVC1_D2010,      AV_CODEC_ID_WMV3 },
81     { &DXVA2_ModeVC1_D,          AV_CODEC_ID_VC1  },
82     { &DXVA2_ModeVC1_D,          AV_CODEC_ID_WMV3 },
83
84     /* HEVC/H.265 */
85     { &DXVA2_ModeHEVC_VLD_Main,  AV_CODEC_ID_HEVC },
86
87     { NULL,                      0 },
88 };
89
90 typedef struct surface_info {
91     int used;
92     uint64_t age;
93 } surface_info;
94
95 typedef struct DXVA2Context {
96     HMODULE d3dlib;
97     HMODULE dxva2lib;
98
99     HANDLE  deviceHandle;
100
101     IDirect3D9                  *d3d9;
102     IDirect3DDevice9            *d3d9device;
103     IDirect3DDeviceManager9     *d3d9devmgr;
104     IDirectXVideoDecoderService *decoder_service;
105     IDirectXVideoDecoder        *decoder;
106
107     GUID                        decoder_guid;
108     DXVA2_ConfigPictureDecode   decoder_config;
109
110     LPDIRECT3DSURFACE9          *surfaces;
111     surface_info                *surface_infos;
112     uint32_t                    num_surfaces;
113     uint64_t                    surface_age;
114
115     AVFrame                     *tmp_frame;
116 } DXVA2Context;
117
118 typedef struct DXVA2SurfaceWrapper {
119     DXVA2Context         *ctx;
120     LPDIRECT3DSURFACE9   surface;
121     IDirectXVideoDecoder *decoder;
122 } DXVA2SurfaceWrapper;
123
124 static void dxva2_destroy_decoder(AVCodecContext *s)
125 {
126     InputStream  *ist = s->opaque;
127     DXVA2Context *ctx = ist->hwaccel_ctx;
128     int i;
129
130     if (ctx->surfaces) {
131         for (i = 0; i < ctx->num_surfaces; i++) {
132             if (ctx->surfaces[i])
133                 IDirect3DSurface9_Release(ctx->surfaces[i]);
134         }
135     }
136     av_freep(&ctx->surfaces);
137     av_freep(&ctx->surface_infos);
138     ctx->num_surfaces = 0;
139     ctx->surface_age  = 0;
140
141     if (ctx->decoder) {
142         IDirectXVideoDecoder_Release(ctx->decoder);
143         ctx->decoder = NULL;
144     }
145 }
146
147 static void dxva2_uninit(AVCodecContext *s)
148 {
149     InputStream  *ist = s->opaque;
150     DXVA2Context *ctx = ist->hwaccel_ctx;
151
152     ist->hwaccel_uninit        = NULL;
153     ist->hwaccel_get_buffer    = NULL;
154     ist->hwaccel_retrieve_data = NULL;
155
156     if (ctx->decoder)
157         dxva2_destroy_decoder(s);
158
159     if (ctx->decoder_service)
160         IDirectXVideoDecoderService_Release(ctx->decoder_service);
161
162     if (ctx->d3d9devmgr && ctx->deviceHandle != INVALID_HANDLE_VALUE)
163         IDirect3DDeviceManager9_CloseDeviceHandle(ctx->d3d9devmgr, ctx->deviceHandle);
164
165     if (ctx->d3d9devmgr)
166         IDirect3DDeviceManager9_Release(ctx->d3d9devmgr);
167
168     if (ctx->d3d9device)
169         IDirect3DDevice9_Release(ctx->d3d9device);
170
171     if (ctx->d3d9)
172         IDirect3D9_Release(ctx->d3d9);
173
174     if (ctx->d3dlib)
175         FreeLibrary(ctx->d3dlib);
176
177     if (ctx->dxva2lib)
178         FreeLibrary(ctx->dxva2lib);
179
180     av_frame_free(&ctx->tmp_frame);
181
182     av_freep(&ist->hwaccel_ctx);
183     av_freep(&s->hwaccel_context);
184 }
185
186 static void dxva2_release_buffer(void *opaque, uint8_t *data)
187 {
188     DXVA2SurfaceWrapper *w   = opaque;
189     DXVA2Context        *ctx = w->ctx;
190     int i;
191
192     for (i = 0; i < ctx->num_surfaces; i++) {
193         if (ctx->surfaces[i] == w->surface) {
194             ctx->surface_infos[i].used = 0;
195             break;
196         }
197     }
198     IDirect3DSurface9_Release(w->surface);
199     IDirectXVideoDecoder_Release(w->decoder);
200     av_free(w);
201 }
202
203 static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
204 {
205     InputStream  *ist = s->opaque;
206     DXVA2Context *ctx = ist->hwaccel_ctx;
207     int i, old_unused = -1;
208     LPDIRECT3DSURFACE9 surface;
209     DXVA2SurfaceWrapper *w = NULL;
210
211     av_assert0(frame->format == AV_PIX_FMT_DXVA2_VLD);
212
213     for (i = 0; i < ctx->num_surfaces; i++) {
214         surface_info *info = &ctx->surface_infos[i];
215         if (!info->used && (old_unused == -1 || info->age < ctx->surface_infos[old_unused].age))
216             old_unused = i;
217     }
218     if (old_unused == -1) {
219         av_log(NULL, AV_LOG_ERROR, "No free DXVA2 surface!\n");
220         return AVERROR(ENOMEM);
221     }
222     i = old_unused;
223
224     surface = ctx->surfaces[i];
225
226     w = av_mallocz(sizeof(*w));
227     if (!w)
228         return AVERROR(ENOMEM);
229
230     frame->buf[0] = av_buffer_create((uint8_t*)surface, 0,
231                                      dxva2_release_buffer, w,
232                                      AV_BUFFER_FLAG_READONLY);
233     if (!frame->buf[0]) {
234         av_free(w);
235         return AVERROR(ENOMEM);
236     }
237
238     w->ctx     = ctx;
239     w->surface = surface;
240     IDirect3DSurface9_AddRef(w->surface);
241     w->decoder = ctx->decoder;
242     IDirectXVideoDecoder_AddRef(w->decoder);
243
244     ctx->surface_infos[i].used = 1;
245     ctx->surface_infos[i].age  = ctx->surface_age++;
246
247     frame->data[3] = (uint8_t *)surface;
248
249     return 0;
250 }
251
252 static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame)
253 {
254     LPDIRECT3DSURFACE9 surface =  (LPDIRECT3DSURFACE9)frame->data[3];
255     InputStream        *ist = s->opaque;
256     DXVA2Context       *ctx = ist->hwaccel_ctx;
257     D3DSURFACE_DESC    surfaceDesc;
258     D3DLOCKED_RECT     LockedRect;
259     HRESULT            hr;
260     int                ret;
261
262     IDirect3DSurface9_GetDesc(surface, &surfaceDesc);
263
264     ctx->tmp_frame->width  = frame->width;
265     ctx->tmp_frame->height = frame->height;
266     ctx->tmp_frame->format = AV_PIX_FMT_NV12;
267
268     ret = av_frame_get_buffer(ctx->tmp_frame, 32);
269     if (ret < 0)
270         return ret;
271
272     hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY);
273     if (FAILED(hr)) {
274         av_log(NULL, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n");
275         return AVERROR_UNKNOWN;
276     }
277
278     av_image_copy_plane(ctx->tmp_frame->data[0], ctx->tmp_frame->linesize[0],
279                         (uint8_t*)LockedRect.pBits,
280                         LockedRect.Pitch, frame->width, frame->height);
281
282     av_image_copy_plane(ctx->tmp_frame->data[1], ctx->tmp_frame->linesize[1],
283                         (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height,
284                         LockedRect.Pitch, frame->width, frame->height / 2);
285
286     IDirect3DSurface9_UnlockRect(surface);
287
288     ret = av_frame_copy_props(ctx->tmp_frame, frame);
289     if (ret < 0)
290         goto fail;
291
292     av_frame_unref(frame);
293     av_frame_move_ref(frame, ctx->tmp_frame);
294
295     return 0;
296 fail:
297     av_frame_unref(ctx->tmp_frame);
298     return ret;
299 }
300
301 static int dxva2_alloc(AVCodecContext *s)
302 {
303     InputStream  *ist = s->opaque;
304     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
305     DXVA2Context *ctx;
306     pDirect3DCreate9      *createD3D = NULL;
307     pCreateDeviceManager9 *createDeviceManager = NULL;
308     HRESULT hr;
309     D3DPRESENT_PARAMETERS d3dpp = {0};
310     D3DDISPLAYMODE        d3ddm;
311     unsigned resetToken = 0;
312     UINT adapter = D3DADAPTER_DEFAULT;
313
314     ctx = av_mallocz(sizeof(*ctx));
315     if (!ctx)
316         return AVERROR(ENOMEM);
317
318     ctx->deviceHandle = INVALID_HANDLE_VALUE;
319
320     ist->hwaccel_ctx           = ctx;
321     ist->hwaccel_uninit        = dxva2_uninit;
322     ist->hwaccel_get_buffer    = dxva2_get_buffer;
323     ist->hwaccel_retrieve_data = dxva2_retrieve_data;
324
325     ctx->d3dlib = LoadLibrary("d3d9.dll");
326     if (!ctx->d3dlib) {
327         av_log(NULL, loglevel, "Failed to load D3D9 library\n");
328         goto fail;
329     }
330     ctx->dxva2lib = LoadLibrary("dxva2.dll");
331     if (!ctx->dxva2lib) {
332         av_log(NULL, loglevel, "Failed to load DXVA2 library\n");
333         goto fail;
334     }
335
336     createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9");
337     if (!createD3D) {
338         av_log(NULL, loglevel, "Failed to locate Direct3DCreate9\n");
339         goto fail;
340     }
341     createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9");
342     if (!createDeviceManager) {
343         av_log(NULL, loglevel, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
344         goto fail;
345     }
346
347     ctx->d3d9 = createD3D(D3D_SDK_VERSION);
348     if (!ctx->d3d9) {
349         av_log(NULL, loglevel, "Failed to create IDirect3D object\n");
350         goto fail;
351     }
352
353     if (ist->hwaccel_device) {
354         adapter = atoi(ist->hwaccel_device);
355         av_log(NULL, AV_LOG_INFO, "Using HWAccel device %d\n", adapter);
356     }
357
358     IDirect3D9_GetAdapterDisplayMode(ctx->d3d9, adapter, &d3ddm);
359     d3dpp.Windowed         = TRUE;
360     d3dpp.BackBufferWidth  = 640;
361     d3dpp.BackBufferHeight = 480;
362     d3dpp.BackBufferCount  = 0;
363     d3dpp.BackBufferFormat = d3ddm.Format;
364     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
365     d3dpp.Flags            = D3DPRESENTFLAG_VIDEO;
366
367     hr = IDirect3D9_CreateDevice(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(),
368                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
369                                  &d3dpp, &ctx->d3d9device);
370     if (FAILED(hr)) {
371         av_log(NULL, loglevel, "Failed to create Direct3D device\n");
372         goto fail;
373     }
374
375     hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr);
376     if (FAILED(hr)) {
377         av_log(NULL, loglevel, "Failed to create Direct3D device manager\n");
378         goto fail;
379     }
380
381     hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken);
382     if (FAILED(hr)) {
383         av_log(NULL, loglevel, "Failed to bind Direct3D device to device manager\n");
384         goto fail;
385     }
386
387     hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle);
388     if (FAILED(hr)) {
389         av_log(NULL, loglevel, "Failed to open device handle\n");
390         goto fail;
391     }
392
393     hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service);
394     if (FAILED(hr)) {
395         av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n");
396         goto fail;
397     }
398
399     ctx->tmp_frame = av_frame_alloc();
400     if (!ctx->tmp_frame)
401         goto fail;
402
403     s->hwaccel_context = av_mallocz(sizeof(struct dxva_context));
404     if (!s->hwaccel_context)
405         goto fail;
406
407     return 0;
408 fail:
409     dxva2_uninit(s);
410     return AVERROR(EINVAL);
411 }
412
413 static int dxva2_get_decoder_configuration(AVCodecContext *s, const GUID *device_guid,
414                                            const DXVA2_VideoDesc *desc,
415                                            DXVA2_ConfigPictureDecode *config)
416 {
417     InputStream  *ist = s->opaque;
418     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
419     DXVA2Context *ctx = ist->hwaccel_ctx;
420     unsigned cfg_count = 0, best_score = 0;
421     DXVA2_ConfigPictureDecode *cfg_list = NULL;
422     DXVA2_ConfigPictureDecode best_cfg = {{0}};
423     HRESULT hr;
424     int i;
425
426     hr = IDirectXVideoDecoderService_GetDecoderConfigurations(ctx->decoder_service, device_guid, desc, NULL, &cfg_count, &cfg_list);
427     if (FAILED(hr)) {
428         av_log(NULL, loglevel, "Unable to retrieve decoder configurations\n");
429         return AVERROR(EINVAL);
430     }
431
432     for (i = 0; i < cfg_count; i++) {
433         DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
434
435         unsigned score;
436         if (cfg->ConfigBitstreamRaw == 1)
437             score = 1;
438         else if (s->codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2)
439             score = 2;
440         else
441             continue;
442         if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt))
443             score += 16;
444         if (score > best_score) {
445             best_score = score;
446             best_cfg   = *cfg;
447         }
448     }
449     CoTaskMemFree(cfg_list);
450
451     if (!best_score) {
452         av_log(NULL, loglevel, "No valid decoder configuration available\n");
453         return AVERROR(EINVAL);
454     }
455
456     *config = best_cfg;
457     return 0;
458 }
459
460 static int dxva2_create_decoder(AVCodecContext *s)
461 {
462     InputStream  *ist = s->opaque;
463     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
464     DXVA2Context *ctx = ist->hwaccel_ctx;
465     struct dxva_context *dxva_ctx = s->hwaccel_context;
466     GUID *guid_list = NULL;
467     unsigned guid_count = 0, i, j;
468     GUID device_guid = GUID_NULL;
469     D3DFORMAT target_format = 0;
470     DXVA2_VideoDesc desc = { 0 };
471     DXVA2_ConfigPictureDecode config;
472     HRESULT hr;
473     int surface_alignment;
474     int ret;
475
476     hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list);
477     if (FAILED(hr)) {
478         av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n");
479         goto fail;
480     }
481
482     for (i = 0; dxva2_modes[i].guid; i++) {
483         D3DFORMAT *target_list = NULL;
484         unsigned target_count = 0;
485         const dxva2_mode *mode = &dxva2_modes[i];
486         if (mode->codec != s->codec_id)
487             continue;
488
489         for (j = 0; j < guid_count; j++) {
490             if (IsEqualGUID(mode->guid, &guid_list[j]))
491                 break;
492         }
493         if (j == guid_count)
494             continue;
495
496         hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(ctx->decoder_service, mode->guid, &target_count, &target_list);
497         if (FAILED(hr)) {
498             continue;
499         }
500         for (j = 0; j < target_count; j++) {
501             const D3DFORMAT format = target_list[j];
502             if (format == MKTAG('N','V','1','2')) {
503                 target_format = format;
504                 break;
505             }
506         }
507         CoTaskMemFree(target_list);
508         if (target_format) {
509             device_guid = *mode->guid;
510             break;
511         }
512     }
513     CoTaskMemFree(guid_list);
514
515     if (IsEqualGUID(&device_guid, &GUID_NULL)) {
516         av_log(NULL, loglevel, "No decoder device for codec found\n");
517         goto fail;
518     }
519
520     desc.SampleWidth  = s->coded_width;
521     desc.SampleHeight = s->coded_height;
522     desc.Format       = target_format;
523
524     ret = dxva2_get_decoder_configuration(s, &device_guid, &desc, &config);
525     if (ret < 0) {
526         goto fail;
527     }
528
529     /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
530        but it causes issues for H.264 on certain AMD GPUs..... */
531     if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO)
532         surface_alignment = 32;
533     /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
534        all coding features have enough room to work with */
535     else if  (s->codec_id == AV_CODEC_ID_HEVC)
536         surface_alignment = 128;
537     else
538         surface_alignment = 16;
539
540     /* 4 base work surfaces */
541     ctx->num_surfaces = 4;
542
543     /* add surfaces based on number of possible refs */
544     if (s->codec_id == AV_CODEC_ID_H264 || s->codec_id == AV_CODEC_ID_HEVC)
545         ctx->num_surfaces += 16;
546     else
547         ctx->num_surfaces += 2;
548
549     /* add extra surfaces for frame threading */
550     if (s->active_thread_type & FF_THREAD_FRAME)
551         ctx->num_surfaces += s->thread_count;
552
553     ctx->surfaces      = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surfaces));
554     ctx->surface_infos = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surface_infos));
555
556     if (!ctx->surfaces || !ctx->surface_infos) {
557         av_log(NULL, loglevel, "Unable to allocate surface arrays\n");
558         goto fail;
559     }
560
561     hr = IDirectXVideoDecoderService_CreateSurface(ctx->decoder_service,
562                                                    FFALIGN(s->coded_width, surface_alignment),
563                                                    FFALIGN(s->coded_height, surface_alignment),
564                                                    ctx->num_surfaces - 1,
565                                                    target_format, D3DPOOL_DEFAULT, 0,
566                                                    DXVA2_VideoDecoderRenderTarget,
567                                                    ctx->surfaces, NULL);
568     if (FAILED(hr)) {
569         av_log(NULL, loglevel, "Failed to create %d video surfaces\n", ctx->num_surfaces);
570         goto fail;
571     }
572
573     hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid,
574                                                         &desc, &config, ctx->surfaces,
575                                                         ctx->num_surfaces, &ctx->decoder);
576     if (FAILED(hr)) {
577         av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n");
578         goto fail;
579     }
580
581     ctx->decoder_guid   = device_guid;
582     ctx->decoder_config = config;
583
584     dxva_ctx->cfg           = &ctx->decoder_config;
585     dxva_ctx->decoder       = ctx->decoder;
586     dxva_ctx->surface       = ctx->surfaces;
587     dxva_ctx->surface_count = ctx->num_surfaces;
588
589     if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E))
590         dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
591
592     return 0;
593 fail:
594     dxva2_destroy_decoder(s);
595     return AVERROR(EINVAL);
596 }
597
598 int dxva2_init(AVCodecContext *s)
599 {
600     InputStream *ist = s->opaque;
601     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
602     DXVA2Context *ctx;
603     int ret;
604
605     if (!ist->hwaccel_ctx) {
606         ret = dxva2_alloc(s);
607         if (ret < 0)
608             return ret;
609     }
610     ctx = ist->hwaccel_ctx;
611
612     if (s->codec_id == AV_CODEC_ID_H264 &&
613         (s->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) {
614         av_log(NULL, loglevel, "Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->profile);
615         return AVERROR(EINVAL);
616     }
617
618     if (ctx->decoder)
619         dxva2_destroy_decoder(s);
620
621     ret = dxva2_create_decoder(s);
622     if (ret < 0) {
623         av_log(NULL, loglevel, "Error creating the DXVA2 decoder\n");
624         return ret;
625     }
626
627     return 0;
628 }