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