[FFmpeg-devel] [PATCH] avfilter/scale_vaapi: add support for basic height/width expressions
Mark Thompson
sw at jkqxz.net
Tue Jan 31 22:26:47 EET 2017
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 :)
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 },
>
More information about the ffmpeg-devel
mailing list