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