]> git.sesse.net Git - vlc/blobdiff - modules/demux/oggseek.c
skins2: simplify equalizer initialization
[vlc] / modules / demux / oggseek.c
index 567d920df32cba2cf16447ae9804f3ae96cefc05..3c65e5f177e4689f1ce0815871bcb032fa1adf9a 100644 (file)
@@ -7,19 +7,19 @@
  * adapted from: http://lives.svn.sourceforge.net/viewvc/lives/trunk/lives-plugins
  * /plugins/decoders/ogg_theora_decoder.c
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
@@ -58,22 +58,6 @@ void oggseek_index_entries_free ( demux_index_entry_t *idx )
 }
 
 
-/* unlink and free idx. If idx is head of list, return new head */
-
-static demux_index_entry_t *index_entry_delete( demux_index_entry_t *idx )
-{
-    demux_index_entry_t *xidx = idx;
-
-    if ( idx->p_prev != NULL ) idx->p_prev->p_next = idx->p_next;
-    else xidx = idx->p_next;
-
-    if ( idx->p_next != NULL ) idx->p_next->p_prev = idx->p_prev;
-    free( idx );
-
-    return xidx;
-}
-
-
 /* internal function to create a new list member */
 
 static demux_index_entry_t *index_entry_new( void )
@@ -391,13 +375,11 @@ static int64_t find_last_frame (demux_t *p_demux, logical_stream_t *p_stream)
     int64_t i_kframe = 0;
     int64_t i_pos1;
     int64_t i_pos2;
-    int64_t i_serialno;
 
     demux_sys_t *p_sys  = p_demux->p_sys;
 
     i_pos1 = p_stream->i_data_start;
     i_pos2 = p_sys->i_total_length;
-    i_serialno = p_stream->os.serialno;
 
     i_start_pos = i_pos2 - OGGSEEK_BYTES_TO_READ;
 
@@ -690,11 +672,20 @@ 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;
+    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 );
 
@@ -706,9 +697,9 @@ 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 );
-    ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
-    ogg_stream_pagein( &p_stream->os, &p_demux->p_sys->current_page );
+    p_sys->i_streams = 0;
+    ogg_stream_clear( &p_stream->os );
+    memcpy( &p_stream->os, &os, sizeof(os) );
 
     return i_frame;
 }
@@ -722,15 +713,17 @@ 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_VORBIS ||
+         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;
@@ -776,14 +769,26 @@ int oggseek_find_frame ( demux_t *p_demux, logical_stream_t *p_stream, int64_t i
 
     i_tframe += p_stream->i_keyframe_offset;
 
+    i_cframe = i_tframe;
+    /* For Opus, seek back 80 ms before the target playback position. */
+    if ( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
+    {
+        if ( i_tframe <= p_stream->i_pre_skip )
+            i_cframe = 0;
+        else if ( i_tframe < 80*48 )
+            i_cframe = 0;
+        else
+            i_cframe = i_tframe - 80*48;
+    }
+
     /* reduce the search domain */
-    fidx = get_bounds_for( p_stream, i_tframe, &i_pos_lower, &i_pos_upper );
+    fidx = get_bounds_for( p_stream, i_cframe, &i_pos_lower, &i_pos_upper );
 
     if ( fidx == NULL )
     {
-        /* no exact match found; search the domain for highest keyframe <= i_tframe */
+        /* no exact match found; search the domain for highest keyframe <= i_cframe */
 
-        i_granulepos = ogg_seek ( p_demux, p_stream, i_tframe, i_pos_lower, i_pos_upper,
+        i_granulepos = ogg_seek ( p_demux, p_stream, i_cframe, i_pos_lower, i_pos_upper,
                                   &i_pagepos, true );
         if ( i_granulepos == -1 )
         {