[vlc-devel] [PATCH] ogg: find the length of an opus stream

etix at videolan.org etix at videolan.org
Thu Sep 6 12:38:49 CEST 2012


From: Ludovic Fauvet <etix at videolan.org>

---
 modules/demux/ogg.c     | 23 +++++++++++++++++++----
 modules/demux/oggseek.c | 17 ++++++++++-------
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c
index 18b43de..2ba6c67 100644
--- a/modules/demux/ogg.c
+++ b/modules/demux/ogg.c
@@ -140,7 +140,7 @@ static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8
 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 * );
@@ -267,7 +267,6 @@ static int Demux( demux_t * p_demux )
          */
         if( Ogg_ReadPage( p_demux, &p_sys->current_page ) != VLC_SUCCESS )
             return 0; /* EOF */
-
         /* Test for End of Stream */
         if( ogg_page_eos( &p_sys->current_page ) )
             p_sys->i_eos++;
@@ -1113,7 +1112,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
                 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,
@@ -1958,7 +1957,8 @@ static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
     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;
@@ -1982,6 +1982,21 @@ static void Ogg_ReadOpusHeader( logical_stream_t *p_stream,
     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,
diff --git a/modules/demux/oggseek.c b/modules/demux/oggseek.c
index c67f8e0..49d8bde 100644
--- a/modules/demux/oggseek.c
+++ b/modules/demux/oggseek.c
@@ -690,10 +690,11 @@ static demux_index_entry_t *get_bounds_for ( logical_stream_t *p_stream, int64_t
 }
 
 
-/* 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 );
@@ -706,9 +707,10 @@ static int64_t find_last_theora_frame ( demux_t *p_demux, logical_stream_t *p_st
 
     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;
 }
@@ -722,15 +724,16 @@ static int64_t find_last_theora_frame ( demux_t *p_demux, logical_stream_t *p_st
 
 
 
-/* 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;
-- 
1.7.12




More information about the vlc-devel mailing list