diff options
author | Johann <johannkoenig@google.com> | 2012-04-04 16:46:43 -0700 |
---|---|---|
committer | Johann <johannkoenig@google.com> | 2012-04-04 16:46:43 -0700 |
commit | f02a7f5c42db707d20e59ff28f32d1eaebcc5429 (patch) | |
tree | f2b0f970e7abee6122333d39fc5da6ca62d63917 /media/libstagefright | |
parent | 4762a5164a986bd6a7ca0e7aba43881b64f146dd (diff) | |
download | frameworks_av-f02a7f5c42db707d20e59ff28f32d1eaebcc5429.zip frameworks_av-f02a7f5c42db707d20e59ff28f32d1eaebcc5429.tar.gz frameworks_av-f02a7f5c42db707d20e59ff28f32d1eaebcc5429.tar.bz2 |
Trust the Cues element
With the Cue based seeking we will get the closest previous key frame.
For audio, use the Cue file to find the Cluster with the video key frame
then incrementally look for the audio Block.
Change-Id: Idc934cca1286b1bb48ee7577b27903ca488a0610
Diffstat (limited to 'media/libstagefright')
-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; |