|
|
|
@ -467,8 +467,8 @@ static block_t *MemToBlock( demux_t *p_demux, uint8_t *p_mem, size_t i_mem, size |
|
|
|
return p_block; |
|
|
|
} |
|
|
|
|
|
|
|
/* Needed by matroska_segment::Seek() */ |
|
|
|
static void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock, |
|
|
|
/* Needed by matroska_segment::Seek() and Seek */ |
|
|
|
void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock, |
|
|
|
mtime_t i_pts, mtime_t i_duration, bool f_mandatory ) |
|
|
|
{ |
|
|
|
demux_sys_t *p_sys = p_demux->p_sys; |
|
|
|
@ -622,153 +622,6 @@ msg_Dbg( p_demux, "block i_dts: %"PRId64" / i_pts: %"PRId64, p_block->i_dts, p_b |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_global_position ) |
|
|
|
{ |
|
|
|
KaxBlock *block; |
|
|
|
KaxSimpleBlock *simpleblock; |
|
|
|
int i_track_skipping; |
|
|
|
int64_t i_block_duration; |
|
|
|
int64_t i_block_ref1; |
|
|
|
int64_t i_block_ref2; |
|
|
|
size_t i_track; |
|
|
|
int64_t i_seek_position = i_start_pos; |
|
|
|
int64_t i_seek_time = i_start_time; |
|
|
|
|
|
|
|
if( i_global_position >= 0 ) |
|
|
|
{ |
|
|
|
/* Special case for seeking in files with no cues */ |
|
|
|
EbmlElement *el = NULL; |
|
|
|
es.I_O().setFilePointer( i_start_pos, seek_beginning ); |
|
|
|
delete ep; |
|
|
|
ep = new EbmlParser( &es, segment, &sys.demuxer ); |
|
|
|
cluster = NULL; |
|
|
|
|
|
|
|
while( ( el = ep->Get() ) != NULL ) |
|
|
|
{ |
|
|
|
if( MKV_IS_ID( el, KaxCluster ) ) |
|
|
|
{ |
|
|
|
cluster = (KaxCluster *)el; |
|
|
|
i_cluster_pos = cluster->GetElementPosition(); |
|
|
|
if( i_index == 0 || |
|
|
|
( i_index > 0 && p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) ) |
|
|
|
{ |
|
|
|
IndexAppendCluster( cluster ); |
|
|
|
} |
|
|
|
if( es.I_O().getFilePointer() >= i_global_position ) |
|
|
|
{ |
|
|
|
ParseCluster(); |
|
|
|
msg_Dbg( &sys.demuxer, "we found a cluster that is in the neighbourhood" ); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
msg_Err( &sys.demuxer, "This file has no cues, and we were unable to seek to the requested position by parsing." ); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if ( i_index > 0 ) |
|
|
|
{ |
|
|
|
int i_idx = 0; |
|
|
|
|
|
|
|
for( ; i_idx < i_index; i_idx++ ) |
|
|
|
{ |
|
|
|
if( p_indexes[i_idx].i_time + i_time_offset > i_date ) |
|
|
|
{ |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( i_idx > 0 ) |
|
|
|
{ |
|
|
|
i_idx--; |
|
|
|
} |
|
|
|
|
|
|
|
i_seek_position = p_indexes[i_idx].i_position; |
|
|
|
i_seek_time = p_indexes[i_idx].i_time; |
|
|
|
} |
|
|
|
|
|
|
|
msg_Dbg( &sys.demuxer, "seek got %"PRId64" (%d%%)", |
|
|
|
i_seek_time, (int)( 100 * i_seek_position / stream_Size( sys.demuxer.s ) ) ); |
|
|
|
|
|
|
|
es.I_O().setFilePointer( i_seek_position, seek_beginning ); |
|
|
|
|
|
|
|
delete ep; |
|
|
|
ep = new EbmlParser( &es, segment, &sys.demuxer ); |
|
|
|
cluster = NULL; |
|
|
|
|
|
|
|
sys.i_start_pts = i_date; |
|
|
|
|
|
|
|
/* now parse until key frame */ |
|
|
|
i_track_skipping = 0; |
|
|
|
for( i_track = 0; i_track < tracks.size(); i_track++ ) |
|
|
|
{ |
|
|
|
if( tracks[i_track]->fmt.i_cat == VIDEO_ES ) |
|
|
|
{ |
|
|
|
tracks[i_track]->b_search_keyframe = true; |
|
|
|
i_track_skipping++; |
|
|
|
} |
|
|
|
} |
|
|
|
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_date ); |
|
|
|
|
|
|
|
while( i_track_skipping > 0 ) |
|
|
|
{ |
|
|
|
if( BlockGet( block, simpleblock, &i_block_ref1, &i_block_ref2, &i_block_duration ) ) |
|
|
|
{ |
|
|
|
msg_Warn( &sys.demuxer, "cannot get block EOF?" ); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
for( i_track = 0; i_track < tracks.size(); i_track++ ) |
|
|
|
{ |
|
|
|
if( (simpleblock && tracks[i_track]->i_number == simpleblock->TrackNum()) || |
|
|
|
(block && tracks[i_track]->i_number == block->TrackNum()) ) |
|
|
|
{ |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( simpleblock ) |
|
|
|
sys.i_pts = (sys.i_chapter_time + simpleblock->GlobalTimecode()) / (mtime_t) 1000; |
|
|
|
else |
|
|
|
sys.i_pts = (sys.i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000; |
|
|
|
|
|
|
|
if( i_track < tracks.size() ) |
|
|
|
{ |
|
|
|
if( sys.i_pts > sys.i_start_pts ) |
|
|
|
{ |
|
|
|
cluster = static_cast<KaxCluster*>(ep->UnGet( i_block_pos, i_cluster_pos )); |
|
|
|
i_track_skipping = 0; |
|
|
|
} |
|
|
|
else if( tracks[i_track]->fmt.i_cat == VIDEO_ES ) |
|
|
|
{ |
|
|
|
if( i_block_ref1 == 0 && tracks[i_track]->b_search_keyframe ) |
|
|
|
{ |
|
|
|
tracks[i_track]->b_search_keyframe = false; |
|
|
|
i_track_skipping--; |
|
|
|
} |
|
|
|
if( !tracks[i_track]->b_search_keyframe ) |
|
|
|
{ |
|
|
|
BlockDecode( &sys.demuxer, block, simpleblock, sys.i_pts, 0, i_block_ref1 >= 0 || i_block_ref2 > 0 ); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
delete block; |
|
|
|
} |
|
|
|
|
|
|
|
/* FIXME current ES_OUT_SET_NEXT_DISPLAY_TIME does not work that well if
|
|
|
|
* the delay is too high. */ |
|
|
|
if( sys.i_pts + 500*1000 < sys.i_start_pts ) |
|
|
|
{ |
|
|
|
sys.i_start_pts = sys.i_pts; |
|
|
|
|
|
|
|
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, sys.i_start_pts ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Demux: reads and demuxes data packets |
|
|
|
***************************************************************************** |
|
|
|
|