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
;
115 vol
->fdsp
= avpriv_float_dsp_alloc(0);
117 return AVERROR(ENOMEM
);
119 return set_expr(&vol
->volume_pexpr
, vol
->volume_expr
, ctx
);
122 static av_cold
void uninit(AVFilterContext
*ctx
)
124 VolumeContext
*vol
= ctx
->priv
;
125 av_expr_free(vol
->volume_pexpr
);
127 av_freep(&vol
->fdsp
);
130 static int query_formats(AVFilterContext
*ctx
)
132 VolumeContext
*vol
= ctx
->priv
;
133 AVFilterFormats
*formats
= NULL
;
134 AVFilterChannelLayouts
*layouts
;
135 static const enum AVSampleFormat sample_fmts
[][7] = {
136 [PRECISION_FIXED
] = {
145 [PRECISION_FLOAT
] = {
150 [PRECISION_DOUBLE
] = {
157 layouts
= ff_all_channel_counts();
159 return AVERROR(ENOMEM
);
160 ff_set_common_channel_layouts(ctx
, layouts
);
162 formats
= ff_make_format_list(sample_fmts
[vol
->precision
]);
164 return AVERROR(ENOMEM
);
165 ff_set_common_formats(ctx
, formats
);
167 formats
= ff_all_samplerates();
169 return AVERROR(ENOMEM
);
170 ff_set_common_samplerates(ctx
, formats
);
175 static inline void scale_samples_u8(uint8_t *dst
, const uint8_t *src
,
176 int nb_samples
, int volume
)
179 for (i
= 0; i
< nb_samples
; i
++)
180 dst
[i
] = av_clip_uint8(((((int64_t)src
[i
] - 128) * volume
+ 128) >> 8) + 128);
183 static inline void scale_samples_u8_small(uint8_t *dst
, const uint8_t *src
,
184 int nb_samples
, int volume
)
187 for (i
= 0; i
< nb_samples
; i
++)
188 dst
[i
] = av_clip_uint8((((src
[i
] - 128) * volume
+ 128) >> 8) + 128);
191 static inline void scale_samples_s16(uint8_t *dst
, const uint8_t *src
,
192 int nb_samples
, int volume
)
195 int16_t *smp_dst
= (int16_t *)dst
;
196 const int16_t *smp_src
= (const int16_t *)src
;
197 for (i
= 0; i
< nb_samples
; i
++)
198 smp_dst
[i
] = av_clip_int16(((int64_t)smp_src
[i
] * volume
+ 128) >> 8);
201 static inline void scale_samples_s16_small(uint8_t *dst
, const uint8_t *src
,
202 int nb_samples
, int volume
)
205 int16_t *smp_dst
= (int16_t *)dst
;
206 const int16_t *smp_src
= (const int16_t *)src
;
207 for (i
= 0; i
< nb_samples
; i
++)
208 smp_dst
[i
] = av_clip_int16((smp_src
[i
] * volume
+ 128) >> 8);
211 static inline void scale_samples_s32(uint8_t *dst
, const uint8_t *src
,
212 int nb_samples
, int volume
)
215 int32_t *smp_dst
= (int32_t *)dst
;
216 const int32_t *smp_src
= (const int32_t *)src
;
217 for (i
= 0; i
< nb_samples
; i
++)
218 smp_dst
[i
] = av_clipl_int32((((int64_t)smp_src
[i
] * volume
+ 128) >> 8));
221 static av_cold
void volume_init(VolumeContext
*vol
)
223 vol
->samples_align
= 1;
225 switch (av_get_packed_sample_fmt(vol
->sample_fmt
)) {
226 case AV_SAMPLE_FMT_U8
:
227 if (vol
->volume_i
< 0x1000000)
228 vol
->scale_samples
= scale_samples_u8_small
;
230 vol
->scale_samples
= scale_samples_u8
;
232 case AV_SAMPLE_FMT_S16
:
233 if (vol
->volume_i
< 0x10000)
234 vol
->scale_samples
= scale_samples_s16_small
;
236 vol
->scale_samples
= scale_samples_s16
;
238 case AV_SAMPLE_FMT_S32
:
239 vol
->scale_samples
= scale_samples_s32
;
241 case AV_SAMPLE_FMT_FLT
:
242 vol
->samples_align
= 4;
244 case AV_SAMPLE_FMT_DBL
:
245 vol
->samples_align
= 8;
250 ff_volume_init_x86(vol
);
253 static int set_volume(AVFilterContext
*ctx
)
255 VolumeContext
*vol
= ctx
->priv
;
257 vol
->volume
= av_expr_eval(vol
->volume_pexpr
, vol
->var_values
, NULL
);
258 if (isnan(vol
->volume
)) {
259 if (vol
->eval_mode
== EVAL_MODE_ONCE
) {
260 av_log(ctx
, AV_LOG_ERROR
, "Invalid value NaN for volume\n");
261 return AVERROR(EINVAL
);
263 av_log(ctx
, AV_LOG_WARNING
, "Invalid value NaN for volume, setting to 0\n");
267 vol
->var_values
[VAR_VOLUME
] = vol
->volume
;
269 av_log(ctx
, AV_LOG_VERBOSE
, "n:%f t:%f pts:%f precision:%s ",
270 vol
->var_values
[VAR_N
], vol
->var_values
[VAR_T
], vol
->var_values
[VAR_PTS
],
271 precision_str
[vol
->precision
]);
273 if (vol
->precision
== PRECISION_FIXED
) {
274 vol
->volume_i
= (int)(vol
->volume
* 256 + 0.5);
275 vol
->volume
= vol
->volume_i
/ 256.0;
276 av_log(ctx
, AV_LOG_VERBOSE
, "volume_i:%d/255 ", vol
->volume_i
);
278 av_log(ctx
, AV_LOG_VERBOSE
, "volume:%f volume_dB:%f\n",
279 vol
->volume
, 20.0*log(vol
->volume
)/M_LN10
);
285 static int config_output(AVFilterLink
*outlink
)
287 AVFilterContext
*ctx
= outlink
->src
;
288 VolumeContext
*vol
= ctx
->priv
;
289 AVFilterLink
*inlink
= ctx
->inputs
[0];
291 vol
->sample_fmt
= inlink
->format
;
292 vol
->channels
= inlink
->channels
;
293 vol
->planes
= av_sample_fmt_is_planar(inlink
->format
) ? vol
->channels
: 1;
295 vol
->var_values
[VAR_N
] =
296 vol
->var_values
[VAR_NB_CONSUMED_SAMPLES
] =
297 vol
->var_values
[VAR_NB_SAMPLES
] =
298 vol
->var_values
[VAR_POS
] =
299 vol
->var_values
[VAR_PTS
] =
300 vol
->var_values
[VAR_STARTPTS
] =
301 vol
->var_values
[VAR_STARTT
] =
302 vol
->var_values
[VAR_T
] =
303 vol
->var_values
[VAR_VOLUME
] = NAN
;
305 vol
->var_values
[VAR_NB_CHANNELS
] = inlink
->channels
;
306 vol
->var_values
[VAR_TB
] = av_q2d(inlink
->time_base
);
307 vol
->var_values
[VAR_SAMPLE_RATE
] = inlink
->sample_rate
;
309 av_log(inlink
->src
, AV_LOG_VERBOSE
, "tb:%f sample_rate:%f nb_channels:%f\n",
310 vol
->var_values
[VAR_TB
],
311 vol
->var_values
[VAR_SAMPLE_RATE
],
312 vol
->var_values
[VAR_NB_CHANNELS
]);
314 return set_volume(ctx
);
317 static int process_command(AVFilterContext
*ctx
, const char *cmd
, const char *args
,
318 char *res
, int res_len
, int flags
)
320 VolumeContext
*vol
= ctx
->priv
;
321 int ret
= AVERROR(ENOSYS
);
323 if (!strcmp(cmd
, "volume")) {
324 if ((ret
= set_expr(&vol
->volume_pexpr
, args
, ctx
)) < 0)
326 if (vol
->eval_mode
== EVAL_MODE_ONCE
)
333 #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
334 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
335 #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
337 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*buf
)
339 AVFilterContext
*ctx
= inlink
->dst
;
340 VolumeContext
*vol
= inlink
->dst
->priv
;
341 AVFilterLink
*outlink
= inlink
->dst
->outputs
[0];
342 int nb_samples
= buf
->nb_samples
;
345 AVFrameSideData
*sd
= av_frame_get_side_data(buf
, AV_FRAME_DATA_REPLAYGAIN
);
348 if (sd
&& vol
->replaygain
!= REPLAYGAIN_IGNORE
) {
349 if (vol
->replaygain
!= REPLAYGAIN_DROP
) {
350 AVReplayGain
*replaygain
= (AVReplayGain
*)sd
->data
;
351 int32_t gain
= 100000;
352 uint32_t peak
= 100000;
355 if (vol
->replaygain
== REPLAYGAIN_TRACK
&&
356 replaygain
->track_gain
!= INT32_MIN
) {
357 gain
= replaygain
->track_gain
;
359 if (replaygain
->track_peak
!= 0)
360 peak
= replaygain
->track_peak
;
361 } else if (replaygain
->album_gain
!= INT32_MIN
) {
362 gain
= replaygain
->album_gain
;
364 if (replaygain
->album_peak
!= 0)
365 peak
= replaygain
->album_peak
;
367 av_log(inlink
->dst
, AV_LOG_WARNING
, "Both ReplayGain gain "
368 "values are unknown.\n");
370 g
= gain
/ 100000.0f
;
371 p
= peak
/ 100000.0f
;
373 av_log(inlink
->dst
, AV_LOG_VERBOSE
,
374 "Using gain %f dB from replaygain side data.\n", g
);
376 vol
->volume
= pow(10, (g
+ vol
->replaygain_preamp
) / 20);
377 if (vol
->replaygain_noclip
)
378 vol
->volume
= FFMIN(vol
->volume
, 1.0 / p
);
379 vol
->volume_i
= (int)(vol
->volume
* 256 + 0.5);
383 av_frame_remove_side_data(buf
, AV_FRAME_DATA_REPLAYGAIN
);
386 if (isnan(vol
->var_values
[VAR_STARTPTS
])) {
387 vol
->var_values
[VAR_STARTPTS
] = TS2D(buf
->pts
);
388 vol
->var_values
[VAR_STARTT
] = TS2T(buf
->pts
, inlink
->time_base
);
390 vol
->var_values
[VAR_PTS
] = TS2D(buf
->pts
);
391 vol
->var_values
[VAR_T
] = TS2T(buf
->pts
, inlink
->time_base
);
392 vol
->var_values
[VAR_N
] = inlink
->frame_count
;
394 pos
= av_frame_get_pkt_pos(buf
);
395 vol
->var_values
[VAR_POS
] = pos
== -1 ? NAN
: pos
;
396 if (vol
->eval_mode
== EVAL_MODE_FRAME
)
399 if (vol
->volume
== 1.0 || vol
->volume_i
== 256) {
404 /* do volume scaling in-place if input buffer is writable */
405 if (av_frame_is_writable(buf
)) {
408 out_buf
= ff_get_audio_buffer(inlink
, nb_samples
);
410 return AVERROR(ENOMEM
);
411 ret
= av_frame_copy_props(out_buf
, buf
);
413 av_frame_free(&out_buf
);
419 if (vol
->precision
!= PRECISION_FIXED
|| vol
->volume_i
> 0) {
420 int p
, plane_samples
;
422 if (av_sample_fmt_is_planar(buf
->format
))
423 plane_samples
= FFALIGN(nb_samples
, vol
->samples_align
);
425 plane_samples
= FFALIGN(nb_samples
* vol
->channels
, vol
->samples_align
);
427 if (vol
->precision
== PRECISION_FIXED
) {
428 for (p
= 0; p
< vol
->planes
; p
++) {
429 vol
->scale_samples(out_buf
->extended_data
[p
],
430 buf
->extended_data
[p
], plane_samples
,
433 } else if (av_get_packed_sample_fmt(vol
->sample_fmt
) == AV_SAMPLE_FMT_FLT
) {
434 for (p
= 0; p
< vol
->planes
; p
++) {
435 vol
->fdsp
->vector_fmul_scalar((float *)out_buf
->extended_data
[p
],
436 (const float *)buf
->extended_data
[p
],
437 vol
->volume
, plane_samples
);
440 for (p
= 0; p
< vol
->planes
; p
++) {
441 vol
->fdsp
->vector_dmul_scalar((double *)out_buf
->extended_data
[p
],
442 (const double *)buf
->extended_data
[p
],
443 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
,
467 static const AVFilterPad avfilter_af_volume_outputs
[] = {
470 .type
= AVMEDIA_TYPE_AUDIO
,
471 .config_props
= config_output
,
476 AVFilter ff_af_volume
= {
478 .description
= NULL_IF_CONFIG_SMALL("Change input volume."),
479 .query_formats
= query_formats
,
480 .priv_size
= sizeof(VolumeContext
),
481 .priv_class
= &volume_class
,
484 .inputs
= avfilter_af_volume_inputs
,
485 .outputs
= avfilter_af_volume_outputs
,
486 .flags
= AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
487 .process_command
= process_command
,