From 06c3cd3c0186803619bc6aad2d8f06c3e9015d15 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 19 Feb 2014 21:01:37 +0100 Subject: [PATCH] af_volume: support using replaygain frame side data --- doc/filters.texi | 17 +++++++++++++++++ libavfilter/af_volume.c | 39 +++++++++++++++++++++++++++++++++++++++ libavfilter/af_volume.h | 8 ++++++++ 3 files changed, 64 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 8d46cd1fb4..93625c6c80 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -616,6 +616,23 @@ precision of the volume scaling. @item double 64-bit floating-point; limits input sample format to DBL. @end table + +@item replaygain +Behaviour on encountering ReplayGain side data in input frames. + +@table @option +@item drop +Remove ReplayGain side data, ignoring its contents (the default). + +@item ignore +Ignore ReplayGain side data, but leave it in the frame. + +@item track +Prefer track gain, if present. + +@item album +Prefer album gain, if present. +@end table @end table @subsection Examples 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); diff --git a/libavfilter/af_volume.h b/libavfilter/af_volume.h index a1883ed2b9..ec13e80ae3 100644 --- a/libavfilter/af_volume.h +++ b/libavfilter/af_volume.h @@ -35,10 +35,18 @@ enum PrecisionType { PRECISION_DOUBLE, }; +enum ReplayGainType { + REPLAYGAIN_DROP, + REPLAYGAIN_IGNORE, + REPLAYGAIN_TRACK, + REPLAYGAIN_ALBUM, +}; + typedef struct VolumeContext { const AVClass *class; AVFloatDSPContext fdsp; enum PrecisionType precision; + enum ReplayGainType replaygain; double volume; int volume_i; int channels; -- GitLab