CompositeSequenceableLoader: Prefer buffered position of A/V tracks

Preferring audio and video tracks matches logic we already have in
[`ProgressiveMediaPeriod.getBufferedPositionUs`](f6fe90f30b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java (L403)).

PiperOrigin-RevId: 599154217
This commit is contained in:
ibaker 2024-01-17 06:30:32 -08:00 committed by Copybara-Service
parent 80bfa819c0
commit 406c0a15be
10 changed files with 286 additions and 42 deletions

View File

@ -15,39 +15,80 @@
*/
package androidx.media3.exoplayer.source;
import static androidx.media3.common.util.Assertions.checkArgument;
import static java.lang.Math.min;
import androidx.media3.common.C;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.LoadingInfo;
import com.google.common.collect.ImmutableList;
import java.util.Collections;
import java.util.List;
/** A {@link SequenceableLoader} that encapsulates multiple other {@link SequenceableLoader}s. */
@UnstableApi
public final class CompositeSequenceableLoader implements SequenceableLoader {
private final SequenceableLoader[] loaders;
private final ImmutableList<SequenceableLoaderWithTrackTypes> loadersWithTrackTypes;
/**
* @deprecated Use {@link CompositeSequenceableLoader#CompositeSequenceableLoader(List, List)}
* instead.
*/
@Deprecated
public CompositeSequenceableLoader(SequenceableLoader[] loaders) {
this.loaders = loaders;
this(
ImmutableList.copyOf(loaders),
Collections.nCopies(loaders.length, ImmutableList.of(C.TRACK_TYPE_UNKNOWN)));
}
public CompositeSequenceableLoader(
List<? extends SequenceableLoader> loaders,
List<List<@C.TrackType Integer>> loaderTrackTypes) {
ImmutableList.Builder<SequenceableLoaderWithTrackTypes> loaderAndTrackTypes =
ImmutableList.builder();
checkArgument(loaders.size() == loaderTrackTypes.size());
for (int i = 0; i < loaders.size(); i++) {
loaderAndTrackTypes.add(
new SequenceableLoaderWithTrackTypes(loaders.get(i), loaderTrackTypes.get(i)));
}
this.loadersWithTrackTypes = loaderAndTrackTypes.build();
}
@Override
public long getBufferedPositionUs() {
long bufferedPositionUs = Long.MAX_VALUE;
for (SequenceableLoader loader : loaders) {
boolean hasAudioVideoTracks = false;
long bufferedPositionAudioVideoUs = Long.MAX_VALUE;
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
SequenceableLoaderWithTrackTypes loader = loadersWithTrackTypes.get(i);
long loaderBufferedPositionUs = loader.getBufferedPositionUs();
if (loader.getTrackTypes().contains(C.TRACK_TYPE_AUDIO)
|| loader.getTrackTypes().contains(C.TRACK_TYPE_VIDEO)) {
hasAudioVideoTracks = true;
if (loaderBufferedPositionUs != C.TIME_END_OF_SOURCE) {
bufferedPositionAudioVideoUs =
min(bufferedPositionAudioVideoUs, loaderBufferedPositionUs);
}
}
if (loaderBufferedPositionUs != C.TIME_END_OF_SOURCE) {
bufferedPositionUs = min(bufferedPositionUs, loaderBufferedPositionUs);
}
}
return bufferedPositionUs == Long.MAX_VALUE ? C.TIME_END_OF_SOURCE : bufferedPositionUs;
if (hasAudioVideoTracks) {
return bufferedPositionAudioVideoUs != Long.MAX_VALUE
? bufferedPositionAudioVideoUs
: C.TIME_END_OF_SOURCE;
} else {
return bufferedPositionUs != Long.MAX_VALUE ? bufferedPositionUs : C.TIME_END_OF_SOURCE;
}
}
@Override
public long getNextLoadPositionUs() {
long nextLoadPositionUs = Long.MAX_VALUE;
for (SequenceableLoader loader : loaders) {
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
long loaderNextLoadPositionUs = loadersWithTrackTypes.get(i).getNextLoadPositionUs();
if (loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE) {
nextLoadPositionUs = min(nextLoadPositionUs, loaderNextLoadPositionUs);
}
@ -57,8 +98,8 @@ public final class CompositeSequenceableLoader implements SequenceableLoader {
@Override
public void reevaluateBuffer(long positionUs) {
for (SequenceableLoader loader : loaders) {
loader.reevaluateBuffer(positionUs);
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
loadersWithTrackTypes.get(i).reevaluateBuffer(positionUs);
}
}
@ -72,13 +113,13 @@ public final class CompositeSequenceableLoader implements SequenceableLoader {
if (nextLoadPositionUs == C.TIME_END_OF_SOURCE) {
break;
}
for (SequenceableLoader loader : loaders) {
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
long loaderNextLoadPositionUs = loadersWithTrackTypes.get(i).getNextLoadPositionUs();
boolean isLoaderBehind =
loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE
&& loaderNextLoadPositionUs <= loadingInfo.playbackPositionUs;
if (loaderNextLoadPositionUs == nextLoadPositionUs || isLoaderBehind) {
madeProgressThisIteration |= loader.continueLoading(loadingInfo);
madeProgressThisIteration |= loadersWithTrackTypes.get(i).continueLoading(loadingInfo);
}
}
madeProgress |= madeProgressThisIteration;
@ -88,11 +129,54 @@ public final class CompositeSequenceableLoader implements SequenceableLoader {
@Override
public boolean isLoading() {
for (SequenceableLoader loader : loaders) {
if (loader.isLoading()) {
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
if (loadersWithTrackTypes.get(i).isLoading()) {
return true;
}
}
return false;
}
private static final class SequenceableLoaderWithTrackTypes implements SequenceableLoader {
private final SequenceableLoader loader;
private final ImmutableList<@C.TrackType Integer> trackTypes;
public SequenceableLoaderWithTrackTypes(
SequenceableLoader loader, List<@C.TrackType Integer> trackTypes) {
this.loader = loader;
this.trackTypes = ImmutableList.copyOf(trackTypes);
}
public ImmutableList<@C.TrackType Integer> getTrackTypes() {
return trackTypes;
}
// SequenceableLoader implementation
@Override
public long getBufferedPositionUs() {
return loader.getBufferedPositionUs();
}
@Override
public long getNextLoadPositionUs() {
return loader.getNextLoadPositionUs();
}
@Override
public boolean continueLoading(LoadingInfo loadingInfo) {
return loader.continueLoading(loadingInfo);
}
@Override
public boolean isLoading() {
return loader.isLoading();
}
@Override
public void reevaluateBuffer(long positionUs) {
loader.reevaluateBuffer(positionUs);
}
}
}

View File

@ -15,17 +15,33 @@
*/
package androidx.media3.exoplayer.source;
import androidx.media3.common.C;
import androidx.media3.common.util.UnstableApi;
import java.util.List;
/** A factory to create composite {@link SequenceableLoader}s. */
@UnstableApi
public interface CompositeSequenceableLoaderFactory {
/** Returns an empty composite {@link SequenceableLoader}, with no delegate loaders. */
SequenceableLoader empty();
/**
* @deprecated Use {@link #empty()} for an empty composite loader, or {@link #create(List, List)}
* for a non-empty one.
*/
@Deprecated
SequenceableLoader createCompositeSequenceableLoader(SequenceableLoader... loaders);
/**
* Creates a composite {@link SequenceableLoader}.
*
* @param loaders The sub-loaders that make up the {@link SequenceableLoader} to be built.
* @param loaderTrackTypes The track types handled by each entry in {@code loaders}. Must be the
* same as {@code loaders}.
* @return A composite {@link SequenceableLoader} that comprises the given loaders.
*/
SequenceableLoader createCompositeSequenceableLoader(SequenceableLoader... loaders);
SequenceableLoader create(
List<? extends SequenceableLoader> loaders,
List<List<@C.TrackType Integer>> loaderTrackTypes);
}

View File

@ -15,7 +15,10 @@
*/
package androidx.media3.exoplayer.source;
import androidx.media3.common.C;
import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** Default implementation of {@link CompositeSequenceableLoaderFactory}. */
@UnstableApi
@ -23,7 +26,21 @@ public final class DefaultCompositeSequenceableLoaderFactory
implements CompositeSequenceableLoaderFactory {
@Override
public SequenceableLoader empty() {
return new CompositeSequenceableLoader(ImmutableList.of(), ImmutableList.of());
}
@Deprecated
@Override
@SuppressWarnings("deprecation") // Calling deprecated constructor
public SequenceableLoader createCompositeSequenceableLoader(SequenceableLoader... loaders) {
return new CompositeSequenceableLoader(loaders);
}
@Override
public SequenceableLoader create(
List<? extends SequenceableLoader> loaders,
List<List<@C.TrackType Integer>> loaderTrackTypes) {
return new CompositeSequenceableLoader(loaders, loaderTrackTypes);
}
}

View File

@ -29,6 +29,7 @@ import androidx.media3.exoplayer.source.chunk.Chunk;
import androidx.media3.exoplayer.source.chunk.MediaChunk;
import androidx.media3.exoplayer.source.chunk.MediaChunkIterator;
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@ -58,8 +59,7 @@ import java.util.List;
this.periods = periods;
childrenPendingPreparation = new ArrayList<>();
childTrackGroupByMergedTrackGroup = new HashMap<>();
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader();
compositeSequenceableLoader = compositeSequenceableLoaderFactory.empty();
streamPeriodIndices = new IdentityHashMap<>();
enabledPeriods = new MediaPeriod[0];
for (int i = 0; i < periods.length; i++) {
@ -172,7 +172,9 @@ import java.util.List;
// Update the local state.
enabledPeriods = enabledPeriodsList.toArray(new MediaPeriod[0]);
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(enabledPeriods);
compositeSequenceableLoaderFactory.create(
enabledPeriodsList,
Lists.transform(enabledPeriodsList, period -> period.getTrackGroups().getTrackTypes()));
return positionUs;
}

View File

@ -25,6 +25,7 @@ import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.List;
/**
@ -90,6 +91,11 @@ public final class TrackGroupArray implements Bundleable {
return length == 0;
}
/** Returns the {@link TrackGroup#type} of each track group in this array. */
public ImmutableList<@C.TrackType Integer> getTrackTypes() {
return ImmutableList.copyOf(Lists.transform(trackGroups, t -> t.type));
}
@Override
public int hashCode() {
if (hashCode == 0) {

View File

@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import androidx.media3.common.C;
import androidx.media3.exoplayer.LoadingInfo;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -38,7 +39,10 @@ public final class CompositeSequenceableLoaderTest {
FakeSequenceableLoader loader2 =
new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(1000);
}
@ -57,7 +61,12 @@ public final class CompositeSequenceableLoaderTest {
/* bufferedPositionUs */ C.TIME_END_OF_SOURCE,
/* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2, loader3),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO),
ImmutableList.of(C.TRACK_TYPE_VIDEO),
ImmutableList.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO)));
assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(1000);
}
@ -76,10 +85,73 @@ public final class CompositeSequenceableLoaderTest {
/* bufferedPositionUs */ C.TIME_END_OF_SOURCE,
/* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(C.TIME_END_OF_SOURCE);
}
/**
* Tests that {@link CompositeSequenceableLoader#getBufferedPositionUs()} returns the minimum
* buffered position of loaders with audio or video tracks (if at least one loader has tracks of
* these types).
*/
@Test
public void getBufferedPositionUs_prefersLoadersWithAudioAndVideoTracks() {
FakeSequenceableLoader loaderWithTextOnly =
new FakeSequenceableLoader(/* bufferedPositionUs= */ 999, /* nextLoadPositionUs= */ 2000);
FakeSequenceableLoader loaderWithAudioVideoAndText =
new FakeSequenceableLoader(/* bufferedPositionUs= */ 1000, /* nextLoadPositionUs= */ 2000);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(
ImmutableList.of(loaderWithTextOnly, loaderWithAudioVideoAndText),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_TEXT),
ImmutableList.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO, C.TRACK_TYPE_TEXT)));
assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(1000);
}
/**
* Tests that {@link CompositeSequenceableLoader#getBufferedPositionUs()} returns the minimum
* buffered position of loaders with audio or video tracks (if at least one loader has tracks of
* these types).
*/
@Test
public void getBufferedPositionUs_prefersLoadersWithAudioAndVideoTracks_endOfSource() {
FakeSequenceableLoader loaderWithTextOnly =
new FakeSequenceableLoader(/* bufferedPositionUs= */ 999, /* nextLoadPositionUs= */ 2000);
FakeSequenceableLoader loaderWithAudioVideoAndText =
new FakeSequenceableLoader(
/* bufferedPositionUs */ C.TIME_END_OF_SOURCE, /* nextLoadPositionUs */
C.TIME_END_OF_SOURCE);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(
ImmutableList.of(loaderWithTextOnly, loaderWithAudioVideoAndText),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_TEXT),
ImmutableList.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO, C.TRACK_TYPE_TEXT)));
assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(C.TIME_END_OF_SOURCE);
}
/**
* Tests that {@link CompositeSequenceableLoader#getBufferedPositionUs()} returns the minimum
* buffered position of all loaders if no loader has audio or video tracks.
*/
@Test
public void getBufferedPositionUs_considersAllTracksIfNoneAreAudioOrVideo() {
FakeSequenceableLoader loaderWithTextOnly =
new FakeSequenceableLoader(/* bufferedPositionUs= */ 999, /* nextLoadPositionUs= */ 2000);
FakeSequenceableLoader loaderWithMetadataOnly =
new FakeSequenceableLoader(/* bufferedPositionUs= */ 1000, /* nextLoadPositionUs= */ 2000);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(
ImmutableList.of(loaderWithTextOnly, loaderWithMetadataOnly),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_TEXT), ImmutableList.of(C.TRACK_TYPE_METADATA)));
assertThat(compositeSequenceableLoader.getBufferedPositionUs()).isEqualTo(999);
}
/**
* Tests that {@link CompositeSequenceableLoader#getNextLoadPositionUs()} returns minimum next
* load position among all sub-loaders.
@ -91,7 +163,10 @@ public final class CompositeSequenceableLoaderTest {
FakeSequenceableLoader loader2 =
new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2000);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
assertThat(compositeSequenceableLoader.getNextLoadPositionUs()).isEqualTo(2000);
}
@ -109,7 +184,12 @@ public final class CompositeSequenceableLoaderTest {
new FakeSequenceableLoader(
/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2, loader3),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO),
ImmutableList.of(C.TRACK_TYPE_VIDEO),
ImmutableList.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO)));
assertThat(compositeSequenceableLoader.getNextLoadPositionUs()).isEqualTo(2000);
}
@ -126,7 +206,10 @@ public final class CompositeSequenceableLoaderTest {
new FakeSequenceableLoader(
/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
assertThat(compositeSequenceableLoader.getNextLoadPositionUs()).isEqualTo(C.TIME_END_OF_SOURCE);
}
@ -142,7 +225,10 @@ public final class CompositeSequenceableLoaderTest {
FakeSequenceableLoader loader2 =
new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
compositeSequenceableLoader.continueLoading(
new LoadingInfo.Builder().setPlaybackPositionUs(100).build());
@ -163,7 +249,12 @@ public final class CompositeSequenceableLoaderTest {
FakeSequenceableLoader loader3 =
new FakeSequenceableLoader(/* bufferedPositionUs */ 1002, /* nextLoadPositionUs */ 2002);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2, loader3),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO),
ImmutableList.of(C.TRACK_TYPE_VIDEO),
ImmutableList.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO)));
compositeSequenceableLoader.continueLoading(
new LoadingInfo.Builder().setPlaybackPositionUs(3000).build());
@ -185,7 +276,10 @@ public final class CompositeSequenceableLoaderTest {
new FakeSequenceableLoader(
/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
compositeSequenceableLoader.continueLoading(
new LoadingInfo.Builder().setPlaybackPositionUs(3000).build());
@ -207,7 +301,10 @@ public final class CompositeSequenceableLoaderTest {
loader1.setNextChunkDurationUs(1000);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
assertThat(
compositeSequenceableLoader.continueLoading(
@ -230,7 +327,10 @@ public final class CompositeSequenceableLoaderTest {
loader2.setNextChunkDurationUs(1000);
CompositeSequenceableLoader compositeSequenceableLoader =
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
new CompositeSequenceableLoader(
ImmutableList.of(loader1, loader2),
ImmutableList.of(
ImmutableList.of(C.TRACK_TYPE_AUDIO), ImmutableList.of(C.TRACK_TYPE_VIDEO)));
assertThat(
compositeSequenceableLoader.continueLoading(

View File

@ -60,6 +60,7 @@ import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import androidx.media3.exoplayer.upstream.LoaderErrorThrower;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.primitives.Ints;
import java.io.IOException;
@ -154,8 +155,7 @@ import java.util.regex.Pattern;
sampleStreams = newSampleStreamArray(0);
eventSampleStreams = new EventSampleStream[0];
trackEmsgHandlerBySampleStream = new IdentityHashMap<>();
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams);
compositeSequenceableLoader = compositeSequenceableLoaderFactory.empty();
Period period = manifest.getPeriod(periodIndex);
eventStreams = period.eventStreams;
Pair<TrackGroupArray, TrackGroupInfo[]> result =
@ -304,7 +304,9 @@ import java.util.regex.Pattern;
eventSampleStreamList.toArray(eventSampleStreams);
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams);
compositeSequenceableLoaderFactory.create(
sampleStreamList,
Lists.transform(sampleStreamList, s -> ImmutableList.of(s.primaryTrackType)));
return positionUs;
}

View File

@ -52,6 +52,8 @@ import androidx.media3.exoplayer.upstream.CmcdConfiguration;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import androidx.media3.extractor.Extractor;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import java.io.IOException;
import java.util.ArrayList;
@ -160,8 +162,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.playerId = playerId;
this.timestampAdjusterInitializationTimeoutMs = timestampAdjusterInitializationTimeoutMs;
sampleStreamWrapperCallback = new SampleStreamWrapperCallback();
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader();
compositeSequenceableLoader = compositeSequenceableLoaderFactory.empty();
streamWrapperIndices = new IdentityHashMap<>();
timestampAdjusterProvider = new TimestampAdjusterProvider();
sampleStreamWrappers = new HlsSampleStreamWrapper[0];
@ -376,9 +377,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Update the local state.
enabledSampleStreamWrappers =
Util.nullSafeArrayCopy(newEnabledSampleStreamWrappers, newEnabledSampleStreamWrapperCount);
ImmutableList<HlsSampleStreamWrapper> enabledSampleStreamWrappersList =
ImmutableList.copyOf(enabledSampleStreamWrappers);
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(
enabledSampleStreamWrappers);
compositeSequenceableLoaderFactory.create(
enabledSampleStreamWrappersList,
Lists.transform(
enabledSampleStreamWrappersList,
sampleStreamWrapper -> sampleStreamWrapper.getTrackGroups().getTrackTypes()));
return positionUs;
}

View File

@ -43,6 +43,8 @@ import androidx.media3.exoplayer.upstream.CmcdConfiguration;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import androidx.media3.exoplayer.upstream.LoaderErrorThrower;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -94,8 +96,7 @@ import java.util.List;
this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory;
trackGroups = buildTrackGroups(manifest, drmSessionManager, subtitleParserFactory);
sampleStreams = newSampleStreamArray(0);
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams);
compositeSequenceableLoader = compositeSequenceableLoaderFactory.empty();
}
public void updateManifest(SsManifest manifest) {
@ -161,7 +162,9 @@ import java.util.List;
sampleStreams = newSampleStreamArray(sampleStreamsList.size());
sampleStreamsList.toArray(sampleStreams);
compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams);
compositeSequenceableLoaderFactory.create(
sampleStreamsList,
Lists.transform(sampleStreamsList, s -> ImmutableList.of(s.primaryTrackType)));
return positionUs;
}

View File

@ -44,7 +44,9 @@ import androidx.media3.exoplayer.source.chunk.ChunkSampleStream;
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
import androidx.media3.exoplayer.upstream.Allocator;
import androidx.media3.exoplayer.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -86,7 +88,9 @@ public class FakeAdaptiveMediaPeriod
this.durationUs = durationUs;
this.transferListener = transferListener;
sampleStreams = new ArrayList<>();
sequenceableLoader = new CompositeSequenceableLoader(new SequenceableLoader[0]);
sequenceableLoader =
new CompositeSequenceableLoader(
/* loaders= */ ImmutableList.of(), /* loaderTrackTypes= */ ImmutableList.of());
fakePreparationLoadTaskId = LoadEventInfo.getNewId();
}
@ -97,7 +101,9 @@ public class FakeAdaptiveMediaPeriod
sampleStream.release();
}
sampleStreams.clear();
sequenceableLoader = new CompositeSequenceableLoader(new SequenceableLoader[0]);
sequenceableLoader =
new CompositeSequenceableLoader(
/* loaders= */ ImmutableList.of(), /* loaderTrackTypes= */ ImmutableList.of());
}
@Override
@ -143,7 +149,7 @@ public class FakeAdaptiveMediaPeriod
return trackGroupArray;
}
@SuppressWarnings({"unchecked", "rawtypes"}) // Casting sample streams created by this class.
@SuppressWarnings({"unchecked"}) // Casting sample streams created by this class.
@Override
public long selectTracks(
@NullableType ExoTrackSelection[] selections,
@ -188,7 +194,9 @@ public class FakeAdaptiveMediaPeriod
}
}
sequenceableLoader =
new CompositeSequenceableLoader(sampleStreams.toArray(new ChunkSampleStream[0]));
new CompositeSequenceableLoader(
sampleStreams,
Lists.transform(sampleStreams, s -> ImmutableList.of(s.primaryTrackType)));
return seekToUs(positionUs);
}