[FFmpeg-cvslog] avfilter/vf_colorlevels: add support for gbrpf32 format

Paul B Mahol git at videolan.org
Mon Jan 30 19:45:08 EET 2023


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Jan 30 17:01:26 2023 +0100| [5508e04c7b710616e33407ac2b3f8d616cb745f0] | committer: Paul B Mahol

avfilter/vf_colorlevels: add support for gbrpf32 format

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=5508e04c7b710616e33407ac2b3f8d616cb745f0
---

 libavfilter/vf_colorlevels.c | 118 +++++++++++++++++++++++++++++++++----------
 1 file changed, 90 insertions(+), 28 deletions(-)

diff --git a/libavfilter/vf_colorlevels.c b/libavfilter/vf_colorlevels.c
index 76adfbd8c8..44ae6cffbf 100644
--- a/libavfilter/vf_colorlevels.c
+++ b/libavfilter/vf_colorlevels.c
@@ -97,11 +97,13 @@ typedef struct ThreadData {
 
     int h;
 
+    float fimin[4];
+    float fomin[4];
     int imin[4];
     int omin[4];
 } ThreadData;
 
-#define DO_COMMON(type, clip, preserve, planar)                                 \
+#define DO_COMMON(type, ptype, clip, preserve, planar)                          \
     const ThreadData *td = arg;                                                 \
     const int linesize = s->linesize;                                           \
     const int step = s->step;                                                   \
@@ -118,14 +120,14 @@ typedef struct ThreadData {
     type *dst_g = (type *)(td->dstrow[G]) + src_linesize * slice_start;         \
     type *dst_b = (type *)(td->dstrow[B]) + src_linesize * slice_start;         \
     type *dst_a = (type *)(td->dstrow[A]) + src_linesize * slice_start;         \
-    const int imin_r = td->imin[R];                                             \
-    const int imin_g = td->imin[G];                                             \
-    const int imin_b = td->imin[B];                                             \
-    const int imin_a = td->imin[A];                                             \
-    const int omin_r = td->omin[R];                                             \
-    const int omin_g = td->omin[G];                                             \
-    const int omin_b = td->omin[B];                                             \
-    const int omin_a = td->omin[A];                                             \
+    const ptype imin_r = s->depth == 32 ? td->fimin[R] : td->imin[R];           \
+    const ptype imin_g = s->depth == 32 ? td->fimin[G] : td->imin[G];           \
+    const ptype imin_b = s->depth == 32 ? td->fimin[B] : td->imin[B];           \
+    const ptype imin_a = s->depth == 32 ? td->fimin[A] : td->imin[A];           \
+    const ptype omin_r = s->depth == 32 ? td->fomin[R] : td->omin[R];           \
+    const ptype omin_g = s->depth == 32 ? td->fomin[G] : td->omin[G];           \
+    const ptype omin_b = s->depth == 32 ? td->fomin[B] : td->omin[B];           \
+    const ptype omin_a = s->depth == 32 ? td->fomin[A] : td->omin[A];           \
     const float coeff_r = td->coeff[R];                                         \
     const float coeff_g = td->coeff[G];                                         \
     const float coeff_b = td->coeff[B];                                         \
@@ -133,12 +135,12 @@ typedef struct ThreadData {
                                                                                 \
     for (int y = slice_start; y < slice_end; y++) {                             \
         for (int x = 0; x < linesize; x += step) {                              \
-            int ir, ig, ib, or, og, ob;                                         \
+            ptype ir, ig, ib, or, og, ob;                                       \
             ir = src_r[x];                                                      \
             ig = src_g[x];                                                      \
             ib = src_b[x];                                                      \
             if (preserve) {                                                     \
-                float ratio, icolor, ocolor, max = s->max;                      \
+                float ratio, icolor, ocolor, max = s->depth==32 ? 1.f : s->max; \
                                                                                 \
                 or = (ir - imin_r) * coeff_r + omin_r;                          \
                 og = (ig - imin_g) * coeff_g + omin_g;                          \
@@ -180,39 +182,40 @@ typedef struct ThreadData {
 
 #define CLIP8(x, depth) av_clip_uint8(x)
 #define CLIP16(x, depth) av_clip_uint16(x)
+#define NOCLIP(x, depth) (x)
 
 static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;
-    DO_COMMON(uint8_t, CLIP8, 0, 0)
+    DO_COMMON(uint8_t, int, CLIP8, 0, 0)
     return 0;
 }
 
 static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;\
-    DO_COMMON(uint16_t, CLIP16, 0, 0)
+    DO_COMMON(uint16_t, int, CLIP16, 0, 0)
     return 0;
 }
 
 static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;
-    DO_COMMON(uint8_t, CLIP8, 1, 0)
+    DO_COMMON(uint8_t, int, CLIP8, 1, 0)
     return 0;
 }
 
 static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;
-    DO_COMMON(uint16_t, CLIP16, 1, 0)
+    DO_COMMON(uint16_t, int, CLIP16, 1, 0)
     return 0;
 }
 
 static int colorlevels_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;
-    DO_COMMON(uint8_t, CLIP8, 0, 1)
+    DO_COMMON(uint8_t, int, CLIP8, 0, 1)
     return 0;
 }
 
@@ -220,7 +223,7 @@ static int colorlevels_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 9;
-    DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1)
     return 0;
 }
 
