@@ -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
325358const 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