avfilter/scale.c: factorize ff_scale_eval_dimensions

Adjustment of evaluated values shifted to ff_adjust_scale_dimensions
Shifted code for force_original_aspect_ratio and force_divisble_by from
vf_scale so it is now available for scale_cuda, scale_npp and
scale_vaapi as well.
This commit is contained in:
Gyan Doshi 2019-12-02 21:11:21 +05:30
parent ff2b75d94c
commit 1b4f473d18
7 changed files with 146 additions and 38 deletions

View file

@ -111,8 +111,6 @@ int ff_scale_eval_dimensions(void *log_ctx,
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format);
const char *expr;
int w, h;
int factor_w, factor_h;
int eval_w, eval_h;
int ret;
const char scale2ref = outlink->src->nb_inputs == 2 && outlink->src->inputs[1] == inlink;
@ -172,10 +170,30 @@ int ff_scale_eval_dimensions(void *log_ctx,
goto fail;
eval_w = (int) res == 0 ? inlink->w : (int) res;
w = eval_w;
h = eval_h;
*ret_w = eval_w;
*ret_h = eval_h;
/* Check if it is requested that the result has to be divisible by a some
return 0;
fail:
av_log(log_ctx, AV_LOG_ERROR,
"Error when evaluating the expression '%s'.\n"
"Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n",
expr, w_expr, h_expr);
return ret;
}
int ff_scale_adjust_dimensions(AVFilterLink *inlink,
int *ret_w, int *ret_h,
int force_original_aspect_ratio, int force_divisible_by)
{
int w, h;
int factor_w, factor_h;
w = *ret_w;
h = *ret_h;
/* Check if it is requested that the result has to be divisible by some
* factor (w or h = -n with n being the factor). */
factor_w = 1;
factor_h = 1;
@ -192,22 +210,41 @@ int ff_scale_eval_dimensions(void *log_ctx,
}
/* 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
* earlier. If no factor was set, 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;
/* Note that force_original_aspect_ratio may overwrite the previous set
* dimensions so that it is not divisible by the set factors anymore
* unless force_divisible_by is defined as well */
if (force_original_aspect_ratio) {
int tmp_w = av_rescale(h, inlink->w, inlink->h);
int tmp_h = av_rescale(w, inlink->h, inlink->w);
if (force_original_aspect_ratio == 1) {
w = FFMIN(tmp_w, w);
h = FFMIN(tmp_h, h);
if (force_divisible_by > 1) {
// round down
w = w / force_divisible_by * force_divisible_by;
h = h / force_divisible_by * force_divisible_by;
}
} else {
w = FFMAX(tmp_w, w);
h = FFMAX(tmp_h, h);
if (force_divisible_by > 1) {
// round up
w = (w + force_divisible_by - 1) / force_divisible_by * force_divisible_by;
h = (h + force_divisible_by - 1) / force_divisible_by * force_divisible_by;
}
}
}
*ret_w = w;
*ret_h = h;
return 0;
fail:
av_log(log_ctx, AV_LOG_ERROR,
"Error when evaluating the expression '%s'.\n"
"Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n",
expr, w_expr, h_expr);
return ret;
}

View file

@ -21,8 +21,28 @@
#include "avfilter.h"
/**
* Parse and evaluate string expressions for width and height. Upon success,
* ff_scale_adjust_dimensions must be called with evaluated width and height
* to obtain actual target dimensions.
*
* Returns 0 upon success, negative value if one of the expressions could
* not be parsed or if NaN was the result of their evaluation.
*/
int ff_scale_eval_dimensions(void *ctx,
const char *w_expr, const char *h_expr,
AVFilterLink *inlink, AVFilterLink *outlink,
int *ret_w, int *ret_h);
/**
* Transform evaluated width and height obtained from ff_scale_eval_dimensions
* into actual target width and height for scaling. Adjustment can occur if one
* or both of the evaluated values are of the form '-n' or if
* force_original_aspect_ratio is set.
*
* Returns 0.
*/
int ff_scale_adjust_dimensions(AVFilterLink *inlink,
int *ret_w, int *ret_h,
int force_original_aspect_ratio, int force_divisible_by);
#endif

View file

