Commit 1e604e1f authored by Timothy B. Terriberry's avatar Timothy B. Terriberry Committed by Jean-Baptiste Kempf

ogg: Fix borken stream resets.

Commit 78a8771f attempted to reset the ogg_stream_state in
find_last_frame(), but it tries to do so using a non-existent page
and then leaks memory (due to using ogg_stream_init() instead of
ogg_stream_reset()). Its caller, Ogg_GetLastPacket(), then tries
to restore the contents of the current packet, but its call to
ogg_stream_pageseek() will immediately fail, leaving the dangling
packet pointers untouched.

Instead, just back up the whole stream state and restore it on
exit. This fixes both problems.
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
(cherry picked from commit d6aeeebe0c7ec9f4defe1751454bc3c1943d84e1)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent c14c1b13
...@@ -135,7 +135,7 @@ static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t * ...@@ -135,7 +135,7 @@ 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 ); static int64_t Ogg_GetLastPacket( demux_t *p_demux, logical_stream_t *p_stream, 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 * );
...@@ -1827,15 +1827,9 @@ static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8 ...@@ -1827,15 +1827,9 @@ static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8
} }
static int64_t Ogg_GetLastPacket( demux_t *p_demux, logical_stream_t *p_stream, static int64_t Ogg_GetLastPacket( demux_t *p_demux, logical_stream_t *p_stream,
ogg_packet *p_oggpacket, double f_rate ) double f_rate )
{ {
int64_t last_packet = oggseek_get_last_frame( p_demux, p_stream ); 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; return ( last_packet >= 0 ) ? last_packet / f_rate : -1;
} }
...@@ -1907,7 +1901,7 @@ static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream, ...@@ -1907,7 +1901,7 @@ 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_packet = Ogg_GetLastPacket( p_demux, p_stream, p_oggpacket, p_stream->f_rate ); int64_t last_packet = Ogg_GetLastPacket( p_demux, p_stream, p_stream->f_rate );
if ( last_packet >= 0 ) if ( last_packet >= 0 )
p_demux->p_sys->i_length = last_packet; p_demux->p_sys->i_length = last_packet;
} }
...@@ -1938,7 +1932,7 @@ static void Ogg_ReadVorbisHeader( demux_t *p_demux, logical_stream_t *p_stream, ...@@ -1938,7 +1932,7 @@ static void Ogg_ReadVorbisHeader( 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_packet = Ogg_GetLastPacket( p_demux, p_stream, p_oggpacket, p_stream->f_rate ); int64_t last_packet = Ogg_GetLastPacket( p_demux, p_stream, p_stream->f_rate );
if ( last_packet >= 0 ) if ( last_packet >= 0 )
p_demux->p_sys->i_length = last_packet; p_demux->p_sys->i_length = last_packet;
} }
...@@ -1997,7 +1991,7 @@ static void Ogg_ReadOpusHeader( demux_t *p_demux, ...@@ -1997,7 +1991,7 @@ 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_packet = Ogg_GetLastPacket( p_demux, p_stream, p_oggpacket, p_stream->f_rate ); int64_t last_packet = Ogg_GetLastPacket( p_demux, p_stream, p_stream->f_rate );
if ( last_packet >= 0 ) if ( last_packet >= 0 )
p_demux->p_sys->i_length = last_packet; p_demux->p_sys->i_length = last_packet;
} }
......
...@@ -696,6 +696,14 @@ static int64_t get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream ) ...@@ -696,6 +696,14 @@ static int64_t get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
int64_t i_frame; int64_t i_frame;
ogg_stream_state os;
/* Backup the stream state. We get called during header processing, and our
* caller expects its header packet to remain valid after the call. If we
* let find_last_frame() reuse the same stream state, then it will
* invalidate the pointers in that packet. */
memcpy(&os, &p_stream->os, sizeof(os));
ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
i_frame = find_last_frame ( p_demux, p_stream ); i_frame = find_last_frame ( p_demux, p_stream );
...@@ -708,9 +716,8 @@ static int64_t get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream ) ...@@ -708,9 +716,8 @@ static int64_t get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream )
seek_byte( p_demux, 0 ); seek_byte( p_demux, 0 );
/* Reset stream states */ /* Reset stream states */
p_sys->i_streams = 0; p_sys->i_streams = 0;
p_stream->i_serial_no = ogg_page_serialno( &p_sys->current_page ); ogg_stream_clear( &p_stream->os );
ogg_stream_init( &p_stream->os, p_stream->i_serial_no ); memcpy( &p_stream->os, &os, sizeof(os) );
ogg_stream_pagein( &p_stream->os, &p_sys->current_page );
return i_frame; return i_frame;
} }
......
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