Skip to content

Commit

Permalink
Rollback of 406c0a1
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 605015994
(cherry picked from commit 3a7a665)
  • Loading branch information
icbaker authored and SheenaChhabra committed Feb 8, 2024
1 parent 1dc4377 commit dbb99fe
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -94,7 +95,7 @@ public void subtitlesRespectClipping_singlePeriod() throws Exception {
player.get().addListener(textCapturer);
player.get().setMediaItem(mediaItem);
player.get().prepare();
player.get().play();
playWhenLoadingIsDone(player.get());
});

textCapturer.block();
Expand Down Expand Up @@ -146,6 +147,9 @@ public void subtitlesRespectClipping_multiplePeriods() throws Exception {
player.get().addListener(textCapturer);
player.get().setMediaItems(mediaItems);
player.get().prepare();
// We don't need playWhenLoadingIsDone here because playback already waits at the end
// of the first period for subtitles to be fully loaded beforetransitioning to the
// second period.
player.get().play();
});

Expand All @@ -157,6 +161,21 @@ public void subtitlesRespectClipping_multiplePeriods() throws Exception {
.isEqualTo("This is the first subtitle.");
}

private static void playWhenLoadingIsDone(Player player) {
AtomicBoolean loadingStarted = new AtomicBoolean(false);
player.addListener(
new Player.Listener() {
@Override
public void onEvents(Player player, Player.Events events) {
if (events.contains(Player.EVENT_IS_LOADING_CHANGED)
&& loadingStarted.getAndSet(player.isLoading())
&& !player.isLoading()) {
player.play();
}
}
});
}

private static class TextCapturingPlaybackListener implements Player.Listener {

private final ConditionVariable playbackEnded;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,88 @@
*/
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;
private long lastAudioVideoBufferedPositionUs;

/**
* @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();
this.lastAudioVideoBufferedPositionUs = C.TIME_UNSET;
}

@Override
public long getBufferedPositionUs() {
long bufferedPositionUs = Long.MAX_VALUE;
for (SequenceableLoader loader : loaders) {
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)
|| loader.getTrackTypes().contains(C.TRACK_TYPE_IMAGE)) {
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 (bufferedPositionAudioVideoUs != Long.MAX_VALUE) {
lastAudioVideoBufferedPositionUs = bufferedPositionAudioVideoUs;
return bufferedPositionAudioVideoUs;
} else if (bufferedPositionUs != Long.MAX_VALUE) {
// If lastAudioVideoBufferedPositionUs != C.TIME_UNSET, then we know there's at least one a/v
// track (because this is the only time we end up assigning lastAudioVideoBufferedPositionUs
// on a previous invocation).
return lastAudioVideoBufferedPositionUs != C.TIME_UNSET
? lastAudioVideoBufferedPositionUs
: bufferedPositionUs;
} else {
return C.TIME_END_OF_SOURCE;
}
}

@Override
public long getNextLoadPositionUs() {
long nextLoadPositionUs = Long.MAX_VALUE;
for (SequenceableLoader loader : loaders) {
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
SequenceableLoaderWithTrackTypes loader = loadersWithTrackTypes.get(i);
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
if (loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE) {
nextLoadPositionUs = min(nextLoadPositionUs, loaderNextLoadPositionUs);
Expand All @@ -57,8 +107,8 @@ public long getNextLoadPositionUs() {

@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);
}
}

Expand All @@ -72,13 +122,13 @@ public boolean continueLoading(LoadingInfo loadingInfo) {
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;
Expand All @@ -88,11 +138,54 @@ public boolean continueLoading(LoadingInfo loadingInfo) {

@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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,32 @@
*/
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
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
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;
Expand Down Expand Up @@ -58,8 +59,7 @@ public MergingMediaPeriod(
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++) {
Expand Down Expand Up @@ -172,7 +172,9 @@ public long selectTracks(
// 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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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;

/**
Expand Down Expand Up @@ -90,6 +91,11 @@ public boolean isEmpty() {
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) {
Expand Down
Loading

0 comments on commit dbb99fe

Please sign in to comment.