Merge pull request #123 from stoyicker:wrapping_media_source

PiperOrigin-RevId: 476376463
This commit is contained in:
Marc Baechinger 2022-10-19 23:42:52 +00:00
commit 8623f1f016
6 changed files with 259 additions and 89 deletions

View File

@ -198,6 +198,13 @@ public abstract class BaseMediaSource implements MediaSource {
drmEventDispatcher.removeEventListener(eventListener); 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 @Override
public final void prepareSource( public final void prepareSource(
MediaSourceCaller caller, MediaSourceCaller caller,

View File

@ -22,10 +22,8 @@ import static java.lang.annotation.ElementType.TYPE_USE;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
@ -39,7 +37,7 @@ import java.util.ArrayList;
* {@link MediaSource} that wraps a source and clips its timeline based on specified start/end * {@link MediaSource} that wraps a source and clips its timeline based on specified start/end
* positions. The wrapped source must consist of a single period. * positions. The wrapped source must consist of a single period.
*/ */
public final class ClippingMediaSource extends CompositeMediaSource<Void> { public final class ClippingMediaSource extends WrappingMediaSource {
/** Thrown when a {@link ClippingMediaSource} cannot clip its wrapped source. */ /** Thrown when a {@link ClippingMediaSource} cannot clip its wrapped source. */
public static final class IllegalClippingException extends IOException { public static final class IllegalClippingException extends IOException {
@ -85,7 +83,6 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
} }
} }
private final MediaSource mediaSource;
private final long startUs; private final long startUs;
private final long endUs; private final long endUs;
private final boolean enableInitialDiscontinuity; private final boolean enableInitialDiscontinuity;
@ -181,8 +178,8 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
boolean enableInitialDiscontinuity, boolean enableInitialDiscontinuity,
boolean allowDynamicClippingUpdates, boolean allowDynamicClippingUpdates,
boolean relativeToDefaultPosition) { boolean relativeToDefaultPosition) {
super(Assertions.checkNotNull(mediaSource));
Assertions.checkArgument(startPositionUs >= 0); Assertions.checkArgument(startPositionUs >= 0);
this.mediaSource = Assertions.checkNotNull(mediaSource);
startUs = startPositionUs; startUs = startPositionUs;
endUs = endPositionUs; endUs = endPositionUs;
this.enableInitialDiscontinuity = enableInitialDiscontinuity; this.enableInitialDiscontinuity = enableInitialDiscontinuity;
@ -192,17 +189,6 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
window = new Timeline.Window(); 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 @Override
public void maybeThrowSourceInfoRefreshError() throws IOException { public void maybeThrowSourceInfoRefreshError() throws IOException {
if (clippingError != null) { if (clippingError != null) {
@ -240,7 +226,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
} }
@Override @Override
protected void onChildSourceInfoRefreshed(Void id, MediaSource mediaSource, Timeline timeline) { protected void onChildSourceInfoRefreshed(Timeline timeline) {
if (clippingError != null) { if (clippingError != null) {
return; return;
} }

View File

@ -19,12 +19,10 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.AbstractConcatenatedTimeline; import com.google.android.exoplayer2.AbstractConcatenatedTimeline;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ShuffleOrder.UnshuffledShuffleOrder; import com.google.android.exoplayer2.source.ShuffleOrder.UnshuffledShuffleOrder;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -41,9 +39,8 @@ import java.util.Map;
* times. * times.
*/ */
@Deprecated @Deprecated
public final class LoopingMediaSource extends CompositeMediaSource<Void> { public final class LoopingMediaSource extends WrappingMediaSource {
private final MaskingMediaSource maskingMediaSource;
private final int loopCount; private final int loopCount;
private final Map<MediaPeriodId, MediaPeriodId> childMediaPeriodIdToMediaPeriodId; private final Map<MediaPeriodId, MediaPeriodId> childMediaPeriodIdToMediaPeriodId;
private final Map<MediaPeriod, MediaPeriodId> mediaPeriodToChildMediaPeriodId; private final Map<MediaPeriod, MediaPeriodId> mediaPeriodToChildMediaPeriodId;
@ -65,21 +62,17 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
* @param loopCount The desired number of loops. Must be strictly positive. * @param loopCount The desired number of loops. Must be strictly positive.
*/ */
public LoopingMediaSource(MediaSource childSource, int loopCount) { public LoopingMediaSource(MediaSource childSource, int loopCount) {
super(new MaskingMediaSource(childSource, /* useLazyPreparation= */ false));
Assertions.checkArgument(loopCount > 0); Assertions.checkArgument(loopCount > 0);
this.maskingMediaSource = new MaskingMediaSource(childSource, /* useLazyPreparation= */ false);
this.loopCount = loopCount; this.loopCount = loopCount;
childMediaPeriodIdToMediaPeriodId = new HashMap<>(); childMediaPeriodIdToMediaPeriodId = new HashMap<>();
mediaPeriodToChildMediaPeriodId = new HashMap<>(); mediaPeriodToChildMediaPeriodId = new HashMap<>();
} }
@Override
public MediaItem getMediaItem() {
return maskingMediaSource.getMediaItem();
}
@Override @Override
@Nullable @Nullable
public Timeline getInitialTimeline() { public Timeline getInitialTimeline() {
MaskingMediaSource maskingMediaSource = (MaskingMediaSource) mediaSource;
return loopCount != Integer.MAX_VALUE return loopCount != Integer.MAX_VALUE
? new LoopingTimeline(maskingMediaSource.getTimeline(), loopCount) ? new LoopingTimeline(maskingMediaSource.getTimeline(), loopCount)
: new InfinitelyLoopingTimeline(maskingMediaSource.getTimeline()); : new InfinitelyLoopingTimeline(maskingMediaSource.getTimeline());
@ -90,29 +83,23 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
return false; return false;
} }
@Override
protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
super.prepareSourceInternal(mediaTransferListener);
prepareChildSource(/* id= */ null, maskingMediaSource);
}
@Override @Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
if (loopCount == Integer.MAX_VALUE) { if (loopCount == Integer.MAX_VALUE) {
return maskingMediaSource.createPeriod(id, allocator, startPositionUs); return mediaSource.createPeriod(id, allocator, startPositionUs);
} }
Object childPeriodUid = LoopingTimeline.getChildPeriodUidFromConcatenatedUid(id.periodUid); Object childPeriodUid = LoopingTimeline.getChildPeriodUidFromConcatenatedUid(id.periodUid);
MediaPeriodId childMediaPeriodId = id.copyWithPeriodUid(childPeriodUid); MediaPeriodId childMediaPeriodId = id.copyWithPeriodUid(childPeriodUid);
childMediaPeriodIdToMediaPeriodId.put(childMediaPeriodId, id); childMediaPeriodIdToMediaPeriodId.put(childMediaPeriodId, id);
MediaPeriod mediaPeriod = MediaPeriod mediaPeriod =
maskingMediaSource.createPeriod(childMediaPeriodId, allocator, startPositionUs); mediaSource.createPeriod(childMediaPeriodId, allocator, startPositionUs);
mediaPeriodToChildMediaPeriodId.put(mediaPeriod, childMediaPeriodId); mediaPeriodToChildMediaPeriodId.put(mediaPeriod, childMediaPeriodId);
return mediaPeriod; return mediaPeriod;
} }
@Override @Override
public void releasePeriod(MediaPeriod mediaPeriod) { public void releasePeriod(MediaPeriod mediaPeriod) {
maskingMediaSource.releasePeriod(mediaPeriod); mediaSource.releasePeriod(mediaPeriod);
@Nullable @Nullable
MediaPeriodId childMediaPeriodId = mediaPeriodToChildMediaPeriodId.remove(mediaPeriod); MediaPeriodId childMediaPeriodId = mediaPeriodToChildMediaPeriodId.remove(mediaPeriod);
if (childMediaPeriodId != null) { if (childMediaPeriodId != null) {
@ -121,7 +108,7 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
} }
@Override @Override
protected void onChildSourceInfoRefreshed(Void id, MediaSource mediaSource, Timeline timeline) { protected void onChildSourceInfoRefreshed(Timeline timeline) {
Timeline loopingTimeline = Timeline loopingTimeline =
loopCount != Integer.MAX_VALUE loopCount != Integer.MAX_VALUE
? new LoopingTimeline(timeline, loopCount) ? new LoopingTimeline(timeline, loopCount)
@ -131,8 +118,7 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
@Override @Override
@Nullable @Nullable
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId( protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(MediaPeriodId mediaPeriodId) {
Void id, MediaPeriodId mediaPeriodId) {
return loopCount != Integer.MAX_VALUE return loopCount != Integer.MAX_VALUE
? childMediaPeriodIdToMediaPeriodId.get(mediaPeriodId) ? childMediaPeriodIdToMediaPeriodId.get(mediaPeriodId)
: mediaPeriodId; : mediaPeriodId;

View File

@ -26,7 +26,6 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Window; import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.source.ads.AdPlaybackState; import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import org.checkerframework.checker.nullness.qual.RequiresNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@ -35,9 +34,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* A {@link MediaSource} that masks the {@link Timeline} with a placeholder until the actual media * A {@link MediaSource} that masks the {@link Timeline} with a placeholder until the actual media
* structure is known. * structure is known.
*/ */
public final class MaskingMediaSource extends CompositeMediaSource<Void> { public final class MaskingMediaSource extends WrappingMediaSource {
private final MediaSource mediaSource;
private final boolean useLazyPreparation; private final boolean useLazyPreparation;
private final Timeline.Window window; private final Timeline.Window window;
private final Timeline.Period period; private final Timeline.Period period;
@ -57,7 +55,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
* initial preparations are triggered only when the player starts buffering the media. * initial preparations are triggered only when the player starts buffering the media.
*/ */
public MaskingMediaSource(MediaSource mediaSource, boolean useLazyPreparation) { public MaskingMediaSource(MediaSource mediaSource, boolean useLazyPreparation) {
this.mediaSource = mediaSource; super(mediaSource);
this.useLazyPreparation = useLazyPreparation && mediaSource.isSingleWindow(); this.useLazyPreparation = useLazyPreparation && mediaSource.isSingleWindow();
window = new Timeline.Window(); window = new Timeline.Window();
period = new Timeline.Period(); period = new Timeline.Period();
@ -78,19 +76,13 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
} }
@Override @Override
public void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { public void prepareSourceInternal() {
super.prepareSourceInternal(mediaTransferListener);
if (!useLazyPreparation) { if (!useLazyPreparation) {
hasStartedPreparing = true; hasStartedPreparing = true;
prepareChildSource(/* id= */ null, mediaSource); prepareChildSource();
} }
} }
@Override
public MediaItem getMediaItem() {
return mediaSource.getMediaItem();
}
@Override @Override
@SuppressWarnings("MissingSuperCall") @SuppressWarnings("MissingSuperCall")
public void maybeThrowSourceInfoRefreshError() { public void maybeThrowSourceInfoRefreshError() {
@ -113,7 +105,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
unpreparedMaskingMediaPeriod = mediaPeriod; unpreparedMaskingMediaPeriod = mediaPeriod;
if (!hasStartedPreparing) { if (!hasStartedPreparing) {
hasStartedPreparing = true; hasStartedPreparing = true;
prepareChildSource(/* id= */ null, mediaSource); prepareChildSource();
} }
} }
return mediaPeriod; return mediaPeriod;
@ -135,8 +127,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
} }
@Override @Override
protected void onChildSourceInfoRefreshed( protected void onChildSourceInfoRefreshed(Timeline newTimeline) {
Void id, MediaSource mediaSource, Timeline newTimeline) {
@Nullable MediaPeriodId idForMaskingPeriodPreparation = null; @Nullable MediaPeriodId idForMaskingPeriodPreparation = null;
if (isPrepared) { if (isPrepared) {
timeline = timeline.cloneWithUpdatedTimeline(newTimeline); timeline = timeline.cloneWithUpdatedTimeline(newTimeline);
@ -206,8 +197,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
@Override @Override
@Nullable @Nullable
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId( protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(MediaPeriodId mediaPeriodId) {
Void id, MediaPeriodId mediaPeriodId) {
return mediaPeriodId.copyWithPeriodUid(getExternalPeriodUid(mediaPeriodId.periodUid)); return mediaPeriodId.copyWithPeriodUid(getExternalPeriodUid(mediaPeriodId.periodUid));
} }
@ -302,11 +292,6 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
return new MaskingTimeline(timeline, replacedInternalWindowUid, replacedInternalPeriodUid); return new MaskingTimeline(timeline, replacedInternalWindowUid, replacedInternalPeriodUid);
} }
/** Returns the wrapped timeline. */
public Timeline getTimeline() {
return timeline;
}
@Override @Override
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
timeline.getWindow(windowIndex, window, defaultPositionProjectionUs); timeline.getWindow(windowIndex, window, defaultPositionProjectionUs);

View File

@ -0,0 +1,229 @@
/*
* 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 com.google.android.exoplayer2.source;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.analytics.PlayerId;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
/**
* 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.
*/
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);
}
}

View File

@ -106,7 +106,6 @@ import com.google.android.exoplayer2.metadata.id3.BinaryFrame;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper; import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper;
import com.google.android.exoplayer2.source.ClippingMediaSource; import com.google.android.exoplayer2.source.ClippingMediaSource;
import com.google.android.exoplayer2.source.CompositeMediaSource;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource; import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.MaskingMediaSource; import com.google.android.exoplayer2.source.MaskingMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
@ -117,6 +116,7 @@ import com.google.android.exoplayer2.source.ShuffleOrder;
import com.google.android.exoplayer2.source.SinglePeriodTimeline; import com.google.android.exoplayer2.source.SinglePeriodTimeline;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.WrappingMediaSource;
import com.google.android.exoplayer2.source.ads.AdPlaybackState; import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.source.ads.ServerSideAdInsertionMediaSource; import com.google.android.exoplayer2.source.ads.ServerSideAdInsertionMediaSource;
import com.google.android.exoplayer2.testutil.Action; import com.google.android.exoplayer2.testutil.Action;
@ -3932,33 +3932,15 @@ public final class ExoPlayerTest {
new TimelineWindowDefinition( new TimelineWindowDefinition(
/* isSeekable= */ true, /* isDynamic= */ false, /* durationUs= */ 10_000_000)); /* isSeekable= */ true, /* isDynamic= */ false, /* durationUs= */ 10_000_000));
final ConcatenatingMediaSource underlyingSource = new ConcatenatingMediaSource(); final ConcatenatingMediaSource underlyingSource = new ConcatenatingMediaSource();
CompositeMediaSource<Void> delegatingMediaSource = WrappingMediaSource delegatingMediaSource =
new CompositeMediaSource<Void>() { new WrappingMediaSource(underlyingSource) {
@Override @Override
public void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { public void prepareSourceInternal() {
super.prepareSourceInternal(mediaTransferListener);
underlyingSource.addMediaSource( underlyingSource.addMediaSource(
new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT)); new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT));
underlyingSource.addMediaSource( underlyingSource.addMediaSource(
new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT)); new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT));
prepareChildSource(null, underlyingSource); super.prepareSourceInternal();
}
@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);
} }
@Override @Override
@ -3966,11 +3948,6 @@ public final class ExoPlayerTest {
return false; return false;
} }
@Override
public MediaItem getMediaItem() {
return underlyingSource.getMediaItem();
}
@Override @Override
@Nullable @Nullable
public Timeline getInitialTimeline() { public Timeline getInitialTimeline() {