1515 */
1616package androidx .media3 .exoplayer .source ;
1717
18+ import static androidx .media3 .common .util .Assertions .checkArgument ;
1819import static java .lang .Math .min ;
1920
2021import androidx .media3 .common .C ;
2122import androidx .media3 .common .util .UnstableApi ;
2223import 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
2630public 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}
0 commit comments