From 7056ddc0e0f1a55996add89e30f0f43054bc68f0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 19 Oct 2019 13:08:37 +0200 Subject: [PATCH] avfilter/vf_fieldhint: add support for duplicating fields Fixes #7066 --- doc/filters.texi | 2 ++ libavfilter/vf_fieldhint.c | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index b105421aee..9b33df7571 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10121,6 +10121,8 @@ field and second number tells from which frame to pick up bottom field. If optionally followed by @code{+} output frame will be marked as interlaced, else if followed by @code{-} output frame will be marked as progressive, else it will be marked same as input frame. +If optionally followed by @code{t} output frame will use only top field, or in +case of @code{b} it will use only bottom field. If line starts with @code{#} or @code{;} that line is skipped. @item mode diff --git a/libavfilter/vf_fieldhint.c b/libavfilter/vf_fieldhint.c index 3cfeb20a38..a5d6762f09 100644 --- a/libavfilter/vf_fieldhint.c +++ b/libavfilter/vf_fieldhint.c @@ -117,7 +117,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out, *top, *bottom; char buf[1024] = { 0 }; int64_t tf, bf; - char hint = '='; + int tfactor = 0, bfactor = 1; + char hint = '=', field = '='; int p; av_frame_free(&s->frame[0]); @@ -137,6 +138,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->line++; if (buf[0] == '#' || buf[0] == ';') { continue; + } else if (sscanf(buf, "%"PRId64",%"PRId64" %c %c", &tf, &bf, &hint, &field) == 4) { + ; } else if (sscanf(buf, "%"PRId64",%"PRId64" %c", &tf, &bf, &hint) == 3) { ; } else if (sscanf(buf, "%"PRId64",%"PRId64"", &tf, &bf) == 2) { @@ -185,6 +188,23 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_assert0(0); } + switch (field) { + case 'b': + tfactor = 1; + top = bottom; + break; + case 't': + bfactor = 0; + bottom = top; + break; + case '=': + break; + default: + av_log(ctx, AV_LOG_ERROR, "Invalid field: %c.\n", field); + av_frame_free(&out); + return AVERROR(EINVAL); + } + switch (hint) { case '+': out->interlaced_frame = 1; @@ -194,6 +214,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) break; case '=': break; + case 'b': + tfactor = 1; + top = bottom; + break; + case 't': + bfactor = 0; + bottom = top; + break; default: av_log(ctx, AV_LOG_ERROR, "Invalid hint: %c.\n", hint); av_frame_free(&out); @@ -203,13 +231,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) for (p = 0; p < s->nb_planes; p++) { av_image_copy_plane(out->data[p], out->linesize[p] * 2, - top->data[p], + top->data[p] + tfactor * top->linesize[p], top->linesize[p] * 2, s->planewidth[p], (s->planeheight[p] + 1) / 2); av_image_copy_plane(out->data[p] + out->linesize[p], out->linesize[p] * 2, - bottom->data[p] + bottom->linesize[p], + bottom->data[p] + bfactor * bottom->linesize[p], bottom->linesize[p] * 2, s->planewidth[p], (s->planeheight[p] + 1) / 2);