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;
110  return MFX_PROFILE_UNKNOWN;
111 
112  for (i = 0; i < FF_ARRAY_ELEMS(qsv_profile_map); i++) {
114  continue;
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)
255  else
257  break;
258  case MFX_FRAMETYPE_B:
260  break;
261  case MFX_FRAMETYPE_P:
262  if (mfx_pic_type & MFX_FRAMETYPE_S)
264  else
266  break;
267  case MFX_FRAMETYPE_UNKNOWN:
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 */
466  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
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) {
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 }
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
qsv_frame_unlock
static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsv.c:605
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
level
uint8_t level
Definition: svq3.c:207
handle_types
static const mfxHandleType handle_types[]
Definition: qsvvpp.c:71
QSVFramesContext::nb_mids
int nb_mids
Definition: qsv_internal.h:77
av_buffer_alloc
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
uid
UID uid
Definition: mxfenc.c:2214
codec_id
enum AVCodecID codec_id
Definition: qsv.c:72
QSV_VERSION_MAJOR
#define QSV_VERSION_MAJOR
Definition: qsv_internal.h:30
QSVFramesContext::hw_frames_ctx
AVBufferRef * hw_frames_ctx
Definition: qsv_internal.h:68
av_get_token
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition: avstring.c:149
averr
int averr
Definition: qsv.c:137
QSVMid::locked_frame
AVFrame * locked_frame
Definition: qsv_internal.h:49
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:89
AVPictureType
AVPictureType
Definition: avutil.h:272
qsv_errors
static const struct @132 qsv_errors[]
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
profile
mfxU16 profile
Definition: qsvenc.c:44
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:329
ff_qsv_map_pictype
enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
Definition: qsv.c:248
AVFrame::width
int width
Definition: frame.h:353
AVQSVDeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_qsv.h:35
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:243
av_hwframe_map
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:740
ff_qsv_find_surface_idx
int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame)
Definition: qsv.c:237
data
const char data[16]
Definition: mxf.c:91
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:387
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
av_buffer_create
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
codec_profile
int codec_profile
Definition: qsv.c:73
FF_LEVEL_UNKNOWN
#define FF_LEVEL_UNKNOWN
Definition: avcodec.h:3019
qsv_profile_map
static const struct @131 qsv_profile_map[]
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:486
mfx_profile
int mfx_profile
Definition: qsv.c:74
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
fail
#define fail()
Definition: checkasm.h:120
qsv_load_plugins
static int qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx)
Definition: qsv.c:277
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
handle_type
mfxHandleType handle_type
Definition: hwcontext_qsv.c:85
desc
const char * desc
Definition: qsv.c:138
qsv_internal.h
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
ff_qsv_print_warning
int ff_qsv_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
Definition: qsv.c:200
AVHWFramesContext::height
int height
Definition: hwcontext.h:228
QSV_VERSION_MINOR
#define QSV_VERSION_MINOR
Definition: qsv_internal.h:31
QSVMid::hw_frame
AVFrame * hw_frame
Definition: qsv_internal.h:50
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
ff_qsv_level_to_mfx
int ff_qsv_level_to_mfx(enum AVCodecID codec_id, int level)
Definition: qsv.c:122
QSV_RUNTIME_VERSION_ATLEAST
#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR)
Definition: qsv_internal.h:41
FF_PROFILE_UNKNOWN
#define FF_PROFILE_UNKNOWN
Definition: avcodec.h:2899
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: avcodec.h:245
if
if(ret)
Definition: filter_design.txt:179
mids_buf_free
static void mids_buf_free(void *opaque, uint8_t *data)
Definition: qsv.c:371
QSVFrame
Definition: qsv_internal.h:54
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:221
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:125
AVHWFramesContext::device_ref
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:140
AV_PIX_FMT_YUVJ420P
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
AV_PICTURE_TYPE_SI
@ AV_PICTURE_TYPE_SI
Switching Intra.
Definition: avutil.h:278
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:274
QSVFramesContext::mids_buf
AVBufferRef * mids_buf
Definition: qsv_internal.h:75
AV_PIX_FMT_QSV
@ AV_PIX_FMT_QSV
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:222
AV_PICTURE_TYPE_SP
@ AV_PICTURE_TYPE_SP
Switching Predicted.
Definition: avutil.h:279
AV_CODEC_ID_MPEG1VIDEO
@ AV_CODEC_ID_MPEG1VIDEO
Definition: avcodec.h:219
error.h
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
ff_qsv_map_pixfmt
int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc)
Definition: qsv.c:220
mfxerr
mfxStatus mfxerr
Definition: qsv.c:136
AV_HWFRAME_MAP_DIRECT
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
Definition: hwcontext.h:519
qsv_map_fourcc
static enum AVPixelFormat qsv_map_fourcc(uint32_t fourcc)
Definition: qsv.c:210
QSVMid::hw_frames_ref
AVBufferRef * hw_frames_ref
Definition: qsv_internal.h:46
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:368
AV_PICTURE_TYPE_NONE
@ AV_PICTURE_TYPE_NONE
Undefined.
Definition: avutil.h:273
ff_qsv_profile_to_mfx
int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile)
Definition: qsv.c:106
QSVFramesContext::mids
QSVMid * mids
Definition: qsv_internal.h:76
AV_CODEC_ID_MJPEG
@ AV_CODEC_ID_MJPEG
Definition: avcodec.h:225
ff_qsv_init_session_frames
int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession, QSVFramesContext *qsv_frames_ctx, const char *load_plugins, int opaque)
Definition: qsv.c:692
hwcontext_qsv.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
common.h
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: avcodec.h:392
QSVMid::surf
mfxFrameSurface1 surf
Definition: qsv_internal.h:51
uint8_t
uint8_t
Definition: audio_convert.c:194
AV_CODEC_ID_VC1
@ AV_CODEC_ID_VC1
Definition: avcodec.h:288
avcodec.h
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
qsv_frame_free
static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition: qsv.c:540
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:89
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:161
ff_qsv_codec_id_to_mfx
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
Definition: qsv.c:43
qsv_frame_get_hdl
static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition: qsv.c:615
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen_template.c:38
AVFrame::hw_frames_ctx
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:634
AVCodecContext
main external API structure.
Definition: avcodec.h:1565
AVFrame::height
int height
Definition: frame.h:353
qsv_frame_alloc
static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition: qsv.c:451
AV_PICTURE_TYPE_B
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition: avutil.h:276
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
av_buffer_ref
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:436
AVQSVFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_qsv.h:42
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:275
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:81
qsv_setup_mids
static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref, AVBufferRef *mids_buf)
Definition: qsv.c:415
QSVFramesContext::logctx
void * logctx
Definition: qsv_internal.h:69
QSVFramesContext
Definition: qsv_internal.h:67
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
QSVMid::handle
mfxHDL handle
Definition: qsv_internal.h:47
qsv_create_mids
static AVBufferRef * qsv_create_mids(AVBufferRef *hw_frames_ref)
Definition: qsv.c:378
imgutils.h
AV_CODEC_ID_VP8
@ AV_CODEC_ID_VP8
Definition: avcodec.h:358
hwcontext.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
ff_qsv_init_session_device
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins)
Definition: qsv.c:622
avstring.h
AV_CODEC_ID_MPEG2VIDEO
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition: avcodec.h:220
QSVMid
Definition: qsv_internal.h:45
ff_qsv_print_error
int ff_qsv_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition: qsv.c:190
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:238
snprintf
#define snprintf
Definition: snprintf.h:34
qsv_frame_lock
static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsv.c:548
ff_qsv_init_internal_session
int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, const char *load_plugins)
Definition: qsv.c:328
ff_qsv_map_error
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
MAP
#define MAP(c, p, v)