Add assertion helper to verify MediaSource/TrackGroups/TrackSelection/StreamKey cycle.
This is useful to write integration tests for MediaSources which check that the stream keys returned by getStreamKeys are compatible with the respective manifest parser. PiperOrigin-RevId: 225542606
This commit is contained in:
parent
254589cbe8
commit
1a3d735bc3
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.testutil;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.offline.FilterableManifest;
|
||||
import com.google.android.exoplayer2.offline.StreamKey;
|
||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||
import com.google.android.exoplayer2.source.MediaPeriod.Callback;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
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.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/** Assertion methods for {@link MediaPeriod}. */
|
||||
public final class MediaPeriodAsserts {
|
||||
|
||||
/**
|
||||
* Interface to create media periods for testing based on a {@link FilterableManifest}.
|
||||
*
|
||||
* @param <T> The type of {@link FilterableManifest}.
|
||||
*/
|
||||
public interface FilterableManifestMediaPeriodFactory<T extends FilterableManifest<T>> {
|
||||
|
||||
/** Returns media period based on the provided filterable manifest. */
|
||||
MediaPeriod createMediaPeriod(T manifest);
|
||||
}
|
||||
|
||||
private MediaPeriodAsserts() {}
|
||||
|
||||
/**
|
||||
* Asserts that the values returns by {@link MediaPeriod#getStreamKeys(TrackSelection)} 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.
|
||||
*/
|
||||
public static <T extends FilterableManifest<T>>
|
||||
void assertGetStreamKeysAndManifestFilterIntegration(
|
||||
FilterableManifestMediaPeriodFactory<T> mediaPeriodFactory, T manifest) {
|
||||
MediaPeriod mediaPeriod = mediaPeriodFactory.createMediaPeriod(manifest);
|
||||
TrackGroupArray trackGroupArray = getTrackGroups(mediaPeriod);
|
||||
|
||||
for (int i = 0; i < trackGroupArray.length; i++) {
|
||||
TrackGroup trackGroup = trackGroupArray.get(i);
|
||||
|
||||
// For each track group, create various test selections.
|
||||
List<TrackSelection> testSelections = new ArrayList<>();
|
||||
for (int j = 0; j < trackGroup.length; j++) {
|
||||
testSelections.add(new TestTrackSelection(trackGroup, j));
|
||||
}
|
||||
if (trackGroup.length > 1) {
|
||||
testSelections.add(new TestTrackSelection(trackGroup, 0, 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));
|
||||
}
|
||||
|
||||
// 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<StreamKey> 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);
|
||||
}
|
||||
assertOneTrackGroupContainsFormats(filteredTrackGroupArray, expectedFormats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertOneTrackGroupContainsFormats(
|
||||
TrackGroupArray trackGroupArray, Format[] formats) {
|
||||
boolean foundSubset = false;
|
||||
for (int i = 0; i < trackGroupArray.length; i++) {
|
||||
if (containsFormats(trackGroupArray.get(i), formats)) {
|
||||
foundSubset = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertThat(foundSubset).isTrue();
|
||||
}
|
||||
|
||||
private static boolean containsFormats(TrackGroup trackGroup, Format[] formats) {
|
||||
HashSet<Format> allFormats = new HashSet<>();
|
||||
for (int i = 0; i < trackGroup.length; i++) {
|
||||
allFormats.add(trackGroup.getFormat(i));
|
||||
}
|
||||
for (int i = 0; i < formats.length; i++) {
|
||||
if (!allFormats.remove(formats[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static TrackGroupArray getTrackGroups(MediaPeriod mediaPeriod) {
|
||||
AtomicReference<TrackGroupArray> trackGroupArray = new AtomicReference<>(null);
|
||||
DummyMainThread dummyMainThread = new DummyMainThread();
|
||||
dummyMainThread.runOnMainThread(
|
||||
() -> {
|
||||
ConditionVariable preparedCondition = new ConditionVariable();
|
||||
mediaPeriod.prepare(
|
||||
new Callback() {
|
||||
@Override
|
||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||
preparedCondition.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
// Ignore.
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
try {
|
||||
preparedCondition.block();
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore.
|
||||
}
|
||||
trackGroupArray.set(mediaPeriod.getTrackGroups());
|
||||
});
|
||||
dummyMainThread.release();
|
||||
return trackGroupArray.get();
|
||||
}
|
||||
|
||||
private static final class TestTrackSelection extends BaseTrackSelection {
|
||||
|
||||
public TestTrackSelection(TrackGroup trackGroup, int... tracks) {
|
||||
super(trackGroup, tracks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelectedIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelectionReason() {
|
||||
return C.SELECTION_REASON_UNKNOWN;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getSelectionData() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user