From 0f18fd87ac59e4652f9190a9018597589292ca2e Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 25 Jun 2024 04:35:32 -0700 Subject: [PATCH] Add guard against additional tracks reported by Extractors Extractors should not report additional tracks once they called ExtractorOutput.endTracks. This causes thread safety issues in ProgressiveMediaPeriod where the array of sample queues is extended while the playback thread accesses the arrays. Detecting this problem early is beneficial to avoid unexplained exceptions later one. In most cases where this may happen (namely TS extractors finding new tracks), it's better to ignore the new tracks instead of failing completely. So this change adds a warning log message and assigns a placeholder output. Note: The same workaround already exists in HlsSampleStreamWrapper and MediaExtractorCompat. Issue: androidx/media#1476 #cherrypick PiperOrigin-RevId: 646427213 (cherry picked from commit 18e631ff790e0e9b3630ea8e36efb468474d0877) --- RELEASENOTES.md | 3 +++ .../media3/exoplayer/source/ProgressiveMediaPeriod.java | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 51e9fb0548..43bc040a42 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -9,6 +9,9 @@ * Fix some audio focus inconsistencies, e.g. not reporting full or transient focus loss while the player is paused ([#1436](https://github.com/androidx/media/issues/1436)). + * Fix potential `IndexOutOfBoundsException` caused by extractors reporting + additional tracks after the initial preparation step + ([#1476](https://github.com/androidx/media/issues/1476)). * Transformer: * Track Selection: * Extractors: diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java index 444d2168d0..0ee2cc1f36 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java @@ -31,6 +31,7 @@ import androidx.media3.common.ParserException; import androidx.media3.common.TrackGroup; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.ConditionVariable; +import androidx.media3.common.util.Log; import androidx.media3.common.util.NullableType; import androidx.media3.common.util.ParsableByteArray; import androidx.media3.common.util.Util; @@ -53,6 +54,7 @@ import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy.LoadErrorInfo; import androidx.media3.exoplayer.upstream.Loader; import androidx.media3.exoplayer.upstream.Loader.LoadErrorAction; import androidx.media3.exoplayer.upstream.Loader.Loadable; +import androidx.media3.extractor.DummyTrackOutput; import androidx.media3.extractor.Extractor; import androidx.media3.extractor.ExtractorOutput; import androidx.media3.extractor.ForwardingSeekMap; @@ -93,6 +95,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; void onSourceInfoRefreshed(long durationUs, boolean isSeekable, boolean isLive); } + private static final String TAG = "ProgressiveMediaPeriod"; + /** * When the source's duration is unknown, it is calculated by adding this value to the largest * sample timestamp seen when buffering completes. @@ -733,6 +737,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return sampleQueues[i]; } } + if (sampleQueuesBuilt) { + Log.w(TAG, "Extractor added new track (id=" + id.id + ") after finishing tracks."); + return new DummyTrackOutput(); + } SampleQueue trackOutput = SampleQueue.createWithDrm(allocator, drmSessionManager, drmEventDispatcher); trackOutput.setUpstreamFormatChangeListener(this);