[vlc-commits] [Git][videolan/vlc][3.0.x] 8 commits: demux: ogg: set index on granule time instead of seek time

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Tue Jul 26 08:50:50 UTC 2022



Hugo Beauzée-Luyssen pushed to branch 3.0.x at VideoLAN / VLC


Commits:
28c8dece by Francois Cartegnie at 2022-07-26T08:08:57+00:00
demux: ogg: set index on granule time instead of seek time

(cherry picked from commit 22bd3d8beeb7f49e1fcbbf755078be10955eeea8)

- - - - -
2146bad1 by Francois Cartegnie at 2022-07-26T08:08:57+00:00
demux: ogg: fix bisect lowest bound/index result

(cherry picked from commit f3228de74c45b54f3b76e41edbb3bcaa395b56ea)

- - - - -
38fbf97e by Francois Cartegnie at 2022-07-26T08:08:57+00:00
oggseek: remove unused members

(cherry picked from commit 3783f868b9427a1e16fd0d61a293ffd49973ba51)

- - - - -
031f1f49 by Francois Cartegnie at 2022-07-26T08:08:57+00:00
demux: ogg: simplify index stuff

(cherry picked from commit 9a42c5312ad6f9ae4634371017b042d53eec954e)

- - - - -
ebfe150e by Francois Cartegnie at 2022-07-26T08:08:57+00:00
demux: ogg: limit indexes

(cherry picked from commit fc94fb4e0b2bb52f2e0ad38ae27a6122cf651c74)
(cherry picked from commit 6a995af679cd9b5d144afe1096865fd29fe0b667)

- - - - -
2e71199f by Francois Cartegnie at 2022-07-26T08:08:57+00:00
demux: ogg: store length as microseconds

(cherry picked from commit ac81e531acee716fa6f9a73f84b3af4573726003)

- - - - -
382cc2ee by Francois Cartegnie at 2022-07-26T08:08:57+00:00
demux: ogg: rename ambiguous member

(cherry picked from commit 125a46cc6c8c60a5923084b525b02b509e8a9d7f)

- - - - -
acae96e0 by Francois Cartegnie at 2022-07-26T08:08:57+00:00
demux: oggseek: remove bos optimization

prevents blind seek to start of stream as granule is never read

(cherry picked from commit cd79514d7bfe666f72b1e88777ed69612bc7aec7)

- - - - -


5 changed files:

- modules/demux/Makefile.am
- modules/demux/ogg.c
- modules/demux/ogg.h
- modules/demux/oggseek.c
- modules/demux/oggseek.h


Changes:

=====================================
modules/demux/Makefile.am
=====================================
@@ -14,7 +14,7 @@ libogg_plugin_la_SOURCES = demux/ogg.c demux/ogg.h demux/oggseek.c demux/oggseek
 	demux/xiph.h demux/opus.h
 libogg_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBVORBIS_CFLAGS) $(OGG_CFLAGS)
 libogg_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(demuxdir)'
-libogg_plugin_la_LIBADD = $(LIBVORBIS_LIBS) $(OGG_LIBS) libxiph_metadata.la
+libogg_plugin_la_LIBADD = $(LIBVORBIS_LIBS) $(OGG_LIBS) $(LIBM) libxiph_metadata.la
 EXTRA_LTLIBRARIES += libogg_plugin.la
 demux_LTLIBRARIES += $(LTLIBogg)
 


=====================================
modules/demux/ogg.c
=====================================
@@ -229,7 +229,7 @@ static int Open( vlc_object_t * p_this )
     if( !p_sys )
         return VLC_ENOMEM;
 
-    p_sys->i_length = -1;
+    p_sys->i_length = 0;
     p_sys->b_preparsing_done = false;
 
     vlc_stream_Control( p_demux->s, STREAM_GET_PTS_DELAY,
@@ -843,8 +843,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             pf = va_arg( args, double * );
             if( p_sys->i_length > 0 && p_sys->i_pcr > VLC_TS_INVALID )
             {
-                *pf =  (double) p_sys->i_pcr /
-                       (double) ( p_sys->i_length * (mtime_t)1000000 );
+                *pf =  (double) p_sys->i_pcr / (double) p_sys->i_length;
             }
             else if( stream_Size( p_demux->s ) > 0 )
             {
@@ -882,9 +881,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             }
 
             assert( p_sys->i_length > 0 );
-            i64 = CLOCK_FREQ * p_sys->i_length * f;
+            i64 = p_sys->i_length * f;
             Ogg_ResetStreamsHelper( p_sys );
-            if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, i64 ) >= 0 )
+            if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, VLC_TS_0 + i64 ) >= 0 )
             {
                 if( acc )
                     es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
@@ -898,8 +897,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             if ( p_sys->i_length < 0 )
                 return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
                                               1, i_query, args );
