[FFmpeg-devel] [PATCH] avfilter/scale_vaapi: add support for basic height/width expressions
Aman Gupta
ffmpeg at tmm1.net
Tue Jan 31 21:14:56 EET 2017
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?
---
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;
+
+ 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;
+ int64_t w, h;
+ double var_values[VARS_NB], res;
+ char *expr;
+ int ret;
+ 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 },
{ "format", "Output video format (software format of hardware frames)",
OFFSET(output_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS },
{ NULL },
--
2.10.1 (Apple Git-78)
More information about the ffmpeg-devel
mailing list