mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Merge pull request #123 from stoyicker:wrapping_media_source
PiperOrigin-RevId: 476376463
This commit is contained in:
commit
cac8c4f6e9
@ -25,6 +25,8 @@
|
||||
AudioTrack offload state.
|
||||
([#134](https://github.com/androidx/media/issues/134)).
|
||||
* Make `AudioTrackBufferSizeProvider` a public interface.
|
||||
* Add `WrappingMediaSource` to simplify wrapping a single `MediaSource`
|
||||
([#7279](https://github.com/google/ExoPlayer/issues/7279)).
|
||||
* Metadata:
|
||||
* `MetadataRenderer` can now be configured to render metadata as soon as
|
||||
they are available. Create an instance with
|
||||
|
@ -200,6 +200,13 @@ public abstract class BaseMediaSource implements MediaSource {
|
||||
drmEventDispatcher.removeEventListener(eventListener);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Overriding deprecated method to make it final.
|
||||
@Override
|
||||
public final void prepareSource(
|
||||
MediaSourceCaller caller, @Nullable TransferListener mediaTransferListener) {
|
||||
prepareSource(caller, mediaTransferListener, PlayerId.UNSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void prepareSource(
|
||||
MediaSourceCaller caller,
|
||||
|
@ -22,12 +22,10 @@ import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Timeline;
|
||||
import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.upstream.Allocator;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Documented;
|
||||
@ -41,7 +39,7 @@ import java.util.ArrayList;
|
||||
* positions. The wrapped source must consist of a single period.
|
||||
*/
|
||||
@UnstableApi
|
||||
public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
public final class ClippingMediaSource extends WrappingMediaSource {
|
||||
|
||||
/** Thrown when a {@link ClippingMediaSource} cannot clip its wrapped source. */
|
||||
public static final class IllegalClippingException extends IOException {
|
||||
@ -87,7 +85,6 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
}
|
||||
}
|
||||
|
||||
private final MediaSource mediaSource;
|
||||
private final long startUs;
|
||||
private final long endUs;
|
||||
private final boolean enableInitialDiscontinuity;
|
||||
@ -183,8 +180,8 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
boolean enableInitialDiscontinuity,
|
||||
boolean allowDynamicClippingUpdates,
|
||||
boolean relativeToDefaultPosition) {
|
||||
super(Assertions.checkNotNull(mediaSource));
|
||||
Assertions.checkArgument(startPositionUs >= 0);
|
||||
this.mediaSource = Assertions.checkNotNull(mediaSource);
|
||||
startUs = startPositionUs;
|
||||
endUs = endPositionUs;
|
||||
this.enableInitialDiscontinuity = enableInitialDiscontinuity;
|
||||
@ -194,17 +191,6 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
window = new Timeline.Window();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaItem getMediaItem() {
|
||||
return mediaSource.getMediaItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
|
||||
super.prepareSourceInternal(mediaTransferListener);
|
||||
prepareChildSource(/* id= */ null, mediaSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||
if (clippingError != null) {
|
||||
@ -242,7 +228,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChildSourceInfoRefreshed(Void id, MediaSource mediaSource, Timeline timeline) {
|
||||
protected void onChildSourceInfoRefreshed(Timeline timeline) {
|
||||
if (clippingError != null) {
|
||||
return;
|
||||
}
|
||||
|
@ -17,12 +17,10 @@ package androidx.media3.exoplayer.source;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.Timeline;
|
||||
import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.AbstractConcatenatedTimeline;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
import androidx.media3.exoplayer.source.ShuffleOrder.UnshuffledShuffleOrder;
|
||||
@ -43,9 +41,8 @@ import java.util.Map;
|
||||
*/
|
||||
@Deprecated
|
||||
@UnstableApi
|
||||
public final class LoopingMediaSource extends CompositeMediaSource<Void> {
|
||||
public final class LoopingMediaSource extends WrappingMediaSource {
|
||||
|
||||
private final MaskingMediaSource maskingMediaSource;
|
||||
private final int loopCount;
|
||||
private final Map<MediaPeriodId, MediaPeriodId> childMediaPeriodIdToMediaPeriodId;
|
||||
private final Map<MediaPeriod, MediaPeriodId> mediaPeriodToChildMediaPeriodId;
|
||||
@ -67,21 +64,17 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
|
||||
* @param loopCount The desired number of loops. Must be strictly positive.
|
||||
*/
|
||||
public LoopingMediaSource(MediaSource childSource, int loopCount) {
|
||||
super(new MaskingMediaSource(childSource, /* useLazyPreparation= */ false));
|
||||
Assertions.checkArgument(loopCount > 0);
|
||||
this.maskingMediaSource = new MaskingMediaSource(childSource, /* useLazyPreparation= */ false);
|
||||
this.loopCount = loopCount;
|
||||
childMediaPeriodIdToMediaPeriodId = new HashMap<>();
|
||||
mediaPeriodToChildMediaPeriodId = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaItem getMediaItem() {
|
||||
return maskingMediaSource.getMediaItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Timeline getInitialTimeline() {
|
||||
MaskingMediaSource maskingMediaSource = (MaskingMediaSource) mediaSource;
|
||||
return loopCount != Integer.MAX_VALUE
|
||||
? new LoopingTimeline(maskingMediaSource.getTimeline(), loopCount)
|
||||
: new InfinitelyLoopingTimeline(maskingMediaSource.getTimeline());
|
||||
@ -92,29 +85,23 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
|
||||
super.prepareSourceInternal(mediaTransferListener);
|
||||
prepareChildSource(/* id= */ null, maskingMediaSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
||||
if (loopCount == Integer.MAX_VALUE) {
|
||||
return maskingMediaSource.createPeriod(id, allocator, startPositionUs);
|
||||
return mediaSource.createPeriod(id, allocator, startPositionUs);
|
||||
}
|
||||
Object childPeriodUid = LoopingTimeline.getChildPeriodUidFromConcatenatedUid(id.periodUid);
|
||||
MediaPeriodId childMediaPeriodId = id.copyWithPeriodUid(childPeriodUid);
|
||||
childMediaPeriodIdToMediaPeriodId.put(childMediaPeriodId, id);
|
||||
MediaPeriod mediaPeriod =
|
||||
maskingMediaSource.createPeriod(childMediaPeriodId, allocator, startPositionUs);
|
||||
mediaSource.createPeriod(childMediaPeriodId, allocator, startPositionUs);
|
||||
mediaPeriodToChildMediaPeriodId.put(mediaPeriod, childMediaPeriodId);
|
||||
return mediaPeriod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releasePeriod(MediaPeriod mediaPeriod) {
|
||||
maskingMediaSource.releasePeriod(mediaPeriod);
|
||||
mediaSource.releasePeriod(mediaPeriod);
|
||||
@Nullable
|
||||
MediaPeriodId childMediaPeriodId = mediaPeriodToChildMediaPeriodId.remove(mediaPeriod);
|
||||
if (childMediaPeriodId != null) {
|
||||
@ -123,7 +110,7 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChildSourceInfoRefreshed(Void id, MediaSource mediaSource, Timeline timeline) {
|
||||
protected void onChildSourceInfoRefreshed(Timeline timeline) {
|
||||
Timeline loopingTimeline =
|
||||
loopCount != Integer.MAX_VALUE
|
||||
? new LoopingTimeline(timeline, loopCount)
|
||||
@ -133,8 +120,7 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
||||
Void id, MediaPeriodId mediaPeriodId) {
|
||||
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(MediaPeriodId mediaPeriodId) {
|
||||
return loopCount != Integer.MAX_VALUE
|
||||
? childMediaPeriodIdToMediaPeriodId.get(mediaPeriodId)
|
||||
: mediaPeriodId;
|
||||
|
@ -28,7 +28,6 @@ import androidx.media3.common.Timeline.Window;
|
||||
import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.upstream.Allocator;
|
||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
@ -37,9 +36,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
* structure is known.
|
||||
*/
|
||||
@UnstableApi
|
||||
public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
public final class MaskingMediaSource extends WrappingMediaSource {
|
||||
|
||||
private final MediaSource mediaSource;
|
||||
private final boolean useLazyPreparation;
|
||||
private final Timeline.Window window;
|
||||
private final Timeline.Period period;
|
||||
@ -59,7 +57,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
* initial preparations are triggered only when the player starts buffering the media.
|
||||
*/
|
||||
public MaskingMediaSource(MediaSource mediaSource, boolean useLazyPreparation) {
|
||||
this.mediaSource = mediaSource;
|
||||
super(mediaSource);
|
||||
this.useLazyPreparation = useLazyPreparation && mediaSource.isSingleWindow();
|
||||
window = new Timeline.Window();
|
||||
period = new Timeline.Period();
|
||||
@ -80,19 +78,13 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
|
||||
super.prepareSourceInternal(mediaTransferListener);
|
||||
public void prepareSourceInternal() {
|
||||
if (!useLazyPreparation) {
|
||||
hasStartedPreparing = true;
|
||||
prepareChildSource(/* id= */ null, mediaSource);
|
||||
prepareChildSource();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaItem getMediaItem() {
|
||||
return mediaSource.getMediaItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("MissingSuperCall")
|
||||
public void maybeThrowSourceInfoRefreshError() {
|
||||
@ -115,7 +107,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
unpreparedMaskingMediaPeriod = mediaPeriod;
|
||||
if (!hasStartedPreparing) {
|
||||
hasStartedPreparing = true;
|
||||
prepareChildSource(/* id= */ null, mediaSource);
|
||||
prepareChildSource();
|
||||
}
|
||||
}
|
||||
return mediaPeriod;
|
||||
@ -137,8 +129,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChildSourceInfoRefreshed(
|
||||
Void id, MediaSource mediaSource, Timeline newTimeline) {
|
||||
protected void onChildSourceInfoRefreshed(Timeline newTimeline) {
|
||||
@Nullable MediaPeriodId idForMaskingPeriodPreparation = null;
|
||||
if (isPrepared) {
|
||||
timeline = timeline.cloneWithUpdatedTimeline(newTimeline);
|
||||
@ -208,8 +199,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
||||
Void id, MediaPeriodId mediaPeriodId) {
|
||||
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(MediaPeriodId mediaPeriodId) {
|
||||
return mediaPeriodId.copyWithPeriodUid(getExternalPeriodUid(mediaPeriodId.periodUid));
|
||||
}
|
||||
|
||||
@ -304,11 +294,6 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
return new MaskingTimeline(timeline, replacedInternalWindowUid, replacedInternalPeriodUid);
|
||||
}
|
||||
|
||||
/** Returns the wrapped timeline. */
|
||||
public Timeline getTimeline() {
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
|
||||
timeline.getWindow(windowIndex, window, defaultPositionProjectionUs);
|
||||
|
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package androidx.media3.exoplayer.source;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Timeline;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.upstream.Allocator;
|
||||
|
||||
/**
|
||||
* An abstract {@link MediaSource} wrapping a single child {@link MediaSource}.
|
||||
*
|
||||
* <p>The implementation may want to override the following methods as needed:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #getMediaItem()}: Amend the {@link MediaItem} for this media source. This is only
|
||||
* used before the child source is prepared.
|
||||
* <li>{@link #onChildSourceInfoRefreshed(Timeline)}: Called whenever the child source's {@link
|
||||
* Timeline} changed. This {@link Timeline} can be amended if needed, for example using {@link
|
||||
* ForwardingTimeline}. The {@link Timeline} for the wrapping source needs to be published
|
||||
* with {@link #refreshSourceInfo(Timeline)}.
|
||||
* <li>{@link #createPeriod}/{@link #releasePeriod}: These methods create and release {@link
|
||||
* MediaPeriod} instances. They typically forward to the wrapped media source and optionally
|
||||
* wrap the returned {@link MediaPeriod}.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Other methods like {@link #prepareSourceInternal}, {@link #enableInternal}, {@link
|
||||
* #disableInternal} or {@link #releaseSourceInternal} only need to be overwritten if required for
|
||||
* resource management.
|
||||
*/
|
||||
@UnstableApi
|
||||
public abstract class WrappingMediaSource extends CompositeMediaSource<Void> {
|
||||
|
||||
private static final Void CHILD_SOURCE_ID = null;
|
||||
|
||||
/** The wrapped child {@link MediaSource}. */
|
||||
protected final MediaSource mediaSource;
|
||||
|
||||
/**
|
||||
* Creates the wrapping {@link MediaSource}.
|
||||
*
|
||||
* @param mediaSource The wrapped child {@link MediaSource}.
|
||||
*/
|
||||
protected WrappingMediaSource(MediaSource mediaSource) {
|
||||
this.mediaSource = mediaSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
|
||||
super.prepareSourceInternal(mediaTransferListener);
|
||||
prepareSourceInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts source preparation and enables the source, see {@link #prepareSource(MediaSourceCaller,
|
||||
* TransferListener, PlayerId)}. This method is called at most once until the next call to {@link
|
||||
* #releaseSourceInternal()}.
|
||||
*/
|
||||
protected void prepareSourceInternal() {
|
||||
prepareChildSource();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Timeline getInitialTimeline() {
|
||||
return mediaSource.getInitialTimeline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleWindow() {
|
||||
return mediaSource.isSingleWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MediaItem} for this media source.
|
||||
*
|
||||
* <p>This method can be overridden to amend the {@link MediaItem} of the child source. It is only
|
||||
* used before the child source is prepared.
|
||||
*
|
||||
* @see MediaSource#getMediaItem()
|
||||
*/
|
||||
@Override
|
||||
public MediaItem getMediaItem() {
|
||||
return mediaSource.getMediaItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the requested {@link MediaPeriod}.
|
||||
*
|
||||
* <p>This method typically forwards to the wrapped media source and optionally wraps the returned
|
||||
* {@link MediaPeriod}.
|
||||
*
|
||||
* @see MediaSource#createPeriod(MediaPeriodId, Allocator, long)
|
||||
*/
|
||||
@Override
|
||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
||||
return mediaSource.createPeriod(id, allocator, startPositionUs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a {@link MediaPeriod}.
|
||||
*
|
||||
* <p>This method typically forwards to the wrapped media source and optionally unwraps the
|
||||
* provided {@link MediaPeriod}.
|
||||
*
|
||||
* @see MediaSource#releasePeriod(MediaPeriod)
|
||||
*/
|
||||
@Override
|
||||
public void releasePeriod(MediaPeriod mediaPeriod) {
|
||||
mediaSource.releasePeriod(mediaPeriod);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void onChildSourceInfoRefreshed(
|
||||
Void id, MediaSource mediaSource, Timeline timeline) {
|
||||
onChildSourceInfoRefreshed(timeline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the child source info has been refreshed.
|
||||
*
|
||||
* <p>This {@link Timeline} can be amended if needed, for example using {@link
|
||||
* ForwardingTimeline}. The {@link Timeline} for the wrapping source needs to be published with
|
||||
* {@link #refreshSourceInfo(Timeline)}.
|
||||
*
|
||||
* @param timeline The timeline of the child source.
|
||||
*/
|
||||
protected void onChildSourceInfoRefreshed(Timeline timeline) {
|
||||
refreshSourceInfo(timeline);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final int getWindowIndexForChildWindowIndex(Void id, int windowIndex) {
|
||||
return getWindowIndexForChildWindowIndex(windowIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the window index in the wrapping source corresponding to the specified window index in
|
||||
* a child source. The default implementation does not change the window index.
|
||||
*
|
||||
* @param windowIndex A window index of the child source.
|
||||
* @return The corresponding window index in the wrapping source.
|
||||
*/
|
||||
protected int getWindowIndexForChildWindowIndex(int windowIndex) {
|
||||
return windowIndex;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected final MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
||||
Void id, MediaPeriodId mediaPeriodId) {
|
||||
return getMediaPeriodIdForChildMediaPeriodId(mediaPeriodId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MediaPeriodId} in the wrapping source corresponding to the specified {@link
|
||||
* MediaPeriodId} in a child source. The default implementation does not change the media period
|
||||
* id.
|
||||
*
|
||||
* @param mediaPeriodId A {@link MediaPeriodId} of the child source.
|
||||
* @return The corresponding {@link MediaPeriodId} in the wrapping source. Null if no
|
||||
* corresponding media period id can be determined.
|
||||
*/
|
||||
@Nullable
|
||||
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(MediaPeriodId mediaPeriodId) {
|
||||
return mediaPeriodId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final long getMediaTimeForChildMediaTime(Void id, long mediaTimeMs) {
|
||||
return getMediaTimeForChildMediaTime(mediaTimeMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the media time in the {@link MediaPeriod} of the wrapping source corresponding to the
|
||||
* specified media time in the {@link MediaPeriod} of the child source. The default implementation
|
||||
* does not change the media time.
|
||||
*
|
||||
* @param mediaTimeMs A media time in the {@link MediaPeriod} of the child source, in
|
||||
* milliseconds.
|
||||
* @return The corresponding media time in the {@link MediaPeriod} of the wrapping source, in
|
||||
* milliseconds.
|
||||
*/
|
||||
protected long getMediaTimeForChildMediaTime(long mediaTimeMs) {
|
||||
return mediaTimeMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the wrapped child source.
|
||||
*
|
||||
* <p>{@link #onChildSourceInfoRefreshed(Timeline)} will be called when the child source updates
|
||||
* its timeline.
|
||||
*
|
||||
* <p>If sources aren't explicitly released with {@link #releaseChildSource()} they will be
|
||||
* released in {@link #releaseSourceInternal()}.
|
||||
*/
|
||||
protected final void prepareChildSource() {
|
||||
prepareChildSource(CHILD_SOURCE_ID, mediaSource);
|
||||
}
|
||||
|
||||
/** Enables the child source. */
|
||||
protected final void enableChildSource() {
|
||||
enableChildSource(CHILD_SOURCE_ID);
|
||||
}
|
||||
|
||||
/** Disables the child source. */
|
||||
protected final void disableChildSource() {
|
||||
disableChildSource(CHILD_SOURCE_ID);
|
||||
}
|
||||
|
||||
/** Releases the child source. */
|
||||
protected final void releaseChildSource() {
|
||||
releaseChildSource(CHILD_SOURCE_ID);
|
||||
}
|
||||
}
|
@ -118,7 +118,6 @@ import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
import androidx.media3.exoplayer.source.ClippingMediaSource;
|
||||
import androidx.media3.exoplayer.source.CompositeMediaSource;
|
||||
import androidx.media3.exoplayer.source.ConcatenatingMediaSource;
|
||||
import androidx.media3.exoplayer.source.MaskingMediaSource;
|
||||
import androidx.media3.exoplayer.source.MediaPeriod;
|
||||
@ -128,6 +127,7 @@ import androidx.media3.exoplayer.source.MediaSourceEventListener;
|
||||
import androidx.media3.exoplayer.source.ShuffleOrder;
|
||||
import androidx.media3.exoplayer.source.SinglePeriodTimeline;
|
||||
import androidx.media3.exoplayer.source.TrackGroupArray;
|
||||
import androidx.media3.exoplayer.source.WrappingMediaSource;
|
||||
import androidx.media3.exoplayer.source.ads.ServerSideAdInsertionMediaSource;
|
||||
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
|
||||
import androidx.media3.exoplayer.upstream.Allocation;
|
||||
@ -3942,33 +3942,15 @@ public final class ExoPlayerTest {
|
||||
new TimelineWindowDefinition(
|
||||
/* isSeekable= */ true, /* isDynamic= */ false, /* durationUs= */ 10_000_000));
|
||||
final ConcatenatingMediaSource underlyingSource = new ConcatenatingMediaSource();
|
||||
CompositeMediaSource<Void> delegatingMediaSource =
|
||||
new CompositeMediaSource<Void>() {
|
||||
WrappingMediaSource delegatingMediaSource =
|
||||
new WrappingMediaSource(underlyingSource) {
|
||||
@Override
|
||||
public void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
|
||||
super.prepareSourceInternal(mediaTransferListener);
|
||||
public void prepareSourceInternal() {
|
||||
underlyingSource.addMediaSource(
|
||||
new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT));
|
||||
underlyingSource.addMediaSource(
|
||||
new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT));
|
||||
prepareChildSource(null, underlyingSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(
|
||||
MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
||||
return underlyingSource.createPeriod(id, allocator, startPositionUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releasePeriod(MediaPeriod mediaPeriod) {
|
||||
underlyingSource.releasePeriod(mediaPeriod);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChildSourceInfoRefreshed(
|
||||
Void id, MediaSource mediaSource, Timeline timeline) {
|
||||
refreshSourceInfo(timeline);
|
||||
super.prepareSourceInternal();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -3976,11 +3958,6 @@ public final class ExoPlayerTest {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaItem getMediaItem() {
|
||||
return underlyingSource.getMediaItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Timeline getInitialTimeline() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user