[FFmpeg-devel] [PATCH] avfilter/vf_cropdetect: add ability to change limit/reset at runtime
Jeffrey CHAPUIS
ashyni1987 at gmail.com
Wed Dec 28 17:37:30 EET 2022
> You need a custom function that will keep old values around and
> realloc the buffers for bboxes using the new reset_count value passed
> as a runtime command, but one that will not call config_input() like
> you did the first time as that one does a lot more than what you need.
>
> It should also call init() to reset frame_nb, a value you of course
> also need to preserve for the fallback scenario, and allocate the new
> buffers but only replace them in the filter context if all four
> allocations succeeded, as doing av_realloc() could potentially not let
> you fallback to continue the process with the old values if required.
Here is my last attempt to do it myself, i don't want to waste
everyone's time, i barely understand what i code, without proper
knowledge in c/c++ and ffmpeg project.
diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c
index 7e985fb27..f4d2f1379 100644
--- a/libavfilter/vf_cropdetect.c
+++ b/libavfilter/vf_cropdetect.c
@@ -422,26 +422,65 @@ 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;
+ AVFilterLink *inlink = ctx->inputs[0];
+ int old_limit = s->limit;
+ int old_reset_count = s->reset_count;
+ int old_frame_nb = s->frame_nb;
+ int ret;
+
+ if ((ret = ff_filter_process_command(ctx, cmd, args, res, res_len,
flags)) < 0)
+ return ret;
+
+ init;
+
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+ const int bufsize = inlink->w * inlink->h;
+ av_image_fill_max_pixsteps(s->max_pixsteps, NULL, desc);
+ if (s->limit < 1.0)
+ s->limit *= (1 << desc->comp[0].depth) - 1;
+
+ s->window_size = FFMAX(s->reset_count, 15);
+ if ((ret = (av_realloc(s->filterbuf, bufsize * s->max_pixsteps[0])
+ || av_realloc(s->bboxes[0], s->window_size * sizeof(*s->bboxes[0]))
+ || av_realloc(s->bboxes[1], s->window_size * sizeof(*s->bboxes[1]))
+ || av_realloc(s->bboxes[2], s->window_size * sizeof(*s->bboxes[2]))
+ || av_realloc(s->bboxes[3], s->window_size *
sizeof(*s->bboxes[3])))) < 0) {
+ s->limit = old_limit;
+ s->reset_count = old_reset_count;
+ s->frame_nb = old_frame_nb;
+ }
+
+ 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 +520,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,
};
> Why are you adding frame pts as metadata? Or the detection parameters?
> Those are not detected, so have no business being there in metadata or
> log.
>
> Regards,
> Marton
It make sense for my lua script, https://github.com/Ashyni/mpv-scripts.
For pts, it's because mpv doesn't provide the frame/pts/pts_time data
alongside others tag field in the metadata, may be an issue should be
open for mpv to change that.
As for the parameters, It's added as a reference to be sure when i look
at the metadata that the result come from the new limit and not the
previous one, same for reset.
It's the only way i can be sure of the result without waiting an
arbitrary time between every change to limit/reset.
In the end, the goal is to analyzed data ahead with something like :
ffmpeg -i <input> -filter_complex
'split[a1][b1];[b1]setpts=PTS-2/TB,cropdetect at cd1=reset=1[b2];[b2][a1]overlay,setpts=PTS-2/TB,cropdetect at cd2=reset=1'
-f null -
with mpv : mp.set_property_native("lavfi-complex",
"[vid1]split[a_1][b_1];[b_1]setpts=PTS-2/TB,cropdetect at cd1=reset=1[b_2];[b_2][a_1]overlay,setpts=PTS-2/TB,cropdetect at cd2=reset=1[vo]")
but that another topic, and mpv have some issue anyway with vf-command
and graph/lavfi-complex.
Reminder, that was an attempt for https://trac.ffmpeg.org/ticket/9851,
if someone wants to take over.
Thanks for your time everyone.
More information about the ffmpeg-devel
mailing list