mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Fix nullness warning for MediaSource/MediaPeriod classes.
PiperOrigin-RevId: 249652301
This commit is contained in:
parent
14c46bc406
commit
3e990a3d24
@ -19,6 +19,7 @@ import android.util.Pair;
|
|||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
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.util.Assertions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for the concatenation of one or more {@link Timeline}s.
|
* Abstract base class for the concatenation of one or more {@link Timeline}s.
|
||||||
@ -35,6 +36,7 @@ import com.google.android.exoplayer2.Timeline;
|
|||||||
* @param concatenatedUid UID of a period in a concatenated timeline.
|
* @param concatenatedUid UID of a period in a concatenated timeline.
|
||||||
* @return UID of the child timeline this period belongs to.
|
* @return UID of the child timeline this period belongs to.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("nullness:return.type.incompatible")
|
||||||
public static Object getChildTimelineUidFromConcatenatedUid(Object concatenatedUid) {
|
public static Object getChildTimelineUidFromConcatenatedUid(Object concatenatedUid) {
|
||||||
return ((Pair<?, ?>) concatenatedUid).first;
|
return ((Pair<?, ?>) concatenatedUid).first;
|
||||||
}
|
}
|
||||||
@ -45,6 +47,7 @@ import com.google.android.exoplayer2.Timeline;
|
|||||||
* @param concatenatedUid UID of a period in a concatenated timeline.
|
* @param concatenatedUid UID of a period in a concatenated timeline.
|
||||||
* @return UID of the period in the child timeline.
|
* @return UID of the period in the child timeline.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("nullness:return.type.incompatible")
|
||||||
public static Object getChildPeriodUidFromConcatenatedUid(Object concatenatedUid) {
|
public static Object getChildPeriodUidFromConcatenatedUid(Object concatenatedUid) {
|
||||||
return ((Pair<?, ?>) concatenatedUid).second;
|
return ((Pair<?, ?>) concatenatedUid).second;
|
||||||
}
|
}
|
||||||
@ -220,7 +223,9 @@ import com.google.android.exoplayer2.Timeline;
|
|||||||
setIds);
|
setIds);
|
||||||
period.windowIndex += firstWindowIndexInChild;
|
period.windowIndex += firstWindowIndexInChild;
|
||||||
if (setIds) {
|
if (setIds) {
|
||||||
period.uid = getConcatenatedUid(getChildUidByChildIndex(childIndex), period.uid);
|
period.uid =
|
||||||
|
getConcatenatedUid(
|
||||||
|
getChildUidByChildIndex(childIndex), Assertions.checkNotNull(period.uid));
|
||||||
}
|
}
|
||||||
return period;
|
return period;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source;
|
package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
@ -25,6 +26,7 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a {@link MediaPeriod} and clips its {@link SampleStream}s to provide a subsequence of their
|
* Wraps a {@link MediaPeriod} and clips its {@link SampleStream}s to provide a subsequence of their
|
||||||
@ -37,8 +39,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
*/
|
*/
|
||||||
public final MediaPeriod mediaPeriod;
|
public final MediaPeriod mediaPeriod;
|
||||||
|
|
||||||
private MediaPeriod.Callback callback;
|
@Nullable private MediaPeriod.Callback callback;
|
||||||
private ClippingSampleStream[] sampleStreams;
|
private @NullableType ClippingSampleStream[] sampleStreams;
|
||||||
private long pendingInitialDiscontinuityPositionUs;
|
private long pendingInitialDiscontinuityPositionUs;
|
||||||
/* package */ long startUs;
|
/* package */ long startUs;
|
||||||
/* package */ long endUs;
|
/* package */ long endUs;
|
||||||
@ -95,10 +97,14 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
public long selectTracks(
|
||||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
@NullableType TrackSelection[] selections,
|
||||||
|
boolean[] mayRetainStreamFlags,
|
||||||
|
@NullableType SampleStream[] streams,
|
||||||
|
boolean[] streamResetFlags,
|
||||||
|
long positionUs) {
|
||||||
sampleStreams = new ClippingSampleStream[streams.length];
|
sampleStreams = new ClippingSampleStream[streams.length];
|
||||||
SampleStream[] childStreams = new SampleStream[streams.length];
|
@NullableType SampleStream[] childStreams = new SampleStream[streams.length];
|
||||||
for (int i = 0; i < streams.length; i++) {
|
for (int i = 0; i < streams.length; i++) {
|
||||||
sampleStreams[i] = (ClippingSampleStream) streams[i];
|
sampleStreams[i] = (ClippingSampleStream) streams[i];
|
||||||
childStreams[i] = sampleStreams[i] != null ? sampleStreams[i].childStream : null;
|
childStreams[i] = sampleStreams[i] != null ? sampleStreams[i].childStream : null;
|
||||||
@ -119,7 +125,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
for (int i = 0; i < streams.length; i++) {
|
for (int i = 0; i < streams.length; i++) {
|
||||||
if (childStreams[i] == null) {
|
if (childStreams[i] == null) {
|
||||||
sampleStreams[i] = null;
|
sampleStreams[i] = null;
|
||||||
} else if (streams[i] == null || sampleStreams[i].childStream != childStreams[i]) {
|
} else if (sampleStreams[i] == null || sampleStreams[i].childStream != childStreams[i]) {
|
||||||
sampleStreams[i] = new ClippingSampleStream(childStreams[i]);
|
sampleStreams[i] = new ClippingSampleStream(childStreams[i]);
|
||||||
}
|
}
|
||||||
streams[i] = sampleStreams[i];
|
streams[i] = sampleStreams[i];
|
||||||
@ -209,12 +215,12 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||||
callback.onPrepared(this);
|
Assertions.checkNotNull(callback).onPrepared(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
callback.onContinueLoadingRequested(this);
|
Assertions.checkNotNull(callback).onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ boolean isPendingInitialDiscontinuity() {
|
/* package */ boolean isPendingInitialDiscontinuity() {
|
||||||
@ -238,7 +244,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldKeepInitialDiscontinuity(long startUs, TrackSelection[] selections) {
|
private static boolean shouldKeepInitialDiscontinuity(
|
||||||
|
long startUs, @NullableType TrackSelection[] selections) {
|
||||||
// If the clipping start position is non-zero, the clipping sample streams will adjust
|
// If the clipping start position is non-zero, the clipping sample streams will adjust
|
||||||
// timestamps on buffers they read from the unclipped sample streams. These adjusted buffer
|
// timestamps on buffers they read from the unclipped sample streams. These adjusted buffer
|
||||||
// timestamps can be negative, because sample streams provide buffers starting at a key-frame,
|
// timestamps can be negative, because sample streams provide buffers starting at a key-frame,
|
||||||
@ -300,7 +307,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
}
|
}
|
||||||
int result = childStream.readData(formatHolder, buffer, requireFormat);
|
int result = childStream.readData(formatHolder, buffer, requireFormat);
|
||||||
if (result == C.RESULT_FORMAT_READ) {
|
if (result == C.RESULT_FORMAT_READ) {
|
||||||
Format format = formatHolder.format;
|
Format format = Assertions.checkNotNull(formatHolder.format);
|
||||||
if (format.encoderDelay != 0 || format.encoderPadding != 0) {
|
if (format.encoderDelay != 0 || format.encoderPadding != 0) {
|
||||||
// Clear gapless playback metadata if the start/end points don't match the media.
|
// Clear gapless playback metadata if the start/end points don't match the media.
|
||||||
int encoderDelay = startUs != 0 ? 0 : format.encoderDelay;
|
int encoderDelay = startUs != 0 ? 0 : format.encoderDelay;
|
||||||
@ -328,7 +335,5 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
}
|
}
|
||||||
return childStream.skipData(positionUs);
|
return childStream.skipData(positionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source;
|
package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
@ -86,9 +87,9 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
|||||||
private final ArrayList<ClippingMediaPeriod> mediaPeriods;
|
private final ArrayList<ClippingMediaPeriod> mediaPeriods;
|
||||||
private final Timeline.Window window;
|
private final Timeline.Window window;
|
||||||
|
|
||||||
private @Nullable Object manifest;
|
@Nullable private Object manifest;
|
||||||
private ClippingTimeline clippingTimeline;
|
@Nullable private ClippingTimeline clippingTimeline;
|
||||||
private IllegalClippingException clippingError;
|
@Nullable private IllegalClippingException clippingError;
|
||||||
private long periodStartUs;
|
private long periodStartUs;
|
||||||
private long periodEndUs;
|
private long periodEndUs;
|
||||||
|
|
||||||
@ -222,7 +223,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
|||||||
Assertions.checkState(mediaPeriods.remove(mediaPeriod));
|
Assertions.checkState(mediaPeriods.remove(mediaPeriod));
|
||||||
mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod);
|
mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod);
|
||||||
if (mediaPeriods.isEmpty() && !allowDynamicClippingUpdates) {
|
if (mediaPeriods.isEmpty() && !allowDynamicClippingUpdates) {
|
||||||
refreshClippedTimeline(clippingTimeline.timeline);
|
refreshClippedTimeline(Assertions.checkNotNull(clippingTimeline).timeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source;
|
package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.Util.castNonNull;
|
||||||
|
|
||||||
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.SeekParameters;
|
import com.google.android.exoplayer2.SeekParameters;
|
||||||
@ -22,6 +24,7 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
|||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Media period that wraps a media source and defers calling its {@link
|
* Media period that wraps a media source and defers calling its {@link
|
||||||
@ -47,10 +50,10 @@ public final class DeferredMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
|
|
||||||
private final Allocator allocator;
|
private final Allocator allocator;
|
||||||
|
|
||||||
private MediaPeriod mediaPeriod;
|
@Nullable private MediaPeriod mediaPeriod;
|
||||||
private Callback callback;
|
@Nullable private Callback callback;
|
||||||
private long preparePositionUs;
|
private long preparePositionUs;
|
||||||
private @Nullable PrepareErrorListener listener;
|
@Nullable private PrepareErrorListener listener;
|
||||||
private boolean notifiedPrepareError;
|
private boolean notifiedPrepareError;
|
||||||
private long preparePositionOverrideUs;
|
private long preparePositionOverrideUs;
|
||||||
|
|
||||||
@ -150,53 +153,57 @@ public final class DeferredMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackGroupArray getTrackGroups() {
|
public TrackGroupArray getTrackGroups() {
|
||||||
return mediaPeriod.getTrackGroups();
|
return castNonNull(mediaPeriod).getTrackGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
public long selectTracks(
|
||||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
@NullableType TrackSelection[] selections,
|
||||||
|
boolean[] mayRetainStreamFlags,
|
||||||
|
@NullableType SampleStream[] streams,
|
||||||
|
boolean[] streamResetFlags,
|
||||||
|
long positionUs) {
|
||||||
if (preparePositionOverrideUs != C.TIME_UNSET && positionUs == preparePositionUs) {
|
if (preparePositionOverrideUs != C.TIME_UNSET && positionUs == preparePositionUs) {
|
||||||
positionUs = preparePositionOverrideUs;
|
positionUs = preparePositionOverrideUs;
|
||||||
preparePositionOverrideUs = C.TIME_UNSET;
|
preparePositionOverrideUs = C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
return mediaPeriod.selectTracks(selections, mayRetainStreamFlags, streams, streamResetFlags,
|
return castNonNull(mediaPeriod)
|
||||||
positionUs);
|
.selectTracks(selections, mayRetainStreamFlags, streams, streamResetFlags, positionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void discardBuffer(long positionUs, boolean toKeyframe) {
|
public void discardBuffer(long positionUs, boolean toKeyframe) {
|
||||||
mediaPeriod.discardBuffer(positionUs, toKeyframe);
|
castNonNull(mediaPeriod).discardBuffer(positionUs, toKeyframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long readDiscontinuity() {
|
public long readDiscontinuity() {
|
||||||
return mediaPeriod.readDiscontinuity();
|
return castNonNull(mediaPeriod).readDiscontinuity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getBufferedPositionUs() {
|
public long getBufferedPositionUs() {
|
||||||
return mediaPeriod.getBufferedPositionUs();
|
return castNonNull(mediaPeriod).getBufferedPositionUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long seekToUs(long positionUs) {
|
public long seekToUs(long positionUs) {
|
||||||
return mediaPeriod.seekToUs(positionUs);
|
return castNonNull(mediaPeriod).seekToUs(positionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
|
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
|
||||||
return mediaPeriod.getAdjustedSeekPositionUs(positionUs, seekParameters);
|
return castNonNull(mediaPeriod).getAdjustedSeekPositionUs(positionUs, seekParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getNextLoadPositionUs() {
|
public long getNextLoadPositionUs() {
|
||||||
return mediaPeriod.getNextLoadPositionUs();
|
return castNonNull(mediaPeriod).getNextLoadPositionUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reevaluateBuffer(long positionUs) {
|
public void reevaluateBuffer(long positionUs) {
|
||||||
mediaPeriod.reevaluateBuffer(positionUs);
|
castNonNull(mediaPeriod).reevaluateBuffer(positionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -206,14 +213,14 @@ public final class DeferredMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
callback.onContinueLoadingRequested(this);
|
castNonNull(callback).onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MediaPeriod.Callback implementation
|
// MediaPeriod.Callback implementation
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||||
callback.onPrepared(this);
|
castNonNull(callback).onPrepared(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getPreparePositionWithOverride(long preparePositionUs) {
|
private long getPreparePositionWithOverride(long preparePositionUs) {
|
||||||
|
@ -242,8 +242,8 @@ public final class ExtractorMediaSource extends BaseMediaSource
|
|||||||
Uri uri,
|
Uri uri,
|
||||||
DataSource.Factory dataSourceFactory,
|
DataSource.Factory dataSourceFactory,
|
||||||
ExtractorsFactory extractorsFactory,
|
ExtractorsFactory extractorsFactory,
|
||||||
Handler eventHandler,
|
@Nullable Handler eventHandler,
|
||||||
EventListener eventListener) {
|
@Nullable EventListener eventListener) {
|
||||||
this(uri, dataSourceFactory, extractorsFactory, eventHandler, eventListener, null);
|
this(uri, dataSourceFactory, extractorsFactory, eventHandler, eventListener, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,9 +264,9 @@ public final class ExtractorMediaSource extends BaseMediaSource
|
|||||||
Uri uri,
|
Uri uri,
|
||||||
DataSource.Factory dataSourceFactory,
|
DataSource.Factory dataSourceFactory,
|
||||||
ExtractorsFactory extractorsFactory,
|
ExtractorsFactory extractorsFactory,
|
||||||
Handler eventHandler,
|
@Nullable Handler eventHandler,
|
||||||
EventListener eventListener,
|
@Nullable EventListener eventListener,
|
||||||
String customCacheKey) {
|
@Nullable String customCacheKey) {
|
||||||
this(
|
this(
|
||||||
uri,
|
uri,
|
||||||
dataSourceFactory,
|
dataSourceFactory,
|
||||||
@ -296,9 +296,9 @@ public final class ExtractorMediaSource extends BaseMediaSource
|
|||||||
Uri uri,
|
Uri uri,
|
||||||
DataSource.Factory dataSourceFactory,
|
DataSource.Factory dataSourceFactory,
|
||||||
ExtractorsFactory extractorsFactory,
|
ExtractorsFactory extractorsFactory,
|
||||||
Handler eventHandler,
|
@Nullable Handler eventHandler,
|
||||||
EventListener eventListener,
|
@Nullable EventListener eventListener,
|
||||||
String customCacheKey,
|
@Nullable String customCacheKey,
|
||||||
int continueLoadingCheckIntervalBytes) {
|
int continueLoadingCheckIntervalBytes) {
|
||||||
this(
|
this(
|
||||||
uri,
|
uri,
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source;
|
package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.SeekParameters;
|
import com.google.android.exoplayer2.SeekParameters;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
@ -23,6 +24,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges multiple {@link MediaPeriod}s.
|
* Merges multiple {@link MediaPeriod}s.
|
||||||
@ -35,9 +37,8 @@ import java.util.IdentityHashMap;
|
|||||||
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
|
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
|
||||||
private final ArrayList<MediaPeriod> childrenPendingPreparation;
|
private final ArrayList<MediaPeriod> childrenPendingPreparation;
|
||||||
|
|
||||||
private Callback callback;
|
@Nullable private Callback callback;
|
||||||
private TrackGroupArray trackGroups;
|
@Nullable private TrackGroupArray trackGroups;
|
||||||
|
|
||||||
private MediaPeriod[] enabledPeriods;
|
private MediaPeriod[] enabledPeriods;
|
||||||
private SequenceableLoader compositeSequenceableLoader;
|
private SequenceableLoader compositeSequenceableLoader;
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ import java.util.IdentityHashMap;
|
|||||||
compositeSequenceableLoader =
|
compositeSequenceableLoader =
|
||||||
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader();
|
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader();
|
||||||
streamPeriodIndices = new IdentityHashMap<>();
|
streamPeriodIndices = new IdentityHashMap<>();
|
||||||
|
enabledPeriods = new MediaPeriod[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,12 +71,16 @@ import java.util.IdentityHashMap;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackGroupArray getTrackGroups() {
|
public TrackGroupArray getTrackGroups() {
|
||||||
return trackGroups;
|
return Assertions.checkNotNull(trackGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
public long selectTracks(
|
||||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
@NullableType TrackSelection[] selections,
|
||||||
|
boolean[] mayRetainStreamFlags,
|
||||||
|
@NullableType SampleStream[] streams,
|
||||||
|
boolean[] streamResetFlags,
|
||||||
|
long positionUs) {
|
||||||
// Map each selection and stream onto a child period index.
|
// Map each selection and stream onto a child period index.
|
||||||
int[] streamChildIndices = new int[selections.length];
|
int[] streamChildIndices = new int[selections.length];
|
||||||
int[] selectionChildIndices = new int[selections.length];
|
int[] selectionChildIndices = new int[selections.length];
|
||||||
@ -94,9 +100,9 @@ import java.util.IdentityHashMap;
|
|||||||
}
|
}
|
||||||
streamPeriodIndices.clear();
|
streamPeriodIndices.clear();
|
||||||
// Select tracks for each child, copying the resulting streams back into a new streams array.
|
// Select tracks for each child, copying the resulting streams back into a new streams array.
|
||||||
SampleStream[] newStreams = new SampleStream[selections.length];
|
@NullableType SampleStream[] newStreams = new SampleStream[selections.length];
|
||||||
SampleStream[] childStreams = new SampleStream[selections.length];
|
@NullableType SampleStream[] childStreams = new SampleStream[selections.length];
|
||||||
TrackSelection[] childSelections = new TrackSelection[selections.length];
|
@NullableType TrackSelection[] childSelections = new TrackSelection[selections.length];
|
||||||
ArrayList<MediaPeriod> enabledPeriodsList = new ArrayList<>(periods.length);
|
ArrayList<MediaPeriod> enabledPeriodsList = new ArrayList<>(periods.length);
|
||||||
for (int i = 0; i < periods.length; i++) {
|
for (int i = 0; i < periods.length; i++) {
|
||||||
for (int j = 0; j < selections.length; j++) {
|
for (int j = 0; j < selections.length; j++) {
|
||||||
@ -114,10 +120,10 @@ import java.util.IdentityHashMap;
|
|||||||
for (int j = 0; j < selections.length; j++) {
|
for (int j = 0; j < selections.length; j++) {
|
||||||
if (selectionChildIndices[j] == i) {
|
if (selectionChildIndices[j] == i) {
|
||||||
// Assert that the child provided a stream for the selection.
|
// Assert that the child provided a stream for the selection.
|
||||||
Assertions.checkState(childStreams[j] != null);
|
SampleStream childStream = Assertions.checkNotNull(childStreams[j]);
|
||||||
newStreams[j] = childStreams[j];
|
newStreams[j] = childStreams[j];
|
||||||
periodEnabled = true;
|
periodEnabled = true;
|
||||||
streamPeriodIndices.put(childStreams[j], i);
|
streamPeriodIndices.put(childStream, i);
|
||||||
} else if (streamChildIndices[j] == i) {
|
} else if (streamChildIndices[j] == i) {
|
||||||
// Assert that the child cleared any previous stream.
|
// Assert that the child cleared any previous stream.
|
||||||
Assertions.checkState(childStreams[j] == null);
|
Assertions.checkState(childStreams[j] == null);
|
||||||
@ -208,7 +214,8 @@ import java.util.IdentityHashMap;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
|
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
|
||||||
return enabledPeriods[0].getAdjustedSeekPositionUs(positionUs, seekParameters);
|
MediaPeriod queryPeriod = enabledPeriods.length > 0 ? enabledPeriods[0] : periods[0];
|
||||||
|
return queryPeriod.getAdjustedSeekPositionUs(positionUs, seekParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MediaPeriod.Callback implementation
|
// MediaPeriod.Callback implementation
|
||||||
@ -233,12 +240,12 @@ import java.util.IdentityHashMap;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||||
callback.onPrepared(this);
|
Assertions.checkNotNull(callback).onPrepared(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod ignored) {
|
public void onContinueLoadingRequested(MediaPeriod ignored) {
|
||||||
callback.onContinueLoadingRequested(this);
|
Assertions.checkNotNull(callback).onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,9 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
|
|||||||
private final ArrayList<MediaSource> pendingTimelineSources;
|
private final ArrayList<MediaSource> pendingTimelineSources;
|
||||||
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
|
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
|
||||||
|
|
||||||
private Object primaryManifest;
|
@Nullable private Object primaryManifest;
|
||||||
private int periodCount;
|
private int periodCount;
|
||||||
private IllegalMergeException mergeError;
|
@Nullable private IllegalMergeException mergeError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mediaSources The {@link MediaSource}s to merge.
|
* @param mediaSources The {@link MediaSource}s to merge.
|
||||||
@ -170,11 +170,13 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @Nullable MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
@Nullable
|
||||||
|
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
||||||
Integer id, MediaPeriodId mediaPeriodId) {
|
Integer id, MediaPeriodId mediaPeriodId) {
|
||||||
return id == 0 ? mediaPeriodId : null;
|
return id == 0 ? mediaPeriodId : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private IllegalMergeException checkTimelineMerges(Timeline timeline) {
|
private IllegalMergeException checkTimelineMerges(Timeline timeline) {
|
||||||
if (periodCount == PERIOD_COUNT_UNSET) {
|
if (periodCount == PERIOD_COUNT_UNSET) {
|
||||||
periodCount = timeline.getPeriodCount();
|
periodCount = timeline.getPeriodCount();
|
||||||
|
@ -31,11 +31,14 @@ import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
|
|||||||
import com.google.android.exoplayer2.upstream.Loader.Loadable;
|
import com.google.android.exoplayer2.upstream.Loader.Loadable;
|
||||||
import com.google.android.exoplayer2.upstream.StatsDataSource;
|
import com.google.android.exoplayer2.upstream.StatsDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||||
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MediaPeriod} with a single sample.
|
* A {@link MediaPeriod} with a single sample.
|
||||||
@ -64,8 +67,7 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
/* package */ boolean notifiedReadingStarted;
|
/* package */ boolean notifiedReadingStarted;
|
||||||
/* package */ boolean loadingFinished;
|
/* package */ boolean loadingFinished;
|
||||||
/* package */ boolean loadingSucceeded;
|
/* package */ byte @MonotonicNonNull [] sampleData;
|
||||||
/* package */ byte[] sampleData;
|
|
||||||
/* package */ int sampleSize;
|
/* package */ int sampleSize;
|
||||||
|
|
||||||
public SingleSampleMediaPeriod(
|
public SingleSampleMediaPeriod(
|
||||||
@ -112,8 +114,12 @@ import java.util.Arrays;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
public long selectTracks(
|
||||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
@NullableType TrackSelection[] selections,
|
||||||
|
boolean[] mayRetainStreamFlags,
|
||||||
|
@NullableType SampleStream[] streams,
|
||||||
|
boolean[] streamResetFlags,
|
||||||
|
long positionUs) {
|
||||||
for (int i = 0; i < selections.length; i++) {
|
for (int i = 0; i < selections.length; i++) {
|
||||||
if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) {
|
if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) {
|
||||||
sampleStreams.remove(streams[i]);
|
sampleStreams.remove(streams[i]);
|
||||||
@ -204,9 +210,8 @@ import java.util.Arrays;
|
|||||||
public void onLoadCompleted(SourceLoadable loadable, long elapsedRealtimeMs,
|
public void onLoadCompleted(SourceLoadable loadable, long elapsedRealtimeMs,
|
||||||
long loadDurationMs) {
|
long loadDurationMs) {
|
||||||
sampleSize = (int) loadable.dataSource.getBytesRead();
|
sampleSize = (int) loadable.dataSource.getBytesRead();
|
||||||
sampleData = loadable.sampleData;
|
sampleData = Assertions.checkNotNull(loadable.sampleData);
|
||||||
loadingFinished = true;
|
loadingFinished = true;
|
||||||
loadingSucceeded = true;
|
|
||||||
eventDispatcher.loadCompleted(
|
eventDispatcher.loadCompleted(
|
||||||
loadable.dataSpec,
|
loadable.dataSpec,
|
||||||
loadable.dataSource.getLastOpenedUri(),
|
loadable.dataSource.getLastOpenedUri(),
|
||||||
@ -325,7 +330,7 @@ import java.util.Arrays;
|
|||||||
streamState = STREAM_STATE_SEND_SAMPLE;
|
streamState = STREAM_STATE_SEND_SAMPLE;
|
||||||
return C.RESULT_FORMAT_READ;
|
return C.RESULT_FORMAT_READ;
|
||||||
} else if (loadingFinished) {
|
} else if (loadingFinished) {
|
||||||
if (loadingSucceeded) {
|
if (sampleData != null) {
|
||||||
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
||||||
buffer.timeUs = 0;
|
buffer.timeUs = 0;
|
||||||
if (buffer.isFlagsOnly()) {
|
if (buffer.isFlagsOnly()) {
|
||||||
@ -371,7 +376,7 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
private final StatsDataSource dataSource;
|
private final StatsDataSource dataSource;
|
||||||
|
|
||||||
private byte[] sampleData;
|
@Nullable private byte[] sampleData;
|
||||||
|
|
||||||
public SourceLoadable(DataSpec dataSpec, DataSource dataSource) {
|
public SourceLoadable(DataSpec dataSpec, DataSource dataSource) {
|
||||||
this.dataSpec = dataSpec;
|
this.dataSpec = dataSpec;
|
||||||
|
@ -18,12 +18,15 @@ package com.google.android.exoplayer2.source.ads;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.annotation.CheckResult;
|
import androidx.annotation.CheckResult;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents ad group times relative to the start of the media and information on the state and
|
* Represents ad group times relative to the start of the media and information on the state and
|
||||||
@ -45,9 +48,9 @@ public final class AdPlaybackState {
|
|||||||
/** The number of ads in the ad group, or {@link C#LENGTH_UNSET} if unknown. */
|
/** The number of ads in the ad group, or {@link C#LENGTH_UNSET} if unknown. */
|
||||||
public final int count;
|
public final int count;
|
||||||
/** The URI of each ad in the ad group. */
|
/** The URI of each ad in the ad group. */
|
||||||
public final Uri[] uris;
|
public final @NullableType Uri[] uris;
|
||||||
/** The state of each ad in the ad group. */
|
/** The state of each ad in the ad group. */
|
||||||
public final @AdState int[] states;
|
@AdState public final int[] states;
|
||||||
/** The durations of each ad in the ad group, in microseconds. */
|
/** The durations of each ad in the ad group, in microseconds. */
|
||||||
public final long[] durationsUs;
|
public final long[] durationsUs;
|
||||||
|
|
||||||
@ -60,7 +63,8 @@ public final class AdPlaybackState {
|
|||||||
/* durationsUs= */ new long[0]);
|
/* durationsUs= */ new long[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AdGroup(int count, @AdState int[] states, Uri[] uris, long[] durationsUs) {
|
private AdGroup(
|
||||||
|
int count, @AdState int[] states, @NullableType Uri[] uris, long[] durationsUs) {
|
||||||
Assertions.checkArgument(states.length == uris.length);
|
Assertions.checkArgument(states.length == uris.length);
|
||||||
this.count = count;
|
this.count = count;
|
||||||
this.states = states;
|
this.states = states;
|
||||||
@ -98,7 +102,7 @@ public final class AdPlaybackState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(@Nullable Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -130,7 +134,7 @@ public final class AdPlaybackState {
|
|||||||
Assertions.checkArgument(this.count == C.LENGTH_UNSET && states.length <= count);
|
Assertions.checkArgument(this.count == C.LENGTH_UNSET && states.length <= count);
|
||||||
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, count);
|
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, count);
|
||||||
long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count);
|
long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count);
|
||||||
Uri[] uris = Arrays.copyOf(this.uris, count);
|
@NullableType Uri[] uris = Arrays.copyOf(this.uris, count);
|
||||||
return new AdGroup(count, states, uris, durationsUs);
|
return new AdGroup(count, states, uris, durationsUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +155,7 @@ public final class AdPlaybackState {
|
|||||||
this.durationsUs.length == states.length
|
this.durationsUs.length == states.length
|
||||||
? this.durationsUs
|
? this.durationsUs
|
||||||
: copyDurationsUsWithSpaceForAdCount(this.durationsUs, states.length);
|
: copyDurationsUsWithSpaceForAdCount(this.durationsUs, states.length);
|
||||||
Uri[] uris = Arrays.copyOf(this.uris, states.length);
|
@NullableType Uri[] uris = Arrays.copyOf(this.uris, states.length);
|
||||||
uris[index] = uri;
|
uris[index] = uri;
|
||||||
states[index] = AD_STATE_AVAILABLE;
|
states[index] = AD_STATE_AVAILABLE;
|
||||||
return new AdGroup(count, states, uris, durationsUs);
|
return new AdGroup(count, states, uris, durationsUs);
|
||||||
@ -177,6 +181,7 @@ public final class AdPlaybackState {
|
|||||||
this.durationsUs.length == states.length
|
this.durationsUs.length == states.length
|
||||||
? this.durationsUs
|
? this.durationsUs
|
||||||
: copyDurationsUsWithSpaceForAdCount(this.durationsUs, states.length);
|
: copyDurationsUsWithSpaceForAdCount(this.durationsUs, states.length);
|
||||||
|
@NullableType
|
||||||
Uri[] uris =
|
Uri[] uris =
|
||||||
this.uris.length == states.length ? this.uris : Arrays.copyOf(this.uris, states.length);
|
this.uris.length == states.length ? this.uris : Arrays.copyOf(this.uris, states.length);
|
||||||
states[index] = state;
|
states[index] = state;
|
||||||
@ -362,7 +367,7 @@ public final class AdPlaybackState {
|
|||||||
if (adGroups[adGroupIndex].count == adCount) {
|
if (adGroups[adGroupIndex].count == adCount) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
AdGroup[] adGroups = Arrays.copyOf(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
adGroups[adGroupIndex] = this.adGroups[adGroupIndex].withAdCount(adCount);
|
adGroups[adGroupIndex] = this.adGroups[adGroupIndex].withAdCount(adCount);
|
||||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
}
|
}
|
||||||
@ -370,7 +375,7 @@ public final class AdPlaybackState {
|
|||||||
/** Returns an instance with the specified ad URI. */
|
/** Returns an instance with the specified ad URI. */
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withAdUri(int adGroupIndex, int adIndexInAdGroup, Uri uri) {
|
public AdPlaybackState withAdUri(int adGroupIndex, int adIndexInAdGroup, Uri uri) {
|
||||||
AdGroup[] adGroups = Arrays.copyOf(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdUri(uri, adIndexInAdGroup);
|
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdUri(uri, adIndexInAdGroup);
|
||||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
}
|
}
|
||||||
@ -378,7 +383,7 @@ public final class AdPlaybackState {
|
|||||||
/** Returns an instance with the specified ad marked as played. */
|
/** Returns an instance with the specified ad marked as played. */
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withPlayedAd(int adGroupIndex, int adIndexInAdGroup) {
|
public AdPlaybackState withPlayedAd(int adGroupIndex, int adIndexInAdGroup) {
|
||||||
AdGroup[] adGroups = Arrays.copyOf(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_PLAYED, adIndexInAdGroup);
|
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_PLAYED, adIndexInAdGroup);
|
||||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
}
|
}
|
||||||
@ -386,7 +391,7 @@ public final class AdPlaybackState {
|
|||||||
/** Returns an instance with the specified ad marked as skipped. */
|
/** Returns an instance with the specified ad marked as skipped. */
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withSkippedAd(int adGroupIndex, int adIndexInAdGroup) {
|
public AdPlaybackState withSkippedAd(int adGroupIndex, int adIndexInAdGroup) {
|
||||||
AdGroup[] adGroups = Arrays.copyOf(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_SKIPPED, adIndexInAdGroup);
|
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_SKIPPED, adIndexInAdGroup);
|
||||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
}
|
}
|
||||||
@ -394,7 +399,7 @@ public final class AdPlaybackState {
|
|||||||
/** Returns an instance with the specified ad marked as having a load error. */
|
/** Returns an instance with the specified ad marked as having a load error. */
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withAdLoadError(int adGroupIndex, int adIndexInAdGroup) {
|
public AdPlaybackState withAdLoadError(int adGroupIndex, int adIndexInAdGroup) {
|
||||||
AdGroup[] adGroups = Arrays.copyOf(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_ERROR, adIndexInAdGroup);
|
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_ERROR, adIndexInAdGroup);
|
||||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
}
|
}
|
||||||
@ -405,7 +410,7 @@ public final class AdPlaybackState {
|
|||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withSkippedAdGroup(int adGroupIndex) {
|
public AdPlaybackState withSkippedAdGroup(int adGroupIndex) {
|
||||||
AdGroup[] adGroups = Arrays.copyOf(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAllAdsSkipped();
|
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAllAdsSkipped();
|
||||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
}
|
}
|
||||||
@ -413,7 +418,7 @@ public final class AdPlaybackState {
|
|||||||
/** Returns an instance with the specified ad durations, in microseconds. */
|
/** Returns an instance with the specified ad durations, in microseconds. */
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withAdDurationsUs(long[][] adDurationUs) {
|
public AdPlaybackState withAdDurationsUs(long[][] adDurationUs) {
|
||||||
AdGroup[] adGroups = Arrays.copyOf(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
for (int adGroupIndex = 0; adGroupIndex < adGroupCount; adGroupIndex++) {
|
for (int adGroupIndex = 0; adGroupIndex < adGroupCount; adGroupIndex++) {
|
||||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdDurationsUs(adDurationUs[adGroupIndex]);
|
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdDurationsUs(adDurationUs[adGroupIndex]);
|
||||||
}
|
}
|
||||||
@ -441,7 +446,7 @@ public final class AdPlaybackState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(@Nullable Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MediaSource} that inserts ads linearly with a provided content media source. This source
|
* A {@link MediaSource} that inserts ads linearly with a provided content media source. This source
|
||||||
@ -114,7 +115,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
*/
|
*/
|
||||||
public RuntimeException getRuntimeExceptionForUnexpected() {
|
public RuntimeException getRuntimeExceptionForUnexpected() {
|
||||||
Assertions.checkState(type == TYPE_UNEXPECTED);
|
Assertions.checkState(type == TYPE_UNEXPECTED);
|
||||||
return (RuntimeException) getCause();
|
return (RuntimeException) Assertions.checkNotNull(getCause());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,12 +132,12 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
|
|
||||||
// Accessed on the player thread.
|
// Accessed on the player thread.
|
||||||
private ComponentListener componentListener;
|
@Nullable private ComponentListener componentListener;
|
||||||
private Timeline contentTimeline;
|
@Nullable private Timeline contentTimeline;
|
||||||
private Object contentManifest;
|
@Nullable private Object contentManifest;
|
||||||
private AdPlaybackState adPlaybackState;
|
@Nullable private AdPlaybackState adPlaybackState;
|
||||||
private MediaSource[][] adGroupMediaSources;
|
private @NullableType MediaSource[][] adGroupMediaSources;
|
||||||
private Timeline[][] adGroupTimelines;
|
private @NullableType Timeline[][] adGroupTimelines;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new source that inserts ads linearly with the content specified by {@code
|
* Constructs a new source that inserts ads linearly with the content specified by {@code
|
||||||
@ -202,24 +203,25 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
||||||
|
AdPlaybackState adPlaybackState = Assertions.checkNotNull(this.adPlaybackState);
|
||||||
if (adPlaybackState.adGroupCount > 0 && id.isAd()) {
|
if (adPlaybackState.adGroupCount > 0 && id.isAd()) {
|
||||||
int adGroupIndex = id.adGroupIndex;
|
int adGroupIndex = id.adGroupIndex;
|
||||||
int adIndexInAdGroup = id.adIndexInAdGroup;
|
int adIndexInAdGroup = id.adIndexInAdGroup;
|
||||||
Uri adUri = adPlaybackState.adGroups[adGroupIndex].uris[adIndexInAdGroup];
|
Uri adUri =
|
||||||
|
Assertions.checkNotNull(adPlaybackState.adGroups[adGroupIndex].uris[adIndexInAdGroup]);
|
||||||
if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) {
|
if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) {
|
||||||
MediaSource adMediaSource = adMediaSourceFactory.createMediaSource(adUri);
|
int adCount = adIndexInAdGroup + 1;
|
||||||
int oldAdCount = adGroupMediaSources[adGroupIndex].length;
|
adGroupMediaSources[adGroupIndex] =
|
||||||
if (adIndexInAdGroup >= oldAdCount) {
|
Arrays.copyOf(adGroupMediaSources[adGroupIndex], adCount);
|
||||||
int adCount = adIndexInAdGroup + 1;
|
adGroupTimelines[adGroupIndex] = Arrays.copyOf(adGroupTimelines[adGroupIndex], adCount);
|
||||||
adGroupMediaSources[adGroupIndex] =
|
|
||||||
Arrays.copyOf(adGroupMediaSources[adGroupIndex], adCount);
|
|
||||||
adGroupTimelines[adGroupIndex] = Arrays.copyOf(adGroupTimelines[adGroupIndex], adCount);
|
|
||||||
}
|
|
||||||
adGroupMediaSources[adGroupIndex][adIndexInAdGroup] = adMediaSource;
|
|
||||||
deferredMediaPeriodByAdMediaSource.put(adMediaSource, new ArrayList<>());
|
|
||||||
prepareChildSource(id, adMediaSource);
|
|
||||||
}
|
}
|
||||||
MediaSource mediaSource = adGroupMediaSources[adGroupIndex][adIndexInAdGroup];
|
MediaSource mediaSource = adGroupMediaSources[adGroupIndex][adIndexInAdGroup];
|
||||||
|
if (mediaSource == null) {
|
||||||
|
mediaSource = adMediaSourceFactory.createMediaSource(adUri);
|
||||||
|
adGroupMediaSources[adGroupIndex][adIndexInAdGroup] = mediaSource;
|
||||||
|
deferredMediaPeriodByAdMediaSource.put(mediaSource, new ArrayList<>());
|
||||||
|
prepareChildSource(id, mediaSource);
|
||||||
|
}
|
||||||
DeferredMediaPeriod deferredMediaPeriod =
|
DeferredMediaPeriod deferredMediaPeriod =
|
||||||
new DeferredMediaPeriod(mediaSource, id, allocator, startPositionUs);
|
new DeferredMediaPeriod(mediaSource, id, allocator, startPositionUs);
|
||||||
deferredMediaPeriod.setPrepareErrorListener(
|
deferredMediaPeriod.setPrepareErrorListener(
|
||||||
@ -227,7 +229,8 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.get(mediaSource);
|
List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.get(mediaSource);
|
||||||
if (mediaPeriods == null) {
|
if (mediaPeriods == null) {
|
||||||
Object periodUid =
|
Object periodUid =
|
||||||
adGroupTimelines[adGroupIndex][adIndexInAdGroup].getUidOfPeriod(/* periodIndex= */ 0);
|
Assertions.checkNotNull(adGroupTimelines[adGroupIndex][adIndexInAdGroup])
|
||||||
|
.getUidOfPeriod(/* periodIndex= */ 0);
|
||||||
MediaPeriodId adSourceMediaPeriodId = new MediaPeriodId(periodUid, id.windowSequenceNumber);
|
MediaPeriodId adSourceMediaPeriodId = new MediaPeriodId(periodUid, id.windowSequenceNumber);
|
||||||
deferredMediaPeriod.createPeriod(adSourceMediaPeriodId);
|
deferredMediaPeriod.createPeriod(adSourceMediaPeriodId);
|
||||||
} else {
|
} else {
|
||||||
@ -258,7 +261,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
@Override
|
@Override
|
||||||
public void releaseSourceInternal() {
|
public void releaseSourceInternal() {
|
||||||
super.releaseSourceInternal();
|
super.releaseSourceInternal();
|
||||||
componentListener.release();
|
Assertions.checkNotNull(componentListener).release();
|
||||||
componentListener = null;
|
componentListener = null;
|
||||||
deferredMediaPeriodByAdMediaSource.clear();
|
deferredMediaPeriodByAdMediaSource.clear();
|
||||||
contentTimeline = null;
|
contentTimeline = null;
|
||||||
@ -305,7 +308,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
maybeUpdateSourceInfo();
|
maybeUpdateSourceInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onContentSourceInfoRefreshed(Timeline timeline, Object manifest) {
|
private void onContentSourceInfoRefreshed(Timeline timeline, @Nullable Object manifest) {
|
||||||
Assertions.checkArgument(timeline.getPeriodCount() == 1);
|
Assertions.checkArgument(timeline.getPeriodCount() == 1);
|
||||||
contentTimeline = timeline;
|
contentTimeline = timeline;
|
||||||
contentManifest = manifest;
|
contentManifest = manifest;
|
||||||
@ -330,6 +333,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void maybeUpdateSourceInfo() {
|
private void maybeUpdateSourceInfo() {
|
||||||
|
Timeline contentTimeline = this.contentTimeline;
|
||||||
if (adPlaybackState != null && contentTimeline != null) {
|
if (adPlaybackState != null && contentTimeline != null) {
|
||||||
adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurations(adGroupTimelines, period));
|
adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurations(adGroupTimelines, period));
|
||||||
Timeline timeline =
|
Timeline timeline =
|
||||||
@ -340,7 +344,8 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long[][] getAdDurations(Timeline[][] adTimelines, Timeline.Period period) {
|
private static long[][] getAdDurations(
|
||||||
|
@NullableType Timeline[][] adTimelines, Timeline.Period period) {
|
||||||
long[][] adDurations = new long[adTimelines.length][];
|
long[][] adDurations = new long[adTimelines.length][];
|
||||||
for (int i = 0; i < adTimelines.length; i++) {
|
for (int i = 0; i < adTimelines.length; i++) {
|
||||||
adDurations[i] = new long[adTimelines[i].length];
|
adDurations[i] = new long[adTimelines[i].length];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user