[vlc-commits] demux: ogg: fix reading flac metadata

Francois Cartegnie git at videolan.org
Mon Nov 9 11:04:51 CET 2015


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Nov  9 10:52:52 2015 +0100| [6bd1b7b5990cdc86a7bd88142b8c78b7e6aad94e] | committer: Francois Cartegnie

demux: ogg: fix reading flac metadata

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

 modules/demux/ogg.c |   57 +++++++++++++++++++++++++++++++++++++++------------
 modules/demux/ogg.h |    4 ++++
 2 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c
index ed2993b..6858698 100644
--- a/modules/demux/ogg.c
+++ b/modules/demux/ogg.c
@@ -146,7 +146,7 @@ static bool Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
 static bool Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
 static void Ogg_ReadOpusHeader( logical_stream_t *, ogg_packet * );
 static bool Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * );
-static bool Ogg_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );
+static bool Ogg_ReadFlacStreamInfo( demux_t *, logical_stream_t *, ogg_packet * );
 static void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
 static bool Ogg_ReadDiracHeader( logical_stream_t *, ogg_packet * );
 static bool Ogg_ReadVP8Header( demux_t *, logical_stream_t *, ogg_packet * );
@@ -1234,15 +1234,17 @@ static void Ogg_DecodePacket( demux_t *p_demux,
             break;
 
         case VLC_CODEC_FLAC:
-            if( !p_stream->fmt.audio.i_rate && p_stream->i_packets_backup == 2 )
+            if( p_stream->i_packets_backup == 1 + p_stream->i_extra_headers_packets )
             {
-                Ogg_ReadFlacHeader( p_demux, p_stream, p_oggpacket );
                 p_stream->b_force_backup = false;
             }
-            else if( p_stream->fmt.audio.i_rate )
+            if( p_stream->special.flac.b_old )
             {
-                p_stream->b_force_backup = false;
-                if( p_oggpacket->bytes >= 9 )
+                Ogg_ReadFlacStreamInfo( p_demux, p_stream, p_oggpacket );
+            }
+            else if( p_stream->i_packets_backup == 1 )
+            {
+                if( p_oggpacket->bytes >= 9 ) /* Point to Flac for extradata */
                 {
                     p_oggpacket->packet += 9;
                     p_oggpacket->bytes -= 9;
@@ -1580,7 +1582,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
                              (int)p_stream->i_pre_skip);
                     p_stream->i_skip_frames = p_stream->i_pre_skip;
                 }
-                /* Check for Flac header (< version 1.1.1) */
+                /* Check for OLD Flac header */
                 else if( oggpacket.bytes >= 4 &&
                     ! memcmp( oggpacket.packet, "fLaC", 4 ) )
                 {
@@ -1590,10 +1592,12 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
                      * important info in the second header packet!!!
                      * (STREAMINFO metadata is in the following packet) */
                     p_stream->b_force_backup = true;
+                    p_stream->i_extra_headers_packets = 1;
+                    p_stream->special.flac.b_old = true;
                     p_stream->fmt.i_cat = AUDIO_ES;
                     p_stream->fmt.i_codec = VLC_CODEC_FLAC;
                 }
-                /* Check for Flac header (>= version 1.1.1) */
+                /* Check for Flac header (>= version 1.0.0) */
                 else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F &&
                     ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) &&
                     ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) )
@@ -1604,13 +1608,16 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
                              "(%i header packets)",
                              oggpacket.packet[5], oggpacket.packet[6],
                              i_packets );
-
+                    /* STREAMINFO is in current packet, and then
+                       followed by 0 or more metadata, blockheader prefixed, and first being a vorbis comment */
                     p_stream->b_force_backup = true;
+                    p_stream->i_extra_headers_packets = i_packets;
+                    p_stream->special.flac.b_old = false;
 
                     p_stream->fmt.i_cat = AUDIO_ES;
                     p_stream->fmt.i_codec = VLC_CODEC_FLAC;
-                    oggpacket.packet += 13; oggpacket.bytes -= 13;
-                    if ( !Ogg_ReadFlacHeader( p_demux, p_stream, &oggpacket ) )
+                    oggpacket.packet += 13; oggpacket.bytes -= 13; /* Point to the streaminfo */
+                    if ( !Ogg_ReadFlacStreamInfo( p_demux, p_stream, &oggpacket ) )
                     {
                         msg_Dbg( p_demux, "found invalid Flac header" );
                         Ogg_LogicalStreamDelete( p_demux, p_stream );
@@ -2420,6 +2427,30 @@ static void Ogg_ExtractComments( demux_t *p_demux, es_format_t *p_fmt,
     }
 }
 
+static inline uint32_t GetDW24BE( const uint8_t *p )
+{
+    uint32_t i = ( p[0] << 16 ) + ( p[1] << 8 ) + ( p[2] );
+#ifdef WORDS_BIGENDIAN
+    i = bswap32(i);
+#endif
+    return i;
+}
+
+static void Ogg_ExtractFlacComments( demux_t *p_demux, es_format_t *p_fmt,
+                                     const uint8_t *p_headers, unsigned i_headers )
+{
+    /* Skip Streaminfo 42 bytes / 1st page */
+    if(i_headers <= 46)
+        return;
+    p_headers += 42; i_headers -= 42;
+    /* Block Header 1 + 3 bytes */
+    uint32_t blocksize = GetDW24BE(&p_headers[1]);
+    if(p_headers[0] == 0x84 && blocksize <= i_headers - 4)
+    {
+        Ogg_ExtractComments( p_demux, p_fmt, &p_headers[4], i_headers - 4 );
+    }
+}
+
 static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
                                  const void *p_headers, unsigned i_headers, unsigned i_skip )
 {
@@ -2465,7 +2496,7 @@ static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t
 
     /* TODO */
     case VLC_CODEC_FLAC:
-        msg_Warn( p_demux, "Ogg_ExtractMeta does not support %4.4s", (const char*)&p_fmt->i_codec );
+        Ogg_ExtractFlacComments( p_demux, p_fmt, p_headers, i_headers );
         break;
 
     /* No meta data */
@@ -2740,7 +2771,7 @@ static void Ogg_ReadOpusHeader( logical_stream_t *p_stream,
     p_stream->i_pre_skip = __MAX( 80*48, p_stream->i_pre_skip );
 }
 
-static bool Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
+static bool Ogg_ReadFlacStreamInfo( demux_t *p_demux, logical_stream_t *p_stream,
                                 ogg_packet *p_oggpacket )
 {
     /* Parse the STREAMINFO metadata */
diff --git a/modules/demux/ogg.h b/modules/demux/ogg.h
index c30b799..cb312ed 100644
--- a/modules/demux/ogg.h
+++ b/modules/demux/ogg.h
@@ -149,6 +149,10 @@ typedef struct logical_stream_s
             int32_t i_framesize;
             int32_t i_framesperpacket;
         } speex;
+        struct
+        {
+            bool b_old;
+        } flac;
     } special;
 
 } logical_stream_t;



More information about the vlc-commits mailing list