in Transform_V1/vf_transform_v1.c [644:741]
static int config_output(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
AVFilterLink *inlink = outlink->src->inputs[0];
TransformContext *s = ctx->priv;
double var_values[VARS_NB], res;
char *expr;
int ret;
var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
if (s->input_stereo_format == STEREO_FORMAT_GUESS) {
int aspect_ratio = inlink->w / inlink->h;
if (aspect_ratio == 1)
s->input_stereo_format = STEREO_FORMAT_TB;
else if (aspect_ratio == 4)
s->input_stereo_format = STEREO_FORMAT_LR;
else
s->input_stereo_format = STEREO_FORMAT_MONO;
}
if (s->max_cube_edge_length > 0) {
if (s->input_stereo_format == STEREO_FORMAT_LR) {
s->cube_edge_length = inlink->w / 8;
} else {
s->cube_edge_length = inlink->w / 4;
}
// do not exceed the max length supplied
if (s->cube_edge_length > s->max_cube_edge_length) {
s->cube_edge_length = s->max_cube_edge_length;
}
}
// ensure cube edge length is a multiple of 16 by rounding down
// so that macroblocks do not cross cube edge boundaries
s->cube_edge_length = s->cube_edge_length - (s->cube_edge_length % 16);
if (s->cube_edge_length > 0) {
if (s->output_layout == LAYOUT_CUBEMAP || s->output_layout == LAYOUT_PLANE_CUBEMAP) {
outlink->w = s->cube_edge_length * 6;
outlink->h = s->cube_edge_length;
if (s->input_stereo_format == STEREO_FORMAT_TB || s->input_stereo_format == STEREO_FORMAT_LR)
outlink->h = outlink->h * 2;
} else if (s->output_layout == LAYOUT_CUBEMAP_32 || s->output_layout == LAYOUT_PLANE_CUBEMAP_32) {
outlink->w = s->cube_edge_length * 3;
outlink->h = s->cube_edge_length * 2;
if (s->input_stereo_format == STEREO_FORMAT_TB || s->input_stereo_format == STEREO_FORMAT_LR)
outlink->h = outlink->h * 2;
} else if (s->output_layout == LAYOUT_CUBEMAP_180) {
outlink->w = s->cube_edge_length * 2.5;
outlink->h = s->cube_edge_length * 1.5;
if (s->input_stereo_format == STEREO_FORMAT_TB || s->input_stereo_format == STEREO_FORMAT_LR)
outlink->h = outlink->h * 2;
}
} else {
var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
av_expr_parse_and_eval(&res, (expr = s->w_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx);
s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res;
if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
av_log(NULL, 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, s->w_expr, s->h_expr);
return ret;
}
s->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 = s->w_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
av_log(NULL, 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, s->w_expr, s->h_expr);
return ret;
}
s->w = res;
outlink->w = s->w;
outlink->h = s->h;
}
av_log(ctx, AV_LOG_VERBOSE, "out_w:%d out_h:%d\n",
outlink->w, outlink->h);
return 0;
}