diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5d7ac43b6a..85f9aec835 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -67,6 +67,8 @@ ([#2882](https://github.com/google/ExoPlayer/issues/2882)). * Correctly populate `Format.label` for audio only HLS streams ([#9608](https://github.com/google/ExoPlayer/issues/9608)). + * Timestamp adjuster initialization occurs after opening the `DataSource` + ([#9777](https://github.com/google/ExoPlayer/pull/9777)). * UI: * Fix the color of the numbers in `StyledPlayerView` rewind and fastforward buttons when using certain themes 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 d0711a6d27..9bdc2b9079 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 @@ -423,19 +423,19 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; // initDataLoadRequired => initDataSource != null && initDataSpec != null Assertions.checkNotNull(initDataSource); Assertions.checkNotNull(initDataSpec); - feedDataToExtractor(initDataSource, initDataSpec, initSegmentEncrypted); + feedDataToExtractor( + initDataSource, + initDataSpec, + initSegmentEncrypted, + /* initializeTimestampAdjuster= */ false); nextLoadPosition = 0; initDataLoadRequired = false; } @RequiresNonNull("output") private void loadMedia() throws IOException { - try { - timestampAdjuster.sharedInitializeOrWait(isMasterTimestampSource, startTimeUs); - } catch (InterruptedException e) { - throw new InterruptedIOException(); - } - feedDataToExtractor(dataSource, dataSpec, mediaSegmentEncrypted); + feedDataToExtractor( + dataSource, dataSpec, mediaSegmentEncrypted, /* initializeTimestampAdjuster= */ true); } /** @@ -445,7 +445,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; */ @RequiresNonNull("output") private void feedDataToExtractor( - DataSource dataSource, DataSpec dataSpec, boolean dataIsEncrypted) throws IOException { + DataSource dataSource, + DataSpec dataSpec, + boolean dataIsEncrypted, + boolean initializeTimestampAdjuster) + throws IOException { // If we previously fed part of this chunk to the extractor, we need to skip it this time. For // encrypted content we need to skip the data by reading it through the source, so as to ensure // correct decryption of the remainder of the chunk. For clear content, we can request the @@ -460,7 +464,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; skipLoadedBytes = false; } try { - ExtractorInput input = prepareExtraction(dataSource, loadDataSpec); + ExtractorInput input = + prepareExtraction(dataSource, loadDataSpec, initializeTimestampAdjuster); if (skipLoadedBytes) { input.skipFully(nextLoadPosition); } @@ -484,9 +489,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; @RequiresNonNull("output") @EnsuresNonNull("extractor") - private DefaultExtractorInput prepareExtraction(DataSource dataSource, DataSpec dataSpec) + private DefaultExtractorInput prepareExtraction( + DataSource dataSource, DataSpec dataSpec, boolean initializeTimestampAdjuster) throws IOException { long bytesToRead = dataSource.open(dataSpec); + if (initializeTimestampAdjuster) { + try { + timestampAdjuster.sharedInitializeOrWait(isMasterTimestampSource, startTimeUs); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } DefaultExtractorInput extractorInput = new DefaultExtractorInput(dataSource, dataSpec.position, bytesToRead);