From 2b13165738df01ff21bb323966def95d7f4e0001 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 22 Apr 2016 03:02:05 -0700 Subject: [PATCH] Optimize HLS seeking. I think the concept of a sparse track might need formalizing in Format at some point. We should probably do a similar thing with sparse tracks in ExtractorSampleSource as well. WDYT? Issue: #551 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=120530195 --- .../extractor/ExtractorSampleSource.java | 4 +++- .../exoplayer/hls/HlsSampleSource.java | 22 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java index 2c951eaa3f..e0d8187a8e 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java @@ -567,7 +567,9 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu // If we're not pending a reset, see if we can seek within the sample queues. boolean seekInsideBuffer = !isPendingReset(); for (int i = 0; seekInsideBuffer && i < sampleQueues.length; i++) { - seekInsideBuffer = sampleQueues[i].skipToKeyframeBefore(positionUs); + if (trackEnabledStates[i]) { + seekInsideBuffer = sampleQueues[i].skipToKeyframeBefore(positionUs); + } } // If we failed to seek within the sample queues, we need to restart. if (!seekInsideBuffer) { diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java index 722596b498..4134820003 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java @@ -532,8 +532,26 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback { lastSeekPositionUs = positionUs; downstreamPositionUs = positionUs; Arrays.fill(pendingResets, true); - chunkSource.seek(); - restartFrom(positionUs); + boolean seekInsideBuffer = !isPendingReset(); + // TODO[REFACTOR]: This will nearly always fail to seek inside all buffers due to sparse tracks + // such as ID3 (probably EIA608 too). We need a way to not care if we can't seek to the keyframe + // before for such tracks. For ID3 we probably explicitly don't want the keyframe before, even + // if we do have it, since it might be quite a long way behind the seek position. We probably + // only want to output ID3 buffers whose timestamps are greater than or equal to positionUs. + for (int i = 0; seekInsideBuffer && i < sampleQueues.length; i++) { + if (groupEnabledStates[i]) { + seekInsideBuffer = sampleQueues[i].skipToKeyframeBefore(positionUs); + } + } + if (seekInsideBuffer) { + while (mediaChunks.size() > 1 && mediaChunks.get(1).startTimeUs <= positionUs) { + mediaChunks.removeFirst(); + } + } else { + // If we failed to seek within the sample queues, we need to restart. + chunkSource.seek(); + restartFrom(positionUs); + } } private void discardSamplesForDisabledTracks() {