FFmpeg
Loading...
Searching...
No Matches
qsv.c
Go to the documentation of this file.
1/*
2 * Intel MediaSDK QSV encoder/decoder shared code
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <mfxvideo.h>
22#include <mfxjpeg.h>
23#include <mfxvp8.h>
24
25#include <stdio.h>
26#include <string.h>
27
28#include "libavutil/avstring.h"
29#include "libavutil/common.h"
30#include "libavutil/error.h"
31#include "libavutil/hwcontext.h"
33#include "libavutil/avassert.h"
34#include "libavutil/mem.h"
35
36#include "avcodec.h"
37#include "qsv_internal.h"
38#include "libavutil/refstruct.h"
39
40#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
41#define QSV_HAVE_USER_PLUGIN !QSV_ONEVPL
42#define QSV_HAVE_AUDIO !QSV_ONEVPL
43
44#if QSV_HAVE_USER_PLUGIN
45#include <mfxplugin.h>
46#endif
47
48#if QSV_ONEVPL
49#include <mfxdispatcher.h>
50#else
51#define MFXUnload(a) do { } while(0)
52#endif
53
55{
56 switch (codec_id) {
58 return MFX_CODEC_AVC;
60 return MFX_CODEC_HEVC;
63 return MFX_CODEC_MPEG2;
64 case AV_CODEC_ID_VC1:
65 return MFX_CODEC_VC1;
66 case AV_CODEC_ID_VP8:
67 return MFX_CODEC_VP8;
69 return MFX_CODEC_JPEG;
70 case AV_CODEC_ID_VP9:
71 return MFX_CODEC_VP9;
72#if QSV_VERSION_ATLEAST(1, 34)
73 case AV_CODEC_ID_AV1:
74 return MFX_CODEC_AV1;
75#endif
76#if QSV_VERSION_ATLEAST(2, 11)
77 case AV_CODEC_ID_VVC:
78 return MFX_CODEC_VVC;
79#endif
80
81 default:
82 break;
83 }
84
85 return AVERROR(ENOSYS);
86}
87
88static const struct {
90 const char *desc;
91} qsv_iopatterns[] = {
92 {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
93 {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
94#if QSV_HAVE_OPAQUE
95 {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
96#endif
97 {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
98 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
99#if QSV_HAVE_OPAQUE
100 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
101#endif
103
105 const char *extra_string)
106{
107 const char *desc = NULL;
108
109 for (int i = 0; i < FF_ARRAY_ELEMS(qsv_iopatterns); i++) {
111 desc = qsv_iopatterns[i].desc;
112 }
113 }
114 if (!desc)
115 desc = "unknown iopattern";
116
117 av_log(log_ctx, AV_LOG_VERBOSE, "%s: %s\n", extra_string, desc);
118 return 0;
119}
120
121static const struct {
122 mfxStatus mfxerr;
123 int averr;
124 const char *desc;
125} qsv_errors[] = {
126 { MFX_ERR_NONE, 0, "success" },
127 { MFX_ERR_UNKNOWN, AVERROR_UNKNOWN, "unknown error" },
128 { MFX_ERR_NULL_PTR, AVERROR(EINVAL), "NULL pointer" },
129 { MFX_ERR_UNSUPPORTED, AVERROR(ENOSYS), "unsupported" },
130 { MFX_ERR_MEMORY_ALLOC, AVERROR(ENOMEM), "failed to allocate memory" },
131 { MFX_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOMEM), "insufficient input/output buffer" },
132 { MFX_ERR_INVALID_HANDLE, AVERROR(EINVAL), "invalid handle" },
133 { MFX_ERR_LOCK_MEMORY, AVERROR(EIO), "failed to lock the memory block" },
134 { MFX_ERR_NOT_INITIALIZED, AVERROR_BUG, "not initialized" },
135 { MFX_ERR_NOT_FOUND, AVERROR(ENOSYS), "specified object was not found" },
136 /* the following 3 errors should always be handled explicitly, so those "mappings"
137 * are for completeness only */
138 { MFX_ERR_MORE_DATA, AVERROR_UNKNOWN, "expect more data at input" },
139 { MFX_ERR_MORE_SURFACE, AVERROR_UNKNOWN, "expect more surface at output" },
140 { MFX_ERR_MORE_BITSTREAM, AVERROR_UNKNOWN, "expect more bitstream at output" },
141 { MFX_ERR_ABORTED, AVERROR_UNKNOWN, "operation aborted" },
142 { MFX_ERR_DEVICE_LOST, AVERROR(EIO), "device lost" },
143 { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters" },
144 { MFX_ERR_INVALID_VIDEO_PARAM, AVERROR(EINVAL), "invalid video parameters" },
145 { MFX_ERR_UNDEFINED_BEHAVIOR, AVERROR_BUG, "undefined behavior" },
146 { MFX_ERR_DEVICE_FAILED, AVERROR(EIO), "device failed" },
147#if QSV_HAVE_AUDIO
148 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters" },
149 { MFX_ERR_INVALID_AUDIO_PARAM, AVERROR(EINVAL), "invalid audio parameters" },
150#endif
151 { MFX_ERR_GPU_HANG, AVERROR(EIO), "GPU Hang" },
152 { MFX_ERR_REALLOC_SURFACE, AVERROR_UNKNOWN, "need bigger surface for output" },
153
154 { MFX_WRN_IN_EXECUTION, 0, "operation in execution" },
155 { MFX_WRN_DEVICE_BUSY, 0, "device busy" },
156 { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" },
157 { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" },
158 { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" },
159 { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" },
160 { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" },
161 { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" },
162#if QSV_HAVE_AUDIO
163 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
164#endif
165
166#if QSV_VERSION_ATLEAST(1, 31)
167 { MFX_ERR_NONE_PARTIAL_OUTPUT, 0, "partial output" },
168#endif
170
171/**
172 * Convert a libmfx error code into an FFmpeg error code.
173 */
174static int qsv_map_error(mfxStatus mfx_err, const char **desc)
175{
176 int i;
177 for (i = 0; i < FF_ARRAY_ELEMS(qsv_errors); i++) {
178 if (qsv_errors[i].mfxerr == mfx_err) {
179 if (desc)
180 *desc = qsv_errors[i].desc;
181 return qsv_errors[i].averr;
182 }
183 }
184 if (desc)
185 *desc = "unknown error";
186 return AVERROR_UNKNOWN;
187}
188
189int ff_qsv_print_error(void *log_ctx, mfxStatus err,
190 const char *error_string)
191{
192 const char *desc;
193 int ret = qsv_map_error(err, &desc);
194 av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err);
195 return ret;
196}
197
198int ff_qsv_print_warning(void *log_ctx, mfxStatus err,
199 const char *warning_string)
200{
201 const char *desc;
202 int ret = qsv_map_error(err, &desc);
203 av_log(log_ctx, AV_LOG_WARNING, "%s: %s (%d)\n", warning_string, desc, err);
204 return ret;
205}
206
208{
209 switch (fourcc) {
210 case MFX_FOURCC_NV12: return AV_PIX_FMT_NV12;
211 case MFX_FOURCC_P010: return AV_PIX_FMT_P010;
212 case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8;
213 case MFX_FOURCC_A2RGB10: return AV_PIX_FMT_X2RGB10;
214 case MFX_FOURCC_RGB4: return AV_PIX_FMT_BGRA;
215 case MFX_FOURCC_YUY2: return AV_PIX_FMT_YUYV422;
216 case MFX_FOURCC_Y210: return AV_PIX_FMT_Y210;
217 case MFX_FOURCC_AYUV: return AV_PIX_FMT_VUYX;
218 case MFX_FOURCC_Y410: return AV_PIX_FMT_XV30;
219#if QSV_VERSION_ATLEAST(1, 31)
220 case MFX_FOURCC_P016: return AV_PIX_FMT_P012;
221 case MFX_FOURCC_Y216: return AV_PIX_FMT_Y212;
222 case MFX_FOURCC_Y416: return AV_PIX_FMT_XV36;
223#endif
224 }
225 return AV_PIX_FMT_NONE;
226}
227
228int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc, uint16_t *shift)
229{
230 switch (format) {
233 case AV_PIX_FMT_NV12:
234 *fourcc = MFX_FOURCC_NV12;
235 *shift = 0;
236 return AV_PIX_FMT_NV12;
238 case AV_PIX_FMT_P010:
239 *fourcc = MFX_FOURCC_P010;
240 *shift = 1;
241 return AV_PIX_FMT_P010;
243 *fourcc = MFX_FOURCC_A2RGB10;
244 *shift = 1;
245 return AV_PIX_FMT_X2RGB10;
246 case AV_PIX_FMT_BGRA:
247 *fourcc = MFX_FOURCC_RGB4;
248 *shift = 0;
249 return AV_PIX_FMT_BGRA;
252 *fourcc = MFX_FOURCC_YUY2;
253 *shift = 0;
254 return AV_PIX_FMT_YUYV422;
256 case AV_PIX_FMT_Y210:
257 *fourcc = MFX_FOURCC_Y210;
258 *shift = 1;
259 return AV_PIX_FMT_Y210;
260 case AV_PIX_FMT_VUYX:
261 *fourcc = MFX_FOURCC_AYUV;
262 *shift = 0;
263 return AV_PIX_FMT_VUYX;
264 case AV_PIX_FMT_XV30:
265 *fourcc = MFX_FOURCC_Y410;
266 *shift = 0;
267 return AV_PIX_FMT_XV30;
268#if QSV_VERSION_ATLEAST(1, 31)
269 case AV_PIX_FMT_P012:
270 *fourcc = MFX_FOURCC_P016;
271 *shift = 1;
272 return AV_PIX_FMT_P012;
273 case AV_PIX_FMT_Y212:
274 *fourcc = MFX_FOURCC_Y216;
275 *shift = 1;
276 return AV_PIX_FMT_Y212;
277 case AV_PIX_FMT_XV36:
278 *fourcc = MFX_FOURCC_Y416;
279 *shift = 1;
280 return AV_PIX_FMT_XV36;
281#endif
282 default:
283 return AVERROR(ENOSYS);
284 }
285}
286
287int ff_qsv_map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface)
288{
289 switch (frame->format) {
290 case AV_PIX_FMT_NV12:
291 case AV_PIX_FMT_P010:
292 case AV_PIX_FMT_P012:
293 surface->Data.Y = frame->data[0];
294 surface->Data.UV = frame->data[1];
295 /* The SDK checks Data.V when using system memory for VP9 encoding */
296 surface->Data.V = surface->Data.UV + 1;
297 break;
299 case AV_PIX_FMT_BGRA:
300 surface->Data.B = frame->data[0];
301 surface->Data.G = frame->data[0] + 1;
302 surface->Data.R = frame->data[0] + 2;
303 surface->Data.A = frame->data[0] + 3;
304 break;
306 surface->Data.Y = frame->data[0];
307 surface->Data.U = frame->data[0] + 1;
308 surface->Data.V = frame->data[0] + 3;
309 break;
310
311 case AV_PIX_FMT_Y210:
312 case AV_PIX_FMT_Y212:
313 surface->Data.Y16 = (mfxU16 *)frame->data[0];
314 surface->Data.U16 = (mfxU16 *)frame->data[0] + 1;
315 surface->Data.V16 = (mfxU16 *)frame->data[0] + 3;
316 break;
317
318 case AV_PIX_FMT_VUYX:
319 surface->Data.V = frame->data[0];
320 surface->Data.U = frame->data[0] + 1;
321 surface->Data.Y = frame->data[0] + 2;
322 // Only set Data.A to a valid address, the SDK doesn't
323 // use the value from the frame.
324 surface->Data.A = frame->data[0] + 3;
325 break;
326
327 case AV_PIX_FMT_XV30:
328 surface->Data.U = frame->data[0];
329 break;
330
331 case AV_PIX_FMT_XV36:
332 surface->Data.U = frame->data[0];
333 surface->Data.Y = frame->data[0] + 2;
334 surface->Data.V = frame->data[0] + 4;
335 // Only set Data.A to a valid address, the SDK doesn't
336 // use the value from the frame.
337 surface->Data.A = frame->data[0] + 6;
338 break;
339
340 default:
341 return AVERROR(ENOSYS);
342 }
343 surface->Data.PitchLow = frame->linesize[0];
344
345 return 0;
346}
347
349{
350 int i;
351 for (i = 0; i < ctx->nb_mids; i++) {
352 QSVMid *mid = &ctx->mids[i];
353 mfxHDLPair *pair = (mfxHDLPair*)frame->surface.Data.MemId;
354 if ((mid->handle_pair->first == pair->first) &&
355 (mid->handle_pair->second == pair->second))
356 return i;
357 }
358 return AVERROR_BUG;
359}
360
361enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct)
362{
363 enum AVFieldOrder field = AV_FIELD_UNKNOWN;
364 switch (mfx_pic_struct & 0xF) {
365 case MFX_PICSTRUCT_PROGRESSIVE:
366 field = AV_FIELD_PROGRESSIVE;
367 break;
368 case MFX_PICSTRUCT_FIELD_TFF:
369 field = AV_FIELD_TT;
370 break;
371 case MFX_PICSTRUCT_FIELD_BFF:
372 field = AV_FIELD_BB;
373 break;
374 }
375
376 return field;
377}
378
379enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
380{
381 enum AVPictureType type;
382 switch (mfx_pic_type & 0x7) {
383 case MFX_FRAMETYPE_I:
384 if (mfx_pic_type & MFX_FRAMETYPE_S)
386 else
388 break;
389 case MFX_FRAMETYPE_B:
391 break;
392 case MFX_FRAMETYPE_P:
393 if (mfx_pic_type & MFX_FRAMETYPE_S)
395 else
397 break;
398 case MFX_FRAMETYPE_UNKNOWN:
400 break;
401 default:
402 av_assert0(0);
403 }
404
405 return type;
406}
407
408static int qsv_load_plugins(mfxSession session, const char *load_plugins,
409 void *logctx)
410{
411#if QSV_HAVE_USER_PLUGIN
412 if (!load_plugins || !*load_plugins)
413 return 0;
414
415 while (*load_plugins) {
416 mfxPluginUID uid;
417 mfxStatus ret;
418 int i, err = 0;
419
420 char *plugin = av_get_token(&load_plugins, ":");
421 if (!plugin)
422 return AVERROR(ENOMEM);
423 if (strlen(plugin) != 2 * sizeof(uid.Data)) {
424 av_log(logctx, AV_LOG_ERROR, "Invalid plugin UID length\n");
425 err = AVERROR(EINVAL);
426 goto load_plugin_fail;
427 }
428
429 for (i = 0; i < sizeof(uid.Data); i++) {
430 err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i);
431 if (err != 1) {
432 av_log(logctx, AV_LOG_ERROR, "Invalid plugin UID\n");
433 err = AVERROR(EINVAL);
434 goto load_plugin_fail;
435 }
436
437 }
438
439 ret = MFXVideoUSER_Load(session, &uid, 1);
440 if (ret < 0) {
441 char errorbuf[128];
442 snprintf(errorbuf, sizeof(errorbuf),
443 "Could not load the requested plugin '%s'", plugin);
444 err = ff_qsv_print_error(logctx, ret, errorbuf);
445 goto load_plugin_fail;
446 }
447
448 if (*load_plugins)
449 load_plugins++;
450load_plugin_fail:
451 av_freep(&plugin);
452 if (err < 0)
453 return err;
454 }
455#endif
456
457 return 0;
458
459}
460
461//This code is only required for Linux since a display handle is required.
462//For Windows the session is complete and ready to use.
463
464#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
465static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
466{
467 AVDictionary *child_device_opts = NULL;
469 int ret;
470
471 av_dict_set(&child_device_opts, "vendor_id", "0x8086", 0);
472 av_dict_set(&child_device_opts, "driver", "iHD", 0);
473
474 ret = av_hwdevice_ctx_create(&qs->va_device_ref, AV_HWDEVICE_TYPE_VAAPI, NULL, child_device_opts, 0);
475 av_dict_free(&child_device_opts);
476 if (ret < 0) {
477 av_log(avctx, AV_LOG_ERROR, "Failed to create a VAAPI device.\n");
478 return ret;
479 } else {
480 qs->va_device_ctx = (AVHWDeviceContext*)qs->va_device_ref->data;
481 hwctx = qs->va_device_ctx->hwctx;
482
483 ret = MFXVideoCORE_SetHandle(qs->session,
484 (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->display);
485 if (ret < 0) {
486 return ff_qsv_print_error(avctx, ret, "Error during set display handle\n");
487 }
488 }
489
490 return 0;
491}
492#endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
493
494#if QSV_ONEVPL
495static int qsv_new_mfx_loader(AVCodecContext *avctx,
496 mfxIMPL implementation,
497 mfxVersion *pver,
498 void **ploader)
499{
500 mfxStatus sts;
501 mfxLoader loader = NULL;
502 mfxConfig cfg;
503 mfxVariant impl_value = {0};
504
505 loader = MFXLoad();
506 if (!loader) {
507 av_log(avctx, AV_LOG_ERROR, "Error creating a MFX loader\n");
508 goto fail;
509 }
510
511 /* Create configurations for implementation */
512 cfg = MFXCreateConfig(loader);
513 if (!cfg) {
514 av_log(avctx, AV_LOG_ERROR, "Error creating a MFX configurations\n");
515 goto fail;
516 }
517
518 impl_value.Type = MFX_VARIANT_TYPE_U32;
519 impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
520 MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
521 sts = MFXSetConfigFilterProperty(cfg,
522 (const mfxU8 *)"mfxImplDescription.Impl", impl_value);
523 if (sts != MFX_ERR_NONE) {
524 av_log(avctx, AV_LOG_ERROR, "Error adding a MFX configuration "
525 "property: %d\n", sts);
526 goto fail;
527 }
528
529 impl_value.Type = MFX_VARIANT_TYPE_U32;
530 impl_value.Data.U32 = pver->Version;
531 sts = MFXSetConfigFilterProperty(cfg,
532 (const mfxU8 *)"mfxImplDescription.ApiVersion.Version",
533 impl_value);
534 if (sts != MFX_ERR_NONE) {
535 av_log(avctx, AV_LOG_ERROR, "Error adding a MFX configuration "
536 "property: %d\n", sts);
537 goto fail;
538 }
539
540 *ploader = loader;
541
542 return 0;
543
544fail:
545 if (loader)
546 MFXUnload(loader);
547
548 *ploader = NULL;
549 return AVERROR_UNKNOWN;
550}
551
552static int qsv_create_mfx_session_from_loader(void *ctx, mfxLoader loader, mfxSession *psession)
553{
554 mfxStatus sts;
555 mfxSession session = NULL;
556 uint32_t impl_idx = 0;
557
558 while (1) {
559 /* Enumerate all implementations */
560 mfxImplDescription *impl_desc;
561
562 sts = MFXEnumImplementations(loader, impl_idx,
563 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
564 (mfxHDL *)&impl_desc);
565 /* Failed to find an available implementation */
566 if (sts == MFX_ERR_NOT_FOUND)
567 break;
568 else if (sts != MFX_ERR_NONE) {
569 impl_idx++;
570 continue;
571 }
572
573 sts = MFXCreateSession(loader, impl_idx, &session);
574 MFXDispReleaseImplDescription(loader, impl_desc);
575 if (sts == MFX_ERR_NONE)
576 break;
577
578 impl_idx++;
579 }
580
581 if (sts != MFX_ERR_NONE) {
582 av_log(ctx, AV_LOG_ERROR, "Error creating a MFX session: %d.\n", sts);
583 goto fail;
584 }
585
586 *psession = session;
587
588 return 0;
589
590fail:
591 if (session)
592 MFXClose(session);
593
594 *psession = NULL;
595 return AVERROR_UNKNOWN;
596}
597
598static int qsv_create_mfx_session(AVCodecContext *avctx,
599 mfxIMPL implementation,
600 mfxVersion *pver,
601 int gpu_copy,
602 mfxSession *psession,
603 void **ploader)
604{
605 mfxLoader loader = NULL;
606
607 /* Don't create a new MFX loader if the input loader is valid */
608 if (*ploader == NULL) {
609 av_log(avctx, AV_LOG_VERBOSE,
610 "Use Intel(R) oneVPL to create MFX session, the required "
611 "implementation version is %d.%d\n",
612 pver->Major, pver->Minor);
613
614 if (qsv_new_mfx_loader(avctx, implementation, pver, (void **)&loader))
615 goto fail;
616
617 av_assert0(loader);
618 } else {
619 av_log(avctx, AV_LOG_VERBOSE,
620 "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
621
622 loader = *ploader;
623 }
624
625 if (qsv_create_mfx_session_from_loader(avctx, loader, psession))
626 goto fail;
627
628 if (!*ploader)
629 *ploader = loader;
630
631 return 0;
632
633fail:
634 if (!*ploader && loader)
635 MFXUnload(loader);
636
637 return AVERROR_UNKNOWN;
638}
639
640#else
641
643 mfxIMPL implementation,
644 mfxVersion *pver,
645 int gpu_copy,
646 mfxSession *psession,
647 void **ploader)
648{
649 mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
650 mfxSession session = NULL;
651 mfxStatus sts;
652
653 av_log(avctx, AV_LOG_VERBOSE,
654 "Use Intel(R) Media SDK to create MFX session, the required "
655 "implementation version is %d.%d\n",
656 pver->Major, pver->Minor);
657
658 *psession = NULL;
659 *ploader = NULL;
660
661 init_par.GPUCopy = gpu_copy;
662 init_par.Implementation = implementation;
663 init_par.Version = *pver;
664 sts = MFXInitEx(init_par, &session);
665 if (sts < 0)
666 return ff_qsv_print_error(avctx, sts,
667 "Error initializing a MFX session");
668 else if (sts > 0) {
669 ff_qsv_print_warning(avctx, sts,
670 "Warning in MFX initialization");
671 return AVERROR_UNKNOWN;
672 }
673
674 *psession = session;
675
676 return 0;
677}
678
679#endif
680
682 const char *load_plugins, int gpu_copy)
683{
684 mfxIMPL impls[] = {
685#if CONFIG_D3D11VA
686 MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11,
687#endif
688 MFX_IMPL_AUTO_ANY
689 };
690 mfxIMPL impl;
691 mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
692
693 const char *desc;
694 int ret;
695
696 for (int i = 0; i < FF_ARRAY_ELEMS(impls); i++) {
697 ret = qsv_create_mfx_session(avctx, impls[i], &ver, gpu_copy, &qs->session,
698 &qs->loader);
699
700 if (ret == 0)
701 break;
702
703 if (i == FF_ARRAY_ELEMS(impls) - 1)
704 return ret;
705 else
706 av_log(avctx, AV_LOG_ERROR, "The current mfx implementation is not "
707 "supported, try next mfx implementation.\n");
708 }
709
710#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
711 ret = ff_qsv_set_display_handle(avctx, qs);
712 if (ret < 0)
713 return ret;
714#endif
715
716 ret = qsv_load_plugins(qs->session, load_plugins, avctx);
717 if (ret < 0) {
718 av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
719 return ret;
720 }
721
722 ret = MFXQueryIMPL(qs->session, &impl);
723 if (ret != MFX_ERR_NONE)
724 return ff_qsv_print_error(avctx, ret,
725 "Error querying the session attributes");
726
727 switch (MFX_IMPL_BASETYPE(impl)) {
728 case MFX_IMPL_SOFTWARE:
729 desc = "software";
730 break;
731 case MFX_IMPL_HARDWARE:
732 case MFX_IMPL_HARDWARE2:
733 case MFX_IMPL_HARDWARE3:
734 case MFX_IMPL_HARDWARE4:
735 desc = "hardware accelerated";
736 break;
737 default:
738 desc = "unknown";
739 }
740
741 av_log(avctx, AV_LOG_VERBOSE,
742 "Initialized an internal MFX session using %s implementation\n",
743 desc);
744
745 return 0;
746}
747
748static void mids_buf_free(AVRefStructOpaque opaque, void *obj)
749{
750 AVBufferRef *hw_frames_ref = opaque.nc;
751 av_buffer_unref(&hw_frames_ref);
752}
753
754static QSVMid *qsv_create_mids(AVBufferRef *hw_frames_ref)
755{
756 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data;
757 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
758 int nb_surfaces = frames_hwctx->nb_surfaces;
759
760 AVBufferRef *hw_frames_ref1;
761 QSVMid *mids;
762 int i;
763
764 hw_frames_ref1 = av_buffer_ref(hw_frames_ref);
765 if (!hw_frames_ref1)
766 return NULL;
767
768 mids = av_refstruct_alloc_ext(nb_surfaces * sizeof(*mids), 0,
769 hw_frames_ref1, mids_buf_free);
770 if (!mids) {
771 av_buffer_unref(&hw_frames_ref1);
772 return NULL;
773 }
774
775 for (i = 0; i < nb_surfaces; i++) {
776 QSVMid *mid = &mids[i];
777 mid->handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[i].Data.MemId;
778 mid->hw_frames_ref = hw_frames_ref1;
779 }
780
781 return mids;
782}
783
784static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref,
785 QSVMid *mids)
786{
787 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data;
788 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
789 int nb_surfaces = frames_hwctx->nb_surfaces;
790 int i;
791
792 // the allocated size of the array is two larger than the number of
793 // surfaces, we store the references to the frames context and the
794 // QSVMid array there
795 resp->mids = av_calloc(nb_surfaces + 2, sizeof(*resp->mids));
796 if (!resp->mids)
797 return AVERROR(ENOMEM);
798
799 for (i = 0; i < nb_surfaces; i++)
800 resp->mids[i] = &mids[i];
801 resp->NumFrameActual = nb_surfaces;
802
803 resp->mids[resp->NumFrameActual] = (mfxMemId)av_buffer_ref(hw_frames_ref);
804 if (!resp->mids[resp->NumFrameActual]) {
805 av_freep(&resp->mids);
806 return AVERROR(ENOMEM);
807 }
808
809 resp->mids[resp->NumFrameActual + 1] = av_refstruct_ref(mids);
810
811 return 0;
812}
813
814static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
815 mfxFrameAllocResponse *resp)
816{
817 QSVFramesContext *ctx = pthis;
818 int ret;
819
820 /* this should only be called from an encoder or decoder and
821 * only allocates video memory frames */
822 if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
823 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ||
824 !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
825 return MFX_ERR_UNSUPPORTED;
826
827 if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
828 /* external frames -- fill from the caller-supplied frames context */
829 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
830 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
831 mfxFrameInfo *i = &req->Info;
832 mfxFrameInfo *i1;
833
834 if (!frames_hwctx->nb_surfaces) {
835 av_log(ctx->logctx, AV_LOG_DEBUG,
836 "Dynamic frame pools, no frame is pre-allocated\n");
837
838 return MFX_ERR_NONE;
839 }
840
841 i1 = &frames_hwctx->surfaces[0].Info;
842 if (i->Width > i1->Width || i->Height > i1->Height ||
843 i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) {
844 av_log(ctx->logctx, AV_LOG_ERROR, "Mismatching surface properties in an "
845 "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
846 i->Width, i->Height, i->FourCC, i->ChromaFormat,
847 i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
848 return MFX_ERR_UNSUPPORTED;
849 }
850
851 ret = qsv_setup_mids(resp, ctx->hw_frames_ctx, ctx->mids);
852 if (ret < 0) {
853 av_log(ctx->logctx, AV_LOG_ERROR,
854 "Error filling an external frame allocation request\n");
855 return MFX_ERR_MEMORY_ALLOC;
856 }
857 } else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
858 /* internal frames -- allocate a new hw frames context */
859 AVHWFramesContext *ext_frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
860 AVQSVFramesContext *ext_frames_hwctx = ext_frames_ctx->hwctx;
861 mfxFrameInfo *i = &req->Info;
862
863 AVBufferRef *frames_ref;
864 QSVMid *mids;
865 AVHWFramesContext *frames_ctx;
866 AVQSVFramesContext *frames_hwctx;
867
868 if (!ext_frames_hwctx->nb_surfaces)
869 return MFX_ERR_UNSUPPORTED;
870
871 frames_ref = av_hwframe_ctx_alloc(ext_frames_ctx->device_ref);
872 if (!frames_ref)
873 return MFX_ERR_MEMORY_ALLOC;
874
875 frames_ctx = (AVHWFramesContext*)frames_ref->data;
876 frames_hwctx = frames_ctx->hwctx;
877
878 frames_ctx->format = AV_PIX_FMT_QSV;
879 frames_ctx->sw_format = ff_qsv_map_fourcc(i->FourCC);
880 frames_ctx->width = i->Width;
881 frames_ctx->height = i->Height;
882 frames_ctx->initial_pool_size = req->NumFrameSuggested;
883
884 frames_hwctx->frame_type = req->Type;
885
886 ret = av_hwframe_ctx_init(frames_ref);
887 if (ret < 0) {
888 av_log(ctx->logctx, AV_LOG_ERROR,
889 "Error initializing a frames context for an internal frame "
890 "allocation request\n");
891 av_buffer_unref(&frames_ref);
892 return MFX_ERR_MEMORY_ALLOC;
893 }
894
895 mids = qsv_create_mids(frames_ref);
896 if (!mids) {
897 av_buffer_unref(&frames_ref);
898 return MFX_ERR_MEMORY_ALLOC;
899 }
900
901 ret = qsv_setup_mids(resp, frames_ref, mids);
902 av_refstruct_unref(&mids);
903 av_buffer_unref(&frames_ref);
904 if (ret < 0) {
905 av_log(ctx->logctx, AV_LOG_ERROR,
906 "Error filling an internal frame allocation request\n");
907 return MFX_ERR_MEMORY_ALLOC;
908 }
909 } else {
910 return MFX_ERR_UNSUPPORTED;
911 }
912
913 return MFX_ERR_NONE;
914}
915
916static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
917{
918 if (!resp->mids)
919 return MFX_ERR_NONE;
920
921 av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual]);
922 av_refstruct_unref(&resp->mids[resp->NumFrameActual + 1]);
923 av_freep(&resp->mids);
924 return MFX_ERR_NONE;
925}
926
927static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
928{
930 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
931 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
932 QSVMid *qsv_mid;
933 AVHWFramesContext *hw_frames_ctx;
934 AVQSVFramesContext *hw_frames_hwctx;
935 int ret;
936
937 if (!frames_hwctx->nb_surfaces)
938 return MFX_ERR_UNSUPPORTED;
939
940 qsv_mid = mid;
941 hw_frames_ctx = (AVHWFramesContext*)qsv_mid->hw_frames_ref->data;
942 hw_frames_hwctx = hw_frames_ctx->hwctx;
943 if (qsv_mid->locked_frame)
944 return MFX_ERR_UNDEFINED_BEHAVIOR;
945
946 /* Allocate a system memory frame that will hold the mapped data. */
947 qsv_mid->locked_frame = av_frame_alloc();
948 if (!qsv_mid->locked_frame)
949 return MFX_ERR_MEMORY_ALLOC;
950 qsv_mid->locked_frame->format = hw_frames_ctx->sw_format;
951
952 /* wrap the provided handle in a hwaccel AVFrame */
953 qsv_mid->hw_frame = av_frame_alloc();
954 if (!qsv_mid->hw_frame)
955 goto fail;
956
957 qsv_mid->hw_frame->data[3] = (uint8_t*)&qsv_mid->surf;
958 qsv_mid->hw_frame->format = AV_PIX_FMT_QSV;
959
960 // doesn't really matter what buffer is used here
961 qsv_mid->hw_frame->buf[0] = av_buffer_alloc(1);
962 if (!qsv_mid->hw_frame->buf[0])
963 goto fail;
964
965 qsv_mid->hw_frame->width = hw_frames_ctx->width;
966 qsv_mid->hw_frame->height = hw_frames_ctx->height;
967
969 if (!qsv_mid->hw_frame->hw_frames_ctx)
970 goto fail;
971
972 qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info;
973 qsv_mid->surf.Data.MemId = qsv_mid->handle_pair;
974
975 /* map the data to the system memory */
976 ret = av_hwframe_map(qsv_mid->locked_frame, qsv_mid->hw_frame,
978 if (ret < 0)
979 goto fail;
980
981 ptr->Pitch = qsv_mid->locked_frame->linesize[0];
982 ptr->Y = qsv_mid->locked_frame->data[0];
983 ptr->U = qsv_mid->locked_frame->data[1];
984 ptr->V = qsv_mid->locked_frame->data[1] + 1;
985
986 return MFX_ERR_NONE;
987fail:
988 av_frame_free(&qsv_mid->hw_frame);
989 av_frame_free(&qsv_mid->locked_frame);
990 return MFX_ERR_MEMORY_ALLOC;
991}
992
993static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
994{
996 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
997 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
998 QSVMid *qsv_mid;
999
1000 if (!frames_hwctx->nb_surfaces)
1001 return MFX_ERR_UNSUPPORTED;
1002
1003 qsv_mid = mid;
1004 av_frame_free(&qsv_mid->locked_frame);
1005 av_frame_free(&qsv_mid->hw_frame);
1006
1007 return MFX_ERR_NONE;
1008}
1009
1010static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
1011{
1013 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
1014 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
1015 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
1016 mfxHDLPair *pair_src;
1017
1018 if (frames_hwctx->nb_surfaces) {
1019 QSVMid *qsv_mid = (QSVMid*)mid;
1020 pair_src = (mfxHDLPair*)qsv_mid->handle_pair;
1021 } else {
1022 pair_src = (mfxHDLPair*)mid;
1023 }
1024
1025 pair_dst->first = pair_src->first;
1026
1027 if (pair_src->second != (mfxMemId)MFX_INFINITE)
1028 pair_dst->second = pair_src->second;
1029 return MFX_ERR_NONE;
1030}
1031
1032int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
1033 AVBufferRef *device_ref, const char *load_plugins,
1034 int gpu_copy)
1035{
1036 AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data;
1037 AVQSVDeviceContext *device_hwctx = device_ctx->hwctx;
1038 mfxSession parent_session = device_hwctx->session;
1039 void *loader = device_hwctx->loader;
1040 mfxHDL handle = NULL;
1041 int hw_handle_supported = 0;
1042
1043 mfxSession session;
1044 mfxVersion ver;
1045 mfxIMPL impl;
1046 mfxHandleType handle_type;
1047 mfxStatus err;
1048 int ret;
1049
1050 err = MFXQueryIMPL(parent_session, &impl);
1051 if (err == MFX_ERR_NONE)
1052 err = MFXQueryVersion(parent_session, &ver);
1053 if (err != MFX_ERR_NONE)
1054 return ff_qsv_print_error(avctx, err,
1055 "Error querying the session attributes");
1056
1057 if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
1058 handle_type = MFX_HANDLE_VA_DISPLAY;
1059 hw_handle_supported = 1;
1060 } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
1061 handle_type = MFX_HANDLE_D3D11_DEVICE;
1062 hw_handle_supported = 1;
1063 } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
1064 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
1065 hw_handle_supported = 1;
1066 }
1067
1068 if (hw_handle_supported) {
1069 err = MFXVideoCORE_GetHandle(parent_session, handle_type, &handle);
1070 if (err != MFX_ERR_NONE) {
1071 return ff_qsv_print_error(avctx, err,
1072 "Error getting handle session");
1073 }
1074 }
1075 if (!handle) {
1076 av_log(avctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
1077 "from the session\n");
1078 }
1079
1080 ret = qsv_create_mfx_session(avctx, impl, &ver, gpu_copy, &session,
1081 &loader);
1082 if (ret)
1083 return ret;
1084
1085 if (handle) {
1086 err = MFXVideoCORE_SetHandle(session, handle_type, handle);
1087 if (err != MFX_ERR_NONE)
1088 return ff_qsv_print_error(avctx, err,
1089 "Error setting a HW handle");
1090 }
1091
1092 if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
1093 err = MFXJoinSession(parent_session, session);
1094 if (err != MFX_ERR_NONE)
1095 return ff_qsv_print_error(avctx, err,
1096 "Error joining session");
1097 }
1098
1099 ret = qsv_load_plugins(session, load_plugins, avctx);
1100 if (ret < 0) {
1101 av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
1102 return ret;
1103 }
1104
1105 *psession = session;
1106 return 0;
1107}
1108
1109int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession,
1110 QSVFramesContext *qsv_frames_ctx,
1111 const char *load_plugins, int opaque, int gpu_copy)
1112{
1113 mfxFrameAllocator frame_allocator = {
1114 .pthis = qsv_frames_ctx,
1115 .Alloc = qsv_frame_alloc,
1116 .Lock = qsv_frame_lock,
1117 .Unlock = qsv_frame_unlock,
1118 .GetHDL = qsv_frame_get_hdl,
1119 .Free = qsv_frame_free,
1120 };
1121
1122 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data;
1123 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
1124
1125 mfxSession session;
1126 mfxStatus err;
1127
1128 int ret;
1129
1130 ret = ff_qsv_init_session_device(avctx, &session,
1131 frames_ctx->device_ref, load_plugins, gpu_copy);
1132 if (ret < 0)
1133 return ret;
1134
1135 if (!opaque) {
1136 qsv_frames_ctx->logctx = avctx;
1137 qsv_frames_ctx->mids = NULL;
1138 qsv_frames_ctx->nb_mids = 0;
1139
1140 /* allocate the memory ids for the external frames */
1141 if (frames_hwctx->nb_surfaces) {
1142 av_refstruct_unref(&qsv_frames_ctx->mids);
1143 qsv_frames_ctx->mids = qsv_create_mids(qsv_frames_ctx->hw_frames_ctx);
1144 if (!qsv_frames_ctx->mids)
1145 return AVERROR(ENOMEM);
1146 qsv_frames_ctx->nb_mids = frames_hwctx->nb_surfaces;
1147 }
1148
1149 err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
1150 if (err != MFX_ERR_NONE)
1151 return ff_qsv_print_error(avctx, err,
1152 "Error setting a frame allocator");
1153 }
1154
1155 *psession = session;
1156 return 0;
1157}
1158
1160{
1161 if (qs->session) {
1162 MFXClose(qs->session);
1163 qs->session = NULL;
1164 }
1165
1166 if (qs->loader) {
1167 MFXUnload(qs->loader);
1168 qs->loader = NULL;
1169 }
1170
1171#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
1172 av_buffer_unref(&qs->va_device_ref);
1173#endif
1174 return 0;
1175}
1176
1178 mfxExtBuffer * param)
1179{
1180 int i;
1181
1182 for (i = 0; i < frame->num_ext_params; i++) {
1183 mfxExtBuffer *ext_buffer = frame->ext_param[i];
1184
1185 if (ext_buffer->BufferId == param->BufferId) {
1186 av_log(avctx, AV_LOG_WARNING, "A buffer with the same type has been "
1187 "added\n");
1188 return;
1189 }
1190 }
1191
1192 if (frame->num_ext_params < QSV_MAX_FRAME_EXT_PARAMS) {
1193 frame->ext_param[frame->num_ext_params] = param;
1194 frame->num_ext_params++;
1195 frame->surface.Data.NumExtParam = frame->num_ext_params;
1196 } else {
1197 av_log(avctx, AV_LOG_WARNING, "Ignore this extra buffer because do not "
1198 "have enough space\n");
1199 }
1200
1201
1202}
static const char *const format[]
Definition af_aiir.c:444
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
common internal and external API header
#define NULL
Definition coverity.c:32
AVFieldOrder
Definition defs.h:211
@ AV_FIELD_TT
Top coded_first, top displayed first.
Definition defs.h:214
@ AV_FIELD_BB
Bottom coded first, bottom displayed first.
Definition defs.h:215
@ AV_FIELD_UNKNOWN
Definition defs.h:212
@ AV_FIELD_PROGRESSIVE
Definition defs.h:213
static AVFrame * frame
error code definitions
static CheckasmConfig cfg
Definition checkasm.c:74
#define fail
Definition test.h:479
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition codec_id.h:47
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_VVC
Definition codec_id.h:247
@ AV_CODEC_ID_AV1
Definition codec_id.h:275
@ AV_CODEC_ID_VC1
Definition codec_id.h:120
@ AV_CODEC_ID_VP8
Definition codec_id.h:190
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
@ AV_CODEC_ID_MJPEG
Definition codec_id.h:57
@ AV_CODEC_ID_VP9
Definition codec_id.h:217
@ AV_CODEC_ID_MPEG1VIDEO
Definition codec_id.h:51
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition codec_id.h:52
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition buffer.c:77
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
AVPictureType
Definition avutil.h:276
@ AV_PICTURE_TYPE_I
Intra.
Definition avutil.h:278
@ AV_PICTURE_TYPE_NONE
Undefined.
Definition avutil.h:277
@ AV_PICTURE_TYPE_SP
Switching Predicted.
Definition avutil.h:283
@ AV_PICTURE_TYPE_P
Predicted.
Definition avutil.h:279
@ AV_PICTURE_TYPE_SI
Switching Intra.
Definition avutil.h:282
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition avutil.h:280
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition avstring.c:143
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition hwcontext.c:615
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition hwcontext.c:337
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition hwcontext.c:263
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition hwcontext.c:793
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
Definition hwcontext.h:531
@ AV_HWDEVICE_TYPE_VAAPI
Definition hwcontext.h:31
cl_device_type type
An API-specific header for AV_HWDEVICE_TYPE_QSV.
static int shift(int a, int b)
Definition bonk.c:261
const char * desc
Definition libsvtav1.c:83
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
UID uid
Definition mxfenc.c:2488
int averr
Definition nvenc.c:157
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:545
#define AV_PIX_FMT_P012
Definition pixfmt.h:609
#define AV_PIX_FMT_Y210
Definition pixfmt.h:612
#define AV_PIX_FMT_P010
Definition pixfmt.h:608
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_XV30
Definition pixfmt.h:615
#define AV_PIX_FMT_X2RGB10
Definition pixfmt.h:619
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:96
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_VUYX
packed VUYX 4:4:4:4, 32bpp, Variant of VUYA where alpha channel is left undefined
Definition pixfmt.h:406
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_X2RGB10LE
packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined
Definition pixfmt.h:384
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
@ AV_PIX_FMT_QSV
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition pixfmt.h:247
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition pixfmt.h:85
#define AV_PIX_FMT_Y212
Definition pixfmt.h:613
#define AV_PIX_FMT_XV36
Definition pixfmt.h:616
int ff_qsv_map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface)
Definition qsv.c:287
static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref, QSVMid *mids)
Definition qsv.c:784
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
Definition qsv.c:54
static int qsv_map_error(mfxStatus mfx_err, const char **desc)
Convert a libmfx error code into an FFmpeg error code.
Definition qsv.c:174
enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct)
Definition qsv.c:361
static int qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx)
Definition qsv.c:408
static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition qsv.c:927
#define MFXUnload(a)
Definition qsv.c:51
int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *load_plugins, int gpu_copy)
Definition qsv.c:681
int mfx_iopattern
Definition qsv.c:89
static const struct @263361020336145376152124322306240314177011071374 qsv_iopatterns[]
static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition qsv.c:814
int ff_qsv_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition qsv.c:189
int ff_qsv_close_internal_session(QSVSession *qs)
Definition qsv.c:1159
int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession, QSVFramesContext *qsv_frames_ctx, const char *load_plugins, int opaque, int gpu_copy)
Definition qsv.c:1109
int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern, const char *extra_string)
Definition qsv.c:104
void ff_qsv_frame_add_ext_param(AVCodecContext *avctx, QSVFrame *frame, mfxExtBuffer *param)
Definition qsv.c:1177
static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition qsv.c:1010
static int qsv_create_mfx_session(AVCodecContext *avctx, mfxIMPL implementation, mfxVersion *pver, int gpu_copy, mfxSession *psession, void **ploader)
Definition qsv.c:642
static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition qsv.c:916
static void mids_buf_free(AVRefStructOpaque opaque, void *obj)
Definition qsv.c:748
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins, int gpu_copy)
Definition qsv.c:1032
enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
Definition qsv.c:379
#define MFX_IMPL_VIA_MASK(impl)
Definition qsv.c:40
enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc)
Definition qsv.c:207
static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition qsv.c:993
int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame)
Definition qsv.c:348
int ff_qsv_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
Definition qsv.c:198
static const struct @313360353265145032047314164301105156143154063363 qsv_errors[]
mfxStatus mfxerr
Definition qsv.c:122
static QSVMid * qsv_create_mids(AVBufferRef *hw_frames_ref)
Definition qsv.c:754
int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc, uint16_t *shift)
Definition qsv.c:228
#define QSV_MAX_FRAME_EXT_PARAMS
#define QSV_VERSION_MAJOR
#define QSV_VERSION_MINOR
#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR)
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition refstruct.c:140
static void * av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(AVRefStructOpaque opaque, void *obj))
A wrapper around av_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition refstruct.h:94
#define FF_ARRAY_ELEMS(a)
#define snprintf
Definition snprintf.h:34
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
main external API structure.
Definition avcodec.h:443
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition frame.h:769
int height
Definition frame.h:544
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition frame.h:649
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:559
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition hwcontext.h:88
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition hwcontext.h:129
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition hwcontext.h:153
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int initial_pool_size
Initial size of the frame pool.
Definition hwcontext.h:190
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
This struct is allocated as AVHWDeviceContext.hwctx.
void * loader
The mfxLoader handle used for mfxSession creation.
This struct is allocated as AVHWFramesContext.hwctx.
mfxFrameSurface1 * surfaces
A pointer to a mfxFrameSurface1 struct.
int nb_surfaces
Number of frames in the pool.
int frame_type
A combination of MFX_MEMTYPE_* describing the frame pool.
VAAPI connection details.
VADisplay display
The VADisplay handle, to be filled by the user.
QSVMid * mids
The memory ids for the external frames.
AVBufferRef * hw_frames_ctx
mfxFrameSurface1 surf
AVFrame * locked_frame
AVBufferRef * hw_frames_ref
AVFrame * hw_frame
mfxHDLPair * handle_pair
mfxSession session
void * loader
#define av_freep(p)
#define av_log(a,...)
static AVFormatContext * ctx
Definition movenc.c:49
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
enum AVCodecID codec_id
uint32_t fourcc