avconv: add support for DXVA2 decoding
[libav.git] / avconv_dxva2.c
CommitLineData
35177ba7
HL
1/*
2 * This file is part of Libav.
3 *
4 * Libav 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 * Libav 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 Libav; 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 "avconv.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
47typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
48typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **);
49
50/* GUIDs not defined in the common dxva2api.h in mingw-w64 */
51#ifndef _MSC_VER
52DEFINE_GUID(DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
53DEFINE_GUID(DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
54DEFINE_GUID(DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
55#endif
56
57DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
58DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
59
60typedef struct dxva2_mode {
61 const GUID *guid;
62 enum AVCodecID codec;
63} dxva2_mode;
64
65static 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
85typedef struct surface_info {
86 int used;
87 uint64_t age;
88} surface_info;
89
90typedef 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
113typedef struct DXVA2SurfaceWrapper {
114 DXVA2Context *ctx;
115 LPDIRECT3DSURFACE9 surface;
116 IDirectXVideoDecoder *decoder;
117} DXVA2SurfaceWrapper;
118
119static 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
141static 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
180static 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
197static 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
246static 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;
290fail:
291 av_frame_unref(ctx->tmp_frame);
292 return ret;
293}
294
295static 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;
402fail:
403 dxva2_uninit(s);
404 return AVERROR(EINVAL);
405}
406
407static 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
454static 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;
583fail:
584 dxva2_destroy_decoder(s);
585 return AVERROR(EINVAL);
586}
587
588int 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}