@ -237,31 +237,9 @@ static int config_props(AVFilterLink *outlink)
&w, &h)) < 0)
goto fail;
/* Note that force_original_aspect_ratio may overwrite the previous set
* dimensions so that it is not divisible by the set factors anymore
* unless force_divisible_by is defined as well */
if (scale->force_original_aspect_ratio) {
int tmp_w = av_rescale(h, inlink->w, inlink->h);
int tmp_h = av_rescale(w, inlink->h, inlink->w);
if (scale->force_original_aspect_ratio == 1) {
w = FFMIN(tmp_w, w);
h = FFMIN(tmp_h, h);
if (scale->force_divisible_by > 1) {
// round down
w = w / scale->force_divisible_by * scale->force_divisible_by;
h = h / scale->force_divisible_by * scale->force_divisible_by;
}
} else {
w = FFMAX(tmp_w, w);
h = FFMAX(tmp_h, h);
if (scale->force_divisible_by > 1) {
// round up
w = (w + scale->force_divisible_by - 1) / scale->force_divisible_by * scale->force_divisible_by;
h = (h + scale->force_divisible_by - 1) / scale->force_divisible_by * scale->force_divisible_by;
}
}
}
ff_scale_adjust_dimensions(inlink, &w, &h,
scale->force_original_aspect_ratio,
scale->force_divisible_by);
if (w > INT_MAX || h > INT_MAX ||
(h * inlink->w) > INT_MAX ||

View file

@ -82,6 +82,9 @@ typedef struct CUDAScaleContext {
char *w_expr; ///< width expression string
char *h_expr; ///< height expression string
int force_original_aspect_ratio;
int force_divisible_by;
CUcontext cu_ctx;
CUmodule cu_module;
CUfunction cu_func_uchar;
@ -305,6 +308,9 @@ static av_cold int cudascale_config_props(AVFilterLink *outlink)
&w, &h)) < 0)
goto fail;
ff_scale_adjust_dimensions(inlink, &w, &h,
s->force_original_aspect_ratio, s->force_divisible_by);
if (((int64_t)h * inlink->w) > INT_MAX ||
((int64_t)w * inlink->h) > INT_MAX)
av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
@ -536,6 +542,11 @@ fail:
static const AVOption options[] = {
{ "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS },
{ "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS },
{ "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" },
{ "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" },
{ "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
{ "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
{ "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS },
{ NULL },
};

View file

@ -98,6 +98,9 @@ typedef struct NPPScaleContext {
char *h_expr; ///< height expression string
char *format_str;
int force_original_aspect_ratio;
int force_divisible_by;
int interp_algo;
} NPPScaleContext;
@ -347,6 +350,9 @@ static int nppscale_config_props(AVFilterLink *outlink)
&w, &h)) < 0)
goto fail;
ff_scale_adjust_dimensions(inlink, &w, &h,
s->force_original_aspect_ratio, s->force_divisible_by);
if (((int64_t)h * inlink->w) > INT_MAX ||
((int64_t)w * inlink->h) > INT_MAX)
av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
@ -552,6 +558,11 @@ static const AVOption options[] = {
{ "cubic2p_b05c03", "2-parameter cubic (B=1/2, C=3/10)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_B05C03 }, 0, 0, FLAGS, "interp_algo" },
{ "super", "supersampling", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_SUPER }, 0, 0, FLAGS, "interp_algo" },
{ "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LANCZOS }, 0, 0, FLAGS, "interp_algo" },
{ "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" },
{ "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" },
{ "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
{ "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
{ "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS },
{ NULL },
};

View file

@ -40,6 +40,9 @@ typedef struct ScaleVAAPIContext {
char *w_expr; // width expression string
char *h_expr; // height expression string
int force_original_aspect_ratio;
int force_divisible_by;
char *colour_primaries_string;
char *colour_transfer_string;
char *colour_matrix_string;
@ -81,6 +84,9 @@ static int scale_vaapi_config_output(AVFilterLink *outlink)
&vpp_ctx->output_width, &vpp_ctx->output_height)) < 0)
return err;
ff_scale_adjust_dimensions(inlink, &vpp_ctx->output_width, &vpp_ctx->output_height,
ctx->force_original_aspect_ratio, ctx->force_divisible_by);
err = ff_vaapi_vpp_config_output(outlink);
if (err < 0)
return err;
@ -247,6 +253,11 @@ static const AVOption scale_vaapi_options[] = {
{ "out_chroma_location", "Output chroma sample location",
OFFSET(chroma_location_string), AV_OPT_TYPE_STRING,
{ .str = NULL }, .flags = FLAGS },
{ "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" },
{ "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" },
{ "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
{ "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
{ "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS },
{ NULL },
};