[vlc-devel] [PATCH] demux: mpeg: add support for lame's replaygain extension
Anatoliy Anischovich
lin.aaa.lin at gmail.com
Tue Dec 30 16:25:06 CET 2014
---
modules/demux/mpeg/es.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/modules/demux/mpeg/es.c b/modules/demux/mpeg/es.c
index dacd452..85447d9 100644
--- a/modules/demux/mpeg/es.c
+++ b/modules/demux/mpeg/es.c
@@ -91,6 +91,14 @@ typedef struct
int (*pf_init)( demux_t *p_demux );
} codec_t;
+typedef struct
+{
+ char psz_version[10];
+ int i_lowpass;
+ float pf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
+ float pf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
+} lame_extra_t;
+
struct demux_sys_t
{
codec_t codec;
@@ -124,6 +132,8 @@ struct demux_sys_t
int i_bytes;
int i_bitrate_avg;
int i_frame_samples;
+ lame_extra_t lame;
+ bool b_lame;
} xing;
};
@@ -209,6 +219,26 @@ static int OpenCommon( demux_t *p_demux,
return VLC_EGENERIC;
}
+ if( p_sys->xing.b_lame )
+ {
+ lame_extra_t *p_lame = &p_sys->xing.lame;
+ es_format_t *p_fmt = &p_sys->p_packetizer->fmt_out;
+
+ for( int i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
+ {
+ if ( p_lame->pf_replay_gain[i] != 0 )
+ {
+ p_fmt->audio_replay_gain.pb_gain[i] = true;
+ p_fmt->audio_replay_gain.pf_gain[i] = p_lame->pf_replay_gain[i];
+ }
+ if ( p_lame->pf_replay_peak[i] != 0 )
+ {
+ p_fmt->audio_replay_gain.pb_peak[i] = true;
+ p_fmt->audio_replay_gain.pf_peak[i] = p_lame->pf_replay_peak[i];
+ }
+ }
+ }
+
while( vlc_object_alive( p_demux ) )
{
if( Parse( p_demux, &p_sys->p_packetized_data ) )
@@ -743,6 +773,30 @@ static uint32_t MpgaXingGetDWBE( const uint8_t **pp_xing, int *pi_xing, uint32_t
return v;
}
+static uint16_t MpgaXingGetWBE( const uint8_t **pp_xing, int *pi_xing, uint16_t i_default )
+{
+ if( *pi_xing < 2 )
+ return i_default;
+
+ uint16_t v = GetWBE( *pp_xing );
+
+ MpgaXingSkip( pp_xing, pi_xing, 2 );
+
+ return v;
+}
+
+static double MpgaXingLameConvertGain( uint16_t x )
+{
+ double gain = (x & 0x1FF) / 10.0;
+
+ return x & 0x200 ? -gain : gain;
+}
+
+static double MpgaXingLameConvertPeak( uint32_t x )
+{
+ return x / 8388608.0; /* pow(2, 23) */
+}
+
static int MpgaInit( demux_t *p_demux )
{
demux_sys_t *p_sys = p_demux->p_sys;
@@ -802,6 +856,32 @@ static int MpgaInit( demux_t *p_demux )
p_sys->xing.i_bytes, p_sys->xing.i_frames,
p_sys->xing.i_frame_samples );
}
+
+ if( i_xing >= 20 && memcmp( p_xing, "LAME", 4 ) == 0)
+ {
+ p_sys->xing.b_lame = true;
+ lame_extra_t *p_lame = &p_sys->xing.lame;
+
+ memcpy( p_lame->psz_version, p_xing, 9 );
+ p_lame->psz_version[9] = '\0';
+
+ MpgaXingSkip( &p_xing, &i_xing, 9 );
+ MpgaXingSkip( &p_xing, &i_xing, 1 ); /* rev_method */
+
+ p_lame->i_lowpass = (*p_xing) * 100;
+ MpgaXingSkip( &p_xing, &i_xing, 1 );
+
+ uint32_t peak = MpgaXingGetDWBE( &p_xing, &i_xing, 0 );
+ uint16_t track = MpgaXingGetWBE( &p_xing, &i_xing, 0 );
+ uint16_t album = MpgaXingGetWBE( &p_xing, &i_xing, 0 );
+
+ p_lame->pf_replay_peak[AUDIO_REPLAY_GAIN_TRACK] = (float) MpgaXingLameConvertPeak( peak );
+ p_lame->pf_replay_gain[AUDIO_REPLAY_GAIN_TRACK] = (float) MpgaXingLameConvertGain( track );
+ p_lame->pf_replay_gain[AUDIO_REPLAY_GAIN_ALBUM] = (float) MpgaXingLameConvertGain( album );
+
+ MpgaXingSkip( &p_xing, &i_xing, 1 ); /* flags */
+ }
+
return VLC_SUCCESS;
}
--
1.9.1
More information about the vlc-devel
mailing list