[FFmpeg-devel] [PATCH] avfilter/scale_vaapi: add support for basic height/width expressions
Aman Gupta
ffmpeg at tmm1.net
Tue Jan 31 23:00:41 EET 2017
On Tue, Jan 31, 2017 at 12:26 PM, Mark Thompson <sw at jkqxz.net> wrote:
> On 31/01/17 19:14, Aman Gupta wrote:
> > From: Aman Gupta <aman at tmm1.net>
> >
> > Copied directly from vf_scale.c.
> >
> > Implements the same expression logic, however not all the variables were
> copied over.
> > This patch was sufficient for my particular use-case
> `scale_vaapi=-2:min(ih\,720)`,
> > but perhaps it makes sense to add support for the remaining variables
> > and pull out shared code into a new vf_scale_common.c?
>
> I would prefer the code fragment not to be copied again, yes.
>
> (Implementing this and removing the duplication between scale, scale_npp,
> scale_qsv and scale_vaapi has been on my to-maybe-do-at-some-point list for
> quite a while, but I've never actually had a use-case for it to push me
> into actually doing it :)
>
Ok, I'll see if I can refactor things to avoid duplication.
You mentioned scale_qsv, and I see the git commit in the history that added
it. But vf_scale_qsv.c is no where to be found on master. Do you know what
happened to it? I'd like to implement the same logic there too if I'm
refactoring things..
>
> If you can't be bothered, then the patch looks mostly sensible to me (some
> issues below, I think mainly coming from it being copied).
>
> > ---
> > libavfilter/vf_scale_vaapi.c | 98 ++++++++++++++++++++++++++++++
> ++++++++++++--
> > 1 file changed, 95 insertions(+), 3 deletions(-)
> >
> > diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
> > index d1cb246..0d1e1b3 100644
> > --- a/libavfilter/vf_scale_vaapi.c
> > +++ b/libavfilter/vf_scale_vaapi.c
> > @@ -22,6 +22,7 @@
> > #include <va/va_vpp.h>
> >
> > #include "libavutil/avassert.h"
> > +#include "libavutil/eval.h"
> > #include "libavutil/hwcontext.h"
> > #include "libavutil/hwcontext_vaapi.h"
> > #include "libavutil/mem.h"
> > @@ -32,6 +33,22 @@
> > #include "formats.h"
> > #include "internal.h"
> >
> > +static const char *const var_names[] = {
> > + "in_w", "iw",
> > + "in_h", "ih",
> > + "out_w", "ow",
> > + "out_h", "oh",
> > + NULL
> > +};
> > +
> > +enum var_name {
> > + VAR_IN_W, VAR_IW,
> > + VAR_IN_H, VAR_IH,
> > + VAR_OUT_W, VAR_OW,
> > + VAR_OUT_H, VAR_OH,
> > + VARS_NB
> > +};
> > +
> > typedef struct ScaleVAAPIContext {
> > const AVClass *class;
> >
> > @@ -50,9 +67,21 @@ typedef struct ScaleVAAPIContext {
> >
> > char *output_format_string;
> > enum AVPixelFormat output_format;
> > +
> > + /**
> > + * New dimensions. Special values are:
> > + * 0 = original width/height
> > + * -1 = keep original aspect
> > + * -N = try to keep aspect but make sure it is divisible by N
> > + */
> > + int w, h;
>
> Why do these exist in addition to output_width and output_height? They
> only seem to be used as temporaries duplicating w and h in
> scale_vaapi_config_output().
>
> > +
> > + char *w_expr; ///< width expression string
> > + char *h_expr; ///< height expression string
> > +
> > + /* computed width/height */
> > int output_width;
> > int output_height;
> > -
> > } ScaleVAAPIContext;
> >
> >
> > @@ -118,6 +147,14 @@ static int scale_vaapi_config_output(AVFilterLink
> *outlink)
> > VAStatus vas;
> > int err, i;
> >
> > + AVFilterLink *inlink = outlink->src->inputs[0];
> > + ScaleVAAPIContext *scale = ctx;
>
> Just use the ctx variable?
>
> > + int64_t w, h;
> > + double var_values[VARS_NB], res;
> > + char *expr;
>
> This variable is write-only.
>
> > + int ret;
>
> Just use err (because of the difference you aren't setting the correct
> error return if one of the evaluation operations fails).
>
> > + int factor_w, factor_h;
> > +
> > scale_vaapi_pipeline_uninit(ctx);
> >
> > ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
> > @@ -162,6 +199,61 @@ static int scale_vaapi_config_output(AVFilterLink
> *outlink)
> > }
> > }
> >
> > + var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w;
> > + var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h;
> > + var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
> > + var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
> > +
> > + /* evaluate width and height */
> > + av_expr_parse_and_eval(&res, (expr = scale->w_expr),
> > + var_names, var_values,
> > + NULL, NULL, NULL, NULL, NULL, 0, ctx);
> > + scale->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res;
> > + if ((ret = av_expr_parse_and_eval(&res, (expr = scale->h_expr),
> > + var_names, var_values,
> > + NULL, NULL, NULL, NULL, NULL, 0,
> ctx)) < 0)
> > + goto fail;
> > + scale->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res;
> > + /* evaluate again the width, as it may depend on the output height
> */
> > + if ((ret = av_expr_parse_and_eval(&res, (expr = scale->w_expr),
> > + var_names, var_values,
> > + NULL, NULL, NULL, NULL, NULL, 0,
> ctx)) < 0)
> > + goto fail;
> > + scale->w = res;
> > +
> > + w = scale->w;
> > + h = scale->h;
> > +
> > + /* Check if it is requested that the result has to be divisible by
> a some
> > + * factor (w or h = -n with n being the factor). */
> > + factor_w = 1;
> > + factor_h = 1;
> > + if (w < -1) {
> > + factor_w = -w;
> > + }
> > + if (h < -1) {
> > + factor_h = -h;
> > + }
> > +
> > + if (w < 0 && h < 0)
> > + scale->w = scale->h = 0;
> > +
> > + if (!(w = scale->w))
> > + w = inlink->w;
> > + if (!(h = scale->h))
> > + h = inlink->h;
> > +
> > + /* Make sure that the result is divisible by the factor we
> determined
> > + * earlier. If no factor was set, it is nothing will happen as the
> default
> > + * factor is 1 */
> > + if (w < 0)
> > + w = av_rescale(h, inlink->w, inlink->h * factor_w) * factor_w;
> > + if (h < 0)
> > + h = av_rescale(w, inlink->h, inlink->w * factor_h) * factor_h;
> > +
> > + ctx->output_width = w;
> > + ctx->output_height = h;
> > +
> > if (ctx->output_width < constraints->min_width ||
> > ctx->output_height < constraints->min_height ||
> > ctx->output_width > constraints->max_width ||
> > @@ -414,9 +506,9 @@ static av_cold void scale_vaapi_uninit(AVFilterContext
> *avctx)
> > #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
> > static const AVOption scale_vaapi_options[] = {
> > { "w", "Output video width",
> > - OFFSET(output_width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
> .flags = FLAGS },
> > + OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = FLAGS },
> > { "h", "Output video height",
> > - OFFSET(output_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
> .flags = FLAGS },
> > + OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = FLAGS },
>
> Should these have default values? "iw", "ih", maybe. (It currently
> segfaults in the evaluation if either of them are not set.)
>
> > { "format", "Output video format (software format of hardware
> frames)",
> > OFFSET(output_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS
> },
> > { NULL },
> >
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
More information about the ffmpeg-devel
mailing list