[FFmpeg-devel] avfilter/vf_hue: 10bit support

Submitted by Michael Niedermayer on Aug. 3, 2018, 2:34 p.m.

Details

Message ID 20180803143451.16825-1-michael@niedermayer.cc
State Accepted
Commit 2612431d1b2b442d9bf5bb639577ad2c506ae66e
Headers show

Commit Message

Michael Niedermayer Aug. 3, 2018, 2:34 p.m.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavfilter/vf_hue.c | 103 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 92 insertions(+), 11 deletions(-)

Comments

Tobias Rapp Aug. 3, 2018, 3:14 p.m.
On 03.08.2018 16:34, Michael Niedermayer wrote:
> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> ---
>   libavfilter/vf_hue.c | 103 ++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 92 insertions(+), 11 deletions(-)
> 
> [...]

Tested here successfully with 10-bit yuvtestsrc data and different hue 
filter option values for h/s/b.

Regards,
Tobias
Reto Kromer Aug. 3, 2018, 3:39 p.m.
Michael Niedermayer wrote:

>Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
>---
> libavfilter/vf_hue.c | 103 +++++++++++++++++++++++++++++++++++
> +++-----
> 1 file changed, 92 insertions(+), 11 deletions(-)

On my side it works fine, but don't have any official status in
the project.

Best regards, Reto


AV Preservation by reto.ch
chemin du Suchet 5 | 1024 Ecublens | Switzerland
Web: <https://reto.ch> | Twitter: @retoch
Michael Niedermayer Aug. 15, 2018, 9:38 p.m.
On Fri, Aug 03, 2018 at 05:39:20PM +0200, Reto Kromer wrote:
> Michael Niedermayer wrote:
> 
> >Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> >---
> > libavfilter/vf_hue.c | 103 +++++++++++++++++++++++++++++++++++
> > +++-----
> > 1 file changed, 92 insertions(+), 11 deletions(-)
> 
> On my side it works fine, but don't have any official status in
> the project.

will apply

thanks

[...]

Patch hide | download patch | download mbox

diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
index 45a5a1a92f..323333b33c 100644
--- a/libavfilter/vf_hue.c
+++ b/libavfilter/vf_hue.c
@@ -80,6 +80,9 @@  typedef struct HueContext {
     uint8_t  lut_l[256];
     uint8_t  lut_u[256][256];
     uint8_t  lut_v[256][256];
+    uint16_t  lut_l16[65536];
+    uint16_t  lut_u10[1024][1024];
+    uint16_t  lut_v10[1024][1024];
 } HueContext;
 
 #define OFFSET(x) offsetof(HueContext, x)
@@ -117,6 +120,9 @@  static inline void create_luma_lut(HueContext *h)
     for (i = 0; i < 256; i++) {
         h->lut_l[i] = av_clip_uint8(i + b * 25.5);
     }
+    for (i = 0; i < 65536; i++) {
+        h->lut_l16[i] = av_clip_uintp2(i + b * 102.4, 10);
+    }
 }
 
 static inline void create_chrominance_lut(HueContext *h, const int32_t c,
@@ -148,6 +154,25 @@  static inline void create_chrominance_lut(HueContext *h, const int32_t c,
             h->lut_v[i][j] = av_clip_uint8(new_v);
         }
     }
+    for (i = 0; i < 1024; i++) {
+        for (j = 0; j < 1024; j++) {
+            u = i - 512;
+            v = j - 512;
+            /*
+             * Apply the rotation of the vector : (c * u) - (s * v)
+             *                                    (s * u) + (c * v)
+             * De-normalize the components (without forgetting to scale 512
+             * by << 16)
+             * Finally scale back the result by >> 16
+             */
+            new_u = ((c * u) - (s * v) + (1 << 15) + (512 << 16)) >> 16;
+            new_v = ((s * u) + (c * v) + (1 << 15) + (512 << 16)) >> 16;
+
+            /* Prevent a potential overflow */
+            h->lut_u10[i][j] = av_clip_uintp2(new_u, 10);
+            h->lut_v10[i][j] = av_clip_uintp2(new_v, 10);
+        }
+    }
 }
 
 static int set_expr(AVExpr **pexpr_ptr, char **expr_ptr,
@@ -231,6 +256,11 @@  static int query_formats(AVFilterContext *ctx)
         AV_PIX_FMT_YUV410P,      AV_PIX_FMT_YUV440P,
         AV_PIX_FMT_YUVA444P,     AV_PIX_FMT_YUVA422P,
         AV_PIX_FMT_YUVA420P,
+        AV_PIX_FMT_YUV444P10,      AV_PIX_FMT_YUV422P10,
+        AV_PIX_FMT_YUV420P10,
+        AV_PIX_FMT_YUV440P10,
+        AV_PIX_FMT_YUVA444P10,     AV_PIX_FMT_YUVA422P10,
+        AV_PIX_FMT_YUVA420P10,
         AV_PIX_FMT_NONE
     };
     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
