diff mbox series

[FFmpeg-devel,1/2] avfilter/vf_blackdetect: support full-range YUV

Message ID 20221209002806.22424-1-ffmpeg@haasn.xyz
State Accepted
Commit 8e2f61ef0467a4b9cf564ca18ebe2c493b80a676
Headers show
Series [FFmpeg-devel,1/2] avfilter/vf_blackdetect: support full-range YUV | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Niklas Haas Dec. 9, 2022, 12:28 a.m. UTC
From: Niklas Haas <git@haasn.dev>

This filter currently makes the distinction between limited and full
range by testing for the deprecated YUVJ pixel formats at link setup
time. This is deprecated and should be improved to perform the detection
based on the per-frame metadata.

Rewrite it to calculate the black pixel threshold at the time of
filtering a frame, when metadata about the frame's color range is known.
Doing it this way has the small side benefit of being able to handle
streams with variable metadata, and is not a meaningful performance
cost.

Signed-off-by: Niklas Haas <git@haasn.dev>
---
 libavfilter/vf_blackdetect.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

Comments

Niklas Haas Dec. 12, 2022, 2:12 p.m. UTC | #1
Any objections to these two patches?

On Fri, 09 Dec 2022 01:28:05 +0100 Niklas Haas <ffmpeg@haasn.xyz> wrote:
> From: Niklas Haas <git@haasn.dev>
> 
> This filter currently makes the distinction between limited and full
> range by testing for the deprecated YUVJ pixel formats at link setup
> time. This is deprecated and should be improved to perform the detection
> based on the per-frame metadata.
> 
> Rewrite it to calculate the black pixel threshold at the time of
> filtering a frame, when metadata about the frame's color range is known.
> Doing it this way has the small side benefit of being able to handle
> streams with variable metadata, and is not a meaningful performance
> cost.
> 
> Signed-off-by: Niklas Haas <git@haasn.dev>
> ---
>  libavfilter/vf_blackdetect.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c
> index 99ff1ac606..c937248169 100644
> --- a/libavfilter/vf_blackdetect.c
> +++ b/libavfilter/vf_blackdetect.c
> @@ -102,8 +102,6 @@ static int config_input(AVFilterLink *inlink)
>      BlackDetectContext *s = ctx->priv;
>      const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
>      const int depth = desc->comp[0].depth;
> -    const int max = (1 << depth) - 1;
> -    const int factor = (1 << (depth - 8));
>  
>      s->depth = depth;
>      s->nb_threads = ff_filter_get_nb_threads(ctx);
> @@ -113,16 +111,10 @@ static int config_input(AVFilterLink *inlink)
>      if (!s->counter)
>          return AVERROR(ENOMEM);
>  
> -    s->pixel_black_th_i = ff_fmt_is_in(inlink->format, yuvj_formats) ?
> -        // luminance_minimum_value + pixel_black_th * luminance_range_size
> -             s->pixel_black_th *  max :
> -        16 * factor + s->pixel_black_th * (235 - 16) * factor;
> -
>      av_log(s, AV_LOG_VERBOSE,
> -           "black_min_duration:%s pixel_black_th:%f pixel_black_th_i:%d picture_black_ratio_th:%f\n",
> +           "black_min_duration:%s pixel_black_th:%f picture_black_ratio_th:%f\n",
>             av_ts2timestr(s->black_min_duration, &s->time_base),
> -           s->pixel_black_th, s->pixel_black_th_i,
> -           s->picture_black_ratio_th);
> +           s->pixel_black_th, s->picture_black_ratio_th);
>      return 0;
>  }
>  
> @@ -182,6 +174,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
>      AVFilterContext *ctx = inlink->dst;
>      BlackDetectContext *s = ctx->priv;
>      double picture_black_ratio = 0;
> +    const int max = (1 << s->depth) - 1;
> +    const int factor = (1 << (s->depth - 8));
> +    const int full = picref->color_range == AVCOL_RANGE_JPEG ||
> +                     ff_fmt_is_in(picref->format, yuvj_formats);
> +
> +    s->pixel_black_th_i = full ? s->pixel_black_th * max :
> +        // luminance_minimum_value + pixel_black_th * luminance_range_size
> +        16 * factor + s->pixel_black_th * (235 - 16) * factor;
>  
>      ff_filter_execute(ctx, black_counter, picref, NULL,
>                        FFMIN(inlink->h, s->nb_threads));
> -- 
> 2.38.1
>
diff mbox series

Patch

diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c
index 99ff1ac606..c937248169 100644
--- a/libavfilter/vf_blackdetect.c
+++ b/libavfilter/vf_blackdetect.c
@@ -102,8 +102,6 @@  static int config_input(AVFilterLink *inlink)
     BlackDetectContext *s = ctx->priv;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     const int depth = desc->comp[0].depth;
-    const int max = (1 << depth) - 1;
-    const int factor = (1 << (depth - 8));
 
     s->depth = depth;
     s->nb_threads = ff_filter_get_nb_threads(ctx);
@@ -113,16 +111,10 @@  static int config_input(AVFilterLink *inlink)
     if (!s->counter)
         return AVERROR(ENOMEM);
 
-    s->pixel_black_th_i = ff_fmt_is_in(inlink->format, yuvj_formats) ?
-        // luminance_minimum_value + pixel_black_th * luminance_range_size
-             s->pixel_black_th *  max :
-        16 * factor + s->pixel_black_th * (235 - 16) * factor;
-
     av_log(s, AV_LOG_VERBOSE,
-           "black_min_duration:%s pixel_black_th:%f pixel_black_th_i:%d picture_black_ratio_th:%f\n",
+           "black_min_duration:%s pixel_black_th:%f picture_black_ratio_th:%f\n",
            av_ts2timestr(s->black_min_duration, &s->time_base),
-           s->pixel_black_th, s->pixel_black_th_i,
-           s->picture_black_ratio_th);
+           s->pixel_black_th, s->picture_black_ratio_th);
     return 0;
 }
 
@@ -182,6 +174,14 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
     AVFilterContext *ctx = inlink->dst;
     BlackDetectContext *s = ctx->priv;
     double picture_black_ratio = 0;
+    const int max = (1 << s->depth) - 1;
+    const int factor = (1 << (s->depth - 8));
+    const int full = picref->color_range == AVCOL_RANGE_JPEG ||
+                     ff_fmt_is_in(picref->format, yuvj_formats);
+
+    s->pixel_black_th_i = full ? s->pixel_black_th * max :
+        // luminance_minimum_value + pixel_black_th * luminance_range_size
+        16 * factor + s->pixel_black_th * (235 - 16) * factor;
 
     ff_filter_execute(ctx, black_counter, picref, NULL,
                       FFMIN(inlink->h, s->nb_threads));