vf_histogram.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/avassert.h"
22 #include "libavutil/opt.h"
23 #include "libavutil/parseutils.h"
24 #include "libavutil/pixdesc.h"
25 #include "avfilter.h"
26 #include "formats.h"
27 #include "internal.h"
28 #include "video.h"
29 
36 };
37 
38 typedef struct HistogramContext {
39  const AVClass *class; ///< AVClass context for log and options purpose
41  unsigned histogram[256];
42  unsigned max_hval;
43  int ncomp;
44  const uint8_t *bg_color;
45  const uint8_t *fg_color;
48  int step;
52 
53 #define OFFSET(x) offsetof(HistogramContext, x)
54 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
55 
56 static const AVOption histogram_options[] = {
57  { "mode", "set histogram mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_LEVELS}, 0, MODE_NB-1, FLAGS, "mode"},
58  { "levels", "standard histogram", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LEVELS}, 0, 0, FLAGS, "mode" },
59  { "waveform", "per row/column luminance graph", 0, AV_OPT_TYPE_CONST, {.i64=MODE_WAVEFORM}, 0, 0, FLAGS, "mode" },
60  { "color", "chroma values in vectorscope", 0, AV_OPT_TYPE_CONST, {.i64=MODE_COLOR}, 0, 0, FLAGS, "mode" },
61  { "color2", "chroma values in vectorscope", 0, AV_OPT_TYPE_CONST, {.i64=MODE_COLOR2}, 0, 0, FLAGS, "mode" },
62  { "level_height", "set level height", OFFSET(level_height), AV_OPT_TYPE_INT, {.i64=200}, 50, 2048, FLAGS},
63  { "scale_height", "set scale height", OFFSET(scale_height), AV_OPT_TYPE_INT, {.i64=12}, 0, 40, FLAGS},
64  { "step", "set waveform step value", OFFSET(step), AV_OPT_TYPE_INT, {.i64=10}, 1, 255, FLAGS},
65  { "waveform_mode", "set waveform mode", OFFSET(waveform_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "waveform_mode"},
66  { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "waveform_mode" },
67  { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "waveform_mode" },
68  { "display_mode", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display_mode"},
69  { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" },
70  { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" },
71  { NULL },
72 };
73 
75 
76 static const enum AVPixelFormat color_pix_fmts[] = {
79 };
80 
81 static const enum AVPixelFormat levels_pix_fmts[] = {
84 };
85 
87 {
88  HistogramContext *h = ctx->priv;
89  const enum AVPixelFormat *pix_fmts;
90 
91  switch (h->mode) {
92  case MODE_WAVEFORM:
93  case MODE_LEVELS:
94  pix_fmts = levels_pix_fmts;
95  break;
96  case MODE_COLOR:
97  case MODE_COLOR2:
98  pix_fmts = color_pix_fmts;
99  break;
100  default:
101  av_assert0(0);
102  }
103 
105 
106  return 0;
107 }
108 
109 static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 };
110 static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 };
111 static const uint8_t white_yuva_color[4] = { 255, 127, 127, 255 };
112 static const uint8_t white_gbrp_color[4] = { 255, 255, 255, 255 };
113 
114 static int config_input(AVFilterLink *inlink)
115 {
116  HistogramContext *h = inlink->dst->priv;
117  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
118 
119  h->ncomp = desc->nb_components;
120 
121  switch (inlink->format) {
122  case AV_PIX_FMT_GBRP:
125  break;
126  default:
129  }
130 
131  return 0;
132 }
133 
134 static int config_output(AVFilterLink *outlink)
135 {
136  AVFilterContext *ctx = outlink->src;
137  HistogramContext *h = ctx->priv;
138 
139  switch (h->mode) {
140  case MODE_LEVELS:
141  outlink->w = 256;
142  outlink->h = (h->level_height + h->scale_height) * FFMAX(h->ncomp * h->display_mode, 1);
143  break;
144  case MODE_WAVEFORM:
145  if (h->waveform_mode)
146  outlink->h = 256 * FFMAX(h->ncomp * h->display_mode, 1);
147  else
148  outlink->w = 256 * FFMAX(h->ncomp * h->display_mode, 1);
149  break;
150  case MODE_COLOR:
151  case MODE_COLOR2:
152  outlink->h = outlink->w = 256;
153  break;
154  default:
155  av_assert0(0);
156  }
157 
158  outlink->sample_aspect_ratio = (AVRational){1,1};
159 
160  return 0;
161 }
162 
163 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
164 {
165  HistogramContext *h = inlink->dst->priv;
166  AVFilterContext *ctx = inlink->dst;
167  AVFilterLink *outlink = ctx->outputs[0];
168  AVFrame *out;
169  const uint8_t *src;
170  uint8_t *dst;
171  int i, j, k, l;
172 
173  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
174  if (!out) {
175  av_frame_free(&in);
176  return AVERROR(ENOMEM);
177  }
178 
179  out->pts = in->pts;
180 
181  for (k = 0; k < h->ncomp; k++)
182  for (i = 0; i < outlink->h; i++)
183  memset(out->data[k] + i * out->linesize[k], h->bg_color[k], outlink->w);
184 
185  switch (h->mode) {
186  case MODE_LEVELS:
187  for (k = 0; k < h->ncomp; k++) {
188  int start = k * (h->level_height + h->scale_height) * h->display_mode;
189 
190  for (i = 0; i < in->height; i++) {
191  src = in->data[k] + i * in->linesize[k];
192  for (j = 0; j < in->width; j++)
193  h->histogram[src[j]]++;
194  }
195 
196  for (i = 0; i < 256; i++)
197  h->max_hval = FFMAX(h->max_hval, h->histogram[i]);
198 
199  for (i = 0; i < outlink->w; i++) {
200  int col_height = h->level_height - (h->histogram[i] * (int64_t)h->level_height + h->max_hval - 1) / h->max_hval;
201 
202  for (j = h->level_height - 1; j >= col_height; j--) {
203  if (h->display_mode) {
204  for (l = 0; l < h->ncomp; l++)
205  out->data[l][(j + start) * out->linesize[l] + i] = h->fg_color[l];
206  } else {
207  out->data[k][(j + start) * out->linesize[k] + i] = 255;
208  }
209  }
210  for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--)
211  out->data[k][(j + start) * out->linesize[k] + i] = i;
212  }
213 
214  memset(h->histogram, 0, 256 * sizeof(unsigned));
215  h->max_hval = 0;
216  }
217  break;
218  case MODE_WAVEFORM:
219  if (h->waveform_mode) {
220  for (k = 0; k < h->ncomp; k++) {
221  int offset = k * 256 * h->display_mode;
222  for (i = 0; i < inlink->w; i++) {
223  for (j = 0; j < inlink->h; j++) {
224  int pos = (offset +
225  in->data[k][j * in->linesize[k] + i]) *
226  out->linesize[k] + i;
227  unsigned value = out->data[k][pos];
228  value = FFMIN(value + h->step, 255);
229  out->data[k][pos] = value;
230  }
231  }
232  }
233  } else {
234  for (k = 0; k < h->ncomp; k++) {
235  int offset = k * 256 * h->display_mode;
236  for (i = 0; i < inlink->h; i++) {
237  src = in ->data[k] + i * in ->linesize[k];
238  dst = out->data[k] + i * out->linesize[k];
239  for (j = 0; j < inlink->w; j++) {
240  int pos = src[j] + offset;
241  unsigned value = dst[pos];
242  value = FFMIN(value + h->step, 255);
243  dst[pos] = value;
244  }
245  }
246  }
247  }
248  break;
249  case MODE_COLOR:
250  for (i = 0; i < inlink->h; i++) {
251  int iw1 = i * in->linesize[1];
252  int iw2 = i * in->linesize[2];
253  for (j = 0; j < inlink->w; j++) {
254  int pos = in->data[1][iw1 + j] * out->linesize[0] + in->data[2][iw2 + j];
255  if (out->data[0][pos] < 255)
256  out->data[0][pos]++;
257  }
258  }
259  for (i = 0; i < 256; i++) {
260  dst = out->data[0] + i * out->linesize[0];
261  for (j = 0; j < 256; j++) {
262  if (!dst[j]) {
263  out->data[1][i * out->linesize[0] + j] = i;
264  out->data[2][i * out->linesize[0] + j] = j;
265  }
266  }
267  }
268  break;
269  case MODE_COLOR2:
270  for (i = 0; i < inlink->h; i++) {
271  int iw1 = i * in->linesize[1];
272  int iw2 = i * in->linesize[2];
273  for (j = 0; j < inlink->w; j++) {
274  int u = in->data[1][iw1 + j];
275  int v = in->data[2][iw2 + j];
276  int pos = u * out->linesize[0] + v;
277  if (!out->data[0][pos])
278  out->data[0][pos] = FFABS(128 - u) + FFABS(128 - v);
279  out->data[1][pos] = u;
280  out->data[2][pos] = v;
281  }
282  }
283  break;
284  default:
285  av_assert0(0);
286  }
287 
288  av_frame_free(&in);
289  return ff_filter_frame(outlink, out);
290 }
291 
292 static const AVFilterPad inputs[] = {
293  {
294  .name = "default",
295  .type = AVMEDIA_TYPE_VIDEO,
296  .filter_frame = filter_frame,
297  .config_props = config_input,
298  },
299  { NULL }
300 };
301 
302 static const AVFilterPad outputs[] = {
303  {
304  .name = "default",
305  .type = AVMEDIA_TYPE_VIDEO,
306  .config_props = config_output,
307  },
308  { NULL }
309 };
310 
312  .name = "histogram",
313  .description = NULL_IF_CONFIG_SMALL("Compute and draw a histogram."),
314  .priv_size = sizeof(HistogramContext),
316  .inputs = inputs,
317  .outputs = outputs,
318  .priv_class = &histogram_class,
319 };
Definition: start.py:1
HistogramMode
Definition: vf_histogram.c:30
float v
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:1778
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVOption.
Definition: opt.h:251
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:73
external API header
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip in
Definition: git-howto.txt:5
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:143
unsigned max_hval
Definition: vf_histogram.c:42
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:308
enum HistogramMode mode
Definition: vf_histogram.c:40
const char * name
Pad name.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static const uint8_t black_gbrp_color[4]
Definition: vf_histogram.c:110
uint8_t
it can be given away to ff_start_frame *A reference passed to ff_filter_frame(or the deprecated ff_start_frame) is given away and must no longer be used.*A reference created with avfilter_ref_buffer belongs to the code that created it.*A reference obtained with ff_get_video_buffer or ff_get_audio_buffer belongs to the code that requested it.*A reference given as return value by the get_video_buffer or get_audio_buffer method is given away and must no longer be used.Link reference fields---------------------The AVFilterLink structure has a few AVFilterBufferRef fields.The cur_buf and out_buf were used with the deprecated start_frame/draw_slice/end_frame API and should no longer be used.src_buf
mode
Definition: f_perms.c:27
AVOptions.
const uint8_t * bg_color
Definition: vf_histogram.c:44
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:159
static const AVFilterPad inputs[]
Definition: vf_histogram.c:292
static int config_input(AVFilterLink *inlink)
Definition: vf_histogram.c:114
void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:545
static const AVFilterPad outputs[]
Definition: vf_histogram.c:302
static enum AVPixelFormat color_pix_fmts[]
Definition: vf_histogram.c:76
A filter pad used for either input or output.
static const uint8_t white_gbrp_color[4]
Definition: vf_histogram.c:112
int width
width and height of the video frame
Definition: frame.h:122
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void * priv
private data for use by the filter
Definition: avfilter.h:545
simple assert() macros that are a bit more flexible than ISO C assert().
#define OFFSET(x)
Definition: vf_histogram.c:53
static const uint8_t offset[127][2]
Definition: vf_spp.c:70
#define FFMAX(a, b)
Definition: common.h:56
unsigned histogram[256]
Definition: vf_histogram.c:41
struct AVRational AVRational
rational number numerator/denominator
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:57
#define FFMIN(a, b)
Definition: common.h:58
struct HistogramContext HistogramContext
const uint8_t * fg_color
Definition: vf_histogram.c:45
#define FFABS(a)
Definition: common.h:53
float u
static enum AVPixelFormat levels_pix_fmts[]
Definition: vf_histogram.c:81
static const AVOption histogram_options[]
Definition: vf_histogram.c:56
for k
NULL
Definition: eval.c:55
AVS_Value src
Definition: avisynth_c.h:523
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:218
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:55
static int config_output(AVFilterLink *outlink)
Definition: vf_histogram.c:134
double value
Definition: eval.c:82
Describe the class of an AVClass context structure.
Definition: log.h:50
Filter definition.
Definition: avfilter.h:436
synthesis window for stochastic i
static const uint8_t white_yuva_color[4]
Definition: vf_histogram.c:111
const char * name
filter name
Definition: avfilter.h:437
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:539
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
Y , 8bpp.
Definition: pixfmt.h:76
AVFILTER_DEFINE_CLASS(histogram)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_...
Definition: pixfmt.h:82
#define FLAGS
Definition: vf_histogram.c:54
static int query_formats(AVFilterContext *ctx)
Definition: vf_histogram.c:86
static const uint8_t black_yuva_color[4]
Definition: vf_histogram.c:109
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_histogram.c:163
An instance of a filter.
Definition: avfilter.h:524
int height
Definition: frame.h:122
void INT64 start
Definition: avisynth_c.h:594
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
AVFilter avfilter_vf_histogram
Definition: vf_histogram.c:311
internal API functions
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
for(j=16;j >0;--j)