diff options
Diffstat (limited to 'media/libstagefright/matroska')
-rw-r--r-- | media/libstagefright/matroska/MatroskaExtractor.cpp | 66 |
1 files changed, 22 insertions, 44 deletions
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index f8c272c..8c63df9 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -95,7 +95,7 @@ struct BlockIterator { void reset(); void seek( - int64_t seekTimeUs, bool seekToKeyFrame, + int64_t seekTimeUs, bool isAudio, int64_t *actualFrameTimeUs); const mkvparser::Block *block() const; @@ -307,7 +307,7 @@ void BlockIterator::reset() { } void BlockIterator::seek( - int64_t seekTimeUs, bool seekToKeyFrame, + int64_t seekTimeUs, bool isAudio, int64_t *actualFrameTimeUs) { Mutex::Autolock autoLock(mExtractor->mLock); @@ -372,9 +372,7 @@ void BlockIterator::seek( } } - // Find the video track for seeking. It doesn't make sense to search the - // audio track because we'd still want to make sure we're jumping to a - // keyframe in the video track. + // The Cue index is built around video keyframes mkvparser::Tracks const *pTracks = pSegment->GetTracks(); const mkvparser::Track *pTrack = NULL; for (size_t index = 0; index < pTracks->GetTracksCount(); ++index) { @@ -385,57 +383,37 @@ void BlockIterator::seek( } } + // Always *search* based on the video track, but finalize based on mTrackNum const mkvparser::CuePoint::TrackPosition* pTP; - if (pTrack) { + if (pTrack && pTrack->GetType() == 1) { pCues->Find(seekTimeNs, pTrack, pCP, pTP); } else { - ALOGE("Did not locate a VIDEO_TRACK"); + ALOGE("Did not locate the video track for seeking"); return; } mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); - if (pTP->m_block > 0) { - // m_block starts at 1, but mBlockEntryIndex is expected to start at 0 - mBlockEntryIndex = pTP->m_block - 1; - } else { - ALOGE("m_block must be > 0"); - return; - } - long prevKeyFrameBlockEntryIndex = -1; + CHECK(mCluster); + CHECK(!mCluster->EOS()); + + // mBlockEntryIndex starts at 0 but m_block starts at 1 + CHECK_GT(pTP->m_block, 0); + mBlockEntryIndex = pTP->m_block - 1; for (;;) { advance_l(); - if (eos()) { - break; - } - - if (block()->GetTrackNumber() != mTrackNum) { - continue; - } - - if (block()->IsKey()) { - prevKeyFrameBlockEntryIndex = mBlockEntryIndex - 1; - } - - int64_t timeNs = block()->GetTime(mCluster); + if (eos()) break; - if (timeNs >= seekTimeNs) { - *actualFrameTimeUs = (timeNs + 500ll) / 1000ll; + if (isAudio || block()->IsKey()) { + // Accept the first key frame + *actualFrameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; + ALOGV("Requested seek point: %lld actual: %lld", + seekTimeUs, actualFrameTimeUs); break; } } - - if (eos()) { - return; - } - - if (seekToKeyFrame && !block()->IsKey()) { - CHECK_GE(prevKeyFrameBlockEntryIndex, 0); - mBlockEntryIndex = prevKeyFrameBlockEntryIndex; - advance_l(); - } } const mkvparser::Block *BlockIterator::block() const { @@ -521,11 +499,11 @@ status_t MatroskaSource::read( && !mExtractor->isLiveStreaming()) { clearPendingFrames(); - // Apparently keyframe indication in audio tracks is unreliable, - // fortunately in all our currently supported audio encodings every - // frame is effectively a keyframe. + // The audio we want is located by using the Cues to seek the video + // stream to find the target Cluster then iterating to finalize for + // audio. int64_t actualFrameTimeUs; - mBlockIter.seek(seekTimeUs, !mIsAudio, &actualFrameTimeUs); + mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); if (mode == ReadOptions::SEEK_CLOSEST) { targetSampleTimeUs = actualFrameTimeUs; |