From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id B84DA4B0C0 for ; Tue, 28 May 2024 07:51:43 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 57B8A68D4FD; Tue, 28 May 2024 10:51:40 +0300 (EEST) Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id AB8C568BA2D for ; Tue, 28 May 2024 10:51:33 +0300 (EEST) Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-3579ef2d436so41369f8f.2 for ; Tue, 28 May 2024 00:51:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1716882693; x=1717487493; darn=ffmpeg.org; h=thread-index:content-language:content-transfer-encoding :mime-version:message-id:date:subject:in-reply-to:references:to:from :from:to:cc:subject:date:message-id:reply-to; bh=sxfu0OojwxaQIGmZqCK9RDBMp15qQwJvqZ6HiNZuKU8=; b=NVPzoBMGbfyDspJVOjF8xPUplI+vhZHqPDU9f8AUQwgxtlrWdsy/H9X/g3uo/q5dlO Rk/NsWV4P++5q3NQuEomnkN22t0vE1H+1pyO0QX0dDt/+Ht5AcDL9QECXVo+FpvlLxQc nCzgtV2GE3ClaZeREDqbfQJKNynrragdYqdx97D9glmYUwfIGvYC+yeHkez4UsPoyWcb 60v2ygGZ4y/1UEvAWLuz0Rr0tq6iz0VvFl8WircMHDsMQJG8CDOSCTaShZDNuPOY/dRG pN0NavJdwbUX9TmMP6aMkIkCtAyKcXxI/B88wT5iMEwcaaTFfWS/4t++Pv9KjHQ8X/PO ybXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716882693; x=1717487493; h=thread-index:content-language:content-transfer-encoding :mime-version:message-id:date:subject:in-reply-to:references:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=sxfu0OojwxaQIGmZqCK9RDBMp15qQwJvqZ6HiNZuKU8=; b=NBKAkkb0gm3Jv+mnwdv0lH4wKBM+2EmWyCIoYyDHU8pYIY7wA9yqjyoOJEBDJBAJwf 26RqwVk/MtL6BwJJ85zA6PW0KwLI5cXxNh56s/+7MFu0EkUiIWT7iv3zjbOIItmqbt7t GKAhxJf6asnz2y1qJQ65OYn8vY/6Ed1j8Gyv4Bcu1U8S5BeZwep8fu79ci4zNP2PHsSX lD8ro4oHeG6fCH9pOlLDDnwUrfDbXnYdikTp4uaBKIJjuWThWckn6qfq8pHD4UBkwl31 P/g5fzJSDYIPwP9E0RCoSqeFhsnxBOonBhe1zYNS0Fz1aE1URatDDeslnC2jMV7RLatv fKDw== X-Gm-Message-State: AOJu0YxQcPQxRtVoTZ/F3UU4eyo3q6C0PW+cF9lLba+zExDCi7smLRhQ arxnam7tDEFyeTT5fD0HzD7P6Zaml13B1BtthiMcRMKSExABukyMZuO5PA== X-Google-Smtp-Source: AGHT+IF4txc0thnW7yUxfyBpenC9B/aMBl03kHHy0jOJNuSII+HwM3uRsj4xF+vW/eXsjlQXHduRcA== X-Received: by 2002:a5d:5001:0:b0:354:fc97:e6e3 with SMTP id ffacd0b85a97d-3552fdf8cf8mr7584199f8f.5.1716882692706; Tue, 28 May 2024 00:51:32 -0700 (PDT) Received: from Mishu ([2a02:2f0f:8201:b100:25f9:b765:8fd4:117f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-35586a15f56sm10959131f8f.109.2024.05.28.00.51.31 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 May 2024 00:51:32 -0700 (PDT) From: To: References: <000c01daa54d$8a0eedf0$9e2cc9d0$@gmail.com> <000801daaa06$5d20fe60$1762fb20$@gmail.com> In-Reply-To: <000801daaa06$5d20fe60$1762fb20$@gmail.com> Date: Tue, 28 May 2024 10:51:31 +0300 Message-ID: <005b01dab0d3$db849c20$928dd460$@gmail.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Content-Language: ro Thread-Index: AQF53sdsVM9iibY6Rm6BSu+PKGSxTgIJ9Ts/sl2aMvA= Subject: Re: [FFmpeg-devel] [PATCH] area changed: scdet filter X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Type: text/plain; charset="iso-8859-2" Content-Transfer-Encoding: quoted-printable Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: > -----Original Message----- > From: radu.taraibuta@gmail.com > Sent: duminic=E3, 19 mai 2024 19:05 > To: ffmpeg-devel@ffmpeg.org > Subject: RE: [PATCH] area changed: scdet filter > = > = > > -----Original Message----- > > From: radu.taraibuta@gmail.com > > Sent: luni, 13 mai 2024 18:52 > > To: ffmpeg-devel@ffmpeg.org > > Subject: [PATCH] area changed: scdet filter > > > > Previous observations: > > > > - Inconsistent code style with other filters. (Mostly using > > AVFilterLink* link instead of AVFilterLink *link). > > I hope it's fine now. > > > > - Unrelated changes, please split trivial unrelated changes into > > separate patches. > > Removed trivial changes from this patch. > > > > - Can't tables be generated at .init/.config_props time? No point in > > storing them into binary. > > Done. > > > > - Adding extra delay is not backward compatible change, it should be > > implemented properly by adding option for users to select mode: next & > prev > > frame or just next or prev frame. > > Added legacy option to the mode parameter. > > > > - Could split frame clone change into earlier separate patch. > > Cannot be done. It's either frame clone or 1 frame delay. > > > > - Where are results of improvements with accuracy so it can be confirmed? > > Here are my test results with manual labeling of scene changes: > > 2379 Full length movie > > > > Method Threshold TP FP FN Precision > > Recall F > > Cubic 7 2357 423 22 0.847841727 0.990752417 > > 0.913742973 > > Cubic 10 2297 200 82 0.919903885 0.965531736 > > 0.94216571 > > Cubic 12 2217 146 162 0.938214135 0.931904161 > > 0.935048503 > > Cubic 15 2049 101 330 0.953023256 0.861286255 > > 0.904835505 > > Linear 2.8 2357 1060 22 0.689786362 > 0.990752417 > > 0.813319531 > > Linear 8 2099 236 280 0.898929336 > 0.882303489 > > 0.890538821 > > Linear 10 1886 173 493 0.91597863 > 0.792770071 > > 0.849932402 > > Legacy 5 2235 1260 144 0.639484979 > 0.939470366 > > 0.760980592 > > Legacy 8 1998 414 381 0.828358209 > 0.839848676 > > 0.83406387 > > Legacy 10 1743 193 636 0.900309917 > 0.732660782 > > 0.80787949 > > > > 15 HDR10Plus_PB_EAC3JOC > > https://mega.nz/file/nehDka6Z#C5_OPbSZkONdOp1jRmc09C9- > > viDc3zMj8ZHruHcWKyA > > > > Method Threshold TP FP FN Precision > > Recall F > > Cubic 10 15 0 0 1 1 1 > > Linear 5 13 1 2 0.928571429 > 0.866666667 > > 0.896551724 > > Legacy 5 12 2 3 0.857142857 0.8 > > 0.827586207 > > > > 21 (HDR HEVC 10-bit BT.2020 24fps) Exodus Sample > > > https://mega.nz/file/Sfw1hDpK#ErxCOpQDVjcI1gq6ZbX3vIfdtXZompkFe0jq47E > > hR2o > > > > Method Threshold TP FP FN Precision > > Recall F > > Cubic 10 21 0 0 1 1 1 > > Linear 4 20 0 1 1 0.952380952 > > 0.975609756 > > Legacy 4 19 0 2 1 0.904761905 > 0.95 > > > > 94 Bieber Grammys > > https://mega.nz/#!c9dhAaKA!MG5Yi- > > MJNATE2_KqcnNJZCRKtTWvdjJP1NwG8Ggdw3E > > > > Method Threshold TP FP FN Precision > > Recall F > > Cubic 15 91 23 3 0.798245614 0.968085106 > > 0.875 > > Cubic 18 85 9 9 0.904255319 0.904255319 > > 0.904255319 > > Linear 7 79 49 15 0.6171875 > 0.840425532 > > 0.711711712 > > Linear 8 74 28 20 0.725490196 > 0.787234043 > > 0.755102041 > > Legacy 7 74 40 20 0.649122807 > 0.787234043 > > 0.711538462 > > Legacy 8 71 26 23 0.731958763 > 0.755319149 > > 0.743455497 > > > > > > Improve scene detection accuracy by comparing frame with both previous > > and next frame (creates one frame delay). > > Add new mode parameter and new method to compute the frame difference > > using cubic square to increase the weight of small changes and new > > mean formula. > > This improves accuracy significantly. Slightly improve performance by > > not using frame clone. > > Add legacy mode for backward compatibility. > > > > Signed-off-by: raduct > > --- > > doc/filters.texi | 16 ++++ > > libavfilter/scene_sad.c | 151 ++++++++++++++++++++++++++++++++++ > > libavfilter/scene_sad.h | 6 ++ > > libavfilter/vf_scdet.c | 156 +++++++++++++++++++++++++----------- > > tests/fate/filter-video.mak | 3 + > > 5 files changed, 284 insertions(+), 48 deletions(-) > > > > diff --git a/doc/filters.texi b/doc/filters.texi index > > bfa8ccec8b..53814e003b 100644 > > --- a/doc/filters.texi > > +++ b/doc/filters.texi > > @@ -21797,6 +21797,22 @@ Default value is @code{10.}. > > @item sc_pass, s > > Set the flag to pass scene change frames to the next filter. Default > value > > is @code{0} > > You can enable it if you want to get snapshot of scene change frames > only. > > + > > +@item mode > > +Set the scene change detection method. Default value is @code{-1} > > +Available values are: > > + > > +@table @samp > > +@item -1 > > +Legacy mode for sum of absolute linear differences. Compare frame > > +with > > previous only and no delay. > > + > > +@item 0 > > +Sum of absolute linear differences. Compare frame with both previous > > +and > > next which introduces a 1 frame delay. > > + > > +@item 1 > > +Sum of mean of cubic root differences. Compare frame with both > > +previous > > and > > next which introduces a 1 frame delay. > > + > > +@end table > > @end table > > > > @anchor{selectivecolor} > > diff --git a/libavfilter/scene_sad.c b/libavfilter/scene_sad.c index > > caf911eb5d..9b80d426bc 100644 > > --- a/libavfilter/scene_sad.c > > +++ b/libavfilter/scene_sad.c > > @@ -21,6 +21,7 @@ > > * Scene SAD functions > > */ > > > > +#include "libavutil/thread.h" > > #include "scene_sad.h" > > > > void ff_scene_sad16_c(SCENE_SAD_PARAMS) > > @@ -71,3 +72,153 @@ ff_scene_sad_fn ff_scene_sad_get_fn(int depth) > > return sad; > > } > > > > +static AVMutex cbrt_mutex =3D AV_MUTEX_INITIALIZER; static uint8_t > > +*cbrt_table[16] =3D { NULL }; static int cbrt_table_ref[16] =3D { 0 }; > > + > > +int ff_init_cbrt(int bitdepth) > > +{ > > + if (bitdepth < 4 || bitdepth > 16) > > + return AVERROR(EINVAL); > > + > > + ff_mutex_lock(&cbrt_mutex); > > + > > + uint8_t *table =3D cbrt_table[bitdepth]; > > + if (table) { > > + cbrt_table_ref[bitdepth]++; > > + goto end; > > + } > > + > > + table =3D av_malloc((1 << bitdepth) * (bitdepth > 8 ? 2 : 1)); > > + if (!table) > > + goto end; > > + cbrt_table[bitdepth] =3D table; > > + cbrt_table_ref[bitdepth] =3D 1; > > + > > + int size =3D 1 << bitdepth; > > + double factor =3D pow(size - 1, 2. / 3.); > > + if (bitdepth <=3D 8) { > > + for (int i =3D 0; i < size; i++) > > + table[i] =3D round(factor * pow(i, 1. / 3.)); > > + } else { > > + uint16_t *tablew =3D (uint16_t*)table; > > + for (int i =3D 0; i < size; i++) > > + tablew[i] =3D round(factor * pow(i, 1. / 3.)); > > + } > > + > > +end: > > + ff_mutex_unlock(&cbrt_mutex); > > + return table !=3D NULL; > > +} > > + > > +void ff_uninit_cbrt(int bitdepth) > > +{ > > + if (bitdepth < 4 || bitdepth > 16) > > + return; > > + ff_mutex_lock(&cbrt_mutex); > > + if (!--cbrt_table_ref[bitdepth]) { > > + av_free(cbrt_table[bitdepth]); > > + cbrt_table[bitdepth] =3D NULL; > > + } > > + ff_mutex_unlock(&cbrt_mutex); > > +} > > + > > +void ff_scene_scrd_c(SCENE_SAD_PARAMS) { > > + uint64_t scrdPlus =3D 0; > > + uint64_t scrdMinus =3D 0; > > + int x, y; > > + > > + uint8_t *table =3D cbrt_table[8]; > > + if (!table) { > > + *sum =3D 0; > > + return; > > + } > > + > > + for (y =3D 0; y < height; y++) { > > + for (x =3D 0; x < width; x++) > > + if (src1[x] > src2[x]) > > + scrdMinus +=3D table[src1[x] - src2[x]]; > > + else > > + scrdPlus +=3D table[src2[x] - src1[x]]; > > + src1 +=3D stride1; > > + src2 +=3D stride2; > > + } > > + > > + double mean =3D (sqrt(scrdPlus) + sqrt(scrdMinus)) / 2.0; > > + *sum =3D 2.0 * mean * mean; > > +} > > + > > +void ff_scene_scrd2B_c(SCENE_SAD_PARAMS, int bitdepth) { > > + uint64_t scrdPlus =3D 0; > > + uint64_t scrdMinus =3D 0; > > + const uint16_t *src1w =3D (const uint16_t*)src1; > > + const uint16_t *src2w =3D (const uint16_t*)src2; > > + int x, y; > > + > > + uint16_t *table =3D (uint16_t*)cbrt_table[bitdepth]; > > + if (!table) { > > + *sum =3D 0; > > + return; > > + } > > + > > + stride1 /=3D 2; > > + stride2 /=3D 2; > > + > > + for (y =3D 0; y < height; y++) { > > + for (x =3D 0; x < width; x++) > > + if (src1w[x] > src2w[x]) > > + scrdMinus +=3D table[src1w[x] - src2w[x]]; > > + else > > + scrdPlus +=3D table[src2w[x] - src1w[x]]; > > + src1w +=3D stride1; > > + src2w +=3D stride2; > > + } > > + > > + double mean =3D (sqrt(scrdPlus) + sqrt(scrdMinus)) / 2.0; > > + *sum =3D 2.0 * mean * mean; > > +} > > + > > +void ff_scene_scrd9_c(SCENE_SAD_PARAMS) > > +{ > > + ff_scene_scrd2B_c(src1, stride1, src2, stride2, width, height, > > +sum, > 9); > > +} > > + > > +void ff_scene_scrd10_c(SCENE_SAD_PARAMS) > > +{ > > + ff_scene_scrd2B_c(src1, stride1, src2, stride2, width, height, > > +sum, > > 10); > > +} > > + > > +void ff_scene_scrd12_c(SCENE_SAD_PARAMS) > > +{ > > + ff_scene_scrd2B_c(src1, stride1, src2, stride2, width, height, > > +sum, > > 12); > > +} > > + > > +void ff_scene_scrd14_c(SCENE_SAD_PARAMS) > > +{ > > + ff_scene_scrd2B_c(src1, stride1, src2, stride2, width, height, > > +sum, > > 14); > > +} > > + > > +void ff_scene_scrd16_c(SCENE_SAD_PARAMS) > > +{ > > + ff_scene_scrd2B_c(src1, stride1, src2, stride2, width, height, > > +sum, > > 16); > > +} > > + > > +ff_scene_sad_fn ff_scene_scrd_get_fn(int depth) { > > + ff_scene_sad_fn scrd =3D NULL; > > + if (depth =3D=3D 8) > > + scrd =3D ff_scene_scrd_c; > > + else if (depth =3D=3D 9) > > + scrd =3D ff_scene_scrd9_c; > > + else if (depth =3D=3D 10) > > + scrd =3D ff_scene_scrd10_c; > > + else if (depth =3D=3D 12) > > + scrd =3D ff_scene_scrd12_c; > > + else if (depth =3D=3D 14) > > + scrd =3D ff_scene_scrd14_c; > > + else if (depth =3D=3D 16) > > + scrd =3D ff_scene_scrd16_c; > > + return scrd; > > +} > > diff --git a/libavfilter/scene_sad.h b/libavfilter/scene_sad.h index > > 173a051f2b..c294bd90f9 100644 > > --- a/libavfilter/scene_sad.h > > +++ b/libavfilter/scene_sad.h > > @@ -41,4 +41,10 @@ ff_scene_sad_fn ff_scene_sad_get_fn_x86(int depth); > > > > ff_scene_sad_fn ff_scene_sad_get_fn(int depth); > > > > +ff_scene_sad_fn ff_scene_scrd_get_fn(int depth); > > + > > +int ff_init_cbrt(int bitdepth); > > + > > +void ff_uninit_cbrt(int bitdepth); > > + > > #endif /* AVFILTER_SCENE_SAD_H */ > > diff --git a/libavfilter/vf_scdet.c b/libavfilter/vf_scdet.c index > > 15399cfebf..93da5837b3 100644 > > --- a/libavfilter/vf_scdet.c > > +++ b/libavfilter/vf_scdet.c > > @@ -31,6 +31,18 @@ > > #include "scene_sad.h" > > #include "video.h" > > > > +enum SCDETMode { > > + MODE_LEGACY =3D -1, > > + MODE_LINEAR =3D 0, > > + MODE_MEAN_CBRT =3D 1 > > +}; > > + > > +typedef struct SCDETFrameInfo { > > + AVFrame *picref; > > + double mafd; > > + double diff; > > +} SCDETFrameInfo; > > + > > typedef struct SCDetContext { > > const AVClass *class; > > > > @@ -39,11 +51,12 @@ typedef struct SCDetContext { > > int nb_planes; > > int bitdepth; > > ff_scene_sad_fn sad; > > - double prev_mafd; > > - double scene_score; > > - AVFrame *prev_picref; > > + SCDETFrameInfo curr_frame; > > + SCDETFrameInfo prev_frame; > > + > > double threshold; > > int sc_pass; > > + enum SCDETMode mode; > > } SCDetContext; > > > > #define OFFSET(x) offsetof(SCDetContext, x) @@ -55,6 +68,7 @@ static > > const AVOption scdet_options[] =3D { > > { "t", "set scene change detect threshold", > > OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl =3D 10.}, 0, 100., V|F > }, > > { "sc_pass", "Set the flag to pass scene change frames", > > OFFSET(sc_pass), AV_OPT_TYPE_BOOL, {.dbl =3D 0 }, 0, 1, V|F > }, > > { "s", "Set the flag to pass scene change frames", > > OFFSET(sc_pass), AV_OPT_TYPE_BOOL, {.dbl =3D 0 }, 0, 1, V|F > }, > > + { "mode", "scene change detection method", > > OFFSET(mode), AV_OPT_TYPE_INT, {.i64 =3D MODE_LEGACY}, > > MODE_LEGACY, > > MODE_MEAN_CBRT, V|F }, > > {NULL} > > }; > > > > @@ -91,7 +105,14 @@ static int config_input(AVFilterLink *inlink) > > s->height[plane] =3D inlink->h >> ((plane =3D=3D 1 || plane = =3D=3D 2) ? > > desc->log2_chroma_h : 0); > > } > > > > - s->sad =3D ff_scene_sad_get_fn(s->bitdepth =3D=3D 8 ? 8 : 16); > > + if (s->mode =3D=3D MODE_LINEAR || s->mode =3D=3D MODE_LEGACY) > > + s->sad =3D ff_scene_sad_get_fn(s->bitdepth =3D=3D 8 ? 8 : 16); > > + else if (s->mode =3D=3D MODE_MEAN_CBRT) { > > + int ret =3D ff_init_cbrt(s->bitdepth); > > + if (ret < 0) > > + return ret; > > + s->sad =3D ff_scene_scrd_get_fn(s->bitdepth); > > + } > > if (!s->sad) > > return AVERROR(EINVAL); > > > > @@ -101,46 +122,97 @@ static int config_input(AVFilterLink *inlink) > > static av_cold void uninit(AVFilterContext *ctx) { > > SCDetContext *s =3D ctx->priv; > > - > > - av_frame_free(&s->prev_picref); > > + if (s->mode =3D=3D MODE_LEGACY) > > + av_frame_free(&s->prev_frame.picref); > > + if (s->mode =3D=3D MODE_MEAN_CBRT) > > + ff_uninit_cbrt(s->bitdepth); > > } > > > > -static double get_scene_score(AVFilterContext *ctx, AVFrame *frame) > > +static void compute_diff(AVFilterContext *ctx) > > { > > - double ret =3D 0; > > SCDetContext *s =3D ctx->priv; > > - AVFrame *prev_picref =3D s->prev_picref; > > + AVFrame *prev_picref =3D s->prev_frame.picref; > > + AVFrame *curr_picref =3D s->curr_frame.picref; > > > > - if (prev_picref && frame->height =3D=3D prev_picref->height > > - && frame->width =3D=3D prev_picref->width) { > > - uint64_t sad =3D 0; > > - double mafd, diff; > > - uint64_t count =3D 0; > > + if (prev_picref && curr_picref > > + && curr_picref->height =3D=3D prev_picref->height > > + && curr_picref->width =3D=3D prev_picref->width) { > > > > + uint64_t sum =3D 0; > > + uint64_t count =3D 0; > > for (int plane =3D 0; plane < s->nb_planes; plane++) { > > - uint64_t plane_sad; > > + uint64_t plane_sum; > > s->sad(prev_picref->data[plane], > prev_picref->linesize[plane], > > - frame->data[plane], frame->linesize[plane], > > - s->width[plane], s->height[plane], &plane_sad); > > - sad +=3D plane_sad; > > + curr_picref->data[plane], > curr_picref->linesize[plane], > > + s->width[plane], s->height[plane], &plane_sum); > > + sum +=3D plane_sum; > > count +=3D s->width[plane] * s->height[plane]; > > } > > > > - mafd =3D (double)sad * 100. / count / (1ULL << s->bitdepth); > > - diff =3D fabs(mafd - s->prev_mafd); > > - ret =3D av_clipf(FFMIN(mafd, diff), 0, 100.); > > - s->prev_mafd =3D mafd; > > - av_frame_free(&prev_picref); > > + s->curr_frame.mafd =3D (double)sum * 100. / count / (1ULL << > > s->bitdepth); > > + if (s->mode =3D=3D MODE_LEGACY) > > + s->curr_frame.diff =3D fabs(s->curr_frame.mafd - > > s->prev_frame.mafd); > > + else > > + s->curr_frame.diff =3D s->curr_frame.mafd - s->prev_frame.mafd; > > + } else { > > + s->curr_frame.mafd =3D 0; > > + s->curr_frame.diff =3D 0; > > } > > - s->prev_picref =3D av_frame_clone(frame); > > - return ret; > > } > > > > -static int set_meta(SCDetContext *s, AVFrame *frame, const char *key, > const > > char *value) > > +static int set_meta(AVFrame *frame, const char *key, const char > > +*value) > > { > > return av_dict_set(&frame->metadata, key, value, 0); } > > > > +static int filter_frame(AVFilterContext *ctx, AVFrame *frame) { > > + AVFilterLink *inlink =3D ctx->inputs[0]; > > + AVFilterLink *outlink =3D ctx->outputs[0]; > > + SCDetContext *s =3D ctx->priv; > > + > > + s->prev_frame =3D s->curr_frame; > > + s->curr_frame.picref =3D frame; > > + > > + if ((s->mode !=3D MODE_LEGACY && s->prev_frame.picref) || (s->mode > > + =3D=3D > > MODE_LEGACY && frame !=3D NULL)) { > > + compute_diff(ctx); > > + > > + if (s->mode =3D=3D MODE_LEGACY) { > > + av_frame_free(&s->prev_frame.picref); > > + s->prev_frame =3D s->curr_frame; > > + s->curr_frame.picref =3D av_frame_clone(s->curr_frame.picref); > > + } else if (s->prev_frame.diff < -s->curr_frame.diff) { > > + s->prev_frame.diff =3D -s->curr_frame.diff; > > + s->prev_frame.mafd =3D s->curr_frame.mafd; > > + } > > + double scene_score =3D av_clipf(s->mode =3D=3D MODE_LEGACY ? > > FFMIN(s->prev_frame.mafd, s->prev_frame.diff) : > > FFMAX(s->prev_frame.diff, 0), 0, 100.); > > + > > + char buf[64]; > > + snprintf(buf, sizeof(buf), "%0.3f", s->prev_frame.mafd); > > + set_meta(s->prev_frame.picref, "lavfi.scd.mafd", buf); > > + snprintf(buf, sizeof(buf), "%0.3f", scene_score); > > + set_meta(s->prev_frame.picref, "lavfi.scd.score", buf); > > + > > + if (scene_score >=3D s->threshold) { > > + av_log(s, AV_LOG_INFO, "lavfi.scd.score: %.3f, > lavfi.scd.time: > > %s\n", > > + scene_score, av_ts2timestr(s->prev_frame.picref->pts, > > &inlink->time_base)); > > + set_meta(s->prev_frame.picref, "lavfi.scd.time", > > + av_ts2timestr(s->prev_frame.picref->pts, > > &inlink->time_base)); > > + } > > + > > + if (s->sc_pass) { > > + if (scene_score >=3D s->threshold) > > + return ff_filter_frame(outlink, s->prev_frame.picref); > > + else > > + av_frame_free(&s->prev_frame.picref); > > + } > > + else > > + return ff_filter_frame(outlink, s->prev_frame.picref); > > + } > > + > > + return 0; > > +} > > + > > static int activate(AVFilterContext *ctx) { > > int ret; > > @@ -148,6 +220,8 @@ static int activate(AVFilterContext *ctx) > > AVFilterLink *outlink =3D ctx->outputs[0]; > > SCDetContext *s =3D ctx->priv; > > AVFrame *frame; > > + int64_t pts; > > + int status; > > > > FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); > > > > @@ -155,31 +229,17 @@ static int activate(AVFilterContext *ctx) > > if (ret < 0) > > return ret; > > > > - if (frame) { > > - char buf[64]; > > - s->scene_score =3D get_scene_score(ctx, frame); > > - snprintf(buf, sizeof(buf), "%0.3f", s->prev_mafd); > > - set_meta(s, frame, "lavfi.scd.mafd", buf); > > - snprintf(buf, sizeof(buf), "%0.3f", s->scene_score); > > - set_meta(s, frame, "lavfi.scd.score", buf); > > + if (ret > 0) > > + return filter_frame(ctx, frame); > > > > - if (s->scene_score >=3D s->threshold) { > > - av_log(s, AV_LOG_INFO, "lavfi.scd.score: %.3f, > lavfi.scd.time: > > %s\n", > > - s->scene_score, av_ts2timestr(frame->pts, > > &inlink->time_base)); > > - set_meta(s, frame, "lavfi.scd.time", > > - av_ts2timestr(frame->pts, &inlink->time_base)); > > - } > > - if (s->sc_pass) { > > - if (s->scene_score >=3D s->threshold) > > - return ff_filter_frame(outlink, frame); > > - else { > > - av_frame_free(&frame); > > - } > > - } else > > - return ff_filter_frame(outlink, frame); > > + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { > > + if (status =3D=3D AVERROR_EOF) > > + ret =3D filter_frame(ctx, NULL); > > + > > + ff_outlink_set_status(outlink, status, pts); > > + return ret; > > } > > > > - FF_FILTER_FORWARD_STATUS(inlink, outlink); > > FF_FILTER_FORWARD_WANTED(outlink, inlink); > > > > return FFERROR_NOT_READY; > > diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak > > index ee9f0f5e40..cff48e33d9 100644 > > --- a/tests/fate/filter-video.mak > > +++ b/tests/fate/filter-video.mak > > @@ -672,6 +672,9 @@ SCDET_DEPS =3D LAVFI_INDEV FILE_PROTOCOL > > MOVIE_FILTER SCDET_FILTER SCALE_FILTER \ FATE_METADATA_FILTER-$(call > > ALLYES, $(SCDET_DEPS)) +=3D fate-filter-metadata-scdet > > fate-filter-metadata-scdet: SRC =3D > > $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov > > fate-filter-metadata-scdet: CMD =3D run $(FILTER_METADATA_COMMAND) > > "sws_flags=3D+accurate_rnd+bitexact;movie=3D'$(SRC)',scdet=3Ds=3D1" > > +FATE_METADATA_FILTER-$(call ALLYES, $(SCDET_DEPS)) +=3D > > fate-filter-metadata-scdet1 > > +fate-filter-metadata-scdet1: SRC =3D > > $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov > > +fate-filter-metadata-scdet1: CMD =3D run $(FILTER_METADATA_COMMAND) > > "sws_flags=3D+accurate_rnd+bitexact;movie=3D'$(SRC)',scdet=3Ds=3D1:t=3D= 6.5:mode=3D1" > > > > CROPDETECT_DEPS =3D LAVFI_INDEV FILE_PROTOCOL MOVIE_FILTER > MOVIE_FILTER > > MESTIMATE_FILTER CROPDETECT_FILTER \ > > SCALE_FILTER MOV_DEMUXER H264_DECODER > > -- > > 2.43.0.windows.1 > > > = > So what's next? Is there anything else I should do? > = Anybody? _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".