diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/BundledHlsMediaChunkExtractor.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/BundledHlsMediaChunkExtractor.java index 78fc9ae732..3311d263c6 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/BundledHlsMediaChunkExtractor.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/BundledHlsMediaChunkExtractor.java @@ -101,4 +101,9 @@ public final class BundledHlsMediaChunkExtractor implements HlsMediaChunkExtract return new BundledHlsMediaChunkExtractor( newExtractorInstance, masterPlaylistFormat, timestampAdjuster); } + + @Override + public void onTruncatedSegmentParsed() { + extractor.seek(/* position= */ 0, /* timeUs= */ 0); + } } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java index 9994ede1cf..8de69a68d1 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java @@ -403,6 +403,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } try { while (!loadCanceled && extractor.read(input)) {} + } catch (EOFException e) { + if ((trackFormat.roleFlags & C.ROLE_FLAG_TRICK_PLAY) != 0) { + // See onTruncatedSegmentParsed's javadoc for more info on why we are swallowing the EOF + // exception for trick play tracks. + extractor.onTruncatedSegmentParsed(); + } else { + throw e; + } } finally { nextLoadPosition = (int) (input.getPosition() - dataSpec.position); } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunkExtractor.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunkExtractor.java index 0ca5c5d0ad..084a3450ba 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunkExtractor.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunkExtractor.java @@ -59,4 +59,15 @@ public interface HlsMediaChunkExtractor { * instances that are not {@link #isReusable() reusable}. */ HlsMediaChunkExtractor recreate(); + + /** + * Resets the sample parsing state. + * + *

Resetting the parsing state allows support for Fragmented MP4 EXT-X-I-FRAME-STREAM-INF + * segments. EXT-X-I-FRAME-STREAM-INF segments are truncated to include only a leading key frame. + * After parsing said keyframe, an extractor may reach an unexpected end of file. By resetting its + * state, we can continue feeding samples from the following segments to the extractor. See #7512 for context. + */ + void onTruncatedSegmentParsed(); }