Skip to content

Commit 406c0a1

Browse files
icbakercopybara-github
authored andcommitted
CompositeSequenceableLoader: Prefer buffered position of A/V tracks
Preferring audio and video tracks matches logic we already have in [`ProgressiveMediaPeriod.getBufferedPositionUs`](https://github.com/androidx/media/blob/f6fe90f30ba022c7e04e14a3dc5c28c568a4d1e2/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java#L403). PiperOrigin-RevId: 599154217
1 parent 80bfa81 commit 406c0a1

File tree

10 files changed

+286
-42
lines changed

10 files changed

+286
-42
lines changed

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/CompositeSequenceableLoader.java

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,80 @@
1515
*/
1616
package androidx.media3.exoplayer.source;
1717

18+
import static androidx.media3.common.util.Assertions.checkArgument;
1819
import static java.lang.Math.min;
1920

2021
import androidx.media3.common.C;
2122
import androidx.media3.common.util.UnstableApi;
2223
import androidx.media3.exoplayer.LoadingInfo;
24+
import com.google.common.collect.ImmutableList;
25+
import java.util.Collections;
26+
import java.util.List;
2327

2428
/** A {@link SequenceableLoader} that encapsulates multiple other {@link SequenceableLoader}s. */
2529
@UnstableApi
2630
public final class CompositeSequenceableLoader implements SequenceableLoader {
2731

28-
private final SequenceableLoader[] loaders;
32+
private final ImmutableList<SequenceableLoaderWithTrackTypes> loadersWithTrackTypes;
2933

34+
/**
35+
* @deprecated Use {@link CompositeSequenceableLoader#CompositeSequenceableLoader(List, List)}
36+
* instead.
37+
*/
38+
@Deprecated
3039
public CompositeSequenceableLoader(SequenceableLoader[] loaders) {
31-
this.loaders = loaders;
40+
this(
41+
ImmutableList.copyOf(loaders),
42+
Collections.nCopies(loaders.length, ImmutableList.of(C.TRACK_TYPE_UNKNOWN)));
43+
}
44+
45+
public CompositeSequenceableLoader(
46+
List<? extends SequenceableLoader> loaders,
47+
List<List<@C.TrackType Integer>> loaderTrackTypes) {
48+
ImmutableList.Builder<SequenceableLoaderWithTrackTypes> loaderAndTrackTypes =
49+
ImmutableList.builder();
50+
checkArgument(loaders.size() == loaderTrackTypes.size());
51+
for (int i = 0; i < loaders.size(); i++) {
52+
loaderAndTrackTypes.add(
53+
new SequenceableLoaderWithTrackTypes(loaders.get(i), loaderTrackTypes.get(i)));
54+
}
55+
this.loadersWithTrackTypes = loaderAndTrackTypes.build();
3256
}
3357

3458
@Override
3559
public long getBufferedPositionUs() {
3660
long bufferedPositionUs = Long.MAX_VALUE;
37-
for (SequenceableLoader loader : loaders) {
61+
boolean hasAudioVideoTracks = false;
62+
long bufferedPositionAudioVideoUs = Long.MAX_VALUE;
63+
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
64+
SequenceableLoaderWithTrackTypes loader = loadersWithTrackTypes.get(i);
3865
long loaderBufferedPositionUs = loader.getBufferedPositionUs();
66+
if (loader.getTrackTypes().contains(C.TRACK_TYPE_AUDIO)
67+
|| loader.getTrackTypes().contains(C.TRACK_TYPE_VIDEO)) {
68+
hasAudioVideoTracks = true;
69+
if (loaderBufferedPositionUs != C.TIME_END_OF_SOURCE) {
70+
bufferedPositionAudioVideoUs =
71+
min(bufferedPositionAudioVideoUs, loaderBufferedPositionUs);
72+
}
73+
}
3974
if (loaderBufferedPositionUs != C.TIME_END_OF_SOURCE) {
4075
bufferedPositionUs = min(bufferedPositionUs, loaderBufferedPositionUs);
4176
}
4277
}
43-
return bufferedPositionUs == Long.MAX_VALUE ? C.TIME_END_OF_SOURCE : bufferedPositionUs;
78+
if (hasAudioVideoTracks) {
79+
return bufferedPositionAudioVideoUs != Long.MAX_VALUE
80+
? bufferedPositionAudioVideoUs
81+
: C.TIME_END_OF_SOURCE;
82+
} else {
83+
return bufferedPositionUs != Long.MAX_VALUE ? bufferedPositionUs : C.TIME_END_OF_SOURCE;
84+
}
4485
}
4586

4687
@Override
4788
public long getNextLoadPositionUs() {
4889
long nextLoadPositionUs = Long.MAX_VALUE;
49-
for (SequenceableLoader loader : loaders) {
50-
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
90+
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
91+
long loaderNextLoadPositionUs = loadersWithTrackTypes.get(i).getNextLoadPositionUs();
5192
if (loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE) {
5293
nextLoadPositionUs = min(nextLoadPositionUs, loaderNextLoadPositionUs);
5394
}
@@ -57,8 +98,8 @@ public long getNextLoadPositionUs() {
5798

5899
@Override
59100
public void reevaluateBuffer(long positionUs) {
60-
for (SequenceableLoader loader : loaders) {
61-
loader.reevaluateBuffer(positionUs);
101+
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
102+
loadersWithTrackTypes.get(i).reevaluateBuffer(positionUs);
62103
}
63104
}
64105

@@ -72,13 +113,13 @@ public boolean continueLoading(LoadingInfo loadingInfo) {
72113
if (nextLoadPositionUs == C.TIME_END_OF_SOURCE) {
73114
break;
74115
}
75-
for (SequenceableLoader loader : loaders) {
76-
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
116+
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
117+
long loaderNextLoadPositionUs = loadersWithTrackTypes.get(i).getNextLoadPositionUs();
77118
boolean isLoaderBehind =
78119
loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE
79120
&& loaderNextLoadPositionUs <= loadingInfo.playbackPositionUs;
80121
if (loaderNextLoadPositionUs == nextLoadPositionUs || isLoaderBehind) {
81-
madeProgressThisIteration |= loader.continueLoading(loadingInfo);
122+
madeProgressThisIteration |= loadersWithTrackTypes.get(i).continueLoading(loadingInfo);
82123
}
83124
}
84125
madeProgress |= madeProgressThisIteration;
@@ -88,11 +129,54 @@ public boolean continueLoading(LoadingInfo loadingInfo) {
88129

89130
@Override
90131
public boolean isLoading() {
91-
for (SequenceableLoader loader : loaders) {
92-
if (loader.isLoading()) {
132+
for (int i = 0; i < loadersWithTrackTypes.size(); i++) {
133+
if (loadersWithTrackTypes.get(i).isLoading()) {
93134
return true;
94135
}
95136
}
96137
return false;
97138
}
139+
140+
private static final class SequenceableLoaderWithTrackTypes implements SequenceableLoader {
141+
142+
private final SequenceableLoader loader;
143+
private final ImmutableList<@C.TrackType Integer> trackTypes;
144+
145+
public SequenceableLoaderWithTrackTypes(
146+
SequenceableLoader loader, List<@C.TrackType Integer> trackTypes) {
147+
this.loader = loader;
148+
this.trackTypes = ImmutableList.copyOf(trackTypes);
149+
}
150+
151+
public ImmutableList<@C.TrackType Integer> getTrackTypes() {
152+
return trackTypes;
153+
}
154+
155+
// SequenceableLoader implementation
156+
157+
@Override
158+
public long getBufferedPositionUs() {
159+
return loader.getBufferedPositionUs();
160+
}
161+
162+
@Override
163+
public long getNextLoadPositionUs() {
164+
return loader.getNextLoadPositionUs();
165+
}
166+
167+
@Override
168+
public boolean continueLoading(LoadingInfo loadingInfo) {
169+
return loader.continueLoading(loadingInfo);
170+
}
171+
172+
@Override
173+
public boolean isLoading() {
174+
return loader.isLoading();
175+
}
176+
177+
@Override
178+
public void reevaluateBuffer(long positionUs) {
179+
loader.reevaluateBuffer(positionUs);
180+
}
181+
}
98182
}

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/CompositeSequenceableLoaderFactory.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,33 @@
1515
*/
1616
package androidx.media3.exoplayer.source;
1717

18+
import androidx.media3.common.C;
1819
import androidx.media3.common.util.UnstableApi;
20+
import java.util.List;
1921

2022
/** A factory to create composite {@link SequenceableLoader}s. */
2123
@UnstableApi
2224
public interface CompositeSequenceableLoaderFactory {
2325

26+
/** Returns an empty composite {@link SequenceableLoader}, with no delegate loaders. */
27+
SequenceableLoader empty();
28+
29+
/**
30+
* @deprecated Use {@link #empty()} for an empty composite loader, or {@link #create(List, List)}
31+
* for a non-empty one.
32+
*/
33+
@Deprecated
34+
SequenceableLoader createCompositeSequenceableLoader(SequenceableLoader... loaders);
35+
2436
/**
2537
* Creates a composite {@link SequenceableLoader}.
2638
*
2739
* @param loaders The sub-loaders that make up the {@link SequenceableLoader} to be built.
40+
* @param loaderTrackTypes The track types handled by each entry in {@code loaders}. Must be the
41+
* same as {@code loaders}.
2842
* @return A composite {@link SequenceableLoader} that comprises the given loaders.
2943
*/
30-
SequenceableLoader createCompositeSequenceableLoader(SequenceableLoader... loaders);
44+
SequenceableLoader create(
45+
List<? extends SequenceableLoader> loaders,
46+
List<List<@C.TrackType Integer>> loaderTrackTypes);
3147
}

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/DefaultCompositeSequenceableLoaderFactory.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,32 @@
1515
*/
1616
package androidx.media3.exoplayer.source;
1717

18+
import androidx.media3.common.C;
1819
import androidx.media3.common.util.UnstableApi;
20+
import com.google.common.collect.ImmutableList;
21+
import java.util.List;
1922

2023
/** Default implementation of {@link CompositeSequenceableLoaderFactory}. */
2124
@UnstableApi
2225
public final class DefaultCompositeSequenceableLoaderFactory
2326
implements CompositeSequenceableLoaderFactory {
2427

2528
@Override
29+
public SequenceableLoader empty() {
30+
return new CompositeSequenceableLoader(ImmutableList.of(), ImmutableList.of());
31+
}
32+
33+
@Deprecated
34+
@Override
35+
@SuppressWarnings("deprecation") // Calling deprecated constructor
2636
public SequenceableLoader createCompositeSequenceableLoader(SequenceableLoader... loaders) {
2737
return new CompositeSequenceableLoader(loaders);
2838
}
39+
40+
@Override
41+
public SequenceableLoader create(
42+
List<? extends SequenceableLoader> loaders,
43+
List<List<@C.TrackType Integer>> loaderTrackTypes) {
44+
return new CompositeSequenceableLoader(loaders, loaderTrackTypes);
45+
}
2946
}

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/MergingMediaPeriod.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import androidx.media3.exoplayer.source.chunk.MediaChunk;
3030
import androidx.media3.exoplayer.source.chunk.MediaChunkIterator;
3131
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
32+
import com.google.common.collect.Lists;
3233
import java.io.IOException;
3334
import java.util.ArrayList;
3435
import java.util.Collections;
@@ -58,8 +59,7 @@ public MergingMediaPeriod(
5859
this.periods = periods;
5960
childrenPendingPreparation = new ArrayList<>();
6061
childTrackGroupByMergedTrackGroup = new HashMap<>();
61-
compositeSequenceableLoader =
62-
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader();
62+
compositeSequenceableLoader = compositeSequenceableLoaderFactory.empty();
6363
streamPeriodIndices = new IdentityHashMap<>();
6464
enabledPeriods = new MediaPeriod[0];
6565
for (int i = 0; i < periods.length; i++) {
@@ -172,7 +172,9 @@ public long selectTracks(
172172
// Update the local state.
173173
enabledPeriods = enabledPeriodsList.toArray(new MediaPeriod[0]);
174174
compositeSequenceableLoader =
175-
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(enabledPeriods);
175+
compositeSequenceableLoaderFactory.create(
176+
enabledPeriodsList,
177+
Lists.transform(enabledPeriodsList, period -> period.getTrackGroups().getTrackTypes()));
176178
return positionUs;
177179
}
178180

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/TrackGroupArray.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import androidx.media3.common.util.UnstableApi;
2626
import androidx.media3.common.util.Util;
2727
import com.google.common.collect.ImmutableList;
28+
import com.google.common.collect.Lists;
2829
import java.util.List;
2930

3031
/**
@@ -90,6 +91,11 @@ public boolean isEmpty() {
9091
return length == 0;
9192
}
9293

94+
/** Returns the {@link TrackGroup#type} of each track group in this array. */
95+
public ImmutableList<@C.TrackType Integer> getTrackTypes() {
96+
return ImmutableList.copyOf(Lists.transform(trackGroups, t -> t.type));
97+
}
98+
9399
@Override
94100
public int hashCode() {
95101
if (hashCode == 0) {

0 commit comments

Comments
 (0)