Commit 6bd1b7b5 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: ogg: fix reading flac metadata

parent 48b5ccf9
...@@ -146,7 +146,7 @@ static bool Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * ); ...@@ -146,7 +146,7 @@ static bool Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
static bool Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * ); static bool Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
static void Ogg_ReadOpusHeader( 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_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 void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
static bool Ogg_ReadDiracHeader( 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 * ); static bool Ogg_ReadVP8Header( demux_t *, logical_stream_t *, ogg_packet * );
...@@ -1234,15 +1234,17 @@ static void Ogg_DecodePacket( demux_t *p_demux, ...@@ -1234,15 +1234,17 @@ static void Ogg_DecodePacket( demux_t *p_demux,
break; break;
case VLC_CODEC_FLAC: 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; 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; Ogg_ReadFlacStreamInfo( p_demux, p_stream, p_oggpacket );
if( p_oggpacket->bytes >= 9 ) }
else if( p_stream->i_packets_backup == 1 )
{
if( p_oggpacket->bytes >= 9 ) /* Point to Flac for extradata */
{ {
p_oggpacket->packet += 9; p_oggpacket->packet += 9;
p_oggpacket->bytes -= 9; p_oggpacket->bytes -= 9;
...@@ -1580,7 +1582,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) ...@@ -1580,7 +1582,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
(int)p_stream->i_pre_skip); (int)p_stream->i_pre_skip);
p_stream->i_skip_frames = 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 && else if( oggpacket.bytes >= 4 &&
! memcmp( oggpacket.packet, "fLaC", 4 ) ) ! memcmp( oggpacket.packet, "fLaC", 4 ) )
{ {
...@@ -1590,10 +1592,12 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) ...@@ -1590,10 +1592,12 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
* important info in the second header packet!!! * important info in the second header packet!!!
* (STREAMINFO metadata is in the following packet) */ * (STREAMINFO metadata is in the following packet) */
p_stream->b_force_backup = true; 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_cat = AUDIO_ES;
p_stream->fmt.i_codec = VLC_CODEC_FLAC; 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 && else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F &&
! memcmp( &oggpacket.packet[1], "FLAC", 4 ) && ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) &&
! memcmp( &oggpacket.packet[9], "fLaC", 4 ) ) ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) )
...@@ -1604,13 +1608,16 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) ...@@ -1604,13 +1608,16 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
"(%i header packets)", "(%i header packets)",
oggpacket.packet[5], oggpacket.packet[6], oggpacket.packet[5], oggpacket.packet[6],
i_packets ); 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->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_cat = AUDIO_ES;
p_stream->fmt.i_codec = VLC_CODEC_FLAC; p_stream->fmt.i_codec = VLC_CODEC_FLAC;
oggpacket.packet += 13; oggpacket.bytes -= 13; oggpacket.packet += 13; oggpacket.bytes -= 13; /* Point to the streaminfo */
if ( !Ogg_ReadFlacHeader( p_demux, p_stream, &oggpacket ) ) if ( !Ogg_ReadFlacStreamInfo( p_demux, p_stream, &oggpacket ) )
{ {
msg_Dbg( p_demux, "found invalid Flac header" ); msg_Dbg( p_demux, "found invalid Flac header" );
Ogg_LogicalStreamDelete( p_demux, p_stream ); Ogg_LogicalStreamDelete( p_demux, p_stream );
...@@ -2420,6 +2427,30 @@ static void Ogg_ExtractComments( demux_t *p_demux, es_format_t *p_fmt, ...@@ -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, static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
const void *p_headers, unsigned i_headers, unsigned i_skip ) 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 ...@@ -2465,7 +2496,7 @@ static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t
/* TODO */ /* TODO */
case VLC_CODEC_FLAC: 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; break;
/* No meta data */ /* No meta data */
...@@ -2740,7 +2771,7 @@ static void Ogg_ReadOpusHeader( logical_stream_t *p_stream, ...@@ -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 ); 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 ) ogg_packet *p_oggpacket )
{ {
/* Parse the STREAMINFO metadata */ /* Parse the STREAMINFO metadata */
......
...@@ -149,6 +149,10 @@ typedef struct logical_stream_s ...@@ -149,6 +149,10 @@ typedef struct logical_stream_s
int32_t i_framesize; int32_t i_framesize;
int32_t i_framesperpacket; int32_t i_framesperpacket;
} speex; } speex;
struct
{
bool b_old;
} flac;
} special; } special;
} logical_stream_t; } logical_stream_t;
......
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