diff options
author | Anton Khirnov <anton@khirnov.net> | 2014-02-19 21:01:37 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2014-03-24 06:07:51 +0100 |
commit | 06c3cd3c0186803619bc6aad2d8f06c3e9015d15 (patch) | |
tree | fc38b79c18a9f70376edd015e6d85af354f1e83a /libavfilter | |
parent | d161ae0a37900cbd36c1390ca32a56b892c02ab5 (diff) | |
download | ffmpeg-streaming-06c3cd3c0186803619bc6aad2d8f06c3e9015d15.zip ffmpeg-streaming-06c3cd3c0186803619bc6aad2d8f06c3e9015d15.tar.gz |
af_volume: support using replaygain frame side data
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/af_volume.c | 39 | ||||
-rw-r--r-- | libavfilter/af_volume.h | 8 |
2 files changed, 47 insertions, 0 deletions
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c index 59223e5..165624e 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 a1883ed..ec13e80 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; |