@@ -271,6 +301,22 @@  static void apply_luma_lut(HueContext *s,
     }
 }
 
+static void apply_luma_lut10(HueContext *s,
+                             uint16_t *ldst, const int dst_linesize,
+                             uint16_t *lsrc, const int src_linesize,
+                             int w, int h)
+{
+    int i;
+
+    while (h--) {
+        for (i = 0; i < w; i++)
+            ldst[i] = s->lut_l16[lsrc[i]];
+
+        lsrc += src_linesize;
+        ldst += dst_linesize;
+    }
+}
+
 static void apply_lut(HueContext *s,
                       uint8_t *udst, uint8_t *vdst, const int dst_linesize,
                       uint8_t *usrc, uint8_t *vsrc, const int src_linesize,
@@ -294,6 +340,29 @@  static void apply_lut(HueContext *s,
     }
 }
 
+static void apply_lut10(HueContext *s,
+                      uint16_t *udst, uint16_t *vdst, const int dst_linesize,
+                      uint16_t *usrc, uint16_t *vsrc, const int src_linesize,
+                      int w, int h)
+{
+    int i;
+
+    while (h--) {
+        for (i = 0; i < w; i++) {
+            const int u = av_clip_uintp2(usrc[i], 10);
+            const int v = av_clip_uintp2(vsrc[i], 10);
+
+            udst[i] = s->lut_u10[u][v];
+            vdst[i] = s->lut_v10[u][v];
+        }
+
+        usrc += src_linesize;
+        vsrc += src_linesize;
+        udst += dst_linesize;
+        vdst += dst_linesize;
+    }
+}
+
 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
 #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb))
 
@@ -305,6 +374,8 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
     const int32_t old_hue_sin = hue->hue_sin, old_hue_cos = hue->hue_cos;
     const float old_brightness = hue->brightness;
     int direct = 0;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+    const int bps = desc->comp[0].depth > 8 ? 2 : 1;
 
     if (av_frame_is_writable(inpic)) {
         direct = 1;
@@ -367,21 +438,31 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
     if (!direct) {
         if (!hue->brightness)
             av_image_copy_plane(outpic->data[0], outpic->linesize[0],
-                                inpic->data[0],  inpic->linesize[0],
-                                inlink->w, inlink->h);
+                                inpic->data[0],   inpic->linesize[0],
+                                inlink->w * bps, inlink->h);
         if (inpic->data[3])
             av_image_copy_plane(outpic->data[3], outpic->linesize[3],
-                                inpic->data[3],  inpic->linesize[3],
-                                inlink->w, inlink->h);
+                                inpic->data[3],   inpic->linesize[3],
+                                inlink->w * bps, inlink->h);
     }
 
-    apply_lut(hue, outpic->data[1], outpic->data[2], outpic->linesize[1],
-              inpic->data[1],  inpic->data[2],  inpic->linesize[1],
-              AV_CEIL_RSHIFT(inlink->w, hue->hsub),
-              AV_CEIL_RSHIFT(inlink->h, hue->vsub));
-    if (hue->brightness)
-        apply_luma_lut(hue, outpic->data[0], outpic->linesize[0],
-                       inpic->data[0], inpic->linesize[0], inlink->w, inlink->h);
+    if (bps > 1) {
+        apply_lut10(hue, (uint16_t*)outpic->data[1], (uint16_t*)outpic->data[2], outpic->linesize[1]/2,
+                         (uint16_t*) inpic->data[1], (uint16_t*) inpic->data[2],  inpic->linesize[1]/2,
+                    AV_CEIL_RSHIFT(inlink->w, hue->hsub),
+                    AV_CEIL_RSHIFT(inlink->h, hue->vsub));
+        if (hue->brightness)
+            apply_luma_lut10(hue, (uint16_t*)outpic->data[0], outpic->linesize[0]/2,
+                                  (uint16_t*) inpic->data[0],  inpic->linesize[0]/2, inlink->w, inlink->h);
+    } else {
+        apply_lut(hue, outpic->data[1], outpic->data[2], outpic->linesize[1],
+                       inpic->data[1],   inpic->data[2],  inpic->linesize[1],
+                  AV_CEIL_RSHIFT(inlink->w, hue->hsub),
+                  AV_CEIL_RSHIFT(inlink->h, hue->vsub));
+        if (hue->brightness)
+            apply_luma_lut(hue, outpic->data[0], outpic->linesize[0],
+                                inpic->data[0],  inpic->linesize[0], inlink->w, inlink->h);
+    }
 
     if (!direct)
         av_frame_free(&inpic);