summaryrefslogtreecommitdiff
path: root/libavfilter/af_volume.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2014-02-19 21:01:37 +0100
committerAnton Khirnov <anton@khirnov.net>2014-03-24 06:07:51 +0100
commit06c3cd3c0186803619bc6aad2d8f06c3e9015d15 (patch)
treefc38b79c18a9f70376edd015e6d85af354f1e83a /libavfilter/af_volume.c
parentd161ae0a37900cbd36c1390ca32a56b892c02ab5 (diff)
af_volume: support using replaygain frame side data
Diffstat (limited to 'libavfilter/af_volume.c')
-rw-r--r--libavfilter/af_volume.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 59223e548b..165624e9df 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -28,7 +28,10 @@
#include "libavutil/common.h"
#include "libavutil/eval.h"
#include "libavutil/float_dsp.h"
+#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
+#include "libavutil/replaygain.h"
+
#include "audio.h"
#include "avfilter.h"
#include "formats.h"
@@ -50,6 +53,12 @@ static const AVOption options[] = {
{ "fixed", "8-bit fixed-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED }, INT_MIN, INT_MAX, A, "precision" },
{ "float", "32-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT }, INT_MIN, INT_MAX, A, "precision" },
{ "double", "64-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A, "precision" },
+ { "replaygain", "Apply replaygain side data when present",
+ OFFSET(replaygain), AV_OPT_TYPE_INT, { .i64 = REPLAYGAIN_DROP }, REPLAYGAIN_DROP, REPLAYGAIN_ALBUM, A, "replaygain" },
+ { "drop", "replaygain side data is dropped", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_DROP }, 0, 0, A, "replaygain" },
+ { "ignore", "replaygain side data is ignored", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_IGNORE }, 0, 0, A, "replaygain" },
+ { "track", "track gain is preferred", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_TRACK }, 0, 0, A, "replaygain" },
+ { "album", "album gain is preferred", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_ALBUM }, 0, 0, A, "replaygain" },
{ NULL },
};
@@ -229,8 +238,38 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
AVFilterLink *outlink = inlink->dst->outputs[0];
int nb_samples = buf->nb_samples;
AVFrame *out_buf;
+ AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN);
int ret;
+ if (sd && vol->replaygain != REPLAYGAIN_IGNORE) {
+ if (vol->replaygain != REPLAYGAIN_DROP) {
+ AVReplayGain *replaygain = (AVReplayGain*)sd->data;
+ int32_t gain;
+ float g;
+
+ if (vol->replaygain == REPLAYGAIN_TRACK &&
+ replaygain->track_gain != INT32_MIN)
+ gain = replaygain->track_gain;
+ else if (replaygain->album_gain != INT32_MIN)
+ gain = replaygain->album_gain;
+ else {
+ av_log(inlink->dst, AV_LOG_WARNING, "Both ReplayGain gain "
+ "values are unknown.\n");
+ gain = 100000;
+ }
+ g = gain / 100000.0f;
+
+ av_log(inlink->dst, AV_LOG_VERBOSE,
+ "Using gain %f dB from replaygain side data.\n", g);
+
+ vol->volume = pow(10, g / 20);
+ vol->volume_i = (int)(vol->volume * 256 + 0.5);
+
+ volume_init(vol);
+ }
+ av_frame_remove_side_data(buf, AV_FRAME_DATA_REPLAYGAIN);
+ }
+
if (vol->volume == 1.0 || vol->volume_i == 256)
return ff_filter_frame(outlink, buf);