Browse Source

mkv: removed legacy seeking

Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
pull/46/head
Filip Roséen 10 years ago
committed by Jean-Baptiste Kempf
parent
commit
45c00bfc33
  1. 181
      modules/demux/mkv/matroska_segment.cpp

181
modules/demux/mkv/matroska_segment.cpp

@ -790,188 +790,9 @@ bool matroska_segment_c::LoadSeekHeadItem( const EbmlCallbacks & ClassInfos, int
return true;
}
struct spoint
{
spoint(unsigned int tk, mtime_t mk_date, int64_t pos, int64_t cpos):
i_track(tk),i_mk_date(mk_date), i_seek_pos(pos),
i_cluster_pos(cpos){}
unsigned int i_track;
mtime_t i_mk_date;
int64_t i_seek_pos;
int64_t i_cluster_pos;
};
void matroska_segment_c::Seek( mtime_t i_mk_date, mtime_t i_mk_time_offset )
{
KaxBlock *block;
KaxSimpleBlock *simpleblock;
int64_t i_block_duration;
size_t i_track;
int64_t i_seek_position = 0; // previously i_start_pos
mtime_t i_mk_seek_time = i_mk_start_time;
mtime_t i_mk_pts = 0;
int i_cat;
bool b_has_key = false;
for( size_t i = 0; i < tracks.size(); i++)
tracks[i]->i_last_dts = VLC_TS_INVALID;
/* Don't try complex seek if we seek to 0 */
if( i_mk_date == 0 && i_mk_time_offset == 0 )
{
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME,
INT64_C(0) );
es.I_O().setFilePointer( 0 /* previously i_start_pos */ );
ep->reconstruct( &es, segment, &sys.demuxer );
cluster = NULL;
sys.i_start_pts = VLC_TS_0;
sys.i_pcr = sys.i_pts = VLC_TS_INVALID;
return;
}
indexes_t::const_iterator index_it = indexes_begin();
if ( index_idx() )
{
index_it = std::upper_bound (
indexes_begin(), indexes_end(), i_mk_date, SeekIndexFinder( i_mk_time_offset )
);
if (index_it != indexes_begin())
--index_it;
i_seek_position = index_it->i_position;
i_mk_seek_time = index_it->i_mk_time;
}
msg_Dbg( &sys.demuxer, "seek got %" PRId64 " - %" PRId64, i_mk_seek_time, i_seek_position );
es.I_O().setFilePointer( i_seek_position, seek_beginning );
ep->reconstruct( &es, segment, &sys.demuxer );
cluster = NULL;
sys.i_start_pts = i_mk_date + VLC_TS_0;
/* now parse until key frame */
std::vector<spoint> spoints;
const int es_types[3] = { VIDEO_ES, AUDIO_ES, SPU_ES };
i_cat = es_types[0];
mtime_t i_seek_preroll = 0;
for( int i = 0; i < 2; i_cat = es_types[++i] )
{
for( i_track = 0; i_track < tracks.size(); i_track++ )
{
if( tracks[i_track]->i_seek_preroll )
{
bool b_enabled;
if( es_out_Control( sys.demuxer.out,
ES_OUT_GET_ES_STATE,
tracks[i_track]->p_es,
&b_enabled ) == VLC_SUCCESS &&
b_enabled )
i_seek_preroll = __MAX( i_seek_preroll,
tracks[i_track]->i_seek_preroll );
}
if( tracks[i_track]->fmt.i_cat == i_cat )
{
spoints.push_back (
spoint (i_track, i_mk_seek_time, i_seek_position, i_seek_position)
);
}
}
if ( likely( !spoints.empty() ) )
break;
}
/*Neither video nor audio track... no seek further*/
if( unlikely( spoints.empty() ) )
{
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_mk_date );
return;
}
i_mk_date -= i_seek_preroll;
for(;;)
{
do
{
bool b_key_picture;
bool b_discardable_picture;
if( BlockGet( block, simpleblock, &b_key_picture, &b_discardable_picture, &i_block_duration ) )
{
msg_Warn( &sys.demuxer, "cannot get block EOF?" );
return;
}
if( simpleblock )
i_mk_pts = sys.i_mk_chapter_time + simpleblock->GlobalTimecode() / INT64_C(1000);
else
i_mk_pts = sys.i_mk_chapter_time + block->GlobalTimecode() / INT64_C(1000);
if( BlockFindTrackIndex( &i_track, block, simpleblock ) == VLC_SUCCESS )
{
if( tracks[i_track]->fmt.i_cat == i_cat && b_key_picture )
{
/* get the seekpoint */
std::vector<spoint>::iterator it;
for ( it = spoints.begin (); it != spoints.end (); ++it )
if (it->i_track == i_track)
break;
if (unlikely (it == spoints.end ()) ) {
msg_Err( &sys.demuxer, "Unable to locate seekpoint using i_track = %zu!", i_track);
return;
}
it->i_mk_date = i_mk_pts;
if( simpleblock )
it->i_seek_pos = simpleblock->GetElementPosition();
else
it->i_seek_pos = i_block_pos;
it->i_cluster_pos = i_cluster_pos;
b_has_key = true;
}
}
delete block;
} while( i_mk_pts < i_mk_date );
if( b_has_key || !index_idx())
break;
/* No key picture was found in the cluster seek to previous seekpoint */
i_mk_date = i_mk_time_offset + index_it->i_mk_time;
index_it--;
i_mk_pts = 0;
es.I_O().setFilePointer( index_it->i_position );
ep->reconstruct( &es, segment, &sys.demuxer );
cluster = NULL;
}
/* rewind to the last I img */
std::vector<spoint>::const_iterator it;
std::vector<spoint>::const_iterator it_min = spoints.begin ();
for (it = spoints.begin () + 1; it != spoints.end (); ++it)
if ( it->i_mk_date < it_min->i_mk_date )
it_min = it;
sys.i_pts = it_min->i_mk_date + VLC_TS_0;
sys.i_pcr = VLC_TS_INVALID;
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_mk_date );
cluster = static_cast<KaxCluster*>( ep->UnGet( it_min->i_seek_pos, it_min->i_cluster_pos ) );
/* hack use BlockGet to get the cluster then goto the wanted block */
if ( !cluster )
{
bool b_key_picture;
bool b_discardable_picture;
BlockGet( block, simpleblock, &b_key_picture, &b_discardable_picture, &i_block_duration );
delete block;
cluster = static_cast<KaxCluster*>( ep->UnGet( it_min->i_seek_pos, it_min->i_cluster_pos ) );
}
// TODO: implement
}
int matroska_segment_c::BlockFindTrackIndex( size_t *pi_track,

Loading…
Cancel
Save