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