summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/filters.texi4
-rw-r--r--libavfilter/vf_fieldhint.c31
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;