This allows for decimating large similar portions of a video while preserving 
small ones.
---
 doc/filters.texi            |  7 +++++++
 libavfilter/version.h       |  2 +-
 libavfilter/vf_mpdecimate.c | 19 +++++++++++++++++--
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 9a0fe9c0a1..d3f6f20014 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -17646,6 +17646,13 @@ number of previous sequentially dropped frames.
 
 Default value is 0.
 
+@item keep
+Set the maximum number of consecutive similar frames to ignore before to start 
dropping them.
+If the value is 0, the frame is dropped disregarding the
+number of previous sequentially similar frames.
+
+Default value is 0.
+
 @item hi
 @item lo
 @item frac
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 0050874108..4dc176dc55 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 100
+#define LIBAVFILTER_VERSION_MICRO 101
 
 
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
diff --git a/libavfilter/vf_mpdecimate.c b/libavfilter/vf_mpdecimate.c
index 71f673cb64..d1e046fc32 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}, INT_MIN, 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);
-- 
2.37.1 (Apple Git-137.1)

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to