-            pi64 = va_arg( args, int64_t * );
-            *pi64 = p_sys->i_length * 1000000;
+            *va_arg( args, int64_t * ) = p_sys->i_length;
             return VLC_SUCCESS;
 
         case DEMUX_GET_TITLE_INFO:
@@ -1580,8 +1578,8 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
     demux_sys_t *p_ogg = p_demux->p_sys  ;
     ogg_packet oggpacket;
 
-    p_ogg->i_total_length = stream_Size ( p_demux->s );
-    msg_Dbg( p_demux, "File length is %"PRId64" bytes", p_ogg->i_total_length );
+    p_ogg->i_total_bytes = stream_Size ( p_demux->s );
+    msg_Dbg( p_demux, "File length is %"PRId64" bytes", p_ogg->i_total_bytes );
 
 
     while( Ogg_ReadPage( p_demux, &p_ogg->current_page ) == VLC_SUCCESS )


=====================================
modules/demux/ogg.h
=====================================
@@ -202,7 +202,7 @@ struct demux_sys_t
     int64_t i_total_frames;
 
     /* length of file in bytes */
-    int64_t i_total_length;
+    int64_t i_total_bytes;
 
     /* offset position in file (for reading) */
     int64_t i_input_position;
@@ -230,7 +230,7 @@ struct demux_sys_t
     bool b_preparsing_done;
     bool b_es_created;
 
-    /* Length, if available. */
+    /* Time length, if available. 0 otherwise. */
     int64_t i_length;
 
     bool b_slave;


=====================================
modules/demux/oggseek.c
=====================================
@@ -35,7 +35,7 @@
 
 #include <ogg/ogg.h>
 #include <limits.h>
-
+#include <math.h>
 #include <assert.h>
 
 #include "ogg.h"
@@ -85,12 +85,18 @@ void oggseek_index_entries_free ( demux_index_entry_t *idx )
 
 /* internal function to create a new list member */
 
-static demux_index_entry_t *index_entry_new( void )
+static demux_index_entry_t *index_entry_new( int64_t i_timestamp, int64_t i_pagepos )
 {
-    demux_index_entry_t *idx = xmalloc( sizeof( demux_index_entry_t ) );
-    if ( !idx ) return NULL;
-    idx->p_next = idx->p_prev = NULL;
-    idx->i_pagepos_end = -1;
+    if ( i_timestamp == VLC_TS_INVALID || i_pagepos < 1 )
+        return NULL;
+
+    demux_index_entry_t *idx = malloc( sizeof(*idx) );
+    if ( idx )
+    {
+        idx->i_value = i_timestamp;
+        idx->i_pagepos = i_pagepos;
+        idx->p_next = NULL;
+    }
     return idx;
 }
 
