[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