@@ -228,7 +231,7 @@ static int colorlevels_slice_10_planar(AVFilterContext *ctx, void *arg, int jobn
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 10;
-    DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1)
     return 0;
 }
 
@@ -236,7 +239,7 @@ static int colorlevels_slice_12_planar(AVFilterContext *ctx, void *arg, int jobn
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 12;
-    DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1)
     return 0;
 }
 
@@ -244,21 +247,28 @@ static int colorlevels_slice_14_planar(AVFilterContext *ctx, void *arg, int jobn
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 14;
-    DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1)
     return 0;
 }
 
 static int colorlevels_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;
-    DO_COMMON(uint16_t, CLIP16, 0, 1)
+    DO_COMMON(uint16_t, int, CLIP16, 0, 1)
+    return 0;
+}
+
+static int colorlevels_slice_32_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    ColorLevelsContext *s = ctx->priv;
+    DO_COMMON(float, float, NOCLIP, 0, 1)
     return 0;
 }
 
 static int colorlevels_preserve_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;
-    DO_COMMON(uint8_t, CLIP8, 1, 1)
+    DO_COMMON(uint8_t, int, CLIP8, 1, 1)
     return 0;
 }
 
@@ -266,7 +276,7 @@ static int colorlevels_preserve_slice_9_planar(AVFilterContext *ctx, void *arg,
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 9;
-    DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1)
     return 0;
 }
 
@@ -274,7 +284,7 @@ static int colorlevels_preserve_slice_10_planar(AVFilterContext *ctx, void *arg,
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 10;
-    DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1)
     return 0;
 }
 
@@ -282,7 +292,7 @@ static int colorlevels_preserve_slice_12_planar(AVFilterContext *ctx, void *arg,
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 12;
-    DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1)
     return 0;
 }
 
@@ -290,14 +300,21 @@ static int colorlevels_preserve_slice_14_planar(AVFilterContext *ctx, void *arg,
 {
     ColorLevelsContext *s = ctx->priv;
     const int depth = 14;
-    DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
+    DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1)
     return 0;
 }
 
 static int colorlevels_preserve_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
     ColorLevelsContext *s = ctx->priv;
-    DO_COMMON(uint16_t, CLIP16, 1, 1)
+    DO_COMMON(uint16_t, int, CLIP16, 1, 1)
+    return 0;
+}
+
+static int colorlevels_preserve_slice_32_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    ColorLevelsContext *s = ctx->priv;
+    DO_COMMON(float, float, NOCLIP, 1, 1)
     return 0;
 }
 
@@ -349,6 +366,10 @@ static int config_input(AVFilterLink *inlink)
             s->colorlevels_slice[0] = colorlevels_slice_16_planar;
             s->colorlevels_slice[1] = colorlevels_preserve_slice_16_planar;
             break;
+        case 32:
+            s->colorlevels_slice[0] = colorlevels_slice_32_planar;
+            s->colorlevels_slice[1] = colorlevels_preserve_slice_32_planar;
+            break;
         }
     }
 
@@ -479,6 +500,46 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             td.omin[i]  = omin;
         }
         break;
+    case 4:
+        for (int i = 0; i < s->nb_comp; i++) {
+            Range *r = &s->range[i];
+            const uint8_t offset = s->rgba_map[i];
+            const uint8_t *srcrow = in->data[0];
+            float imin = r->in_min;
+            float imax = r->in_max;
+            float omin = r->out_min;
+            float omax = r->out_max;
+            float coeff;
+
+            if (imin < 0.f) {
+                imin = 1.f;
+                for (int y = 0; y < inlink->h; y++) {
+                    const float *src = (const float *)srcrow;
+
+                    for (int x = 0; x < s->linesize; x += step)
+                        imin = fminf(imin, src[x + offset]);
+                    srcrow += in->linesize[0];
+                }
+            }
+            if (imax < 0.f) {
+                srcrow = in->data[0];
+                imax = 0.f;
+                for (int y = 0; y < inlink->h; y++) {
+                    const float *src = (const float *)srcrow;
+
+                    for (int x = 0; x < s->linesize; x += step)
+                        imax = fmaxf(imax, src[x + offset]);
+                    srcrow += in->linesize[0];
+                }
+            }
+
+            coeff = (omax - omin) / (double)(imax - imin);
+
+            td.coeff[i] = coeff;
+            td.fimin[i] = imin;
+            td.fomin[i] = omin;
+        }
+        break;
     }
 
     ff_filter_execute(ctx, s->colorlevels_slice[s->preserve_color > 0], &td, NULL,
@@ -524,7 +585,8 @@ const AVFilter ff_vf_colorlevels = {
                    AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
                    AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
                    AV_PIX_FMT_GBRP14,
-                   AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16),
+                   AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
+                   AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };



More information about the ffmpeg-cvslog mailing list