FFmpeg
qsvvpp.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * @file
21  * Intel Quick Sync Video VPP base function
22  */
23 
24 #include "libavutil/common.h"
25 #include "libavutil/mathematics.h"
26 #include "libavutil/time.h"
27 #include "libavutil/pixdesc.h"
28 
29 #include "internal.h"
30 #include "qsvvpp.h"
31 #include "video.h"
32 
33 #if QSV_ONEVPL
34 #include <mfxdispatcher.h>
35 #else
36 #define MFXUnload(a) do { } while(0)
37 #endif
38 
39 #define IS_VIDEO_MEMORY(mode) (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \
40  MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
41 #if QSV_HAVE_OPAQUE
42 #define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
43 #endif
44 #define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
45 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
46 
47 #define QSV_HAVE_AUDIO !QSV_ONEVPL
48 
49 static const AVRational default_tb = { 1, 90000 };
50 
51 typedef struct QSVAsyncFrame {
52  mfxSyncPoint sync;
53  QSVFrame *frame;
55 
56 static const struct {
58  const char *desc;
59 } qsv_iopatterns[] = {
60  {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
61  {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
62 #if QSV_HAVE_OPAQUE
63  {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
64 #endif
65  {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
66  {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
67 #if QSV_HAVE_OPAQUE
68  {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
69 #endif
70 };
71 
73  const char *extra_string)
74 {
75  const char *desc = NULL;
76 
77  for (int i = 0; i < FF_ARRAY_ELEMS(qsv_iopatterns); i++) {
79  desc = qsv_iopatterns[i].desc;
80  }
81  }
82  if (!desc)
83  desc = "unknown iopattern";
84 
85  av_log(log_ctx, AV_LOG_VERBOSE, "%s: %s\n", extra_string, desc);
86  return 0;
87 }
88 
89 static const struct {
90  mfxStatus mfxerr;
91  int averr;
92  const char *desc;
93 } qsv_errors[] = {
94  { MFX_ERR_NONE, 0, "success" },
95  { MFX_ERR_UNKNOWN, AVERROR_UNKNOWN, "unknown error" },
96  { MFX_ERR_NULL_PTR, AVERROR(EINVAL), "NULL pointer" },
97  { MFX_ERR_UNSUPPORTED, AVERROR(ENOSYS), "unsupported" },
98  { MFX_ERR_MEMORY_ALLOC, AVERROR(ENOMEM), "failed to allocate memory" },
99  { MFX_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOMEM), "insufficient input/output buffer" },
100  { MFX_ERR_INVALID_HANDLE, AVERROR(EINVAL), "invalid handle" },
101  { MFX_ERR_LOCK_MEMORY, AVERROR(EIO), "failed to lock the memory block" },
102  { MFX_ERR_NOT_INITIALIZED, AVERROR_BUG, "not initialized" },
103  { MFX_ERR_NOT_FOUND, AVERROR(ENOSYS), "specified object was not found" },
104  /* the following 3 errors should always be handled explicitly, so those "mappings"
105  * are for completeness only */
106  { MFX_ERR_MORE_DATA, AVERROR_UNKNOWN, "expect more data at input" },
107  { MFX_ERR_MORE_SURFACE, AVERROR_UNKNOWN, "expect more surface at output" },
108  { MFX_ERR_MORE_BITSTREAM, AVERROR_UNKNOWN, "expect more bitstream at output" },
109  { MFX_ERR_ABORTED, AVERROR_UNKNOWN, "operation aborted" },
110  { MFX_ERR_DEVICE_LOST, AVERROR(EIO), "device lost" },
111  { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters" },
112  { MFX_ERR_INVALID_VIDEO_PARAM, AVERROR(EINVAL), "invalid video parameters" },
113  { MFX_ERR_UNDEFINED_BEHAVIOR, AVERROR_BUG, "undefined behavior" },
114  { MFX_ERR_DEVICE_FAILED, AVERROR(EIO), "device failed" },
115 #if QSV_HAVE_AUDIO
116  { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters" },
117  { MFX_ERR_INVALID_AUDIO_PARAM, AVERROR(EINVAL), "invalid audio parameters" },
118 #endif
119  { MFX_ERR_GPU_HANG, AVERROR(EIO), "GPU Hang" },
120  { MFX_ERR_REALLOC_SURFACE, AVERROR_UNKNOWN, "need bigger surface for output" },
121 
122  { MFX_WRN_IN_EXECUTION, 0, "operation in execution" },
123  { MFX_WRN_DEVICE_BUSY, 0, "device busy" },
124  { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" },
125  { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" },
126  { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" },
127  { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" },
128  { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" },
129  { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" },
130 #if QSV_HAVE_AUDIO
131  { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
132 #endif
133 
134 #if QSV_VERSION_ATLEAST(1, 31)
135  { MFX_ERR_NONE_PARTIAL_OUTPUT, 0, "partial output" },
136 #endif
137 };
138 
139 static int qsv_map_error(mfxStatus mfx_err, const char **desc)
140 {
141  int i;
142  for (i = 0; i < FF_ARRAY_ELEMS(qsv_errors); i++) {
143  if (qsv_errors[i].mfxerr == mfx_err) {
144  if (desc)
145  *desc = qsv_errors[i].desc;
146  return qsv_errors[i].averr;
147  }
148  }
149  if (desc)
150  *desc = "unknown error";
151  return AVERROR_UNKNOWN;
152 }
153 
154 int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err,
155  const char *error_string)
156 {
157  const char *desc;
158  int ret;
159  ret = qsv_map_error(err, &desc);
160  av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err);
161  return ret;
162 }
163 
164 int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err,
165  const char *warning_string)
166 {
167  const char *desc;
168  int ret;
169  ret = qsv_map_error(err, &desc);
170  av_log(log_ctx, AV_LOG_WARNING, "%s: %s (%d)\n", warning_string, desc, err);
171  return ret;
172 }
173 
174 /* functions for frameAlloc */
175 static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
176  mfxFrameAllocResponse *resp)
177 {
178  QSVVPPContext *s = pthis;
179  int i;
180 
181  if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
182  !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
183  !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
184  return MFX_ERR_UNSUPPORTED;
185 
186  if (req->Type & MFX_MEMTYPE_FROM_VPPIN) {
187  resp->mids = av_mallocz(s->nb_surface_ptrs_in * sizeof(*resp->mids));
188  if (!resp->mids)
189  return AVERROR(ENOMEM);
190 
191  for (i = 0; i < s->nb_surface_ptrs_in; i++)
192  resp->mids[i] = s->surface_ptrs_in[i]->Data.MemId;
193 
194  resp->NumFrameActual = s->nb_surface_ptrs_in;
195  } else {
196  resp->mids = av_mallocz(s->nb_surface_ptrs_out * sizeof(*resp->mids));
197  if (!resp->mids)
198  return AVERROR(ENOMEM);
199 
200  for (i = 0; i < s->nb_surface_ptrs_out; i++)
201  resp->mids[i] = s->surface_ptrs_out[i]->Data.MemId;
202 
203  resp->NumFrameActual = s->nb_surface_ptrs_out;
204  }
205 
206  return MFX_ERR_NONE;
207 }
208 
209 static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
210 {
211  av_freep(&resp->mids);
212  return MFX_ERR_NONE;
213 }
214 
215 static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
216 {
217  return MFX_ERR_UNSUPPORTED;
218 }
219 
220 static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
221 {
222  return MFX_ERR_UNSUPPORTED;
223 }
224 
225 static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
226 {
227  mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
228  mfxHDLPair *pair_src = (mfxHDLPair*)mid;
229 
230  pair_dst->first = pair_src->first;
231 
232  if (pair_src->second != (mfxMemId)MFX_INFINITE)
233  pair_dst->second = pair_src->second;
234  return MFX_ERR_NONE;
235 }
236 
238 {
239  switch (format) {
240  case AV_PIX_FMT_YUV420P:
241  return MFX_FOURCC_YV12;
242  case AV_PIX_FMT_NV12:
243  return MFX_FOURCC_NV12;
244  case AV_PIX_FMT_YUYV422:
245  return MFX_FOURCC_YUY2;
246  case AV_PIX_FMT_BGRA:
247  return MFX_FOURCC_RGB4;
248  case AV_PIX_FMT_P010:
249  return MFX_FOURCC_P010;
250 #if CONFIG_VAAPI
251  case AV_PIX_FMT_UYVY422:
252  return MFX_FOURCC_UYVY;
253 #endif
254  }
255 
256  return MFX_FOURCC_NV12;
257 }
258 
259 static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface)
260 {
261  switch (frame->format) {
262  case AV_PIX_FMT_NV12:
263  case AV_PIX_FMT_P010:
264  surface->Data.Y = frame->data[0];
265  surface->Data.UV = frame->data[1];
266  break;
267  case AV_PIX_FMT_YUV420P:
268  surface->Data.Y = frame->data[0];
269  surface->Data.U = frame->data[1];
270  surface->Data.V = frame->data[2];
271  break;
272  case AV_PIX_FMT_YUYV422:
273  surface->Data.Y = frame->data[0];
274  surface->Data.U = frame->data[0] + 1;
275  surface->Data.V = frame->data[0] + 3;
276  break;
277  case AV_PIX_FMT_RGB32:
278  surface->Data.B = frame->data[0];
279  surface->Data.G = frame->data[0] + 1;
280  surface->Data.R = frame->data[0] + 2;
281  surface->Data.A = frame->data[0] + 3;
282  break;
283  case AV_PIX_FMT_UYVY422:
284  surface->Data.Y = frame->data[0] + 1;
285  surface->Data.U = frame->data[0];
286  surface->Data.V = frame->data[0] + 2;
287  break;
288  default:
289  return MFX_ERR_UNSUPPORTED;
290  }
291  surface->Data.Pitch = frame->linesize[0];
292 
293  return 0;
294 }
295 
296 /* fill the surface info */
297 static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
298 {
299  enum AVPixelFormat pix_fmt;
300  AVHWFramesContext *frames_ctx;
301  AVQSVFramesContext *frames_hwctx;
302  const AVPixFmtDescriptor *desc;
303 
304  if (link->format == AV_PIX_FMT_QSV) {
305  if (!link->hw_frames_ctx)
306  return AVERROR(EINVAL);
307 
308  frames_ctx = (AVHWFramesContext *)link->hw_frames_ctx->data;
309  frames_hwctx = frames_ctx->hwctx;
310  *frameinfo = frames_hwctx->surfaces[0].Info;
311  } else {
312  pix_fmt = link->format;
314  if (!desc)
315  return AVERROR_BUG;
316 
317  frameinfo->CropX = 0;
318  frameinfo->CropY = 0;
319  frameinfo->Width = FFALIGN(link->w, 32);
320  frameinfo->Height = FFALIGN(link->h, 32);
321  frameinfo->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
322  frameinfo->FourCC = pix_fmt_to_mfx_fourcc(pix_fmt);
323  frameinfo->BitDepthLuma = desc->comp[0].depth;
324  frameinfo->BitDepthChroma = desc->comp[0].depth;
325  frameinfo->Shift = desc->comp[0].depth > 8;
326  if (desc->log2_chroma_w && desc->log2_chroma_h)
327  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV420;
328  else if (desc->log2_chroma_w)
329  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV422;
330  else
331  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV444;
332  }
333 
334  frameinfo->CropW = link->w;
335  frameinfo->CropH = link->h;
336  frameinfo->FrameRateExtN = link->frame_rate.num;
337  frameinfo->FrameRateExtD = link->frame_rate.den;
338 
339  /* Apparently VPP in the SDK requires the frame rate to be set to some value, otherwise
340  * init will fail */
341  if (frameinfo->FrameRateExtD == 0 || frameinfo->FrameRateExtN == 0) {
342  frameinfo->FrameRateExtN = 25;
343  frameinfo->FrameRateExtD = 1;
344  }
345 
346  frameinfo->AspectRatioW = link->sample_aspect_ratio.num ? link->sample_aspect_ratio.num : 1;
347  frameinfo->AspectRatioH = link->sample_aspect_ratio.den ? link->sample_aspect_ratio.den : 1;
348 
349  return 0;
350 }
351 
353 {
354  while (list) {
355  /* list->queued==1 means the frame is not cached in VPP
356  * process any more, it can be released to pool. */
357  if ((list->queued == 1) && !list->surface.Data.Locked) {
358  av_frame_free(&list->frame);
359  list->queued = 0;
360  }
361  list = list->next;
362  }
363 }
364 
366 {
367  while (*list) {
368  QSVFrame *frame;
369 
370  frame = *list;
371  *list = (*list)->next;
372  av_frame_free(&frame->frame);
373  av_freep(&frame);
374  }
375 }
376 
378 {
379  QSVFrame *out = *list;
380 
381  for (; out; out = out->next) {
382  if (!out->queued) {
383  out->queued = 1;
384  break;
385  }
386  }
387 
388  if (!out) {
389  out = av_mallocz(sizeof(*out));
390  if (!out) {
391  av_log(NULL, AV_LOG_ERROR, "Can't alloc new output frame.\n");
392  return NULL;
393  }
394  out->queued = 1;
395  out->next = *list;
396  *list = out;
397  }
398 
399  return out;
400 }
401 
402 /* get the input surface */
404 {
405  QSVFrame *qsv_frame;
406  AVFilterContext *ctx = inlink->dst;
407 
408  clear_unused_frames(s->in_frame_list);
409 
410  qsv_frame = get_free_frame(&s->in_frame_list);
411  if (!qsv_frame)
412  return NULL;
413 
414  /* Turn AVFrame into mfxFrameSurface1.
415  * For video/opaque memory mode, pix_fmt is AV_PIX_FMT_QSV, and
416  * mfxFrameSurface1 is stored in AVFrame->data[3];
417  * for system memory mode, raw video data is stored in
418  * AVFrame, we should map it into mfxFrameSurface1.
419  */
420  if (!IS_SYSTEM_MEMORY(s->in_mem_mode)) {
421  if (picref->format != AV_PIX_FMT_QSV) {
422  av_log(ctx, AV_LOG_ERROR, "QSVVPP gets a wrong frame.\n");
423  return NULL;
424  }
425  qsv_frame->frame = av_frame_clone(picref);
426  qsv_frame->surface = *(mfxFrameSurface1 *)qsv_frame->frame->data[3];
427  } else {
428  /* make a copy if the input is not padded as libmfx requires */
429  if (picref->height & 31 || picref->linesize[0] & 31) {
430  qsv_frame->frame = ff_get_video_buffer(inlink,
431  FFALIGN(inlink->w, 32),
432  FFALIGN(inlink->h, 32));
433  if (!qsv_frame->frame)
434  return NULL;
435 
436  qsv_frame->frame->width = picref->width;
437  qsv_frame->frame->height = picref->height;
438 
439  if (av_frame_copy(qsv_frame->frame, picref) < 0) {
440  av_frame_free(&qsv_frame->frame);
441  return NULL;
442  }
443 
444  if (av_frame_copy_props(qsv_frame->frame, picref) < 0) {
445  av_frame_free(&qsv_frame->frame);
446  return NULL;
447  }
448  } else
449  qsv_frame->frame = av_frame_clone(picref);
450 
451  if (map_frame_to_surface(qsv_frame->frame,
452  &qsv_frame->surface) < 0) {
453  av_log(ctx, AV_LOG_ERROR, "Unsupported frame.\n");
454  return NULL;
455  }
456  }
457 
458  qsv_frame->surface.Info = s->frame_infos[FF_INLINK_IDX(inlink)];
459  qsv_frame->surface.Data.TimeStamp = av_rescale_q(qsv_frame->frame->pts,
460  inlink->time_base, default_tb);
461 
462  qsv_frame->surface.Info.PicStruct =
463  !qsv_frame->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
464  (qsv_frame->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF :
465  MFX_PICSTRUCT_FIELD_BFF);
466  if (qsv_frame->frame->repeat_pict == 1)
467  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
468  else if (qsv_frame->frame->repeat_pict == 2)
469  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
470  else if (qsv_frame->frame->repeat_pict == 4)
471  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
472 
473  return qsv_frame;
474 }
475 
476 /* get the output surface */
478 {
479  AVFilterContext *ctx = outlink->src;
480  QSVFrame *out_frame;
481  int ret;
482 
483  clear_unused_frames(s->out_frame_list);
484 
485  out_frame = get_free_frame(&s->out_frame_list);
486  if (!out_frame)
487  return NULL;
488 
489  /* For video memory, get a hw frame;
490  * For system memory, get a sw frame and map it into a mfx_surface. */
491  if (!IS_SYSTEM_MEMORY(s->out_mem_mode)) {
492  out_frame->frame = av_frame_alloc();
493  if (!out_frame->frame)
494  return NULL;
495 
496  ret = av_hwframe_get_buffer(outlink->hw_frames_ctx, out_frame->frame, 0);
497  if (ret < 0) {
498  av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n");
499  return NULL;
500  }
501 
502  out_frame->surface = *(mfxFrameSurface1 *)out_frame->frame->data[3];
503  } else {
504  /* Get a frame with aligned dimensions.
505  * Libmfx need system memory being 128x64 aligned */
506  out_frame->frame = ff_get_video_buffer(outlink,
507  FFALIGN(outlink->w, 128),
508  FFALIGN(outlink->h, 64));
509  if (!out_frame->frame)
510  return NULL;
511 
512  ret = map_frame_to_surface(out_frame->frame,
513  &out_frame->surface);
514  if (ret < 0)
515  return NULL;
516  }
517 
518  if (outlink->frame_rate.num && outlink->frame_rate.den)
519  out_frame->frame->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
520  else
521  out_frame->frame->duration = 0;
522 
523  out_frame->frame->width = outlink->w;
524  out_frame->frame->height = outlink->h;
525  out_frame->surface.Info = s->vpp_param.vpp.Out;
526 
527  return out_frame;
528 }
529 
530 /* create the QSV session */
532 {
533  AVFilterLink *inlink = avctx->inputs[0];
534  AVFilterLink *outlink = avctx->outputs[0];
535  AVQSVFramesContext *in_frames_hwctx = NULL;
536  AVQSVFramesContext *out_frames_hwctx = NULL;
537 
538  AVBufferRef *device_ref;
539  AVHWDeviceContext *device_ctx;
540  AVQSVDeviceContext *device_hwctx;
541  mfxHDL handle;
542  mfxHandleType handle_type;
543  mfxVersion ver;
544  mfxIMPL impl;
545  int ret, i;
546 
547  if (inlink->hw_frames_ctx) {
548  AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
549 
550  device_ref = frames_ctx->device_ref;
551  in_frames_hwctx = frames_ctx->hwctx;
552 
553  s->in_mem_mode = in_frames_hwctx->frame_type;
554 
555  s->surface_ptrs_in = av_calloc(in_frames_hwctx->nb_surfaces,
556  sizeof(*s->surface_ptrs_in));
557  if (!s->surface_ptrs_in)
558  return AVERROR(ENOMEM);
559 
560  for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
561  s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i;
562 
563  s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces;
564  } else if (avctx->hw_device_ctx) {
565  device_ref = avctx->hw_device_ctx;
566  s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
567  } else {
568  av_log(avctx, AV_LOG_ERROR, "No hw context provided.\n");
569  return AVERROR(EINVAL);
570  }
571 
572  device_ctx = (AVHWDeviceContext *)device_ref->data;
573  device_hwctx = device_ctx->hwctx;
574 
575  if (outlink->format == AV_PIX_FMT_QSV) {
576  AVHWFramesContext *out_frames_ctx;
577  AVBufferRef *out_frames_ref = av_hwframe_ctx_alloc(device_ref);
578  if (!out_frames_ref)
579  return AVERROR(ENOMEM);
580 
581 #if QSV_HAVE_OPAQUE
582  s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ?
583  MFX_MEMTYPE_OPAQUE_FRAME :
584  MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
585 #else
586  s->out_mem_mode = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
587 #endif
588 
589  out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data;
590  out_frames_hwctx = out_frames_ctx->hwctx;
591 
592  out_frames_ctx->format = AV_PIX_FMT_QSV;
593  out_frames_ctx->width = FFALIGN(outlink->w, 32);
594  out_frames_ctx->height = FFALIGN(outlink->h, 32);
595  out_frames_ctx->sw_format = s->out_sw_format;
596  out_frames_ctx->initial_pool_size = 64;
597  if (avctx->extra_hw_frames > 0)
598  out_frames_ctx->initial_pool_size += avctx->extra_hw_frames;
599  out_frames_hwctx->frame_type = s->out_mem_mode;
600 
601  ret = av_hwframe_ctx_init(out_frames_ref);
602  if (ret < 0) {
603  av_buffer_unref(&out_frames_ref);
604  av_log(avctx, AV_LOG_ERROR, "Error creating frames_ctx for output pad.\n");
605  return ret;
606  }
607 
608  s->surface_ptrs_out = av_calloc(out_frames_hwctx->nb_surfaces,
609  sizeof(*s->surface_ptrs_out));
610  if (!s->surface_ptrs_out) {
611  av_buffer_unref(&out_frames_ref);
612  return AVERROR(ENOMEM);
613  }
614 
615  for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
616  s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
617  s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
618 
619  av_buffer_unref(&outlink->hw_frames_ctx);
620  outlink->hw_frames_ctx = out_frames_ref;
621  } else
622  s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
623 
624  /* extract the properties of the "master" session given to us */
625  ret = MFXQueryIMPL(device_hwctx->session, &impl);
626  if (ret == MFX_ERR_NONE)
627  ret = MFXQueryVersion(device_hwctx->session, &ver);
628  if (ret != MFX_ERR_NONE) {
629  av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n");
630  return AVERROR_UNKNOWN;
631  }
632 
633  if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
634  handle_type = MFX_HANDLE_VA_DISPLAY;
635  } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
636  handle_type = MFX_HANDLE_D3D11_DEVICE;
637  } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
638  handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
639  } else {
640  av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n");
641  return AVERROR_UNKNOWN;
642  }
643 
644  ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
645  if (ret < 0)
646  return ff_qsvvpp_print_error(avctx, ret, "Error getting the session handle");
647  else if (ret > 0) {
648  ff_qsvvpp_print_warning(avctx, ret, "Warning in getting the session handle");
649  return AVERROR_UNKNOWN;
650  }
651 
652  /* create a "slave" session with those same properties, to be used for vpp */
653  ret = ff_qsvvpp_create_mfx_session(avctx, device_hwctx->loader, impl, &ver,
654  &s->session);
655  if (ret)
656  return ret;
657 
658  if (handle) {
659  ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
660  if (ret != MFX_ERR_NONE)
661  return AVERROR_UNKNOWN;
662  }
663 
664  if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
665  ret = MFXJoinSession(device_hwctx->session, s->session);
666  if (ret != MFX_ERR_NONE)
667  return AVERROR_UNKNOWN;
668  }
669 
670 #if QSV_HAVE_OPAQUE
671  if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
672  s->opaque_alloc.In.Surfaces = s->surface_ptrs_in;
673  s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
674  s->opaque_alloc.In.Type = s->in_mem_mode;
675 
676  s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out;
677  s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out;
678  s->opaque_alloc.Out.Type = s->out_mem_mode;
679 
680  s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
681  s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
682  } else
683 #endif
684  if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) {
685  mfxFrameAllocator frame_allocator = {
686  .pthis = s,
687  .Alloc = frame_alloc,
688  .Lock = frame_lock,
689  .Unlock = frame_unlock,
690  .GetHDL = frame_get_hdl,
691  .Free = frame_free,
692  };
693 
694  ret = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator);
695  if (ret != MFX_ERR_NONE)
696  return AVERROR_UNKNOWN;
697  }
698 
699  return 0;
700 }
701 
703 {
704  int i;
705  int ret;
706  QSVVPPContext *s = avctx->priv;
707 
708  s->filter_frame = param->filter_frame;
709  if (!s->filter_frame)
710  s->filter_frame = ff_filter_frame;
711  s->out_sw_format = param->out_sw_format;
712 
713  /* create the vpp session */
714  ret = init_vpp_session(avctx, s);
715  if (ret < 0)
716  goto failed;
717 
718  s->frame_infos = av_calloc(avctx->nb_inputs, sizeof(*s->frame_infos));
719  if (!s->frame_infos) {
720  ret = AVERROR(ENOMEM);
721  goto failed;
722  }
723 
724  /* Init each input's information */
725  for (i = 0; i < avctx->nb_inputs; i++) {
726  ret = fill_frameinfo_by_link(&s->frame_infos[i], avctx->inputs[i]);
727  if (ret < 0)
728  goto failed;
729  }
730 
731  /* Update input's frame info according to crop */
732  for (i = 0; i < param->num_crop; i++) {
733  QSVVPPCrop *crop = param->crop + i;
734  if (crop->in_idx > avctx->nb_inputs) {
735  ret = AVERROR(EINVAL);
736  goto failed;
737  }
738  s->frame_infos[crop->in_idx].CropX = crop->x;
739  s->frame_infos[crop->in_idx].CropY = crop->y;
740  s->frame_infos[crop->in_idx].CropW = crop->w;
741  s->frame_infos[crop->in_idx].CropH = crop->h;
742  }
743 
744  s->vpp_param.vpp.In = s->frame_infos[0];
745 
746  ret = fill_frameinfo_by_link(&s->vpp_param.vpp.Out, avctx->outputs[0]);
747  if (ret < 0) {
748  av_log(avctx, AV_LOG_ERROR, "Fail to get frame info from link.\n");
749  goto failed;
750  }
751 
752 #if QSV_HAVE_OPAQUE
753  if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
754  s->nb_ext_buffers = param->num_ext_buf + 1;
755  s->ext_buffers = av_calloc(s->nb_ext_buffers, sizeof(*s->ext_buffers));
756  if (!s->ext_buffers) {
757  ret = AVERROR(ENOMEM);
758  goto failed;
759  }
760 
761  s->ext_buffers[0] = (mfxExtBuffer *)&s->opaque_alloc;
762  for (i = 1; i < param->num_ext_buf; i++)
763  s->ext_buffers[i] = param->ext_buf[i - 1];
764  s->vpp_param.ExtParam = s->ext_buffers;
765  s->vpp_param.NumExtParam = s->nb_ext_buffers;
766  } else {
767  s->vpp_param.NumExtParam = param->num_ext_buf;
768  s->vpp_param.ExtParam = param->ext_buf;
769  }
770 #else
771  s->vpp_param.NumExtParam = param->num_ext_buf;
772  s->vpp_param.ExtParam = param->ext_buf;
773 #endif
774 
775  s->got_frame = 0;
776 
777  /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */
778  s->async_fifo = av_fifo_alloc2(s->async_depth + 1, sizeof(QSVAsyncFrame), 0);
779  if (!s->async_fifo) {
780  ret = AVERROR(ENOMEM);
781  goto failed;
782  }
783 
784  s->vpp_param.AsyncDepth = s->async_depth;
785 
786  if (IS_SYSTEM_MEMORY(s->in_mem_mode))
787  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
788  else if (IS_VIDEO_MEMORY(s->in_mem_mode))
789  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY;
790 #if QSV_HAVE_OPAQUE
791  else if (IS_OPAQUE_MEMORY(s->in_mem_mode))
792  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY;
793 #endif
794 
795  if (IS_SYSTEM_MEMORY(s->out_mem_mode))
796  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
797  else if (IS_VIDEO_MEMORY(s->out_mem_mode))
798  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY;
799 #if QSV_HAVE_OPAQUE
800  else if (IS_OPAQUE_MEMORY(s->out_mem_mode))
801  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
802 #endif
803 
804  /* Print input memory mode */
805  ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0x0F, "VPP");
806  /* Print output memory mode */
807  ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0xF0, "VPP");
808  ret = MFXVideoVPP_Init(s->session, &s->vpp_param);
809  if (ret < 0) {
810  ret = ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp");
811  goto failed;
812  } else if (ret > 0)
813  ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp");
814 
815  return 0;
816 
817 failed:
818  ff_qsvvpp_close(avctx);
819 
820  return ret;
821 }
822 
824 {
825  QSVVPPContext *s = avctx->priv;
826 
827  if (s->session) {
828  MFXVideoVPP_Close(s->session);
829  MFXClose(s->session);
830  s->session = NULL;
831  }
832 
833  /* release all the resources */
834  clear_frame_list(&s->in_frame_list);
835  clear_frame_list(&s->out_frame_list);
836  av_freep(&s->surface_ptrs_in);
837  av_freep(&s->surface_ptrs_out);
838 #if QSV_HAVE_OPAQUE
839  av_freep(&s->ext_buffers);
840 #endif
841  av_freep(&s->frame_infos);
842  av_fifo_freep2(&s->async_fifo);
843 
844  return 0;
845 }
846 
848 {
849  AVFilterContext *ctx = inlink->dst;
850  AVFilterLink *outlink = ctx->outputs[0];
851  QSVAsyncFrame aframe;
852  mfxSyncPoint sync;
853  QSVFrame *in_frame, *out_frame;
854  int ret, ret1, filter_ret;
855 
856  while (s->eof && av_fifo_read(s->async_fifo, &aframe, 1) >= 0) {
857  if (MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000) < 0)
858  av_log(ctx, AV_LOG_WARNING, "Sync failed.\n");
859 
860  filter_ret = s->filter_frame(outlink, aframe.frame->frame);
861  if (filter_ret < 0) {
862  av_frame_free(&aframe.frame->frame);
863  return filter_ret;
864  }
865  aframe.frame->queued--;
866  s->got_frame = 1;
867  aframe.frame->frame = NULL;
868  };
869 
870  if (!picref)
871  return 0;
872 
873  in_frame = submit_frame(s, inlink, picref);
874  if (!in_frame) {
875  av_log(ctx, AV_LOG_ERROR, "Failed to submit frame on input[%d]\n",
877  return AVERROR(ENOMEM);
878  }
879 
880  do {
881  out_frame = query_frame(s, outlink);
882  if (!out_frame) {
883  av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n");
884  return AVERROR(ENOMEM);
885  }
886 
887  do {
888  ret = MFXVideoVPP_RunFrameVPPAsync(s->session, &in_frame->surface,
889  &out_frame->surface, NULL, &sync);
890  if (ret == MFX_WRN_DEVICE_BUSY)
891  av_usleep(500);
892  } while (ret == MFX_WRN_DEVICE_BUSY);
893 
894  if (ret < 0 && ret != MFX_ERR_MORE_SURFACE) {
895  /* Ignore more_data error */
896  if (ret == MFX_ERR_MORE_DATA)
897  return AVERROR(EAGAIN);
898  break;
899  }
900  out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp,
901  default_tb, outlink->time_base);
902 
903  out_frame->queued++;
904  aframe = (QSVAsyncFrame){ sync, out_frame };
905  av_fifo_write(s->async_fifo, &aframe, 1);
906 
907  if (av_fifo_can_read(s->async_fifo) > s->async_depth) {
908  av_fifo_read(s->async_fifo, &aframe, 1);
909 
910  do {
911  ret1 = MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000);
912  } while (ret1 == MFX_WRN_IN_EXECUTION);
913 
914  if (ret1 < 0) {
915  ret = ret1;
916  break;
917  }
918 
919  filter_ret = s->filter_frame(outlink, aframe.frame->frame);
920  if (filter_ret < 0) {
921  av_frame_free(&aframe.frame->frame);
922  return filter_ret;
923  }
924 
925  aframe.frame->queued--;
926  s->got_frame = 1;
927  aframe.frame->frame = NULL;
928  }
929  } while(ret == MFX_ERR_MORE_SURFACE);
930 
931  if (ret < 0)
932  return ff_qsvvpp_print_error(ctx, ret, "Error running VPP");
933  else if (ret > 0)
934  ff_qsvvpp_print_warning(ctx, ret, "Warning in running VPP");
935 
936  return 0;
937 }
938 
939 #if QSV_ONEVPL
940 
942  void *loader,
943  mfxIMPL implementation,
944  mfxVersion *pver,
945  mfxSession *psession)
946 {
947  mfxStatus sts;
948  mfxSession session = NULL;
949  uint32_t impl_idx = 0;
950 
952  "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
953 
954  if (!loader) {
955  av_log(ctx, AV_LOG_ERROR, "Invalid MFX Loader handle\n");
956  return AVERROR(EINVAL);
957  }
958 
959  while (1) {
960  /* Enumerate all implementations */
961  mfxImplDescription *impl_desc;
962 
963  sts = MFXEnumImplementations(loader, impl_idx,
964  MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
965  (mfxHDL *)&impl_desc);
966  /* Failed to find an available implementation */
967  if (sts == MFX_ERR_NOT_FOUND)
968  break;
969  else if (sts != MFX_ERR_NONE) {
970  impl_idx++;
971  continue;
972  }
973 
974  sts = MFXCreateSession(loader, impl_idx, &session);
975  MFXDispReleaseImplDescription(loader, impl_desc);
976  if (sts == MFX_ERR_NONE)
977  break;
978 
979  impl_idx++;
980  }
981 
982  if (sts < 0)
983  return ff_qsvvpp_print_error(ctx, sts,
984  "Error creating a MFX session");
985  else if (sts > 0) {
987  "Warning in MFX session creation");
988  return AVERROR_UNKNOWN;
989  }
990 
991  *psession = session;
992 
993  return 0;
994 }
995 
996 #else
997 
999  void *loader,
1000  mfxIMPL implementation,
1001  mfxVersion *pver,
1002  mfxSession *psession)
1003 {
1004  mfxSession session = NULL;
1005  mfxStatus sts;
1006 
1008  "Use Intel(R) Media SDK to create MFX session, API version is "
1009  "%d.%d, the required implementation version is %d.%d\n",
1010  MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1011 
1012  *psession = NULL;
1013  sts = MFXInit(implementation, pver, &session);
1014  if (sts < 0)
1015  return ff_qsvvpp_print_error(ctx, sts,
1016  "Error initializing an MFX session");
1017  else if (sts > 0) {
1018  ff_qsvvpp_print_warning(ctx, sts, "Warning in MFX session initialization");
1019  return AVERROR_UNKNOWN;
1020  }
1021 
1022  *psession = session;
1023 
1024  return 0;
1025 }
1026 
1027 #endif
1028 
1030 {
1031  /* When process YUV420 frames, FFmpeg uses same alignment on Y/U/V
1032  * planes. VPL and MSDK use Y plane's pitch / 2 as U/V planes's
1033  * pitch, which makes U/V planes 16-bytes aligned. We need to set a
1034  * separate alignment to meet runtime's behaviour.
1035  */
1037  FFALIGN(inlink->w, 32),
1038  FFALIGN(inlink->h, 32),
1039  16);
1040 }
ff_default_get_video_buffer2
AVFrame * ff_default_get_video_buffer2(AVFilterLink *link, int w, int h, int align)
Definition: video.c:41
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:101
frame_get_hdl
static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition: qsvvpp.c:225
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
QSVVPPCrop::in_idx
int in_idx
Input index.
Definition: qsvvpp.h:89
AVQSVFramesContext::frame_type
int frame_type
A combination of MFX_MEMTYPE_* describing the frame pool.
Definition: hwcontext_qsv.h:60
mfx_iopattern
int mfx_iopattern
Definition: qsvvpp.c:57
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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
IS_OPAQUE_MEMORY
#define IS_OPAQUE_MEMORY(mode)
Definition: qsvvpp.c:42
out
FILE * out
Definition: movenc.c:54
init_vpp_session
static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
Definition: qsvvpp.c:531
frame_alloc
static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition: qsvvpp.c:175
QSVVPPParam::crop
QSVVPPCrop * crop
Definition: qsvvpp.h:106
QSVVPPParam::out_sw_format
enum AVPixelFormat out_sw_format
Definition: qsvvpp.h:102
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:969
AVFrame::duration
int64_t duration
Duration of the frame, in the same units as pts.
Definition: frame.h:728
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2888
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:209
ff_qsvvpp_get_video_buffer
AVFrame * ff_qsvvpp_get_video_buffer(AVFilterLink *inlink, int w, int h)
Definition: qsvvpp.c:1029
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:99
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:334
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
pixdesc.h
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:437
AVFrame::width
int width
Definition: frame.h:402
AVQSVDeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_qsv.h:35
w
uint8_t w
Definition: llviddspenc.c:38
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:248
AVFrame::top_field_first
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:491
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AVFilterContext::hw_device_ctx
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in.
Definition: avfilter.h:448
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
mathematics.h
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:229
video.h
QSVFrame::frame
AVFrame * frame
Definition: qsv_internal.h:81
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:351
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:407
qsvvpp.h
av_fifo_write
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition: fifo.c:188
AVFilterContext::extra_hw_frames
int extra_hw_frames
Sets the number of extra hardware frames which the filter will allocate on its output links for use i...
Definition: avfilter.h:478
clear_unused_frames
static void clear_unused_frames(QSVFrame *list)
Definition: qsvvpp.c:352
AVRational::num
int num
Numerator.
Definition: rational.h:59
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:87
ff_qsvvpp_print_iopattern
int ff_qsvvpp_print_iopattern(void *log_ctx, int mfx_iopattern, const char *extra_string)
Definition: qsvvpp.c:72
MFX_IMPL_VIA_MASK
#define MFX_IMPL_VIA_MASK(impl)
Definition: qsvvpp.c:45
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_fifo_read
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition: fifo.c:240
AVHWFramesContext::height
int height
Definition: hwcontext.h:229
QSVVPPCrop::w
int w
Definition: qsvvpp.h:90
s
#define s(width, name)
Definition: cbs_vp9.c:256
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
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
QSV_RUNTIME_VERSION_ATLEAST
#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR)
Definition: qsv_internal.h:64
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:465
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
default_tb
static const AVRational default_tb
Definition: qsvvpp.c:49
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_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
link
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 link
Definition: filter_design.txt:23
if
if(ret)
Definition: filter_design.txt:179
fill_frameinfo_by_link
static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
Definition: qsvvpp.c:297
QSVFrame
Definition: qsv_internal.h:80
QSVVPPContext
Definition: qsvvpp.h:55
ff_qsvvpp_close
int ff_qsvvpp_close(AVFilterContext *avctx)
Definition: qsvvpp.c:823
AVQSVFramesContext::surfaces
mfxFrameSurface1 * surfaces
Definition: hwcontext_qsv.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:222
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:594
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:139
QSVVPPParam::num_crop
int num_crop
Definition: qsvvpp.h:105
QSVVPPParam
Definition: qsvvpp.h:93
QSVVPPCrop::x
int x
Definition: qsvvpp.h:90
qsv_errors
static const struct @232 qsv_errors[]
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVHWFramesContext::device_ref
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:141
pix_fmt_to_mfx_fourcc
static int pix_fmt_to_mfx_fourcc(int format)
Definition: qsvvpp.c:237
ff_qsvvpp_print_error
int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition: qsvvpp.c:154
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:400
av_fifo_can_read
size_t av_fifo_can_read(const AVFifo *f)
Definition: fifo.c:87
list
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 list
Definition: filter_design.txt:25
QSVFrame::surface
mfxFrameSurface1 surface
Definition: qsv_internal.h:82
time.h
AV_PIX_FMT_QSV
@ AV_PIX_FMT_QSV
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:240
AVFilterContext::nb_inputs
unsigned nb_inputs
number of input pads
Definition: avfilter.h:401
av_frame_copy
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:762
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
IS_VIDEO_MEMORY
#define IS_VIDEO_MEMORY(mode)
Definition: qsvvpp.c:39
frame_unlock
static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsvvpp.c:220
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:417
mfxerr
mfxStatus mfxerr
Definition: qsvvpp.c:90
AV_PIX_FMT_RGB32
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:432
AVQSVDeviceContext::loader
void * loader
The mfxLoader handle used for mfxSession creation.
Definition: hwcontext_qsv.h:47
AVQSVFramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_qsv.h:55
internal.h
QSVAsyncFrame::frame
QSVFrame * frame
Definition: qsvdec.c:72
AVFrame::interlaced_frame
int interlaced_frame
The content of the picture is interlaced.
Definition: frame.h:486
QSVAsyncFrame::sync
mfxSyncPoint sync
Definition: qsvvpp.c:52
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
common.h
desc
const char * desc
Definition: qsvvpp.c:58
QSVVPPParam::num_ext_buf
int num_ext_buf
Definition: qsvvpp.h:98
frame_lock
static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: qsvvpp.c:215
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
QSVVPPParam::filter_frame
int(* filter_frame)(AVFilterLink *outlink, AVFrame *frame)
Definition: qsvvpp.h:95
ff_qsvvpp_init
int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param)
Definition: qsvvpp.c:702
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:262
map_frame_to_surface
static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface)
Definition: qsvvpp.c:259
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
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
QSVFrame::queued
int queued
Definition: qsv_internal.h:100
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:162
av_fifo_alloc2
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition: fifo.c:47
AVFrame::sample_aspect_ratio
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition: frame.h:432
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:81
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:678
QSVVPPCrop::h
int h
Crop rectangle.
Definition: qsvvpp.h:90
QSVVPPCrop::y
int y
Definition: qsvvpp.h:90
AVFrame::height
int height
Definition: frame.h:402
ff_qsvvpp_filter_frame
int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref)
Definition: qsvvpp.c:847
AVQSVDeviceContext::session
mfxSession session
Definition: hwcontext_qsv.h:36
AVRational::den
int den
Denominator.
Definition: rational.h:60
averr
int averr
Definition: qsvvpp.c:91
FF_INLINK_IDX
#define FF_INLINK_IDX(link)
Find the index of a link.
Definition: internal.h:337
qsv_map_error
static int qsv_map_error(mfxStatus mfx_err, const char **desc)
Definition: qsvvpp.c:139
clear_frame_list
static void clear_frame_list(QSVFrame **list)
Definition: qsvvpp.c:365
AVFilterContext
An instance of a filter.
Definition: avfilter.h:392
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:508
qsv_iopatterns
static const struct @231 qsv_iopatterns[]
AVQSVFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_qsv.h:53
AVHWFramesContext::initial_pool_size
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:199
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
QSVAsyncFrame::sync
mfxSyncPoint * sync
Definition: qsvdec.c:71
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:375
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_fifo_freep2
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition: fifo.c:286
h
h
Definition: vp9dsp_template.c:2038
IS_SYSTEM_MEMORY
#define IS_SYSTEM_MEMORY(mode)
Definition: qsvvpp.c:44
QSVVPPCrop
Definition: qsvvpp.h:88
get_free_frame
static QSVFrame * get_free_frame(QSVFrame **list)
Definition: qsvvpp.c:377
QSVAsyncFrame
Definition: qsvdec.c:70
ff_qsvvpp_create_mfx_session
int ff_qsvvpp_create_mfx_session(void *ctx, void *loader, mfxIMPL implementation, mfxVersion *pver, mfxSession *psession)
Definition: qsvvpp.c:998
av_hwframe_get_buffer
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:507
frame_free
static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition: qsvvpp.c:209
ff_qsvvpp_print_warning
int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
Definition: qsvvpp.c:164
AVFrame::repeat_pict
int repeat_pict
When decoding, this signals how much the picture must be delayed.
Definition: frame.h:481
QSVVPPParam::ext_buf
mfxExtBuffer ** ext_buf
Definition: qsvvpp.h:99
submit_frame
static QSVFrame * submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref)
Definition: qsvvpp.c:403
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:404
query_frame
static QSVFrame * query_frame(QSVVPPContext *s, AVFilterLink *outlink)
Definition: qsvvpp.c:477