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