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