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