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 FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * audio volume filter
25  */
26 
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 #define F AV_OPT_FLAG_FILTERING_PARAM
45 
46 static const AVOption volume_options[] = {
47  { "volume", "set volume adjustment",
48  OFFSET(volume), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 0, 0x7fffff, A|F },
49  { "precision", "select mathematical precision",
50  OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A|F, "precision" },
51  { "fixed", "select 8-bit fixed-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED }, INT_MIN, INT_MAX, A|F, "precision" },
52  { "float", "select 32-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT }, INT_MIN, INT_MAX, A|F, "precision" },
53  { "double", "select 64-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A|F, "precision" },
54  { NULL },
55 };
56 
58 
59 static av_cold int init(AVFilterContext *ctx)
60 {
61  VolumeContext *vol = ctx->priv;
62 
63  if (vol->precision == PRECISION_FIXED) {
64  vol->volume_i = (int)(vol->volume * 256 + 0.5);
65  vol->volume = vol->volume_i / 256.0;
66  av_log(ctx, AV_LOG_VERBOSE, "volume:(%d/256)(%f)(%1.2fdB) precision:fixed\n",
67  vol->volume_i, vol->volume, 20.0*log(vol->volume)/M_LN10);
68  } else {
69  av_log(ctx, AV_LOG_VERBOSE, "volume:(%f)(%1.2fdB) precision:%s\n",
70  vol->volume, 20.0*log(vol->volume)/M_LN10,
71  precision_str[vol->precision]);
72  }
73 
74  return 0;
75 }
76 
78 {
79  VolumeContext *vol = ctx->priv;
82  static const enum AVSampleFormat sample_fmts[][7] = {
83  [PRECISION_FIXED] = {
91  },
92  [PRECISION_FLOAT] = {
95  AV_SAMPLE_FMT_NONE
96  },
97  [PRECISION_DOUBLE] = {
100  AV_SAMPLE_FMT_NONE
101  }
102  };
103 
104  layouts = ff_all_channel_layouts();
105  if (!layouts)
106  return AVERROR(ENOMEM);
107  ff_set_common_channel_layouts(ctx, layouts);
108 
109  formats = ff_make_format_list(sample_fmts[vol->precision]);
110  if (!formats)
111  return AVERROR(ENOMEM);
112  ff_set_common_formats(ctx, formats);
113 
114  formats = ff_all_samplerates();
115  if (!formats)
116  return AVERROR(ENOMEM);
117  ff_set_common_samplerates(ctx, formats);
118 
119  return 0;
120 }
121 
122 static inline void scale_samples_u8(uint8_t *dst, const uint8_t *src,
123  int nb_samples, int volume)
124 {
125  int i;
126  for (i = 0; i < nb_samples; i++)
127  dst[i] = av_clip_uint8(((((int64_t)src[i] - 128) * volume + 128) >> 8) + 128);
128 }
129 
130 static inline void scale_samples_u8_small(uint8_t *dst, const uint8_t *src,
131  int nb_samples, int volume)
132 {
133  int i;
134  for (i = 0; i < nb_samples; i++)
135  dst[i] = av_clip_uint8((((src[i] - 128) * volume + 128) >> 8) + 128);
136 }
137 
138 static inline void scale_samples_s16(uint8_t *dst, const uint8_t *src,
139  int nb_samples, int volume)
140 {
141  int i;
142  int16_t *smp_dst = (int16_t *)dst;
143  const int16_t *smp_src = (const int16_t *)src;
144  for (i = 0; i < nb_samples; i++)
145  smp_dst[i] = av_clip_int16(((int64_t)smp_src[i] * volume + 128) >> 8);
146 }
147 
148 static inline void scale_samples_s16_small(uint8_t *dst, const uint8_t *src,
149  int nb_samples, int volume)
150 {
151  int i;
152  int16_t *smp_dst = (int16_t *)dst;
153  const int16_t *smp_src = (const int16_t *)src;
154  for (i = 0; i < nb_samples; i++)
155  smp_dst[i] = av_clip_int16((smp_src[i] * volume + 128) >> 8);
156 }
157 
158 static inline void scale_samples_s32(uint8_t *dst, const uint8_t *src,
159  int nb_samples, int volume)
160 {
161  int i;
162  int32_t *smp_dst = (int32_t *)dst;
163  const int32_t *smp_src = (const int32_t *)src;
164  for (i = 0; i < nb_samples; i++)
165  smp_dst[i] = av_clipl_int32((((int64_t)smp_src[i] * volume + 128) >> 8));
166 }
167 
168 static void volume_init(VolumeContext *vol)
169 {
170  vol->samples_align = 1;
171 
172  switch (av_get_packed_sample_fmt(vol->sample_fmt)) {
173  case AV_SAMPLE_FMT_U8:
174  if (vol->volume_i < 0x1000000)
176  else
178  break;
179  case AV_SAMPLE_FMT_S16:
180  if (vol->volume_i < 0x10000)
182  else
184  break;
185  case AV_SAMPLE_FMT_S32:
187  break;
188  case AV_SAMPLE_FMT_FLT:
189  avpriv_float_dsp_init(&vol->fdsp, 0);
190  vol->samples_align = 4;
191  break;
192  case AV_SAMPLE_FMT_DBL:
193  avpriv_float_dsp_init(&vol->fdsp, 0);
194  vol->samples_align = 8;
195  break;
196  }
197 
198  if (ARCH_X86)
199  ff_volume_init_x86(vol);
200 }
201 
202 static int config_output(AVFilterLink *outlink)
203 {
204  AVFilterContext *ctx = outlink->src;
205  VolumeContext *vol = ctx->priv;
206  AVFilterLink *inlink = ctx->inputs[0];
207 
208  vol->sample_fmt = inlink->format;
210  vol->planes = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1;
211 
212  volume_init(vol);
213 
214  return 0;
215 }
216 
217 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
218 {
219  VolumeContext *vol = inlink->dst->priv;
220  AVFilterLink *outlink = inlink->dst->outputs[0];
221  int nb_samples = buf->nb_samples;
222  AVFrame *out_buf;
223 
224  if (vol->volume == 1.0 || vol->volume_i == 256)
225  return ff_filter_frame(outlink, buf);
226 
227  /* do volume scaling in-place if input buffer is writable */
228  if (av_frame_is_writable(buf)) {
229  out_buf = buf;
230  } else {
231  out_buf = ff_get_audio_buffer(inlink, nb_samples);
232  if (!out_buf)
233  return AVERROR(ENOMEM);
234  av_frame_copy_props(out_buf, buf);
235  }
236 
237  if (vol->precision != PRECISION_FIXED || vol->volume_i > 0) {
238  int p, plane_samples;
239 
241  plane_samples = FFALIGN(nb_samples, vol->samples_align);
242  else
243  plane_samples = FFALIGN(nb_samples * vol->channels, vol->samples_align);
244 
245  if (vol->precision == PRECISION_FIXED) {
246  for (p = 0; p < vol->planes; p++) {
247  vol->scale_samples(out_buf->extended_data[p],
248  buf->extended_data[p], plane_samples,
249  vol->volume_i);
250  }
252  for (p = 0; p < vol->planes; p++) {
253  vol->fdsp.vector_fmul_scalar((float *)out_buf->extended_data[p],
254  (const float *)buf->extended_data[p],
255  vol->volume, plane_samples);
256  }
257  } else {
258  for (p = 0; p < vol->planes; p++) {
259  vol->fdsp.vector_dmul_scalar((double *)out_buf->extended_data[p],
260  (const double *)buf->extended_data[p],
261  vol->volume, plane_samples);
262  }
263  }
264  }
265 
266  if (buf != out_buf)
267  av_frame_free(&buf);
268 
269  return ff_filter_frame(outlink, out_buf);
270 }
271 
273  {
274  .name = "default",
275  .type = AVMEDIA_TYPE_AUDIO,
276  .filter_frame = filter_frame,
277  },
278  { NULL }
279 };
280 
282  {
283  .name = "default",
284  .type = AVMEDIA_TYPE_AUDIO,
285  .config_props = config_output,
286  },
287  { NULL }
288 };
289 
291  .name = "volume",
292  .description = NULL_IF_CONFIG_SMALL("Change input volume."),
293  .query_formats = query_formats,
294  .priv_size = sizeof(VolumeContext),
295  .priv_class = &volume_class,
296  .init = init,
297  .inputs = avfilter_af_volume_inputs,
298  .outputs = avfilter_af_volume_outputs,
299 };
static void volume_init(VolumeContext *vol)
Definition: af_volume.c:168
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:424
#define A
Definition: af_volume.c:43
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVOption.
Definition: opt.h:251
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:117
external API header
enum PrecisionType precision
Definition: af_volume.h:41
AVFloatDSPContext fdsp
Definition: af_volume.h:40
static av_cold int init(AVFilterContext *ctx)
Definition: af_volume.c:59
signed 16 bits
Definition: samplefmt.h:52
#define FFALIGN(x, a)
Definition: common.h:63
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:308
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:532
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
#define av_cold
Definition: attributes.h:78
AVOptions.
int samples_align
Definition: af_volume.h:50
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
signed 32 bits, planar
Definition: samplefmt.h:59
static const AVClass volume_class
Definition: af_volume.c:57
float, planar
Definition: samplefmt.h:60
static void scale_samples_s32(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:158
A filter pad used for either input or output.
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:84
audio volume filter
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:84
#define ARCH_X86
Definition: config.h:35
#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
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:361
void av_log(void *avcl, int level, const char *fmt,...)
Send the specified message to the log if the level is less than or equal to the current av_log_level...
Definition: log.c:246
static int query_formats(AVFilterContext *ctx)
Definition: af_volume.c:77
signed 32 bits
Definition: samplefmt.h:53
#define F
Definition: af_volume.c:44
#define AV_LOG_VERBOSE
Definition: log.h:157
static void scale_samples_s16(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:138
audio channel layout utility functions
static void scale_samples_u8_small(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:130
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition: samplefmt.c:73
static const AVFilterPad avfilter_af_volume_outputs[]
Definition: af_volume.c:281
static void scale_samples_u8(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:122
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (...
Definition: formats.c:402
A list of supported channel layouts.
Definition: formats.h:85
double volume
Definition: af_volume.h:42
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:134
enum AVSampleFormat sample_fmt
Definition: af_volume.h:46
NULL
Definition: eval.c:55
AVS_Value src
Definition: avisynth_c.h:523
void * buf
Definition: avisynth_c.h:594
Filter definition.
Definition: avfilter.h:436
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:118
synthesis window for stochastic i
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:69
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
static const AVOption volume_options[]
Definition: af_volume.c:46
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:539
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:396
static void scale_samples_s16_small(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.c:148
static const char * precision_str[]
Definition: af_volume.c:38
#define M_LN10
Definition: mathematics.h:37
void ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:533
void ff_volume_init_x86(VolumeContext *vol)
static const AVFilterPad avfilter_af_volume_inputs[]
Definition: af_volume.c:272
common internal and external API header
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common formats
Definition: swscale.txt:33
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
Definition: af_volume.c:217
AVSampleFormat
Audio Sample Formats.
Definition: samplefmt.h:49
unsigned 8 bits
Definition: samplefmt.h:51
unsigned 8 bits, planar
Definition: samplefmt.h:57
#define AVFILTER_DEFINE_CLASS(fname)
#define OFFSET(x)
Definition: af_volume.c:42
struct VolumeContext VolumeContext
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:524
signed 16 bits, planar
Definition: samplefmt.h:58
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:700
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:526
void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact)
Initialize a float DSP context.
Definition: float_dsp.c:118
internal API functions
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:117
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:127
double, planar
Definition: samplefmt.h:61
AVFilter avfilter_af_volume
Definition: af_volume.c:290
void(* scale_samples)(uint8_t *dst, const uint8_t *src, int nb_samples, int volume)
Definition: af_volume.h:48
simple arithmetic expression evaluator
static int config_output(AVFilterLink *outlink)
Definition: af_volume.c:202