FFmpeg
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 "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) {
57  case AV_CODEC_ID_H264:
58  return MFX_CODEC_AVC;
59  case AV_CODEC_ID_HEVC:
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;
68  case AV_CODEC_ID_MJPEG:
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 
88 static 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
102 };
103 
104 int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern,
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 
121 static 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
169 };
170 
171 /**
172  * Convert a libmfx error code into an FFmpeg error code.
173  */
174 static 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 
189 int 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 
198 int 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 
228 int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc, uint16_t *shift)
229 {
230  switch (format) {
231  case AV_PIX_FMT_YUV420P:
232  case AV_PIX_FMT_YUVJ420P:
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;
242  case AV_PIX_FMT_X2RGB10:
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;
250  case AV_PIX_FMT_YUV422P:
251  case AV_PIX_FMT_YUYV422:
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 
287 int 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;
305  case AV_PIX_FMT_YUYV422:
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 
361 enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct)
362 {
364  switch (mfx_pic_struct & 0xF) {
365  case MFX_PICSTRUCT_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 
379 enum 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 
408 static 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++;
450 load_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
465 static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
466 {
467  AVDictionary *child_device_opts = NULL;
468  AVVAAPIDeviceContext *hwctx;
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
495 static 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 
544 fail:
545  if (loader)
546  MFXUnload(loader);
547 
548  *ploader = NULL;
549  return AVERROR_UNKNOWN;
550 }
551 
552 static 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 
590 fail:
591  if (session)
592  MFXClose(session);
593 
594  *psession = NULL;
595  return AVERROR_UNKNOWN;
596 }
597 
598 static 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 
633 fail:
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 
748 static void mids_buf_free(FFRefStructOpaque opaque, void *obj)
749 {
750  AVBufferRef *hw_frames_ref = opaque.nc;
751  av_buffer_unref(&hw_frames_ref);
752 }
753 
754 static 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 = ff_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 
784 static 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] = ff_refstruct_ref(mids);
810 
811  return 0;
812 }
813 
814 static 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  ff_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 
916 static 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  ff_refstruct_unref(&resp->mids[resp->NumFrameActual + 1]);
923  av_freep(&resp->mids);
924  return MFX_ERR_NONE;
925 }
926 
927 static 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 
968  qsv_mid->hw_frame->hw_frames_ctx = av_buffer_ref(qsv_mid->hw_frames_ref);
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;
987 fail:
988  av_frame_free(&qsv_mid->hw_frame);
989  av_frame_free(&qsv_mid->locked_frame);
990  return MFX_ERR_MEMORY_ALLOC;
991 }
992 
993 static 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 
1010 static 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 
1032 int 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 
1109 int 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  ff_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 }
QSV_MAX_FRAME_EXT_PARAMS
#define QSV_MAX_FRAME_EXT_PARAMS
Definition: qsv_internal.h:57
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:85
qsv_frame_unlock
static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsv.c:993
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
QSVFramesContext::nb_mids
int nb_mids
Definition: qsv_internal.h:125
ff_refstruct_ref
void * ff_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition: refstruct.c:140
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
uid
UID uid
Definition: mxfenc.c:2428
QSV_VERSION_MAJOR
#define QSV_VERSION_MAJOR
Definition: qsv_internal.h:47
QSVFramesContext::hw_frames_ctx
AVBufferRef * hw_frames_ctx
Definition: qsv_internal.h:115
AVFieldOrder
AVFieldOrder
Definition: defs.h:200
averr
int averr
Definition: qsv.c:123
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AV_FIELD_PROGRESSIVE
@ AV_FIELD_PROGRESSIVE
Definition: defs.h:202
AVPictureType
AVPictureType
Definition: avutil.h:277
ff_refstruct_alloc_ext
static void * ff_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(FFRefStructOpaque opaque, void *obj))
A wrapper around ff_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition: refstruct.h:94
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:322
ff_qsv_close_internal_session
int ff_qsv_close_internal_session(QSVSession *qs)
Definition: qsv.c:1159
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
ff_qsv_map_pictype
enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
Definition: qsv.c:379
AVQSVDeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_qsv.h:35
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:248
av_hwframe_map
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:778
ff_qsv_find_surface_idx
int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame)
Definition: qsv.c:348
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:502
AV_PIX_FMT_XV30
#define AV_PIX_FMT_XV30
Definition: pixfmt.h:559
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
AVVAAPIDeviceContext::display
VADisplay display
The VADisplay handle, to be filled by the user.
Definition: hwcontext_vaapi.h:72
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
AVDictionary
Definition: dict.c:34
FFRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
mids_buf_free
static void mids_buf_free(FFRefStructOpaque opaque, void *obj)
Definition: qsv.c:748
ff_qsv_init_session_device
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins, int gpu_copy)
Definition: qsv.c:1032
AV_HWFRAME_MAP_DIRECT
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
Definition: hwcontext.h:528
AV_FIELD_TT
@ AV_FIELD_TT
Top coded_first, top displayed first.
Definition: defs.h:203
ff_qsv_map_frame_to_surface
int ff_qsv_map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface)
Definition: qsv.c:287
fail
#define fail()
Definition: checkasm.h:189
MFXUnload
#define MFXUnload(a)
Definition: qsv.c:51
qsv_load_plugins
static int qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx)
Definition: qsv.c:408
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
refstruct.h
desc
const char * desc
Definition: qsv.c:90
qsv_internal.h
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:150
AV_PIX_FMT_Y210
#define AV_PIX_FMT_Y210
Definition: pixfmt.h:556
qsv_setup_mids
static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref, QSVMid *mids)
Definition: qsv.c:784
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
ff_qsv_print_warning
int ff_qsv_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
Definition: qsv.c:198
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
qsv_errors
static const struct @199 qsv_errors[]
AV_FIELD_UNKNOWN
@ AV_FIELD_UNKNOWN
Definition: defs.h:201
QSV_VERSION_MINOR
#define QSV_VERSION_MINOR
Definition: qsv_internal.h:48
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
AV_CODEC_ID_VP9
@ AV_CODEC_ID_VP9
Definition: codec_id.h:222
QSV_RUNTIME_VERSION_ATLEAST
#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR)
Definition: qsv_internal.h:63
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
ctx
AVFormatContext * ctx
Definition: movenc.c:49
field
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this field
Definition: writing_filters.txt:78
codec_id
enum AVCodecID codec_id
Definition: vaapi_decode.c:410
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
if
if(ret)
Definition: filter_design.txt:179
ff_qsv_init_session_frames
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
QSVFrame
Definition: qsv_internal.h:79
NULL
#define NULL
Definition: coverity.c:32
av_buffer_unref
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
AV_CODEC_ID_AV1
@ AV_CODEC_ID_AV1
Definition: codec_id.h:284
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
AVHWFramesContext::device_ref
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:126
AV_PIX_FMT_YUVJ420P
@ 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
AV_PICTURE_TYPE_SI
@ AV_PICTURE_TYPE_SI
Switching Intra.
Definition: avutil.h:283
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:279
ff_qsv_print_iopattern
int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern, const char *extra_string)
Definition: qsv.c:104
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:503
AV_PIX_FMT_QSV
@ AV_PIX_FMT_QSV
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:247
AV_PICTURE_TYPE_SP
@ AV_PICTURE_TYPE_SP
Switching Predicted.
Definition: avutil.h:284
AV_CODEC_ID_MPEG1VIDEO
@ AV_CODEC_ID_MPEG1VIDEO
Definition: codec_id.h:53
error.h
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
AV_PIX_FMT_X2RGB10LE
@ 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
mfxerr
mfxStatus mfxerr
Definition: qsv.c:122
AV_PIX_FMT_P012
#define AV_PIX_FMT_P012
Definition: pixfmt.h:553
shift
static int shift(int a, int b)
Definition: bonk.c:261
QSVMid::hw_frames_ref
AVBufferRef * hw_frames_ref
Definition: qsv_internal.h:71
FFRefStructOpaque::nc
void * nc
Definition: refstruct.h:59
AV_PICTURE_TYPE_NONE
@ AV_PICTURE_TYPE_NONE
Undefined.
Definition: avutil.h:278
AV_PIX_FMT_Y212
#define AV_PIX_FMT_Y212
Definition: pixfmt.h:557
AV_CODEC_ID_VVC
@ AV_CODEC_ID_VVC
Definition: codec_id.h:252
mfx_iopattern
int mfx_iopattern
Definition: qsv.c:89
QSVMid::handle_pair
mfxHDLPair * handle_pair
Definition: qsv_internal.h:72
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:223
av_buffer_alloc
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:77
QSVFramesContext::mids
QSVMid * mids
The memory ids for the external frames.
Definition: qsv_internal.h:124
AV_HWDEVICE_TYPE_VAAPI
@ AV_HWDEVICE_TYPE_VAAPI
Definition: hwcontext.h:31
AV_CODEC_ID_MJPEG
@ AV_CODEC_ID_MJPEG
Definition: codec_id.h:59
hwcontext_qsv.h
ff_qsv_map_pixfmt
int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc, uint16_t *shift)
Definition: qsv.c:228
ff_qsv_map_picstruct
enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct)
Definition: qsv.c:361
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AV_FIELD_BB
@ AV_FIELD_BB
Bottom coded first, bottom displayed first.
Definition: defs.h:204
common.h
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:228
AV_PIX_FMT_X2RGB10
#define AV_PIX_FMT_X2RGB10
Definition: pixfmt.h:563
AV_CODEC_ID_VC1
@ AV_CODEC_ID_VC1
Definition: codec_id.h:122
qsv_map_error
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
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
avcodec.h
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:115
qsv_frame_free
static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition: qsv.c:916
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_NV12
@ 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
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
QSVSession
Definition: qsv_internal.h:105
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
ff_qsv_codec_id_to_mfx
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
Definition: qsv.c:54
qsv_frame_get_hdl
static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition: qsv.c:1010
av_hwdevice_ctx_create
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:600
AVCodecContext
main external API structure.
Definition: avcodec.h:451
qsv_frame_alloc
static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition: qsv.c:814
AV_PICTURE_TYPE_B
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition: avutil.h:281
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
av_get_token
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
qsv_create_mfx_session
static int qsv_create_mfx_session(AVCodecContext *avctx, mfxIMPL implementation, mfxVersion *pver, int gpu_copy, mfxSession *psession, void **ploader)
Definition: qsv.c:642
MFX_IMPL_VIA_MASK
#define MFX_IMPL_VIA_MASK(impl)
Definition: qsv.c:40
QSVSession::session
mfxSession session
Definition: qsv_internal.h:106
ff_qsv_map_fourcc
enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc)
Definition: qsv.c:207
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:552
AVQSVFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_qsv.h:53
qsv_iopatterns
static const struct @198 qsv_iopatterns[]
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:280
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
QSVFramesContext::logctx
void * logctx
Definition: qsv_internal.h:116
QSVFramesContext
Definition: qsv_internal.h:114
qsv_create_mids
static QSVMid * qsv_create_mids(AVBufferRef *hw_frames_ref)
Definition: qsv.c:754
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_set
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:88
AV_PIX_FMT_XV36
#define AV_PIX_FMT_XV36
Definition: pixfmt.h:560
AV_CODEC_ID_VP8
@ AV_CODEC_ID_VP8
Definition: codec_id.h:192
hwcontext.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVVAAPIDeviceContext
VAAPI connection details.
Definition: hwcontext_vaapi.h:68
avstring.h
AV_PIX_FMT_VUYX
@ AV_PIX_FMT_VUYX
packed VUYX 4:4:4:4, 32bpp, Variant of VUYA where alpha channel is left undefined
Definition: pixfmt.h:406
QSVSession::loader
void * loader
Definition: qsv_internal.h:111
ff_qsv_frame_add_ext_param
void ff_qsv_frame_add_ext_param(AVCodecContext *avctx, QSVFrame *frame, mfxExtBuffer *param)
Definition: qsv.c:1177
AV_CODEC_ID_MPEG2VIDEO
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition: codec_id.h:54
QSVMid
Definition: qsv_internal.h:70
ff_qsv_print_error
int ff_qsv_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition: qsv.c:189
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:263
ff_qsv_init_internal_session
int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *load_plugins, int gpu_copy)
Definition: qsv.c:681
snprintf
#define snprintf
Definition: snprintf.h:34
qsv_frame_lock
static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsv.c:927
ff_refstruct_unref
void ff_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition: refstruct.c:120