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