Commit 9735a6b2 authored by Ludovic Fauvet's avatar Ludovic Fauvet Committed by Jean-Baptiste Kempf

ogg: fix computation of vorbis stream length (close #1859)

Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
(cherry picked from commit 2a19f53cfef8183170cb32be9bb84d7b07a7837b)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 4574b150
...@@ -135,10 +135,11 @@ static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t * ...@@ -135,10 +135,11 @@ static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *
/* */ /* */
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, vlc_fourcc_t i_codec, const uint8_t *p_headers, int i_headers );
static int64_t Ogg_GetLastPacket( demux_t *p_demux, logical_stream_t *p_stream, ogg_packet *p_oggpacket, double f_rate );
/* Logical bitstream headers */ /* Logical bitstream headers */
static void Ogg_ReadTheoraHeader( demux_t *, logical_stream_t *, ogg_packet * ); static void Ogg_ReadTheoraHeader( demux_t *, logical_stream_t *, ogg_packet * );
static void Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * ); static void Ogg_ReadVorbisHeader( demux_t *, logical_stream_t *, ogg_packet * );
static void Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * ); static void Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
static void Ogg_ReadOpusHeader( demux_t *, logical_stream_t *, ogg_packet * ); static void Ogg_ReadOpusHeader( demux_t *, logical_stream_t *, ogg_packet * );
static void Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * ); static void Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * );
...@@ -317,7 +318,7 @@ static int Demux( demux_t * p_demux ) ...@@ -317,7 +318,7 @@ static int Demux( demux_t * p_demux )
oggpacket.bytes >= 7 && oggpacket.bytes >= 7 &&
! memcmp( oggpacket.packet, "\x01vorbis", 7 ) ) ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
{ {
Ogg_ReadVorbisHeader( p_stream, &oggpacket ); Ogg_ReadVorbisHeader( p_demux, p_stream, &oggpacket );
p_stream->i_secondary_header_packets = 0; p_stream->i_secondary_header_packets = 0;
} }
else if( p_stream->fmt.i_codec == VLC_CODEC_CMML ) else if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
...@@ -1096,7 +1097,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) ...@@ -1096,7 +1097,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
if( oggpacket.bytes >= 7 && if( oggpacket.bytes >= 7 &&
! memcmp( oggpacket.packet, "\x01vorbis", 7 ) ) ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
{ {
Ogg_ReadVorbisHeader( p_stream, &oggpacket ); Ogg_ReadVorbisHeader( p_demux, p_stream, &oggpacket );
msg_Dbg( p_demux, "found vorbis header" ); msg_Dbg( p_demux, "found vorbis header" );
} }
/* Check for Speex header */ /* Check for Speex header */
...@@ -1825,6 +1826,19 @@ static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8 ...@@ -1825,6 +1826,19 @@ static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8
p_demux->info.i_update |= INPUT_UPDATE_META; p_demux->info.i_update |= INPUT_UPDATE_META;
} }
static int64_t Ogg_GetLastPacket( demux_t *p_demux, logical_stream_t *p_stream,
ogg_packet *p_oggpacket, double f_rate )
{
int64_t last_packet = oggseek_get_last_frame( p_demux, p_stream );
/*
* Since there's quite a good chance that ogg_stream_packetout was called,
* the given p_oggpacket may point to invalid data. Fill it with some valid ones
*/
ogg_stream_packetpeek( &p_stream->os, p_oggpacket );
return ( last_packet >= 0 ) ? last_packet / f_rate : -1;
}
static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream, static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream,
ogg_packet *p_oggpacket ) ogg_packet *p_oggpacket )
{ {
...@@ -1885,6 +1899,7 @@ static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream, ...@@ -1885,6 +1899,7 @@ static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream,
i_version = i_major * 1000000 + i_minor * 1000 + i_subminor; i_version = i_major * 1000000 + i_minor * 1000 + i_subminor;
p_stream->i_keyframe_offset = 0; p_stream->i_keyframe_offset = 0;
p_stream->f_rate = ((float)i_fps_numerator) / i_fps_denominator;
if ( i_version >= 3002001 ) if ( i_version >= 3002001 )
{ {
...@@ -1892,24 +1907,14 @@ static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream, ...@@ -1892,24 +1907,14 @@ static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream,
} }
if ( p_demux->p_sys->i_length < 0 ) if ( p_demux->p_sys->i_length < 0 )
{ {
int64_t last_frame = oggseek_get_last_frame( p_demux, p_stream ); int64_t last_packet = Ogg_GetLastPacket( p_demux, p_stream, p_oggpacket, p_stream->f_rate );
/* if ( last_packet >= 0 )
* Since there's quite a good chance that ogg_stream_packetout was called, p_demux->p_sys->i_length = last_packet;
* the given p_oggpacket may point to invalid data. Fill it with some valid ones
*/
ogg_stream_packetpeek( &p_stream->os, p_oggpacket );
if ( last_frame >= 0 )
{
p_demux->p_sys->i_length = last_frame / ((float)i_fps_numerator /
(float)i_fps_denominator);
}
} }
p_stream->f_rate = ((float)i_fps_numerator) / i_fps_denominator;
} }
static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream, static void Ogg_ReadVorbisHeader( demux_t *p_demux, logical_stream_t *p_stream,
ogg_packet *p_oggpacket ) ogg_packet *p_oggpacket )
{ {
oggpack_buffer opb; oggpack_buffer opb;
...@@ -1930,6 +1935,13 @@ static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream, ...@@ -1930,6 +1935,13 @@ static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
oggpack_read( &opb, 32 ); oggpack_read( &opb, 32 );
oggpack_adv( &opb, 32 ); oggpack_adv( &opb, 32 );
p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 ); p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
if ( p_demux->p_sys->i_length < 0 )
{
int64_t last_packet = Ogg_GetLastPacket( p_demux, p_stream, p_oggpacket, p_stream->f_rate );
if ( last_packet >= 0 )
p_demux->p_sys->i_length = last_packet;
}
} }
static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream, static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
...@@ -1985,17 +1997,9 @@ static void Ogg_ReadOpusHeader( demux_t *p_demux, ...@@ -1985,17 +1997,9 @@ static void Ogg_ReadOpusHeader( demux_t *p_demux,
if ( p_demux->p_sys->i_length < 0 ) if ( p_demux->p_sys->i_length < 0 )
{ {
int64_t last_frame = oggseek_get_last_frame( p_demux, p_stream ); int64_t last_packet = Ogg_GetLastPacket( p_demux, p_stream, p_oggpacket, p_stream->f_rate );
/* if ( last_packet >= 0 )
* Since there's quite a good chance that ogg_stream_packetout was called, p_demux->p_sys->i_length = last_packet;
* the given p_oggpacket may point to invalid data. Fill it with some valid ones
*/
ogg_stream_packetpeek( &p_stream->os, p_oggpacket );
if ( last_frame >= 0 )
{
p_demux->p_sys->i_length = last_frame / p_stream->f_rate;
}
} }
} }
......
...@@ -731,6 +731,7 @@ int64_t oggseek_get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream ) ...@@ -731,6 +731,7 @@ int64_t oggseek_get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream )
int64_t i_frame = -1; int64_t i_frame = -1;
if ( p_stream->fmt.i_codec == VLC_CODEC_THEORA || if ( p_stream->fmt.i_codec == VLC_CODEC_THEORA ||
p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
p_stream->fmt.i_codec == VLC_CODEC_OPUS ) p_stream->fmt.i_codec == VLC_CODEC_OPUS )
{ {
i_frame = get_last_frame ( p_demux, p_stream ); i_frame = get_last_frame ( p_demux, p_stream );
......
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