summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp66
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;