... | ... |
@@ -616,6 +616,23 @@ precision of the volume scaling. |
616 | 616 |
@item double |
617 | 617 |
64-bit floating-point; limits input sample format to DBL. |
618 | 618 |
@end table |
619 |
+ |
|
620 |
+@item replaygain |
|
621 |
+Behaviour on encountering ReplayGain side data in input frames. |
|
622 |
+ |
|
623 |
+@table @option |
|
624 |
+@item drop |
|
625 |
+Remove ReplayGain side data, ignoring its contents (the default). |
|
626 |
+ |
|
627 |
+@item ignore |
|
628 |
+Ignore ReplayGain side data, but leave it in the frame. |
|
629 |
+ |
|
630 |
+@item track |
|
631 |
+Prefer track gain, if present. |
|
632 |
+ |
|
633 |
+@item album |
|
634 |
+Prefer album gain, if present. |
|
635 |
+@end table |
|
619 | 636 |
@end table |
620 | 637 |
|
621 | 638 |
@subsection Examples |
... | ... |
@@ -28,7 +28,10 @@ |
28 | 28 |
#include "libavutil/common.h" |
29 | 29 |
#include "libavutil/eval.h" |
30 | 30 |
#include "libavutil/float_dsp.h" |
31 |
+#include "libavutil/intreadwrite.h" |
|
31 | 32 |
#include "libavutil/opt.h" |
33 |
+#include "libavutil/replaygain.h" |
|
34 |
+ |
|
32 | 35 |
#include "audio.h" |
33 | 36 |
#include "avfilter.h" |
34 | 37 |
#include "formats.h" |
... | ... |
@@ -50,6 +53,12 @@ static const AVOption options[] = { |
50 | 50 |
{ "fixed", "8-bit fixed-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED }, INT_MIN, INT_MAX, A, "precision" }, |
51 | 51 |
{ "float", "32-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT }, INT_MIN, INT_MAX, A, "precision" }, |
52 | 52 |
{ "double", "64-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A, "precision" }, |
53 |
+ { "replaygain", "Apply replaygain side data when present", |
|
54 |
+ OFFSET(replaygain), AV_OPT_TYPE_INT, { .i64 = REPLAYGAIN_DROP }, REPLAYGAIN_DROP, REPLAYGAIN_ALBUM, A, "replaygain" }, |
|
55 |
+ { "drop", "replaygain side data is dropped", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_DROP }, 0, 0, A, "replaygain" }, |
|
56 |
+ { "ignore", "replaygain side data is ignored", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_IGNORE }, 0, 0, A, "replaygain" }, |
|
57 |
+ { "track", "track gain is preferred", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_TRACK }, 0, 0, A, "replaygain" }, |
|
58 |
+ { "album", "album gain is preferred", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_ALBUM }, 0, 0, A, "replaygain" }, |
|
53 | 59 |
{ NULL }, |
54 | 60 |
}; |
55 | 61 |
|
... | ... |
@@ -229,8 +238,38 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) |
229 | 229 |
AVFilterLink *outlink = inlink->dst->outputs[0]; |
230 | 230 |
int nb_samples = buf->nb_samples; |
231 | 231 |
AVFrame *out_buf; |
232 |
+ AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); |
|
232 | 233 |
int ret; |
233 | 234 |
|
235 |
+ if (sd && vol->replaygain != REPLAYGAIN_IGNORE) { |
|
236 |
+ if (vol->replaygain != REPLAYGAIN_DROP) { |
|
237 |
+ AVReplayGain *replaygain = (AVReplayGain*)sd->data; |
|
238 |
+ int32_t gain; |
|
239 |
+ float g; |
|
240 |
+ |
|
241 |
+ if (vol->replaygain == REPLAYGAIN_TRACK && |
|
242 |
+ replaygain->track_gain != INT32_MIN) |
|
243 |
+ gain = replaygain->track_gain; |
|
244 |
+ else if (replaygain->album_gain != INT32_MIN) |
|
245 |
+ gain = replaygain->album_gain; |
|
246 |
+ else { |
|
247 |
+ av_log(inlink->dst, AV_LOG_WARNING, "Both ReplayGain gain " |
|
248 |
+ "values are unknown.\n"); |
|
249 |
+ gain = 100000; |
|
250 |
+ } |
|
251 |
+ g = gain / 100000.0f; |
|
252 |
+ |
|
253 |
+ av_log(inlink->dst, AV_LOG_VERBOSE, |
|
254 |
+ "Using gain %f dB from replaygain side data.\n", g); |
|
255 |
+ |
|
256 |
+ vol->volume = pow(10, g / 20); |
|
257 |
+ vol->volume_i = (int)(vol->volume * 256 + 0.5); |
|
258 |
+ |
|
259 |
+ volume_init(vol); |
|
260 |
+ } |
|
261 |
+ av_frame_remove_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); |
|
262 |
+ } |
|
263 |
+ |
|
234 | 264 |
if (vol->volume == 1.0 || vol->volume_i == 256) |
235 | 265 |
return ff_filter_frame(outlink, buf); |
236 | 266 |
|
... | ... |
@@ -35,10 +35,18 @@ enum PrecisionType { |
35 | 35 |
PRECISION_DOUBLE, |
36 | 36 |
}; |
37 | 37 |
|
38 |
+enum ReplayGainType { |
|
39 |
+ REPLAYGAIN_DROP, |
|
40 |
+ REPLAYGAIN_IGNORE, |
|
41 |
+ REPLAYGAIN_TRACK, |
|
42 |
+ REPLAYGAIN_ALBUM, |
|
43 |
+}; |
|
44 |
+ |
|
38 | 45 |
typedef struct VolumeContext { |
39 | 46 |
const AVClass *class; |
40 | 47 |
AVFloatDSPContext fdsp; |
41 | 48 |
enum PrecisionType precision; |
49 |
+ enum ReplayGainType replaygain; |
|
42 | 50 |
double volume; |
43 | 51 |
int volume_i; |
44 | 52 |
int channels; |