From 1ab83dd3693742da42a32e1f8ed5f9a0778ed43e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 14 Mar 2022 17:39:01 +0100 Subject: [PATCH] avfilter/vf_fieldhint: add pattern mode of filtering --- doc/filters.texi | 4 +++- libavfilter/vf_fieldhint.c | 31 ++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index c4cf083526..2607c1330b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12318,7 +12318,9 @@ case of @code{b} it will use only bottom field. If line starts with @code{#} or @code{;} that line is skipped. @item mode -Can be item @code{absolute} or @code{relative}. Default is @code{absolute}. +Can be item @code{absolute} or @code{relative} or @code{pattern}. Default is @code{absolute}. +The @code{pattern} mode is same as @code{relative} mode, except at last entry of file if there +are more frames to process than @code{hint} file is seek back to start. @end table Example of first several lines of @code{hint} file for @code{relative} mode: diff --git a/libavfilter/vf_fieldhint.c b/libavfilter/vf_fieldhint.c index e4513dddfa..e7afac1116 100644 --- a/libavfilter/vf_fieldhint.c +++ b/libavfilter/vf_fieldhint.c @@ -27,6 +27,13 @@ #include "internal.h" #include "video.h" +enum HintModes { + ABSOLUTE_HINT, + RELATIVE_HINT, + PATTERN_HINT, + NB_HINTS, +}; + typedef struct FieldHintContext { const AVClass *class; @@ -48,9 +55,10 @@ typedef struct FieldHintContext { static const AVOption fieldhint_options[] = { { "hint", "set hint file", OFFSET(hint_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, - { "mode", "set hint mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" }, - { "absolute", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, - { "relative", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, + { "mode", "set hint mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_HINTS-1, FLAGS, "mode" }, + { "absolute", 0, 0, AV_OPT_TYPE_CONST, {.i64=ABSOLUTE_HINT}, 0, 0, FLAGS, "mode" }, + { "relative", 0, 0, AV_OPT_TYPE_CONST, {.i64=RELATIVE_HINT}, 0, 0, FLAGS, "mode" }, + { "pattern", 0, 0, AV_OPT_TYPE_CONST, {.i64=PATTERN_HINT}, 0, 0, FLAGS, "mode" }, { NULL } }; @@ -141,22 +149,30 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return AVERROR_INVALIDDATA; } switch (s->mode) { - case 0: + case ABSOLUTE_HINT: if (tf > outlink->frame_count_in + 1 || tf < FFMAX(0, outlink->frame_count_in - 1) || bf > outlink->frame_count_in + 1 || bf < FFMAX(0, outlink->frame_count_in - 1)) { av_log(ctx, AV_LOG_ERROR, "Out of range frames %"PRId64" and/or %"PRId64" on line %"PRId64" for %"PRId64". input frame.\n", tf, bf, s->line, inlink->frame_count_out); return AVERROR_INVALIDDATA; } break; - case 1: + case PATTERN_HINT: + case RELATIVE_HINT: if (tf > 1 || tf < -1 || bf > 1 || bf < -1) { av_log(ctx, AV_LOG_ERROR, "Out of range %"PRId64" and/or %"PRId64" on line %"PRId64" for %"PRId64". input frame.\n", tf, bf, s->line, inlink->frame_count_out); return AVERROR_INVALIDDATA; } + break; + default: + return AVERROR_BUG; }; break; } else { + if (s->mode == PATTERN_HINT) { + fseek(s->hint, 0, SEEK_SET); + continue; + } av_log(ctx, AV_LOG_ERROR, "Missing entry for %"PRId64". input frame.\n", inlink->frame_count_out); return AVERROR_INVALIDDATA; } @@ -168,11 +184,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, s->frame[1]); switch (s->mode) { - case 0: + case ABSOLUTE_HINT: top = s->frame[tf - outlink->frame_count_in + 1]; bottom = s->frame[bf - outlink->frame_count_in + 1]; break; - case 1: + case PATTERN_HINT: + case RELATIVE_HINT: top = s->frame[1 + tf]; bottom = s->frame[1 + bf]; break;