diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java
index 532131ba7d..b40bbb35d1 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java
@@ -87,18 +87,18 @@ public interface MediaPeriod extends SequenceableLoader {
TrackGroupArray getTrackGroups();
/**
- * Returns a list of {@link StreamKey stream keys} which allow to filter the media in this period
- * to load only the parts needed to play the provided {@link TrackSelection}.
+ * Returns a list of {@link StreamKey StreamKeys} which allow to filter the media in this period
+ * to load only the parts needed to play the provided {@link TrackSelection TrackSelections}.
*
*
This method is only called after the period has been prepared.
*
- * @param trackSelection The {@link TrackSelection} describing the tracks for which stream keys
- * are requested.
- * @return The corresponding {@link StreamKey stream keys} for the selected tracks, or an empty
+ * @param trackSelections The {@link TrackSelection TrackSelections} describing the tracks for
+ * which stream keys are requested.
+ * @return The corresponding {@link StreamKey StreamKeys} for the selected tracks, or an empty
* list if filtering is not possible and the entire media needs to be loaded to play the
* selected tracks.
*/
- default List getStreamKeys(TrackSelection trackSelection) {
+ default List getStreamKeys(List trackSelections) {
return Collections.emptyList();
}
diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java
index 8798ea09b2..ae6b60183c 100644
--- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java
+++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java
@@ -144,11 +144,14 @@ import java.util.List;
}
@Override
- public List getStreamKeys(TrackSelection trackSelection) {
- List streamKeys = new ArrayList<>(trackSelection.length());
- int streamElementIndex = trackGroups.indexOf(trackSelection.getTrackGroup());
- for (int i = 0; i < trackSelection.length(); i++) {
- streamKeys.add(new StreamKey(streamElementIndex, trackSelection.getIndexInTrackGroup(i)));
+ public List getStreamKeys(List trackSelections) {
+ List streamKeys = new ArrayList<>();
+ for (int selectionIndex = 0; selectionIndex < trackSelections.size(); selectionIndex++) {
+ TrackSelection trackSelection = trackSelections.get(selectionIndex);
+ int streamElementIndex = trackGroups.indexOf(trackSelection.getTrackGroup());
+ for (int i = 0; i < trackSelection.length(); i++) {
+ streamKeys.add(new StreamKey(streamElementIndex, trackSelection.getIndexInTrackGroup(i)));
+ }
}
return streamKeys;
}
diff --git a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriodTest.java b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriodTest.java
index f4feef3949..54de4badbd 100644
--- a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriodTest.java
+++ b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriodTest.java
@@ -61,7 +61,7 @@ public class SsMediaPeriodTest {
createStreamElement(
/* name= */ "text", C.TRACK_TYPE_TEXT, createTextFormat(/* language= */ "eng")));
FilterableManifestMediaPeriodFactory mediaPeriodFactory =
- manifest ->
+ (manifest, periodIndex) ->
new SsMediaPeriod(
manifest,
mock(SsChunkSource.Factory.class),
@@ -77,7 +77,7 @@ public class SsMediaPeriodTest {
mock(Allocator.class));
MediaPeriodAsserts.assertGetStreamKeysAndManifestFilterIntegration(
- mediaPeriodFactory, testManifest);
+ mediaPeriodFactory, testManifest, /* periodIndex= */ 0);
}
private static Format createVideoFormat(int bitrate) {
diff --git a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaPeriodAsserts.java b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaPeriodAsserts.java
index 48b9128caf..5235163684 100644
--- a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaPeriodAsserts.java
+++ b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaPeriodAsserts.java
@@ -30,6 +30,8 @@ import com.google.android.exoplayer2.trackselection.BaseTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.util.ConditionVariable;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@@ -45,53 +47,81 @@ public final class MediaPeriodAsserts {
public interface FilterableManifestMediaPeriodFactory> {
/** Returns media period based on the provided filterable manifest. */
- MediaPeriod createMediaPeriod(T manifest);
+ MediaPeriod createMediaPeriod(T manifest, int periodIndex);
}
private MediaPeriodAsserts() {}
/**
- * Asserts that the values returns by {@link MediaPeriod#getStreamKeys(TrackSelection)} are
- * compatible with a {@link FilterableManifest} using these stream keys.
+ * Asserts that the values returns by {@link MediaPeriod#getStreamKeys(List)} are compatible with
+ * a {@link FilterableManifest} using these stream keys.
*
* @param mediaPeriodFactory A factory to create a {@link MediaPeriod} based on a manifest.
* @param manifest The manifest which is to be tested.
+ * @param periodIndex The index of period in the manifest.
*/
public static >
void assertGetStreamKeysAndManifestFilterIntegration(
- FilterableManifestMediaPeriodFactory mediaPeriodFactory, T manifest) {
- MediaPeriod mediaPeriod = mediaPeriodFactory.createMediaPeriod(manifest);
+ FilterableManifestMediaPeriodFactory mediaPeriodFactory, T manifest, int periodIndex) {
+ MediaPeriod mediaPeriod = mediaPeriodFactory.createMediaPeriod(manifest, periodIndex);
TrackGroupArray trackGroupArray = getTrackGroups(mediaPeriod);
+ // Create test vector of query test selections:
+ // - One selection with one track per group, two tracks or all tracks.
+ // - Two selections with tracks from multiple groups, or tracks from a single group.
+ // - Multiple selections with tracks from all groups.
+ List> testSelections = new ArrayList<>();
for (int i = 0; i < trackGroupArray.length; i++) {
TrackGroup trackGroup = trackGroupArray.get(i);
-
- // For each track group, create various test selections.
- List testSelections = new ArrayList<>();
for (int j = 0; j < trackGroup.length; j++) {
- testSelections.add(new TestTrackSelection(trackGroup, j));
+ testSelections.add(Collections.singletonList(new TestTrackSelection(trackGroup, j)));
}
if (trackGroup.length > 1) {
- testSelections.add(new TestTrackSelection(trackGroup, 0, 1));
+ testSelections.add(Collections.singletonList(new TestTrackSelection(trackGroup, 0, 1)));
+ testSelections.add(
+ Arrays.asList(
+ new TrackSelection[] {
+ new TestTrackSelection(trackGroup, 0), new TestTrackSelection(trackGroup, 1)
+ }));
}
if (trackGroup.length > 2) {
int[] allTracks = new int[trackGroup.length];
for (int j = 0; j < trackGroup.length; j++) {
allTracks[j] = j;
}
- testSelections.add(new TestTrackSelection(trackGroup, allTracks));
+ testSelections.add(
+ Collections.singletonList(new TestTrackSelection(trackGroup, allTracks)));
}
+ }
+ if (trackGroupArray.length > 1) {
+ testSelections.add(
+ Arrays.asList(
+ new TrackSelection[] {
+ new TestTrackSelection(trackGroupArray.get(0), 0),
+ new TestTrackSelection(trackGroupArray.get(1), 0)
+ }));
+ }
+ if (trackGroupArray.length > 2) {
+ List selectionsFromAllGroups = new ArrayList<>();
+ for (int i = 0; i < trackGroupArray.length; i++) {
+ selectionsFromAllGroups.add(new TestTrackSelection(trackGroupArray.get(i), 0));
+ }
+ testSelections.add(selectionsFromAllGroups);
+ }
- // Get stream keys for each selection and check that the resulting filtered manifest includes
- // at least the same subset of tracks.
- for (TrackSelection testSelection : testSelections) {
- List streamKeys = mediaPeriod.getStreamKeys(testSelection);
- T filteredManifest = manifest.copy(streamKeys);
- MediaPeriod filteredMediaPeriod = mediaPeriodFactory.createMediaPeriod(filteredManifest);
- TrackGroupArray filteredTrackGroupArray = getTrackGroups(filteredMediaPeriod);
- Format[] expectedFormats = new Format[testSelection.length()];
- for (int k = 0; k < testSelection.length(); k++) {
- expectedFormats[k] = testSelection.getFormat(k);
+ // Verify for each case that stream keys can be used to create filtered tracks which still
+ // contain at least all requested formats.
+ for (List testSelection : testSelections) {
+ List streamKeys = mediaPeriod.getStreamKeys(testSelection);
+ T filteredManifest = manifest.copy(streamKeys);
+ // The filtered manifest should only have one period left.
+ MediaPeriod filteredMediaPeriod =
+ mediaPeriodFactory.createMediaPeriod(filteredManifest, /* periodIndex= */ 0);
+ TrackGroupArray filteredTrackGroupArray = getTrackGroups(filteredMediaPeriod);
+ for (TrackSelection trackSelection : testSelection) {
+ Format[] expectedFormats = new Format[trackSelection.length()];
+ for (int k = 0; k < trackSelection.length(); k++) {
+ expectedFormats[k] = trackSelection.getFormat(k);
}
assertOneTrackGroupContainsFormats(filteredTrackGroupArray, expectedFormats);
}