@@ -100,60 +106,31 @@ const demux_index_entry_t *OggSeek_IndexAdd ( logical_stream_t *p_stream,
                                              int64_t i_timestamp,
                                              int64_t i_pagepos )
 {
-    demux_index_entry_t *idx;
-    demux_index_entry_t *last_idx = NULL;
-
-    if ( p_stream == NULL ) return NULL;
-
-    idx = p_stream->idx;
-
-    if ( i_timestamp < 1 || i_pagepos < 1 ) return NULL;
-
-    if ( idx == NULL )
-    {
-        demux_index_entry_t *ie = index_entry_new();
-        if ( !ie ) return NULL;
-        ie->i_value = i_timestamp;
-        ie->i_pagepos = i_pagepos;
-        p_stream->idx = ie;
-        return ie;
-    }
-
-    while ( idx != NULL )
-    {
-        if ( idx->i_pagepos > i_pagepos ) break;
-        last_idx = idx;
-        idx = idx->p_next;
-    }
-
-    /* new entry; insert after last_idx */
-    idx = index_entry_new();
-    if ( !idx ) return NULL;
-    if ( last_idx != NULL )
-    {
-        idx->p_next = last_idx->p_next;
-        last_idx->p_next = idx;
-        idx->p_prev = last_idx;
-    }
-    else
+    demux_index_entry_t **pp_next = &p_stream->idx;
+    for( ; *pp_next; )
     {
-        idx->p_next = p_stream->idx;
-        p_stream->idx = idx;
+        if( (*pp_next)->i_pagepos >= i_pagepos )
+        {
+            if( (*pp_next)->i_pagepos == i_pagepos )
+                return NULL;
+            break;
+        }
+        pp_next = &((*pp_next)->p_next);
     }
 
-    if ( idx->p_next != NULL )
+    demux_index_entry_t *ie = index_entry_new( i_timestamp, i_pagepos );
+    if ( ie )
     {
-        idx->p_next->p_prev = idx;
+        ie->p_next = *pp_next;
+        *pp_next = ie;
     }
 
-    idx->i_value = i_timestamp;
-    idx->i_pagepos = i_pagepos;
-
-    return idx;
+    return ie;
 }
 
 static bool OggSeekIndexFind ( logical_stream_t *p_stream, int64_t i_timestamp,
-                               int64_t *pi_pos_lower, int64_t *pi_pos_upper )
+                               int64_t *pi_pos_lower, int64_t *pi_pos_upper,
+                               int64_t *pi_lower_timestamp )
 {
     demux_index_entry_t *idx = p_stream->idx;
 
@@ -164,11 +141,13 @@ static bool OggSeekIndexFind ( logical_stream_t *p_stream, int64_t i_timestamp,
             if ( !idx->p_next ) /* found on last index */
             {
                 *pi_pos_lower = idx->i_pagepos;
+                *pi_lower_timestamp = idx->i_value;
                 return true;
             }
             if ( idx->p_next->i_value > i_timestamp )
             {
                 *pi_pos_lower = idx->i_pagepos;
+                *pi_lower_timestamp = idx->i_value;
                 *pi_pos_upper = idx->p_next->i_pagepos;
                 return true;
             }
@@ -209,11 +188,11 @@ static int64_t get_data( demux_t *p_demux, int64_t i_bytes_to_read )
     char *buf;
     int64_t i_result;
 
-    if ( p_sys->i_total_length > 0 )
+    if ( p_sys->i_total_bytes > 0 )
     {
-        if ( p_sys->i_input_position + i_bytes_to_read > p_sys->i_total_length )
+        if ( p_sys->i_input_position + i_bytes_to_read > p_sys->i_total_bytes )
         {
-            i_bytes_to_read = p_sys->i_total_length - p_sys->i_input_position;
+            i_bytes_to_read = p_sys->i_total_bytes - p_sys->i_input_position;
             if ( i_bytes_to_read <= 0 ) {
                 return 0;
             }
@@ -291,7 +270,7 @@ void Oggseek_ProbeEnd( demux_t *p_demux )
                         continue;
 
                     i_length = Oggseek_GranuleToAbsTimestamp( p_sys->pp_stream[i], i_granule, false );
-                    p_sys->i_length = __MAX( p_sys->i_length, i_length / 1000000 );
+                    p_sys->i_length = __MAX( p_sys->i_length, i_length );
                     break;
                 }
             }
@@ -342,9 +321,6 @@ static int64_t find_first_page_granule( demux_t *p_demux,
 
     seek_byte( p_demux, i_pos1 );
 
-    if ( i_pos1 == p_stream->i_data_start )
-        return p_sys->i_input_position;
-
     if ( i_bytes_to_read > OGGSEEK_BYTES_TO_READ ) i_bytes_to_read = OGGSEEK_BYTES_TO_READ;
 
     while ( 1 )
@@ -752,7 +728,7 @@ int64_t Oggseek_GranuleToAbsTimestamp( logical_stream_t *p_stream,
 
 /* returns pos */
 static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stream,
-            int64_t i_targettime, int64_t i_pos_lower, int64_t i_pos_upper)
+            int64_t i_targettime, int64_t i_pos_lower, int64_t i_pos_upper, int64_t *pi_seek_time)
 {
     int64_t i_start_pos;
     int64_t i_end_pos;
@@ -770,8 +746,8 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
     demux_sys_t *p_sys  = p_demux->p_sys;
 
     i_pos_lower = __MAX( i_pos_lower, p_stream->i_data_start );
-    i_pos_upper = __MIN( i_pos_upper, p_sys->i_total_length );
-    if ( i_pos_upper < 0 ) i_pos_upper = p_sys->i_total_length;
+    i_pos_upper = __MIN( i_pos_upper, p_sys->i_total_bytes );
+    if ( i_pos_upper < 0 ) i_pos_upper = p_sys->i_total_bytes;
 
     i_start_pos = i_pos_lower;
     i_end_pos = i_pos_upper;
@@ -782,6 +758,21 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
     OggDebug( msg_Dbg(p_demux, "Bisecting for time=%"PRId64" between %"PRId64" and %"PRId64,
             i_targettime, i_pos_lower, i_pos_upper ) );
 
+    /* Check lowest possible bound that will never be checked in bisection */
+    current.i_pos = find_first_page_granule( p_demux,
+                                             i_pos_lower,
+                                             __MIN(i_start_pos + PAGE_HEADER_BYTES, i_end_pos),
+                                             p_stream,
+                                             &current.i_granule );
+    if( current.i_granule != -1 )
+    {
+        current.i_timestamp = Oggseek_GranuleToAbsTimestamp( p_stream, current.i_granule, false );
+        if( current.i_timestamp <= i_targettime )
+            bestlower = current;
+        else
+            lowestupper = current;
+    }
+
     do
     {
         /* see if the frame lies in current segment */
@@ -850,7 +841,7 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
         i_segsize = ( i_end_pos - i_start_pos + 1 ) >> 1;
         i_start_pos += i_segsize;
 
-    } while ( i_segsize > 64 );
+    } while ( i_segsize > PAGE_HEADER_BYTES );
 
     if ( bestlower.i_granule == -1 )
     {
@@ -866,6 +857,7 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
                 __MAX ( bestlower.i_pos - OGGSEEK_BYTES_TO_READ, p_stream->i_data_start ),
                 bestlower.i_pos,
                 p_stream, bestlower.i_granule /* unused */ );
+        *pi_seek_time = bestlower.i_timestamp;
         return a;
     }
     /* If not each packet is usable as keyframe, query the codec for keyframe */
@@ -884,9 +876,11 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
         int64_t a = OggBackwardSeekToFrame( p_demux,
             __MAX ( bestlower.i_pos - OGGSEEK_BYTES_TO_READ, p_stream->i_data_start ),
             stream_Size( p_demux->s ), p_stream, i_keyframegranule );
+       *pi_seek_time = Oggseek_GranuleToAbsTimestamp(p_stream, i_keyframegranule, false);
         return a;
     }
 
