Remove HlsMediaChunk from null-checking blacklist
PiperOrigin-RevId: 274566133
This commit is contained in:
parent
d36abf966e
commit
e670b1d0f6
@ -23,6 +23,7 @@ import com.google.android.exoplayer2.drm.DrmInitData;
|
|||||||
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
|
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
|
||||||
import com.google.android.exoplayer2.extractor.Extractor;
|
import com.google.android.exoplayer2.extractor.Extractor;
|
||||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||||
|
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||||
import com.google.android.exoplayer2.metadata.Metadata;
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
import com.google.android.exoplayer2.metadata.id3.Id3Decoder;
|
import com.google.android.exoplayer2.metadata.id3.Id3Decoder;
|
||||||
import com.google.android.exoplayer2.metadata.id3.PrivFrame;
|
import com.google.android.exoplayer2.metadata.id3.PrivFrame;
|
||||||
@ -30,6 +31,7 @@ import com.google.android.exoplayer2.source.chunk.MediaChunk;
|
|||||||
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist;
|
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
import com.google.android.exoplayer2.util.TimestampAdjuster;
|
import com.google.android.exoplayer2.util.TimestampAdjuster;
|
||||||
import com.google.android.exoplayer2.util.UriUtil;
|
import com.google.android.exoplayer2.util.UriUtil;
|
||||||
@ -39,6 +41,9 @@ import java.io.IOException;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An HLS {@link MediaChunk}.
|
* An HLS {@link MediaChunk}.
|
||||||
@ -93,7 +98,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
/* key= */ null);
|
/* key= */ null);
|
||||||
boolean mediaSegmentEncrypted = mediaSegmentKey != null;
|
boolean mediaSegmentEncrypted = mediaSegmentKey != null;
|
||||||
byte[] mediaSegmentIv =
|
byte[] mediaSegmentIv =
|
||||||
mediaSegmentEncrypted ? getEncryptionIvArray(mediaSegment.encryptionIV) : null;
|
mediaSegmentEncrypted
|
||||||
|
? getEncryptionIvArray(Assertions.checkNotNull(mediaSegment.encryptionIV))
|
||||||
|
: null;
|
||||||
DataSource mediaDataSource = buildDataSource(dataSource, mediaSegmentKey, mediaSegmentIv);
|
DataSource mediaDataSource = buildDataSource(dataSource, mediaSegmentKey, mediaSegmentIv);
|
||||||
|
|
||||||
// Init segment.
|
// Init segment.
|
||||||
@ -104,7 +111,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
if (initSegment != null) {
|
if (initSegment != null) {
|
||||||
initSegmentEncrypted = initSegmentKey != null;
|
initSegmentEncrypted = initSegmentKey != null;
|
||||||
byte[] initSegmentIv =
|
byte[] initSegmentIv =
|
||||||
initSegmentEncrypted ? getEncryptionIvArray(initSegment.encryptionIV) : null;
|
initSegmentEncrypted
|
||||||
|
? getEncryptionIvArray(Assertions.checkNotNull(initSegment.encryptionIV))
|
||||||
|
: null;
|
||||||
Uri initSegmentUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, initSegment.url);
|
Uri initSegmentUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, initSegment.url);
|
||||||
initDataSpec =
|
initDataSpec =
|
||||||
new DataSpec(
|
new DataSpec(
|
||||||
@ -170,6 +179,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
public static final String PRIV_TIMESTAMP_FRAME_OWNER =
|
public static final String PRIV_TIMESTAMP_FRAME_OWNER =
|
||||||
"com.apple.streaming.transportStreamTimestamp";
|
"com.apple.streaming.transportStreamTimestamp";
|
||||||
|
private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder();
|
||||||
|
|
||||||
private static final AtomicInteger uidSource = new AtomicInteger();
|
private static final AtomicInteger uidSource = new AtomicInteger();
|
||||||
|
|
||||||
@ -186,8 +196,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
/** The url of the playlist from which this chunk was obtained. */
|
/** The url of the playlist from which this chunk was obtained. */
|
||||||
public final Uri playlistUrl;
|
public final Uri playlistUrl;
|
||||||
|
|
||||||
@Nullable private final DataSource initDataSource;
|
// These should be final, but can't be due to
|
||||||
@Nullable private final DataSpec initDataSpec;
|
// https://github.com/typetools/checker-framework/issues/2215
|
||||||
|
@MonotonicNonNull private DataSource initDataSource;
|
||||||
|
@MonotonicNonNull private DataSpec initDataSpec;
|
||||||
|
@MonotonicNonNull private Extractor previousExtractor;
|
||||||
|
|
||||||
private final boolean isMasterTimestampSource;
|
private final boolean isMasterTimestampSource;
|
||||||
private final boolean hasGapTag;
|
private final boolean hasGapTag;
|
||||||
private final TimestampAdjuster timestampAdjuster;
|
private final TimestampAdjuster timestampAdjuster;
|
||||||
@ -195,15 +209,14 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
private final HlsExtractorFactory extractorFactory;
|
private final HlsExtractorFactory extractorFactory;
|
||||||
@Nullable private final List<Format> muxedCaptionFormats;
|
@Nullable private final List<Format> muxedCaptionFormats;
|
||||||
@Nullable private final DrmInitData drmInitData;
|
@Nullable private final DrmInitData drmInitData;
|
||||||
@Nullable private final Extractor previousExtractor;
|
|
||||||
private final Id3Decoder id3Decoder;
|
private final Id3Decoder id3Decoder;
|
||||||
private final ParsableByteArray scratchId3Data;
|
private final ParsableByteArray scratchId3Data;
|
||||||
private final boolean mediaSegmentEncrypted;
|
private final boolean mediaSegmentEncrypted;
|
||||||
private final boolean initSegmentEncrypted;
|
private final boolean initSegmentEncrypted;
|
||||||
|
|
||||||
private Extractor extractor;
|
@MonotonicNonNull private Extractor extractor;
|
||||||
private boolean isExtractorReusable;
|
private boolean isExtractorReusable;
|
||||||
private HlsSampleStreamWrapper output;
|
@MonotonicNonNull private HlsSampleStreamWrapper output;
|
||||||
// nextLoadPosition refers to the init segment if initDataLoadRequired is true.
|
// nextLoadPosition refers to the init segment if initDataLoadRequired is true.
|
||||||
// Otherwise, nextLoadPosition refers to the media segment.
|
// Otherwise, nextLoadPosition refers to the media segment.
|
||||||
private int nextLoadPosition;
|
private int nextLoadPosition;
|
||||||
@ -217,13 +230,13 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
DataSpec dataSpec,
|
DataSpec dataSpec,
|
||||||
Format format,
|
Format format,
|
||||||
boolean mediaSegmentEncrypted,
|
boolean mediaSegmentEncrypted,
|
||||||
DataSource initDataSource,
|
@Nullable DataSource initDataSource,
|
||||||
@Nullable DataSpec initDataSpec,
|
@Nullable DataSpec initDataSpec,
|
||||||
boolean initSegmentEncrypted,
|
boolean initSegmentEncrypted,
|
||||||
Uri playlistUrl,
|
Uri playlistUrl,
|
||||||
@Nullable List<Format> muxedCaptionFormats,
|
@Nullable List<Format> muxedCaptionFormats,
|
||||||
int trackSelectionReason,
|
int trackSelectionReason,
|
||||||
Object trackSelectionData,
|
@Nullable Object trackSelectionData,
|
||||||
long startTimeUs,
|
long startTimeUs,
|
||||||
long endTimeUs,
|
long endTimeUs,
|
||||||
long chunkMediaSequence,
|
long chunkMediaSequence,
|
||||||
@ -247,8 +260,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
chunkMediaSequence);
|
chunkMediaSequence);
|
||||||
this.mediaSegmentEncrypted = mediaSegmentEncrypted;
|
this.mediaSegmentEncrypted = mediaSegmentEncrypted;
|
||||||
this.discontinuitySequenceNumber = discontinuitySequenceNumber;
|
this.discontinuitySequenceNumber = discontinuitySequenceNumber;
|
||||||
this.initDataSource = initDataSource;
|
// Workaround for https://github.com/typetools/checker-framework/issues/2215
|
||||||
this.initDataSpec = initDataSpec;
|
if (initDataSpec != null) {
|
||||||
|
this.initDataSpec = initDataSpec;
|
||||||
|
this.initDataSource = Assertions.checkNotNull(initDataSource);
|
||||||
|
initDataLoadRequired = true;
|
||||||
|
}
|
||||||
this.initSegmentEncrypted = initSegmentEncrypted;
|
this.initSegmentEncrypted = initSegmentEncrypted;
|
||||||
this.playlistUrl = playlistUrl;
|
this.playlistUrl = playlistUrl;
|
||||||
this.isMasterTimestampSource = isMasterTimestampSource;
|
this.isMasterTimestampSource = isMasterTimestampSource;
|
||||||
@ -257,11 +274,13 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
this.extractorFactory = extractorFactory;
|
this.extractorFactory = extractorFactory;
|
||||||
this.muxedCaptionFormats = muxedCaptionFormats;
|
this.muxedCaptionFormats = muxedCaptionFormats;
|
||||||
this.drmInitData = drmInitData;
|
this.drmInitData = drmInitData;
|
||||||
this.previousExtractor = previousExtractor;
|
// Workaround for https://github.com/typetools/checker-framework/issues/2215
|
||||||
|
if (previousExtractor != null) {
|
||||||
|
this.previousExtractor = previousExtractor;
|
||||||
|
}
|
||||||
this.id3Decoder = id3Decoder;
|
this.id3Decoder = id3Decoder;
|
||||||
this.scratchId3Data = scratchId3Data;
|
this.scratchId3Data = scratchId3Data;
|
||||||
this.shouldSpliceIn = shouldSpliceIn;
|
this.shouldSpliceIn = shouldSpliceIn;
|
||||||
initDataLoadRequired = initDataSpec != null;
|
|
||||||
uid = uidSource.getAndIncrement();
|
uid = uidSource.getAndIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +308,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() throws IOException, InterruptedException {
|
public void load() throws IOException, InterruptedException {
|
||||||
|
// output == null means init() hasn't been called.
|
||||||
|
Assertions.checkNotNull(output);
|
||||||
if (extractor == null && previousExtractor != null) {
|
if (extractor == null && previousExtractor != null) {
|
||||||
extractor = previousExtractor;
|
extractor = previousExtractor;
|
||||||
isExtractorReusable = true;
|
isExtractorReusable = true;
|
||||||
@ -306,15 +327,20 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
|
@RequiresNonNull("output")
|
||||||
private void maybeLoadInitData() throws IOException, InterruptedException {
|
private void maybeLoadInitData() throws IOException, InterruptedException {
|
||||||
if (!initDataLoadRequired) {
|
if (!initDataLoadRequired) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// initDataLoadRequired => initDataSource != null && initDataSpec != null
|
||||||
|
Assertions.checkNotNull(initDataSource);
|
||||||
|
Assertions.checkNotNull(initDataSpec);
|
||||||
feedDataToExtractor(initDataSource, initDataSpec, initSegmentEncrypted);
|
feedDataToExtractor(initDataSource, initDataSpec, initSegmentEncrypted);
|
||||||
nextLoadPosition = 0;
|
nextLoadPosition = 0;
|
||||||
initDataLoadRequired = false;
|
initDataLoadRequired = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresNonNull("output")
|
||||||
private void loadMedia() throws IOException, InterruptedException {
|
private void loadMedia() throws IOException, InterruptedException {
|
||||||
if (!isMasterTimestampSource) {
|
if (!isMasterTimestampSource) {
|
||||||
timestampAdjuster.waitUntilInitialized();
|
timestampAdjuster.waitUntilInitialized();
|
||||||
@ -330,6 +356,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
* concludes (because of a thrown exception or because the operation finishes), the number of fed
|
* concludes (because of a thrown exception or because the operation finishes), the number of fed
|
||||||
* bytes is written to {@code nextLoadPosition}.
|
* bytes is written to {@code nextLoadPosition}.
|
||||||
*/
|
*/
|
||||||
|
@RequiresNonNull("output")
|
||||||
private void feedDataToExtractor(
|
private void feedDataToExtractor(
|
||||||
DataSource dataSource, DataSpec dataSpec, boolean dataIsEncrypted)
|
DataSource dataSource, DataSpec dataSpec, boolean dataIsEncrypted)
|
||||||
throws IOException, InterruptedException {
|
throws IOException, InterruptedException {
|
||||||
@ -354,7 +381,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
try {
|
try {
|
||||||
int result = Extractor.RESULT_CONTINUE;
|
int result = Extractor.RESULT_CONTINUE;
|
||||||
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
||||||
result = extractor.read(input, /* seekPosition= */ null);
|
result = extractor.read(input, DUMMY_POSITION_HOLDER);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
nextLoadPosition = (int) (input.getPosition() - dataSpec.absoluteStreamPosition);
|
nextLoadPosition = (int) (input.getPosition() - dataSpec.absoluteStreamPosition);
|
||||||
@ -364,6 +391,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresNonNull("output")
|
||||||
|
@EnsuresNonNull("extractor")
|
||||||
private DefaultExtractorInput prepareExtraction(DataSource dataSource, DataSpec dataSpec)
|
private DefaultExtractorInput prepareExtraction(DataSource dataSource, DataSpec dataSpec)
|
||||||
throws IOException, InterruptedException {
|
throws IOException, InterruptedException {
|
||||||
long bytesToRead = dataSource.open(dataSpec);
|
long bytesToRead = dataSource.open(dataSpec);
|
||||||
@ -483,10 +512,15 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
/**
|
/**
|
||||||
* If the segment is fully encrypted, returns an {@link Aes128DataSource} that wraps the original
|
* If the segment is fully encrypted, returns an {@link Aes128DataSource} that wraps the original
|
||||||
* in order to decrypt the loaded data. Else returns the original.
|
* in order to decrypt the loaded data. Else returns the original.
|
||||||
|
*
|
||||||
|
* <p>{@code fullSegmentEncryptionKey} & {@code encryptionIv} can either both be null, or neither.
|
||||||
*/
|
*/
|
||||||
private static DataSource buildDataSource(DataSource dataSource, byte[] fullSegmentEncryptionKey,
|
private static DataSource buildDataSource(
|
||||||
byte[] encryptionIv) {
|
DataSource dataSource,
|
||||||
|
@Nullable byte[] fullSegmentEncryptionKey,
|
||||||
|
@Nullable byte[] encryptionIv) {
|
||||||
if (fullSegmentEncryptionKey != null) {
|
if (fullSegmentEncryptionKey != null) {
|
||||||
|
Assertions.checkNotNull(encryptionIv);
|
||||||
return new Aes128DataSource(dataSource, fullSegmentEncryptionKey, encryptionIv);
|
return new Aes128DataSource(dataSource, fullSegmentEncryptionKey, encryptionIv);
|
||||||
}
|
}
|
||||||
return dataSource;
|
return dataSource;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user