[vlc-commits] demux: ogg: add replay gain support

Francois Cartegnie git at videolan.org
Thu Sep 12 21:36:05 CEST 2013


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Sep 12 19:00:23 2013 +0200| [256391f7caacf5b47d5f9ba27ff7368dfaf009f1] | committer: Francois Cartegnie

demux: ogg: add replay gain support

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=256391f7caacf5b47d5f9ba27ff7368dfaf009f1
---

 modules/demux/flac.c          |    2 +-
 modules/demux/ogg.c           |   47 +++++++++++++++++++++++++++++++----------
 modules/demux/xiph_metadata.c |   38 ++++++++++++++++++++++++++++++++-
 modules/demux/xiph_metadata.h |    4 +++-
 4 files changed, 77 insertions(+), 14 deletions(-)

diff --git a/modules/demux/flac.c b/modules/demux/flac.c
index a2ac4dc..1356835 100644
--- a/modules/demux/flac.c
+++ b/modules/demux/flac.c
@@ -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,
         &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 )
diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c
index 57edb99..749c346 100644
--- a/modules/demux/ogg.c
+++ b/modules/demux/ogg.c
@@ -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 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 );
 
 /* Logical bitstream headers */
@@ -848,7 +848,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
                                     p_stream->p_es, &p_stream->fmt );
 
                 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 );
 
                 /* 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 *
 
     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;
 
@@ -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_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,
                              &p_ogg->i_attachments, &p_ogg->attachments,
                              &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 )
         {
             char psz_url[128];
@@ -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 );
             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 )
@@ -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++ )
         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;
 
-    switch( i_codec )
+    switch( p_fmt->i_codec )
     {
     /* 3 headers with the 2° one being the comments */
     case VLC_CODEC_VORBIS:
     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;
     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;
     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;
 
     /* N headers with the 2° one being the comments */
     case VLC_CODEC_KATE:
         /* 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;
 
     /* TODO */
     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;
 
     /* No meta data */
diff --git a/modules/demux/xiph_metadata.c b/modules/demux/xiph_metadata.c
index 16e060d..bef41e2 100644
--- a/modules/demux/xiph_metadata.c
+++ b/modules/demux/xiph_metadata.c
@@ -148,7 +148,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
         const uint8_t *p_data, int i_data,
         int *i_attachments, input_attachment_t ***attachments,
         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 i_comment;
@@ -292,6 +294,40 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
                     *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) )
         {
             unsigned int i_chapt;
diff --git a/modules/demux/xiph_metadata.h b/modules/demux/xiph_metadata.h
index de97c2b..6e318f5 100644
--- a/modules/demux/xiph_metadata.h
+++ b/modules/demux/xiph_metadata.h
@@ -36,7 +36,9 @@ void vorbis_ParseComment( vlc_meta_t **pp_meta,
         const uint8_t *p_data, int i_data,
         int *i_attachments, input_attachment_t ***attachments,
         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 {
   const char *psz_tag;



More information about the vlc-commits mailing list