+    *pi_seek_time = bestlower.i_timestamp;
     return bestlower.i_pos;
 }
 
@@ -908,7 +902,8 @@ int Oggseek_BlindSeektoAbsoluteTime( demux_t *p_demux, logical_stream_t *p_strea
     if ( i_lowerpos != -1 ) b_found = true;
 
     /* And also search in our own index */
-    if ( !b_found && OggSeekIndexFind( p_stream, i_time, &i_lowerpos, &i_upperpos ) )
+    int64_t foo;
+    if ( !b_found && OggSeekIndexFind( p_stream, i_time, &i_lowerpos, &i_upperpos, &foo ) )
     {
         b_found = true;
     }
@@ -926,14 +921,16 @@ int Oggseek_BlindSeektoAbsoluteTime( demux_t *p_demux, logical_stream_t *p_strea
     /* or search */
     if ( !b_found && b_fastseek )
     {
+        int64_t i_sync_time;
         i_lowerpos = OggBisectSearchByTime( p_demux, p_stream, i_time,
-                                            p_stream->i_data_start, p_sys->i_total_length );
+                                            p_stream->i_data_start, p_sys->i_total_bytes,
+                                            &i_sync_time );
         b_found = ( i_lowerpos != -1 );
     }
 
     if ( !b_found ) return -1;
 
-    if ( i_lowerpos < p_stream->i_data_start || i_upperpos > p_sys->i_total_length )
+    if ( i_lowerpos < p_stream->i_data_start || i_upperpos > p_sys->i_total_bytes )
         return -1;
 
     /* And really do seek */
@@ -974,7 +971,7 @@ int Oggseek_BlindSeektoPosition( demux_t *p_demux, logical_stream_t *p_stream,
          * final seek time */
         i_pagepos = OggBackwardSeekToFrame( p_demux,
                 __MAX ( i_size - MAX_PAGE_SIZE, p_stream->i_data_start ),
-                __MIN ( i_size + MAX_PAGE_SIZE, p_demux->p_sys->i_total_length ),
+                __MIN ( i_size + MAX_PAGE_SIZE, p_demux->p_sys->i_total_bytes ),
                 p_stream, i_granule );
     }
     else
@@ -1011,15 +1008,17 @@ int Oggseek_SeektoAbsolutetime( demux_t *p_demux, logical_stream_t *p_stream,
     }
     OggDebug( msg_Dbg( p_demux, "Search bounds set to %"PRId64" %"PRId64" using skeleton index", i_offset_lower, i_offset_upper ) );
 
-    OggNoDebug(
-        OggSeekIndexFind( p_stream, i_time, &i_offset_lower, &i_offset_upper )
-    );
+
+    int64_t i_lower_index;
+    if(!OggSeekIndexFind( p_stream, i_time, &i_offset_lower, &i_offset_upper, &i_lower_index ))
+        i_lower_index = 0;
 
     i_offset_lower = __MAX( i_offset_lower, p_stream->i_data_start );
-    i_offset_upper = __MIN( i_offset_upper, p_sys->i_total_length );
+    i_offset_upper = __MIN( i_offset_upper, p_sys->i_total_bytes );
 
+    int64_t i_sync_time;
     int64_t i_pagepos = OggBisectSearchByTime( p_demux, p_stream, i_time,
-                                       i_offset_lower, i_offset_upper);
+                                       i_offset_lower, i_offset_upper, &i_sync_time );
     if ( i_pagepos >= 0 )
     {
         /* be sure to clear any state or read+pagein() will fail on same # */
@@ -1027,11 +1026,13 @@ int Oggseek_SeektoAbsolutetime( demux_t *p_demux, logical_stream_t *p_stream,
         p_sys->i_input_position = i_pagepos;
         seek_byte( p_demux, p_sys->i_input_position );
     }
+
     /* Insert keyframe position into index */
-    OggNoDebug(
-    if ( i_pagepos >= p_stream->i_data_start )
-        OggSeek_IndexAdd( p_stream, i_time, i_pagepos )
-    );
+    int64_t index_interval = p_sys->i_length
+              ? CLOCK_FREQ * ceil( sqrt( p_sys->i_length / CLOCK_FREQ ) / 2 )
+              : CLOCK_FREQ * 5;
+    if ( i_pagepos >= p_stream->i_data_start && ( i_sync_time - i_lower_index >= index_interval ) )
+        OggSeek_IndexAdd( p_stream, i_sync_time, i_pagepos );
 
     OggDebug( msg_Dbg( p_demux, "=================== Seeked To %"PRId64" time %"PRId64, i_pagepos, i_time ) );
     return i_pagepos;


=====================================
modules/demux/oggseek.h
=====================================
@@ -30,23 +30,13 @@
 
 #define OGGSEEK_BYTES_TO_READ 8500
 
-/* index entries are structured as follows:
- *   - for theora, highest granulepos -> pagepos (bytes) where keyframe begins
- *  - for dirac, kframe (sync point) -> pagepos of sequence start (?)
- */
-
 /* this is typedefed to demux_index_entry_t in ogg.h */
 struct oggseek_index_entry
 {
     demux_index_entry_t *p_next;
-    demux_index_entry_t *p_prev;
-
     /* value is highest granulepos for theora, sync frame for dirac */
     int64_t i_value;
     int64_t i_pagepos;
-
-    /* not used for theora because the granulepos tells us this */
-    int64_t i_pagepos_end;
 };
 
 int64_t Ogg_GetKeyframeGranule ( logical_stream_t *p_stream, int64_t i_granule );



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/704f40be73de1e3626b3897663cdafa11f6706f8...acae96e091320da18730345d6eef7257fcb595ba

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/704f40be73de1e3626b3897663cdafa11f6706f8...acae96e091320da18730345d6eef7257fcb595ba
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list