Commit 51cff6ef authored by Francois Cartegnie's avatar Francois Cartegnie

demux: ogg: add skeleton index seeking

parent d6a7b808
This diff is collapsed.
......@@ -41,6 +41,7 @@
#define PACKET_IS_SYNCPOINT 0x08
typedef struct oggseek_index_entry demux_index_entry_t;
typedef struct ogg_skeleton_t ogg_skeleton_t;
typedef struct logical_stream_s
{
......@@ -57,6 +58,7 @@ typedef struct logical_stream_s
* data for the decoder. We back them up here in case we need to re-feed
* them to the decoder. */
bool b_force_backup;
bool b_have_updated_format;
int i_packets_backup;
int32_t i_extra_headers_packets;
void *p_headers;
......@@ -85,6 +87,9 @@ typedef struct logical_stream_s
/* keyframe index for seeking, created as we discover keyframes */
demux_index_entry_t *idx;
/* Skeleton data */
ogg_skeleton_t *p_skel;
/* skip some frames after a seek */
int i_skip_frames;
......@@ -99,12 +104,25 @@ typedef struct logical_stream_s
} logical_stream_t;
struct ogg_skeleton_t
{
int i_messages;
char **ppsz_messages;
unsigned char *p_index;
uint64_t i_index;
uint64_t i_index_size;
int64_t i_indexstampden;/* time denominator */
int64_t i_indexfirstnum;/* first sample time numerator */
int64_t i_indexlastnum;
};
struct demux_sys_t
{
ogg_sync_state oy; /* sync and verify incoming physical bitstream */
int i_streams; /* number of logical bitstreams */
logical_stream_t **pp_stream; /* pointer to an array of logical streams */
logical_stream_t *p_skelstream; /* pointer to skeleton stream if any */
logical_stream_t *p_old_stream; /* pointer to a old logical stream to avoid recreating it */
......@@ -140,6 +158,13 @@ struct demux_sys_t
int i_seekpoints;
seekpoint_t **pp_seekpoints;
/* skeleton */
struct
{
uint16_t major;
uint16_t minor;
} skeleton;
/* */
int i_attachments;
input_attachment_t **attachments;
......@@ -149,3 +174,10 @@ struct demux_sys_t
DemuxDebug( bool b_seeked; )
};
unsigned const char * Read7BitsVariableLE( unsigned const char *,
unsigned const char const *,
uint64_t * );
bool Ogg_GetBoundsUsingSkeletonIndex( logical_stream_t *p_stream, int64_t i_time,
int64_t *pi_lower, int64_t *pi_upper );
......@@ -246,7 +246,6 @@ static bool OggSeekIndexFind ( logical_stream_t *p_stream, int64_t i_timestamp,
int64_t *pi_pos_lower, int64_t *pi_pos_upper )
{
demux_index_entry_t *idx = p_stream->idx;
*pi_pos_lower = *pi_pos_upper = -1;
while ( idx != NULL )
{
......@@ -553,7 +552,6 @@ clean:
ogg_stream_clear( &os );
}
/* convert a theora frame to a granulepos */
static inline int64_t frame_to_gpos( logical_stream_t *p_stream, int64_t i_kframe,
......@@ -1273,6 +1271,54 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
* public functions
*************************************************************************/
int Oggseek_BlindSeektoAbsoluteTime( demux_t *p_demux, logical_stream_t *p_stream,
int64_t i_time, bool b_fastseek )
{
demux_sys_t *p_sys = p_demux->p_sys;
int64_t i_pos = -1;
int64_t i_unusedpos = -1;
bool b_found = false;
/* Search in skeleton */
Ogg_GetBoundsUsingSkeletonIndex( p_stream, i_time, &i_pos, &i_unusedpos );
if ( i_pos != -1 ) b_found = true;
/* And also search in our own index */
if ( !b_found && OggSeekIndexFind( p_stream, i_time, &i_pos, &i_unusedpos ) )
{
b_found = true;
}
/* Or try to be smart with audio fixed bitrate streams */
if ( !b_found && p_stream->fmt.i_cat == AUDIO_ES && p_sys->i_streams == 1
&& p_sys->i_bitrate && Ogg_GetKeyframeGranule( p_stream, 0xFF00FF00 ) == 0xFF00FF00 )
{
/* But only if there's no keyframe/preload requirements */
/* FIXME: add function to get preload time by codec, ex: opus */
i_pos = i_time * p_sys->i_bitrate / INT64_C(8000000);
b_found = true;
}
/* or search */
if ( !b_found && b_fastseek )
{
i_pos = OggBisectSearchByTime( p_demux, p_stream, i_time,
p_stream->i_data_start, p_sys->i_total_length );
b_found = ( i_pos != -1 );
}
if ( !b_found ) return -1;
if ( i_pos < p_stream->i_data_start || i_unusedpos > p_sys->i_total_length )
return -1;
/* And really do seek */
p_sys->i_input_position = i_pos;
seek_byte( p_demux, p_sys->i_input_position );
ogg_stream_reset( &p_stream->os );
return i_pos;
}
int Oggseek_BlindSeektoPosition( demux_t *p_demux, logical_stream_t *p_stream,
double f, bool b_canfastseek )
......@@ -1319,8 +1365,20 @@ int Oggseek_SeektoAbsolutetime( demux_t *p_demux, logical_stream_t *p_stream,
demux_sys_t *p_sys = p_demux->p_sys;
OggDebug( msg_Dbg( p_demux, "=================== Seeking To Absolute Time %"PRId64, i_time ) );
int64_t i_offset_lower = p_stream->i_data_start;
int64_t i_offset_upper = p_sys->i_total_length;
int64_t i_offset_lower = -1;
int64_t i_offset_upper = -1;
if ( Ogg_GetBoundsUsingSkeletonIndex( p_stream, i_time, &i_offset_lower, &i_offset_upper ) )
{
/* Exact match */
OggDebug( msg_Dbg( p_demux, "Found keyframe at %"PRId64" using skeleton index", i_offset_lower ) );
if ( i_offset_lower == -1 ) i_offset_lower = p_stream->i_data_start;
p_sys->i_input_position = i_offset_lower;
seek_byte( p_demux, p_sys->i_input_position );
ogg_stream_reset( &p_stream->os );
return i_offset_lower;
}
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 )
......@@ -1420,4 +1478,3 @@ int64_t oggseek_read_page( demux_t *p_demux )
return i_result + PAGE_HEADER_BYTES + i_nsegs;
}
......@@ -55,6 +55,7 @@ bool Ogg_IsKeyFrame ( logical_stream_t *, ogg_packet * );
int64_t Oggseek_GranuleToAbsTimestamp ( logical_stream_t *p_stream, int64_t i_granule,
bool b_presentation );
bool Oggseek_PacketPCRFixup ( logical_stream_t *p_stream, ogg_page *, ogg_packet * );
int Oggseek_BlindSeektoAbsoluteTime ( demux_t *, logical_stream_t *, int64_t, bool );
int Oggseek_BlindSeektoPosition ( demux_t *, logical_stream_t *, double f, bool );
int Oggseek_SeektoAbsolutetime ( demux_t *, logical_stream_t *, int64_t i_granulepos );
const demux_index_entry_t *OggSeek_IndexAdd ( logical_stream_t *, int64_t, int64_t );
......
......@@ -289,6 +289,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
p_stream->p_oggds_header = 0;
/* FIXME: https://trac.videolan.org/vlc/ticket/1412 */
switch( p_input->p_fmt->i_cat )
{
case VIDEO_ES:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment