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 "internal.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 {
300  enum AVPixelFormat pix_fmt;
301  AVHWFramesContext *frames_ctx;
302  AVQSVFramesContext *frames_hwctx;
303  const AVPixFmtDescriptor *desc;
304 
305  if (link->format == AV_PIX_FMT_QSV) {
306  if (!link->hw_frames_ctx)
307  return AVERROR(EINVAL);
308 
309  frames_ctx = (AVHWFramesContext *)link->hw_frames_ctx->data;
310  frames_hwctx = frames_ctx->hwctx;
311  *frameinfo = frames_hwctx->surfaces[0].Info;
312  } else {
313  pix_fmt = link->format;
315  if (!desc)
316  return AVERROR_BUG;
317 
318  frameinfo->CropX = 0;
319  frameinfo->CropY = 0;
320  frameinfo->Width = FFALIGN(link->w, 32);
321  frameinfo->Height = FFALIGN(link->h, 32);
322  frameinfo->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
323  frameinfo->FourCC = pix_fmt_to_mfx_fourcc(pix_fmt);
324  frameinfo->BitDepthLuma = desc->comp[0].depth;
325  frameinfo->BitDepthChroma = desc->comp[0].depth;
326  frameinfo->Shift = desc->comp[0].depth > 8;
327  if (desc->log2_chroma_w && desc->log2_chroma_h)
328  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV420;
329  else if (desc->log2_chroma_w)
330  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV422;
331  else
332  frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV444;
333  }
334 
335  frameinfo->CropW = link->w;
336  frameinfo->CropH = link->h;
337  frameinfo->FrameRateExtN = link->frame_rate.num;
338  frameinfo->FrameRateExtD = link->frame_rate.den;
339 
340  /* Apparently VPP in the SDK requires the frame rate to be set to some value, otherwise
341  * init will fail */
342  if (frameinfo->FrameRateExtD == 0 || frameinfo->FrameRateExtN == 0) {
343  frameinfo->FrameRateExtN = 25;
344  frameinfo->FrameRateExtD = 1;
345  }
346 
347  frameinfo->AspectRatioW = link->sample_aspect_ratio.num ? link->sample_aspect_ratio.num : 1;
348  frameinfo->AspectRatioH = link->sample_aspect_ratio.den ? link->sample_aspect_ratio.den : 1;
349 
350  return 0;
351 }
352 
354 {
355  while (list) {
356  /* list->queued==1 means the frame is not cached in VPP
357  * process any more, it can be released to pool. */
358  if ((list->queued == 1) && !list->surface.Data.Locked) {
359  av_frame_free(&list->frame);
360  list->queued = 0;
361  }
362  list = list->next;
363  }
364 }
365 
367 {
368  while (*list) {
369  QSVFrame *frame;
370 
371  frame = *list;
372  *list = (*list)->next;
373  av_frame_free(&frame->frame);
374  av_freep(&frame);
375  }
376 }
377 
379 {
380  QSVFrame *out = *list;
381 
382  for (; out; out = out->next) {
383  if (!out->queued) {
384  out->queued = 1;
385  break;
386  }
387  }
388 
389  if (!out) {
390  out = av_mallocz(sizeof(*out));
391  if (!out) {
392  av_log(NULL, AV_LOG_ERROR, "Can't alloc new output frame.\n");
393  return NULL;
394  }
395  out->queued = 1;
396  out->next = *list;
397  *list = out;
398  }
399 
400  return out;
401 }
402 
403 /* get the input surface */
405 {
406  QSVFrame *qsv_frame;
407  AVFilterContext *ctx = inlink->dst;
408 
409  clear_unused_frames(s->in_frame_list);
410 
411  qsv_frame = get_free_frame(&s->in_frame_list);
412  if (!qsv_frame)
413  return NULL;
414 
415  /* Turn AVFrame into mfxFrameSurface1.
416  * For video/opaque memory mode, pix_fmt is AV_PIX_FMT_QSV, and
417  * mfxFrameSurface1 is stored in AVFrame->data[3];
418  * for system memory mode, raw video data is stored in
419  * AVFrame, we should map it into mfxFrameSurface1.
420  */
421  if (!IS_SYSTEM_MEMORY(s->in_mem_mode)) {
422  if (picref->format != AV_PIX_FMT_QSV) {
423  av_log(ctx, AV_LOG_ERROR, "QSVVPP gets a wrong frame.\n");
424  return NULL;
425  }
426  qsv_frame->frame = av_frame_clone(picref);
427  qsv_frame->surface = *(mfxFrameSurface1 *)qsv_frame->frame->data[3];
428  } else {
429  /* make a copy if the input is not padded as libmfx requires */
430  if (picref->height & 31 || picref->linesize[0] & 31) {
431  qsv_frame->frame = ff_get_video_buffer(inlink,
432  FFALIGN(inlink->w, 32),
433  FFALIGN(inlink->h, 32));
434  if (!qsv_frame->frame)
435  return NULL;
436 
437  qsv_frame->frame->width = picref->width;
438  qsv_frame->frame->height = picref->height;
439 
440  if (av_frame_copy(qsv_frame->frame, picref) < 0) {
441  av_frame_free(&qsv_frame->frame);
442  return NULL;
443  }
444 
445  if (av_frame_copy_props(qsv_frame->frame, picref) < 0) {
446  av_frame_free(&qsv_frame->frame);
447  return NULL;
448  }
449  } else
450  qsv_frame->frame = av_frame_clone(picref);
451 
452  if (map_frame_to_surface(qsv_frame->frame,
453  &qsv_frame->surface) < 0) {
454  av_log(ctx, AV_LOG_ERROR, "Unsupported frame.\n");
455  return NULL;
456  }
457  }
458 
459  qsv_frame->surface.Info = s->frame_infos[FF_INLINK_IDX(inlink)];
460  qsv_frame->surface.Data.TimeStamp = av_rescale_q(qsv_frame->frame->pts,
461  inlink->time_base, default_tb);
462 
463  qsv_frame->surface.Info.PicStruct =
464  !(qsv_frame->frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE :
465  ((qsv_frame->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF :
466  MFX_PICSTRUCT_FIELD_BFF);
467  if (qsv_frame->frame->repeat_pict == 1)
468  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
469  else if (qsv_frame->frame->repeat_pict == 2)
470  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
471  else if (qsv_frame->frame->repeat_pict == 4)
472  qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
473 
474  return qsv_frame;
475 }
476 
477 /* get the output surface */
478 static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFrame *in)
479 {
480  AVFilterContext *ctx = outlink->src;
481  QSVFrame *out_frame;
482  int ret;
483 
484  clear_unused_frames(s->out_frame_list);
485 
486  out_frame = get_free_frame(&s->out_frame_list);
487  if (!out_frame)
488  return NULL;
489 
490  /* For video memory, get a hw frame;
491  * For system memory, get a sw frame and map it into a mfx_surface. */
492  if (!IS_SYSTEM_MEMORY(s->out_mem_mode)) {
493  out_frame->frame = av_frame_alloc();
494  if (!out_frame->frame)
495  return NULL;
496 
497  ret = av_frame_copy_props(out_frame->frame, in);
498  if (ret < 0) {
499  av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n");
500  return NULL;
501  }
502 
503  ret = av_hwframe_get_buffer(outlink->hw_frames_ctx, out_frame->frame, 0);
504  if (ret < 0) {
505  av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n");
506  return NULL;
507  }
508 
509  out_frame->surface = *(mfxFrameSurface1 *)out_frame->frame->data[3];
510  } else {
511  /* Get a frame with aligned dimensions.
512  * Libmfx need system memory being 128x64 aligned */
513  out_frame->frame = ff_get_video_buffer(outlink,
514  FFALIGN(outlink->w, 128),
515  FFALIGN(outlink->h, 64));
516  if (!out_frame->frame)
517  return NULL;
518 
519  ret = av_frame_copy_props(out_frame->frame, in);
520  if (ret < 0) {
521  av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n");
522  return NULL;
523  }
524 
525  ret = map_frame_to_surface(out_frame->frame,
526  &out_frame->surface);
527  if (ret < 0)
528  return NULL;
529  }
530 
531  if (outlink->frame_rate.num && outlink->frame_rate.den)
532  out_frame->frame->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
533  else
534  out_frame->frame->duration = 0;
535 
536  out_frame->frame->width = outlink->w;
537  out_frame->frame->height = outlink->h;
538  out_frame->surface.Info = s->vpp_param.vpp.Out;
539 
540  for (int i = 0; i < s->vpp_param.NumExtParam; i++) {
541  mfxExtBuffer *extbuf = s->vpp_param.ExtParam[i];
542 
543  if (extbuf->BufferId == MFX_EXTBUFF_VPP_DEINTERLACING) {
544 #if FF_API_INTERLACED_FRAME
546  out_frame->frame->interlaced_frame = 0;
548 #endif
549  out_frame->frame->flags &= ~AV_FRAME_FLAG_INTERLACED;
550  break;
551  }
552  }
553 
554  out_frame->surface.Info.PicStruct =
555  !(out_frame->frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE :
556  ((out_frame->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF :
557  MFX_PICSTRUCT_FIELD_BFF);
558 
559  return out_frame;
560 }
561 
562 /* create the QSV session */
564 {
565  AVFilterLink *inlink = avctx->inputs[0];
566  AVFilterLink *outlink = avctx->outputs[0];
567  AVQSVFramesContext *in_frames_hwctx = NULL;
568  AVQSVFramesContext *out_frames_hwctx = NULL;
569 
570  AVBufferRef *device_ref;
571  AVHWDeviceContext *device_ctx;
572  AVQSVDeviceContext *device_hwctx;
573  mfxHDL handle;
574  mfxHandleType handle_type;
575  mfxVersion ver;
576  mfxIMPL impl;
577  int ret, i;
578 
579  if (inlink->hw_frames_ctx) {
580  AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
581 
582  device_ref = frames_ctx->device_ref;
583  in_frames_hwctx = frames_ctx->hwctx;
584 
585  s->in_mem_mode = in_frames_hwctx->frame_type;
586 
587  s->surface_ptrs_in = av_calloc(in_frames_hwctx->nb_surfaces,
588  sizeof(*s->surface_ptrs_in));
589  if (!s->surface_ptrs_in)
590  return AVERROR(ENOMEM);
591 
592  for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
593  s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i;
594 
595  s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces;
596  } else if (avctx->hw_device_ctx) {
597  device_ref = avctx->hw_device_ctx;
598  s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
599  } else {
600  av_log(avctx, AV_LOG_ERROR, "No hw context provided.\n");
601  return AVERROR(EINVAL);
602  }
603 
604  device_ctx = (AVHWDeviceContext *)device_ref->data;
605  device_hwctx = device_ctx->hwctx;
606 
607  if (outlink->format == AV_PIX_FMT_QSV) {
608  AVHWFramesContext *out_frames_ctx;
609  AVBufferRef *out_frames_ref = av_hwframe_ctx_alloc(device_ref);
610  if (!out_frames_ref)
611  return AVERROR(ENOMEM);
612 
613 #if QSV_HAVE_OPAQUE
614  s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ?
615  MFX_MEMTYPE_OPAQUE_FRAME :
616  MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
617 #else
618  s->out_mem_mode = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
619 #endif
620 
621  out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data;
622  out_frames_hwctx = out_frames_ctx->hwctx;
623 
624  out_frames_ctx->format = AV_PIX_FMT_QSV;
625  out_frames_ctx->width = FFALIGN(outlink->w, 32);
626  out_frames_ctx->height = FFALIGN(outlink->h, 32);
627  out_frames_ctx->sw_format = s->out_sw_format;
628  out_frames_ctx->initial_pool_size = 64;
629  if (avctx->extra_hw_frames > 0)
630  out_frames_ctx->initial_pool_size += avctx->extra_hw_frames;
631  out_frames_hwctx->frame_type = s->out_mem_mode;
632 
633  ret = av_hwframe_ctx_init(out_frames_ref);
634  if (ret < 0) {
635  av_buffer_unref(&out_frames_ref);
636  av_log(avctx, AV_LOG_ERROR, "Error creating frames_ctx for output pad.\n");
637  return ret;
638  }
639 
640  s->surface_ptrs_out = av_calloc(out_frames_hwctx->nb_surfaces,
641  sizeof(*s->surface_ptrs_out));
642  if (!s->surface_ptrs_out) {
643  av_buffer_unref(&out_frames_ref);
644  return AVERROR(ENOMEM);
645  }
646 
647  for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
648  s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
649  s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
650 
651  av_buffer_unref(&outlink->hw_frames_ctx);
652  outlink->hw_frames_ctx = out_frames_ref;
653  } else
654  s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
655 
656  /* extract the properties of the "master" session given to us */
657  ret = MFXQueryIMPL(device_hwctx->session, &impl);
658  if (ret == MFX_ERR_NONE)
659  ret = MFXQueryVersion(device_hwctx->session, &ver);
660  if (ret != MFX_ERR_NONE) {
661  av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n");
662  return AVERROR_UNKNOWN;
663  }
664 
665  if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
666  handle_type = MFX_HANDLE_VA_DISPLAY;
667  } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
668  handle_type = MFX_HANDLE_D3D11_DEVICE;
669  } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
670  handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
671  } else {
672  av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n");
673  return AVERROR_UNKNOWN;
674  }
675 
676  ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
677  if (ret < 0)
678  return ff_qsvvpp_print_error(avctx, ret, "Error getting the session handle");
679  else if (ret > 0) {
680  ff_qsvvpp_print_warning(avctx, ret, "Warning in getting the session handle");
681  return AVERROR_UNKNOWN;
682  }
683 
684  /* create a "slave" session with those same properties, to be used for vpp */
685  ret = ff_qsvvpp_create_mfx_session(avctx, device_hwctx->loader, impl, &ver,
686  &s->session);
687  if (ret)
688  return ret;
689 
690  ret = MFXQueryVersion(s->session, &s->ver);
691  if (ret != MFX_ERR_NONE) {
692  av_log(avctx, AV_LOG_ERROR, "Error querying the runtime version\n");
693  return AVERROR_UNKNOWN;
694  }
695 
696  if (handle) {
697  ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
698  if (ret != MFX_ERR_NONE)
699  return AVERROR_UNKNOWN;
700  }
701 
702  if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
703  ret = MFXJoinSession(device_hwctx->session, s->session);
704  if (ret != MFX_ERR_NONE)
705  return AVERROR_UNKNOWN;
706  }
707 
708 #if QSV_HAVE_OPAQUE
709  if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
710  s->opaque_alloc.In.Surfaces = s->surface_ptrs_in;
711  s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
712  s->opaque_alloc.In.Type = s->in_mem_mode;
713 
714  s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out;
715  s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out;
716  s->opaque_alloc.Out.Type = s->out_mem_mode;
717 
718  s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
719  s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
720  } else
721 #endif
722  if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) {
723  mfxFrameAllocator frame_allocator = {
724  .pthis = s,
725  .Alloc = frame_alloc,
726  .Lock = frame_lock,
727  .Unlock = frame_unlock,
728  .GetHDL = frame_get_hdl,
729  .Free = frame_free,
730  };
731 
732  ret = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator);
733  if (ret != MFX_ERR_NONE)
734  return AVERROR_UNKNOWN;
735  }
736 
737  return 0;
738 }
739 
741 {
742  return 0;
743 }
744 
746 {
747  int i;
748  int ret;
749  QSVVPPContext *s = avctx->priv;
750 
751  s->filter_frame = param->filter_frame;
752  if (!s->filter_frame)
753  s->filter_frame = ff_filter_frame;
754  s->out_sw_format = param->out_sw_format;
755 
756  s->set_frame_ext_params = param->set_frame_ext_params;
757  if (!s->set_frame_ext_params)
758  s->set_frame_ext_params = set_frame_ext_params_null;
759 
760  /* create the vpp session */
761  ret = init_vpp_session(avctx, s);
762  if (ret < 0)
763  goto failed;
764 
765  s->frame_infos = av_calloc(avctx->nb_inputs, sizeof(*s->frame_infos));
766  if (!s->frame_infos) {
767  ret = AVERROR(ENOMEM);
768  goto failed;
769  }
770 
771  /* Init each input's information */
772  for (i = 0; i < avctx->nb_inputs; i++) {
773  ret = fill_frameinfo_by_link(&s->frame_infos[i], avctx->inputs[i]);
774  if (ret < 0)
775  goto failed;
776  }
777 
778  /* Update input's frame info according to crop */
779  for (i = 0; i < param->num_crop; i++) {
780  QSVVPPCrop *crop = param->crop + i;
781  if (crop->in_idx > avctx->nb_inputs) {
782  ret = AVERROR(EINVAL);
783  goto failed;
784  }
785  s->frame_infos[crop->in_idx].CropX = crop->x;
786  s->frame_infos[crop->in_idx].CropY = crop->y;
787  s->frame_infos[crop->in_idx].CropW = crop->w;
788  s->frame_infos[crop->in_idx].CropH = crop->h;
789  }
790 
791  s->vpp_param.vpp.In = s->frame_infos[0];
792 
793  ret = fill_frameinfo_by_link(&s->vpp_param.vpp.Out, avctx->outputs[0]);
794  if (ret < 0) {
795  av_log(avctx, AV_LOG_ERROR, "Fail to get frame info from link.\n");
796  goto failed;
797  }
798 
799  s->nb_seq_buffers = param->num_ext_buf;
800 #if QSV_HAVE_OPAQUE
801  if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode))
802  s->nb_seq_buffers++;
803 #endif
804 
805  if (s->nb_seq_buffers) {
806  s->seq_buffers = av_calloc(s->nb_seq_buffers, sizeof(*s->seq_buffers));
807  if (!s->seq_buffers) {
808  ret = AVERROR(ENOMEM);
809  goto failed;
810  }
811 
812  for (i = 0; i < param->num_ext_buf; i++)
813  s->seq_buffers[i] = param->ext_buf[i];
814 
815 #if QSV_HAVE_OPAQUE
816  if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode))
817  s->seq_buffers[i] = (mfxExtBuffer *)&s->opaque_alloc;
818 #endif
819 
820  s->nb_ext_buffers = s->nb_seq_buffers;
821  s->ext_buffers = av_calloc(s->nb_ext_buffers, sizeof(*s->ext_buffers));
822  if (!s->ext_buffers) {
823  ret = AVERROR(ENOMEM);
824  goto failed;
825  }
826 
827  memcpy(s->ext_buffers, s->seq_buffers, s->nb_seq_buffers * sizeof(*s->seq_buffers));
828  }
829 
830  s->vpp_param.ExtParam = s->ext_buffers;
831  s->vpp_param.NumExtParam = s->nb_ext_buffers;
832 
833  s->got_frame = 0;
834 
835  /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */
836  s->async_fifo = av_fifo_alloc2(s->async_depth + 1, sizeof(QSVAsyncFrame), 0);
837  if (!s->async_fifo) {
838  ret = AVERROR(ENOMEM);
839  goto failed;
840  }
841 
842  s->vpp_param.AsyncDepth = s->async_depth;
843 
844  if (IS_SYSTEM_MEMORY(s->in_mem_mode))
845  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
846  else if (IS_VIDEO_MEMORY(s->in_mem_mode))
847  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY;
848 #if QSV_HAVE_OPAQUE
849  else if (IS_OPAQUE_MEMORY(s->in_mem_mode))
850  s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY;
851 #endif
852 
853  if (IS_SYSTEM_MEMORY(s->out_mem_mode))
854  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
855  else if (IS_VIDEO_MEMORY(s->out_mem_mode))
856  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY;
857 #if QSV_HAVE_OPAQUE
858  else if (IS_OPAQUE_MEMORY(s->out_mem_mode))
859  s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
860 #endif
861 
862  /* Print input memory mode */
863  ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0x0F, "VPP");
864  /* Print output memory mode */
865  ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0xF0, "VPP");
866 
867  /* Validate VPP params, but don't initial VPP session here */
868  ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param);
869  if (ret < 0) {
870  ret = ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params");
871  goto failed;
872  } else if (ret > 0)
873  ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params");
874 
875  return 0;
876 
877 failed:
878  ff_qsvvpp_close(avctx);
879 
880  return ret;
881 }
882 
884 {
885  int ret;
886  mfxExtBuffer *ext_param[QSVVPP_MAX_FRAME_EXTBUFS];
887  QSVVPPFrameParam fp = { 0, ext_param };
888 
889  ret = s->set_frame_ext_params(avctx, in->frame, out->frame, &fp);
890  if (ret)
891  return ret;
892 
893  if (fp.num_ext_buf) {
894  av_freep(&s->ext_buffers);
895  s->nb_ext_buffers = s->nb_seq_buffers + fp.num_ext_buf;
896 
897  s->ext_buffers = av_calloc(s->nb_ext_buffers, sizeof(*s->ext_buffers));
898  if (!s->ext_buffers)
899  return AVERROR(ENOMEM);
900 
901  memcpy(&s->ext_buffers[0], s->seq_buffers, s->nb_seq_buffers * sizeof(*s->seq_buffers));
902  memcpy(&s->ext_buffers[s->nb_seq_buffers], fp.ext_buf, fp.num_ext_buf * sizeof(*fp.ext_buf));
903  s->vpp_param.ExtParam = s->ext_buffers;
904  s->vpp_param.NumExtParam = s->nb_ext_buffers;
905  }
906 
907  if (!s->vpp_initted) {
908  s->vpp_param.vpp.In.PicStruct = in->surface.Info.PicStruct;
909  s->vpp_param.vpp.Out.PicStruct = out->surface.Info.PicStruct;
910 
911  /* Query VPP params again, including params for frame */
912  ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param);
913  if (ret < 0)
914  return ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params");
915  else if (ret > 0)
916  ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params");
917 
918  ret = MFXVideoVPP_Init(s->session, &s->vpp_param);
919  if (ret < 0)
920  return ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp");
921  else if (ret > 0)
922  ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp");
923 
924  s->vpp_initted = 1;
925  } else if (fp.num_ext_buf) {
926  ret = MFXVideoVPP_Reset(s->session, &s->vpp_param);
927  if (ret < 0) {
928  ret = ff_qsvvpp_print_error(avctx, ret, "Failed to reset session for qsvvpp");
929  return ret;
930  } else if (ret > 0)
931  ff_qsvvpp_print_warning(avctx, ret, "Warning When resetting session for qsvvpp");
932  }
933 
934  return 0;
935 }
936 
938 {
939  QSVVPPContext *s = avctx->priv;
940 
941  if (s->session) {
942  MFXVideoVPP_Close(s->session);
943  MFXClose(s->session);
944  s->session = NULL;
945  s->vpp_initted = 0;
946  }
947 
948  /* release all the resources */
949  clear_frame_list(&s->in_frame_list);
950  clear_frame_list(&s->out_frame_list);
951  av_freep(&s->surface_ptrs_in);
952  av_freep(&s->surface_ptrs_out);
953  av_freep(&s->seq_buffers);
954  av_freep(&s->ext_buffers);
955  av_freep(&s->frame_infos);
956  av_fifo_freep2(&s->async_fifo);
957 
958  return 0;
959 }
960 
962 {
963  AVFilterContext *ctx = inlink->dst;
964  AVFilterLink *outlink = ctx->outputs[0];
965  QSVAsyncFrame aframe;
966  mfxSyncPoint sync;
967  QSVFrame *in_frame, *out_frame;
968  int ret, ret1, filter_ret;
969 
970  while (s->eof && av_fifo_read(s->async_fifo, &aframe, 1) >= 0) {
971  if (MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000) < 0)
972  av_log(ctx, AV_LOG_WARNING, "Sync failed.\n");
973 
974  filter_ret = s->filter_frame(outlink, aframe.frame->frame);
975  if (filter_ret < 0) {
976  av_frame_free(&aframe.frame->frame);
977  return filter_ret;
978  }
979  aframe.frame->queued--;
980  s->got_frame = 1;
981  aframe.frame->frame = NULL;
982  };
983 
984  if (!picref)
985  return 0;
986 
987  in_frame = submit_frame(s, inlink, picref);
988  if (!in_frame) {
989  av_log(ctx, AV_LOG_ERROR, "Failed to submit frame on input[%d]\n",
991  return AVERROR(ENOMEM);
992  }
993 
994  do {
995  out_frame = query_frame(s, outlink, in_frame->frame);
996  if (!out_frame) {
997  av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n");
998  return AVERROR(ENOMEM);
999  }
1000 
1001  ret = qsvvpp_init_vpp_session(ctx, s, in_frame, out_frame);
1002  if (ret)
1003  return ret;
1004 
1005  do {
1006  ret = MFXVideoVPP_RunFrameVPPAsync(s->session, &in_frame->surface,
1007  &out_frame->surface, NULL, &sync);
1008  if (ret == MFX_WRN_DEVICE_BUSY)
1009  av_usleep(500);
1010  } while (ret == MFX_WRN_DEVICE_BUSY);
1011 
1012  if (ret < 0 && ret != MFX_ERR_MORE_SURFACE) {
1013  /* Ignore more_data error */
1014  if (ret == MFX_ERR_MORE_DATA)
1015  return AVERROR(EAGAIN);
1016  break;
1017  }
1018  out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp,
1019  default_tb, outlink->time_base);
1020 
1021  out_frame->queued++;
1022  aframe = (QSVAsyncFrame){ sync, out_frame };
1023  av_fifo_write(s->async_fifo, &aframe, 1);
1024 
1025  if (av_fifo_can_read(s->async_fifo) > s->async_depth) {
1026  av_fifo_read(s->async_fifo, &aframe, 1);
1027 
1028  do {
1029  ret1 = MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000);
1030  } while (ret1 == MFX_WRN_IN_EXECUTION);
1031 
1032  if (ret1 < 0) {
1033  ret = ret1;
1034  break;
1035  }
1036 
1037  filter_ret = s->filter_frame(outlink, aframe.frame->frame);
1038  if (filter_ret < 0) {
1039  av_frame_free(&aframe.frame->frame);
1040  return filter_ret;
1041  }
1042 
1043  aframe.frame->queued--;
1044  s->got_frame = 1;
1045  aframe.frame->frame = NULL;
1046  }
1047  } while(ret == MFX_ERR_MORE_SURFACE);
1048 
1049  if (ret < 0)
1050  return ff_qsvvpp_print_error(ctx, ret, "Error running VPP");
1051  else if (ret > 0)
1052  ff_qsvvpp_print_warning(ctx, ret, "Warning in running VPP");
1053 
1054  return 0;
1055 }
1056 
1057 #if QSV_ONEVPL
1058 
1060  void *loader,
1061  mfxIMPL implementation,
1062  mfxVersion *pver,
1063  mfxSession *psession)
1064 {
1065  mfxStatus sts;
1066  mfxSession session = NULL;
1067  uint32_t impl_idx = 0;
1068 
1070  "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
1071 
1072  if (!loader) {
1073  av_log(ctx, AV_LOG_ERROR, "Invalid MFX Loader handle\n");
1074  return AVERROR(EINVAL);
1075  }
1076 
1077  while (1) {
1078  /* Enumerate all implementations */
1079  mfxImplDescription *impl_desc;
1080 
1081  sts = MFXEnumImplementations(loader, impl_idx,
1082  MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
1083  (mfxHDL *)&impl_desc);
1084  /* Failed to find an available implementation */
1085  if (sts == MFX_ERR_NOT_FOUND)
1086  break;
1087  else if (sts != MFX_ERR_NONE) {
1088  impl_idx++;
1089  continue;
1090  }
1091 
1092  sts = MFXCreateSession(loader, impl_idx, &session);
1093  MFXDispReleaseImplDescription(loader, impl_desc);
1094  if (sts == MFX_ERR_NONE)
1095  break;
1096 
1097  impl_idx++;
1098  }
1099 
1100  if (sts < 0)
1101  return ff_qsvvpp_print_error(ctx, sts,
1102  "Error creating a MFX session");
1103  else if (sts > 0) {
1105  "Warning in MFX session creation");
1106  return AVERROR_UNKNOWN;
1107  }
1108 
1109  *psession = session;
1110 
1111  return 0;
1112 }
1113 
1114 #else
1115 
1117  void *loader,
1118  mfxIMPL implementation,
1119  mfxVersion *pver,
1120  mfxSession *psession)
1121 {
1122  mfxSession session = NULL;
1123  mfxStatus sts;
1124 
1126  "Use Intel(R) Media SDK to create MFX session, API version is "
1127  "%d.%d, the required implementation version is %d.%d\n",
1128  MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1129 
1130  *psession = NULL;
1131  sts = MFXInit(implementation, pver, &session);
1132  if (sts < 0)
1133  return ff_qsvvpp_print_error(ctx, sts,
1134  "Error initializing an MFX session");
1135  else if (sts > 0) {
1136  ff_qsvvpp_print_warning(ctx, sts, "Warning in MFX session initialization");
1137  return AVERROR_UNKNOWN;
1138  }
1139 
1140  *psession = session;
1141 
1142  return 0;
1143 }
1144 
1145 #endif
1146 
1148 {
1149  /* When process YUV420 frames, FFmpeg uses same alignment on Y/U/V
1150  * planes. VPL and MSDK use Y plane's pitch / 2 as U/V planes's
1151  * pitch, which makes U/V planes 16-bytes aligned. We need to set a
1152  * separate alignment to meet runtime's behaviour.
1153  */
1155  FFALIGN(inlink->w, 32),
1156  FFALIGN(inlink->h, 32),
1157  16);
1158 }
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:112
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:60
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:186
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:563
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:1015
AVFrame::duration
int64_t duration
Duration of the frame, in the same units as pts.
Definition: frame.h:781
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2965
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:1147
query_frame
static QSVFrame * query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFrame *in)
Definition: qsvvpp.c:478
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:160
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:375
pixdesc.h
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:487
AVFrame::width
int width
Definition: frame.h:447
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: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:469
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:647
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:396
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:639
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:422
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:492
clear_unused_frames
static void clear_unused_frames(QSVFrame *list)
Definition: qsvvpp.c:353
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:148
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:552
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: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
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:593
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:937
AVQSVFramesContext::surfaces
mfxFrameSurface1 * surfaces
Definition: hwcontext_qsv.h:54
NULL
#define NULL
Definition: coverity.c:32
qsv_errors
static const struct @266 qsv_errors[]
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:210
qsv_iopatterns
static const struct @265 qsv_iopatterns[]
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:709
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
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:415
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
fp
#define fp
Definition: regdef.h:44
AVFilterContext::nb_inputs
unsigned nb_inputs
number of input pads
Definition: avfilter.h:416
av_frame_copy
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:999
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:462
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:740
AV_PIX_FMT_RGB32
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:451
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
QSVAsyncFrame::sync
mfxSyncPoint sync
Definition: qsvvpp.c:53
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
common.h
desc
const char * desc
Definition: qsvvpp.c:59
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:745
AV_FRAME_FLAG_INTERLACED
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition: frame.h:634
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:482
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:88
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:726
QSVVPPCrop::h
int h
Crop rectangle.
Definition: qsvvpp.h:107
QSVVPPCrop::y
int y
Definition: qsvvpp.h:107
AVFrame::height
int height
Definition: frame.h:447
ff_qsvvpp_filter_frame
int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref)
Definition: qsvvpp.c:961
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
FF_INLINK_IDX
#define FF_INLINK_IDX(link)
Find the index of a link.
Definition: internal.h:331
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:366
AVFilterContext
An instance of a filter.
Definition: avfilter.h:407
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:528
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
qsvvpp_init_vpp_session
static int qsvvpp_init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s, const QSVFrame *in, QSVFrame *out)
Definition: qsvvpp.c:883
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: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:420
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_fifo_freep2
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition: fifo.c:286
h
h
Definition: vp9dsp_template.c:2038
IS_SYSTEM_MEMORY
#define IS_SYSTEM_MEMORY(mode)
Definition: qsvvpp.c:45
QSVVPPCrop
Definition: qsvvpp.h:105
get_free_frame
static QSVFrame * get_free_frame(QSVFrame **list)
Definition: qsvvpp.c:378
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:1116
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:543
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:404
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:419