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