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/ffmath.h"
31 #include "libavutil/float_dsp.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/replaygain.h"
40 #include "af_volume.h"
42 static const char * const precision_str
[] = {
43 "fixed", "float", "double"
46 static const char *const var_names
[] = {
47 "n", ///< frame number (starting at zero)
48 "nb_channels", ///< number of channels
49 "nb_consumed_samples", ///< number of samples consumed by the filter
50 "nb_samples", ///< number of samples in the current frame
52 "pos", ///< position in the file of the frame
54 "pts", ///< frame presentation timestamp
55 "sample_rate", ///< sample rate
56 "startpts", ///< PTS at start of stream
57 "startt", ///< time at start of stream
58 "t", ///< time in the file of the frame
60 "volume", ///< last set value
64 #define OFFSET(x) offsetof(VolumeContext, x)
65 #define A AV_OPT_FLAG_AUDIO_PARAM
66 #define F AV_OPT_FLAG_FILTERING_PARAM
67 #define T AV_OPT_FLAG_RUNTIME_PARAM
69 static const AVOption volume_options
[] = {
70 { "volume", "set volume adjustment expression",
71 OFFSET(volume_expr
), AV_OPT_TYPE_STRING
, { .str
= "1.0" }, .flags
= A
|F
|T
},
72 { "precision", "select mathematical precision",
73 OFFSET(precision
), AV_OPT_TYPE_INT
, { .i64
= PRECISION_FLOAT
}, PRECISION_FIXED
, PRECISION_DOUBLE
, A
|F
, .unit
= "precision" },
74 { "fixed", "select 8-bit fixed-point", 0, AV_OPT_TYPE_CONST
, { .i64
= PRECISION_FIXED
}, INT_MIN
, INT_MAX
, A
|F
, .unit
= "precision" },
75 { "float", "select 32-bit floating-point", 0, AV_OPT_TYPE_CONST
, { .i64
= PRECISION_FLOAT
}, INT_MIN
, INT_MAX
, A
|F
, .unit
= "precision" },
76 { "double", "select 64-bit floating-point", 0, AV_OPT_TYPE_CONST
, { .i64
= PRECISION_DOUBLE
}, INT_MIN
, INT_MAX
, A
|F
, .unit
= "precision" },
77 { "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
, .unit
= "eval" },
78 { "once", "eval volume expression once", 0, AV_OPT_TYPE_CONST
, {.i64
=EVAL_MODE_ONCE
}, .flags
= A
|F
, .unit
= "eval" },
79 { "frame", "eval volume expression per-frame", 0, AV_OPT_TYPE_CONST
, {.i64
=EVAL_MODE_FRAME
}, .flags
= A
|F
, .unit
= "eval" },
80 { "replaygain", "Apply replaygain side data when present",
81 OFFSET(replaygain
), AV_OPT_TYPE_INT
, { .i64
= REPLAYGAIN_DROP
}, REPLAYGAIN_DROP
, REPLAYGAIN_ALBUM
, A
|F
, .unit
= "replaygain" },
82 { "drop", "replaygain side data is dropped", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_DROP
}, 0, 0, A
|F
, .unit
= "replaygain" },
83 { "ignore", "replaygain side data is ignored", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_IGNORE
}, 0, 0, A
|F
, .unit
= "replaygain" },
84 { "track", "track gain is preferred", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_TRACK
}, 0, 0, A
|F
, .unit
= "replaygain" },
85 { "album", "album gain is preferred", 0, AV_OPT_TYPE_CONST
, { .i64
= REPLAYGAIN_ALBUM
}, 0, 0, A
|F
, .unit
= "replaygain" },
86 { "replaygain_preamp", "Apply replaygain pre-amplification",
87 OFFSET(replaygain_preamp
), AV_OPT_TYPE_DOUBLE
, { .dbl
= 0.0 }, -15.0, 15.0, A
|F
},
88 { "replaygain_noclip", "Apply replaygain clipping prevention",
89 OFFSET(replaygain_noclip
), AV_OPT_TYPE_BOOL
, { .i64
= 1 }, 0, 1, A
|F
},
93 AVFILTER_DEFINE_CLASS(volume
);
95 static int set_expr(AVExpr
**pexpr
, const char *expr
, void *log_ctx
)
102 ret
= av_expr_parse(pexpr
, expr
, var_names
,
103 NULL
, NULL
, NULL
, NULL
, 0, log_ctx
);
105 av_log(log_ctx
, AV_LOG_ERROR
,
106 "Error when evaluating the volume expression '%s'\n", expr
);
115 static av_cold
int init(AVFilterContext
*ctx
)
117 VolumeContext
*vol
= ctx
->priv
;
119 vol
->fdsp
= avpriv_float_dsp_alloc(0);
121 return AVERROR(ENOMEM
);
123 return set_expr(&vol
->volume_pexpr
, vol
->volume_expr
, ctx
);
126 static av_cold
void uninit(AVFilterContext
*ctx
)
128 VolumeContext
*vol
= ctx
->priv
;
129 av_expr_free(vol
->volume_pexpr
);
130 av_freep(&vol
->fdsp
);
133 static int query_formats(const AVFilterContext
*ctx
,
134 AVFilterFormatsConfig
**cfg_in
,
135 AVFilterFormatsConfig
**cfg_out
)
137 const VolumeContext
*vol
= ctx
->priv
;
138 static const enum AVSampleFormat sample_fmts
[][7] = {
139 [PRECISION_FIXED
] = {
148 [PRECISION_FLOAT
] = {
153 [PRECISION_DOUBLE
] = {
161 ret
= ff_set_common_formats_from_list2(ctx
, cfg_in
, cfg_out
, sample_fmts
[vol
->precision
]);
168 static inline void scale_samples_u8(uint8_t *dst
, const uint8_t *src
,
169 int nb_samples
, int volume
)
172 for (i
= 0; i
< nb_samples
; i
++)
173 dst
[i
] = av_clip_uint8(((((int64_t)src
[i
] - 128) * volume
+ 128) >> 8) + 128);
176 static inline void scale_samples_u8_small(uint8_t *dst
, const uint8_t *src
,
177 int nb_samples
, int volume
)
180 for (i
= 0; i
< nb_samples
; i
++)
181 dst
[i
] = av_clip_uint8((((src
[i
] - 128) * volume
+ 128) >> 8) + 128);
184 static inline void scale_samples_s16(uint8_t *dst
, const uint8_t *src
,
185 int nb_samples
, int volume
)
188 int16_t *smp_dst
= (int16_t *)dst
;
189 const int16_t *smp_src
= (const int16_t *)src
;
190 for (i
= 0; i
< nb_samples
; i
++)
191 smp_dst
[i
] = av_clip_int16(((int64_t)smp_src
[i
] * volume
+ 128) >> 8);
194 static inline void scale_samples_s16_small(uint8_t *dst
, const uint8_t *src
,
195 int nb_samples
, int volume
)
198 int16_t *smp_dst
= (int16_t *)dst
;
199 const int16_t *smp_src
= (const int16_t *)src
;
200 for (i
= 0; i
< nb_samples
; i
++)
201 smp_dst
[i
] = av_clip_int16((smp_src
[i
] * volume
+ 128) >> 8);
204 static inline void scale_samples_s32(uint8_t *dst
, const uint8_t *src
,
205 int nb_samples
, int volume
)
208 int32_t *smp_dst
= (int32_t *)dst
;
209 const int32_t *smp_src
= (const int32_t *)src
;
210 for (i
= 0; i
< nb_samples
; i
++)
211 smp_dst
[i
] = av_clipl_int32((((int64_t)smp_src
[i
] * volume
+ 128) >> 8));
214 static av_cold
void volume_init(VolumeContext
*vol
)
216 vol
->samples_align
= 1;
218 switch (av_get_packed_sample_fmt(vol
->sample_fmt
)) {
219 case AV_SAMPLE_FMT_U8
:
220 if (vol
->volume_i
< 0x1000000)
221 vol
->scale_samples
= scale_samples_u8_small
;
223 vol
->scale_samples
= scale_samples_u8
;
225 case AV_SAMPLE_FMT_S16
:
226 if (vol
->volume_i
< 0x10000)
227 vol
->scale_samples
= scale_samples_s16_small
;
229 vol
->scale_samples
= scale_samples_s16
;
231 case AV_SAMPLE_FMT_S32
:
232 vol
->scale_samples
= scale_samples_s32
;
234 case AV_SAMPLE_FMT_FLT
:
235 vol
->samples_align
= 4;
237 case AV_SAMPLE_FMT_DBL
:
238 vol
->samples_align
= 8;
243 ff_volume_init_x86(vol
);
247 static int set_volume(AVFilterContext
*ctx
)
249 VolumeContext
*vol
= ctx
->priv
;
251 vol
->volume
= av_expr_eval(vol
->volume_pexpr
, vol
->var_values
, NULL
);
252 if (isnan(vol
->volume
)) {
253 if (vol
->eval_mode
== EVAL_MODE_ONCE
) {
254 av_log(ctx
, AV_LOG_ERROR
, "Invalid value NaN for volume\n");
255 return AVERROR(EINVAL
);
257 av_log(ctx
, AV_LOG_WARNING
, "Invalid value NaN for volume, setting to 0\n");
261 vol
->var_values
[VAR_VOLUME
] = vol
->volume
;
263 av_log(ctx
, AV_LOG_VERBOSE
, "n:%f t:%f pts:%f precision:%s ",
264 vol
->var_values
[VAR_N
], vol
->var_values
[VAR_T
], vol
->var_values
[VAR_PTS
],
265 precision_str
[vol
->precision
]);
267 if (vol
->precision
== PRECISION_FIXED
) {
268 vol
->volume_i
= (int)(vol
->volume
* 256 + 0.5);
269 vol
->volume
= vol
->volume_i
/ 256.0;
270 av_log(ctx
, AV_LOG_VERBOSE
, "volume_i:%d/255 ", vol
->volume_i
);
272 av_log(ctx
, AV_LOG_VERBOSE
, "volume:%f volume_dB:%f\n",
273 vol
->volume
, 20.0*log10(vol
->volume
));
279 static int config_output(AVFilterLink
*outlink
)
281 AVFilterContext
*ctx
= outlink
->src
;
282 VolumeContext
*vol
= ctx
->priv
;
283 AVFilterLink
*inlink
= ctx
->inputs
[0];
285 vol
->sample_fmt
= inlink
->format
;
286 vol
->channels
= inlink
->ch_layout
.nb_channels
;
287 vol
->planes
= av_sample_fmt_is_planar(inlink
->format
) ? vol
->channels
: 1;
289 vol
->var_values
[VAR_N
] =
290 vol
->var_values
[VAR_NB_CONSUMED_SAMPLES
] =
291 vol
->var_values
[VAR_NB_SAMPLES
] =
293 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
->ch_layout
.nb_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 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*buf
)
331 FilterLink
*inl
= ff_filter_link(inlink
);
332 AVFilterContext
*ctx
= inlink
->dst
;
333 VolumeContext
*vol
= inlink
->dst
->priv
;
334 AVFilterLink
*outlink
= inlink
->dst
->outputs
[0];
335 int nb_samples
= buf
->nb_samples
;
337 AVFrameSideData
*sd
= av_frame_get_side_data(buf
, AV_FRAME_DATA_REPLAYGAIN
);
340 if (sd
&& vol
->replaygain
!= REPLAYGAIN_IGNORE
) {
341 if (vol
->replaygain
!= REPLAYGAIN_DROP
) {
342 AVReplayGain
*replaygain
= (AVReplayGain
*)sd
->data
;
343 int32_t gain
= 100000;
344 uint32_t peak
= 100000;
347 if (vol
->replaygain
== REPLAYGAIN_TRACK
&&
348 replaygain
->track_gain
!= INT32_MIN
) {
349 gain
= replaygain
->track_gain
;
351 if (replaygain
->track_peak
!= 0)
352 peak
= replaygain
->track_peak
;
353 } else if (replaygain
->album_gain
!= INT32_MIN
) {
354 gain
= replaygain
->album_gain
;
356 if (replaygain
->album_peak
!= 0)
357 peak
= replaygain
->album_peak
;
359 av_log(inlink
->dst
, AV_LOG_WARNING
, "Both ReplayGain gain "
360 "values are unknown.\n");
362 g
= gain
/ 100000.0f
;
363 p
= peak
/ 100000.0f
;
365 av_log(inlink
->dst
, AV_LOG_VERBOSE
,
366 "Using gain %f dB from replaygain side data.\n", g
);
368 vol
->volume
= ff_exp10((g
+ vol
->replaygain_preamp
) / 20);
369 if (vol
->replaygain_noclip
)
370 vol
->volume
= FFMIN(vol
->volume
, 1.0 / p
);
371 vol
->volume_i
= (int)(vol
->volume
* 256 + 0.5);
375 av_frame_remove_side_data(buf
, AV_FRAME_DATA_REPLAYGAIN
);
378 if (isnan(vol
->var_values
[VAR_STARTPTS
])) {
379 vol
->var_values
[VAR_STARTPTS
] = TS2D(buf
->pts
);
380 vol
->var_values
[VAR_STARTT
] = TS2T(buf
->pts
, inlink
->time_base
);
382 vol
->var_values
[VAR_PTS
] = TS2D(buf
->pts
);
383 vol
->var_values
[VAR_T
] = TS2T(buf
->pts
, inlink
->time_base
);
384 vol
->var_values
[VAR_N
] = inl
->frame_count_out
;
387 FF_DISABLE_DEPRECATION_WARNINGS
391 vol
->var_values
[VAR_POS
] = pos
== -1 ? NAN
: pos
;
393 FF_ENABLE_DEPRECATION_WARNINGS
395 if (vol
->eval_mode
== EVAL_MODE_FRAME
)
398 if (vol
->volume
== 1.0 || vol
->volume_i
== 256) {
403 /* do volume scaling in-place if input buffer is writable */
404 if (av_frame_is_writable(buf
)
405 && (vol
->precision
!= PRECISION_FIXED
|| vol
->volume_i
> 0)) {
408 out_buf
= ff_get_audio_buffer(outlink
, nb_samples
);
411 return AVERROR(ENOMEM
);
413 ret
= av_frame_copy_props(out_buf
, buf
);
415 av_frame_free(&out_buf
);
421 if (vol
->precision
!= PRECISION_FIXED
|| vol
->volume_i
> 0) {
422 int p
, plane_samples
;
424 if (av_sample_fmt_is_planar(buf
->format
))
425 plane_samples
= FFALIGN(nb_samples
, vol
->samples_align
);
427 plane_samples
= FFALIGN(nb_samples
* vol
->channels
, vol
->samples_align
);
429 if (vol
->precision
== PRECISION_FIXED
) {
430 for (p
= 0; p
< vol
->planes
; p
++) {
431 vol
->scale_samples(out_buf
->extended_data
[p
],
432 buf
->extended_data
[p
], plane_samples
,
435 } else if (av_get_packed_sample_fmt(vol
->sample_fmt
) == AV_SAMPLE_FMT_FLT
) {
436 for (p
= 0; p
< vol
->planes
; p
++) {
437 vol
->fdsp
->vector_fmul_scalar((float *)out_buf
->extended_data
[p
],
438 (const float *)buf
->extended_data
[p
],
439 vol
->volume
, plane_samples
);
442 for (p
= 0; p
< vol
->planes
; p
++) {
443 vol
->fdsp
->vector_dmul_scalar((double *)out_buf
->extended_data
[p
],
444 (const double *)buf
->extended_data
[p
],
445 vol
->volume
, plane_samples
);
454 vol
->var_values
[VAR_NB_CONSUMED_SAMPLES
] += out_buf
->nb_samples
;
455 return ff_filter_frame(outlink
, out_buf
);
458 static const AVFilterPad avfilter_af_volume_inputs
[] = {
461 .type
= AVMEDIA_TYPE_AUDIO
,
462 .filter_frame
= filter_frame
,
466 static const AVFilterPad avfilter_af_volume_outputs
[] = {
469 .type
= AVMEDIA_TYPE_AUDIO
,
470 .config_props
= config_output
,
474 const FFFilter ff_af_volume
= {
476 .p
.description
= NULL_IF_CONFIG_SMALL("Change input volume."),
477 .p
.priv_class
= &volume_class
,
478 .p
.flags
= AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
479 .priv_size
= sizeof(VolumeContext
),
482 FILTER_INPUTS(avfilter_af_volume_inputs
),
483 FILTER_OUTPUTS(avfilter_af_volume_outputs
),
484 FILTER_QUERY_FUNC2(query_formats
),
485 .process_command
= process_command
,