FFmpeg
vf_scale_qsv.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  * scale video filter - QSV
22  */
23 
24 #include <mfx/mfxvideo.h>
25 
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "libavutil/avstring.h"
30 #include "libavutil/common.h"
31 #include "libavutil/eval.h"
32 #include "libavutil/hwcontext.h"
34 #include "libavutil/internal.h"
35 #include "libavutil/mathematics.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/pixdesc.h"
38 #include "libavutil/time.h"
39 #include "libavfilter/qsvvpp.h"
40 
41 #include "avfilter.h"
42 #include "formats.h"
43 #include "internal.h"
44 #include "video.h"
45 
46 static const char *const var_names[] = {
47  "PI",
48  "PHI",
49  "E",
50  "in_w", "iw",
51  "in_h", "ih",
52  "out_w", "ow",
53  "out_h", "oh",
54  "a", "dar",
55  "sar",
56  NULL
57 };
58 
59 enum var_name {
70 };
71 
72 #define QSV_HAVE_SCALING_CONFIG QSV_VERSION_ATLEAST(1, 19)
73 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
74 
75 typedef struct QSVScaleContext {
76  const AVClass *class;
77 
78  /* a clone of the main session, used internally for scaling */
79  mfxSession session;
80 
81  mfxMemId *mem_ids_in;
83 
84  mfxMemId *mem_ids_out;
86 
87  mfxFrameSurface1 **surface_ptrs_in;
89 
90  mfxFrameSurface1 **surface_ptrs_out;
92 
93  mfxExtOpaqueSurfaceAlloc opaque_alloc;
94 
95 #if QSV_HAVE_SCALING_CONFIG
96  mfxExtVPPScaling scale_conf;
97 #endif
98  int mode;
99 
102 
104 
105  /**
106  * New dimensions. Special values are:
107  * 0 = original width/height
108  * -1 = keep original aspect
109  */
110  int w, h;
111 
112  /**
113  * Output sw format. AV_PIX_FMT_NONE for no conversion.
114  */
116 
117  char *w_expr; ///< width expression string
118  char *h_expr; ///< height expression string
119  char *format_str;
121 
123 {
124  QSVScaleContext *s = ctx->priv;
125 
126  if (!strcmp(s->format_str, "same")) {
127  s->format = AV_PIX_FMT_NONE;
128  } else {
129  s->format = av_get_pix_fmt(s->format_str);
130  if (s->format == AV_PIX_FMT_NONE) {
131  av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str);
132  return AVERROR(EINVAL);
133  }
134  }
135 
136  return 0;
137 }
138 
140 {
141  QSVScaleContext *s = ctx->priv;
142 
143  if (s->session) {
144  MFXClose(s->session);
145  s->session = NULL;
146  }
147 
148  av_freep(&s->mem_ids_in);
149  av_freep(&s->mem_ids_out);
150  s->nb_mem_ids_in = 0;
151  s->nb_mem_ids_out = 0;
152 
153  av_freep(&s->surface_ptrs_in);
154  av_freep(&s->surface_ptrs_out);
155  s->nb_surface_ptrs_in = 0;
156  s->nb_surface_ptrs_out = 0;
157 }
158 
160  int out_width, int out_height)
161 {
162  QSVScaleContext *s = ctx->priv;
163  AVFilterLink *outlink = ctx->outputs[0];
164 
165  AVHWFramesContext *in_frames_ctx;
166  AVHWFramesContext *out_frames_ctx;
167  AVQSVFramesContext *in_frames_hwctx;
168  AVQSVFramesContext *out_frames_hwctx;
169  enum AVPixelFormat in_format;
170  enum AVPixelFormat out_format;
171  int i, ret;
172 
173  /* check that we have a hw context */
174  if (!ctx->inputs[0]->hw_frames_ctx) {
175  av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
176  return AVERROR(EINVAL);
177  }
178  in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
179  in_frames_hwctx = in_frames_ctx->hwctx;
180 
181  in_format = in_frames_ctx->sw_format;
182  out_format = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
183 
184  outlink->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref);
185  if (!outlink->hw_frames_ctx)
186  return AVERROR(ENOMEM);
187  out_frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
188  out_frames_hwctx = out_frames_ctx->hwctx;
189 
190  out_frames_ctx->format = AV_PIX_FMT_QSV;
191  out_frames_ctx->width = FFALIGN(out_width, 16);
192  out_frames_ctx->height = FFALIGN(out_height, 16);
193  out_frames_ctx->sw_format = out_format;
194  out_frames_ctx->initial_pool_size = 4;
195 
196  out_frames_hwctx->frame_type = in_frames_hwctx->frame_type | MFX_MEMTYPE_FROM_VPPOUT;
197 
198  ret = ff_filter_init_hw_frames(ctx, outlink, 32);
199  if (ret < 0)
200  return ret;
201 
203  if (ret < 0)
204  return ret;
205 
206  for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) {
207  mfxFrameInfo *info = &out_frames_hwctx->surfaces[i].Info;
208  info->CropW = out_width;
209  info->CropH = out_height;
210  }
211 
212  return 0;
213 }
214 
215 static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
216  mfxFrameAllocResponse *resp)
217 {
218  AVFilterContext *ctx = pthis;
219  QSVScaleContext *s = ctx->priv;
220 
221  if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
222  !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
223  !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
224  return MFX_ERR_UNSUPPORTED;
225 
226  if (req->Type & MFX_MEMTYPE_FROM_VPPIN) {
227  resp->mids = s->mem_ids_in;
228  resp->NumFrameActual = s->nb_mem_ids_in;
229  } else {
230  resp->mids = s->mem_ids_out;
231  resp->NumFrameActual = s->nb_mem_ids_out;
232  }
233 
234  return MFX_ERR_NONE;
235 }
236 
237 static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
238 {
239  return MFX_ERR_NONE;
240 }
241 
242 static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
243 {
244  return MFX_ERR_UNSUPPORTED;
245 }
246 
247 static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
248 {
249  return MFX_ERR_UNSUPPORTED;
250 }
251 
252 static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
253 {
254  mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
255  mfxHDLPair *pair_src = (mfxHDLPair*)mid;
256 
257  pair_dst->first = pair_src->first;
258 
259  if (pair_src->second != (mfxMemId)MFX_INFINITE)
260  pair_dst->second = pair_src->second;
261  return MFX_ERR_NONE;
262 }
263 
265 {
266 
267  QSVScaleContext *s = ctx->priv;
268  AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
269  AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)ctx->outputs[0]->hw_frames_ctx->data;
270  AVQSVFramesContext *in_frames_hwctx = in_frames_ctx->hwctx;
271  AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx;
272  AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx;
273 
274  int opaque = !!(in_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
275 
276  mfxHDL handle = NULL;
277  mfxHandleType handle_type;
278  mfxVersion ver;
279  mfxIMPL impl;
280  mfxVideoParam par;
281  mfxStatus err;
282  int i;
283 
284  s->num_ext_buf = 0;
285 
286  /* extract the properties of the "master" session given to us */
287  err = MFXQueryIMPL(device_hwctx->session, &impl);
288  if (err == MFX_ERR_NONE)
289  err = MFXQueryVersion(device_hwctx->session, &ver);
290  if (err != MFX_ERR_NONE) {
291  av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n");
292  return AVERROR_UNKNOWN;
293  }
294 
295  if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
296  handle_type = MFX_HANDLE_VA_DISPLAY;
297  } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
298  handle_type = MFX_HANDLE_D3D11_DEVICE;
299  } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
300  handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
301  } else {
302  av_log(ctx, AV_LOG_ERROR, "Error unsupported handle type\n");
303  return AVERROR_UNKNOWN;
304  }
305 
306  err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
307  if (err < 0)
308  return ff_qsvvpp_print_error(ctx, err, "Error getting the session handle");
309  else if (err > 0) {
310  ff_qsvvpp_print_warning(ctx, err, "Warning in getting the session handle");
311  return AVERROR_UNKNOWN;
312  }
313 
314  /* create a "slave" session with those same properties, to be used for
315  * actual scaling */
316  err = MFXInit(impl, &ver, &s->session);
317  if (err != MFX_ERR_NONE) {
318  av_log(ctx, AV_LOG_ERROR, "Error initializing a session for scaling\n");
319  return AVERROR_UNKNOWN;
320  }
321 
322  if (handle) {
323  err = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
324  if (err != MFX_ERR_NONE)
325  return AVERROR_UNKNOWN;
326  }
327 
328  if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
329  err = MFXJoinSession(device_hwctx->session, s->session);
330  if (err != MFX_ERR_NONE)
331  return AVERROR_UNKNOWN;
332  }
333 
334  memset(&par, 0, sizeof(par));
335 
336  if (opaque) {
337  s->surface_ptrs_in = av_calloc(in_frames_hwctx->nb_surfaces,
338  sizeof(*s->surface_ptrs_in));
339  if (!s->surface_ptrs_in)
340  return AVERROR(ENOMEM);
341  for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
342  s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i;
343  s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces;
344 
345  s->surface_ptrs_out = av_calloc(out_frames_hwctx->nb_surfaces,
346  sizeof(*s->surface_ptrs_out));
347  if (!s->surface_ptrs_out)
348  return AVERROR(ENOMEM);
349  for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
350  s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
351  s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
352 
353  s->opaque_alloc.In.Surfaces = s->surface_ptrs_in;
354  s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in;
355  s->opaque_alloc.In.Type = in_frames_hwctx->frame_type;
356 
357  s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out;
358  s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out;
359  s->opaque_alloc.Out.Type = out_frames_hwctx->frame_type;
360 
361  s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
362  s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
363 
364  s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->opaque_alloc;
365 
366  par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
367  } else {
368  mfxFrameAllocator frame_allocator = {
369  .pthis = ctx,
370  .Alloc = frame_alloc,
371  .Lock = frame_lock,
372  .Unlock = frame_unlock,
373  .GetHDL = frame_get_hdl,
374  .Free = frame_free,
375  };
376 
377  s->mem_ids_in = av_calloc(in_frames_hwctx->nb_surfaces,
378  sizeof(*s->mem_ids_in));
379  if (!s->mem_ids_in)
380  return AVERROR(ENOMEM);
381  for (i = 0; i < in_frames_hwctx->nb_surfaces; i++)
382  s->mem_ids_in[i] = in_frames_hwctx->surfaces[i].Data.MemId;
383  s->nb_mem_ids_in = in_frames_hwctx->nb_surfaces;
384 
385  s->mem_ids_out = av_calloc(out_frames_hwctx->nb_surfaces,
386  sizeof(*s->mem_ids_out));
387  if (!s->mem_ids_out)
388  return AVERROR(ENOMEM);
389  for (i = 0; i < out_frames_hwctx->nb_surfaces; i++)
390  s->mem_ids_out[i] = out_frames_hwctx->surfaces[i].Data.MemId;
391  s->nb_mem_ids_out = out_frames_hwctx->nb_surfaces;
392 
393  err = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator);
394  if (err != MFX_ERR_NONE)
395  return AVERROR_UNKNOWN;
396 
397  par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
398  }
399 
400 #if QSV_HAVE_SCALING_CONFIG
401  memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling));
402  s->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING;
403  s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling);
404  s->scale_conf.ScalingMode = s->mode;
405  s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf;
406  av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %d\n", s->mode);
407 #endif
408 
409  par.ExtParam = s->ext_buffers;
410  par.NumExtParam = s->num_ext_buf;
411 
412  par.AsyncDepth = 1; // TODO async
413 
414  par.vpp.In = in_frames_hwctx->surfaces[0].Info;
415  par.vpp.Out = out_frames_hwctx->surfaces[0].Info;
416 
417  /* Apparently VPP requires the frame rate to be set to some value, otherwise
418  * init will fail (probably for the framerate conversion filter). Since we
419  * are only doing scaling here, we just invent an arbitrary
420  * value */
421  par.vpp.In.FrameRateExtN = 25;
422  par.vpp.In.FrameRateExtD = 1;
423  par.vpp.Out.FrameRateExtN = 25;
424  par.vpp.Out.FrameRateExtD = 1;
425 
426  /* Print input memory mode */
427  ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0x0F, "VPP");
428  /* Print output memory mode */
429  ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0xF0, "VPP");
430  err = MFXVideoVPP_Init(s->session, &par);
431  if (err < 0)
432  return ff_qsvvpp_print_error(ctx, err,
433  "Error opening the VPP for scaling");
434  else if (err > 0) {
436  "Warning in VPP initialization");
437  return AVERROR_UNKNOWN;
438  }
439 
440  return 0;
441 }
442 
443 static int init_scale_session(AVFilterContext *ctx, int in_width, int in_height,
444  int out_width, int out_height)
445 {
446  int ret;
447 
449 
450  ret = init_out_pool(ctx, out_width, out_height);
451  if (ret < 0)
452  return ret;
453 
455  if (ret < 0)
456  return ret;
457 
458  return 0;
459 }
460 
462 {
463  AVFilterContext *ctx = outlink->src;
464  AVFilterLink *inlink = outlink->src->inputs[0];
465  QSVScaleContext *s = ctx->priv;
466  int64_t w, h;
467  double var_values[VARS_NB], res;
468  char *expr;
469  int ret;
470 
471  var_values[VAR_PI] = M_PI;
472  var_values[VAR_PHI] = M_PHI;
473  var_values[VAR_E] = M_E;
474  var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w;
475  var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h;
476  var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
477  var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
478  var_values[VAR_A] = (double) inlink->w / inlink->h;
479  var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ?
480  (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
481  var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR];
482 
483  /* evaluate width and height */
484  av_expr_parse_and_eval(&res, (expr = s->w_expr),
485  var_names, var_values,
486  NULL, NULL, NULL, NULL, NULL, 0, ctx);
487  s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res;
488  if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr),
489  var_names, var_values,
490  NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
491  goto fail;
492  s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res;
493  /* evaluate again the width, as it may depend on the output height */
494  if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr),
495  var_names, var_values,
496  NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
497  goto fail;
498  s->w = res;
499 
500  w = s->w;
501  h = s->h;
502 
503  /* sanity check params */
504  if (w < -1 || h < -1) {
505  av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n");
506  return AVERROR(EINVAL);
507  }
508  if (w == -1 && h == -1)
509  s->w = s->h = 0;
510 
511  if (!(w = s->w))
512  w = inlink->w;
513  if (!(h = s->h))
514  h = inlink->h;
515  if (w == -1)
516  w = av_rescale(h, inlink->w, inlink->h);
517  if (h == -1)
518  h = av_rescale(w, inlink->h, inlink->w);
519 
520  if (w > INT_MAX || h > INT_MAX ||
521  (h * inlink->w) > INT_MAX ||
522  (w * inlink->h) > INT_MAX)
523  av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
524 
525  outlink->w = w;
526  outlink->h = h;
527 
528  ret = init_scale_session(ctx, inlink->w, inlink->h, w, h);
529  if (ret < 0)
530  return ret;
531 
532  av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n",
533  inlink->w, inlink->h, outlink->w, outlink->h);
534 
535  if (inlink->sample_aspect_ratio.num)
536  outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w,
537  outlink->w*inlink->h},
538  inlink->sample_aspect_ratio);
539  else
540  outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
541 
542  return 0;
543 
544 fail:
546  "Error when evaluating the expression '%s'\n", expr);
547  return ret;
548 }
549 
551 {
552  AVFilterContext *ctx = link->dst;
553  QSVScaleContext *s = ctx->priv;
554  AVFilterLink *outlink = ctx->outputs[0];
555 
556  mfxSyncPoint sync = NULL;
557  mfxStatus err;
558 
559  AVFrame *out = NULL;
560  int ret = 0;
561 
562  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
563  if (!out) {
564  ret = AVERROR(ENOMEM);
565  goto fail;
566  }
567 
568  do {
569  err = MFXVideoVPP_RunFrameVPPAsync(s->session,
570  (mfxFrameSurface1*)in->data[3],
571  (mfxFrameSurface1*)out->data[3],
572  NULL, &sync);
573  if (err == MFX_WRN_DEVICE_BUSY)
574  av_usleep(1);
575  } while (err == MFX_WRN_DEVICE_BUSY);
576 
577  if (err < 0) {
578  ret = ff_qsvvpp_print_error(ctx, err, "Error during scaling");
579  goto fail;
580  }
581 
582  if (!sync) {
583  av_log(ctx, AV_LOG_ERROR, "No sync during scaling\n");
585  goto fail;
586  }
587 
588  do {
589  err = MFXVideoCORE_SyncOperation(s->session, sync, 1000);
590  } while (err == MFX_WRN_IN_EXECUTION);
591  if (err < 0) {
592  ret = ff_qsvvpp_print_error(ctx, err, "Error synchronizing the operation");
593  goto fail;
594  }
595 
596  ret = av_frame_copy_props(out, in);
597  if (ret < 0)
598  goto fail;
599 
600  out->width = outlink->w;
601  out->height = outlink->h;
602 
603  av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den,
604  (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w,
605  (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h,
606  INT_MAX);
607 
608  av_frame_free(&in);
609  return ff_filter_frame(outlink, out);
610 fail:
611  av_frame_free(&in);
612  av_frame_free(&out);
613  return ret;
614 }
615 
616 #define OFFSET(x) offsetof(QSVScaleContext, x)
617 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
618 static const AVOption options[] = {
619  { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS },
620  { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS },
621  { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },
622 
623 #if QSV_HAVE_SCALING_CONFIG
624  { "mode", "set scaling mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"},
625  { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"},
626  { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"},
627 #else
628  { "mode", "(not supported)", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = 0}, 0, INT_MAX, FLAGS, "mode"},
629  { "low_power", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, FLAGS, "mode"},
630  { "hq", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0, FLAGS, "mode"},
631 #endif
632 
633  { NULL },
634 };
635 
636 static const AVClass qsvscale_class = {
637  .class_name = "scale_qsv",
638  .item_name = av_default_item_name,
639  .option = options,
640  .version = LIBAVUTIL_VERSION_INT,
641 };
642 
643 static const AVFilterPad qsvscale_inputs[] = {
644  {
645  .name = "default",
646  .type = AVMEDIA_TYPE_VIDEO,
647  .filter_frame = qsvscale_filter_frame,
648  },
649 };
650 
651 static const AVFilterPad qsvscale_outputs[] = {
652  {
653  .name = "default",
654  .type = AVMEDIA_TYPE_VIDEO,
655  .config_props = qsvscale_config_props,
656  },
657 };
658 
660  .name = "scale_qsv",
661  .description = NULL_IF_CONFIG_SMALL("QuickSync video scaling and format conversion"),
662 
663  .init = qsvscale_init,
664  .uninit = qsvscale_uninit,
665 
666  .priv_size = sizeof(QSVScaleContext),
667  .priv_class = &qsvscale_class,
668 
671 
673 
674  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
675 };
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:98
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
AVQSVFramesContext::frame_type
int frame_type
A combination of MFX_MEMTYPE_* describing the frame pool.
Definition: hwcontext_qsv.h:49
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
QSVScaleContext::num_ext_buf
int num_ext_buf
Definition: vf_scale_qsv.c:101
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
opt.h
var_names
static const char *const var_names[]
Definition: vf_scale_qsv.c:46
QSV_HAVE_SCALING_CONFIG
#define QSV_HAVE_SCALING_CONFIG
Definition: vf_scale_qsv.c:72
VAR_IW
@ VAR_IW
Definition: vf_scale_qsv.c:63
M_PHI
#define M_PHI
Definition: mathematics.h:49
out
FILE * out
Definition: movenc.c:54
FF_FILTER_FLAG_HWFRAME_AWARE
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
Definition: internal.h:371
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1018
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:209
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:112
QSVScaleContext::session
mfxSession session
Definition: vf_scale_qsv.c:79
qsvscale_init
static av_cold int qsvscale_init(AVFilterContext *ctx)
Definition: vf_scale_qsv.c:122
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:333
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
pixdesc.h
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:247
qsvscale_outputs
static const AVFilterPad qsvscale_outputs[]
Definition: vf_scale_qsv.c:651
AVOption
AVOption.
Definition: opt.h:247
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
frame_alloc
static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition: vf_scale_qsv.c:215
mathematics.h
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:153
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:229
video.h
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:317
VAR_OH
@ VAR_OH
Definition: vf_scale_qsv.c:66
VAR_OUT_H
@ VAR_OUT_H
Definition: vf_scale_qsv.c:66
formats.h
VAR_OUT_W
@ VAR_OUT_W
Definition: vf_scale_qsv.c:65
QSVScaleContext::h_expr
char * h_expr
height expression string
Definition: vf_scale_qsv.c:118
qsvvpp.h
fail
#define fail()
Definition: checkasm.h:127
OFFSET
#define OFFSET(x)
Definition: vf_scale_qsv.c:616
QSVScaleContext::nb_mem_ids_in
int nb_mem_ids_in
Definition: vf_scale_qsv.c:82
QSVScaleContext::h
int h
Definition: vf_scale_qsv.c:110
MFX_IMPL_VIA_MASK
#define MFX_IMPL_VIA_MASK(impl)
Definition: vf_scale_qsv.c:73
QSVScaleContext::mem_ids_out
mfxMemId * mem_ids_out
Definition: vf_scale_qsv.c:84
av_reduce
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition: rational.c:35
init_out_session
static int init_out_session(AVFilterContext *ctx)
Definition: vf_scale_qsv.c:264
AVRational::num
int num
Numerator.
Definition: rational.h:59
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:50
ff_qsvvpp_print_iopattern
int ff_qsvvpp_print_iopattern(void *log_ctx, int mfx_iopattern, const char *extra_string)
Definition: qsvvpp.c:55
QSVScaleContext::nb_surface_ptrs_in
int nb_surface_ptrs_in
Definition: vf_scale_qsv.c:88
VAR_PHI
@ VAR_PHI
Definition: vf_scale_qsv.c:61
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AVHWFramesContext::height
int height
Definition: hwcontext.h:229
VAR_OW
@ VAR_OW
Definition: vf_scale_qsv.c:65
s
#define s(width, name)
Definition: cbs_vp9.c:257
M_E
#define M_E
Definition: mathematics.h:37
QSV_RUNTIME_VERSION_ATLEAST
#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR)
Definition: qsv_internal.h:59
info
MIPS optimizations info
Definition: mips.txt:2
QSVScaleContext::surface_ptrs_in
mfxFrameSurface1 ** surface_ptrs_in
Definition: vf_scale_qsv.c:87
var_name
var_name
Definition: noise_bsf.c:47
ctx
AVFormatContext * ctx
Definition: movenc.c:48
QSVScaleContext::surface_ptrs_out
mfxFrameSurface1 ** surface_ptrs_out
Definition: vf_scale_qsv.c:90
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
NAN
#define NAN
Definition: mathematics.h:64
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:191
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
QSVScaleContext::format
enum AVPixelFormat format
Output sw format.
Definition: vf_scale_qsv.c:115
frame_free
static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition: vf_scale_qsv.c:237
FLAGS
#define FLAGS
Definition: vf_scale_qsv.c:617
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
AVQSVFramesContext::surfaces
mfxFrameSurface1 * surfaces
Definition: hwcontext_qsv.h:43
frame_unlock
static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: vf_scale_qsv.c:247
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:222
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:537
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
VAR_DAR
@ VAR_DAR
Definition: vf_scale_qsv.c:67
AVHWFramesContext::device_ref
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:141
QSVScaleContext::w_expr
char * w_expr
width expression string
Definition: vf_scale_qsv.c:117
ff_qsvvpp_print_error
int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err, const char *error_string)
Definition: qsvvpp.c:127
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:394
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
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:212
QSVScaleContext::ext_buffers
mfxExtBuffer * ext_buffers[1+QSV_HAVE_SCALING_CONFIG]
Definition: vf_scale_qsv.c:100
frame_lock
static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: vf_scale_qsv.c:242
QSVScaleContext::mode
int mode
Definition: vf_scale_qsv.c:98
QSVScaleContext::shift_height
int shift_height
Definition: vf_scale_qsv.c:103
eval.h
VAR_IN_W
@ VAR_IN_W
Definition: vf_scale_qsv.c:63
ff_vf_scale_qsv
const AVFilter ff_vf_scale_qsv
Definition: vf_scale_qsv.c:659
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
av_expr_parse_and_eval
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
Definition: eval.c:776
VAR_IH
@ VAR_IH
Definition: vf_scale_qsv.c:64
QSVScaleContext::nb_mem_ids_out
int nb_mem_ids_out
Definition: vf_scale_qsv.c:85
frame_get_hdl
static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition: vf_scale_qsv.c:252
AVQSVFramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_qsv.h:44
qsvscale_config_props
static int qsvscale_config_props(AVFilterLink *outlink)
Definition: vf_scale_qsv.c:461
M_PI
#define M_PI
Definition: mathematics.h:52
VARS_NB
@ VARS_NB
Definition: vf_scale_qsv.c:69
internal.h
options
static const AVOption options[]
Definition: vf_scale_qsv.c:618
FILTER_SINGLE_PIXFMT
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition: internal.h:181
QSVScaleContext::shift_width
int shift_width
Definition: vf_scale_qsv.c:103
init_out_pool
static int init_out_pool(AVFilterContext *ctx, int out_width, int out_height)
Definition: vf_scale_qsv.c:159
hwcontext_qsv.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
internal.h
VAR_A
@ VAR_A
Definition: vf_scale_qsv.c:67
common.h
VAR_IN_H
@ VAR_IN_H
Definition: vf_scale_qsv.c:64
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:56
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:128
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:271
AVFilter
Filter definition.
Definition: avfilter.h:149
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
AVHWFramesContext::device_ctx
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:149
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:162
AVFrame::sample_aspect_ratio
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition: frame.h:391
av_get_pix_fmt
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:2496
qsvscale_class
static const AVClass qsvscale_class
Definition: vf_scale_qsv.c:636
AVQSVDeviceContext::session
mfxSession session
Definition: hwcontext_qsv.h:36
qsvscale_inputs
static const AVFilterPad qsvscale_inputs[]
Definition: vf_scale_qsv.c:643
AVRational::den
int den
Denominator.
Definition: rational.h:60
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
avfilter.h
QSVScaleContext::mem_ids_in
mfxMemId * mem_ids_in
Definition: vf_scale_qsv.c:81
av_mul_q
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
AVFilterContext
An instance of a filter.
Definition: avfilter.h:386
AVQSVFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_qsv.h:42
AVHWFramesContext::initial_pool_size
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:199
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
qsvscale_filter_frame
static int qsvscale_filter_frame(AVFilterLink *link, AVFrame *in)
Definition: vf_scale_qsv.c:550
init_scale_session
static int init_scale_session(AVFilterContext *ctx, int in_width, int in_height, int out_width, int out_height)
Definition: vf_scale_qsv.c:443
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:192
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
hwcontext.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
QSVScaleContext
Definition: vf_scale_qsv.c:75
qsvscale_uninit
static av_cold void qsvscale_uninit(AVFilterContext *ctx)
Definition: vf_scale_qsv.c:139
h
h
Definition: vp9dsp_template.c:2038
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
QSVScaleContext::w
int w
New dimensions.
Definition: vf_scale_qsv.c:110
QSVScaleContext::format_str
char * format_str
Definition: vf_scale_qsv.c:119
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:233
VAR_SAR
@ VAR_SAR
Definition: vf_scale_qsv.c:68
VAR_PI
@ VAR_PI
Definition: vf_scale_qsv.c:60
QSVScaleContext::nb_surface_ptrs_out
int nb_surface_ptrs_out
Definition: vf_scale_qsv.c:91
ff_qsvvpp_print_warning
int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err, const char *warning_string)
Definition: qsvvpp.c:137
VAR_E
@ VAR_E
Definition: vf_scale_qsv.c:62
QSVScaleContext::opaque_alloc
mfxExtOpaqueSurfaceAlloc opaque_alloc
Definition: vf_scale_qsv.c:93
ff_filter_init_hw_frames
int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, int default_pool_size)
Perform any additional setup required for hardware frames.
Definition: avfilter.c:1567