summaryrefslogtreecommitdiff
path: root/libavfilter
diff options
context:
space:
mode:
authorThilo Borgmann <thilo.borgmann@mail.de>2023-05-08 14:37:26 +0200
committerThilo Borgmann <thilo.borgmann@mail.de>2023-05-08 21:55:53 +0200
commit21a0b6bca80192a641b09774c603bd1acbda316e (patch)
tree0df02a93f1c8c3ea5158b7a01e7b8c0fa7e3c794 /libavfilter
parent1eed7f65624cd590a4acd944f9bbeb9f03634a3f (diff)
downloadffmpeg-21a0b6bca80192a641b09774c603bd1acbda316e.tar.gz
avfilter/vf_mpdecimate: Add option to keep the first N similar frames before dropping
This allows for decimating large similar portions of a video while preserving small ones.
Diffstat (limited to 'libavfilter')
-rw-r--r--libavfilter/version.h2
-rw-r--r--libavfilter/vf_mpdecimate.c19
2 files changed, 18 insertions, 3 deletions
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 4dc176dc55..c303f96b15 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -32,7 +32,7 @@
#include "version_major.h"
#define LIBAVFILTER_VERSION_MINOR 7
-#define LIBAVFILTER_VERSION_MICRO 101
+#define LIBAVFILTER_VERSION_MICRO 102
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
diff --git a/libavfilter/vf_mpdecimate.c b/libavfilter/vf_mpdecimate.c
index 71f673cb64..a7b50d3973 100644
--- a/libavfilter/vf_mpdecimate.c
+++ b/libavfilter/vf_mpdecimate.c
@@ -46,6 +46,9 @@ typedef struct DecimateContext {
int drop_count; ///< if positive: number of frames sequentially dropped
///< if negative: number of sequential frames which were not dropped
+ int max_keep_count; ///< number of similar frames to ignore before to start dropping them
+ int keep_count; ///< number of similar frames already ignored
+
int hsub, vsub; ///< chroma subsampling values
AVFrame *ref; ///< reference picture
av_pixelutils_sad_fn sad; ///< sum of absolute difference function
@@ -57,6 +60,8 @@ typedef struct DecimateContext {
static const AVOption mpdecimate_options[] = {
{ "max", "set the maximum number of consecutive dropped frames (positive), or the minimum interval between dropped frames (negative)",
OFFSET(max_drop_count), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS },
+ { "keep", "set the number of similar consecutive frames to be kept before starting to drop similar frames",
+ OFFSET(max_keep_count), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
{ "hi", "set high dropping threshold", OFFSET(hi), AV_OPT_TYPE_INT, {.i64=64*12}, INT_MIN, INT_MAX, FLAGS },
{ "lo", "set low dropping threshold", OFFSET(lo), AV_OPT_TYPE_INT, {.i64=64*5}, INT_MIN, INT_MAX, FLAGS },
{ "frac", "set fraction dropping threshold", OFFSET(frac), AV_OPT_TYPE_FLOAT, {.dbl=0.33}, 0, 1, FLAGS },
@@ -112,6 +117,12 @@ static int decimate_frame(AVFilterContext *ctx,
DecimateContext *decimate = ctx->priv;
int plane;
+ if (decimate->max_keep_count > 0 &&
+ decimate->keep_count > -1 &&
+ decimate->keep_count < decimate->max_keep_count) {
+ decimate->keep_count++;
+ return 0;
+ }
if (decimate->max_drop_count > 0 &&
decimate->drop_count >= decimate->max_drop_count)
return 0;
@@ -196,20 +207,24 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *cur)
if (decimate->ref && decimate_frame(inlink->dst, cur, decimate->ref)) {
decimate->drop_count = FFMAX(1, decimate->drop_count+1);
+ decimate->keep_count = -1; // do not keep any more frames until non-similar frames are detected
} else {
av_frame_free(&decimate->ref);
decimate->ref = cur;
decimate->drop_count = FFMIN(-1, decimate->drop_count-1);
+ if (decimate->keep_count < 0) // re-enable counting similiar frames to ignore before dropping
+ decimate->keep_count = 0;
if ((ret = ff_filter_frame(outlink, av_frame_clone(cur))) < 0)
return ret;
}
av_log(inlink->dst, AV_LOG_DEBUG,
- "%s pts:%s pts_time:%s drop_count:%d\n",
+ "%s pts:%s pts_time:%s drop_count:%d keep_count:%d\n",
decimate->drop_count > 0 ? "drop" : "keep",
av_ts2str(cur->pts), av_ts2timestr(cur->pts, &inlink->time_base),
- decimate->drop_count);
+ decimate->drop_count,
+ decimate->keep_count);
if (decimate->drop_count > 0)
av_frame_free(&cur);