From d334dfdcba1eb676ff9c8708a263b0279afb4720 Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 5 Oct 2016 13:16:58 -0700 Subject: [PATCH] Fix merging of selected streams. Playback would fail if a renderer is toggled from consuming from one child to another in a single step. Issue: #1900 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=135270356 --- RELEASENOTES.md | 3 ++- .../exoplayer2/source/MergingMediaPeriod.java | 11 +++++----- .../exoplayer2/source/hls/HlsMediaPeriod.java | 22 ++++++++++++------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f2ab674102..150effebb1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -4,7 +4,8 @@ * Fixes for MergingMediaSource and sideloaded subtitles. ([#1882](https://github.com/google/ExoPlayer/issues/1882), - [#1854](https://github.com/google/ExoPlayer/issues/1854)). + [#1854](https://github.com/google/ExoPlayer/issues/1854), + [#1900](https://github.com/google/ExoPlayer/issues/1900)). * Reduced effect of application code leaking player references ([#1855](https://github.com/google/ExoPlayer/issues/1855)). * Initial support for fragmented MP4 in HLS. diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java index 81721d587c..cfab4b14aa 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java @@ -85,7 +85,8 @@ import java.util.IdentityHashMap; } } streamPeriodIndices.clear(); - // Select tracks for each child, copying the resulting streams back into the streams array. + // Select tracks for each child, copying the resulting streams back into a new streams array. + SampleStream[] newStreams = new SampleStream[selections.length]; SampleStream[] childStreams = new SampleStream[selections.length]; TrackSelection[] childSelections = new TrackSelection[selections.length]; ArrayList enabledPeriodsList = new ArrayList<>(periods.length); @@ -106,22 +107,20 @@ import java.util.IdentityHashMap; if (selectionChildIndices[j] == i) { // Assert that the child provided a stream for the selection. Assertions.checkState(childStreams[j] != null); - streams[j] = childStreams[j]; + newStreams[j] = childStreams[j]; periodEnabled = true; streamPeriodIndices.put(childStreams[j], i); } else if (streamChildIndices[j] == i) { // Assert that the child cleared any previous stream. Assertions.checkState(childStreams[j] == null); - if (selectionChildIndices[j] == C.INDEX_UNSET) { - // No other child will be setting the stream at index j, so clear it. - streams[j] = null; - } } } if (periodEnabled) { enabledPeriodsList.add(periods[i]); } } + // Copy the new streams back into the streams array. + System.arraycopy(newStreams, 0, streams, 0, newStreams.length); // Update the local state. enabledPeriods = new MediaPeriod[enabledPeriodsList.size()]; enabledPeriodsList.toArray(enabledPeriods); diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index ceb47771a6..7ed979c902 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -39,6 +39,7 @@ import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.Loader; import com.google.android.exoplayer2.upstream.ParsingLoadable; +import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; import java.util.ArrayList; import java.util.IdentityHashMap; @@ -154,7 +155,8 @@ import java.util.List; } boolean selectedNewTracks = false; streamWrapperIndices.clear(); - // Select tracks for each child, copying the resulting streams back into the streams array. + // Select tracks for each child, copying the resulting streams back into a new streams array. + SampleStream[] newStreams = new SampleStream[selections.length]; SampleStream[] childStreams = new SampleStream[selections.length]; TrackSelection[] childSelections = new TrackSelection[selections.length]; ArrayList enabledSampleStreamWrapperList = new ArrayList<>( @@ -168,19 +170,23 @@ import java.util.List; mayRetainStreamFlags, childStreams, streamResetFlags, !seenFirstTrackSelection); boolean wrapperEnabled = false; for (int j = 0; j < selections.length; j++) { - if (selectionChildIndices[j] == i - || (selectionChildIndices[j] == C.INDEX_UNSET && streamChildIndices[j] == i)) { - streams[j] = childStreams[j]; - if (childStreams[j] != null) { - wrapperEnabled = true; - streamWrapperIndices.put(childStreams[j], i); - } + if (selectionChildIndices[j] == i) { + // Assert that the child provided a stream for the selection. + Assertions.checkState(childStreams[j] != null); + newStreams[j] = childStreams[j]; + wrapperEnabled = true; + streamWrapperIndices.put(childStreams[j], i); + } else if (streamChildIndices[j] == i) { + // Assert that the child cleared any previous stream. + Assertions.checkState(childStreams[j] == null); } } if (wrapperEnabled) { enabledSampleStreamWrapperList.add(sampleStreamWrappers[i]); } } + // Copy the new streams back into the streams array. + System.arraycopy(newStreams, 0, streams, 0, newStreams.length); // Update the local state. enabledSampleStreamWrappers = new HlsSampleStreamWrapper[enabledSampleStreamWrapperList.size()]; enabledSampleStreamWrapperList.toArray(enabledSampleStreamWrappers);