@ -119,6 +119,9 @@ private:
const mkvparser : : BlockEntry * mBlockEntry ;
long mBlockEntryIndex ;
unsigned long mTrackType ;
void seekwithoutcue_l ( int64_t seekTimeUs , int64_t * actualFrameTimeUs ) ;
void advance_l ( ) ;
BlockIterator ( const BlockIterator & ) ;
@ -290,6 +293,7 @@ BlockIterator::BlockIterator(
mCluster ( NULL ) ,
mBlockEntry ( NULL ) ,
mBlockEntryIndex ( 0 ) {
mTrackType = mExtractor - > mSegment - > GetTracks ( ) - > GetTrackByNumber ( trackNum ) - > GetType ( ) ;
reset ( ) ;
}
@ -442,12 +446,14 @@ void BlockIterator::seek(
}
if ( ! pCues ) {
ALOGE ( " No Cues in file " ) ;
ALOGV ( " No Cues in file,seek without cue data " ) ;
seekwithoutcue_l ( seekTimeUs , actualFrameTimeUs ) ;
return ;
}
}
else if ( ! pSH ) {
ALOGE ( " No SeekHead " ) ;
ALOGV ( " No SeekHead, seek without cue data " ) ;
seekwithoutcue_l ( seekTimeUs , actualFrameTimeUs ) ;
return ;
}
@ -456,7 +462,9 @@ void BlockIterator::seek(
while ( ! pCues - > DoneParsing ( ) ) {
pCues - > LoadCuePoint ( ) ;
pCP = pCues - > GetLast ( ) ;
CHECK ( pCP ) ;
ALOGV ( " pCP = %s " , pCP = = NULL ? " NULL " : " not NULL " ) ;
if ( pCP = = NULL )
continue ;
size_t trackCount = mExtractor - > mTracks . size ( ) ;
for ( size_t index = 0 ; index < trackCount ; + + index ) {
@ -494,6 +502,7 @@ void BlockIterator::seek(
// Always *search* based on the video track, but finalize based on mTrackNum
if ( ! pTP ) {
ALOGE ( " Did not locate the video track for seeking " ) ;
seekwithoutcue_l ( seekTimeUs , actualFrameTimeUs ) ;
return ;
}
@ -537,6 +546,31 @@ int64_t BlockIterator::blockTimeUs() const {
return ( mBlockEntry - > GetBlock ( ) - > GetTime ( mCluster ) + 500ll ) / 1000ll ;
}
void BlockIterator : : seekwithoutcue_l ( int64_t seekTimeUs , int64_t * actualFrameTimeUs ) {
mCluster = mExtractor - > mSegment - > FindCluster ( seekTimeUs * 1000ll ) ;
const long status = mCluster - > GetFirst ( mBlockEntry ) ;
if ( status < 0 ) { // error
ALOGE ( " get last blockenry failed! " ) ;
mCluster = NULL ;
return ;
}
mBlockEntryIndex = 0 ;
while ( ! eos ( ) & & ( ( block ( ) - > GetTrackNumber ( ) ! = mTrackNum ) | | ( blockTimeUs ( ) < seekTimeUs ) ) ) {
advance_l ( ) ;
}
// video track will seek to the next key frame.
if ( mTrackType = = 1 ) {
while ( ! eos ( ) & & ( ( block ( ) - > GetTrackNumber ( ) ! = mTrackNum ) | |
! mBlockEntry - > GetBlock ( ) - > IsKey ( ) ) ) {
advance_l ( ) ;
}
}
* actualFrameTimeUs = blockTimeUs ( ) ;
ALOGV ( " seekTimeUs:%lld, actualFrameTimeUs:%lld, tracknum:%lld " ,
( long long ) seekTimeUs , ( long long ) * actualFrameTimeUs , ( long long ) mTrackNum ) ;
}
////////////////////////////////////////////////////////////////////////////////
static unsigned U24_AT ( const uint8_t * ptr ) {
@ -956,17 +990,56 @@ MatroskaExtractor::MatroskaExtractor(DataSourceHelper *source)
return ;
}
// from mkvparser::Segment::Load(), but stop at first cluster
ret = mSegment - > ParseHeaders ( ) ;
if ( ret = = 0 ) {
long len ;
ret = mSegment - > LoadCluster ( pos , len ) ;
if ( ret > = 1 ) {
// no more clusters
ret = 0 ;
if ( mIsLiveStreaming ) {
// from mkvparser::Segment::Load(), but stop at first cluster
ret = mSegment - > ParseHeaders ( ) ;
if ( ret = = 0 ) {
long len ;
ret = mSegment - > LoadCluster ( pos , len ) ;
if ( ret > = 1 ) {
// no more clusters
ret = 0 ;
}
} else if ( ret > 0 ) {
ret = mkvparser : : E_BUFFER_NOT_FULL ;
}
} else {
ret = mSegment - > ParseHeaders ( ) ;
if ( ret < 0 ) {
ALOGE ( " Segment parse header return fail %lld " , ret ) ;
delete mSegment ;
mSegment = NULL ;
return ;
} else if ( ret = = 0 ) {
const mkvparser : : Cues * mCues = mSegment - > GetCues ( ) ;
const mkvparser : : SeekHead * mSH = mSegment - > GetSeekHead ( ) ;
if ( ( mCues = = NULL ) & & ( mSH ! = NULL ) ) {
size_t count = mSH - > GetCount ( ) ;
const mkvparser : : SeekHead : : Entry * mEntry ;
for ( size_t index = 0 ; index < count ; index + + ) {
mEntry = mSH - > GetEntry ( index ) ;
if ( mEntry - > id = = 0x0C53BB6B ) { // Cues ID
long len ;
long long pos ;
mSegment - > ParseCues ( mEntry - > pos , pos , len ) ;
mCues = mSegment - > GetCues ( ) ;
ALOGV ( " find cue data by seekhead " ) ;
break ;
}
}
}
if ( mCues ) {
long len ;
ret = mSegment - > LoadCluster ( pos , len ) ;
ALOGV ( " has Cue data, Cluster num=%ld " , mSegment - > GetCount ( ) ) ;
} else {
long status_Load = mSegment - > Load ( ) ;
ALOGW ( " no Cue data,Segment Load status:%ld " , status_Load ) ;
}
} else if ( ret > 0 ) {
ret = mkvparser : : E_BUFFER_NOT_FULL ;
}
} else if ( ret > 0 ) {
ret = mkvparser : : E_BUFFER_NOT_FULL ;
}
if ( ret < 0 ) {