On 12/27/2022 8:46 AM, Jeffrey CHAPUIS wrote:
Hello, first attempt to contribute.

Related to https://trac.ffmpeg.org/ticket/9851.

Tested with ffmpeg and mpv, amazing results.

Signed-off-by: Ashyni <jeffre...@tuta.io>
---
  doc/filters.texi                           | 13 +++++
  libavfilter/vf_cropdetect.c                | 42 +++++++++++++--
  tests/ref/fate/filter-metadata-cropdetect  | 60 +++++++++++-----------
  tests/ref/fate/filter-metadata-cropdetect1 | 14 ++---
  tests/ref/fate/filter-metadata-cropdetect2 | 14 ++---
  5 files changed, 94 insertions(+), 49 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index ceab0ea0f..bbb778368 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -10552,6 +10552,19 @@ ffmpeg -flags2 +export_mvs -i file.mp4 -vf cropdetect=mode=mvedges,metadata=mode
  @end example
  @end itemize
  +@subsection Commands
+
+This filter supports the following commands:
+@table @option
+@item limit
+@item reset, reset_count
+
+The command accepts the same syntax of the corresponding option.
+
+If the specified expression is not valid, it is kept at its current
+value.
+@end table
+
  @anchor{cue}
  @section cue
  diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c
index 7e985fb27..fda803651 100644
--- a/libavfilter/vf_cropdetect.c
+++ b/libavfilter/vf_cropdetect.c
@@ -422,26 +422,57 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
          SET_META("lavfi.cropdetect.h",  h);
          SET_META("lavfi.cropdetect.x",  x);
          SET_META("lavfi.cropdetect.y",  y);
+        SET_META("lavfi.cropdetect.pts", frame->pts);
+        SET_META("lavfi.cropdetect.limit", limit);
+        SET_META("lavfi.cropdetect.reset", s->reset_count);
           av_log(ctx, AV_LOG_INFO,
-               "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pts:%"PRId64" t:%f crop=%d:%d:%d:%d\n", +               "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pts:%"PRId64" t:%f limit:%d crop=%d:%d:%d:%d\n",
                 s->x1, s->x2, s->y1, s->y2, w, h, x, y, frame->pts,
                frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base),
-               w, h, x, y);
+               limit, w, h, x, y);
      }
       return ff_filter_frame(inlink->dst->outputs[0], frame);
  }
 +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
+                           char *res, int res_len, int flags)
+{
+    CropDetectContext *s = ctx->priv;
+    int ret;
+
+    if (!strcmp(cmd, "limit") || !strcmp(cmd, "reset") || !strcmp(cmd, "reset_count")) {

You could just call ff_filter_process_command() instead of hardcoding supported commands here. It will ignore any option without the AV_OPT_FLAG_RUNTIME_PARAM flag.

+
+        int old_limit = s->limit;
+        int old_reset_count = s->reset_count;
+
+        AVFilterLink *inlink = ctx->inputs[0];
+
+        av_opt_set(s, cmd, args, 0);
+
+        if ((ret = config_input(inlink)) < 0) {

This is going to generate memleaks, and needlessly reallocate unrelated buffers. You should instead av_realloc all four s->bboxes buffers here, and reset s->limit.

+            s->limit = old_limit;
+            s->reset_count = old_reset_count;
+            return ret;
+        }
+    }
+    else
+        ret = AVERROR(ENOSYS);
+
+    return ret;
+}
+
  #define OFFSET(x) offsetof(CropDetectContext, x)
  #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_RUNTIME_PARAM
   static const AVOption cropdetect_options[] = {
-    { "limit", "Threshold below which the pixel is considered black", OFFSET(limit),       AV_OPT_TYPE_FLOAT, { .dbl = 24.0/255 }, 0, 65535, FLAGS }, +    { "limit", "Threshold below which the pixel is considered black", OFFSET(limit),       AV_OPT_TYPE_FLOAT, { .dbl = 24.0/255 }, 0, 65535, TFLAGS },      { "round", "Value by which the width/height should be divisible", OFFSET(round),       AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX, FLAGS }, -    { "reset", "Recalculate the crop area after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, { .i64 = 0 },  0, INT_MAX, FLAGS }, +    { "reset", "Recalculate the crop area after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, { .i64 = 0 },  0, INT_MAX, TFLAGS },      { "skip",  "Number of initial frames to skip", OFFSET(skip),        AV_OPT_TYPE_INT, { .i64 = 2 },  0, INT_MAX, FLAGS }, -    { "reset_count", "Recalculate the crop area after this many frames",OFFSET(reset_count),AV_OPT_TYPE_INT,{ .i64 = 0 },  0, INT_MAX, FLAGS }, +    { "reset_count", "Recalculate the crop area after this many frames",OFFSET(reset_count),AV_OPT_TYPE_INT,{ .i64 = 0 },  0, INT_MAX, TFLAGS },      { "max_outliers", "Threshold count of outliers", OFFSET(max_outliers),AV_OPT_TYPE_INT, { .i64 = 0 },  0, INT_MAX, FLAGS },      { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_BLACK}, 0, MODE_NB-1, FLAGS, "mode" },          { "black",    "detect black pixels surrounding the video", 0, AV_OPT_TYPE_CONST, {.i64=MODE_BLACK},    INT_MIN, INT_MAX, FLAGS, "mode" },
@@ -481,4 +512,5 @@ const AVFilter ff_vf_cropdetect = {
      FILTER_OUTPUTS(avfilter_vf_cropdetect_outputs),
      FILTER_PIXFMTS_ARRAY(pix_fmts),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY,
+    .process_command = process_command,
  };
_______________________________________________
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