Signed-off-by: Paul B Mahol <onemda@gmail.com>
Paul B Mahol authored on 2015/08/26 03:02:42... | ... |
@@ -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: |