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.Player;
|
||||
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.
|
||||
@ -35,6 +36,7 @@ import com.google.android.exoplayer2.Timeline;
|
||||
* @param concatenatedUid UID of a period in a concatenated timeline.
|
||||
* @return UID of the child timeline this period belongs to.
|
||||
*/
|
||||
@SuppressWarnings("nullness:return.type.incompatible")
|
||||
public static Object getChildTimelineUidFromConcatenatedUid(Object concatenatedUid) {
|
||||
return ((Pair<?, ?>) concatenatedUid).first;
|
||||
}
|
||||
@ -45,6 +47,7 @@ import com.google.android.exoplayer2.Timeline;
|
||||
* @param concatenatedUid UID of a period in a concatenated timeline.
|
||||
* @return UID of the period in the child timeline.
|
||||
*/
|
||||
@SuppressWarnings("nullness:return.type.incompatible")
|
||||
public static Object getChildPeriodUidFromConcatenatedUid(Object concatenatedUid) {
|
||||
return ((Pair<?, ?>) concatenatedUid).second;
|
||||
}
|
||||
@ -220,7 +223,9 @@ import com.google.android.exoplayer2.Timeline;
|
||||
setIds);
|
||||
period.windowIndex += firstWindowIndexInChild;
|
||||
if (setIds) {
|
||||
period.uid = getConcatenatedUid(getChildUidByChildIndex(childIndex), period.uid);
|
||||
period.uid =
|
||||
getConcatenatedUid(
|
||||
getChildUidByChildIndex(childIndex), Assertions.checkNotNull(period.uid));
|
||||
}
|
||||
return period;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
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.Util;
|
||||
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
|
||||
@ -37,8 +39,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
*/
|
||||
public final MediaPeriod mediaPeriod;
|
||||
|
||||
private MediaPeriod.Callback callback;
|
||||
private ClippingSampleStream[] sampleStreams;
|
||||
@Nullable private MediaPeriod.Callback callback;
|
||||
private @NullableType ClippingSampleStream[] sampleStreams;
|
||||
private long pendingInitialDiscontinuityPositionUs;
|
||||
/* package */ long startUs;
|
||||
/* package */ long endUs;
|
||||
@ -95,10 +97,14 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
}
|
||||
|
||||
@Override
|
||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
||||
public long selectTracks(
|
||||
@NullableType TrackSelection[] selections,
|
||||
boolean[] mayRetainStreamFlags,
|
||||
@NullableType SampleStream[] streams,
|
||||
boolean[] streamResetFlags,
|
||||
long positionUs) {
|
||||
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++) {
|
||||
sampleStreams[i] = (ClippingSampleStream) streams[i];
|
||||
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++) {
|
||||
if (childStreams[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]);
|
||||
}
|
||||
streams[i] = sampleStreams[i];
|
||||
@ -209,12 +215,12 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||
callback.onPrepared(this);
|
||||
Assertions.checkNotNull(callback).onPrepared(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
callback.onContinueLoadingRequested(this);
|
||||
Assertions.checkNotNull(callback).onContinueLoadingRequested(this);
|
||||
}
|
||||
|
||||
/* 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
|
||||
// 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,
|
||||
@ -300,7 +307,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
}
|
||||
int result = childStream.readData(formatHolder, buffer, requireFormat);
|
||||
if (result == C.RESULT_FORMAT_READ) {
|
||||
Format format = formatHolder.format;
|
||||
Format format = Assertions.checkNotNull(formatHolder.format);
|
||||
if (format.encoderDelay != 0 || format.encoderPadding != 0) {
|
||||
// Clear gapless playback metadata if the start/end points don't match the media.
|
||||
int encoderDelay = startUs != 0 ? 0 : format.encoderDelay;
|
||||
@ -328,7 +335,5 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
}
|
||||
return childStream.skipData(positionUs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
@ -86,9 +87,9 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
private final ArrayList<ClippingMediaPeriod> mediaPeriods;
|
||||
private final Timeline.Window window;
|
||||
|
||||
private @Nullable Object manifest;
|
||||
private ClippingTimeline clippingTimeline;
|
||||
private IllegalClippingException clippingError;
|
||||
@Nullable private Object manifest;
|
||||
@Nullable private ClippingTimeline clippingTimeline;
|
||||
@Nullable private IllegalClippingException clippingError;
|
||||
private long periodStartUs;
|
||||
private long periodEndUs;
|
||||
|
||||
@ -222,7 +223,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
Assertions.checkState(mediaPeriods.remove(mediaPeriod));
|
||||
mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod);
|
||||
if (mediaPeriods.isEmpty() && !allowDynamicClippingUpdates) {
|
||||
refreshClippedTimeline(clippingTimeline.timeline);
|
||||
refreshClippedTimeline(Assertions.checkNotNull(clippingTimeline).timeline);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import static com.google.android.exoplayer2.util.Util.castNonNull;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
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.upstream.Allocator;
|
||||
import java.io.IOException;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
|
||||
/**
|
||||
* 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 MediaPeriod mediaPeriod;
|
||||
private Callback callback;
|
||||
@Nullable private MediaPeriod mediaPeriod;
|
||||
@Nullable private Callback callback;
|
||||
private long preparePositionUs;
|
||||
private @Nullable PrepareErrorListener listener;
|
||||
@Nullable private PrepareErrorListener listener;
|
||||
private boolean notifiedPrepareError;
|
||||
private long preparePositionOverrideUs;
|
||||
|
||||
@ -150,53 +153,57 @@ public final class DeferredMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
|
||||
@Override
|
||||
public TrackGroupArray getTrackGroups() {
|
||||
return mediaPeriod.getTrackGroups();
|
||||
return castNonNull(mediaPeriod).getTrackGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
||||
public long selectTracks(
|
||||
@NullableType TrackSelection[] selections,
|
||||
boolean[] mayRetainStreamFlags,
|
||||
@NullableType SampleStream[] streams,
|
||||
boolean[] streamResetFlags,
|
||||
long positionUs) {
|
||||
if (preparePositionOverrideUs != C.TIME_UNSET && positionUs == preparePositionUs) {
|
||||
positionUs = preparePositionOverrideUs;
|
||||
preparePositionOverrideUs = C.TIME_UNSET;
|
||||
}
|
||||
return mediaPeriod.selectTracks(selections, mayRetainStreamFlags, streams, streamResetFlags,
|
||||
positionUs);
|
||||
return castNonNull(mediaPeriod)
|
||||
.selectTracks(selections, mayRetainStreamFlags, streams, streamResetFlags, positionUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discardBuffer(long positionUs, boolean toKeyframe) {
|
||||
mediaPeriod.discardBuffer(positionUs, toKeyframe);
|
||||
castNonNull(mediaPeriod).discardBuffer(positionUs, toKeyframe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readDiscontinuity() {
|
||||
return mediaPeriod.readDiscontinuity();
|
||||
return castNonNull(mediaPeriod).readDiscontinuity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBufferedPositionUs() {
|
||||
return mediaPeriod.getBufferedPositionUs();
|
||||
return castNonNull(mediaPeriod).getBufferedPositionUs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long seekToUs(long positionUs) {
|
||||
return mediaPeriod.seekToUs(positionUs);
|
||||
return castNonNull(mediaPeriod).seekToUs(positionUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
|
||||
return mediaPeriod.getAdjustedSeekPositionUs(positionUs, seekParameters);
|
||||
return castNonNull(mediaPeriod).getAdjustedSeekPositionUs(positionUs, seekParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNextLoadPositionUs() {
|
||||
return mediaPeriod.getNextLoadPositionUs();
|
||||
return castNonNull(mediaPeriod).getNextLoadPositionUs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reevaluateBuffer(long positionUs) {
|
||||
mediaPeriod.reevaluateBuffer(positionUs);
|
||||
castNonNull(mediaPeriod).reevaluateBuffer(positionUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -206,14 +213,14 @@ public final class DeferredMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
callback.onContinueLoadingRequested(this);
|
||||
castNonNull(callback).onContinueLoadingRequested(this);
|
||||
}
|
||||
|
||||
// MediaPeriod.Callback implementation
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||
callback.onPrepared(this);
|
||||
castNonNull(callback).onPrepared(this);
|
||||
}
|
||||
|
||||
private long getPreparePositionWithOverride(long preparePositionUs) {
|
||||
|
@ -242,8 +242,8 @@ public final class ExtractorMediaSource extends BaseMediaSource
|
||||
Uri uri,
|
||||
DataSource.Factory dataSourceFactory,
|
||||
ExtractorsFactory extractorsFactory,
|
||||
Handler eventHandler,
|
||||
EventListener eventListener) {
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable EventListener eventListener) {
|
||||
this(uri, dataSourceFactory, extractorsFactory, eventHandler, eventListener, null);
|
||||
}
|
||||
|
||||
@ -264,9 +264,9 @@ public final class ExtractorMediaSource extends BaseMediaSource
|
||||
Uri uri,
|
||||
DataSource.Factory dataSourceFactory,
|
||||
ExtractorsFactory extractorsFactory,
|
||||
Handler eventHandler,
|
||||
EventListener eventListener,
|
||||
String customCacheKey) {
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable EventListener eventListener,
|
||||
@Nullable String customCacheKey) {
|
||||
this(
|
||||
uri,
|
||||
dataSourceFactory,
|
||||
@ -296,9 +296,9 @@ public final class ExtractorMediaSource extends BaseMediaSource
|
||||
Uri uri,
|
||||
DataSource.Factory dataSourceFactory,
|
||||
ExtractorsFactory extractorsFactory,
|
||||
Handler eventHandler,
|
||||
EventListener eventListener,
|
||||
String customCacheKey,
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable EventListener eventListener,
|
||||
@Nullable String customCacheKey,
|
||||
int continueLoadingCheckIntervalBytes) {
|
||||
this(
|
||||
uri,
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.SeekParameters;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
@ -23,6 +24,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
|
||||
/**
|
||||
* Merges multiple {@link MediaPeriod}s.
|
||||
@ -35,9 +37,8 @@ import java.util.IdentityHashMap;
|
||||
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
|
||||
private final ArrayList<MediaPeriod> childrenPendingPreparation;
|
||||
|
||||
private Callback callback;
|
||||
private TrackGroupArray trackGroups;
|
||||
|
||||
@Nullable private Callback callback;
|
||||
@Nullable private TrackGroupArray trackGroups;
|
||||
private MediaPeriod[] enabledPeriods;
|
||||
private SequenceableLoader compositeSequenceableLoader;
|
||||
|
||||
@ -49,6 +50,7 @@ import java.util.IdentityHashMap;
|
||||
compositeSequenceableLoader =
|
||||
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader();
|
||||
streamPeriodIndices = new IdentityHashMap<>();
|
||||
enabledPeriods = new MediaPeriod[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -69,12 +71,16 @@ import java.util.IdentityHashMap;
|
||||
|
||||
@Override
|
||||
public TrackGroupArray getTrackGroups() {
|
||||
return trackGroups;
|
||||
return Assertions.checkNotNull(trackGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
||||
public long selectTracks(
|
||||
@NullableType TrackSelection[] selections,
|
||||
boolean[] mayRetainStreamFlags,
|
||||
@NullableType SampleStream[] streams,
|
||||
boolean[] streamResetFlags,
|
||||
long positionUs) {
|
||||
// Map each selection and stream onto a child period index.
|
||||
int[] streamChildIndices = new int[selections.length];
|
||||
int[] selectionChildIndices = new int[selections.length];
|
||||
@ -94,9 +100,9 @@ import java.util.IdentityHashMap;
|
||||
}
|
||||
streamPeriodIndices.clear();
|
||||
// Select tracks for each child, copying the resulting streams back into a new streams array.
|
||||
SampleStream[] newStreams = new SampleStream[selections.length];
|
||||
SampleStream[] childStreams = new SampleStream[selections.length];
|
||||
TrackSelection[] childSelections = new TrackSelection[selections.length];
|
||||
@NullableType SampleStream[] newStreams = new SampleStream[selections.length];
|
||||
@NullableType SampleStream[] childStreams = new SampleStream[selections.length];
|
||||
@NullableType TrackSelection[] childSelections = new TrackSelection[selections.length];
|
||||
ArrayList<MediaPeriod> enabledPeriodsList = new ArrayList<>(periods.length);
|
||||
for (int i = 0; i < periods.length; i++) {
|
||||
for (int j = 0; j < selections.length; j++) {
|
||||
@ -114,10 +120,10 @@ import java.util.IdentityHashMap;
|
||||
for (int j = 0; j < selections.length; j++) {
|
||||
if (selectionChildIndices[j] == i) {
|
||||
// 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];
|
||||
periodEnabled = true;
|
||||
streamPeriodIndices.put(childStreams[j], i);
|
||||
streamPeriodIndices.put(childStream, i);
|
||||
} else if (streamChildIndices[j] == i) {
|
||||
// Assert that the child cleared any previous stream.
|
||||
Assertions.checkState(childStreams[j] == null);
|
||||
@ -208,7 +214,8 @@ import java.util.IdentityHashMap;
|
||||
|
||||
@Override
|
||||
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
|
||||
@ -233,12 +240,12 @@ import java.util.IdentityHashMap;
|
||||
}
|
||||
}
|
||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||
callback.onPrepared(this);
|
||||
Assertions.checkNotNull(callback).onPrepared(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
|
||||
|
||||
private Object primaryManifest;
|
||||
@Nullable private Object primaryManifest;
|
||||
private int periodCount;
|
||||
private IllegalMergeException mergeError;
|
||||
@Nullable private IllegalMergeException mergeError;
|
||||
|
||||
/**
|
||||
* @param mediaSources The {@link MediaSource}s to merge.
|
||||
@ -170,11 +170,13 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
||||
@Nullable
|
||||
protected MediaPeriodId getMediaPeriodIdForChildMediaPeriodId(
|
||||
Integer id, MediaPeriodId mediaPeriodId) {
|
||||
return id == 0 ? mediaPeriodId : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private IllegalMergeException checkTimelineMerges(Timeline timeline) {
|
||||
if (periodCount == PERIOD_COUNT_UNSET) {
|
||||
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.StatsDataSource;
|
||||
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.Util;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
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.
|
||||
@ -64,8 +67,7 @@ import java.util.Arrays;
|
||||
|
||||
/* package */ boolean notifiedReadingStarted;
|
||||
/* package */ boolean loadingFinished;
|
||||
/* package */ boolean loadingSucceeded;
|
||||
/* package */ byte[] sampleData;
|
||||
/* package */ byte @MonotonicNonNull [] sampleData;
|
||||
/* package */ int sampleSize;
|
||||
|
||||
public SingleSampleMediaPeriod(
|
||||
@ -112,8 +114,12 @@ import java.util.Arrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
||||
public long selectTracks(
|
||||
@NullableType TrackSelection[] selections,
|
||||
boolean[] mayRetainStreamFlags,
|
||||
@NullableType SampleStream[] streams,
|
||||
boolean[] streamResetFlags,
|
||||
long positionUs) {
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) {
|
||||
sampleStreams.remove(streams[i]);
|
||||
@ -204,9 +210,8 @@ import java.util.Arrays;
|
||||
public void onLoadCompleted(SourceLoadable loadable, long elapsedRealtimeMs,
|
||||
long loadDurationMs) {
|
||||
sampleSize = (int) loadable.dataSource.getBytesRead();
|
||||
sampleData = loadable.sampleData;
|
||||
sampleData = Assertions.checkNotNull(loadable.sampleData);
|
||||
loadingFinished = true;
|
||||
loadingSucceeded = true;
|
||||
eventDispatcher.loadCompleted(
|
||||
loadable.dataSpec,
|
||||
loadable.dataSource.getLastOpenedUri(),
|
||||
@ -325,7 +330,7 @@ import java.util.Arrays;
|
||||
streamState = STREAM_STATE_SEND_SAMPLE;
|
||||
return C.RESULT_FORMAT_READ;
|
||||
} else if (loadingFinished) {
|
||||
if (loadingSucceeded) {
|
||||
if (sampleData != null) {
|
||||
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
||||
buffer.timeUs = 0;
|
||||
if (buffer.isFlagsOnly()) {
|
||||
@ -371,7 +376,7 @@ import java.util.Arrays;
|
||||
|
||||
private final StatsDataSource dataSource;
|
||||
|
||||
private byte[] sampleData;
|
||||
@Nullable private byte[] sampleData;
|
||||
|
||||
public SourceLoadable(DataSpec dataSpec, DataSource dataSource) {
|
||||
this.dataSpec = dataSpec;
|
||||
|
@ -18,12 +18,15 @@ package com.google.android.exoplayer2.source.ads;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.CheckResult;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
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
|
||||
@ -45,9 +48,9 @@ public final class AdPlaybackState {
|
||||
/** The number of ads in the ad group, or {@link C#LENGTH_UNSET} if unknown. */
|
||||
public final int count;
|
||||
/** 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. */
|
||||
public final @AdState int[] states;
|
||||
@AdState public final int[] states;
|
||||
/** The durations of each ad in the ad group, in microseconds. */
|
||||
public final long[] durationsUs;
|
||||
|
||||
@ -60,7 +63,8 @@ public final class AdPlaybackState {
|
||||
/* 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);
|
||||
this.count = count;
|
||||
this.states = states;
|
||||
@ -98,7 +102,7 @@ public final class AdPlaybackState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@ -130,7 +134,7 @@ public final class AdPlaybackState {
|
||||
Assertions.checkArgument(this.count == C.LENGTH_UNSET && states.length <= count);
|
||||
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, 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);
|
||||
}
|
||||
|
||||
@ -151,7 +155,7 @@ public final class AdPlaybackState {
|
||||
this.durationsUs.length == states.length
|
||||
? this.durationsUs
|
||||
: 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;
|
||||
states[index] = AD_STATE_AVAILABLE;
|
||||
return new AdGroup(count, states, uris, durationsUs);
|
||||
@ -177,6 +181,7 @@ public final class AdPlaybackState {
|
||||
this.durationsUs.length == states.length
|
||||
? this.durationsUs
|
||||
: copyDurationsUsWithSpaceForAdCount(this.durationsUs, states.length);
|
||||
@NullableType
|
||||
Uri[] uris =
|
||||
this.uris.length == states.length ? this.uris : Arrays.copyOf(this.uris, states.length);
|
||||
states[index] = state;
|
||||
@ -362,7 +367,7 @@ public final class AdPlaybackState {
|
||||
if (adGroups[adGroupIndex].count == adCount) {
|
||||
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);
|
||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
@ -370,7 +375,7 @@ public final class AdPlaybackState {
|
||||
/** Returns an instance with the specified ad URI. */
|
||||
@CheckResult
|
||||
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);
|
||||
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. */
|
||||
@CheckResult
|
||||
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);
|
||||
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. */
|
||||
@CheckResult
|
||||
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);
|
||||
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. */
|
||||
@CheckResult
|
||||
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);
|
||||
return new AdPlaybackState(adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
@ -405,7 +410,7 @@ public final class AdPlaybackState {
|
||||
*/
|
||||
@CheckResult
|
||||
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();
|
||||
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. */
|
||||
@CheckResult
|
||||
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++) {
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdDurationsUs(adDurationUs[adGroupIndex]);
|
||||
}
|
||||
@ -441,7 +446,7 @@ public final class AdPlaybackState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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
|
||||
@ -114,7 +115,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||
*/
|
||||
public RuntimeException getRuntimeExceptionForUnexpected() {
|
||||
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;
|
||||
|
||||
// Accessed on the player thread.
|
||||
private ComponentListener componentListener;
|
||||
private Timeline contentTimeline;
|
||||
private Object contentManifest;
|
||||
private AdPlaybackState adPlaybackState;
|
||||
private MediaSource[][] adGroupMediaSources;
|
||||
private Timeline[][] adGroupTimelines;
|
||||
@Nullable private ComponentListener componentListener;
|
||||
@Nullable private Timeline contentTimeline;
|
||||
@Nullable private Object contentManifest;
|
||||
@Nullable private AdPlaybackState adPlaybackState;
|
||||
private @NullableType MediaSource[][] adGroupMediaSources;
|
||||
private @NullableType Timeline[][] adGroupTimelines;
|
||||
|
||||
/**
|
||||
* 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
|
||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
||||
AdPlaybackState adPlaybackState = Assertions.checkNotNull(this.adPlaybackState);
|
||||
if (adPlaybackState.adGroupCount > 0 && id.isAd()) {
|
||||
int adGroupIndex = id.adGroupIndex;
|
||||
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) {
|
||||
MediaSource adMediaSource = adMediaSourceFactory.createMediaSource(adUri);
|
||||
int oldAdCount = adGroupMediaSources[adGroupIndex].length;
|
||||
if (adIndexInAdGroup >= oldAdCount) {
|
||||
int adCount = adIndexInAdGroup + 1;
|
||||
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);
|
||||
int adCount = adIndexInAdGroup + 1;
|
||||
adGroupMediaSources[adGroupIndex] =
|
||||
Arrays.copyOf(adGroupMediaSources[adGroupIndex], adCount);
|
||||
adGroupTimelines[adGroupIndex] = Arrays.copyOf(adGroupTimelines[adGroupIndex], adCount);
|
||||
}
|
||||
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 =
|
||||
new DeferredMediaPeriod(mediaSource, id, allocator, startPositionUs);
|
||||
deferredMediaPeriod.setPrepareErrorListener(
|
||||
@ -227,7 +229,8 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||
List<DeferredMediaPeriod> mediaPeriods = deferredMediaPeriodByAdMediaSource.get(mediaSource);
|
||||
if (mediaPeriods == null) {
|
||||
Object periodUid =
|
||||
adGroupTimelines[adGroupIndex][adIndexInAdGroup].getUidOfPeriod(/* periodIndex= */ 0);
|
||||
Assertions.checkNotNull(adGroupTimelines[adGroupIndex][adIndexInAdGroup])
|
||||
.getUidOfPeriod(/* periodIndex= */ 0);
|
||||
MediaPeriodId adSourceMediaPeriodId = new MediaPeriodId(periodUid, id.windowSequenceNumber);
|
||||
deferredMediaPeriod.createPeriod(adSourceMediaPeriodId);
|
||||
} else {
|
||||
@ -258,7 +261,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||
@Override
|
||||
public void releaseSourceInternal() {
|
||||
super.releaseSourceInternal();
|
||||
componentListener.release();
|
||||
Assertions.checkNotNull(componentListener).release();
|
||||
componentListener = null;
|
||||
deferredMediaPeriodByAdMediaSource.clear();
|
||||
contentTimeline = null;
|
||||
@ -305,7 +308,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||
maybeUpdateSourceInfo();
|
||||
}
|
||||
|
||||
private void onContentSourceInfoRefreshed(Timeline timeline, Object manifest) {
|
||||
private void onContentSourceInfoRefreshed(Timeline timeline, @Nullable Object manifest) {
|
||||
Assertions.checkArgument(timeline.getPeriodCount() == 1);
|
||||
contentTimeline = timeline;
|
||||
contentManifest = manifest;
|
||||
@ -330,6 +333,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||
}
|
||||
|
||||
private void maybeUpdateSourceInfo() {
|
||||
Timeline contentTimeline = this.contentTimeline;
|
||||
if (adPlaybackState != null && contentTimeline != null) {
|
||||
adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurations(adGroupTimelines, period));
|
||||
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][];
|
||||
for (int i = 0; i < adTimelines.length; i++) {
|
||||
adDurations[i] = new long[adTimelines[i].length];
|
||||
|
Loading…
x
Reference in New Issue
Block a user