static void Ogg_ReadTheoraHeader( demux_t *, logical_stream_t *, ogg_packet * );
static void Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
static void Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
-static void Ogg_ReadOpusHeader( 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_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );
static void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
else if( oggpacket.bytes >= 8 &&
! memcmp( oggpacket.packet, "OpusHead", 8 ) )
{
- Ogg_ReadOpusHeader( p_stream, &oggpacket );
+ Ogg_ReadOpusHeader( p_demux, p_stream, &oggpacket );
msg_Dbg( p_demux, "found opus header, channels: %i, "
"pre-skip: %i",
p_stream->fmt.audio.i_channels,
p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
}
-static void Ogg_ReadOpusHeader( logical_stream_t *p_stream,
+static void Ogg_ReadOpusHeader( demux_t *p_demux,
+ logical_stream_t *p_stream,
ogg_packet *p_oggpacket )
{
oggpack_buffer opb;
oggpack_adv( &opb, 8 ); /* version_id */
p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
p_stream->i_pre_skip = oggpack_read( &opb, 16 );
+
+ if ( p_demux->p_sys->i_length < 0 )
+ {
+ int64_t last_frame = 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 );
+
+ if ( last_frame >= 0 )
+ {
+ p_demux->p_sys->i_length = last_frame / p_stream->f_rate;
+ }
+ }
}
static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
}
-/* get highest frame in theora stream */
+/* get highest frame in theora and opus streams */
-static int64_t find_last_theora_frame ( demux_t *p_demux, logical_stream_t *p_stream )
+static int64_t get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream )
{
+ demux_sys_t *p_sys = p_demux->p_sys;
int64_t i_frame;
i_frame = find_last_frame ( p_demux, p_stream );
seek_byte( p_demux, 0 );
/* Reset stream states */
- p_stream->i_serial_no = ogg_page_serialno( &p_demux->p_sys->current_page );
+ p_sys->i_streams = 0;
+ p_stream->i_serial_no = ogg_page_serialno( &p_sys->current_page );
ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
- ogg_stream_pagein( &p_stream->os, &p_demux->p_sys->current_page );
+ ogg_stream_pagein( &p_stream->os, &p_sys->current_page );
return i_frame;
}
-/* return highest frame number for p_stream (which must be a theora or dirac video stream) */
+/* return highest frame number for p_stream (which must be a theora, dirac or opus stream) */
int64_t oggseek_get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream )
{
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_OPUS )
{
- i_frame = find_last_theora_frame ( p_demux, p_stream );
+ i_frame = get_last_frame ( p_demux, p_stream );
if ( i_frame < 0 ) return -1;
return i_frame;