Commit 256391f7 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: ogg: add replay gain support

parent d6e513d1
...@@ -582,7 +582,7 @@ static void ParseComment( demux_t *p_demux, const uint8_t *p_data, int i_data ) ...@@ -582,7 +582,7 @@ static void ParseComment( demux_t *p_demux, const uint8_t *p_data, int i_data )
vorbis_ParseComment( &p_sys->p_meta, &p_data[4], i_data - 4, vorbis_ParseComment( &p_sys->p_meta, &p_data[4], i_data - 4,
&p_sys->i_attachments, &p_sys->attachments, &p_sys->i_attachments, &p_sys->attachments,
&p_sys->i_cover_score, &p_sys->i_cover_idx, NULL, NULL ); &p_sys->i_cover_score, &p_sys->i_cover_idx, NULL, NULL, NULL, NULL );
} }
static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, int i_data ) static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, int i_data )
......
...@@ -133,7 +133,7 @@ static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_strea ...@@ -133,7 +133,7 @@ static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_strea
static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream ); static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream );
/* */ /* */
static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8_t *p_headers, int i_headers ); static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers );
static int64_t Ogg_GetLastPacket( demux_t *p_demux, logical_stream_t *p_stream, double f_rate ); static int64_t Ogg_GetLastPacket( demux_t *p_demux, logical_stream_t *p_stream, double f_rate );
/* Logical bitstream headers */ /* Logical bitstream headers */
...@@ -848,7 +848,7 @@ static void Ogg_DecodePacket( demux_t *p_demux, ...@@ -848,7 +848,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
p_stream->p_es, &p_stream->fmt ); p_stream->p_es, &p_stream->fmt );
if( p_stream->i_headers > 0 ) if( p_stream->i_headers > 0 )
Ogg_ExtractMeta( p_demux, p_stream->fmt.i_codec, Ogg_ExtractMeta( p_demux, & p_stream->fmt,
p_stream->p_headers, p_stream->i_headers ); p_stream->p_headers, p_stream->i_headers );
/* we're not at BOS anymore for this logical stream */ /* we're not at BOS anymore for this logical stream */
...@@ -1863,7 +1863,8 @@ static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t * ...@@ -1863,7 +1863,8 @@ static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *
return !b_compatible; return !b_compatible;
} }
static void Ogg_ExtractXiphMeta( demux_t *p_demux, const void *p_headers, unsigned i_headers, unsigned i_skip ) static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
const void *p_headers, unsigned i_headers, unsigned i_skip )
{ {
demux_sys_t *p_ogg = p_demux->p_sys; demux_sys_t *p_ogg = p_demux->p_sys;
...@@ -1878,10 +1879,18 @@ static void Ogg_ExtractXiphMeta( demux_t *p_demux, const void *p_headers, unsign ...@@ -1878,10 +1879,18 @@ static void Ogg_ExtractXiphMeta( demux_t *p_demux, const void *p_headers, unsign
{ {
int i_cover_score = 0; int i_cover_score = 0;
int i_cover_idx = 0; int i_cover_idx = 0;
float pf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
float pf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
for(int i=0; i< AUDIO_REPLAY_GAIN_MAX; i++ )
{
pf_replay_gain[i] = 0;
pf_replay_peak[i] = 0;
}
vorbis_ParseComment( &p_ogg->p_meta, (uint8_t*)pp_data[1] + i_skip, pi_size[1] - i_skip, vorbis_ParseComment( &p_ogg->p_meta, (uint8_t*)pp_data[1] + i_skip, pi_size[1] - i_skip,
&p_ogg->i_attachments, &p_ogg->attachments, &p_ogg->i_attachments, &p_ogg->attachments,
&i_cover_score, &i_cover_idx, &i_cover_score, &i_cover_idx,
&p_ogg->i_seekpoints, &p_ogg->pp_seekpoints ); &p_ogg->i_seekpoints, &p_ogg->pp_seekpoints,
&pf_replay_gain, &pf_replay_peak );
if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments ) if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments )
{ {
char psz_url[128]; char psz_url[128];
...@@ -1889,6 +1898,22 @@ static void Ogg_ExtractXiphMeta( demux_t *p_demux, const void *p_headers, unsign ...@@ -1889,6 +1898,22 @@ static void Ogg_ExtractXiphMeta( demux_t *p_demux, const void *p_headers, unsign
p_ogg->attachments[i_cover_idx]->psz_name ); p_ogg->attachments[i_cover_idx]->psz_name );
vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url ); vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url );
} }
for ( int i=0; i<AUDIO_REPLAY_GAIN_MAX;i++ )
{
if ( pf_replay_gain[i] != 0 )
{
p_fmt->audio_replay_gain.pb_gain[i] = true;
p_fmt->audio_replay_gain.pf_gain[i] = pf_replay_gain[i];
msg_Dbg( p_demux, "setting replay gain %d to %f", i, pf_replay_gain[i] );
}
if ( pf_replay_peak[i] != 0 )
{
p_fmt->audio_replay_gain.pb_peak[i] = true;
p_fmt->audio_replay_gain.pf_peak[i] = pf_replay_peak[i];
msg_Dbg( p_demux, "setting replay peak %d to %f", i, pf_replay_gain[i] );
}
}
} }
if( p_ogg->i_seekpoints > 1 ) if( p_ogg->i_seekpoints > 1 )
...@@ -1899,33 +1924,33 @@ static void Ogg_ExtractXiphMeta( demux_t *p_demux, const void *p_headers, unsign ...@@ -1899,33 +1924,33 @@ static void Ogg_ExtractXiphMeta( demux_t *p_demux, const void *p_headers, unsign
for( unsigned i = 0; i < i_count; i++ ) for( unsigned i = 0; i < i_count; i++ )
free( pp_data[i] ); free( pp_data[i] );
} }
static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8_t *p_headers, int i_headers ) static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers )
{ {
demux_sys_t *p_ogg = p_demux->p_sys; demux_sys_t *p_ogg = p_demux->p_sys;
switch( i_codec ) switch( p_fmt->i_codec )
{ {
/* 3 headers with the 2° one being the comments */ /* 3 headers with the 2° one being the comments */
case VLC_CODEC_VORBIS: case VLC_CODEC_VORBIS:
case VLC_CODEC_THEORA: case VLC_CODEC_THEORA:
Ogg_ExtractXiphMeta( p_demux, p_headers, i_headers, 1+6 ); Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+6 );
break; break;
case VLC_CODEC_OPUS: case VLC_CODEC_OPUS:
Ogg_ExtractXiphMeta( p_demux, p_headers, i_headers, 8 ); Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 8 );
break; break;
case VLC_CODEC_SPEEX: case VLC_CODEC_SPEEX:
Ogg_ExtractXiphMeta( p_demux, p_headers, i_headers, 0 ); Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 0 );
break; break;
/* N headers with the 2° one being the comments */ /* N headers with the 2° one being the comments */
case VLC_CODEC_KATE: case VLC_CODEC_KATE:
/* 1 byte for header type, 7 bytes for magic, 1 reserved zero byte */ /* 1 byte for header type, 7 bytes for magic, 1 reserved zero byte */
Ogg_ExtractXiphMeta( p_demux, p_headers, i_headers, 1+7+1 ); Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+7+1 );
break; break;
/* TODO */ /* TODO */
case VLC_CODEC_FLAC: case VLC_CODEC_FLAC:
msg_Warn( p_demux, "Ogg_ExtractMeta does not support %4.4s", (const char*)&i_codec ); msg_Warn( p_demux, "Ogg_ExtractMeta does not support %4.4s", (const char*)&p_fmt->i_codec );
break; break;
/* No meta data */ /* No meta data */
......
...@@ -148,7 +148,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta, ...@@ -148,7 +148,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
const uint8_t *p_data, int i_data, const uint8_t *p_data, int i_data,
int *i_attachments, input_attachment_t ***attachments, int *i_attachments, input_attachment_t ***attachments,
int *i_cover_score, int *i_cover_idx, int *i_cover_score, int *i_cover_idx,
int *i_seekpoint, seekpoint_t ***ppp_seekpoint ) int *i_seekpoint, seekpoint_t ***ppp_seekpoint,
float (* ppf_replay_gain)[AUDIO_REPLAY_GAIN_MAX],
float (* ppf_replay_peak)[AUDIO_REPLAY_GAIN_MAX] )
{ {
int n; int n;
int i_comment; int i_comment;
...@@ -292,6 +294,40 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta, ...@@ -292,6 +294,40 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
*i_attachments, *attachments, p_attachment ); *i_attachments, *attachments, p_attachment );
} }
} }
else if ( ppf_replay_gain && ppf_replay_peak && !strncmp(psz_comment, "REPLAYGAIN_", 11) )
{
char *p = strchr( psz_comment, '=' );
char *psz_val;
if (!p) continue;
if ( !strncmp(psz_comment, "REPLAYGAIN_TRACK_GAIN=", 22) )
{
psz_val = malloc( strlen(p+1) + 1 );
if (!psz_val) continue;
if( sscanf( ++p, "%s dB", psz_val ) == 1 )
{
(*ppf_replay_gain)[AUDIO_REPLAY_GAIN_TRACK] = us_atof( psz_val );
free( psz_val );
}
}
else if ( !strncmp(psz_comment, "REPLAYGAIN_ALBUM_GAIN=", 22) )
{
psz_val = malloc( strlen(p+1) + 1 );
if (!psz_val) continue;
if( sscanf( ++p, "%s dB", psz_val ) == 1 )
{
(*ppf_replay_gain)[AUDIO_REPLAY_GAIN_ALBUM] = us_atof( psz_val );
free( psz_val );
}
}
else if ( !strncmp(psz_comment, "REPLAYGAIN_ALBUM_PEAK=", 22) )
{
(*ppf_replay_peak)[AUDIO_REPLAY_GAIN_ALBUM] = us_atof( ++p );
}
else if ( !strncmp(psz_comment, "REPLAYGAIN_TRACK_PEAK=", 22) )
{
(*ppf_replay_peak)[AUDIO_REPLAY_GAIN_TRACK] = us_atof( ++p );
}
}
else if( !strncmp(psz_comment, "CHAPTER", 7) ) else if( !strncmp(psz_comment, "CHAPTER", 7) )
{ {
unsigned int i_chapt; unsigned int i_chapt;
......
...@@ -36,7 +36,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta, ...@@ -36,7 +36,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
const uint8_t *p_data, int i_data, const uint8_t *p_data, int i_data,
int *i_attachments, input_attachment_t ***attachments, int *i_attachments, input_attachment_t ***attachments,
int *i_cover_score, int *i_cover_idx, int *i_cover_score, int *i_cover_idx,
int *i_seekpoint, seekpoint_t ***ppp_seekpoint ); int *i_seekpoint, seekpoint_t ***ppp_seekpoint,
float (* ppf_replay_gain)[AUDIO_REPLAY_GAIN_MAX],
float (* ppf_replay_peak)[AUDIO_REPLAY_GAIN_MAX] );
static const struct { static const struct {
const char *psz_tag; const char *psz_tag;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment