FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
avf_showvolume.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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/avstring.h"
23 #include "libavutil/eval.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/opt.h"
26 #include "libavutil/parseutils.h"
28 #include "avfilter.h"
29 #include "formats.h"
30 #include "audio.h"
31 #include "video.h"
32 #include "internal.h"
33 
34 static const char *const var_names[] = { "VOLUME", "CHANNEL", NULL };
36 
37 typedef struct ShowVolumeContext {
38  const AVClass *class;
39  int w, h;
40  int b;
41  double f;
43  char *color;
44 
47  int draw_text;
49  double *values;
51 
52 #define OFFSET(x) offsetof(ShowVolumeContext, x)
53 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
54 
55 static const AVOption showvolume_options[] = {
56  { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
57  { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
58  { "b", "set border width", OFFSET(b), AV_OPT_TYPE_INT, {.i64=1}, 0, 5, FLAGS },
59  { "w", "set channel width", OFFSET(w), AV_OPT_TYPE_INT, {.i64=400}, 80, 1080, FLAGS },
60  { "h", "set channel height", OFFSET(h), AV_OPT_TYPE_INT, {.i64=20}, 1, 100, FLAGS },
61  { "f", "set fade", OFFSET(f), AV_OPT_TYPE_DOUBLE, {.dbl=0.95}, 0.001, 1, FLAGS },
62  { "c", "set volume color expression", OFFSET(color), AV_OPT_TYPE_STRING, {.str="if(gte(VOLUME,-6), if(gte(VOLUME,-2), if(gte(VOLUME,-1), if(gt(VOLUME,0), 0xff0000ff, 0xff0066ff), 0xff00ffff),0xff00ff00),0xffff0000)"}, 0, 0, FLAGS },
63  { "t", "display channel names", OFFSET(draw_text), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
64  { "v", "display volume value", OFFSET(draw_volume), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
65  { NULL }
66 };
67 
68 AVFILTER_DEFINE_CLASS(showvolume);
69 
71 {
72  ShowVolumeContext *s = ctx->priv;
73  int ret;
74 
75  if (s->color) {
76  ret = av_expr_parse(&s->c_expr, s->color, var_names,
77  NULL, NULL, NULL, NULL, 0, ctx);
78  if (ret < 0)
79  return ret;
80  }
81 
82  return 0;
83 }
84 
86 {
89  AVFilterLink *inlink = ctx->inputs[0];
90  AVFilterLink *outlink = ctx->outputs[0];
92  static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE };
93  int ret;
94 
95  formats = ff_make_format_list(sample_fmts);
96  if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0)
97  return ret;
98 
99  layouts = ff_all_channel_layouts();
100  if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0)
101  return ret;
102 
103  formats = ff_all_samplerates();
104  if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0)
105  return ret;
106 
107  formats = ff_make_format_list(pix_fmts);
108  if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0)
109  return ret;
110 
111  return 0;
112 }
113 
114 static int config_input(AVFilterLink *inlink)
115 {
116  AVFilterContext *ctx = inlink->dst;
117  ShowVolumeContext *s = ctx->priv;
118  int nb_samples;
119 
120  nb_samples = FFMAX(1024, ((double)inlink->sample_rate / av_q2d(s->frame_rate)) + 0.5);
121  inlink->partial_buf_size =
122  inlink->min_samples =
123  inlink->max_samples = nb_samples;
124  s->values = av_calloc(inlink->channels * VAR_VARS_NB, sizeof(double));
125  if (!s->values)
126  return AVERROR(ENOMEM);
127  return 0;
128 }
129 
130 static int config_output(AVFilterLink *outlink)
131 {
132  ShowVolumeContext *s = outlink->src->priv;
133  AVFilterLink *inlink = outlink->src->inputs[0];
134 
135  outlink->w = s->w;
136  outlink->h = s->h * inlink->channels + (inlink->channels - 1) * s->b;
137  outlink->sample_aspect_ratio = (AVRational){1,1};
138  outlink->frame_rate = s->frame_rate;
139 
140  return 0;
141 }
142 
143 static void drawtext(AVFrame *pic, int x, int y, const char *txt)
144 {
145  const uint8_t *font;
146  int font_height;
147  int i;
148 
149  font = avpriv_cga_font, font_height = 8;
150 
151  for (i = 0; txt[i]; i++) {
152  int char_y, mask;
153  uint8_t *p = pic->data[0] + y*pic->linesize[0] + (x + i*8)*4;
154 
155  for (char_y = 0; char_y < font_height; char_y++) {
156  for (mask = 0x80; mask; mask >>= 1) {
157  if (font[txt[i] * font_height + char_y] & mask)
158  AV_WN32(p, ~AV_RN32(p));
159  p += 4;
160  }
161  p += pic->linesize[0] - 8*4;
162  }
163  }
164 }
165 
166 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
167 {
168  AVFilterContext *ctx = inlink->dst;
169  AVFilterLink *outlink = ctx->outputs[0];
170  ShowVolumeContext *s = ctx->priv;
171  int c, i, j, k;
172  AVFrame *out;
173 
174  if (!s->out || s->out->width != outlink->w ||
175  s->out->height != outlink->h) {
176  av_frame_free(&s->out);
177  s->out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
178  if (!s->out) {
179  av_frame_free(&insamples);
180  return AVERROR(ENOMEM);
181  }
182 
183  for (i = 0; i < outlink->h; i++)
184  memset(s->out->data[0] + i * s->out->linesize[0], 0, outlink->w * 4);
185  }
186  s->out->pts = insamples->pts;
187 
188  for (j = 0; j < outlink->h; j++) {
189  uint8_t *dst = s->out->data[0] + j * s->out->linesize[0];
190  for (k = 0; k < s->w; k++) {
191  dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] * s->f, 0);
192  dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] * s->f, 0);
193  dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] * s->f, 0);
194  dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] * s->f, 0);
195  }
196  }
197 
198  for (c = 0; c < inlink->channels; c++) {
199  float *src = (float *)insamples->extended_data[c];
200  float max = 0;
201  uint32_t color;
202 
203  for (i = 0; i < insamples->nb_samples; i++)
204  max = FFMAX(max, src[i]);
205 
206  s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max);
207  max = av_clipf(max, 0, 1);
208  s->values[c * VAR_VARS_NB + VAR_CHANNEL] = c;
209  color = av_expr_eval(s->c_expr, &s->values[c * VAR_VARS_NB], NULL);
210 
211  for (j = 0; j < s->h; j++) {
212  uint8_t *dst = s->out->data[0] + (c * s->h + c * s->b + j) * s->out->linesize[0];
213 
214  for (k = 0; k < s->w * max; k++)
215  AV_WN32A(dst + k * 4, color);
216  }
217 
218  if (s->h >= 8 && s->draw_text)
219  drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2,
221  }
222 
223  av_frame_free(&insamples);
224  out = av_frame_clone(s->out);
225  if (!out)
226  return AVERROR(ENOMEM);
228 
229  for (c = 0; c < inlink->channels && s->draw_volume; c++) {
230  if (s->h >= 8) {
231  char buf[16];
232 
233  snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]);
234  drawtext(out, FFMAX(0, s->w - 8 * (int)strlen(buf)), c * (s->h + s->b) + (s->h - 8) / 2, buf);
235  }
236  }
237 
238  return ff_filter_frame(outlink, out);
239 }
240 
242 {
243  ShowVolumeContext *s = ctx->priv;
244 
245  av_frame_free(&s->out);
246  av_expr_free(s->c_expr);
247  av_freep(&s->values);
248 }
249 
250 static const AVFilterPad showvolume_inputs[] = {
251  {
252  .name = "default",
253  .type = AVMEDIA_TYPE_AUDIO,
254  .config_props = config_input,
255  .filter_frame = filter_frame,
256  },
257  { NULL }
258 };
259 
260 static const AVFilterPad showvolume_outputs[] = {
261  {
262  .name = "default",
263  .type = AVMEDIA_TYPE_VIDEO,
264  .config_props = config_output,
265  },
266  { NULL }
267 };
268 
270  .name = "showvolume",
271  .description = NULL_IF_CONFIG_SMALL("Convert input audio volume to video output."),
272  .init = init,
273  .uninit = uninit,
274  .query_formats = query_formats,
275  .priv_size = sizeof(ShowVolumeContext),
276  .inputs = showvolume_inputs,
277  .outputs = showvolume_outputs,
278  .priv_class = &showvolume_class,
279 };
float, planar
Definition: samplefmt.h:70
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:631
This structure describes decoded (raw) audio or video data.
Definition: frame.h:181
AVOption.
Definition: opt.h:245
AVFilter ff_avf_showvolume
AVFormatContext * ctx
Definition: movenc-test.c:48
Main libavfilter public API header.
const char * b
Definition: vf_curves.c:109
static int draw_text(AVFilterContext *ctx, AVFrame *frame, int width, int height)
Definition: vf_drawtext.c:1137
static enum AVSampleFormat formats[]
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:657
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:76
#define AV_WN32A(p, v)
Definition: intreadwrite.h:538
static const AVOption showvolume_options[]
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
const char * name
Pad name.
Definition: internal.h:59
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:312
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:435
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1163
static const AVFilterPad showvolume_outputs[]
uint8_t
#define av_cold
Definition: attributes.h:82
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:262
Definition: eval.c:148
#define OFFSET(x)
static double av_q2d(AVRational a)
Convert rational to double.
Definition: rational.h:80
AVRational frame_rate
A filter pad used for either input or output.
Definition: internal.h:53
int width
width and height of the video frame
Definition: frame.h:230
const uint8_t avpriv_cga_font[2048]
Definition: xga_font_data.c:29
static const uint16_t mask[17]
Definition: lzw.c:38
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:154
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:176
void * priv
private data for use by the filter
Definition: avfilter.h:319
#define FFMAX(a, b)
Definition: common.h:94
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:95
uint64_t channel_layout
Channel layout of the audio data.
Definition: frame.h:343
audio channel layout utility functions
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:440
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
static const AVFilterPad showvolume_inputs[]
static const AVFilterPad outputs[]
Definition: af_afftfilt.c:385
#define src
Definition: vp9dsp.c:530
static int config_output(AVFilterLink *outlink)
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (w...
Definition: formats.c:401
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:461
A list of supported channel layouts.
Definition: formats.h:85
FILE * out
Definition: movenc-test.c:54
static const AVFilterPad inputs[]
Definition: af_afftfilt.c:375
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:59
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:317
static int query_formats(AVFilterContext *ctx)
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:209
void * buf
Definition: avisynth_c.h:553
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:141
rational number numerator/denominator
Definition: rational.h:43
offset must point to AVRational
Definition: opt.h:235
static av_cold int init(AVFilterContext *ctx)
const char * name
Filter name.
Definition: avfilter.h:145
#define snprintf
Definition: snprintf.h:34
#define AV_RN32(p)
Definition: intreadwrite.h:364
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:316
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:262
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:395
void * av_calloc(size_t nmemb, size_t size)
Allocate a block of nmemb * size bytes with alignment suitable for all memory accesses (including vec...
Definition: mem.c:260
int av_frame_make_writable(AVFrame *frame)
Ensure that the frame data is writable, avoiding data copy if possible.
Definition: frame.c:522
#define FLAGS
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:192
#define AV_WN32(p, v)
Definition: intreadwrite.h:376
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
Get the channel with the given index in channel_layout.
static double c[64]
static int config_input(AVFilterLink *inlink)
static av_cold void uninit(AVFilterContext *ctx)
static const char *const var_names[]
const char * av_get_channel_name(uint64_t channel)
Get the name of a given channel.
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:712
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:304
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
int height
Definition: frame.h:230
#define av_freep(p)
internal API functions
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:225
static void drawtext(AVFrame *pic, int x, int y, const char *txt)
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:235
for(j=16;j >0;--j)
AVFILTER_DEFINE_CLASS(showvolume)
CGA/EGA/VGA ROM font data.
simple arithmetic expression evaluator