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  }
249 
250  return MFX_FOURCC_NV12;
251 }
252 
253 static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface)
254 {
255  switch (frame->format) {
256  case AV_PIX_FMT_NV12:
257  case AV_PIX_FMT_P010:
258  surface->Data.Y = frame->data[0];
259  surface->Data.UV = frame->data[1];
260  break;
261  case AV_PIX_FMT_YUV420P:
262  surface->Data.Y = frame->data[0];
263  surface->Data.U = frame->data[1];
264  surface->Data.V = frame->data[2];
265  break;
266  case AV_PIX_FMT_YUYV422:
267  surface->Data.Y = frame->data[0];
268  surface->Data.U = frame->data[0] + 1;
269  surface->Data.V = frame->data[0] + 3;
270  break;
271  case AV_PIX_FMT_RGB32:
272  surface->Data.B = frame->data[0];
273  surface->Data.G = frame->data[0] + 1;
274  surface->Data.R = frame->data[0] + 2;
275  surface->Data.A = frame->data[0] + 3;
276  break;
277  default:
278  return MFX_ERR_UNSUPPORTED;
279  }
280  surface->Data.Pitch = frame->linesize[0];
281 
282  return 0;
283 }
284 
285 /* fill the surface info */
286 static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
287 {
288  enum AVPixelFormat pix_fmt;
289  AVHWFramesContext *frames_ctx;
290  AVQSVFramesContext *frames_hwctx;
291  const AVPixFmtDescriptor *desc;
292 
293  if (link->format == AV_PIX_FMT_QSV) {
294  if (!link->hw_frames_ctx)
295  return AVERROR(EINVAL);
296 
297  frames_ctx = (AVHWFramesContext *)link->hw_frames_ctx->data;
298  frames_hwctx = frames_ctx->hwctx;
299  *frameinfo = frames_hwctx->surfaces[0].Info;
300  } else {
301  pix_fmt = link->format;
303  if (!desc)
304  return AVERROR_BUG;
305 
306  frameinfo->CropX = 0;
307  frameinfo->CropY = 0;
308  frameinfo->Width = FFALIGN(link->w, 32);
309  frameinfo->Height = FFALIGN(link->h, 32);
310  frameinfo->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
311  frameinfo->FourCC = pix_fmt_to_mfx_fourcc(pix_fmt);
312  frameinfo->BitDepthLuma = desc->comp[0].depth;
313  frameinfo->BitDepthChroma = desc->comp[0].depth;
314  frameinfo->Shift = desc->comp[0].depth > 8;
315  if (desc->log2_chroma_w && desc->log2_chroma_h)
316  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV420;
317  else if (desc->log2_chroma_w)
318  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV422;
319  else
320  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV444;
321  }
322 
323  frameinfo->CropW = link->w;
324  frameinfo->CropH = link->h;
325  frameinfo->FrameRateExtN = link->frame_rate.num;
326  frameinfo->FrameRateExtD = link->frame_rate.den;
327 
328  /* Apparently VPP in the SDK requires the frame rate to be set to some value, otherwise
329  * init will fail */
330  if (frameinfo->FrameRateExtD == 0 || frameinfo->FrameRateExtN == 0) {
331  frameinfo->FrameRateExtN = 25;
332  frameinfo->FrameRateExtD = 1;
333  }
334 
335  frameinfo->AspectRatioW = link->sample_aspect_ratio.num ? link->sample_aspect_ratio.num : 1;
336  frameinfo->AspectRatioH = link->sample_aspect_ratio.den ? link->sample_aspect_ratio.den : 1;
337 
338  return 0;
339 }
340 
342 {
343  while (list) {
344  /* list->queued==1 means the frame is not cached in VPP
345  * process any more, it can be released to pool. */
346  if ((list->queued == 1) && !list->surface.Data.Locked) {
347  av_frame_free(&list->frame);
348  list->queued = 0;
349  }
350  list = list->next;
351  }
352 }
353 
355 {
356  while (*list) {
357  QSVFrame *frame;
358 
359  frame = *list;
360  *list = (*list)->next;
361  av_frame_free(&frame->frame);
362  av_freep(&frame);
363  }
364 }
365 
367 {
368  QSVFrame *out = *list;
369 
370  for (; out; out = out->next) {
371  if (!out->queued) {
372  out->queued = 1;
373  break;
374  }
375  }
376 
377  if (!out) {
378  out = av_mallocz(sizeof(*out));
379  if (!out) {
380  av_log(NULL, AV_LOG_ERROR, "Can't alloc new output frame.\n");
381  return NULL;
382  }
383  out->queued = 1;
384  out->next = *list;
385  *list = out;
386  }
387 
388  return out;
389 }
390 
391 /* get the input surface */
393 {
394  QSVFrame *qsv_frame;
395  AVFilterContext *ctx = inlink->dst;
396 
397  clear_unused_frames(s->in_frame_list);
398 
399  qsv_frame = get_free_frame(&s->in_frame_list);
400  if (!qsv_frame)
401  return NULL;
402 
403  /* Turn AVFrame into mfxFrameSurface1.
404  * For video/opaque memory mode, pix_fmt is AV_PIX_FMT_QSV, and
405  * mfxFrameSurface1 is stored in AVFrame->data[3];
406  * for system memory mode, raw video data is stored in
407  * AVFrame, we should map it into mfxFrameSurface1.
408  */
409  if (!IS_SYSTEM_MEMORY(s->in_mem_mode)) {
410  if (picref->format != AV_PIX_FMT_QSV) {
411  av_log(ctx, AV_LOG_ERROR, "QSVVPP gets a wrong frame.\n");
412  return NULL;
413  }
414  qsv_frame->frame = av_frame_clone(picref);
415  qsv_frame->surface = *(mfxFrameSurface1 *)qsv_frame->frame->data[3];
416  } else {
417  /* make a copy if the input is not padded as libmfx requires */
418  if (picref->height & 31 || picref->linesize[0] & 31) {
419  qsv_frame->frame = ff_get_video_buffer(inlink,
420  FFALIGN(inlink->w, 32),
421  FFALIGN(inlink->h, 32));
422  if (!qsv_frame->frame)
423  return NULL;
424 
425  qsv_frame->frame->width = picref->width;
426  qsv_frame->frame->height = picref->height;
427 
428  if (av_frame_copy(qsv_frame->frame, picref) < 0) {
429  av_frame_free(&qsv_frame->frame);
430  return NULL;
431  }
432 
433  av_frame_copy_props(qsv_frame->frame, picref);
434  } else
435  qsv_frame->frame = av_frame_clone(picref);
436 
437  if (map_frame_to_surface(qsv_frame->frame,
438  &qsv_frame->surface) < 0) {
439  av_log(ctx, AV_LOG_ERROR, "Unsupported frame.\n");
440  return NULL;
441  }
442  }
443 
444  qsv_frame->surface.Info = s->frame_infos[FF_INLINK_IDX(inlink)];
445  qsv_frame->surface.Data.TimeStamp = av_rescale_q(qsv_frame->frame->pts,
446  inlink->time_base, default_tb);
447 
448  qsv_frame->surface.Info.PicStruct =
449  !qsv_frame->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
450  (qsv_frame->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF :
451  MFX_PICSTRUCT_FIELD_BFF);
452  if (qsv_frame->frame->repeat_pict == 1)
453  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
454  else if (qsv_frame->frame->repeat_pict == 2)
455  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
456  else if (qsv_frame->frame->repeat_pict == 4)
457  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
458 
459  return qsv_frame;
460 }
461 
462 /* get the output surface */
464 {
465  AVFilterContext *ctx = outlink->src;
466  QSVFrame *out_frame;
467  int ret;
468 
469  clear_unused_frames(s->out_frame_list);
470 
471  out_frame = get_free_frame(&s->out_frame_list);
472  if (!out_frame)
473  return NULL;
474 
475  /* For video memory, get a hw frame;
476  * For system memory, get a sw frame and map it into a mfx_surface. */
477  if (!IS_SYSTEM_MEMORY(s->out_mem_mode)) {
478  out_frame->frame = av_frame_alloc();
479  if (!out_frame->frame)
480  return NULL;
481 
482  ret = av_hwframe_get_buffer(outlink->hw_frames_ctx, out_frame->frame, 0);
483  if (ret < 0) {
484  av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n");
485  return NULL;
486  }
487 
488  out_frame->surface = *(mfxFrameSurface1 *)out_frame->frame->data[3];
489  } else {
490  /* Get a frame with aligned dimensions.
491  * Libmfx need system memory being 128x64 aligned */
492  out_frame->frame = ff_get_video_buffer(outlink,
493  FFALIGN(outlink->w, 128),
494  FFALIGN(outlink->h, 64));
495  if (!out_frame->frame)
496  return NULL;
497 
498  ret = map_frame_to_surface(out_frame->frame,
499  &out_frame->surface);
500  if (ret < 0)
501  return NULL;
502  }
503 
504  out_frame->frame->width = outlink->w;
505  out_frame->frame->height = outlink->h;
506  out_frame->surface.Info = s->vpp_param.vpp.Out;
507 
508  return out_frame;
509 }
510 
511 /* create the QSV session */
513 {
514  AVFilterLink *inlink = avctx->inputs[0];
515  AVFilterLink *outlink = avctx->outputs[0];
516  AVQSVFramesContext *in_frames_hwctx = NULL;
517  AVQSVFramesContext *out_frames_hwctx = NULL;
518 
519  AVBufferRef *device_ref;
520  AVHWDeviceContext *device_ctx;
521  AVQSVDeviceContext *device_hwctx;
522  mfxHDL handle;
523  mfxHandleType handle_type;
524  mfxVersion ver;
525  mfxIMPL impl;
526  int ret, i;
527 
528  if (inlink->hw_frames_ctx) {
529  AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
530 
531  device_ref = frames_ctx->device_ref;
532  in_frames_hwctx = frames_ctx->hwctx;
533 
534  s->in_mem_mode = in_frames_hwctx->frame_type;
535 
536  s->surface_ptrs_in = av_calloc(in_frames_hwctx->nb_surfaces,
537  sizeof(*s->surface_ptrs_in));
538  if (!s->surface_ptrs_in)
539  return AVERROR(ENOMEM);
540 
541  for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
542  s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i;
543 
544  s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces;
545  } else if (avctx->hw_device_ctx) {
546  device_ref = avctx->hw_device_ctx;
547  s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
548  } else {
549  av_log(avctx, AV_LOG_ERROR, "No hw context provided.\n");
550  return AVERROR(EINVAL);
551  }
552 
553  device_ctx = (AVHWDeviceContext *)device_ref->data;
554  device_hwctx = device_ctx->hwctx;
555 
556  if (outlink->format == AV_PIX_FMT_QSV) {
557  AVHWFramesContext *out_frames_ctx;
558  AVBufferRef *out_frames_ref = av_hwframe_ctx_alloc(device_ref);
559  if (!out_frames_ref)
560  return AVERROR(ENOMEM);
561 
562 #if QSV_HAVE_OPAQUE
563  s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ?
564  MFX_MEMTYPE_OPAQUE_FRAME :
565  MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
566 #else
567  s->out_mem_mode = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
568 #endif
569 
570  out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data;
571  out_frames_hwctx = out_frames_ctx->hwctx;
572 
573  out_frames_ctx->format = AV_PIX_FMT_QSV;
574  out_frames_ctx->width = FFALIGN(outlink->w, 32);
575  out_frames_ctx->height = FFALIGN(outlink->h, 32);
576  out_frames_ctx->sw_format = s->out_sw_format;
577  out_frames_ctx->initial_pool_size = 64;
578  if (avctx->extra_hw_frames > 0)
579  out_frames_ctx->initial_pool_size += avctx->extra_hw_frames;
580  out_frames_hwctx->frame_type = s->out_mem_mode;
581 
582  ret = av_hwframe_ctx_init(out_frames_ref);
583  if (ret < 0) {
584  av_buffer_unref(&out_frames_ref);
585  av_log(avctx, AV_LOG_ERROR, "Error creating frames_ctx for output pad.\n");
586  return ret;
587  }
588 
589  s->surface_ptrs_out = av_calloc(out_frames_hwctx->nb_surfaces,
590  sizeof(*s->surface_ptrs_out));
591  if (!s->surface_ptrs_out) {
592  av_buffer_unref(&out_frames_ref);
593  return AVERROR(ENOMEM);
594  }
595 
596  for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
597  s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
598  s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
599 
600  av_buffer_unref(&outlink->hw_frames_ctx);
601  outlink->hw_frames_ctx = out_frames_ref;
602  } else
603  s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
604 
605  /* extract the properties of the "master" session given to us */
606  ret = MFXQueryIMPL(device_hwctx->session, &impl);
607  if (ret == MFX_ERR_NONE)
608  ret = MFXQueryVersion(device_hwctx->session, &ver);
609  if (ret != MFX_ERR_NONE) {
610  av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n");
611  return AVERROR_UNKNOWN;
612  }
613 
614  if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
615  handle_type = MFX_HANDLE_VA_DISPLAY;
616  } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
617  handle_type = MFX_HANDLE_D3D11_DEVICE;
618  } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
619  handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
620  } else {
621  av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n");
622  return AVERROR_UNKNOWN;
623  }
624 
625  ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
626  if (ret < 0)
627  return ff_qsvvpp_print_error(avctx, ret, "Error getting the session handle");
628  else if (ret > 0) {
629  ff_qsvvpp_print_warning(avctx, ret, "Warning in getting the session handle");
630  return AVERROR_UNKNOWN;
631  }
632 
633  /* create a "slave" session with those same properties, to be used for vpp */
634  ret = ff_qsvvpp_create_mfx_session(avctx, device_hwctx->loader, impl, &ver,
635  &s->session);
636  if (ret)
637  return ret;
638 
639  if (handle) {
640  ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
641  if (ret != MFX_ERR_NONE)
642  return AVERROR_UNKNOWN;
643  }
644 
645  if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
646  ret = MFXJoinSession(device_hwctx->session, s->session);
647  if (ret != MFX_ERR_NONE)
648  return AVERROR_UNKNOWN;
649  }
650 
651 #if QSV_HAVE_OPAQUE
652  if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
653  s->opaque_alloc.In.Surfaces = s->surface_ptrs_in;
654  s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
655  s->opaque_alloc.In.Type = s->in_mem_mode;
656 
657  s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out;
658  s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out;
659  s->opaque_alloc.Out.Type = s->out_mem_mode;
660 
661  s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
662  s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
663  } else
664 #endif
665  if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) {
666  mfxFrameAllocator frame_allocator = {
667  .pthis = s,
668  .Alloc = frame_alloc,
669  .Lock = frame_lock,
670  .Unlock = frame_unlock,
671  .GetHDL = frame_get_hdl,
672  .Free = frame_free,
673  };
674 
675  ret = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator);
676  if (ret != MFX_ERR_NONE)
677  return AVERROR_UNKNOWN;
678  }
679 
680  return 0;
681 }
682 
684 {
685  int i;
686  int ret;
687  QSVVPPContext *s;
688 
689  s = av_mallocz(sizeof(*s));
690  if (!s)
691  return AVERROR(ENOMEM);
692 
693  s->filter_frame = param->filter_frame;
694  if (!s->filter_frame)
695  s->filter_frame = ff_filter_frame;
696  s->out_sw_format = param->out_sw_format;
697 
698  /* create the vpp session */
699  ret = init_vpp_session(avctx, s);
700  if (ret < 0)
701  goto failed;
702 
703  s->frame_infos = av_calloc(avctx->nb_inputs, sizeof(*s->frame_infos));
704  if (!s->frame_infos) {
705  ret = AVERROR(ENOMEM);
706  goto failed;
707  }
708 
709  /* Init each input's information */
710  for (i = 0; i < avctx->nb_inputs; i++) {
711  ret = fill_frameinfo_by_link(&s->frame_infos[i], avctx->inputs[i]);
712  if (ret < 0)
713  goto failed;
714  }
715 
716  /* Update input's frame info according to crop */
717  for (i = 0; i < param->num_crop; i++) {
718  QSVVPPCrop *crop = param->crop + i;
719  if (crop->in_idx > avctx->nb_inputs) {
720  ret = AVERROR(EINVAL);
721  goto failed;
722  }
723  s->frame_infos[crop->in_idx].CropX = crop->x;
724  s->frame_infos[crop->in_idx].CropY = crop->y;
725  s->frame_infos[crop->in_idx].CropW = crop->w;
726  s->frame_infos[crop->in_idx].CropH = crop->h;
727  }
728 
729  s->vpp_param.vpp.In = s->frame_infos[0];
730 
731  ret = fill_frameinfo_by_link(&s->vpp_param.vpp.Out, avctx->outputs[0]);
732  if (ret < 0) {
733  av_log(avctx, AV_LOG_ERROR, "Fail to get frame info from link.\n");
734  goto failed;
735  }
736 
737 #if QSV_HAVE_OPAQUE
738  if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
739  s->nb_ext_buffers = param->num_ext_buf + 1;
740  s->ext_buffers = av_calloc(s->nb_ext_buffers, sizeof(*s->ext_buffers));
741  if (!s->ext_buffers) {
742  ret = AVERROR(ENOMEM);
743  goto failed;
744  }
745 
746  s->ext_buffers[0] = (mfxExtBuffer *)&s->opaque_alloc;
747  for (i = 1; i < param->num_ext_buf; i++)
748  s->ext_buffers[i] = param->ext_buf[i - 1];
749  s->vpp_param.ExtParam = s->ext_buffers;
750  s->vpp_param.NumExtParam = s->nb_ext_buffers;
751  } else {
752  s->vpp_param.NumExtParam = param->num_ext_buf;
753  s->vpp_param.ExtParam = param->ext_buf;
754  }
755 #else
756  s->vpp_param.NumExtParam = param->num_ext_buf;
757  s->vpp_param.ExtParam = param->ext_buf;
758 #endif
759 
760  s->got_frame = 0;
761 
762  /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */
763  s->async_fifo = av_fifo_alloc2(param->async_depth + 1, sizeof(QSVAsyncFrame), 0);
764  s->async_depth = param->async_depth;
765  if (!s->async_fifo) {
766  ret = AVERROR(ENOMEM);
767  goto failed;
768  }
769 
770  s->vpp_param.AsyncDepth = param->async_depth;
771 
772  if (IS_SYSTEM_MEMORY(s->in_mem_mode))
773  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
774  else if (IS_VIDEO_MEMORY(s->in_mem_mode))
775  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY;
776 #if QSV_HAVE_OPAQUE
777  else if (IS_OPAQUE_MEMORY(s->in_mem_mode))
778  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY;
779 #endif
780 
781  if (IS_SYSTEM_MEMORY(s->out_mem_mode))
782  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
783  else if (IS_VIDEO_MEMORY(s->out_mem_mode))
784  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY;
785 #if QSV_HAVE_OPAQUE
786  else if (IS_OPAQUE_MEMORY(s->out_mem_mode))
787  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
788 #endif
789 
790  /* Print input memory mode */
791  ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0x0F, "VPP");
792  /* Print output memory mode */
793  ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0xF0, "VPP");
794  ret = MFXVideoVPP_Init(s->session, &s->vpp_param);
795  if (ret < 0) {
796  ret = ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp");
797  goto failed;
798  } else if (ret > 0)
799  ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp");
800 
801  *vpp = s;
802  return 0;
803 
804 failed:
805  ff_qsvvpp_free(&s);
806 
807  return ret;
808 }
809 
811 {
812  QSVVPPContext *s = *vpp;
813 
814  if (!s)
815  return 0;
816 
817  if (s->session) {
818  MFXVideoVPP_Close(s->session);
819  MFXClose(s->session);
820  }
821 
822  /* release all the resources */
823  clear_frame_list(&s->in_frame_list);
824  clear_frame_list(&s->out_frame_list);
825  av_freep(&s->surface_ptrs_in);
826  av_freep(&s->surface_ptrs_out);
827 #if QSV_HAVE_OPAQUE
828  av_freep(&s->ext_buffers);
829 #endif
830  av_freep(&s->frame_infos);
831  av_fifo_freep2(&s->async_fifo);
832  av_freep(vpp);
833 
834  return 0;
835 }
836 
838 {
839  AVFilterContext *ctx = inlink->dst;
840  AVFilterLink *outlink = ctx->outputs[0];
841  QSVAsyncFrame aframe;
842  mfxSyncPoint sync;
843  QSVFrame *in_frame, *out_frame;
844  int ret, ret1, filter_ret;
845 
846  while (s->eof && av_fifo_read(s->async_fifo, &aframe, 1) >= 0) {
847  if (MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000) < 0)
848  av_log(ctx, AV_LOG_WARNING, "Sync failed.\n");
849 
850  filter_ret = s->filter_frame(outlink, aframe.frame->frame);
851  if (filter_ret < 0) {
852  av_frame_free(&aframe.frame->frame);
853  return filter_ret;
854  }
855  aframe.frame->queued--;
856  s->got_frame = 1;
857  aframe.frame->frame = NULL;
858  };
859 
860  if (!picref)
861  return 0;
862 
863  in_frame = submit_frame(s, inlink, picref);
864  if (!in_frame) {
865  av_log(ctx, AV_LOG_ERROR, "Failed to submit frame on input[%d]\n",
867  return AVERROR(ENOMEM);
868  }
869 
870  do {
871  out_frame = query_frame(s, outlink);
872  if (!out_frame) {
873  av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n");
874  return AVERROR(ENOMEM);
875  }
876 
877  do {
878  ret = MFXVideoVPP_RunFrameVPPAsync(s->session, &in_frame->surface,
879  &out_frame->surface, NULL, &sync);
880  if (ret == MFX_WRN_DEVICE_BUSY)
881  av_usleep(500);
882  } while (ret == MFX_WRN_DEVICE_BUSY);
883 
884  if (ret < 0 && ret != MFX_ERR_MORE_SURFACE) {
885  /* Ignore more_data error */
886  if (ret == MFX_ERR_MORE_DATA)
887  return AVERROR(EAGAIN);
888  break;
889  }
890  out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp,
891  default_tb, outlink->time_base);
892 
893  out_frame->queued++;
894  aframe = (QSVAsyncFrame){ sync, out_frame };
895  av_fifo_write(s->async_fifo, &aframe, 1);
896 
897  if (av_fifo_can_read(s->async_fifo) > s->async_depth) {
898  av_fifo_read(s->async_fifo, &aframe, 1);
899 
900  do {
901  ret1 = MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000);
902  } while (ret1 == MFX_WRN_IN_EXECUTION);
903 
904  if (ret1 < 0) {
905  ret = ret1;
906  break;
907  }
908 
909  filter_ret = s->filter_frame(outlink, aframe.frame->frame);
910  if (filter_ret < 0) {
911  av_frame_free(&aframe.frame->frame);
912  return filter_ret;
913  }
914 
915  aframe.frame->queued--;
916  s->got_frame = 1;
917  aframe.frame->frame = NULL;
918  }
919  } while(ret == MFX_ERR_MORE_SURFACE);
920 
921  if (ret < 0)
922  return ff_qsvvpp_print_error(ctx, ret, "Error running VPP");
923  else if (ret > 0)
924  ff_qsvvpp_print_warning(ctx, ret, "Warning in running VPP");
925 
926  return 0;
927 }
928 
929 #if QSV_ONEVPL
930 
932  void *loader,
933  mfxIMPL implementation,
934  mfxVersion *pver,
935  mfxSession *psession)
936 {
937  mfxStatus sts;
938  mfxSession session = NULL;
939  uint32_t impl_idx = 0;
940 
942  "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
943 
944  if (!loader) {
945  av_log(ctx, AV_LOG_ERROR, "Invalid MFX Loader handle\n");
946  return AVERROR(EINVAL);
947  }
948 
949  while (1) {
950  /* Enumerate all implementations */
951  mfxImplDescription *impl_desc;
952 
953  sts = MFXEnumImplementations(loader, impl_idx,
954  MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
955  (mfxHDL *)&impl_desc);
956  /* Failed to find an available implementation */
957  if (sts == MFX_ERR_NOT_FOUND)
958  break;
959  else if (sts != MFX_ERR_NONE) {
960  impl_idx++;
961  continue;
962  }
963 
964  sts = MFXCreateSession(loader, impl_idx, &session);
965  MFXDispReleaseImplDescription(loader, impl_desc);
966  if (sts == MFX_ERR_NONE)
967  break;
968 
969  impl_idx++;
970  }
971 
972  if (sts < 0)
973  return ff_qsvvpp_print_error(ctx, sts,
974  "Error creating a MFX session");
975  else if (sts > 0) {
977  "Warning in MFX session creation");
978  return AVERROR_UNKNOWN;
979  }
980 
981  *psession = session;
982 
983  return 0;
984 }
985 
986 #else
987 
989  void *loader,
990  mfxIMPL implementation,
991  mfxVersion *pver,
992  mfxSession *psession)
993 {
994  mfxSession session = NULL;
995  mfxStatus sts;
996 
998  "Use Intel(R) Media SDK to create MFX session, API version is "
999  "%d.%d, the required implementation version is %d.%d\n",
1000  MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1001 
1002  *psession = NULL;
1003  sts = MFXInit(implementation, pver, &session);
1004  if (sts < 0)
1005  return ff_qsvvpp_print_error(ctx, sts,
1006  "Error initializing an MFX session");
1007  else if (sts > 0) {
1008  ff_qsvvpp_print_warning(ctx, sts, "Warning in MFX session initialization");
1009  return AVERROR_UNKNOWN;
1010  }
1011 
1012  *psession = session;
1013 
1014  return 0;
1015 }
1016 
1017 #endif
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:87
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:512
frame_alloc
static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition: qsvvpp.c:175
QSVVPPParam::crop
QSVVPPCrop * crop
Definition: qsvvpp.h:104
QSVVPPParam::out_sw_format
enum AVPixelFormat out_sw_format
Definition: qsvvpp.h:100
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1009
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2858
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
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:116
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:325
pixdesc.h
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:432
AVFrame::width
int width
Definition: frame.h:397
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:248
AVFrame::top_field_first
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:482
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:471
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:346
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:501
clear_unused_frames
static void clear_unused_frames(QSVFrame *list)
Definition: qsvvpp.c:341
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:104
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:88
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
ff_qsvvpp_create
int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param)
Definition: qsvvpp.c:683
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:474
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
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:41
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
QSVVPPParam::async_depth
int async_depth
Definition: qsvvpp.h:106
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:286
QSVFrame
Definition: qsv_internal.h:80
QSVVPPContext
Definition: qsvvpp.h:55
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:603
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:103
QSVVPPParam
Definition: qsvvpp.h:91
QSVVPPCrop::x
int x
Definition: qsvvpp.h:88
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:423
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
ff_qsvvpp_free
int ff_qsvvpp_free(QSVVPPContext **vpp)
Definition: qsvvpp.c:810
AVFilterContext::nb_inputs
unsigned nb_inputs
number of input pads
Definition: avfilter.h:424
av_frame_copy
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:771
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:412
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:477
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:96
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:264
QSVVPPParam::filter_frame
int(* filter_frame)(AVFilterLink *outlink, AVFrame *frame)
Definition: qsvvpp.h:93
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
map_frame_to_surface
static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface)
Definition: qsvvpp.c:253
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:427
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:664
QSVVPPCrop::h
int h
Crop rectangle.
Definition: qsvvpp.h:88
QSVVPPCrop::y
int y
Definition: qsvvpp.h:88
AVFrame::height
int height
Definition: frame.h:397
ff_qsvvpp_filter_frame
int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref)
Definition: qsvvpp.c:837
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:333
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:354
AVFilterContext
An instance of a filter.
Definition: avfilter.h:415
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:370
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
IS_SYSTEM_MEMORY
#define IS_SYSTEM_MEMORY(mode)
Definition: qsvvpp.c:44
QSVVPPCrop
Definition: qsvvpp.h:86
get_free_frame
static QSVFrame * get_free_frame(QSVFrame **list)
Definition: qsvvpp.c:366
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:988
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:472
QSVVPPParam::ext_buf
mfxExtBuffer ** ext_buf
Definition: qsvvpp.h:97
submit_frame
static QSVFrame * submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref)
Definition: qsvvpp.c:392
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:427
query_frame
static QSVFrame * query_frame(QSVVPPContext *s, AVFilterLink *outlink)
Definition: qsvvpp.c:463