2 * Copyright (c) 2011 Stefano Sabatini
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
5 * This file is part of FFmpeg.
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.
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.
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
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/common.h"
29 #include "libavutil/eval.h"
30 #include "libavutil/float_dsp.h"
31 #include "libavutil/intreadwrite.h"
32 #include "libavutil/opt.h"
33 #include "libavutil/replaygain.h"
39 #include "af_volume.h"
41 static const char * const precision_str
[] = {
42 "fixed", "float", "double"
45 static const char *const var_names
[] = {
46 "n", ///< frame number (starting at zero)
47 "nb_channels", ///< number of channels
48 "nb_consumed_samples", ///< number of samples consumed by the filter
49 "nb_samples", ///< number of samples in the current frame
50 "pos", ///< position in the file of the frame
51 "pts", ///< frame presentation timestamp
52 "sample_rate", ///< sample rate
53 "startpts", ///< PTS at start of stream
54 "startt", ///< time at start of stream
55 "t", ///< time in the file of the frame
57 "volume", ///< last set value
61 #define OFFSET(x) offsetof(VolumeContext, x)
62 #define A AV_OPT_FLAG_AUDIO_PARAM
63 #define F AV_OPT_FLAG_FILTERING_PARAM
65 static const AVOption volume_options
[] = {
66 { "volume", "set volume adjustment expression",
67 OFFSET(volume_expr
), AV_OPT_TYPE_STRING
, { .str
= "1.0" }, .flags
= A
|F
},
68 { "precision", "select mathematical precision",
69 OFFSET(precision
), AV_OPT_TYPE_INT
, { .i64
= PRECISION_FLOAT
}, PRECISION_FIXED
, PRECISION_DOUBLE
, A
|F
, "precision" },
70 { "fixed", "select 8-bit fixed-point", 0, AV_OPT_TYPE_CONST
, { .i64
= PRECISION_FIXED
}, INT_MIN
, INT_MAX
, A
|F
, "precision" },
71 { "float", "select 32-bit floating-point", 0, AV_OPT_TYPE_CONST
, { .i64
= PRECISION_FLOAT
}, INT_MIN
, INT_MAX
, A
|F
, "precision" },
72 { "double", "select 64-bit floating-point", 0, AV_OPT_TYPE_CONST
, { .i64
= PRECISION_DOUBLE
}, INT_MIN
, INT_MAX
, A
|F
, "precision" },
73 { "eval", "specify when to evaluate expressions", OFFSET(eval_mode
), AV_OPT_TYPE_INT
, {.i64
= EVAL_MODE_ONCE
}, 0, EVAL_MODE_NB
-1, .flags
= A
|F
, "eval" },
74 { "once", "eval volume expression once", 0, AV_OPT_TYPE_CONST
, {.i64
=EVAL_MODE_ONCE
}, .flags
= A
|F
, .unit
= "eval" },
75 { "frame", "eval volume expression per-frame", 0, AV_OPT_TYPE_CONST
, {.i64
=EVAL_MODE_FRAME
}, .flags
= A
|F
, .unit
= "eval" },
76 { "replaygain", "Apply replaygain side data when present",
77 OFFSET(replaygain
), AV_OPT_TYPE_INT
, { .i64
= REPLAYGAIN_DROP
}, REPLAYGAIN_DROP
, REPLAYGAIN_ALBUM
, A
, "replaygain" },
78 { "drop", "replaygain side data is dropped", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_DROP
}, 0, 0, A
, "replaygain" },
79 { "ignore", "replaygain side data is ignored", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_IGNORE
}, 0, 0, A
, "replaygain" },
80 { "track", "track gain is preferred", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_TRACK
}, 0, 0, A
, "replaygain" },
81 { "album", "album gain is preferred", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_ALBUM
}, 0, 0, A
, "replaygain" },
82 { "replaygain_preamp", "Apply replaygain pre-amplification",
83 OFFSET(replaygain_preamp
), AV_OPT_TYPE_DOUBLE
, { .dbl
= 0.0 }, -15.0, 15.0, A
},
84 { "replaygain_noclip", "Apply replaygain clipping prevention",
85 OFFSET(replaygain_noclip
), AV_OPT_TYPE_INT
, { .i64
= 1 }, 0, 1, A
},
89 AVFILTER_DEFINE_CLASS(volume
);
91 static int set_expr(AVExpr
**pexpr
, const char *expr
, void *log_ctx
)
98 ret
= av_expr_parse(pexpr
, expr
, var_names
,
99 NULL
, NULL
, NULL
, NULL
, 0, log_ctx
);
101 av_log(log_ctx
, AV_LOG_ERROR
,
102 "Error when evaluating the volume expression '%s'\n", expr
);
111 static av_cold
int init(AVFilterContext
*ctx
)
113 VolumeContext
*vol
= ctx
->priv
;
114 return set_expr(&vol
->volume_pexpr
, vol
->volume_expr
, ctx
);
117 static av_cold
void uninit(AVFilterContext
*ctx
)
119 VolumeContext
*vol
= ctx
->priv
;
120 av_expr_free(vol
->volume_pexpr
);
124 static int query_formats(AVFilterContext
*ctx
)
126 VolumeContext
*vol
= ctx
->priv
;
127 AVFilterFormats
*formats
= NULL
;
128 AVFilterChannelLayouts
*layouts
;
129 static const enum AVSampleFormat sample_fmts
[][7] = {
130 [PRECISION_FIXED
] = {
139 [PRECISION_FLOAT
] = {
144 [PRECISION_DOUBLE
] = {
151 layouts
= ff_all_channel_counts();
153 return AVERROR(ENOMEM
);
154 ff_set_common_channel_layouts(ctx
, layouts
);
156 formats
= ff_make_format_list(sample_fmts
[vol
->precision
]);
158 return AVERROR(ENOMEM
);
159 ff_set_common_formats(ctx
, formats
);
161 formats
= ff_all_samplerates();
163 return AVERROR(ENOMEM
);
164 ff_set_common_samplerates(ctx
, formats
);
169 static inline void scale_samples_u8(uint8_t *dst
, const uint8_t *src
,
170 int nb_samples
, int volume
)
173 for (i
= 0; i
< nb_samples
; i
++)
174 dst
[i
] = av_clip_uint8(((((int64_t)src
[i
] - 128) * volume
+ 128) >> 8) + 128);
177 static inline void scale_samples_u8_small(uint8_t *dst
, const uint8_t *src
,
178 int nb_samples
, int volume
)
181 for (i
= 0; i
< nb_samples
; i
++)
182 dst
[i
] = av_clip_uint8((((src
[i
] - 128) * volume
+ 128) >> 8) + 128);
185 static inline void scale_samples_s16(uint8_t *dst
, const uint8_t *src
,
186 int nb_samples
, int volume
)
189 int16_t *smp_dst
= (int16_t *)dst
;
190 const int16_t *smp_src
= (const int16_t *)src
;
191 for (i
= 0; i
< nb_samples
; i
++)
192 smp_dst
[i
] = av_clip_int16(((int64_t)smp_src
[i
] * volume
+ 128) >> 8);
195 static inline void scale_samples_s16_small(uint8_t *dst
, const uint8_t *src
,
196 int nb_samples
, int volume
)
199 int16_t *smp_dst
= (int16_t *)dst
;
200 const int16_t *smp_src
= (const int16_t *)src
;
201 for (i
= 0; i
< nb_samples
; i
++)
202 smp_dst
[i
] = av_clip_int16((smp_src
[i
] * volume
+ 128) >> 8);
205 static inline void scale_samples_s32(uint8_t *dst
, const uint8_t *src
,
206 int nb_samples
, int volume
)
209 int32_t *smp_dst
= (int32_t *)dst
;
210 const int32_t *smp_src
= (const int32_t *)src
;
211 for (i
= 0; i
< nb_samples
; i
++)
212 smp_dst
[i
] = av_clipl_int32((((int64_t)smp_src
[i
] * volume
+ 128) >> 8));
215 static av_cold
void volume_init(VolumeContext
*vol
)
217 vol
->samples_align
= 1;
219 switch (av_get_packed_sample_fmt(vol
->sample_fmt
)) {
220 case AV_SAMPLE_FMT_U8
:
221 if (vol
->volume_i
< 0x1000000)
222 vol
->scale_samples
= scale_samples_u8_small
;
224 vol
->scale_samples
= scale_samples_u8
;
226 case AV_SAMPLE_FMT_S16
:
227 if (vol
->volume_i
< 0x10000)
228 vol
->scale_samples
= scale_samples_s16_small
;
230 vol
->scale_samples
= scale_samples_s16
;
232 case AV_SAMPLE_FMT_S32
:
233 vol
->scale_samples
= scale_samples_s32
;
235 case AV_SAMPLE_FMT_FLT
:
236 avpriv_float_dsp_init(&vol
->fdsp
, 0);
237 vol
->samples_align
= 4;
239 case AV_SAMPLE_FMT_DBL
:
240 avpriv_float_dsp_init(&vol
->fdsp
, 0);
241 vol
->samples_align
= 8;
246 ff_volume_init_x86(vol
);
249 static int set_volume(AVFilterContext
*ctx
)
251 VolumeContext
*vol
= ctx
->priv
;
253 vol
->volume
= av_expr_eval(vol
->volume_pexpr
, vol
->var_values
, NULL
);
254 if (isnan(vol
->volume
)) {
255 if (vol
->eval_mode
== EVAL_MODE_ONCE
) {
256 av_log(ctx
, AV_LOG_ERROR
, "Invalid value NaN for volume\n");
257 return AVERROR(EINVAL
);
259 av_log(ctx
, AV_LOG_WARNING
, "Invalid value NaN for volume, setting to 0\n");
263 vol
->var_values
[VAR_VOLUME
] = vol
->volume
;
265 av_log(ctx
, AV_LOG_VERBOSE
, "n:%f t:%f pts:%f precision:%s ",
266 vol
->var_values
[VAR_N
], vol
->var_values
[VAR_T
], vol
->var_values
[VAR_PTS
],
267 precision_str
[vol
->precision
]);
269 if (vol
->precision
== PRECISION_FIXED
) {
270 vol
->volume_i
= (int)(vol
->volume
* 256 + 0.5);
271 vol
->volume
= vol
->volume_i
/ 256.0;
272 av_log(ctx
, AV_LOG_VERBOSE
, "volume_i:%d/255 ", vol
->volume_i
);
274 av_log(ctx
, AV_LOG_VERBOSE
, "volume:%f volume_dB:%f\n",
275 vol
->volume
, 20.0*log(vol
->volume
)/M_LN10
);
281 static int config_output(AVFilterLink
*outlink
)
283 AVFilterContext
*ctx
= outlink
->src
;
284 VolumeContext
*vol
= ctx
->priv
;
285 AVFilterLink
*inlink
= ctx
->inputs
[0];
287 vol
->sample_fmt
= inlink
->format
;
288 vol
->channels
= inlink
->channels
;
289 vol
->planes
= av_sample_fmt_is_planar(inlink
->format
) ? vol
->channels
: 1;
291 vol
->var_values
[VAR_N
] =
292 vol
->var_values
[VAR_NB_CONSUMED_SAMPLES
] =
293 vol
->var_values
[VAR_NB_SAMPLES
] =
294 vol
->var_values
[VAR_POS
] =
295 vol
->var_values
[VAR_PTS
] =
296 vol
->var_values
[VAR_STARTPTS
] =
297 vol
->var_values
[VAR_STARTT
] =
298 vol
->var_values
[VAR_T
] =
299 vol
->var_values
[VAR_VOLUME
] = NAN
;
301 vol
->var_values
[VAR_NB_CHANNELS
] = inlink
->channels
;
302 vol
->var_values
[VAR_TB
] = av_q2d(inlink
->time_base
);
303 vol
->var_values
[VAR_SAMPLE_RATE
] = inlink
->sample_rate
;
305 av_log(inlink
->src
, AV_LOG_VERBOSE
, "tb:%f sample_rate:%f nb_channels:%f\n",
306 vol
->var_values
[VAR_TB
],
307 vol
->var_values
[VAR_SAMPLE_RATE
],
308 vol
->var_values
[VAR_NB_CHANNELS
]);
310 return set_volume(ctx
);
313 static int process_command(AVFilterContext
*ctx
, const char *cmd
, const char *args
,
314 char *res
, int res_len
, int flags
)
316 VolumeContext
*vol
= ctx
->priv
;
317 int ret
= AVERROR(ENOSYS
);
319 if (!strcmp(cmd
, "volume")) {
320 if ((ret
= set_expr(&vol
->volume_pexpr
, args
, ctx
)) < 0)
322 if (vol
->eval_mode
== EVAL_MODE_ONCE
)
329 #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
330 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
331 #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
333 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*buf
)
335 AVFilterContext
*ctx
= inlink
->dst
;
336 VolumeContext
*vol
= inlink
->dst
->priv
;
337 AVFilterLink
*outlink
= inlink
->dst
->outputs
[0];
338 int nb_samples
= buf
->nb_samples
;
341 AVFrameSideData
*sd
= av_frame_get_side_data(buf
, AV_FRAME_DATA_REPLAYGAIN
);
344 if (sd
&& vol
->replaygain
!= REPLAYGAIN_IGNORE
) {
345 if (vol
->replaygain
!= REPLAYGAIN_DROP
) {
346 AVReplayGain
*replaygain
= (AVReplayGain
*)sd
->data
;
347 int32_t gain
= 100000;
348 uint32_t peak
= 100000;
351 if (vol
->replaygain
== REPLAYGAIN_TRACK
&&
352 replaygain
->track_gain
!= INT32_MIN
) {
353 gain
= replaygain
->track_gain
;
355 if (replaygain
->track_peak
!= 0)
356 peak
= replaygain
->track_peak
;
357 } else if (replaygain
->album_gain
!= INT32_MIN
) {
358 gain
= replaygain
->album_gain
;
360 if (replaygain
->album_peak
!= 0)
361 peak
= replaygain
->album_peak
;
363 av_log(inlink
->dst
, AV_LOG_WARNING
, "Both ReplayGain gain "
364 "values are unknown.\n");
366 g
= gain
/ 100000.0f
;
367 p
= peak
/ 100000.0f
;
369 av_log(inlink
->dst
, AV_LOG_VERBOSE
,
370 "Using gain %f dB from replaygain side data.\n", g
);
372 vol
->volume
= pow(10, (g
+ vol
->replaygain_preamp
) / 20);
373 if (vol
->replaygain_noclip
)
374 vol
->volume
= FFMIN(vol
->volume
, 1.0 / p
);
375 vol
->volume_i
= (int)(vol
->volume
* 256 + 0.5);
379 av_frame_remove_side_data(buf
, AV_FRAME_DATA_REPLAYGAIN
);
382 if (isnan(vol
->var_values
[VAR_STARTPTS
])) {
383 vol
->var_values
[VAR_STARTPTS
] = TS2D(buf
->pts
);
384 vol
->var_values
[VAR_STARTT
] = TS2T(buf
->pts
, inlink
->time_base
);
386 vol
->var_values
[VAR_PTS
] = TS2D(buf
->pts
);
387 vol
->var_values
[VAR_T
] = TS2T(buf
->pts
, inlink
->time_base
);
388 vol
->var_values
[VAR_N
] = inlink
->frame_count
;
390 pos
= av_frame_get_pkt_pos(buf
);
391 vol
->var_values
[VAR_POS
] = pos
== -1 ? NAN
: pos
;
392 if (vol
->eval_mode
== EVAL_MODE_FRAME
)
395 if (vol
->volume
== 1.0 || vol
->volume_i
== 256) {
400 /* do volume scaling in-place if input buffer is writable */
401 if (av_frame_is_writable(buf
)) {
404 out_buf
= ff_get_audio_buffer(inlink
, nb_samples
);
406 return AVERROR(ENOMEM
);
407 ret
= av_frame_copy_props(out_buf
, buf
);
409 av_frame_free(&out_buf
);
415 if (vol
->precision
!= PRECISION_FIXED
|| vol
->volume_i
> 0) {
416 int p
, plane_samples
;
418 if (av_sample_fmt_is_planar(buf
->format
))
419 plane_samples
= FFALIGN(nb_samples
, vol
->samples_align
);
421 plane_samples
= FFALIGN(nb_samples
* vol
->channels
, vol
->samples_align
);
423 if (vol
->precision
== PRECISION_FIXED
) {
424 for (p
= 0; p
< vol
->planes
; p
++) {
425 vol
->scale_samples(out_buf
->extended_data
[p
],
426 buf
->extended_data
[p
], plane_samples
,
429 } else if (av_get_packed_sample_fmt(vol
->sample_fmt
) == AV_SAMPLE_FMT_FLT
) {
430 for (p
= 0; p
< vol
->planes
; p
++) {
431 vol
->fdsp
.vector_fmul_scalar((float *)out_buf
->extended_data
[p
],
432 (const float *)buf
->extended_data
[p
],
433 vol
->volume
, plane_samples
);
436 for (p
= 0; p
< vol
->planes
; p
++) {
437 vol
->fdsp
.vector_dmul_scalar((double *)out_buf
->extended_data
[p
],
438 (const double *)buf
->extended_data
[p
],
439 vol
->volume
, plane_samples
);
450 vol
->var_values
[VAR_NB_CONSUMED_SAMPLES
] += out_buf
->nb_samples
;
451 return ff_filter_frame(outlink
, out_buf
);
454 static const AVFilterPad avfilter_af_volume_inputs
[] = {
457 .type
= AVMEDIA_TYPE_AUDIO
,
458 .filter_frame
= filter_frame
,
463 static const AVFilterPad avfilter_af_volume_outputs
[] = {
466 .type
= AVMEDIA_TYPE_AUDIO
,
467 .config_props
= config_output
,
472 AVFilter ff_af_volume
= {
474 .description
= NULL_IF_CONFIG_SMALL("Change input volume."),
475 .query_formats
= query_formats
,
476 .priv_size
= sizeof(VolumeContext
),
477 .priv_class
= &volume_class
,
480 .inputs
= avfilter_af_volume_inputs
,
481 .outputs
= avfilter_af_volume_outputs
,
482 .flags
= AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
483 .process_command
= process_command
,