Browse code

avfilter/vf_histogram: 9 and 10 bit depth support

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2015/08/26 03:02:42
Showing 1 changed files
... ...
@@ -22,6 +22,8 @@
22 22
 #include "libavutil/opt.h"
23 23
 #include "libavutil/parseutils.h"
24 24
 #include "libavutil/pixdesc.h"
25
+#include "libavutil/imgutils.h"
26
+#include "libavutil/intreadwrite.h"
25 27
 #include "avfilter.h"
26 28
 #include "formats.h"
27 29
 #include "internal.h"
... ...
@@ -38,7 +40,9 @@ enum HistogramMode {
38 38
 typedef struct HistogramContext {
39 39
     const AVClass *class;               ///< AVClass context for log and options purpose
40 40
     int mode;                           ///< HistogramMode
41
-    unsigned       histogram[256];
41
+    unsigned       histogram[256*256];
42
+    int            histogram_size;
43
+    int            mult;
42 44
     int            ncomp;
43 45
     const uint8_t  *bg_color;
44 46
     const uint8_t  *fg_color;
... ...
@@ -94,21 +98,46 @@ static const enum AVPixelFormat levels_in_pix_fmts[] = {
94 94
     AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUVJ411P,
95 95
     AV_PIX_FMT_YUV440P,  AV_PIX_FMT_YUV410P,
96 96
     AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
97
+    AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9,
98
+    AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
99
+    AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
100
+    AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
97 101
     AV_PIX_FMT_GBRAP,    AV_PIX_FMT_GBRP,
102
+    AV_PIX_FMT_GBRP9,    AV_PIX_FMT_GBRP10,
98 103
     AV_PIX_FMT_GRAY8,
99 104
     AV_PIX_FMT_NONE
100 105
 };
101 106
 
102
-static const enum AVPixelFormat levels_out_yuv_pix_fmts[] = {
107
+static const enum AVPixelFormat levels_out_yuv8_pix_fmts[] = {
103 108
     AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P,
104 109
     AV_PIX_FMT_NONE
105 110
 };
106 111
 
107
-static const enum AVPixelFormat levels_out_rgb_pix_fmts[] = {
112
+static const enum AVPixelFormat levels_out_yuv9_pix_fmts[] = {
113
+    AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUV444P9,
114
+    AV_PIX_FMT_NONE
115
+};
116
+
117
+static const enum AVPixelFormat levels_out_yuv10_pix_fmts[] = {
118
+    AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUV444P10,
119
+    AV_PIX_FMT_NONE
120
+};
121
+
122
+static const enum AVPixelFormat levels_out_rgb8_pix_fmts[] = {
108 123
     AV_PIX_FMT_GBRAP,    AV_PIX_FMT_GBRP,
109 124
     AV_PIX_FMT_NONE
110 125
 };
111 126
 
127
+static const enum AVPixelFormat levels_out_rgb9_pix_fmts[] = {
128
+    AV_PIX_FMT_GBRP9,
129
+    AV_PIX_FMT_NONE
130
+};
131
+
132
+static const enum AVPixelFormat levels_out_rgb10_pix_fmts[] = {
133
+    AV_PIX_FMT_GBRP10,
134
+    AV_PIX_FMT_NONE
135
+};
136
+
112 137
 static const enum AVPixelFormat waveform_pix_fmts[] = {
113 138
      AV_PIX_FMT_GBRP,     AV_PIX_FMT_GBRAP,
114 139
      AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
... ...
@@ -136,7 +165,7 @@ static int query_formats(AVFilterContext *ctx)
136 136
         AVFilterFormats *avff;
137 137
         const AVPixFmtDescriptor *desc;
138 138
         const enum AVPixelFormat *out_pix_fmts;
139
-        int rgb, i;
139
+        int rgb, i, bits;
140 140
 
141 141
         if (!ctx->inputs[0]->in_formats ||
142 142
             !ctx->inputs[0]->in_formats->nb_formats) {
... ...
@@ -148,16 +177,26 @@ static int query_formats(AVFilterContext *ctx)
148 148
         avff = ctx->inputs[0]->in_formats;
149 149
         desc = av_pix_fmt_desc_get(avff->formats[0]);
150 150
         rgb = desc->flags & AV_PIX_FMT_FLAG_RGB;
151
+        bits = desc->comp[0].depth_minus1;
151 152
         for (i = 1; i < avff->nb_formats; i++) {
152 153
             desc = av_pix_fmt_desc_get(avff->formats[i]);
153
-            if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB))
154
+            if ((rgb != desc->flags & AV_PIX_FMT_FLAG_RGB) ||
155
+                (bits != desc->comp[0].depth_minus1))
154 156
                 return AVERROR(EAGAIN);
155 157
         }
156 158
 
157
-        if (rgb)
158
-            out_pix_fmts = levels_out_rgb_pix_fmts;
159
-        else
160
-            out_pix_fmts = levels_out_yuv_pix_fmts;
159
+        if (rgb && bits == 7)
160
+            out_pix_fmts = levels_out_rgb8_pix_fmts;
161
+        else if (rgb && bits == 8)
162
+            out_pix_fmts = levels_out_rgb9_pix_fmts;
163
+        else if (rgb && bits == 9)
164
+            out_pix_fmts = levels_out_rgb10_pix_fmts;
165
+        else if (bits == 7)
166
+            out_pix_fmts = levels_out_yuv8_pix_fmts;
167
+        else if (bits == 8)
168
+            out_pix_fmts = levels_out_yuv9_pix_fmts;
169
+        else // if (bits == 9)
170
+            out_pix_fmts = levels_out_yuv10_pix_fmts;
161 171
         ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats);
162 172
 
163 173
         return 0;
... ...
@@ -188,8 +227,12 @@ static int config_input(AVFilterLink *inlink)
188 188
 
189 189
     h->desc  = av_pix_fmt_desc_get(inlink->format);
190 190
     h->ncomp = h->desc->nb_components;
191
+    h->histogram_size = 1 << (h->desc->comp[0].depth_minus1 + 1);
192
+    h->mult = h->histogram_size / 256;
191 193
 
192 194
     switch (inlink->format) {
195
+    case AV_PIX_FMT_GBRP10:
196
+    case AV_PIX_FMT_GBRP9:
193 197
     case AV_PIX_FMT_GBRAP:
194 198
     case AV_PIX_FMT_GBRP:
195 199
         h->bg_color = black_gbrp_color;
... ...
@@ -220,7 +263,7 @@ static int config_output(AVFilterLink *outlink)
220 220
             if ((1 << i) & h->components)
221 221
                 ncomp++;
222 222
         }
223
-        outlink->w = 256;
223
+        outlink->w = h->histogram_size;
224 224
         outlink->h = (h->level_height + h->scale_height) * FFMAX(ncomp * h->display_mode, 1);
225 225
         break;
226 226
     case MODE_WAVEFORM:
... ...
@@ -298,7 +341,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
298 298
     AVFilterContext *ctx  = inlink->dst;
299 299
     AVFilterLink *outlink = ctx->outputs[0];
300 300
     AVFrame *out;
301
-    const uint8_t *src;
302 301
     uint8_t *dst;
303 302
     int i, j, k, l, m;
304 303
 
... ...
@@ -314,10 +356,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
314 314
         const int is_chroma = (k == 1 || k == 2);
315 315
         const int dst_h = FF_CEIL_RSHIFT(outlink->h, (is_chroma ? h->odesc->log2_chroma_h : 0));
316 316
         const int dst_w = FF_CEIL_RSHIFT(outlink->w, (is_chroma ? h->odesc->log2_chroma_w : 0));
317
-        for (i = 0; i < dst_h ; i++)
318
-            memset(out->data[h->odesc->comp[k].plane] +
319
-                   i * out->linesize[h->odesc->comp[k].plane],
320
-                   h->bg_color[k], dst_w);
317
+
318
+        if (h->histogram_size <= 256) {
319
+            for (i = 0; i < dst_h ; i++)
320
+                memset(out->data[h->odesc->comp[k].plane] +
321
+                       i * out->linesize[h->odesc->comp[k].plane],
322
+                       h->bg_color[k], dst_w);
323
+        } else {
324
+            const int mult = h->mult;
325
+
326
+            for (i = 0; i < dst_h ; i++)
327
+                for (j = 0; j < dst_w; j++)
328
+                    AV_WN16(out->data[h->odesc->comp[k].plane] +
329
+                        i * out->linesize[h->odesc->comp[k].plane] + j * 2,
330
+                        h->bg_color[k] * mult);
331
+        }
321 332
     }
322 333
 
323 334
     switch (h->mode) {
... ...
@@ -326,21 +379,29 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
326 326
             const int p = h->desc->comp[k].plane;
327 327
             const int height = h->planeheight[p];
328 328
             const int width = h->planewidth[p];
329
-            int start;
330 329
             double max_hval_log;
331 330
             unsigned max_hval = 0;
331
+            int start;
332 332
 
333 333
             if (!((1 << k) & h->components))
334 334
                 continue;
335 335
             start = m++ * (h->level_height + h->scale_height) * h->display_mode;
336 336
 
337
-            for (i = 0; i < height; i++) {
338
-                src = in->data[p] + i * in->linesize[p];
339
-                for (j = 0; j < width; j++)
340
-                    h->histogram[src[j]]++;
337
+            if (h->histogram_size <= 256) {
338
+                for (i = 0; i < height; i++) {
339
+                    const uint8_t *src = in->data[p] + i * in->linesize[p];
340
+                    for (j = 0; j < width; j++)
341
+                        h->histogram[src[j]]++;
342
+                }
343
+            } else {
344
+                for (i = 0; i < height; i++) {
345
+                    const uint16_t *src = (const uint16_t *)(in->data[p] + i * in->linesize[p]);
346
+                    for (j = 0; j < width; j++)
347
+                        h->histogram[src[j]]++;
348
+                }
341 349
             }
342 350
 
343
-            for (i = 0; i < 256; i++)
351
+            for (i = 0; i < h->histogram_size; i++)
344 352
                 max_hval = FFMAX(max_hval, h->histogram[i]);
345 353
             max_hval_log = log2(max_hval + 1);
346 354
 
... ...
@@ -352,19 +413,34 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
352 352
                 else
353 353
                     col_height = h->level_height - (h->histogram[i] * (int64_t)h->level_height + max_hval - 1) / max_hval;
354 354
 
355
-                for (j = h->level_height - 1; j >= col_height; j--) {
356
-                    if (h->display_mode) {
357
-                        for (l = 0; l < h->ncomp; l++)
358
-                            out->data[l][(j + start) * out->linesize[l] + i] = h->fg_color[l];
359
-                    } else {
360
-                        out->data[p][(j + start) * out->linesize[p] + i] = 255;
355
+                if (h->histogram_size <= 256) {
356
+                    for (j = h->level_height - 1; j >= col_height; j--) {
357
+                        if (h->display_mode) {
358
+                            for (l = 0; l < h->ncomp; l++)
359
+                                out->data[l][(j + start) * out->linesize[l] + i] = h->fg_color[l];
360
+                        } else {
361
+                            out->data[p][(j + start) * out->linesize[p] + i] = 255;
362
+                        }
363
+                    }
364
+                    for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--)
365
+                        out->data[p][(j + start) * out->linesize[p] + i] = i;
366
+                } else {
367
+                    const int mult = h->mult;
368
+
369
+                    for (j = h->level_height - 1; j >= col_height; j--) {
370
+                        if (h->display_mode) {
371
+                            for (l = 0; l < h->ncomp; l++)
372
+                                AV_WN16(out->data[l] + (j + start) * out->linesize[l] + i * 2, h->fg_color[l] * mult);
373
+                        } else {
374
+                            AV_WN16(out->data[p] + (j + start) * out->linesize[p] + i * 2, 255 * mult);
375
+                        }
361 376
                     }
377
+                    for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--)
378
+                        AV_WN16(out->data[p] + (j + start) * out->linesize[p] + i * 2, i);
362 379
                 }
363
-                for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--)
364
-                    out->data[p][(j + start) * out->linesize[p] + i] = i;
365 380
             }
366 381
 
367
-            memset(h->histogram, 0, 256 * sizeof(unsigned));
382
+            memset(h->histogram, 0, h->histogram_size * sizeof(unsigned));
368 383
         }
369 384
         break;
370 385
     case MODE_WAVEFORM: