15
15
*/
16
16
package androidx .media3 .exoplayer .source ;
17
17
18
+ import static androidx .media3 .common .util .Assertions .checkArgument ;
18
19
import static java .lang .Math .min ;
19
20
20
21
import androidx .media3 .common .C ;
21
22
import androidx .media3 .common .util .UnstableApi ;
22
23
import androidx .media3 .exoplayer .LoadingInfo ;
24
+ import com .google .common .collect .ImmutableList ;
25
+ import java .util .Collections ;
26
+ import java .util .List ;
23
27
24
28
/** A {@link SequenceableLoader} that encapsulates multiple other {@link SequenceableLoader}s. */
25
29
@ UnstableApi
26
30
public final class CompositeSequenceableLoader implements SequenceableLoader {
27
31
28
- private final SequenceableLoader [] loaders ;
32
+ private final ImmutableList <SequenceableLoaderWithTrackTypes > loadersWithTrackTypes ;
33
+ private long lastAudioVideoBufferedPositionUs ;
29
34
35
+ /**
36
+ * @deprecated Use {@link CompositeSequenceableLoader#CompositeSequenceableLoader(List, List)}
37
+ * instead.
38
+ */
39
+ @ Deprecated
30
40
public CompositeSequenceableLoader (SequenceableLoader [] loaders ) {
31
- this .loaders = loaders ;
41
+ this (
42
+ ImmutableList .copyOf (loaders ),
43
+ Collections .nCopies (loaders .length , ImmutableList .of (C .TRACK_TYPE_UNKNOWN )));
44
+ }
45
+
46
+ public CompositeSequenceableLoader (
47
+ List <? extends SequenceableLoader > loaders ,
48
+ List <List <@ C .TrackType Integer >> loaderTrackTypes ) {
49
+ ImmutableList .Builder <SequenceableLoaderWithTrackTypes > loaderAndTrackTypes =
50
+ ImmutableList .builder ();
51
+ checkArgument (loaders .size () == loaderTrackTypes .size ());
52
+ for (int i = 0 ; i < loaders .size (); i ++) {
53
+ loaderAndTrackTypes .add (
54
+ new SequenceableLoaderWithTrackTypes (loaders .get (i ), loaderTrackTypes .get (i )));
55
+ }
56
+ this .loadersWithTrackTypes = loaderAndTrackTypes .build ();
57
+ this .lastAudioVideoBufferedPositionUs = C .TIME_UNSET ;
32
58
}
33
59
34
60
@ Override
35
61
public long getBufferedPositionUs () {
36
62
long bufferedPositionUs = Long .MAX_VALUE ;
37
- for (SequenceableLoader loader : loaders ) {
63
+ long bufferedPositionAudioVideoUs = Long .MAX_VALUE ;
64
+ for (int i = 0 ; i < loadersWithTrackTypes .size (); i ++) {
65
+ SequenceableLoaderWithTrackTypes loader = loadersWithTrackTypes .get (i );
38
66
long loaderBufferedPositionUs = loader .getBufferedPositionUs ();
67
+
68
+ if (loader .getTrackTypes ().contains (C .TRACK_TYPE_AUDIO )
69
+ || loader .getTrackTypes ().contains (C .TRACK_TYPE_VIDEO )
70
+ || loader .getTrackTypes ().contains (C .TRACK_TYPE_IMAGE )) {
71
+ if (loaderBufferedPositionUs != C .TIME_END_OF_SOURCE ) {
72
+ bufferedPositionAudioVideoUs =
73
+ min (bufferedPositionAudioVideoUs , loaderBufferedPositionUs );
74
+ }
75
+ }
39
76
if (loaderBufferedPositionUs != C .TIME_END_OF_SOURCE ) {
40
77
bufferedPositionUs = min (bufferedPositionUs , loaderBufferedPositionUs );
41
78
}
42
79
}
43
- return bufferedPositionUs == Long .MAX_VALUE ? C .TIME_END_OF_SOURCE : bufferedPositionUs ;
80
+ if (bufferedPositionAudioVideoUs != Long .MAX_VALUE ) {
81
+ lastAudioVideoBufferedPositionUs = bufferedPositionAudioVideoUs ;
82
+ return bufferedPositionAudioVideoUs ;
83
+ } else if (bufferedPositionUs != Long .MAX_VALUE ) {
84
+ // If lastAudioVideoBufferedPositionUs != C.TIME_UNSET, then we know there's at least one a/v
85
+ // track (because this is the only time we end up assigning lastAudioVideoBufferedPositionUs
86
+ // on a previous invocation).
87
+ return lastAudioVideoBufferedPositionUs != C .TIME_UNSET
88
+ ? lastAudioVideoBufferedPositionUs
89
+ : bufferedPositionUs ;
90
+ } else {
91
+ return C .TIME_END_OF_SOURCE ;
92
+ }
44
93
}
45
94
46
95
@ Override
47
96
public long getNextLoadPositionUs () {
48
97
long nextLoadPositionUs = Long .MAX_VALUE ;
49
- for (SequenceableLoader loader : loaders ) {
98
+ for (int i = 0 ; i < loadersWithTrackTypes .size (); i ++) {
99
+ SequenceableLoaderWithTrackTypes loader = loadersWithTrackTypes .get (i );
50
100
long loaderNextLoadPositionUs = loader .getNextLoadPositionUs ();
51
101
if (loaderNextLoadPositionUs != C .TIME_END_OF_SOURCE ) {
52
102
nextLoadPositionUs = min (nextLoadPositionUs , loaderNextLoadPositionUs );
@@ -57,8 +107,8 @@ public long getNextLoadPositionUs() {
57
107
58
108
@ Override
59
109
public void reevaluateBuffer (long positionUs ) {
60
- for (SequenceableLoader loader : loaders ) {
61
- loader .reevaluateBuffer (positionUs );
110
+ for (int i = 0 ; i < loadersWithTrackTypes . size (); i ++ ) {
111
+ loadersWithTrackTypes . get ( i ) .reevaluateBuffer (positionUs );
62
112
}
63
113
}
64
114
@@ -72,13 +122,13 @@ public boolean continueLoading(LoadingInfo loadingInfo) {
72
122
if (nextLoadPositionUs == C .TIME_END_OF_SOURCE ) {
73
123
break ;
74
124
}
75
- for (SequenceableLoader loader : loaders ) {
76
- long loaderNextLoadPositionUs = loader .getNextLoadPositionUs ();
125
+ for (int i = 0 ; i < loadersWithTrackTypes . size (); i ++ ) {
126
+ long loaderNextLoadPositionUs = loadersWithTrackTypes . get ( i ) .getNextLoadPositionUs ();
77
127
boolean isLoaderBehind =
78
128
loaderNextLoadPositionUs != C .TIME_END_OF_SOURCE
79
129
&& loaderNextLoadPositionUs <= loadingInfo .playbackPositionUs ;
80
130
if (loaderNextLoadPositionUs == nextLoadPositionUs || isLoaderBehind ) {
81
- madeProgressThisIteration |= loader .continueLoading (loadingInfo );
131
+ madeProgressThisIteration |= loadersWithTrackTypes . get ( i ) .continueLoading (loadingInfo );
82
132
}
83
133
}
84
134
madeProgress |= madeProgressThisIteration ;
@@ -88,11 +138,54 @@ public boolean continueLoading(LoadingInfo loadingInfo) {
88
138
89
139
@ Override
90
140
public boolean isLoading () {
91
- for (SequenceableLoader loader : loaders ) {
92
- if (loader .isLoading ()) {
141
+ for (int i = 0 ; i < loadersWithTrackTypes . size (); i ++ ) {
142
+ if (loadersWithTrackTypes . get ( i ) .isLoading ()) {
93
143
return true ;
94
144
}
95
145
}
96
146
return false ;
97
147
}
148
+
149
+ private static final class SequenceableLoaderWithTrackTypes implements SequenceableLoader {
150
+
151
+ private final SequenceableLoader loader ;
152
+ private final ImmutableList <@ C .TrackType Integer > trackTypes ;
153
+
154
+ public SequenceableLoaderWithTrackTypes (
155
+ SequenceableLoader loader , List <@ C .TrackType Integer > trackTypes ) {
156
+ this .loader = loader ;
157
+ this .trackTypes = ImmutableList .copyOf (trackTypes );
158
+ }
159
+
160
+ public ImmutableList <@ C .TrackType Integer > getTrackTypes () {
161
+ return trackTypes ;
162
+ }
163
+
164
+ // SequenceableLoader implementation
165
+
166
+ @ Override
167
+ public long getBufferedPositionUs () {
168
+ return loader .getBufferedPositionUs ();
169
+ }
170
+
171
+ @ Override
172
+ public long getNextLoadPositionUs () {
173
+ return loader .getNextLoadPositionUs ();
174
+ }
175
+
176
+ @ Override
177
+ public boolean continueLoading (LoadingInfo loadingInfo ) {
178
+ return loader .continueLoading (loadingInfo );
179
+ }
180
+
181
+ @ Override
182
+ public boolean isLoading () {
183
+ return loader .isLoading ();
184
+ }
185
+
186
+ @ Override
187
+ public void reevaluateBuffer (long positionUs ) {
188
+ loader .reevaluateBuffer (positionUs );
189
+ }
190
+ }
98
191
}
0 commit comments