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 <mfx/mfxvideo.h>
22 #include <mfx/mfxplugin.h>
23 #include <mfx/mfxjpeg.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/imgutils.h"
34 #include "libavutil/avassert.h"
35 
36 #include "avcodec.h"
37 #include "qsv_internal.h"
38 
39 #if QSV_VERSION_ATLEAST(1, 12)
40 #include "mfx/mfxvp8.h"
41 #endif
42 
44 {
45  switch (codec_id) {
46  case AV_CODEC_ID_H264:
47  return MFX_CODEC_AVC;
48 #if QSV_VERSION_ATLEAST(1, 8)
49  case AV_CODEC_ID_HEVC:
50  return MFX_CODEC_HEVC;
51 #endif
54  return MFX_CODEC_MPEG2;
55  case AV_CODEC_ID_VC1:
56  return MFX_CODEC_VC1;
57 #if QSV_VERSION_ATLEAST(1, 12)
58  case AV_CODEC_ID_VP8:
59  return MFX_CODEC_VP8;
60 #endif
61  case AV_CODEC_ID_MJPEG:
62  return MFX_CODEC_JPEG;
63 #if QSV_VERSION_ATLEAST(1, 19)
64  case AV_CODEC_ID_VP9:
65  return MFX_CODEC_VP9;
66 #endif
67 
68  default:
69  break;
70  }
71 
72  return AVERROR(ENOSYS);
73 }
74 
75 
76 static const struct {
80 } qsv_profile_map[] = {
81 #define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, MFX_PROFILE_ ## v }
82  MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2_SIMPLE ),
83  MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2_MAIN ),
84  MAP(MPEG2VIDEO, MPEG2_HIGH, MPEG2_HIGH ),
85 
86  MAP(H264, H264_BASELINE, AVC_BASELINE ),
87  MAP(H264, H264_CONSTRAINED_BASELINE, AVC_BASELINE),
88 #if QSV_VERSION_ATLEAST(1, 3)
89  MAP(H264, H264_EXTENDED, AVC_EXTENDED ),
90 #endif
91  MAP(H264, H264_MAIN, AVC_MAIN ),
92  MAP(H264, H264_HIGH, AVC_HIGH ),
93  MAP(H264, H264_HIGH_422, AVC_HIGH_422 ),
94 
95 #if QSV_VERSION_ATLEAST(1, 8)
96  MAP(HEVC, HEVC_MAIN, HEVC_MAIN ),
97  MAP(HEVC, HEVC_MAIN_10, HEVC_MAIN10 ),
98  MAP(HEVC, HEVC_MAIN_STILL_PICTURE, HEVC_MAINSP ),
99 #endif
100 #if QSV_VERSION_ATLEAST(1, 16)
101  MAP(HEVC, HEVC_REXT, HEVC_REXT ),
102 #endif
103 
104  MAP(VC1, VC1_SIMPLE, VC1_SIMPLE ),
105  MAP(VC1, VC1_MAIN, VC1_MAIN ),
106  MAP(VC1, VC1_COMPLEX, VC1_ADVANCED ),
107  MAP(VC1, VC1_ADVANCED, VC1_ADVANCED ),
108 #undef MAP
109 };
110 
112 {
113  int i;
114  if (profile == FF_PROFILE_UNKNOWN)
115  return MFX_PROFILE_UNKNOWN;
116 
117  for (i = 0; i < FF_ARRAY_ELEMS(qsv_profile_map); i++) {
118  if (qsv_profile_map[i].codec_id != codec_id)
119  continue;
120  if (qsv_profile_map[i].codec_profile == profile)
121  return qsv_profile_map[i].mfx_profile;
122  }
123 
124  return MFX_PROFILE_UNKNOWN;
125 }
126 
128 {
129  if (level == FF_LEVEL_UNKNOWN)
130  return MFX_LEVEL_UNKNOWN;
131 
132  switch (codec_id) {
133  case AV_CODEC_ID_HEVC:
134  return level / 3;
135  default:
136  return level;
137  }
138 }
139 
140 static const struct {
142  const char *desc;
143 } qsv_iopatterns[] = {
144  {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
145  {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
146  {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
147  {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
148  {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
149  {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
150 };
151 
152 int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern,
153  const char *extra_string)
154 {
155  const char *desc = NULL;
156 
157  for (int i = 0; i < FF_ARRAY_ELEMS(qsv_iopatterns); i++) {
158  if (qsv_iopatterns[i].mfx_iopattern == mfx_iopattern) {
159  desc = qsv_iopatterns[i].desc;
160  }
161  }
162  if (!desc)
163  desc = "unknown iopattern";
164 
165  av_log(log_ctx, AV_LOG_VERBOSE, "%s: %s\n", extra_string, desc);
166  return 0;
167 }
168 
169 static const struct {
170  mfxStatus mfxerr;
171  int averr;
172  const char *desc;
173 } qsv_errors[] = {
174  { MFX_ERR_NONE, 0, "success" },
175  { MFX_ERR_UNKNOWN, AVERROR_UNKNOWN, "unknown error" },
176  { MFX_ERR_NULL_PTR, AVERROR(EINVAL), "NULL pointer" },
177  { MFX_ERR_UNSUPPORTED, AVERROR(ENOSYS), "unsupported" },
178  { MFX_ERR_MEMORY_ALLOC, AVERROR(ENOMEM), "failed to allocate memory" },
179  { MFX_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOMEM), "insufficient input/output buffer" },
180  { MFX_ERR_INVALID_HANDLE, AVERROR(EINVAL), "invalid handle" },
181  { MFX_ERR_LOCK_MEMORY, AVERROR(EIO), "failed to lock the memory block" },
182  { MFX_ERR_NOT_INITIALIZED, AVERROR_BUG, "not initialized" },
183  { MFX_ERR_NOT_FOUND, AVERROR(ENOSYS), "specified object was not found" },
184  /* the following 3 errors should always be handled explicitly, so those "mappings"
185  * are for completeness only */
186  { MFX_ERR_MORE_DATA, AVERROR_UNKNOWN, "expect more data at input" },
187  { MFX_ERR_MORE_SURFACE, AVERROR_UNKNOWN, "expect more surface at output" },
188  { MFX_ERR_MORE_BITSTREAM, AVERROR_UNKNOWN, "expect more bitstream at output" },
189  { MFX_ERR_ABORTED, AVERROR_UNKNOWN, "operation aborted" },
190  { MFX_ERR_DEVICE_LOST, AVERROR(EIO), "device lost" },
191  { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters" },
192  { MFX_ERR_INVALID_VIDEO_PARAM, AVERROR(EINVAL), "invalid video parameters" },
193  { MFX_ERR_UNDEFINED_BEHAVIOR, AVERROR_BUG, "undefined behavior" },
194  { MFX_ERR_DEVICE_FAILED, AVERROR(EIO), "device failed" },
195  { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters" },
196  { MFX_ERR_INVALID_AUDIO_PARAM, AVERROR(EINVAL), "invalid audio parameters" },
197 
198  { MFX_WRN_IN_EXECUTION, 0, "operation in execution" },
199  { MFX_WRN_DEVICE_BUSY, 0, "device busy" },
200  { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" },
201  { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" },
202  { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" },
203  { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" },
204  { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" },
205  { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" },
206  { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
207 };
208 
209 int ff_qsv_map_error(mfxStatus mfx_err, const char **desc)
210 {
211  int i;
212  for (i = 0; i < FF_ARRAY_ELEMS(qsv_errors); i++) {
213  if (qsv_errors[i].mfxerr == mfx_err) {
214  if (desc)
215  *desc = qsv_errors[i].desc;
216  return qsv_errors[i].averr;
217  }
218  }
219  if (desc)
220  *desc = "unknown error";
221  return AVERROR_UNKNOWN;
222 }
223 
224 int ff_qsv_print_error(void *log_ctx, mfxStatus err,
225  const char *error_string)
226 {
227  const char *desc;
228  int ret;
229  ret = ff_qsv_map_error(err, &desc);
230  av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err);
231  return ret;
232 }
233 
234 int ff_qsv_print_warning(void *log_ctx, mfxStatus err,
235  const char *warning_string)
236 {
237  const char *desc;
238  int ret;
239  ret = ff_qsv_map_error(err, &desc);
240  av_log(log_ctx, AV_LOG_WARNING, "%s: %s (%d)\n", warning_string, desc, err);
241  return ret;
242 }
243 
245 {
246  switch (fourcc) {
247  case MFX_FOURCC_NV12: return AV_PIX_FMT_NV12;
248  case MFX_FOURCC_P010: return AV_PIX_FMT_P010;
249  case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8;
250  }
251  return AV_PIX_FMT_NONE;
252 }
253 
255 {
256  switch (format) {
257  case AV_PIX_FMT_YUV420P:
258  case AV_PIX_FMT_YUVJ420P:
259  case AV_PIX_FMT_NV12:
260  *fourcc = MFX_FOURCC_NV12;
261  return AV_PIX_FMT_NV12;
263  case AV_PIX_FMT_P010:
264  *fourcc = MFX_FOURCC_P010;
265  return AV_PIX_FMT_P010;
266  default:
267  return AVERROR(ENOSYS);
268  }
269 }
270 
272 {
273  int i;
274  for (i = 0; i < ctx->nb_mids; i++) {
275  QSVMid *mid = &ctx->mids[i];
276  if (mid->handle == frame->surface.Data.MemId)
277  return i;
278  }
279  return AVERROR_BUG;
280 }
281 
282 enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct)
283 {
285  switch (mfx_pic_struct & 0xF) {
286  case MFX_PICSTRUCT_PROGRESSIVE:
287  field = AV_FIELD_PROGRESSIVE;
288  break;
289  case MFX_PICSTRUCT_FIELD_TFF:
290  field = AV_FIELD_TT;
291  break;
292  case MFX_PICSTRUCT_FIELD_BFF:
293  field = AV_FIELD_BB;
294  break;
295  }
296 
297  return field;
298 }
299 
300 enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
301 {
302  enum AVPictureType type;
303  switch (mfx_pic_type & 0x7) {
304  case MFX_FRAMETYPE_I:
305  if (mfx_pic_type & MFX_FRAMETYPE_S)
306  type = AV_PICTURE_TYPE_SI;
307  else
308  type = AV_PICTURE_TYPE_I;
309  break;
310  case MFX_FRAMETYPE_B:
311  type = AV_PICTURE_TYPE_B;
312  break;
313  case MFX_FRAMETYPE_P:
314  if (mfx_pic_type & MFX_FRAMETYPE_S)
315  type = AV_PICTURE_TYPE_SP;
316  else
317  type = AV_PICTURE_TYPE_P;
318  break;
319  case MFX_FRAMETYPE_UNKNOWN:
320  type = AV_PICTURE_TYPE_NONE;
321  break;
322  default:
323  av_assert0(0);
324  }
325 
326  return type;
327 }
328 
329 static int qsv_load_plugins(mfxSession session, const char *load_plugins,
330  void *logctx)
331 {
332  if (!load_plugins || !*load_plugins)
333  return 0;
334 
335  while (*load_plugins) {
336  mfxPluginUID uid;
337  mfxStatus ret;
338  int i, err = 0;
339 
340  char *plugin = av_get_token(&load_plugins, ":");
341  if (!plugin)
342  return AVERROR(ENOMEM);
343  if (strlen(plugin) != 2 * sizeof(uid.Data)) {
344  av_log(logctx, AV_LOG_ERROR, "Invalid plugin UID length\n");
345  err = AVERROR(EINVAL);
346  goto load_plugin_fail;
347  }
348 
349  for (i = 0; i < sizeof(uid.Data); i++) {
350  err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i);
351  if (err != 1) {
352  av_log(logctx, AV_LOG_ERROR, "Invalid plugin UID\n");
353  err = AVERROR(EINVAL);
354  goto load_plugin_fail;
355  }
356 
357  }
358 
359  ret = MFXVideoUSER_Load(session, &uid, 1);
360  if (ret < 0) {
361  char errorbuf[128];
362  snprintf(errorbuf, sizeof(errorbuf),
363  "Could not load the requested plugin '%s'", plugin);
364  err = ff_qsv_print_error(logctx, ret, errorbuf);
365  goto load_plugin_fail;
366  }
367 
368  if (*load_plugins)
369  load_plugins++;
370 load_plugin_fail:
371  av_freep(&plugin);
372  if (err < 0)
373  return err;
374  }
375 
376  return 0;
377 
378 }
379 
380 //This code is only required for Linux since a display handle is required.
381 //For Windows the session is complete and ready to use.
382 
383 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
384 static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
385 {
386  AVDictionary *child_device_opts = NULL;
387  AVVAAPIDeviceContext *hwctx;
388  int ret;
389 
390  av_dict_set(&child_device_opts, "kernel_driver", "i915", 0);
391  av_dict_set(&child_device_opts, "driver", "iHD", 0);
392 
393  ret = av_hwdevice_ctx_create(&qs->va_device_ref, AV_HWDEVICE_TYPE_VAAPI, NULL, child_device_opts, 0);
394  if (ret < 0) {
395  av_log(avctx, AV_LOG_ERROR, "Failed to create a VAAPI device.\n");
396  return ret;
397  } else {
398  qs->va_device_ctx = (AVHWDeviceContext*)qs->va_device_ref->data;
399  hwctx = qs->va_device_ctx->hwctx;
400 
401  ret = MFXVideoCORE_SetHandle(qs->session,
402  (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->display);
403  if (ret < 0) {
404  return ff_qsv_print_error(avctx, ret, "Error during set display handle\n");
405  }
406  }
407 
408  av_dict_free(&child_device_opts);
409 
410  return 0;
411 }
412 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
413 
415  const char *load_plugins, int gpu_copy)
416 {
417  mfxIMPL impl = MFX_IMPL_AUTO_ANY;
418  mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
419  mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
420 
421  const char *desc;
422  int ret;
423 
424 #if QSV_VERSION_ATLEAST(1, 16)
425  init_par.GPUCopy = gpu_copy;
426 #endif
427  init_par.Implementation = impl;
428  init_par.Version = ver;
429  ret = MFXInitEx(init_par, &qs->session);
430  if (ret < 0)
431  return ff_qsv_print_error(avctx, ret,
432  "Error initializing an internal MFX session");
433 
434 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
435  ret = ff_qsv_set_display_handle(avctx, qs);
436  if (ret < 0)
437  return ret;
438 #endif
439 
440  ret = qsv_load_plugins(qs->session, load_plugins, avctx);
441  if (ret < 0) {
442  av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
443  return ret;
444  }
445 
446  MFXQueryIMPL(qs->session, &impl);
447 
448  switch (MFX_IMPL_BASETYPE(impl)) {
449  case MFX_IMPL_SOFTWARE:
450  desc = "software";
451  break;
452  case MFX_IMPL_HARDWARE:
453  case MFX_IMPL_HARDWARE2:
454  case MFX_IMPL_HARDWARE3:
455  case MFX_IMPL_HARDWARE4:
456  desc = "hardware accelerated";
457  break;
458  default:
459  desc = "unknown";
460  }
461 
462  av_log(avctx, AV_LOG_VERBOSE,
463  "Initialized an internal MFX session using %s implementation\n",
464  desc);
465 
466  return 0;
467 }
468 
469 static void mids_buf_free(void *opaque, uint8_t *data)
470 {
471  AVBufferRef *hw_frames_ref = opaque;
472  av_buffer_unref(&hw_frames_ref);
473  av_freep(&data);
474 }
475 
476 static AVBufferRef *qsv_create_mids(AVBufferRef *hw_frames_ref)
477 {
478  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data;
479  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
480  int nb_surfaces = frames_hwctx->nb_surfaces;
481 
482  AVBufferRef *mids_buf, *hw_frames_ref1;
483  QSVMid *mids;
484  int i;
485 
486  hw_frames_ref1 = av_buffer_ref(hw_frames_ref);
487  if (!hw_frames_ref1)
488  return NULL;
489 
490  mids = av_mallocz_array(nb_surfaces, sizeof(*mids));
491  if (!mids) {
492  av_buffer_unref(&hw_frames_ref1);
493  return NULL;
494  }
495 
496  mids_buf = av_buffer_create((uint8_t*)mids, nb_surfaces * sizeof(*mids),
497  mids_buf_free, hw_frames_ref1, 0);
498  if (!mids_buf) {
499  av_buffer_unref(&hw_frames_ref1);
500  av_freep(&mids);
501  return NULL;
502  }
503 
504  for (i = 0; i < nb_surfaces; i++) {
505  QSVMid *mid = &mids[i];
506  mid->handle = frames_hwctx->surfaces[i].Data.MemId;
507  mid->hw_frames_ref = hw_frames_ref1;
508  }
509 
510  return mids_buf;
511 }
512 
513 static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref,
514  AVBufferRef *mids_buf)
515 {
516  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data;
517  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
518  QSVMid *mids = (QSVMid*)mids_buf->data;
519  int nb_surfaces = frames_hwctx->nb_surfaces;
520  int i;
521 
522  // the allocated size of the array is two larger than the number of
523  // surfaces, we store the references to the frames context and the
524  // QSVMid array there
525  resp->mids = av_mallocz_array(nb_surfaces + 2, sizeof(*resp->mids));
526  if (!resp->mids)
527  return AVERROR(ENOMEM);
528 
529  for (i = 0; i < nb_surfaces; i++)
530  resp->mids[i] = &mids[i];
531  resp->NumFrameActual = nb_surfaces;
532 
533  resp->mids[resp->NumFrameActual] = (mfxMemId)av_buffer_ref(hw_frames_ref);
534  if (!resp->mids[resp->NumFrameActual]) {
535  av_freep(&resp->mids);
536  return AVERROR(ENOMEM);
537  }
538 
539  resp->mids[resp->NumFrameActual + 1] = av_buffer_ref(mids_buf);
540  if (!resp->mids[resp->NumFrameActual + 1]) {
541  av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual]);
542  av_freep(&resp->mids);
543  return AVERROR(ENOMEM);
544  }
545 
546  return 0;
547 }
548 
549 static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
550  mfxFrameAllocResponse *resp)
551 {
552  QSVFramesContext *ctx = pthis;
553  int ret;
554 
555  /* this should only be called from an encoder or decoder and
556  * only allocates video memory frames */
557  if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
558  MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ||
559  !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
560  return MFX_ERR_UNSUPPORTED;
561 
562  if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
563  /* external frames -- fill from the caller-supplied frames context */
565  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
566  mfxFrameInfo *i = &req->Info;
567  mfxFrameInfo *i1 = &frames_hwctx->surfaces[0].Info;
568 
569  if (i->Width > i1->Width || i->Height > i1->Height ||
570  i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) {
571  av_log(ctx->logctx, AV_LOG_ERROR, "Mismatching surface properties in an "
572  "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
573  i->Width, i->Height, i->FourCC, i->ChromaFormat,
574  i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
575  return MFX_ERR_UNSUPPORTED;
576  }
577 
578  ret = qsv_setup_mids(resp, ctx->hw_frames_ctx, ctx->mids_buf);
579  if (ret < 0) {
580  av_log(ctx->logctx, AV_LOG_ERROR,
581  "Error filling an external frame allocation request\n");
582  return MFX_ERR_MEMORY_ALLOC;
583  }
584  } else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
585  /* internal frames -- allocate a new hw frames context */
586  AVHWFramesContext *ext_frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
587  mfxFrameInfo *i = &req->Info;
588 
589  AVBufferRef *frames_ref, *mids_buf;
590  AVHWFramesContext *frames_ctx;
591  AVQSVFramesContext *frames_hwctx;
592 
593  frames_ref = av_hwframe_ctx_alloc(ext_frames_ctx->device_ref);
594  if (!frames_ref)
595  return MFX_ERR_MEMORY_ALLOC;
596 
597  frames_ctx = (AVHWFramesContext*)frames_ref->data;
598  frames_hwctx = frames_ctx->hwctx;
599 
600  frames_ctx->format = AV_PIX_FMT_QSV;
601  frames_ctx->sw_format = ff_qsv_map_fourcc(i->FourCC);
602  frames_ctx->width = i->Width;
603  frames_ctx->height = i->Height;
604  frames_ctx->initial_pool_size = req->NumFrameSuggested;
605 
606  frames_hwctx->frame_type = req->Type;
607 
608  ret = av_hwframe_ctx_init(frames_ref);
609  if (ret < 0) {
610  av_log(ctx->logctx, AV_LOG_ERROR,
611  "Error initializing a frames context for an internal frame "
612  "allocation request\n");
613  av_buffer_unref(&frames_ref);
614  return MFX_ERR_MEMORY_ALLOC;
615  }
616 
617  mids_buf = qsv_create_mids(frames_ref);
618  if (!mids_buf) {
619  av_buffer_unref(&frames_ref);
620  return MFX_ERR_MEMORY_ALLOC;
621  }
622 
623  ret = qsv_setup_mids(resp, frames_ref, mids_buf);
624  av_buffer_unref(&mids_buf);
625  av_buffer_unref(&frames_ref);
626  if (ret < 0) {
627  av_log(ctx->logctx, AV_LOG_ERROR,
628  "Error filling an internal frame allocation request\n");
629  return MFX_ERR_MEMORY_ALLOC;
630  }
631  } else {
632  return MFX_ERR_UNSUPPORTED;
633  }
634 
635  return MFX_ERR_NONE;
636 }
637 
638 static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
639 {
640  av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual]);
641  av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual + 1]);
642  av_freep(&resp->mids);
643  return MFX_ERR_NONE;
644 }
645 
646 static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
647 {
648  QSVMid *qsv_mid = mid;
649  AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)qsv_mid->hw_frames_ref->data;
650  AVQSVFramesContext *hw_frames_hwctx = hw_frames_ctx->hwctx;
651  int ret;
652 
653  if (qsv_mid->locked_frame)
654  return MFX_ERR_UNDEFINED_BEHAVIOR;
655 
656  /* Allocate a system memory frame that will hold the mapped data. */
657  qsv_mid->locked_frame = av_frame_alloc();
658  if (!qsv_mid->locked_frame)
659  return MFX_ERR_MEMORY_ALLOC;
660  qsv_mid->locked_frame->format = hw_frames_ctx->sw_format;
661 
662  /* wrap the provided handle in a hwaccel AVFrame */
663  qsv_mid->hw_frame = av_frame_alloc();
664  if (!qsv_mid->hw_frame)
665  goto fail;
666 
667  qsv_mid->hw_frame->data[3] = (uint8_t*)&qsv_mid->surf;
668  qsv_mid->hw_frame->format = AV_PIX_FMT_QSV;
669 
670  // doesn't really matter what buffer is used here
671  qsv_mid->hw_frame->buf[0] = av_buffer_alloc(1);
672  if (!qsv_mid->hw_frame->buf[0])
673  goto fail;
674 
675  qsv_mid->hw_frame->width = hw_frames_ctx->width;
676  qsv_mid->hw_frame->height = hw_frames_ctx->height;
677 
678  qsv_mid->hw_frame->hw_frames_ctx = av_buffer_ref(qsv_mid->hw_frames_ref);
679  if (!qsv_mid->hw_frame->hw_frames_ctx)
680  goto fail;
681 
682  qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info;
683  qsv_mid->surf.Data.MemId = qsv_mid->handle;
684 
685  /* map the data to the system memory */
686  ret = av_hwframe_map(qsv_mid->locked_frame, qsv_mid->hw_frame,
688  if (ret < 0)
689  goto fail;
690 
691  ptr->Pitch = qsv_mid->locked_frame->linesize[0];
692  ptr->Y = qsv_mid->locked_frame->data[0];
693  ptr->U = qsv_mid->locked_frame->data[1];
694  ptr->V = qsv_mid->locked_frame->data[1] + 1;
695 
696  return MFX_ERR_NONE;
697 fail:
698  av_frame_free(&qsv_mid->hw_frame);
699  av_frame_free(&qsv_mid->locked_frame);
700  return MFX_ERR_MEMORY_ALLOC;
701 }
702 
703 static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
704 {
705  QSVMid *qsv_mid = mid;
706 
707  av_frame_free(&qsv_mid->locked_frame);
708  av_frame_free(&qsv_mid->hw_frame);
709 
710  return MFX_ERR_NONE;
711 }
712 
713 static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
714 {
715  QSVMid *qsv_mid = (QSVMid*)mid;
716  *hdl = qsv_mid->handle;
717  return MFX_ERR_NONE;
718 }
719 
720 int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
721  AVBufferRef *device_ref, const char *load_plugins,
722  int gpu_copy)
723 {
724  static const mfxHandleType handle_types[] = {
725  MFX_HANDLE_VA_DISPLAY,
726  MFX_HANDLE_D3D9_DEVICE_MANAGER,
727  MFX_HANDLE_D3D11_DEVICE,
728  };
729  AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data;
730  AVQSVDeviceContext *device_hwctx = device_ctx->hwctx;
731  mfxSession parent_session = device_hwctx->session;
732  mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
733  mfxHDL handle = NULL;
734 
735  mfxSession session;
736  mfxVersion ver;
737  mfxIMPL impl;
738  mfxHandleType handle_type;
739  mfxStatus err;
740 
741  int i, ret;
742 
743  err = MFXQueryIMPL(parent_session, &impl);
744  if (err == MFX_ERR_NONE)
745  err = MFXQueryVersion(parent_session, &ver);
746  if (err != MFX_ERR_NONE)
747  return ff_qsv_print_error(avctx, err,
748  "Error querying the session attributes");
749 
750  for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) {
751  err = MFXVideoCORE_GetHandle(parent_session, handle_types[i], &handle);
752  if (err == MFX_ERR_NONE) {
754  break;
755  }
756  handle = NULL;
757  }
758  if (!handle) {
759  av_log(avctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
760  "from the session\n");
761  }
762 
763 #if QSV_VERSION_ATLEAST(1, 16)
764  init_par.GPUCopy = gpu_copy;
765 #endif
766  init_par.Implementation = impl;
767  init_par.Version = ver;
768  err = MFXInitEx(init_par, &session);
769  if (err != MFX_ERR_NONE)
770  return ff_qsv_print_error(avctx, err,
771  "Error initializing a child MFX session");
772 
773  if (handle) {
774  err = MFXVideoCORE_SetHandle(session, handle_type, handle);
775  if (err != MFX_ERR_NONE)
776  return ff_qsv_print_error(avctx, err,
777  "Error setting a HW handle");
778  }
779 
780  if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
781  err = MFXJoinSession(parent_session, session);
782  if (err != MFX_ERR_NONE)
783  return ff_qsv_print_error(avctx, err,
784  "Error joining session");
785  }
786 
787  ret = qsv_load_plugins(session, load_plugins, avctx);
788  if (ret < 0) {
789  av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
790  return ret;
791  }
792 
793  *psession = session;
794  return 0;
795 }
796 
797 int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession,
798  QSVFramesContext *qsv_frames_ctx,
799  const char *load_plugins, int opaque, int gpu_copy)
800 {
801  mfxFrameAllocator frame_allocator = {
802  .pthis = qsv_frames_ctx,
803  .Alloc = qsv_frame_alloc,
804  .Lock = qsv_frame_lock,
805  .Unlock = qsv_frame_unlock,
806  .GetHDL = qsv_frame_get_hdl,
807  .Free = qsv_frame_free,
808  };
809 
810  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data;
811  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
812 
813  mfxSession session;
814  mfxStatus err;
815 
816  int ret;
817 
818  ret = ff_qsv_init_session_device(avctx, &session,
819  frames_ctx->device_ref, load_plugins, gpu_copy);
820  if (ret < 0)
821  return ret;
822 
823  if (!opaque) {
824  qsv_frames_ctx->logctx = avctx;
825 
826  /* allocate the memory ids for the external frames */
827  av_buffer_unref(&qsv_frames_ctx->mids_buf);
828  qsv_frames_ctx->mids_buf = qsv_create_mids(qsv_frames_ctx->hw_frames_ctx);
829  if (!qsv_frames_ctx->mids_buf)
830  return AVERROR(ENOMEM);
831  qsv_frames_ctx->mids = (QSVMid*)qsv_frames_ctx->mids_buf->data;
832  qsv_frames_ctx->nb_mids = frames_hwctx->nb_surfaces;
833 
834  err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
835  if (err != MFX_ERR_NONE)
836  return ff_qsv_print_error(avctx, err,
837  "Error setting a frame allocator");
838  }
839 
840  *psession = session;
841  return 0;
842 }
843 
845 {
846  if (qs->session) {
847  MFXClose(qs->session);
848  qs->session = NULL;
849  }
850 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
851  av_buffer_unref(&qs->va_device_ref);
852 #endif
853  return 0;
854 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
#define NULL
Definition: coverity.c:32
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:125
static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition: qsv.c:549
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static const mfxHandleType handle_types[]
Definition: qsvvpp.c:71
static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsv.c:703
misc image utilities
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
mfxHandleType handle_type
Definition: hwcontext_qsv.c:85
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:486
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_qsv.h:42
uint32_t fourcc
Definition: vaapi_decode.c:238
enum AVCodecID codec_id
Definition: qsv.c:77
static int qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx)
Definition: qsv.c:329
int ff_qsv_level_to_mfx(enum AVCodecID codec_id, int level)
Definition: qsv.c:127
int averr
Definition: qsv.c:171
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR)
Definition: qsv_internal.h:57
GLint GLenum type
Definition: opengl_enc.c:104
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins, int gpu_copy)
Definition: qsv.c:720
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
AVFrame * locked_frame
Definition: qsv_internal.h:65
AVBufferRef * hw_frames_ctx
Definition: qsv_internal.h:92
int ff_qsv_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition: qsv.c:224
Undefined.
Definition: avutil.h:273
Switching Intra.
Definition: avutil.h:278
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:634
UID uid
Definition: mxfenc.c:2222
#define FF_LEVEL_UNKNOWN
Definition: avcodec.h:3022
#define AV_PIX_FMT_P010
Definition: pixfmt.h:436
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
#define MAP(c, p, v)
uint8_t
AVFrame * hw_frame
Definition: qsv_internal.h:66
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
AVBufferRef * mids_buf
Definition: qsv_internal.h:99
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
static void mids_buf_free(void *opaque, uint8_t *data)
Definition: qsv.c:469
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
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:571
int mfx_iopattern
Definition: qsv.c:141
static const struct @135 qsv_errors[]
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
int ff_qsv_map_error(mfxStatus mfx_err, const char **desc)
Convert a libmfx error code into an ffmpeg error code.
Definition: qsv.c:209
#define av_log(a,...)
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_qsv.h:35
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:797
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
int width
Definition: frame.h:353
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame)
Definition: qsv.c:271
error code definitions
The mapping must be direct.
Definition: hwcontext.h:519
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
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
static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition: qsv.c:638
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
mfxHDL handle
Definition: qsv_internal.h:63
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:89
int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern, const char *extra_string)
Definition: qsv.c:152
simple assert() macros that are a bit more flexible than ISO C assert().
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:28
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:329
int ff_qsv_close_internal_session(QSVSession *qs)
Definition: qsv.c:844
enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
Definition: qsv.c:300
#define fail()
Definition: checkasm.h:122
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:149
int ff_qsv_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
Definition: qsv.c:234
static const struct @133 qsv_profile_map[]
int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc)
Definition: qsv.c:254
int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile)
Definition: qsv.c:111
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
#define QSV_VERSION_MINOR
Definition: qsv_internal.h:47
#define FF_PROFILE_UNKNOWN
Definition: avcodec.h:2902
const char * desc
Definition: qsv.c:142
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
Definition: qsv.c:43
static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition: qsv.c:713
AVFormatContext * ctx
Definition: movenc.c:48
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
mfxFrameSurface1 surface
Definition: qsv_internal.h:72
preferred ID for MPEG-1/2 video decoding
Definition: avcodec.h:220
#define FF_ARRAY_ELEMS(a)
if(ret)
VADisplay display
The VADisplay handle, to be filled by the user.
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
Libavcodec external API header.
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
main external API structure.
Definition: avcodec.h:1568
uint8_t * data
The data buffer.
Definition: buffer.h:89
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:161
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:70
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:387
Switching Predicted.
Definition: avutil.h:279
AVBufferRef * hw_frames_ref
Definition: qsv_internal.h:62
AVFieldOrder
Definition: avcodec.h:1546
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:222
int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *load_plugins, int gpu_copy)
Definition: qsv.c:414
AVPictureType
Definition: avutil.h:272
#define snprintf
Definition: snprintf.h:34
static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref, AVBufferRef *mids_buf)
Definition: qsv.c:513
static const struct @134 qsv_iopatterns[]
mfxU16 profile
Definition: qsvenc.c:44
static AVBufferRef * qsv_create_mids(AVBufferRef *hw_frames_ref)
Definition: qsv.c:476
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
uint8_t level
Definition: svq3.c:207
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:140
mfxStatus mfxerr
Definition: qsv.c:170
A reference to a data buffer.
Definition: buffer.h:81
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
common internal and external API header
static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsv.c:646
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:740
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:243
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
mfxFrameSurface1 surf
Definition: qsv_internal.h:67
Bi-dir predicted.
Definition: avutil.h:276
#define QSV_VERSION_MAJOR
Definition: qsv_internal.h:46
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
VAAPI connection details.
int height
Definition: frame.h:353
int codec_profile
Definition: qsv.c:78
enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct)
Definition: qsv.c:282
#define av_freep(p)
An API-specific header for AV_HWDEVICE_TYPE_QSV.
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
int mfx_profile
Definition: qsv.c:79
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:221
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
mfxSession session
Definition: qsv_internal.h:84
Predicted.
Definition: avutil.h:275
enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc)
Definition: qsv.c:244
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191