mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add ClippingMediaSource.Builder
This prevents complicated constructor changes when we add new options. PiperOrigin-RevId: 721415339
This commit is contained in:
parent
344214d711
commit
df575a8d19
@ -15,7 +15,10 @@
|
||||
*/
|
||||
package androidx.media3.exoplayer.source;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static androidx.media3.common.util.Util.msToUs;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
@ -29,6 +32,7 @@ import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.exoplayer.upstream.Allocator;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -43,6 +47,161 @@ import java.util.ArrayList;
|
||||
@UnstableApi
|
||||
public final class ClippingMediaSource extends WrappingMediaSource {
|
||||
|
||||
/** A builder for {@link ClippingMediaSource}. */
|
||||
public static final class Builder {
|
||||
|
||||
private final MediaSource mediaSource;
|
||||
|
||||
private long startPositionUs;
|
||||
private long endPositionUs;
|
||||
private boolean enableInitialDiscontinuity;
|
||||
private boolean allowDynamicClippingUpdates;
|
||||
private boolean relativeToDefaultPosition;
|
||||
private boolean buildCalled;
|
||||
|
||||
/**
|
||||
* Creates the builder.
|
||||
*
|
||||
* @param mediaSource The {@link MediaSource} to clip.
|
||||
*/
|
||||
public Builder(MediaSource mediaSource) {
|
||||
this.mediaSource = checkNotNull(mediaSource);
|
||||
this.enableInitialDiscontinuity = true;
|
||||
this.endPositionUs = C.TIME_END_OF_SOURCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clip start position.
|
||||
*
|
||||
* <p>The start position is relative to the wrapped source's {@link Timeline.Window}, unless
|
||||
* {@link #setRelativeToDefaultPosition} is set to {@code true}.
|
||||
*
|
||||
* @param startPositionMs The clip start position in milliseconds.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setStartPositionMs(long startPositionMs) {
|
||||
return setStartPositionUs(msToUs(startPositionMs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clip start position.
|
||||
*
|
||||
* <p>The start position is relative to the wrapped source's {@link Timeline.Window}, unless
|
||||
* {@link #setRelativeToDefaultPosition} is set to {@code true}.
|
||||
*
|
||||
* @param startPositionUs The clip start position in microseconds.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setStartPositionUs(long startPositionUs) {
|
||||
checkArgument(startPositionUs >= 0);
|
||||
checkState(!buildCalled);
|
||||
this.startPositionUs = startPositionUs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clip end position.
|
||||
*
|
||||
* <p>The end position is relative to the wrapped source's {@link Timeline.Window}, unless
|
||||
* {@link #setRelativeToDefaultPosition} is set to {@code true}.
|
||||
*
|
||||
* <p>Specify {@link C#TIME_END_OF_SOURCE} to provide samples up to the end of the source.
|
||||
* Specifying a position that exceeds the wrapped source's duration will also result in the end
|
||||
* of the source not being clipped.
|
||||
*
|
||||
* @param endPositionMs The clip end position in milliseconds, or {@link C#TIME_END_OF_SOURCE}.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setEndPositionMs(long endPositionMs) {
|
||||
return setEndPositionUs(msToUs(endPositionMs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clip end position.
|
||||
*
|
||||
* <p>The end position is relative to the wrapped source's {@link Timeline.Window}, unless
|
||||
* {@link #setRelativeToDefaultPosition} is set to {@code true}.
|
||||
*
|
||||
* <p>Specify {@link C#TIME_END_OF_SOURCE} to provide samples up to the end of the source.
|
||||
* Specifying a position that exceeds the wrapped source's duration will also result in the end
|
||||
* of the source not being clipped.
|
||||
*
|
||||
* @param endPositionUs The clip end position in microseconds, or {@link C#TIME_END_OF_SOURCE}.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setEndPositionUs(long endPositionUs) {
|
||||
checkState(!buildCalled);
|
||||
this.endPositionUs = endPositionUs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable the initial discontinuity.
|
||||
*
|
||||
* <p>This discontinuity is needed to handle pre-rolling samples from a previous keyframe if the
|
||||
* start position doesn't fall onto a keyframe.
|
||||
*
|
||||
* <p>When starting from the beginning of the stream or when clipping a format that is
|
||||
* guaranteed to have keyframes only, the discontinuity won't be applied even if enabled.
|
||||
*
|
||||
* <p>The default value is {@code true}.
|
||||
*
|
||||
* @param enableInitialDiscontinuity Whether to enable the initial discontinuity.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setEnableInitialDiscontinuity(boolean enableInitialDiscontinuity) {
|
||||
checkState(!buildCalled);
|
||||
this.enableInitialDiscontinuity = enableInitialDiscontinuity;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the clipping of active media periods moves with a live window.
|
||||
*
|
||||
* <p>If {@code false}, playback ends when it reaches {@code endPositionUs} in the last reported
|
||||
* live window at the time a media period was created.
|
||||
*
|
||||
* <p>The default value is {@code false}.
|
||||
*
|
||||
* @param allowDynamicClippingUpdates Whether to allow dynamic clipping updates.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setAllowDynamicClippingUpdates(boolean allowDynamicClippingUpdates) {
|
||||
checkState(!buildCalled);
|
||||
this.allowDynamicClippingUpdates = allowDynamicClippingUpdates;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the start and end position are relative to the default position of the wrapped
|
||||
* source's {@link Timeline.Window}.
|
||||
*
|
||||
* <p>The default value is {@code false}.
|
||||
*
|
||||
* @param relativeToDefaultPosition Whether the start and end positions are relative to the
|
||||
* default position of the wrapped source's {@link Timeline.Window}.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setRelativeToDefaultPosition(boolean relativeToDefaultPosition) {
|
||||
checkState(!buildCalled);
|
||||
this.relativeToDefaultPosition = relativeToDefaultPosition;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds the {@link ClippingMediaSource}. */
|
||||
public ClippingMediaSource build() {
|
||||
buildCalled = true;
|
||||
return new ClippingMediaSource(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Thrown when a {@link ClippingMediaSource} cannot clip its wrapped source. */
|
||||
public static final class IllegalClippingException extends IOException {
|
||||
|
||||
@ -109,80 +268,28 @@ public final class ClippingMediaSource extends WrappingMediaSource {
|
||||
private long periodEndUs;
|
||||
|
||||
/**
|
||||
* Creates a new clipping source that wraps the specified source and provides samples between the
|
||||
* specified start and end position.
|
||||
*
|
||||
* @param mediaSource The single-period source to wrap.
|
||||
* @param startPositionUs The start position within {@code mediaSource}'s window at which to start
|
||||
* providing samples, in microseconds.
|
||||
* @param endPositionUs The end position within {@code mediaSource}'s window at which to stop
|
||||
* providing samples, in microseconds. Specify {@link C#TIME_END_OF_SOURCE} to provide samples
|
||||
* from the specified start point up to the end of the source. Specifying a position that
|
||||
* exceeds the {@code mediaSource}'s duration will also result in the end of the source not
|
||||
* being clipped.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ClippingMediaSource(MediaSource mediaSource, long startPositionUs, long endPositionUs) {
|
||||
this(
|
||||
mediaSource,
|
||||
startPositionUs,
|
||||
endPositionUs,
|
||||
/* enableInitialDiscontinuity= */ true,
|
||||
/* allowDynamicClippingUpdates= */ false,
|
||||
/* relativeToDefaultPosition= */ false);
|
||||
new Builder(mediaSource)
|
||||
.setStartPositionUs(startPositionUs)
|
||||
.setEndPositionUs(endPositionUs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new clipping source that wraps the specified source and provides samples from the
|
||||
* default position for the specified duration.
|
||||
*
|
||||
* @param mediaSource The single-period source to wrap.
|
||||
* @param durationUs The duration from the default position in the window in {@code mediaSource}'s
|
||||
* timeline at which to stop providing samples. Specifying a duration that exceeds the {@code
|
||||
* mediaSource}'s duration will result in the end of the source not being clipped.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ClippingMediaSource(MediaSource mediaSource, long durationUs) {
|
||||
this(
|
||||
mediaSource,
|
||||
/* startPositionUs= */ 0,
|
||||
/* endPositionUs= */ durationUs,
|
||||
/* enableInitialDiscontinuity= */ true,
|
||||
/* allowDynamicClippingUpdates= */ false,
|
||||
/* relativeToDefaultPosition= */ true);
|
||||
this(new Builder(mediaSource).setEndPositionUs(durationUs).setRelativeToDefaultPosition(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new clipping source that wraps the specified source.
|
||||
*
|
||||
* <p>If the start point is guaranteed to be a key frame, pass {@code false} to {@code
|
||||
* enableInitialPositionDiscontinuity} to suppress an initial discontinuity when a period is first
|
||||
* read from.
|
||||
*
|
||||
* <p>For live streams, if the clipping positions should move with the live window, pass {@code
|
||||
* true} to {@code allowDynamicClippingUpdates}. Otherwise, the live stream ends when the playback
|
||||
* reaches {@code endPositionUs} in the last reported live window at the time a media period was
|
||||
* created.
|
||||
*
|
||||
* @param mediaSource The single-period source to wrap.
|
||||
* @param startPositionUs The start position at which to start providing samples, in microseconds.
|
||||
* If {@code relativeToDefaultPosition} is {@code false}, this position is relative to the
|
||||
* start of the window in {@code mediaSource}'s timeline. If {@code relativeToDefaultPosition}
|
||||
* is {@code true}, this position is relative to the default position in the window in {@code
|
||||
* mediaSource}'s timeline.
|
||||
* @param endPositionUs The end position at which to stop providing samples, in microseconds.
|
||||
* Specify {@link C#TIME_END_OF_SOURCE} to provide samples from the specified start point up
|
||||
* to the end of the source. Specifying a position that exceeds the {@code mediaSource}'s
|
||||
* duration will also result in the end of the source not being clipped. If {@code
|
||||
* relativeToDefaultPosition} is {@code false}, the specified position is relative to the
|
||||
* start of the window in {@code mediaSource}'s timeline. If {@code relativeToDefaultPosition}
|
||||
* is {@code true}, this position is relative to the default position in the window in {@code
|
||||
* mediaSource}'s timeline.
|
||||
* @param enableInitialDiscontinuity Whether the initial discontinuity should be enabled.
|
||||
* @param allowDynamicClippingUpdates Whether the clipping of active media periods moves with a
|
||||
* live window. If {@code false}, playback ends when it reaches {@code endPositionUs} in the
|
||||
* last reported live window at the time a media period was created.
|
||||
* @param relativeToDefaultPosition Whether {@code startPositionUs} and {@code endPositionUs} are
|
||||
* relative to the default position in the window in {@code mediaSource}'s timeline.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ClippingMediaSource(
|
||||
MediaSource mediaSource,
|
||||
long startPositionUs,
|
||||
@ -190,13 +297,22 @@ public final class ClippingMediaSource extends WrappingMediaSource {
|
||||
boolean enableInitialDiscontinuity,
|
||||
boolean allowDynamicClippingUpdates,
|
||||
boolean relativeToDefaultPosition) {
|
||||
super(Assertions.checkNotNull(mediaSource));
|
||||
Assertions.checkArgument(startPositionUs >= 0);
|
||||
startUs = startPositionUs;
|
||||
endUs = endPositionUs;
|
||||
this.enableInitialDiscontinuity = enableInitialDiscontinuity;
|
||||
this.allowDynamicClippingUpdates = allowDynamicClippingUpdates;
|
||||
this.relativeToDefaultPosition = relativeToDefaultPosition;
|
||||
this(
|
||||
new Builder(mediaSource)
|
||||
.setStartPositionUs(startPositionUs)
|
||||
.setEndPositionUs(endPositionUs)
|
||||
.setEnableInitialDiscontinuity(enableInitialDiscontinuity)
|
||||
.setAllowDynamicClippingUpdates(allowDynamicClippingUpdates)
|
||||
.setRelativeToDefaultPosition(relativeToDefaultPosition));
|
||||
}
|
||||
|
||||
private ClippingMediaSource(Builder builder) {
|
||||
super(builder.mediaSource);
|
||||
this.startUs = builder.startPositionUs;
|
||||
this.endUs = builder.endPositionUs;
|
||||
this.enableInitialDiscontinuity = builder.enableInitialDiscontinuity;
|
||||
this.allowDynamicClippingUpdates = builder.allowDynamicClippingUpdates;
|
||||
this.relativeToDefaultPosition = builder.relativeToDefaultPosition;
|
||||
mediaPeriods = new ArrayList<>();
|
||||
window = new Timeline.Window();
|
||||
}
|
||||
|
@ -583,13 +583,13 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
|
||||
&& !mediaItem.clippingConfiguration.relativeToDefaultPosition) {
|
||||
return mediaSource;
|
||||
}
|
||||
return new ClippingMediaSource(
|
||||
mediaSource,
|
||||
mediaItem.clippingConfiguration.startPositionUs,
|
||||
mediaItem.clippingConfiguration.endPositionUs,
|
||||
/* enableInitialDiscontinuity= */ !mediaItem.clippingConfiguration.startsAtKeyFrame,
|
||||
/* allowDynamicClippingUpdates= */ mediaItem.clippingConfiguration.relativeToLiveWindow,
|
||||
mediaItem.clippingConfiguration.relativeToDefaultPosition);
|
||||
return new ClippingMediaSource.Builder(mediaSource)
|
||||
.setStartPositionUs(mediaItem.clippingConfiguration.startPositionUs)
|
||||
.setEndPositionUs(mediaItem.clippingConfiguration.endPositionUs)
|
||||
.setEnableInitialDiscontinuity(!mediaItem.clippingConfiguration.startsAtKeyFrame)
|
||||
.setAllowDynamicClippingUpdates(mediaItem.clippingConfiguration.relativeToLiveWindow)
|
||||
.setRelativeToDefaultPosition(mediaItem.clippingConfiguration.relativeToDefaultPosition)
|
||||
.build();
|
||||
}
|
||||
|
||||
private MediaSource maybeWrapWithAdsMediaSource(MediaItem mediaItem, MediaSource mediaSource) {
|
||||
|
@ -694,16 +694,18 @@ public class ExoPlayerTest {
|
||||
.build();
|
||||
// Use media sources with discontinuities so that enabled streams are set to final.
|
||||
ClippingMediaSource clippedFakeAudioSource =
|
||||
new ClippingMediaSource(
|
||||
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.AUDIO_FORMAT), 0, 300_000L);
|
||||
new ClippingMediaSource.Builder(
|
||||
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.AUDIO_FORMAT))
|
||||
.setEndPositionMs(300)
|
||||
.build();
|
||||
ClippingMediaSource clippedFakeAudioVideoSource =
|
||||
new ClippingMediaSource(
|
||||
new FakeMediaSource(
|
||||
new FakeTimeline(),
|
||||
ExoPlayerTestRunner.VIDEO_FORMAT,
|
||||
ExoPlayerTestRunner.AUDIO_FORMAT),
|
||||
0,
|
||||
300_000L);
|
||||
new ClippingMediaSource.Builder(
|
||||
new FakeMediaSource(
|
||||
new FakeTimeline(),
|
||||
ExoPlayerTestRunner.VIDEO_FORMAT,
|
||||
ExoPlayerTestRunner.AUDIO_FORMAT))
|
||||
.setEndPositionMs(300)
|
||||
.build();
|
||||
player.setMediaSources(
|
||||
ImmutableList.of(
|
||||
clippedFakeAudioSource, clippedFakeAudioVideoSource, clippedFakeAudioSource));
|
||||
@ -3825,8 +3827,10 @@ public class ExoPlayerTest {
|
||||
long startPositionUs = 300_000;
|
||||
long expectedDurationUs = 700_000;
|
||||
MediaSource mediaSource =
|
||||
new ClippingMediaSource(
|
||||
new FakeMediaSource(), startPositionUs, startPositionUs + expectedDurationUs);
|
||||
new ClippingMediaSource.Builder(new FakeMediaSource())
|
||||
.setStartPositionUs(startPositionUs)
|
||||
.setEndPositionUs(startPositionUs + expectedDurationUs)
|
||||
.build();
|
||||
Clock clock = new FakeClock(/* isAutoAdvancing= */ true);
|
||||
AtomicReference<Player> playerReference = new AtomicReference<>();
|
||||
AtomicLong positionAtDiscontinuityMs = new AtomicLong(C.TIME_UNSET);
|
||||
@ -3964,10 +3968,9 @@ public class ExoPlayerTest {
|
||||
throws Exception {
|
||||
FakeMediaSource mediaSource = new FakeMediaSource(/* timeline= */ null);
|
||||
MediaSource clippedMediaSource =
|
||||
new ClippingMediaSource(
|
||||
mediaSource,
|
||||
/* startPositionUs= */ 3 * C.MICROS_PER_SECOND,
|
||||
/* endPositionUs= */ C.TIME_END_OF_SOURCE);
|
||||
new ClippingMediaSource.Builder(mediaSource)
|
||||
.setStartPositionUs(3 * C.MICROS_PER_SECOND)
|
||||
.build();
|
||||
MediaSource concatenatedMediaSource = new ConcatenatingMediaSource(clippedMediaSource);
|
||||
AtomicLong positionWhenReady = new AtomicLong();
|
||||
ActionSchedule actionSchedule =
|
||||
|
@ -188,13 +188,17 @@ public final class MergingPlaylistPlaybackTest {
|
||||
C.TRACK_TYPE_AUDIO);
|
||||
if (videoClipped) {
|
||||
videoSource =
|
||||
new ClippingMediaSource(
|
||||
videoSource, /* startPositionUs= */ 300_000, /* endPositionUs= */ 600_000);
|
||||
new ClippingMediaSource.Builder(videoSource)
|
||||
.setStartPositionMs(300)
|
||||
.setEndPositionMs(600)
|
||||
.build();
|
||||
}
|
||||
if (audioClipped) {
|
||||
audioSource =
|
||||
new ClippingMediaSource(
|
||||
audioSource, /* startPositionUs= */ 500_000, /* endPositionUs= */ 800_000);
|
||||
new ClippingMediaSource.Builder(audioSource)
|
||||
.setStartPositionMs(500)
|
||||
.setEndPositionMs(800)
|
||||
.build();
|
||||
}
|
||||
return new MergingMediaSource(
|
||||
/* adjustPeriodTimeOffsets= */ true,
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package androidx.media3.exoplayer.source;
|
||||
|
||||
import static androidx.media3.common.util.Util.msToUs;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@ -574,13 +573,13 @@ public final class ClippingMediaSourceTest {
|
||||
FakeMediaSource fakeMediaSource = new FakeMediaSource();
|
||||
fakeMediaSource.setCanUpdateMediaItems(true);
|
||||
fakeMediaSource.updateMediaItem(mediaItem);
|
||||
return new ClippingMediaSource(
|
||||
fakeMediaSource,
|
||||
msToUs(mediaItem.clippingConfiguration.startPositionMs),
|
||||
msToUs(mediaItem.clippingConfiguration.endPositionMs),
|
||||
mediaItem.clippingConfiguration.startsAtKeyFrame,
|
||||
mediaItem.clippingConfiguration.relativeToLiveWindow,
|
||||
mediaItem.clippingConfiguration.relativeToDefaultPosition);
|
||||
return new ClippingMediaSource.Builder(fakeMediaSource)
|
||||
.setStartPositionMs(mediaItem.clippingConfiguration.startPositionMs)
|
||||
.setEndPositionMs(mediaItem.clippingConfiguration.endPositionMs)
|
||||
.setEnableInitialDiscontinuity(!mediaItem.clippingConfiguration.startsAtKeyFrame)
|
||||
.setAllowDynamicClippingUpdates(mediaItem.clippingConfiguration.relativeToLiveWindow)
|
||||
.setRelativeToDefaultPosition(mediaItem.clippingConfiguration.relativeToDefaultPosition)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -589,7 +588,11 @@ public final class ClippingMediaSourceTest {
|
||||
private static Timeline getClippedTimeline(Timeline timeline, long startUs, long endUs)
|
||||
throws IOException {
|
||||
FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline);
|
||||
ClippingMediaSource mediaSource = new ClippingMediaSource(fakeMediaSource, startUs, endUs);
|
||||
ClippingMediaSource mediaSource =
|
||||
new ClippingMediaSource.Builder(fakeMediaSource)
|
||||
.setStartPositionUs(startUs)
|
||||
.setEndPositionUs(endUs)
|
||||
.build();
|
||||
return getClippedTimelines(fakeMediaSource, mediaSource)[0];
|
||||
}
|
||||
|
||||
@ -599,7 +602,11 @@ public final class ClippingMediaSourceTest {
|
||||
private static Timeline getClippedTimeline(Timeline timeline, long durationUs)
|
||||
throws IOException {
|
||||
FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline);
|
||||
ClippingMediaSource mediaSource = new ClippingMediaSource(fakeMediaSource, durationUs);
|
||||
ClippingMediaSource mediaSource =
|
||||
new ClippingMediaSource.Builder(fakeMediaSource)
|
||||
.setEndPositionUs(durationUs)
|
||||
.setRelativeToDefaultPosition(true)
|
||||
.build();
|
||||
return getClippedTimelines(fakeMediaSource, mediaSource)[0];
|
||||
}
|
||||
|
||||
@ -617,13 +624,12 @@ public final class ClippingMediaSourceTest {
|
||||
throws IOException {
|
||||
FakeMediaSource fakeMediaSource = new FakeMediaSource(firstTimeline);
|
||||
ClippingMediaSource mediaSource =
|
||||
new ClippingMediaSource(
|
||||
fakeMediaSource,
|
||||
startUs,
|
||||
endUs,
|
||||
/* enableInitialDiscontinuity= */ true,
|
||||
allowDynamicUpdates,
|
||||
fromDefaultPosition);
|
||||
new ClippingMediaSource.Builder(fakeMediaSource)
|
||||
.setStartPositionUs(startUs)
|
||||
.setEndPositionUs(endUs)
|
||||
.setAllowDynamicClippingUpdates(allowDynamicUpdates)
|
||||
.setRelativeToDefaultPosition(fromDefaultPosition)
|
||||
.build();
|
||||
return getClippedTimelines(fakeMediaSource, mediaSource, additionalTimelines);
|
||||
}
|
||||
|
||||
|
@ -814,10 +814,10 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
}
|
||||
|
||||
MediaSource silenceMediaSource =
|
||||
new ClippingMediaSource(
|
||||
new SilenceMediaSource(editedMediaItem.durationUs),
|
||||
editedMediaItem.mediaItem.clippingConfiguration.startPositionUs,
|
||||
editedMediaItem.mediaItem.clippingConfiguration.endPositionUs);
|
||||
new ClippingMediaSource.Builder(new SilenceMediaSource(editedMediaItem.durationUs))
|
||||
.setStartPositionUs(editedMediaItem.mediaItem.clippingConfiguration.startPositionUs)
|
||||
.setEndPositionUs(editedMediaItem.mediaItem.clippingConfiguration.endPositionUs)
|
||||
.build();
|
||||
|
||||
return new MergingMediaSource(mainMediaSource, silenceMediaSource);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user