[vlc-commits] [Git][videolan/vlc][master] 7 commits: demux: ogg: set index on granule time instead of seek time

Steve Lhomme (@robUx4) gitlab at videolan.org
Tue Jul 12 11:24:39 UTC 2022



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
22bd3d8b by Francois Cartegnie at 2022-07-12T11:08:43+00:00
demux: ogg: set index on granule time instead of seek time

- - - - -
f3228de7 by Francois Cartegnie at 2022-07-12T11:08:43+00:00
demux: ogg: fix bisect lowest bound/index result

- - - - -
3783f868 by Francois Cartegnie at 2022-07-12T11:08:43+00:00
oggseek: remove unused members

- - - - -
9a42c531 by Francois Cartegnie at 2022-07-12T11:08:43+00:00
demux: ogg: simplify index stuff

- - - - -
fc94fb4e by Francois Cartegnie at 2022-07-12T11:08:43+00:00
demux: ogg: limit indexes

- - - - -
ac81e531 by Francois Cartegnie at 2022-07-12T11:08:43+00:00
demux: ogg: store length as microseconds

- - - - -
125a46cc by Francois Cartegnie at 2022-07-12T11:08:43+00:00
demux: ogg: rename ambiguous member

- - - - -


4 changed files:

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


Changes:

=====================================
modules/demux/ogg.c
=====================================
@@ -241,7 +241,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;
 
     /* Set exported functions */
@@ -760,8 +760,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 
             if( p_sys->i_length > 0 && p_sys->i_pcr != VLC_TICK_INVALID )
             {
-                vlc_tick_t duration = vlc_tick_from_sec( p_sys->i_length );
-                pos = (double) p_sys->i_pcr / (double) duration;
+                pos = (double) p_sys->i_pcr / (double) p_sys->i_length;
             }
             else if( vlc_stream_GetSize( p_demux->s, &size ) == 0 && size > 0 )
             {
@@ -801,7 +800,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             }
 
             assert( p_sys->i_length > 0 );
-            i64 = vlc_tick_from_sec( f * p_sys->i_length );
+            i64 = f * p_sys->i_length;
             Ogg_PreparePostSeek( p_sys );
             if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, VLC_TICK_0 + i64 ) >= 0 )
             {
@@ -817,7 +816,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 );
-            *va_arg( args, vlc_tick_t * ) = vlc_tick_from_sec(p_sys->i_length);
+            *va_arg( args, vlc_tick_t * ) = p_sys->i_length;
             return VLC_SUCCESS;
 
         case DEMUX_GET_TITLE_INFO:
@@ -1548,8 +1547,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
=====================================
@@ -189,7 +189,7 @@ typedef struct
     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;
@@ -219,8 +219,8 @@ typedef struct
     bool b_preparsing_done;
     bool b_es_created;
 
-    /* Length in second, if available. */
-    int64_t i_length;
+    /* Time length, if available. 0 otherwise. */
+    vlc_tick_t i_length;
 
     bool b_slave;
 


=====================================
modules/demux/oggseek.c
=====================================
@@ -39,7 +39,7 @@
 
 #include <ogg/ogg.h>
 #include <limits.h>
-
+#include <math.h>
 #include <assert.h>
 
 #include "ogg.h"
@@ -78,12 +78,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( vlc_tick_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_TICK_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;
 }
 
@@ -93,60 +99,31 @@ const demux_index_entry_t *OggSeek_IndexAdd ( logical_stream_t *p_stream,
                                              vlc_tick_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 == VLC_TICK_INVALID || 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 )
+    demux_index_entry_t **pp_next = &p_stream->idx;
+    for( ; *pp_next; )
     {
-        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
-    {
-        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, vlc_tick_t i_timestamp,
-                               int64_t *pi_pos_lower, int64_t *pi_pos_upper )
+                               int64_t *pi_pos_lower, int64_t *pi_pos_upper,
+                               vlc_tick_t *pi_lower_timestamp )
 {
     demux_index_entry_t *idx = p_stream->idx;
 
@@ -157,11 +134,13 @@ static bool OggSeekIndexFind ( logical_stream_t *p_stream, vlc_tick_t i_timestam
             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;
             }
@@ -202,11 +181,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;
             }
@@ -288,7 +267,7 @@ void Oggseek_ProbeEnd( demux_t *p_demux )
                     if( i_length != VLC_TICK_INVALID )
                     {
                         /* We found at least a page with valid granule */
-                        p_sys->i_length = __MAX( p_sys->i_length, SEC_FROM_VLC_TICK(i_length - VLC_TICK_0) );
+                        p_sys->i_length = __MAX( p_sys->i_length, i_length - VLC_TICK_0 );
                         goto clean;
                     }
                     break;
@@ -632,7 +611,7 @@ restart:
 
 /* returns pos */
 static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stream,
-            vlc_tick_t i_targettime, int64_t i_pos_lower, int64_t i_pos_upper)
+            vlc_tick_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;
@@ -650,8 +629,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;
@@ -662,6 +641,22 @@ 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 = Ogg_GranuleToTime( p_stream, current.i_granule,
+                                                 !p_stream->b_contiguous, false );
+        if( current.i_timestamp <= i_targettime )
+            bestlower = current;
+        else
+            lowestupper = current;
+    }
+
     do
     {
         /* see if the frame lies in current segment */
@@ -731,7 +726,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 )
     {
@@ -747,6 +742,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 */
@@ -765,9 +761,12 @@ 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 = Ogg_GranuleToTime( p_stream, i_keyframegranule,
+                                          !p_stream->b_contiguous, false );
         return a;
     }
 
+    *pi_seek_time = bestlower.i_timestamp;
     return bestlower.i_pos;
 }
 
@@ -789,7 +788,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 ) )
+    vlc_tick_t foo;
+    if ( !b_found && OggSeekIndexFind( p_stream, i_time, &i_lowerpos, &i_upperpos, &foo ) )
     {
         b_found = true;
     }
@@ -807,14 +807,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 */
@@ -856,7 +858,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_sys->i_total_length ),
+                __MIN ( i_size + MAX_PAGE_SIZE, p_sys->i_total_bytes ),
                 p_stream, i_granule );
     }
     else
@@ -894,15 +896,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 )
-    );
+
+    vlc_tick_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 # */
@@ -910,11 +914,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 )
-    );
+    vlc_tick_t index_interval = p_sys->i_length
+              ? vlc_tick_from_sec( ceil( sqrt( SEC_FROM_VLC_TICK( p_sys->i_length ) ) / 2 ) )
+              : vlc_tick_from_sec( 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
=====================================
@@ -40,23 +40,13 @@
 #define OGGSEEK_BYTES_TO_READ 8500
 #define OGGSEEK_SERIALNO_MAX_LOOKUP_BYTES (OGGSEEK_BYTES_TO_READ * 25)
 
-/* 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 */
     vlc_tick_t i_value;
     int64_t i_pagepos;
-
-    /* not used for theora because the granulepos tells us this */
-    int64_t i_pagepos_end;
 };
 
 int     Oggseek_BlindSeektoAbsoluteTime ( demux_t *, logical_stream_t *, vlc_tick_t, bool );



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/53f6ee83fbd1c34bde38677a12555d8e667faa76...125a46cc6c8c60a5923084b525b02b509e8a9d7f

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/53f6ee83fbd1c34bde38677a12555d8e667faa76...125a46cc6c8c60a5923084b525b02b509e8a9d7f
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