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 cad1cdc03d..693af382f1 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 @@ -138,9 +138,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { if (loader.isLoading()) { loader.cancelLoading(); } else { - discardExtractors(); - clearCurrentLoadable(); - previousTsLoadable = null; + clearState(); } } } @@ -186,7 +184,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { TsExtractor extractor = extractors.getFirst(); while (extractors.size() > 1 && !extractor.hasSamples()) { // We're finished reading from the extractor for all tracks, and so can discard it. - extractors.removeFirst().clear(); + extractors.removeFirst().release(); extractor = extractors.getFirst(); } @@ -294,11 +292,10 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { @Override public void onLoadCanceled(Loadable loadable) { - clearCurrentLoadable(); if (enabledTrackCount > 0) { restartFrom(pendingResetPositionUs); } else { - previousTsLoadable = null; + clearState(); } } @@ -312,17 +309,24 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { private void restartFrom(long positionUs) { pendingResetPositionUs = positionUs; - previousTsLoadable = null; loadingFinished = false; - discardExtractors(); if (loader.isLoading()) { loader.cancelLoading(); } else { - clearCurrentLoadable(); + clearState(); maybeStartLoading(); } } + private void clearState() { + for (int i = 0; i < extractors.size(); i++) { + extractors.get(i).release(); + } + extractors.clear(); + clearCurrentLoadable(); + previousTsLoadable = null; + } + private void clearCurrentLoadable() { currentLoadable = null; currentLoadableException = null; @@ -370,13 +374,6 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { loader.startLoading(currentLoadable, this); } - private void discardExtractors() { - for (int i = 0; i < extractors.size(); i++) { - extractors.get(i).clear(); - } - extractors.clear(); - } - private boolean isTsChunk(HlsChunk chunk) { return chunk instanceof TsChunk; } diff --git a/library/src/main/java/com/google/android/exoplayer/hls/TsExtractor.java b/library/src/main/java/com/google/android/exoplayer/hls/TsExtractor.java index 6a00873eae..d574078162 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/TsExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/TsExtractor.java @@ -58,12 +58,16 @@ public final class TsExtractor { private final SamplePool samplePool; /* package */ final long firstSampleTimestamp; - private boolean prepared; + // Accessed only by the consuming thread. private boolean spliceConfigured; + // Accessed only by the loading thread. /* package */ boolean pendingFirstSampleTimestampAdjustment; /* package */ long sampleTimestampOffsetUs; - /* package */ long largestParsedTimestampUs; + + // Accessed by both the loading and consuming threads. + private volatile boolean prepared; + /* package */ volatile long largestParsedTimestampUs; public TsExtractor(long firstSampleTimestamp, SamplePool samplePool) { this.firstSampleTimestamp = firstSampleTimestamp; @@ -111,11 +115,13 @@ public final class TsExtractor { } /** - * Flushes any pending or incomplete samples, returning them to the sample pool. + * Releases the extractor, recycling any pending or incomplete samples to the sample pool. + *
+ * This method should not be called whilst {@link #read(DataSource)} is also being invoked.
*/
- public void clear() {
+ public void release() {
for (int i = 0; i < sampleQueues.size(); i++) {
- sampleQueues.valueAt(i).clear();
+ sampleQueues.valueAt(i).release();
}
}
@@ -504,16 +510,19 @@ public final class TsExtractor {
private final SamplePool samplePool;
private final ConcurrentLinkedQueue