X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_scale.c;h=cb427940861b52e065d4b4d6aa341492cfeede77;hb=c271d88257e74ec24a6815b66ef4d5cdbc3a05ba;hp=f741419e7e23bbcf1c78fe00b2395585b5fc4af6;hpb=762c2b5dcd99a08452299cd1f83070f88115f1f3;p=ffmpeg diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index f741419e7e2..cb427940861 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -86,6 +86,7 @@ typedef struct ScaleContext { int in_v_chr_pos; int force_original_aspect_ratio; + int force_divisible_by; int nb_slices; @@ -237,7 +238,8 @@ static int config_props(AVFilterLink *outlink) 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. */ + * 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); @@ -245,9 +247,19 @@ static int config_props(AVFilterLink *outlink) 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; + } } } @@ -400,7 +412,7 @@ static int scale_slice(AVFilterLink *link, AVFrame *out_buf, AVFrame *cur_pic, s out,out_stride); } -static int filter_frame(AVFilterLink *link, AVFrame *in) +static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) { ScaleContext *scale = link->dst->priv; AVFilterLink *outlink = link->dst->outputs[0]; @@ -409,6 +421,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) char buf[32]; int in_range; + *frame_out = NULL; if (in->colorspace == AVCOL_SPC_YCGCO) av_log(link->dst, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); @@ -437,8 +450,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) return ret; } - if (!scale->sws) - return ff_filter_frame(outlink, in); + if (!scale->sws) { + *frame_out = in; + return 0; + } scale->hsub = desc->log2_chroma_w; scale->vsub = desc->log2_chroma_h; @@ -448,6 +463,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) av_frame_free(&in); return AVERROR(ENOMEM); } + *frame_out = out; av_frame_copy_props(out, in); out->width = outlink->w; @@ -521,7 +537,21 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) } av_frame_free(&in); - return ff_filter_frame(outlink, out); + return 0; +} + +static int filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + int ret; + + ret = scale_frame(link, in, &out); + if (out) + return ff_filter_frame(outlink, out); + + return ret; } static int filter_frame_ref(AVFilterLink *link, AVFrame *in) @@ -572,8 +602,16 @@ static const AVOption scale_options[] = { { "interl", "set interlacing", OFFSET(interlaced), AV_OPT_TYPE_BOOL, {.i64 = 0 }, -1, 1, FLAGS }, { "size", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS }, { "s", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS }, - { "in_color_matrix", "set input YCbCr type", OFFSET(in_color_matrix), AV_OPT_TYPE_STRING, { .str = "auto" }, .flags = FLAGS }, - { "out_color_matrix", "set output YCbCr type", OFFSET(out_color_matrix), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "in_color_matrix", "set input YCbCr type", OFFSET(in_color_matrix), AV_OPT_TYPE_STRING, { .str = "auto" }, .flags = FLAGS, "color" }, + { "out_color_matrix", "set output YCbCr type", OFFSET(out_color_matrix), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS, "color"}, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .str = "auto" }, 0, 0, FLAGS, "color" }, + { "bt601", NULL, 0, AV_OPT_TYPE_CONST, { .str = "bt601" }, 0, 0, FLAGS, "color" }, + { "bt470", NULL, 0, AV_OPT_TYPE_CONST, { .str = "bt470" }, 0, 0, FLAGS, "color" }, + { "smpte170m", NULL, 0, AV_OPT_TYPE_CONST, { .str = "smpte170m" }, 0, 0, FLAGS, "color" }, + { "bt709", NULL, 0, AV_OPT_TYPE_CONST, { .str = "bt709" }, 0, 0, FLAGS, "color" }, + { "fcc", NULL, 0, AV_OPT_TYPE_CONST, { .str = "fcc" }, 0, 0, FLAGS, "color" }, + { "smpte240m", NULL, 0, AV_OPT_TYPE_CONST, { .str = "smpte240m" }, 0, 0, FLAGS, "color" }, + { "bt2020", NULL, 0, AV_OPT_TYPE_CONST, { .str = "bt2020" }, 0, 0, FLAGS, "color" }, { "in_range", "set input color range", OFFSET( in_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" }, { "out_range", "set output color range", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" }, { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, "range" }, @@ -592,6 +630,7 @@ static const AVOption scale_options[] = { { "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 }, { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS }, { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS }, { "nb_slices", "set the number of slices (debug purpose only)", OFFSET(nb_slices), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },