]> git.sesse.net Git - vlc/commitdiff
ogg: find the length of an opus stream
authorLudovic Fauvet <etix@videolan.org>
Thu, 6 Sep 2012 10:38:49 +0000 (12:38 +0200)
committerJean-Baptiste Kempf <jb@videolan.org>
Thu, 6 Sep 2012 12:33:11 +0000 (14:33 +0200)
Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
modules/demux/ogg.c
modules/demux/oggseek.c

index 18b43dedea30df8dedba8787bbeac0548d500174..3830e89ddc62121d4bb673f8e12c9cd6a95c2aab 100644 (file)
@@ -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 * );
@@ -1113,7 +1113,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 +1958,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 +1983,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,
index c67f8e0168f65deb3136847bd310b0231e5bda19..49d8bdec0e55431214669d11b4fb7a1ed4a2ec28 100644 (file)
@@ -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;