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 
22 #include "libavutil/eval.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/parseutils.h"
27 #include "avfilter.h"
28 #include "formats.h"
29 #include "audio.h"
30 #include "video.h"
31 #include "internal.h"
32 
33 typedef struct ShowVolumeContext {
34  const AVClass *class;
35  int w, h;
36  int f, b;
38  char *color;
39 
42  int draw_text;
44 
45 #define OFFSET(x) offsetof(ShowVolumeContext, x)
46 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
47 
48 static const AVOption showvolume_options[] = {
49  { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
50  { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
51  { "b", "set border width", OFFSET(b), AV_OPT_TYPE_INT, {.i64=1}, 0, 5, FLAGS },
52  { "w", "set channel width", OFFSET(w), AV_OPT_TYPE_INT, {.i64=400}, 40, 1080, FLAGS },
53  { "h", "set channel height", OFFSET(h), AV_OPT_TYPE_INT, {.i64=20}, 1, 100, FLAGS },
54  { "f", "set fade", OFFSET(f), AV_OPT_TYPE_INT, {.i64=20}, 1, 255, FLAGS },
55  { "c", "set volume color expression", OFFSET(color), AV_OPT_TYPE_STRING, {.str="if(gte(VOLUME,-2), if(gte(VOLUME,-1),0xff0000ff, 0xff00ffff),0xff00ff00)"}, 0, 0, FLAGS },
56  { "t", "display channel names", OFFSET(draw_text), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS },
57  { NULL }
58 };
59 
60 AVFILTER_DEFINE_CLASS(showvolume);
61 
62 static const char *const var_names[] = { "VOLUME", "CHANNEL", NULL };
64 
65 static av_cold int init(AVFilterContext *ctx)
66 {
67  ShowVolumeContext *s = ctx->priv;
68  int ret;
69 
70  if (s->color) {
71  ret = av_expr_parse(&s->c_expr, s->color, var_names,
72  NULL, NULL, NULL, NULL, 0, ctx);
73  if (ret < 0)
74  return ret;
75  }
76 
77  return 0;
78 }
79 
81 {
84  AVFilterLink *inlink = ctx->inputs[0];
85  AVFilterLink *outlink = ctx->outputs[0];
87  static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE };
88 
89  formats = ff_make_format_list(sample_fmts);
90  if (!formats)
91  return AVERROR(ENOMEM);
92  ff_formats_ref(formats, &inlink->out_formats);
93 
94  layouts = ff_all_channel_layouts();
95  if (!layouts)
96  return AVERROR(ENOMEM);
98 
99  formats = ff_all_samplerates();
100  if (!formats)
101  return AVERROR(ENOMEM);
102  ff_formats_ref(formats, &inlink->out_samplerates);
103 
104  formats = ff_make_format_list(pix_fmts);
105  if (!formats)
106  return AVERROR(ENOMEM);
107  ff_formats_ref(formats, &outlink->in_formats);
108 
109  return 0;
110 }
111 
112 static int config_input(AVFilterLink *inlink)
113 {
114  AVFilterContext *ctx = inlink->dst;
115  ShowVolumeContext *s = ctx->priv;
116  int nb_samples;
117 
118  nb_samples = FFMAX(1024, ((double)inlink->sample_rate / av_q2d(s->frame_rate)) + 0.5);
119  inlink->partial_buf_size =
120  inlink->min_samples =
121  inlink->max_samples = nb_samples;
122 
123  return 0;
124 }
125 
126 static int config_output(AVFilterLink *outlink)
127 {
128  ShowVolumeContext *s = outlink->src->priv;
129  AVFilterLink *inlink = outlink->src->inputs[0];
130 
131  outlink->w = s->w;
132  outlink->h = s->h * inlink->channels + (inlink->channels - 1) * s->b;
133  outlink->sample_aspect_ratio = (AVRational){1,1};
134  outlink->frame_rate = s->frame_rate;
135 
136  return 0;
137 }
138 
139 static void drawtext(AVFrame *pic, int x, int y, const char *txt)
140 {
141  const uint8_t *font;
142  int font_height;
143  int i;
144 
145  font = avpriv_cga_font, font_height = 8;
146 
147  for (i = 0; txt[i]; i++) {
148  int char_y, mask;
149  uint8_t *p = pic->data[0] + y*pic->linesize[0] + (x + i*8)*4;
150 
151  for (char_y = 0; char_y < font_height; char_y++) {
152  for (mask = 0x80; mask; mask >>= 1) {
153  if (font[txt[i] * font_height + char_y] & mask)
154  AV_WN32(p, ~AV_RN32(p));
155  p += 4;
156  }
157  p += pic->linesize[0] - 8*4;
158  }
159  }
160 }
161 
162 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
163 {
164  AVFilterContext *ctx = inlink->dst;
165  AVFilterLink *outlink = ctx->outputs[0];
166  ShowVolumeContext *s = ctx->priv;
167  int c, i, j, k;
168  double values[VAR_VARS_NB];
169 
170  if (!s->out || s->out->width != outlink->w ||
171  s->out->height != outlink->h) {
172  av_frame_free(&s->out);
173  s->out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
174  if (!s->out) {
175  av_frame_free(&insamples);
176  return AVERROR(ENOMEM);
177  }
178 
179  for (i = 0; i < outlink->h; i++)
180  memset(s->out->data[0] + i * s->out->linesize[0], 0, outlink->w * 4);
181  }
182  s->out->pts = insamples->pts;
183 
184  for (j = 0; j < outlink->h; j++) {
185  uint8_t *dst = s->out->data[0] + j * s->out->linesize[0];
186  for (k = 0; k < s->w; k++) {
187  dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] - s->f, 0);
188  dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] - s->f, 0);
189  dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] - s->f, 0);
190  dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] - s->f, 0);
191  }
192  }
193 
194  for (c = 0; c < inlink->channels; c++) {
195  float *src = (float *)insamples->extended_data[c];
196  float max = 0;
197  uint32_t color;
198 
199  for (i = 0; i < insamples->nb_samples; i++)
200  max = FFMAX(max, src[i]);
201 
202  max = av_clipf(max, 0, 1);
203  values[VAR_VOLUME] = 20.0 * log(max) / M_LN10;
204  values[VAR_CHANNEL] = c;
205  color = av_expr_eval(s->c_expr, values, NULL);
206 
207  for (j = 0; j < s->h; j++) {
208  uint8_t *dst = s->out->data[0] + (c * s->h + c * s->b + j) * s->out->linesize[0];
209 
210  for (k = 0; k < s->w * max; k++)
211  AV_WN32A(dst + k * 4, color);
212  }
213 
214  if (s->h >= 8 && s->draw_text)
215  drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2,
217  }
218 
219  av_frame_free(&insamples);
220 
221  return ff_filter_frame(outlink, av_frame_clone(s->out));
222 }
223 
224 static av_cold void uninit(AVFilterContext *ctx)
225 {
226  ShowVolumeContext *s = ctx->priv;
227 
228  av_frame_free(&s->out);
229  av_expr_free(s->c_expr);
230 }
231 
232 static const AVFilterPad showvolume_inputs[] = {
233  {
234  .name = "default",
235  .type = AVMEDIA_TYPE_AUDIO,
236  .config_props = config_input,
237  .filter_frame = filter_frame,
238  },
239  { NULL }
240 };
241 
242 static const AVFilterPad showvolume_outputs[] = {
243  {
244  .name = "default",
245  .type = AVMEDIA_TYPE_VIDEO,
246  .config_props = config_output,
247  },
248  { NULL }
249 };
250 
252  .name = "showvolume",
253  .description = NULL_IF_CONFIG_SMALL("Convert input audio volume to video output."),
254  .init = init,
255  .uninit = uninit,
256  .query_formats = query_formats,
257  .priv_size = sizeof(ShowVolumeContext),
258  .inputs = showvolume_inputs,
259  .outputs = showvolume_outputs,
260  .priv_class = &showvolume_class,
261 };
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:171
AVOption.
Definition: opt.h:255
AVFilter ff_avf_showvolume
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:248
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:1125
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:653
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:109
#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:69
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:641
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:417
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1158
static const AVFilterPad showvolume_outputs[]
uint8_t
#define av_cold
Definition: attributes.h:74
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:257
Definition: eval.c:144
#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:63
int width
width and height of the video frame
Definition: frame.h:220
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:148
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:175
void * priv
private data for use by the filter
Definition: avfilter.h:654
#define FFMAX(a, b)
Definition: common.h:79
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:427
audio channel layout utility functions
float y
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:422
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
static const AVFilterPad showvolume_inputs[]
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:385
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:451
A list of supported channel layouts.
Definition: formats.h:85
AVS_Value src
Definition: avisynth_c.h:482
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:313
static int query_formats(AVFilterContext *ctx)
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:199
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:470
static const AVFilterPad inputs[]
Definition: af_ashowinfo.c:239
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:474
#define AV_RN32(p)
Definition: intreadwrite.h:364
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:648
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:209
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:379
#define FLAGS
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:182
#define M_LN10
Definition: mathematics.h:37
#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:708
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:633
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
int height
Definition: frame.h:220
internal API functions
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:215
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:225
for(j=16;j >0;--j)
AVFILTER_DEFINE_CLASS(showvolume)
CGA/EGA/VGA ROM font data.
simple arithmetic expression evaluator