annotate ffmpeg/libavfilter/vf_histogram.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Copyright (c) 2012-2013 Paul B Mahol
yading@10 3 *
yading@10 4 * This file is part of FFmpeg.
yading@10 5 *
yading@10 6 * FFmpeg is free software; you can redistribute it and/or
yading@10 7 * modify it under the terms of the GNU Lesser General Public
yading@10 8 * License as published by the Free Software Foundation; either
yading@10 9 * version 2.1 of the License, or (at your option) any later version.
yading@10 10 *
yading@10 11 * FFmpeg is distributed in the hope that it will be useful,
yading@10 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 14 * Lesser General Public License for more details.
yading@10 15 *
yading@10 16 * You should have received a copy of the GNU Lesser General Public
yading@10 17 * License along with FFmpeg; if not, write to the Free Software
yading@10 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 19 */
yading@10 20
yading@10 21 #include "libavutil/avassert.h"
yading@10 22 #include "libavutil/opt.h"
yading@10 23 #include "libavutil/parseutils.h"
yading@10 24 #include "libavutil/pixdesc.h"
yading@10 25 #include "avfilter.h"
yading@10 26 #include "formats.h"
yading@10 27 #include "internal.h"
yading@10 28 #include "video.h"
yading@10 29
yading@10 30 enum HistogramMode {
yading@10 31 MODE_LEVELS,
yading@10 32 MODE_WAVEFORM,
yading@10 33 MODE_COLOR,
yading@10 34 MODE_COLOR2,
yading@10 35 MODE_NB
yading@10 36 };
yading@10 37
yading@10 38 typedef struct HistogramContext {
yading@10 39 const AVClass *class; ///< AVClass context for log and options purpose
yading@10 40 enum HistogramMode mode;
yading@10 41 unsigned histogram[256];
yading@10 42 unsigned max_hval;
yading@10 43 int ncomp;
yading@10 44 const uint8_t *bg_color;
yading@10 45 const uint8_t *fg_color;
yading@10 46 int level_height;
yading@10 47 int scale_height;
yading@10 48 int step;
yading@10 49 int waveform_mode;
yading@10 50 int display_mode;
yading@10 51 } HistogramContext;
yading@10 52
yading@10 53 #define OFFSET(x) offsetof(HistogramContext, x)
yading@10 54 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
yading@10 55
yading@10 56 static const AVOption histogram_options[] = {
yading@10 57 { "mode", "set histogram mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_LEVELS}, 0, MODE_NB-1, FLAGS, "mode"},
yading@10 58 { "levels", "standard histogram", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LEVELS}, 0, 0, FLAGS, "mode" },
yading@10 59 { "waveform", "per row/column luminance graph", 0, AV_OPT_TYPE_CONST, {.i64=MODE_WAVEFORM}, 0, 0, FLAGS, "mode" },
yading@10 60 { "color", "chroma values in vectorscope", 0, AV_OPT_TYPE_CONST, {.i64=MODE_COLOR}, 0, 0, FLAGS, "mode" },
yading@10 61 { "color2", "chroma values in vectorscope", 0, AV_OPT_TYPE_CONST, {.i64=MODE_COLOR2}, 0, 0, FLAGS, "mode" },
yading@10 62 { "level_height", "set level height", OFFSET(level_height), AV_OPT_TYPE_INT, {.i64=200}, 50, 2048, FLAGS},
yading@10 63 { "scale_height", "set scale height", OFFSET(scale_height), AV_OPT_TYPE_INT, {.i64=12}, 0, 40, FLAGS},
yading@10 64 { "step", "set waveform step value", OFFSET(step), AV_OPT_TYPE_INT, {.i64=10}, 1, 255, FLAGS},
yading@10 65 { "waveform_mode", "set waveform mode", OFFSET(waveform_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "waveform_mode"},
yading@10 66 { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "waveform_mode" },
yading@10 67 { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "waveform_mode" },
yading@10 68 { "display_mode", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display_mode"},
yading@10 69 { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" },
yading@10 70 { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" },
yading@10 71 { NULL },
yading@10 72 };
yading@10 73
yading@10 74 AVFILTER_DEFINE_CLASS(histogram);
yading@10 75
yading@10 76 static const enum AVPixelFormat color_pix_fmts[] = {
yading@10 77 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVJ444P,
yading@10 78 AV_PIX_FMT_NONE
yading@10 79 };
yading@10 80
yading@10 81 static const enum AVPixelFormat levels_pix_fmts[] = {
yading@10 82 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVJ444P,
yading@10 83 AV_PIX_FMT_GRAY8, AV_PIX_FMT_GBRP, AV_PIX_FMT_NONE
yading@10 84 };
yading@10 85
yading@10 86 static int query_formats(AVFilterContext *ctx)
yading@10 87 {
yading@10 88 HistogramContext *h = ctx->priv;
yading@10 89 const enum AVPixelFormat *pix_fmts;
yading@10 90
yading@10 91 switch (h->mode) {
yading@10 92 case MODE_WAVEFORM:
yading@10 93 case MODE_LEVELS:
yading@10 94 pix_fmts = levels_pix_fmts;
yading@10 95 break;
yading@10 96 case MODE_COLOR:
yading@10 97 case MODE_COLOR2:
yading@10 98 pix_fmts = color_pix_fmts;
yading@10 99 break;
yading@10 100 default:
yading@10 101 av_assert0(0);
yading@10 102 }
yading@10 103
yading@10 104 ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
yading@10 105
yading@10 106 return 0;
yading@10 107 }
yading@10 108
yading@10 109 static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 };
yading@10 110 static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 };
yading@10 111 static const uint8_t white_yuva_color[4] = { 255, 127, 127, 255 };
yading@10 112 static const uint8_t white_gbrp_color[4] = { 255, 255, 255, 255 };
yading@10 113
yading@10 114 static int config_input(AVFilterLink *inlink)
yading@10 115 {
yading@10 116 HistogramContext *h = inlink->dst->priv;
yading@10 117 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
yading@10 118
yading@10 119 h->ncomp = desc->nb_components;
yading@10 120
yading@10 121 switch (inlink->format) {
yading@10 122 case AV_PIX_FMT_GBRP:
yading@10 123 h->bg_color = black_gbrp_color;
yading@10 124 h->fg_color = white_gbrp_color;
yading@10 125 break;
yading@10 126 default:
yading@10 127 h->bg_color = black_yuva_color;
yading@10 128 h->fg_color = white_yuva_color;
yading@10 129 }
yading@10 130
yading@10 131 return 0;
yading@10 132 }
yading@10 133
yading@10 134 static int config_output(AVFilterLink *outlink)
yading@10 135 {
yading@10 136 AVFilterContext *ctx = outlink->src;
yading@10 137 HistogramContext *h = ctx->priv;
yading@10 138
yading@10 139 switch (h->mode) {
yading@10 140 case MODE_LEVELS:
yading@10 141 outlink->w = 256;
yading@10 142 outlink->h = (h->level_height + h->scale_height) * FFMAX(h->ncomp * h->display_mode, 1);
yading@10 143 break;
yading@10 144 case MODE_WAVEFORM:
yading@10 145 if (h->waveform_mode)
yading@10 146 outlink->h = 256 * FFMAX(h->ncomp * h->display_mode, 1);
yading@10 147 else
yading@10 148 outlink->w = 256 * FFMAX(h->ncomp * h->display_mode, 1);
yading@10 149 break;
yading@10 150 case MODE_COLOR:
yading@10 151 case MODE_COLOR2:
yading@10 152 outlink->h = outlink->w = 256;
yading@10 153 break;
yading@10 154 default:
yading@10 155 av_assert0(0);
yading@10 156 }
yading@10 157
yading@10 158 outlink->sample_aspect_ratio = (AVRational){1,1};
yading@10 159
yading@10 160 return 0;
yading@10 161 }
yading@10 162
yading@10 163 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
yading@10 164 {
yading@10 165 HistogramContext *h = inlink->dst->priv;
yading@10 166 AVFilterContext *ctx = inlink->dst;
yading@10 167 AVFilterLink *outlink = ctx->outputs[0];
yading@10 168 AVFrame *out;
yading@10 169 const uint8_t *src;
yading@10 170 uint8_t *dst;
yading@10 171 int i, j, k, l;
yading@10 172
yading@10 173 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
yading@10 174 if (!out) {
yading@10 175 av_frame_free(&in);
yading@10 176 return AVERROR(ENOMEM);
yading@10 177 }
yading@10 178
yading@10 179 out->pts = in->pts;
yading@10 180
yading@10 181 for (k = 0; k < h->ncomp; k++)
yading@10 182 for (i = 0; i < outlink->h; i++)
yading@10 183 memset(out->data[k] + i * out->linesize[k], h->bg_color[k], outlink->w);
yading@10 184
yading@10 185 switch (h->mode) {
yading@10 186 case MODE_LEVELS:
yading@10 187 for (k = 0; k < h->ncomp; k++) {
yading@10 188 int start = k * (h->level_height + h->scale_height) * h->display_mode;
yading@10 189
yading@10 190 for (i = 0; i < in->height; i++) {
yading@10 191 src = in->data[k] + i * in->linesize[k];
yading@10 192 for (j = 0; j < in->width; j++)
yading@10 193 h->histogram[src[j]]++;
yading@10 194 }
yading@10 195
yading@10 196 for (i = 0; i < 256; i++)
yading@10 197 h->max_hval = FFMAX(h->max_hval, h->histogram[i]);
yading@10 198
yading@10 199 for (i = 0; i < outlink->w; i++) {
yading@10 200 int col_height = h->level_height - (h->histogram[i] * (int64_t)h->level_height + h->max_hval - 1) / h->max_hval;
yading@10 201
yading@10 202 for (j = h->level_height - 1; j >= col_height; j--) {
yading@10 203 if (h->display_mode) {
yading@10 204 for (l = 0; l < h->ncomp; l++)
yading@10 205 out->data[l][(j + start) * out->linesize[l] + i] = h->fg_color[l];
yading@10 206 } else {
yading@10 207 out->data[k][(j + start) * out->linesize[k] + i] = 255;
yading@10 208 }
yading@10 209 }
yading@10 210 for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--)
yading@10 211 out->data[k][(j + start) * out->linesize[k] + i] = i;
yading@10 212 }
yading@10 213
yading@10 214 memset(h->histogram, 0, 256 * sizeof(unsigned));
yading@10 215 h->max_hval = 0;
yading@10 216 }
yading@10 217 break;
yading@10 218 case MODE_WAVEFORM:
yading@10 219 if (h->waveform_mode) {
yading@10 220 for (k = 0; k < h->ncomp; k++) {
yading@10 221 int offset = k * 256 * h->display_mode;
yading@10 222 for (i = 0; i < inlink->w; i++) {
yading@10 223 for (j = 0; j < inlink->h; j++) {
yading@10 224 int pos = (offset +
yading@10 225 in->data[k][j * in->linesize[k] + i]) *
yading@10 226 out->linesize[k] + i;
yading@10 227 unsigned value = out->data[k][pos];
yading@10 228 value = FFMIN(value + h->step, 255);
yading@10 229 out->data[k][pos] = value;
yading@10 230 }
yading@10 231 }
yading@10 232 }
yading@10 233 } else {
yading@10 234 for (k = 0; k < h->ncomp; k++) {
yading@10 235 int offset = k * 256 * h->display_mode;
yading@10 236 for (i = 0; i < inlink->h; i++) {
yading@10 237 src = in ->data[k] + i * in ->linesize[k];
yading@10 238 dst = out->data[k] + i * out->linesize[k];
yading@10 239 for (j = 0; j < inlink->w; j++) {
yading@10 240 int pos = src[j] + offset;
yading@10 241 unsigned value = dst[pos];
yading@10 242 value = FFMIN(value + h->step, 255);
yading@10 243 dst[pos] = value;
yading@10 244 }
yading@10 245 }
yading@10 246 }
yading@10 247 }
yading@10 248 break;
yading@10 249 case MODE_COLOR:
yading@10 250 for (i = 0; i < inlink->h; i++) {
yading@10 251 int iw1 = i * in->linesize[1];
yading@10 252 int iw2 = i * in->linesize[2];
yading@10 253 for (j = 0; j < inlink->w; j++) {
yading@10 254 int pos = in->data[1][iw1 + j] * out->linesize[0] + in->data[2][iw2 + j];
yading@10 255 if (out->data[0][pos] < 255)
yading@10 256 out->data[0][pos]++;
yading@10 257 }
yading@10 258 }
yading@10 259 for (i = 0; i < 256; i++) {
yading@10 260 dst = out->data[0] + i * out->linesize[0];
yading@10 261 for (j = 0; j < 256; j++) {
yading@10 262 if (!dst[j]) {
yading@10 263 out->data[1][i * out->linesize[0] + j] = i;
yading@10 264 out->data[2][i * out->linesize[0] + j] = j;
yading@10 265 }
yading@10 266 }
yading@10 267 }
yading@10 268 break;
yading@10 269 case MODE_COLOR2:
yading@10 270 for (i = 0; i < inlink->h; i++) {
yading@10 271 int iw1 = i * in->linesize[1];
yading@10 272 int iw2 = i * in->linesize[2];
yading@10 273 for (j = 0; j < inlink->w; j++) {
yading@10 274 int u = in->data[1][iw1 + j];
yading@10 275 int v = in->data[2][iw2 + j];
yading@10 276 int pos = u * out->linesize[0] + v;
yading@10 277 if (!out->data[0][pos])
yading@10 278 out->data[0][pos] = FFABS(128 - u) + FFABS(128 - v);
yading@10 279 out->data[1][pos] = u;
yading@10 280 out->data[2][pos] = v;
yading@10 281 }
yading@10 282 }
yading@10 283 break;
yading@10 284 default:
yading@10 285 av_assert0(0);
yading@10 286 }
yading@10 287
yading@10 288 av_frame_free(&in);
yading@10 289 return ff_filter_frame(outlink, out);
yading@10 290 }
yading@10 291
yading@10 292 static const AVFilterPad inputs[] = {
yading@10 293 {
yading@10 294 .name = "default",
yading@10 295 .type = AVMEDIA_TYPE_VIDEO,
yading@10 296 .filter_frame = filter_frame,
yading@10 297 .config_props = config_input,
yading@10 298 },
yading@10 299 { NULL }
yading@10 300 };
yading@10 301
yading@10 302 static const AVFilterPad outputs[] = {
yading@10 303 {
yading@10 304 .name = "default",
yading@10 305 .type = AVMEDIA_TYPE_VIDEO,
yading@10 306 .config_props = config_output,
yading@10 307 },
yading@10 308 { NULL }
yading@10 309 };
yading@10 310
yading@10 311 AVFilter avfilter_vf_histogram = {
yading@10 312 .name = "histogram",
yading@10 313 .description = NULL_IF_CONFIG_SMALL("Compute and draw a histogram."),
yading@10 314 .priv_size = sizeof(HistogramContext),
yading@10 315 .query_formats = query_formats,
yading@10 316 .inputs = inputs,
yading@10 317 .outputs = outputs,
yading@10 318 .priv_class = &histogram_class,
yading@10 319 };