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  default:
64  break;
65  }
66 
67  return AVERROR(ENOSYS);
68 }
69 
70 
71 static const struct {
75 } qsv_profile_map[] = {
76 #define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, MFX_PROFILE_ ## v }
77  MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2_SIMPLE ),
78  MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2_MAIN ),
79  MAP(MPEG2VIDEO, MPEG2_HIGH, MPEG2_HIGH ),
80 
81  MAP(H264, H264_BASELINE, AVC_BASELINE ),
82  MAP(H264, H264_CONSTRAINED_BASELINE, AVC_BASELINE),
83 #if QSV_VERSION_ATLEAST(1, 3)
84  MAP(H264, H264_EXTENDED, AVC_EXTENDED ),
85 #endif
86  MAP(H264, H264_MAIN, AVC_MAIN ),
87  MAP(H264, H264_HIGH, AVC_HIGH ),
88  MAP(H264, H264_HIGH_422, AVC_HIGH_422 ),
89 
90 #if QSV_VERSION_ATLEAST(1, 8)
91  MAP(HEVC, HEVC_MAIN, HEVC_MAIN ),
92  MAP(HEVC, HEVC_MAIN_10, HEVC_MAIN10 ),
93  MAP(HEVC, HEVC_MAIN_STILL_PICTURE, HEVC_MAINSP ),
94 #endif
95 #if QSV_VERSION_ATLEAST(1, 16)
96  MAP(HEVC, HEVC_REXT, HEVC_REXT ),
97 #endif
98 
99  MAP(VC1, VC1_SIMPLE, VC1_SIMPLE ),
100  MAP(VC1, VC1_MAIN, VC1_MAIN ),
101  MAP(VC1, VC1_COMPLEX, VC1_ADVANCED ),
102  MAP(VC1, VC1_ADVANCED, VC1_ADVANCED ),
103 #undef MAP
104 };
105 
107 {
108  int i;
109  if (profile == FF_PROFILE_UNKNOWN)
110  return MFX_PROFILE_UNKNOWN;
111 
112  for (i = 0; i < FF_ARRAY_ELEMS(qsv_profile_map); i++) {
113  if (qsv_profile_map[i].codec_id != codec_id)
114  continue;
115  if (qsv_profile_map[i].codec_profile == profile)
116  return qsv_profile_map[i].mfx_profile;
117  }
118 
119  return MFX_PROFILE_UNKNOWN;
120 }
121 
123 {
124  if (level == FF_LEVEL_UNKNOWN)
125  return MFX_LEVEL_UNKNOWN;
126 
127  switch (codec_id) {
128  case AV_CODEC_ID_HEVC:
129  return level / 3;
130  default:
131  return level;
132  }
133 }
134 
135 static const struct {
136  mfxStatus mfxerr;
137  int averr;
138  const char *desc;
139 } qsv_errors[] = {
140  { MFX_ERR_NONE, 0, "success" },
141  { MFX_ERR_UNKNOWN, AVERROR_UNKNOWN, "unknown error" },
142  { MFX_ERR_NULL_PTR, AVERROR(EINVAL), "NULL pointer" },
143  { MFX_ERR_UNSUPPORTED, AVERROR(ENOSYS), "unsupported" },
144  { MFX_ERR_MEMORY_ALLOC, AVERROR(ENOMEM), "failed to allocate memory" },
145  { MFX_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOMEM), "insufficient input/output buffer" },
146  { MFX_ERR_INVALID_HANDLE, AVERROR(EINVAL), "invalid handle" },
147  { MFX_ERR_LOCK_MEMORY, AVERROR(EIO), "failed to lock the memory block" },
148  { MFX_ERR_NOT_INITIALIZED, AVERROR_BUG, "not initialized" },
149  { MFX_ERR_NOT_FOUND, AVERROR(ENOSYS), "specified object was not found" },
150  /* the following 3 errors should always be handled explicitly, so those "mappings"
151  * are for completeness only */
152  { MFX_ERR_MORE_DATA, AVERROR_UNKNOWN, "expect more data at input" },
153  { MFX_ERR_MORE_SURFACE, AVERROR_UNKNOWN, "expect more surface at output" },
154  { MFX_ERR_MORE_BITSTREAM, AVERROR_UNKNOWN, "expect more bitstream at output" },
155  { MFX_ERR_ABORTED, AVERROR_UNKNOWN, "operation aborted" },
156  { MFX_ERR_DEVICE_LOST, AVERROR(EIO), "device lost" },
157  { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters" },
158  { MFX_ERR_INVALID_VIDEO_PARAM, AVERROR(EINVAL), "invalid video parameters" },
159  { MFX_ERR_UNDEFINED_BEHAVIOR, AVERROR_BUG, "undefined behavior" },
160  { MFX_ERR_DEVICE_FAILED, AVERROR(EIO), "device failed" },
161  { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters" },
162  { MFX_ERR_INVALID_AUDIO_PARAM, AVERROR(EINVAL), "invalid audio parameters" },
163 
164  { MFX_WRN_IN_EXECUTION, 0, "operation in execution" },
165  { MFX_WRN_DEVICE_BUSY, 0, "device busy" },
166  { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" },
167  { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" },
168  { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" },
169  { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" },
170  { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" },
171  { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" },
172  { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
173 };
174 
175 int ff_qsv_map_error(mfxStatus mfx_err, const char **desc)
176 {
177  int i;
178  for (i = 0; i < FF_ARRAY_ELEMS(qsv_errors); i++) {
179  if (qsv_errors[i].mfxerr == mfx_err) {
180  if (desc)
181  *desc = qsv_errors[i].desc;
182  return qsv_errors[i].averr;
183  }
184  }
185  if (desc)
186  *desc = "unknown error";
187  return AVERROR_UNKNOWN;
188 }
189 
190 int ff_qsv_print_error(void *log_ctx, mfxStatus err,
191  const char *error_string)
192 {
193  const char *desc;
194  int ret;
195  ret = ff_qsv_map_error(err, &desc);
196  av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err);
197  return ret;
198 }
199 
200 int ff_qsv_print_warning(void *log_ctx, mfxStatus err,
201  const char *warning_string)
202 {
203  const char *desc;
204  int ret;
205  ret = ff_qsv_map_error(err, &desc);
206  av_log(log_ctx, AV_LOG_WARNING, "%s: %s (%d)\n", warning_string, desc, err);
207  return ret;
208 }
209 
210 static enum AVPixelFormat qsv_map_fourcc(uint32_t fourcc)
211 {
212  switch (fourcc) {
213  case MFX_FOURCC_NV12: return AV_PIX_FMT_NV12;
214  case MFX_FOURCC_P010: return AV_PIX_FMT_P010;
215  case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8;
216  }
217  return AV_PIX_FMT_NONE;
218 }
219 
221 {
222  switch (format) {
223  case AV_PIX_FMT_YUV420P:
224  case AV_PIX_FMT_YUVJ420P:
225  case AV_PIX_FMT_NV12:
226  *fourcc = MFX_FOURCC_NV12;
227  return AV_PIX_FMT_NV12;
229  case AV_PIX_FMT_P010:
230  *fourcc = MFX_FOURCC_P010;
231  return AV_PIX_FMT_P010;
232  default:
233  return AVERROR(ENOSYS);
234  }
235 }
236 
238 {
239  int i;
240  for (i = 0; i < ctx->nb_mids; i++) {
241  QSVMid *mid = &ctx->mids[i];
242  if (mid->handle == frame->surface.Data.MemId)
243  return i;
244  }
245  return AVERROR_BUG;
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 int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
329  const char *load_plugins)
330 {
331  mfxIMPL impl = MFX_IMPL_AUTO_ANY;
332  mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
333 
334  const char *desc;
335  int ret;
336 
337  ret = MFXInit(impl, &ver, session);
338  if (ret < 0)
339  return ff_qsv_print_error(avctx, ret,
340  "Error initializing an internal MFX session");
341 
342  ret = qsv_load_plugins(*session, load_plugins, avctx);
343  if (ret < 0) {
344  av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
345  return ret;
346  }
347 
348  MFXQueryIMPL(*session, &impl);
349 
350  switch (MFX_IMPL_BASETYPE(impl)) {
351  case MFX_IMPL_SOFTWARE:
352  desc = "software";
353  break;
354  case MFX_IMPL_HARDWARE:
355  case MFX_IMPL_HARDWARE2:
356  case MFX_IMPL_HARDWARE3:
357  case MFX_IMPL_HARDWARE4:
358  desc = "hardware accelerated";
359  break;
360  default:
361  desc = "unknown";
362  }
363 
364  av_log(avctx, AV_LOG_VERBOSE,
365  "Initialized an internal MFX session using %s implementation\n",
366  desc);
367 
368  return 0;
369 }
370 
371 static void mids_buf_free(void *opaque, uint8_t *data)
372 {
373  AVBufferRef *hw_frames_ref = opaque;
374  av_buffer_unref(&hw_frames_ref);
375  av_freep(&data);
376 }
377 
378 static AVBufferRef *qsv_create_mids(AVBufferRef *hw_frames_ref)
379 {
380  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data;
381  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
382  int nb_surfaces = frames_hwctx->nb_surfaces;
383 
384  AVBufferRef *mids_buf, *hw_frames_ref1;
385  QSVMid *mids;
386  int i;
387 
388  hw_frames_ref1 = av_buffer_ref(hw_frames_ref);
389  if (!hw_frames_ref1)
390  return NULL;
391 
392  mids = av_mallocz_array(nb_surfaces, sizeof(*mids));
393  if (!mids) {
394  av_buffer_unref(&hw_frames_ref1);
395  return NULL;
396  }
397 
398  mids_buf = av_buffer_create((uint8_t*)mids, nb_surfaces * sizeof(*mids),
399  mids_buf_free, hw_frames_ref1, 0);
400  if (!mids_buf) {
401  av_buffer_unref(&hw_frames_ref1);
402  av_freep(&mids);
403  return NULL;
404  }
405 
406  for (i = 0; i < nb_surfaces; i++) {
407  QSVMid *mid = &mids[i];
408  mid->handle = frames_hwctx->surfaces[i].Data.MemId;
409  mid->hw_frames_ref = hw_frames_ref1;
410  }
411 
412  return mids_buf;
413 }
414 
415 static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref,
416  AVBufferRef *mids_buf)
417 {
418  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data;
419  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
420  QSVMid *mids = (QSVMid*)mids_buf->data;
421  int nb_surfaces = frames_hwctx->nb_surfaces;
422  int i;
423 
424  // the allocated size of the array is two larger than the number of
425  // surfaces, we store the references to the frames context and the
426  // QSVMid array there
427  resp->mids = av_mallocz_array(nb_surfaces + 2, sizeof(*resp->mids));
428  if (!resp->mids)
429  return AVERROR(ENOMEM);
430 
431  for (i = 0; i < nb_surfaces; i++)
432  resp->mids[i] = &mids[i];
433  resp->NumFrameActual = nb_surfaces;
434 
435  resp->mids[resp->NumFrameActual] = (mfxMemId)av_buffer_ref(hw_frames_ref);
436  if (!resp->mids[resp->NumFrameActual]) {
437  av_freep(&resp->mids);
438  return AVERROR(ENOMEM);
439  }
440 
441  resp->mids[resp->NumFrameActual + 1] = av_buffer_ref(mids_buf);
442  if (!resp->mids[resp->NumFrameActual + 1]) {
443  av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual]);
444  av_freep(&resp->mids);
445  return AVERROR(ENOMEM);
446  }
447 
448  return 0;
449 }
450 
451 static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
452  mfxFrameAllocResponse *resp)
453 {
454  QSVFramesContext *ctx = pthis;
455  int ret;
456 
457  /* this should only be called from an encoder or decoder and
458  * only allocates video memory frames */
459  if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
460  MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ||
461  !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
462  return MFX_ERR_UNSUPPORTED;
463 
464  if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
465  /* external frames -- fill from the caller-supplied frames context */
467  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
468  mfxFrameInfo *i = &req->Info;
469  mfxFrameInfo *i1 = &frames_hwctx->surfaces[0].Info;
470 
471  if (i->Width > i1->Width || i->Height > i1->Height ||
472  i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) {
473  av_log(ctx->logctx, AV_LOG_ERROR, "Mismatching surface properties in an "
474  "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
475  i->Width, i->Height, i->FourCC, i->ChromaFormat,
476  i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
477  return MFX_ERR_UNSUPPORTED;
478  }
479 
480  ret = qsv_setup_mids(resp, ctx->hw_frames_ctx, ctx->mids_buf);
481  if (ret < 0) {
482  av_log(ctx->logctx, AV_LOG_ERROR,
483  "Error filling an external frame allocation request\n");
484  return MFX_ERR_MEMORY_ALLOC;
485  }
486  } else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
487  /* internal frames -- allocate a new hw frames context */
488  AVHWFramesContext *ext_frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
489  mfxFrameInfo *i = &req->Info;
490 
491  AVBufferRef *frames_ref, *mids_buf;
492  AVHWFramesContext *frames_ctx;
493  AVQSVFramesContext *frames_hwctx;
494 
495  frames_ref = av_hwframe_ctx_alloc(ext_frames_ctx->device_ref);
496  if (!frames_ref)
497  return MFX_ERR_MEMORY_ALLOC;
498 
499  frames_ctx = (AVHWFramesContext*)frames_ref->data;
500  frames_hwctx = frames_ctx->hwctx;
501 
502  frames_ctx->format = AV_PIX_FMT_QSV;
503  frames_ctx->sw_format = qsv_map_fourcc(i->FourCC);
504  frames_ctx->width = i->Width;
505  frames_ctx->height = i->Height;
506  frames_ctx->initial_pool_size = req->NumFrameSuggested;
507 
508  frames_hwctx->frame_type = req->Type;
509 
510  ret = av_hwframe_ctx_init(frames_ref);
511  if (ret < 0) {
512  av_log(ctx->logctx, AV_LOG_ERROR,
513  "Error initializing a frames context for an internal frame "
514  "allocation request\n");
515  av_buffer_unref(&frames_ref);
516  return MFX_ERR_MEMORY_ALLOC;
517  }
518 
519  mids_buf = qsv_create_mids(frames_ref);
520  if (!mids_buf) {
521  av_buffer_unref(&frames_ref);
522  return MFX_ERR_MEMORY_ALLOC;
523  }
524 
525  ret = qsv_setup_mids(resp, frames_ref, mids_buf);
526  av_buffer_unref(&mids_buf);
527  av_buffer_unref(&frames_ref);
528  if (ret < 0) {
529  av_log(ctx->logctx, AV_LOG_ERROR,
530  "Error filling an internal frame allocation request\n");
531  return MFX_ERR_MEMORY_ALLOC;
532  }
533  } else {
534  return MFX_ERR_UNSUPPORTED;
535  }
536 
537  return MFX_ERR_NONE;
538 }
539 
540 static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
541 {
542  av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual]);
543  av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual + 1]);
544  av_freep(&resp->mids);
545  return MFX_ERR_NONE;
546 }
547 
548 static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
549 {
550  QSVMid *qsv_mid = mid;
551  AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)qsv_mid->hw_frames_ref->data;
552  AVQSVFramesContext *hw_frames_hwctx = hw_frames_ctx->hwctx;
553  int ret;
554 
555  if (qsv_mid->locked_frame)
556  return MFX_ERR_UNDEFINED_BEHAVIOR;
557 
558  /* Allocate a system memory frame that will hold the mapped data. */
559  qsv_mid->locked_frame = av_frame_alloc();
560  if (!qsv_mid->locked_frame)
561  return MFX_ERR_MEMORY_ALLOC;
562  qsv_mid->locked_frame->format = hw_frames_ctx->sw_format;
563 
564  /* wrap the provided handle in a hwaccel AVFrame */
565  qsv_mid->hw_frame = av_frame_alloc();
566  if (!qsv_mid->hw_frame)
567  goto fail;
568 
569  qsv_mid->hw_frame->data[3] = (uint8_t*)&qsv_mid->surf;
570  qsv_mid->hw_frame->format = AV_PIX_FMT_QSV;
571 
572  // doesn't really matter what buffer is used here
573  qsv_mid->hw_frame->buf[0] = av_buffer_alloc(1);
574  if (!qsv_mid->hw_frame->buf[0])
575  goto fail;
576 
577  qsv_mid->hw_frame->width = hw_frames_ctx->width;
578  qsv_mid->hw_frame->height = hw_frames_ctx->height;
579 
580  qsv_mid->hw_frame->hw_frames_ctx = av_buffer_ref(qsv_mid->hw_frames_ref);
581  if (!qsv_mid->hw_frame->hw_frames_ctx)
582  goto fail;
583 
584  qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info;
585  qsv_mid->surf.Data.MemId = qsv_mid->handle;
586 
587  /* map the data to the system memory */
588  ret = av_hwframe_map(qsv_mid->locked_frame, qsv_mid->hw_frame,
590  if (ret < 0)
591  goto fail;
592 
593  ptr->Pitch = qsv_mid->locked_frame->linesize[0];
594  ptr->Y = qsv_mid->locked_frame->data[0];
595  ptr->U = qsv_mid->locked_frame->data[1];
596  ptr->V = qsv_mid->locked_frame->data[1] + 1;
597 
598  return MFX_ERR_NONE;
599 fail:
600  av_frame_free(&qsv_mid->hw_frame);
601  av_frame_free(&qsv_mid->locked_frame);
602  return MFX_ERR_MEMORY_ALLOC;
603 }
604 
605 static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
606 {
607  QSVMid *qsv_mid = mid;
608 
609  av_frame_free(&qsv_mid->locked_frame);
610  av_frame_free(&qsv_mid->hw_frame);
611 
612  return MFX_ERR_NONE;
613 }
614 
615 static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
616 {
617  QSVMid *qsv_mid = (QSVMid*)mid;
618  *hdl = qsv_mid->handle;
619  return MFX_ERR_NONE;
620 }
621 
622 int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
623  AVBufferRef *device_ref, const char *load_plugins)
624 {
625  static const mfxHandleType handle_types[] = {
626  MFX_HANDLE_VA_DISPLAY,
627  MFX_HANDLE_D3D9_DEVICE_MANAGER,
628  MFX_HANDLE_D3D11_DEVICE,
629  };
630  AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data;
631  AVQSVDeviceContext *device_hwctx = device_ctx->hwctx;
632  mfxSession parent_session = device_hwctx->session;
633 
634  mfxSession session;
635  mfxVersion ver;
636  mfxIMPL impl;
637  mfxHDL handle = NULL;
638  mfxHandleType handle_type;
639  mfxStatus err;
640 
641  int i, ret;
642 
643  err = MFXQueryIMPL(parent_session, &impl);
644  if (err == MFX_ERR_NONE)
645  err = MFXQueryVersion(parent_session, &ver);
646  if (err != MFX_ERR_NONE)
647  return ff_qsv_print_error(avctx, err,
648  "Error querying the session attributes");
649 
650  for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) {
651  err = MFXVideoCORE_GetHandle(parent_session, handle_types[i], &handle);
652  if (err == MFX_ERR_NONE) {
653  handle_type = handle_types[i];
654  break;
655  }
656  handle = NULL;
657  }
658  if (!handle) {
659  av_log(avctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
660  "from the session\n");
661  }
662 
663  err = MFXInit(impl, &ver, &session);
664  if (err != MFX_ERR_NONE)
665  return ff_qsv_print_error(avctx, err,
666  "Error initializing a child MFX session");
667 
668  if (handle) {
669  err = MFXVideoCORE_SetHandle(session, handle_type, handle);
670  if (err != MFX_ERR_NONE)
671  return ff_qsv_print_error(avctx, err,
672  "Error setting a HW handle");
673  }
674 
675  if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
676  err = MFXJoinSession(parent_session, session);
677  if (err != MFX_ERR_NONE)
678  return ff_qsv_print_error(avctx, err,
679  "Error joining session");
680  }
681 
682  ret = qsv_load_plugins(session, load_plugins, avctx);
683  if (ret < 0) {
684  av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
685  return ret;
686  }
687 
688  *psession = session;
689  return 0;
690 }
691 
692 int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession,
693  QSVFramesContext *qsv_frames_ctx,
694  const char *load_plugins, int opaque)
695 {
696  mfxFrameAllocator frame_allocator = {
697  .pthis = qsv_frames_ctx,
698  .Alloc = qsv_frame_alloc,
699  .Lock = qsv_frame_lock,
700  .Unlock = qsv_frame_unlock,
701  .GetHDL = qsv_frame_get_hdl,
702  .Free = qsv_frame_free,
703  };
704 
705  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data;
706  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
707 
708  mfxSession session;
709  mfxStatus err;
710 
711  int ret;
712 
713  ret = ff_qsv_init_session_device(avctx, &session,
714  frames_ctx->device_ref, load_plugins);
715  if (ret < 0)
716  return ret;
717 
718  if (!opaque) {
719  qsv_frames_ctx->logctx = avctx;
720 
721  /* allocate the memory ids for the external frames */
722  av_buffer_unref(&qsv_frames_ctx->mids_buf);
723  qsv_frames_ctx->mids_buf = qsv_create_mids(qsv_frames_ctx->hw_frames_ctx);
724  if (!qsv_frames_ctx->mids_buf)
725  return AVERROR(ENOMEM);
726  qsv_frames_ctx->mids = (QSVMid*)qsv_frames_ctx->mids_buf->data;
727  qsv_frames_ctx->nb_mids = frames_hwctx->nb_surfaces;
728 
729  err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
730  if (err != MFX_ERR_NONE)
731  return ff_qsv_print_error(avctx, err,
732  "Error setting a frame allocator");
733  }
734 
735  *psession = session;
736  return 0;
737 }
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:451
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:605
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:72
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:122
int averr
Definition: qsv.c:137
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:41
GLint GLenum type
Definition: opengl_enc.c:104
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:49
AVBufferRef * hw_frames_ctx
Definition: qsv_internal.h:68
int ff_qsv_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition: qsv.c:190
The mapping must be direct.
Definition: hwcontext.h:519
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:2215
#define FF_LEVEL_UNKNOWN
Definition: avcodec.h:3019
#define AV_PIX_FMT_P010
Definition: pixfmt.h:436
static const struct @132 qsv_errors[]
#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:50
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:75
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:371
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
#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:175
int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession, QSVFramesContext *qsv_frames_ctx, const char *load_plugins, int opaque)
Definition: qsv.c:692
#define av_log(a,...)
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_qsv.h:35
#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:237
error code definitions
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition: qsv.c:540
mfxHDL handle
Definition: qsv_internal.h:47
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
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
enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
Definition: qsv.c:248
#define fail()
Definition: checkasm.h:120
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:200
int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc)
Definition: qsv.c:220
int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile)
Definition: qsv.c:106
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:31
#define FF_PROFILE_UNKNOWN
Definition: avcodec.h:2899
const char * desc
Definition: qsv.c:138
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:615
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:56
preferred ID for MPEG-1/2 video decoding
Definition: avcodec.h:220
#define FF_ARRAY_ELEMS(a)
if(ret)
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:1565
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
#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:46
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
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:415
mfxU16 profile
Definition: qsvenc.c:44
static AVBufferRef * qsv_create_mids(AVBufferRef *hw_frames_ref)
Definition: qsv.c:378
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:136
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:548
static enum AVPixelFormat qsv_map_fourcc(uint32_t fourcc)
Definition: qsv.c:210
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:51
Bi-dir predicted.
Definition: avutil.h:276
int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, const char *load_plugins)
Definition: qsv.c:328
#define QSV_VERSION_MAJOR
Definition: qsv_internal.h:30
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
static const struct @131 qsv_profile_map[]
int height
Definition: frame.h:353
int codec_profile
Definition: qsv.c:73
#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:74
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
Predicted.
Definition: avutil.h:275
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins)
Definition: qsv.c:622
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191