Merge commit '06c3cd3c0186803619bc6aad2d8f06c3e9015d15'

* commit '06c3cd3c0186803619bc6aad2d8f06c3e9015d15':
  af_volume: support using replaygain frame side data

Conflicts:
	doc/filters.texi
	libavfilter/af_volume.c
	libavfilter/af_volume.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2014-03-24 15:04:47 +01:00
commit 8de75f703a
3 changed files with 65 additions and 1 deletions

View File

@ -1830,6 +1830,23 @@ precision of the volume scaling.
64-bit floating-point; limits input sample format to DBL. 64-bit floating-point; limits input sample format to DBL.
@end table @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
@item eval @item eval
Set when the volume expression is evaluated. Set when the volume expression is evaluated.

View File

@ -28,7 +28,10 @@
#include "libavutil/common.h" #include "libavutil/common.h"
#include "libavutil/eval.h" #include "libavutil/eval.h"
#include "libavutil/float_dsp.h" #include "libavutil/float_dsp.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/replaygain.h"
#include "audio.h" #include "audio.h"
#include "avfilter.h" #include "avfilter.h"
#include "formats.h" #include "formats.h"
@ -70,7 +73,13 @@ static const AVOption volume_options[] = {
{ "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" }, { "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" },
{ "once", "eval volume expression once", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_ONCE}, .flags = A|F, .unit = "eval" }, { "once", "eval volume expression once", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_ONCE}, .flags = A|F, .unit = "eval" },
{ "frame", "eval volume expression per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = A|F, .unit = "eval" }, { "frame", "eval volume expression per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = A|F, .unit = "eval" },
{ NULL } { "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 },
}; };
AVFILTER_DEFINE_CLASS(volume); AVFILTER_DEFINE_CLASS(volume);
@ -325,8 +334,38 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
int nb_samples = buf->nb_samples; int nb_samples = buf->nb_samples;
AVFrame *out_buf; AVFrame *out_buf;
int64_t pos; int64_t pos;
AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN);
int ret; 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 (isnan(vol->var_values[VAR_STARTPTS])) { if (isnan(vol->var_values[VAR_STARTPTS])) {
vol->var_values[VAR_STARTPTS] = TS2D(buf->pts); vol->var_values[VAR_STARTPTS] = TS2D(buf->pts);
vol->var_values[VAR_STARTT ] = TS2T(buf->pts, inlink->time_base); vol->var_values[VAR_STARTT ] = TS2T(buf->pts, inlink->time_base);

View File

@ -58,6 +58,13 @@ enum VolumeVarName {
VAR_VARS_NB VAR_VARS_NB
}; };
enum ReplayGainType {
REPLAYGAIN_DROP,
REPLAYGAIN_IGNORE,
REPLAYGAIN_TRACK,
REPLAYGAIN_ALBUM,
};
typedef struct VolumeContext { typedef struct VolumeContext {
const AVClass *class; const AVClass *class;
AVFloatDSPContext fdsp; AVFloatDSPContext fdsp;
@ -67,6 +74,7 @@ typedef struct VolumeContext {
AVExpr *volume_pexpr; AVExpr *volume_pexpr;
double var_values[VAR_VARS_NB]; double var_values[VAR_VARS_NB];
enum ReplayGainType replaygain;
double volume; double volume;
int volume_i; int volume_i;
int channels; int channels;