Skip to content

Commit 713f90f

Browse files
committed
Experiment with seeking to closest frame instead of closest syncframe
Also supports SEEK_CLOSEST mode in the Matroska/Webm extractor. Change-Id: I257771648dfe41392a4cf8932f625489dcb9f234
1 parent 0777d2d commit 713f90f

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

media/libstagefright/AwesomePlayer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,7 @@ void AwesomePlayer::onVideoEvent() {
16091609
mSeekTimeUs,
16101610
mSeeking == SEEK_VIDEO_ONLY
16111611
? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1612-
: MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1612+
: MediaSource::ReadOptions::SEEK_CLOSEST);
16131613
}
16141614
for (;;) {
16151615
status_t err = mVideoSource->read(&mVideoBuffer, &options);

media/libstagefright/matroska/MatroskaExtractor.cpp

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ struct BlockIterator {
9393

9494
void advance();
9595
void reset();
96-
void seek(int64_t seekTimeUs, bool seekToKeyFrame);
96+
97+
void seek(
98+
int64_t seekTimeUs, bool seekToKeyFrame,
99+
int64_t *actualFrameTimeUs);
97100

98101
const mkvparser::Block *block() const;
99102
int64_t blockTimeUs() const;
@@ -303,23 +306,53 @@ void BlockIterator::reset() {
303306
} while (!eos() && block()->GetTrackNumber() != mTrackNum);
304307
}
305308

306-
void BlockIterator::seek(int64_t seekTimeUs, bool seekToKeyFrame) {
309+
void BlockIterator::seek(
310+
int64_t seekTimeUs, bool seekToKeyFrame,
311+
int64_t *actualFrameTimeUs) {
307312
Mutex::Autolock autoLock(mExtractor->mLock);
308313

309-
mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
314+
*actualFrameTimeUs = -1ll;
315+
316+
int64_t seekTimeNs = seekTimeUs * 1000ll;
317+
318+
mCluster = mExtractor->mSegment->FindCluster(seekTimeNs);
310319
mBlockEntry = NULL;
311320
mBlockEntryIndex = 0;
312321

313-
do {
322+
long prevKeyFrameBlockEntryIndex = -1;
323+
324+
for (;;) {
314325
advance_l();
315-
}
316-
while (!eos() && block()->GetTrackNumber() != mTrackNum);
317326

318-
if (seekToKeyFrame) {
319-
while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
320-
advance_l();
327+
if (eos()) {
328+
break;
329+
}
330+
331+
if (block()->GetTrackNumber() != mTrackNum) {
332+
continue;
333+
}
334+
335+
if (block()->IsKey()) {
336+
prevKeyFrameBlockEntryIndex = mBlockEntryIndex - 1;
337+
}
338+
339+
int64_t timeNs = block()->GetTime(mCluster);
340+
341+
if (timeNs >= seekTimeNs) {
342+
*actualFrameTimeUs = (timeNs + 500ll) / 1000ll;
343+
break;
321344
}
322345
}
346+
347+
if (eos()) {
348+
return;
349+
}
350+
351+
if (seekToKeyFrame && !block()->IsKey()) {
352+
CHECK_GE(prevKeyFrameBlockEntryIndex, 0);
353+
mBlockEntryIndex = prevKeyFrameBlockEntryIndex;
354+
advance_l();
355+
}
323356
}
324357

325358
const mkvparser::Block *BlockIterator::block() const {
@@ -397,6 +430,8 @@ status_t MatroskaSource::read(
397430
MediaBuffer **out, const ReadOptions *options) {
398431
*out = NULL;
399432

433+
int64_t targetSampleTimeUs = -1ll;
434+
400435
int64_t seekTimeUs;
401436
ReadOptions::SeekMode mode;
402437
if (options && options->getSeekTo(&seekTimeUs, &mode)
@@ -406,10 +441,14 @@ status_t MatroskaSource::read(
406441
// Apparently keyframe indication in audio tracks is unreliable,
407442
// fortunately in all our currently supported audio encodings every
408443
// frame is effectively a keyframe.
409-
mBlockIter.seek(seekTimeUs, !mIsAudio);
444+
int64_t actualFrameTimeUs;
445+
mBlockIter.seek(seekTimeUs, !mIsAudio, &actualFrameTimeUs);
446+
447+
if (mode == ReadOptions::SEEK_CLOSEST) {
448+
targetSampleTimeUs = actualFrameTimeUs;
449+
}
410450
}
411451

412-
again:
413452
while (mPendingFrames.empty()) {
414453
status_t err = readBlock();
415454

@@ -424,6 +463,11 @@ status_t MatroskaSource::read(
424463
mPendingFrames.erase(mPendingFrames.begin());
425464

426465
if (mType != AVC) {
466+
if (targetSampleTimeUs >= 0ll) {
467+
frame->meta_data()->setInt64(
468+
kKeyTargetTime, targetSampleTimeUs);
469+
}
470+
427471
*out = frame;
428472

429473
return OK;
@@ -506,6 +550,11 @@ status_t MatroskaSource::read(
506550
frame->release();
507551
frame = NULL;
508552

553+
if (targetSampleTimeUs >= 0ll) {
554+
buffer->meta_data()->setInt64(
555+
kKeyTargetTime, targetSampleTimeUs);
556+
}
557+
509558
*out = buffer;
510559

511560
return OK;

0 commit comments

Comments
 (0)