static int config_output()

in Transform360/vf_transform360.c [170:274]


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->output_stereo_format == STEREO_FORMAT_GUESS) {
        if (s->input_stereo_format == STEREO_FORMAT_MONO) {
            s->output_stereo_format = STEREO_FORMAT_MONO;
        } else {
            s->output_stereo_format =
                (s->output_layout == LAYOUT_CUBEMAP_23_OFFCENTER)
                    ? STEREO_FORMAT_LR
                    : STEREO_FORMAT_TB;
        }
    }

    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_32) {
            outlink->w = s->cube_edge_length * 3;
            outlink->h = s->cube_edge_length * 2;

        } else if (s->output_layout == LAYOUT_CUBEMAP_23_OFFCENTER) {
            outlink->w = s->cube_edge_length * 2;
            outlink->h = s->cube_edge_length * 3;
        }
    } 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;
    }

    if (s->output_stereo_format == STEREO_FORMAT_TB) {
        outlink->h *= 2;
        s->h *= 2;
    } else if (s->output_stereo_format == STEREO_FORMAT_LR) {
        outlink->w *= 2;
        s->w *= 2;
    }

    av_log(ctx, AV_LOG_VERBOSE, "out_w:%d out_h:%d\n",
            outlink->w, outlink->h);

    return 0;
}