af_volume: support using replaygain frame side data
[ffmpeg.git] / libavfilter / af_volume.c
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
22 /**
23  * @file
24  * audio volume filter
25  */
26
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"
34
35 #include "audio.h"
36 #include "avfilter.h"
37 #include "formats.h"
38 #include "internal.h"
39 #include "af_volume.h"
40
41 static const char *precision_str[] = {
42     "fixed", "float", "double"
43 };
44
45 #define OFFSET(x) offsetof(VolumeContext, x)
46 #define A AV_OPT_FLAG_AUDIO_PARAM
47
48 static const AVOption options[] = {
49     { "volume", "Volume adjustment.",
50             OFFSET(volume), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 0, 0x7fffff, A },
51     { "precision", "Mathematical precision.",
52             OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A, "precision" },
53         { "fixed",  "8-bit fixed-point.",     0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED  }, INT_MIN, INT_MAX, A, "precision" },
54         { "float",  "32-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT  }, INT_MIN, INT_MAX, A, "precision" },
55         { "double", "64-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A, "precision" },
56     { "replaygain", "Apply replaygain side data when present",
57             OFFSET(replaygain), AV_OPT_TYPE_INT, { .i64 = REPLAYGAIN_DROP }, REPLAYGAIN_DROP, REPLAYGAIN_ALBUM, A, "replaygain" },
58         { "drop",   "replaygain side data is dropped", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_DROP   }, 0, 0, A, "replaygain" },
59         { "ignore", "replaygain side data is ignored", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_IGNORE }, 0, 0, A, "replaygain" },
60         { "track",  "track gain is preferred",         0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_TRACK  }, 0, 0, A, "replaygain" },
61         { "album",  "album gain is preferred",         0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_ALBUM  }, 0, 0, A, "replaygain" },
62     { NULL },
63 };
64
65 static const AVClass volume_class = {
66     .class_name = "volume filter",
67     .item_name  = av_default_item_name,
68     .option     = options,
69     .version    = LIBAVUTIL_VERSION_INT,
70 };
71
72 static av_cold int init(AVFilterContext *ctx)
73 {
74     VolumeContext *vol = ctx->priv;
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     return 0;
88 }
89
90 static int query_formats(AVFilterContext *ctx)
91 {
92     VolumeContext *vol = ctx->priv;
93     AVFilterFormats *formats = NULL;
94     AVFilterChannelLayouts *layouts;
95     static const enum AVSampleFormat sample_fmts[][7] = {
96         /* PRECISION_FIXED */
97         {
98             AV_SAMPLE_FMT_U8,
99             AV_SAMPLE_FMT_U8P,
100             AV_SAMPLE_FMT_S16,
101             AV_SAMPLE_FMT_S16P,
102             AV_SAMPLE_FMT_S32,
103             AV_SAMPLE_FMT_S32P,
104             AV_SAMPLE_FMT_NONE
105         },
106         /* PRECISION_FLOAT */
107         {
108             AV_SAMPLE_FMT_FLT,
109             AV_SAMPLE_FMT_FLTP,
110             AV_SAMPLE_FMT_NONE
111         },
112         /* PRECISION_DOUBLE */
113         {
114             AV_SAMPLE_FMT_DBL,
115             AV_SAMPLE_FMT_DBLP,
116             AV_SAMPLE_FMT_NONE
117         }
118     };
119
120     layouts = ff_all_channel_layouts();
121     if (!layouts)
122         return AVERROR(ENOMEM);
123     ff_set_common_channel_layouts(ctx, layouts);
124
125     formats = ff_make_format_list(sample_fmts[vol->precision]);
126     if (!formats)
127         return AVERROR(ENOMEM);
128     ff_set_common_formats(ctx, formats);
129
130     formats = ff_all_samplerates();
131     if (!formats)
132         return AVERROR(ENOMEM);
133     ff_set_common_samplerates(ctx, formats);
134
135     return 0;
136 }
137
138 static inline void scale_samples_u8(uint8_t *dst, const uint8_t *src,
139                                     int nb_samples, int volume)
140 {
141     int i;
142     for (i = 0; i < nb_samples; i++)
143         dst[i] = av_clip_uint8(((((int64_t)src[i] - 128) * volume + 128) >> 8) + 128);
144 }
145
146 static inline void scale_samples_u8_small(uint8_t *dst, const uint8_t *src,
147                                           int nb_samples, int volume)
148 {
149     int i;
150     for (i = 0; i < nb_samples; i++)
151         dst[i] = av_clip_uint8((((src[i] - 128) * volume + 128) >> 8) + 128);
152 }
153
154 static inline void scale_samples_s16(uint8_t *dst, const uint8_t *src,
155                                      int nb_samples, int volume)
156 {
157     int i;
158     int16_t *smp_dst       = (int16_t *)dst;
159     const int16_t *smp_src = (const int16_t *)src;
160     for (i = 0; i < nb_samples; i++)
161         smp_dst[i] = av_clip_int16(((int64_t)smp_src[i] * volume + 128) >> 8);
162 }
163
164 static inline void scale_samples_s16_small(uint8_t *dst, const uint8_t *src,
165                                            int nb_samples, int volume)
166 {
167     int i;
168     int16_t *smp_dst       = (int16_t *)dst;
169     const int16_t *smp_src = (const int16_t *)src;
170     for (i = 0; i < nb_samples; i++)
171         smp_dst[i] = av_clip_int16((smp_src[i] * volume + 128) >> 8);
172 }
173
174 static inline void scale_samples_s32(uint8_t *dst, const uint8_t *src,
175                                      int nb_samples, int volume)
176 {
177     int i;
178     int32_t *smp_dst       = (int32_t *)dst;
179     const int32_t *smp_src = (const int32_t *)src;
180     for (i = 0; i < nb_samples; i++)
181         smp_dst[i] = av_clipl_int32((((int64_t)smp_src[i] * volume + 128) >> 8));
182 }
183
184
185
186 static av_cold void volume_init(VolumeContext *vol)
187 {
188     vol->samples_align = 1;
189
190     switch (av_get_packed_sample_fmt(vol->sample_fmt)) {
191     case AV_SAMPLE_FMT_U8:
192         if (vol->volume_i < 0x1000000)
193             vol->scale_samples = scale_samples_u8_small;
194         else
195             vol->scale_samples = scale_samples_u8;
196         break;
197     case AV_SAMPLE_FMT_S16:
198         if (vol->volume_i < 0x10000)
199             vol->scale_samples = scale_samples_s16_small;
200         else
201             vol->scale_samples = scale_samples_s16;
202         break;
203     case AV_SAMPLE_FMT_S32:
204         vol->scale_samples = scale_samples_s32;
205         break;
206     case AV_SAMPLE_FMT_FLT:
207         avpriv_float_dsp_init(&vol->fdsp, 0);
208         vol->samples_align = 4;
209         break;
210     case AV_SAMPLE_FMT_DBL:
211         avpriv_float_dsp_init(&vol->fdsp, 0);
212         vol->samples_align = 8;
213         break;
214     }
215
216     if (ARCH_X86)
217         ff_volume_init_x86(vol);
218 }
219
220 static int config_output(AVFilterLink *outlink)
221 {
222     AVFilterContext *ctx = outlink->src;
223     VolumeContext *vol   = ctx->priv;
224     AVFilterLink *inlink = ctx->inputs[0];
225
226     vol->sample_fmt = inlink->format;
227     vol->channels   = av_get_channel_layout_nb_channels(inlink->channel_layout);
228     vol->planes     = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1;
229
230     volume_init(vol);
231
232     return 0;
233 }
234
235 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
236 {
237     VolumeContext *vol    = inlink->dst->priv;
238     AVFilterLink *outlink = inlink->dst->outputs[0];
239     int nb_samples        = buf->nb_samples;
240     AVFrame *out_buf;
241     AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN);
242     int ret;
243
244     if (sd && vol->replaygain != REPLAYGAIN_IGNORE) {
245         if (vol->replaygain != REPLAYGAIN_DROP) {
246             AVReplayGain *replaygain = (AVReplayGain*)sd->data;
247             int32_t gain;
248             float g;
249
250             if (vol->replaygain == REPLAYGAIN_TRACK &&
251                 replaygain->track_gain != INT32_MIN)
252                 gain = replaygain->track_gain;
253             else if (replaygain->album_gain != INT32_MIN)
254                 gain = replaygain->album_gain;
255             else {
256                 av_log(inlink->dst, AV_LOG_WARNING, "Both ReplayGain gain "
257                        "values are unknown.\n");
258                 gain = 100000;
259             }
260             g = gain / 100000.0f;
261
262             av_log(inlink->dst, AV_LOG_VERBOSE,
263                    "Using gain %f dB from replaygain side data.\n", g);
264
265             vol->volume   = pow(10, g / 20);
266             vol->volume_i = (int)(vol->volume * 256 + 0.5);
267
268             volume_init(vol);
269         }
270         av_frame_remove_side_data(buf, AV_FRAME_DATA_REPLAYGAIN);
271     }
272
273     if (vol->volume == 1.0 || vol->volume_i == 256)
274         return ff_filter_frame(outlink, buf);
275
276     /* do volume scaling in-place if input buffer is writable */
277     if (av_frame_is_writable(buf)) {
278         out_buf = buf;
279     } else {
280         out_buf = ff_get_audio_buffer(inlink, nb_samples);
281         if (!out_buf)
282             return AVERROR(ENOMEM);
283         ret = av_frame_copy_props(out_buf, buf);
284         if (ret < 0) {
285             av_frame_free(&out_buf);
286             av_frame_free(&buf);
287             return ret;
288         }
289     }
290
291     if (vol->precision != PRECISION_FIXED || vol->volume_i > 0) {
292         int p, plane_samples;
293
294         if (av_sample_fmt_is_planar(buf->format))
295             plane_samples = FFALIGN(nb_samples, vol->samples_align);
296         else
297             plane_samples = FFALIGN(nb_samples * vol->channels, vol->samples_align);
298
299         if (vol->precision == PRECISION_FIXED) {
300             for (p = 0; p < vol->planes; p++) {
301                 vol->scale_samples(out_buf->extended_data[p],
302                                    buf->extended_data[p], plane_samples,
303                                    vol->volume_i);
304             }
305         } else if (av_get_packed_sample_fmt(vol->sample_fmt) == AV_SAMPLE_FMT_FLT) {
306             for (p = 0; p < vol->planes; p++) {
307                 vol->fdsp.vector_fmul_scalar((float *)out_buf->extended_data[p],
308                                              (const float *)buf->extended_data[p],
309                                              vol->volume, plane_samples);
310             }
311         } else {
312             for (p = 0; p < vol->planes; p++) {
313                 vol->fdsp.vector_dmul_scalar((double *)out_buf->extended_data[p],
314                                              (const double *)buf->extended_data[p],
315                                              vol->volume, plane_samples);
316             }
317         }
318     }
319
320     emms_c();
321
322     if (buf != out_buf)
323         av_frame_free(&buf);
324
325     return ff_filter_frame(outlink, out_buf);
326 }
327
328 static const AVFilterPad avfilter_af_volume_inputs[] = {
329     {
330         .name           = "default",
331         .type           = AVMEDIA_TYPE_AUDIO,
332         .filter_frame   = filter_frame,
333     },
334     { NULL }
335 };
336
337 static const AVFilterPad avfilter_af_volume_outputs[] = {
338     {
339         .name         = "default",
340         .type         = AVMEDIA_TYPE_AUDIO,
341         .config_props = config_output,
342     },
343     { NULL }
344 };
345
346 AVFilter ff_af_volume = {
347     .name           = "volume",
348     .description    = NULL_IF_CONFIG_SMALL("Change input volume."),
349     .query_formats  = query_formats,
350     .priv_size      = sizeof(VolumeContext),
351     .priv_class     = &volume_class,
352     .init           = init,
353     .inputs         = avfilter_af_volume_inputs,
354     .outputs        = avfilter_af_volume_outputs,
355 };