Skip to content

Commit 461829d

Browse files
ychaparovcopybara-github
authored andcommitted
Allow setting a LoadControl on CompositionPlayer
PiperOrigin-RevId: 795460388
1 parent 1430c59 commit 461829d

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

libraries/transformer/src/main/java/androidx/media3/transformer/CompositionPlayer.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@
6161
import androidx.media3.effect.DefaultVideoFrameProcessor;
6262
import androidx.media3.effect.SingleInputVideoGraph;
6363
import androidx.media3.effect.TimestampAdjustment;
64+
import androidx.media3.exoplayer.DefaultLoadControl;
6465
import androidx.media3.exoplayer.ExoPlayer;
66+
import androidx.media3.exoplayer.LoadControl;
6567
import androidx.media3.exoplayer.RendererCapabilities;
6668
import androidx.media3.exoplayer.RendererCapabilities.Capabilities;
6769
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
@@ -130,6 +132,7 @@ public static final class Builder {
130132
private VideoGraph.@MonotonicNonNull Factory videoGraphFactory;
131133

132134
private @MonotonicNonNull GlObjectsProvider glObjectsProvider;
135+
private LoadControl loadControl;
133136
private boolean enableReplayableCache;
134137
private long lateThresholdToDropInputUs;
135138
private boolean built;
@@ -148,6 +151,7 @@ public Builder(Context context) {
148151
.setMaxOutputSize(GlUtil.MAX_BITMAP_DECODING_SIZE);
149152
videoPrewarmingEnabled = true;
150153
lateThresholdToDropInputUs = LATE_US_TO_DROP_INPUT_FRAME;
154+
loadControl = new DefaultLoadControl();
151155
clock = Clock.DEFAULT;
152156
}
153157

@@ -290,6 +294,21 @@ public Builder setGlObjectsProvider(GlObjectsProvider glObjectsProvider) {
290294
return this;
291295
}
292296

297+
/**
298+
* Sets the {@link LoadControl} that will be used by the player to control buffering of all
299+
* {@linkplain EditedMediaItem#mediaItem media items} in a {@link Composition}.
300+
*
301+
* <p>By default, a {@link DefaultLoadControl} is used.
302+
*
303+
* @param loadControl A {@link LoadControl}.
304+
* @return This builder, for convenience.
305+
*/
306+
@CanIgnoreReturnValue
307+
public Builder setLoadControl(LoadControl loadControl) {
308+
this.loadControl = loadControl;
309+
return this;
310+
}
311+
293312
/**
294313
* Sets whether to enable replayable cache.
295314
*
@@ -402,6 +421,7 @@ public CompositionPlayer build() {
402421
private final VideoGraph.Factory videoGraphFactory;
403422
private final boolean videoPrewarmingEnabled;
404423
private final HandlerWrapper compositionInternalListenerHandler;
424+
private final LoadControl loadControl;
405425
private final boolean enableReplayableCache;
406426
private final long lateThresholdToDropInputUs;
407427

@@ -454,6 +474,7 @@ private CompositionPlayer(Builder builder) {
454474
videoGraphFactory = checkNotNull(builder.videoGraphFactory);
455475
videoPrewarmingEnabled = builder.videoPrewarmingEnabled;
456476
compositionInternalListenerHandler = clock.createHandler(builder.looper, /* callback= */ null);
477+
loadControl = builder.loadControl;
457478
this.enableReplayableCache = builder.enableReplayableCache;
458479
lateThresholdToDropInputUs = builder.lateThresholdToDropInputUs;
459480
videoTracksSelected = new SparseBooleanArray();
@@ -1477,6 +1498,7 @@ private SequencePlayerHolder(
14771498
.setPlaybackLooper(playbackLooper)
14781499
.setRenderersFactory(renderersFactory)
14791500
.setHandleAudioBecomingNoisy(true)
1501+
.setLoadControl(loadControl)
14801502
.setClock(clock)
14811503
// Use dynamic scheduling to show the first video/image frame more promptly when the
14821504
// player is paused (which is common in editing applications).

libraries/transformer/src/test/java/androidx/media3/transformer/CompositionPlayerTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
import androidx.media3.common.util.ConditionVariable;
4949
import androidx.media3.common.util.Log;
5050
import androidx.media3.common.util.NullableType;
51+
import androidx.media3.exoplayer.DefaultLoadControl;
52+
import androidx.media3.exoplayer.analytics.PlayerId;
5153
import androidx.media3.exoplayer.audio.AudioSink;
5254
import androidx.media3.exoplayer.audio.DefaultAudioSink;
5355
import androidx.media3.exoplayer.audio.ForwardingAudioSink;
@@ -946,6 +948,22 @@ public void setScrubbingModeEnabled_updatesPlaybackSuppressionReason() throws Ti
946948
.isEqualTo(PLAYBACK_SUPPRESSION_REASON_SCRUBBING);
947949
}
948950

951+
@Test
952+
public void prepare_withCustomLoadControl_preparesTheLoadControl() throws Exception {
953+
CustomLoadControl customLoadControl = new CustomLoadControl();
954+
CompositionPlayer.Builder playerBuilder = createCompositionPlayerBuilder();
955+
playerBuilder.setLoadControl(customLoadControl);
956+
CompositionPlayer player = playerBuilder.build();
957+
958+
player.setComposition(buildComposition());
959+
player.prepare();
960+
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
961+
962+
assertThat(customLoadControl.prepared).isTrue();
963+
964+
player.release();
965+
}
966+
949967
private static CompositionPlayer buildCompositionPlayer() {
950968
return createCompositionPlayerBuilder().build();
951969
}
@@ -970,4 +988,14 @@ private static Composition buildComposition() {
970988
new EditedMediaItemSequence.Builder(editedMediaItem1, editedMediaItem2).build();
971989
return new Composition.Builder(sequence).build();
972990
}
991+
992+
private static final class CustomLoadControl extends DefaultLoadControl {
993+
public boolean prepared;
994+
995+
@Override
996+
public void onPrepared(PlayerId playerId) {
997+
prepared = true;
998+
super.onPrepared(playerId);
999+
}
1000+
}
9731001
}

0 commit comments

Comments
 (0)