[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,
+ ¤t.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