af_volume.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Stefano Sabatini
3  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
27 #include "libavutil/audioconvert.h"
28 #include "libavutil/common.h"
29 #include "libavutil/eval.h"
30 #include "libavutil/float_dsp.h"
31 #include "libavutil/opt.h"
32 #include "audio.h"
33 #include "avfilter.h"
34 #include "formats.h"
35 #include "internal.h"
36 #include "af_volume.h"
37 
38 static const char *precision_str[] = {
39  "fixed", "float", "double"
40 };
41 
42 #define OFFSET(x) offsetof(VolumeContext, x)
43 #define A AV_OPT_FLAG_AUDIO_PARAM
44 
45 static const AVOption options[] = {
46  { "volume", "Volume adjustment.",
47  OFFSET(volume), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 0, 0x7fffff, A },
48  { "precision", "Mathematical precision.",
49  OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A, "precision" },
50  { "fixed", "8-bit fixed-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED }, INT_MIN, INT_MAX, A, "precision" },
51  { "float", "32-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT }, INT_MIN, INT_MAX, A, "precision" },
52  { "double", "64-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A, "precision" },
53  { NULL },
54 };
55 
56 static const AVClass volume_class = {
57  .class_name = "volume filter",
58  .item_name = av_default_item_name,
59  .option = options,
60  .version = LIBAVUTIL_VERSION_INT,
61 };
62 
63 static av_cold int init(AVFilterContext *ctx, const char *args)
64 {
65  VolumeContext *vol = ctx->priv;
66  int ret;
67 
68  vol->class = &volume_class;
70 
71  if ((ret = av_set_options_string(vol, args, "=", ":")) < 0) {
72  av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
73  return ret;
74  }
75 
76  if (vol->precision == PRECISION_FIXED) {
77  vol->volume_i = (int)(vol->volume * 256 + 0.5);
78  vol->volume = vol->volume_i / 256.0;
79  av_log(ctx, AV_LOG_VERBOSE, "volume:(%d/256)(%f)(%1.2fdB) precision:fixed\n",
80  vol->volume_i, vol->volume, 20.0*log(vol->volume)/M_LN10);
81  } else {
82  av_log(ctx, AV_LOG_VERBOSE, "volume:(%f)(%1.2fdB) precision:%s\n",
83  vol->volume, 20.0*log(vol->volume)/M_LN10,
84  precision_str[vol->precision]);
85  }
86 
87  av_opt_free(vol);
88  return ret;
89 }
90 
92 {
93  VolumeContext *vol = ctx->priv;
96  static const enum AVSampleFormat sample_fmts[][7] = {
97  /* PRECISION_FIXED */
98  {
106  },
107  /* PRECISION_FLOAT */
108  {
112  },
113  /* PRECISION_DOUBLE */
114  {
118  }
119  };
120 
121  layouts = ff_all_channel_layouts();
122  if (!layouts)
123  return AVERROR(ENOMEM);
124  ff_set_common_channel_layouts(ctx, layouts);
125 
126  formats = ff_make_format_list(sample_fmts[vol->precision]);
127  if (!formats)
128  return AVERROR(ENOMEM);
129  ff_set_common_formats(ctx, formats);
130 
131  formats = ff_all_samplerates();
132  if (!formats)
133  return AVERROR(ENOMEM);
134  ff_set_common_samplerates(ctx, formats);
135 
136  return 0;
137 }
138 
139 static inline void scale_samples_u8(uint8_t *dst, const uint8_t *src,
140  int nb_samples, int volume)
141 {
142  int i;
143  for (i = 0; i < nb_samples; i++)
144  dst[i] = av_clip_uint8(((((int64_t)src[i] - 128) * volume + 128) >> 8) + 128);
145 }
146 
147 static inline void scale_samples_u8_small(uint8_t *dst, const uint8_t *src,
148  int nb_samples, int volume)
149 {
150  int i;
151  for (i = 0; i < nb_samples; i++)
152  dst[i] = av_clip_uint8((((src[i] - 128) * volume + 128) >> 8) + 128);
153 }
154 
155 static inline void scale_samples_s16(uint8_t *dst, const uint8_t *src,
156  int nb_samples, int volume)
157 {
158  int i;
159  int16_t *smp_dst = (int16_t *)dst;
160  const int16_t *smp_src = (const int16_t *)src;
161  for (i = 0; i < nb_samples; i++)
162  smp_dst[i] = av_clip_int16(((int64_t)smp_src[i] * volume + 128) >> 8);
163 }
164 
165 static inline void scale_samples_s16_small(uint8_t *dst, const uint8_t *src,
166  int nb_samples, int volume)
167 {
168  int i;
169  int16_t *smp_dst = (int16_t *)dst;
170  const int16_t *smp_src = (const int16_t *)src;
171  for (i = 0; i < nb_samples; i++)
172  smp_dst[i] = av_clip_int16((smp_src[i] * volume + 128) >> 8);
173 }
174 
175 static inline void scale_samples_s32(uint8_t *dst, const uint8_t *src,
176  int nb_samples, int volume)
177 {
178  int i;
179  int32_t *smp_dst = (int32_t *)dst;
180  const int32_t *smp_src = (const int32_t *)src;
181  for (i = 0; i < nb_samples; i++)
182  smp_dst[i] = av_clipl_int32((((int64_t)smp_src[i] * volume + 128) >> 8));
183 }
184 
185 
186 
187 static void volume_init(VolumeContext *vol)
188 {
189  vol->samples_align = 1;
190 
191  switch (av_get_packed_sample_fmt(vol->sample_fmt)) {
192  case AV_SAMPLE_FMT_U8:
193  if (vol->volume_i < 0x1000000)
195  else
197  break;
198  case AV_SAMPLE_FMT_S16:
199  if (vol->volume_i < 0x10000)
201  else
203  break;
204  case AV_SAMPLE_FMT_S32:
206  break;
207  case AV_SAMPLE_FMT_FLT:
208  avpriv_float_dsp_init(&vol->fdsp, 0);
209  vol->samples_align = 4;
210  break;
211  case AV_SAMPLE_FMT_DBL:
212  avpriv_float_dsp_init(&vol->fdsp, 0);
213  vol->samples_align = 8;
214  break;
215  }
216 
217  if (ARCH_X86)
218  ff_volume_init_x86(vol);
219 }
220 
221 static int config_output(AVFilterLink *outlink)
222 {
223  AVFilterContext *ctx = outlink->src;
224  VolumeContext *vol = ctx->priv;
225  AVFilterLink *inlink = ctx->inputs[0];
226 
227  vol->sample_fmt = inlink->format;
229  vol->planes = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1;
230 
231  volume_init(vol);
232 
233  return 0;
234 }
235 
236 static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
237 {
238  VolumeContext *vol = inlink->dst->priv;
239  AVFilterLink *outlink = inlink->dst->outputs[0];
240  int nb_samples = buf->audio->nb_samples;
241  AVFilterBufferRef *out_buf;
242 
243  if (vol->volume == 1.0 || vol->volume_i == 256)
244  return ff_filter_frame(outlink, buf);
245 
246  /* do volume scaling in-place if input buffer is writable */
247  if (buf->perms & AV_PERM_WRITE) {
248  out_buf = buf;
249  } else {
250  out_buf = ff_get_audio_buffer(inlink, AV_PERM_WRITE, nb_samples);
251  if (!out_buf)
252  return AVERROR(ENOMEM);
253  out_buf->pts = buf->pts;
254  }
255 
256  if (vol->precision != PRECISION_FIXED || vol->volume_i > 0) {
257  int p, plane_samples;
258 
260  plane_samples = FFALIGN(nb_samples, vol->samples_align);
261  else
262  plane_samples = FFALIGN(nb_samples * vol->channels, vol->samples_align);
263 
264  if (vol->precision == PRECISION_FIXED) {
265  for (p = 0; p < vol->planes; p++) {
266  vol->scale_samples(out_buf->extended_data[p],
267  buf->extended_data[p], plane_samples,
268  vol->volume_i);
269  }
271  for (p = 0; p < vol->planes; p++) {
272  vol->fdsp.vector_fmul_scalar((float *)out_buf->extended_data[p],
273  (const float *)buf->extended_data[p],
274  vol->volume, plane_samples);
275  }
276  } else {
277  for (p = 0; p < vol->planes; p++) {
278  vol->fdsp.vector_dmul_scalar((double *)out_buf->extended_data[p],
279  (const double *)buf->extended_data[p],
280  vol->volume, plane_samples);
281  }
282  }
283  }
284 
285  if (buf != out_buf)
287 
288  return ff_filter_frame(outlink, out_buf);
289 }
290 
292  {
293  .name = "default",
294  .type = AVMEDIA_TYPE_AUDIO,
295  .filter_frame = filter_frame,
296  },
297  { NULL }
298 };
299 
301  {
302  .name = "default",
303  .type = AVMEDIA_TYPE_AUDIO,
304  .config_props = config_output,
305  },
306  { NULL }
307 };
308 
310  .name = "volume",
311  .description = NULL_IF_CONFIG_SMALL("Change input volume."),
312  .query_formats = query_formats,
313  .priv_size = sizeof(VolumeContext),
314  .init = init,
315  .inputs = avfilter_af_volume_inputs,
316  .outputs = avfilter_af_volume_outputs,
317 };
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: avfilter.h:156
static av_cold int init(AVFilterContext *ctx, const char *args)
Definition: af_volume.c:63
static void volume_init(VolumeContext *vol)
Definition: af_volume.c:187
AVFilterBufferRef * ff_get_audio_buffer(AVFilterLink *link, int perms, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:63
#define A
Definition: af_volume.c:43
int nb_samples
number of audio samples
Definition: avfilter.h:111
AVOption.
Definition: opt.h:233
AVFilterBufferRefAudioProps * audio
audio buffer specific properties
Definition: avfilter.h:160
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:122
static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
Definition: af_volume.c:236
enum PrecisionType precision
Definition: af_volume.h:41
void av_opt_set_defaults(void *s)
Set the values of all AVOption fields to their default values.
Definition: opt.c:505
int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:459
AVFloatDSPContext fdsp
Definition: af_volume.h:40
int av_set_options_string(void *ctx, const char *opts, const char *key_val_sep, const char *pairs_sep)
Parse the key/value pairs list in opts.
Definition: opt.c:587
static enum AVSampleFormat formats[]
signed 16 bits
Definition: samplefmt.h:52
void avfilter_unref_buffer(AVFilterBufferRef *ref)
Remove a reference to a buffer.
Definition: buffer.c:75
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:165
const char * name
Pad name.
Definition: internal.h:39
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:38
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:426
uint8_t
AV_SAMPLE_FMT_U8
AVOptions.
int samples_align
Definition: af_volume.h:50
void(* scale_samples)(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.h:48
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:375
signed 32 bits, planar
Definition: samplefmt.h:59
static const AVOption options[]
Definition: af_volume.c:45
static const AVClass volume_class
Definition: af_volume.c:56
float, planar
Definition: samplefmt.h:60
int64_t pts
presentation timestamp.
Definition: avfilter.h:167
static void scale_samples_s32(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:175
A filter pad used for either input or output.
Definition: internal.h:33
audio volume filter
sample_fmts
Definition: avconv_filter.c:63
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:88
void * priv
private data for use by the filter
Definition: avfilter.h:439
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:146
void(* vector_dmul_scalar)(double *dst, const double *src, double mul, int len)
Multiply a vector of double by a scalar double.
Definition: float_dsp.h:82
static int query_formats(AVFilterContext *ctx)
Definition: af_volume.c:91
signed 32 bits
Definition: samplefmt.h:53
static void scale_samples_s16(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:155
static void scale_samples_u8_small(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:147
int32_t
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition: samplefmt.c:64
void(* vector_fmul_scalar)(float *dst, const float *src, float mul, int len)
Multiply a vector of floats by a scalar float.
Definition: float_dsp.h:67
static const AVFilterPad avfilter_af_volume_outputs[]
Definition: af_volume.c:300
static void scale_samples_u8(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:139
LIBAVUTIL_VERSION_INT
Definition: eval.c:52
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout/sa...
Definition: formats.c:244
double volume
Definition: af_volume.h:42
enum AVSampleFormat sample_fmt
Definition: af_volume.h:46
A reference to an AVFilterBuffer.
Definition: avfilter.h:139
NULL
Definition: eval.c:52
AV_SAMPLE_FMT_NONE
Definition: avconv_filter.c:63
int perms
permissions, see the AV_PERM_* flags
Definition: avfilter.h:172
av_default_item_name
Definition: dnxhdenc.c:43
out nb_samples
Describe the class of an AVClass context structure.
Definition: log.h:33
Filter definition.
Definition: avfilter.h:371
static const AVFilterPad inputs[]
Definition: af_ashowinfo.c:110
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:101
const char * name
filter name
Definition: avfilter.h:372
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:433
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:433
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:238
static void scale_samples_s16_small(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:165
static const char * precision_str[]
Definition: af_volume.c:38
void ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:363
void av_opt_free(void *obj)
Free all string and binary options in obj.
Definition: opt.c:607
void ff_volume_init_x86(VolumeContext *vol)
static const AVFilterPad avfilter_af_volume_inputs[]
Definition: af_volume.c:291
common internal and external API header
#define ARCH_X86
Definition: config.h:33
AVSampleFormat
Audio Sample Formats.
Definition: samplefmt.h:49
#define AV_PERM_WRITE
can write to the buffer
Definition: avfilter.h:98
unsigned 8 bits, planar
Definition: samplefmt.h:57
#define OFFSET(x)
Definition: af_volume.c:42
struct VolumeContext VolumeContext
int format
media format
Definition: avfilter.h:170
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:418
signed 16 bits, planar
Definition: samplefmt.h:58
void ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *layouts)
A helper for query_formats() which sets all links to the same list of channel layouts/sample rates...
Definition: formats.c:356
void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact)
Initialize a float DSP context.
Definition: float_dsp.c:55
internal API functions
const AVClass * class
Definition: af_volume.h:39
double, planar
Definition: samplefmt.h:61
AVFilter avfilter_af_volume
Definition: af_volume.c:309
simple arithmetic expression evaluator
static int config_output(AVFilterLink *outlink)
Definition: af_volume.c:221