Add non-null by default to source.chunk

PiperOrigin-RevId: 289859343
This commit is contained in:
olly 2020-01-15 15:58:57 +00:00 committed by Oliver Woodman
parent 4a5d788fa6
commit 090aed3aca
10 changed files with 77 additions and 189 deletions

View File

@ -20,6 +20,8 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
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 org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
* A base implementation of {@link MediaChunk} that outputs to a {@link BaseMediaChunkOutput}. * A base implementation of {@link MediaChunk} that outputs to a {@link BaseMediaChunkOutput}.
@ -37,8 +39,8 @@ public abstract class BaseMediaChunk extends MediaChunk {
*/ */
public final long clippedEndTimeUs; public final long clippedEndTimeUs;
private BaseMediaChunkOutput output; private @MonotonicNonNull BaseMediaChunkOutput output;
private int[] firstSampleIndices; private int @MonotonicNonNull [] firstSampleIndices;
/** /**
* @param dataSource The source from which the data should be loaded. * @param dataSource The source from which the data should be loaded.
@ -87,14 +89,14 @@ public abstract class BaseMediaChunk extends MediaChunk {
* from this chunk. * from this chunk.
*/ */
public final int getFirstSampleIndex(int trackIndex) { public final int getFirstSampleIndex(int trackIndex) {
return firstSampleIndices[trackIndex]; return Assertions.checkStateNotNull(firstSampleIndices)[trackIndex];
} }
/** /**
* Returns the output most recently passed to {@link #init(BaseMediaChunkOutput)}. * Returns the output most recently passed to {@link #init(BaseMediaChunkOutput)}.
*/ */
protected final BaseMediaChunkOutput getOutput() { protected final BaseMediaChunkOutput getOutput() {
return output; return Assertions.checkStateNotNull(output);
} }
} }

View File

@ -58,10 +58,8 @@ public final class BaseMediaChunkOutput implements TrackOutputProvider {
public int[] getWriteIndices() { public int[] getWriteIndices() {
int[] writeIndices = new int[sampleQueues.length]; int[] writeIndices = new int[sampleQueues.length];
for (int i = 0; i < sampleQueues.length; i++) { for (int i = 0; i < sampleQueues.length; i++) {
if (sampleQueues[i] != null) {
writeIndices[i] = sampleQueues[i].getWriteIndex(); writeIndices[i] = sampleQueues[i].getWriteIndex();
} }
}
return writeIndices; return writeIndices;
} }
@ -71,10 +69,8 @@ public final class BaseMediaChunkOutput implements TrackOutputProvider {
*/ */
public void setSampleOffsetUs(long sampleOffsetUs) { public void setSampleOffsetUs(long sampleOffsetUs) {
for (SampleQueue sampleQueue : sampleQueues) { for (SampleQueue sampleQueue : sampleQueues) {
if (sampleQueue != null) {
sampleQueue.setSampleOffsetUs(sampleOffsetUs); sampleQueue.setSampleOffsetUs(sampleOffsetUs);
} }
} }
}
} }

View File

@ -42,10 +42,7 @@ public abstract class Chunk implements Loadable {
* reporting only. * reporting only.
*/ */
public final int type; public final int type;
/** /** The format of the track to which this chunk belongs. */
* The format of the track to which this chunk belongs, or null if the chunk does not belong to
* a track.
*/
public final Format trackFormat; public final Format trackFormat;
/** /**
* One of the {@link C} {@code SELECTION_REASON_*} constants if the chunk belongs to a track. * One of the {@link C} {@code SELECTION_REASON_*} constants if the chunk belongs to a track.

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.source.chunk; package com.google.android.exoplayer2.source.chunk;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.util.SparseArray; import android.util.SparseArray;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
@ -28,6 +30,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import java.io.IOException; import java.io.IOException;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
* An {@link Extractor} wrapper for loading chunks that contain a single primary track, and possibly * An {@link Extractor} wrapper for loading chunks that contain a single primary track, and possibly
@ -63,10 +66,10 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
private final SparseArray<BindingTrackOutput> bindingTrackOutputs; private final SparseArray<BindingTrackOutput> bindingTrackOutputs;
private boolean extractorInitialized; private boolean extractorInitialized;
private TrackOutputProvider trackOutputProvider; @Nullable private TrackOutputProvider trackOutputProvider;
private long endTimeUs; private long endTimeUs;
private SeekMap seekMap; private @MonotonicNonNull SeekMap seekMap;
private Format[] sampleFormats; private Format @MonotonicNonNull [] sampleFormats;
/** /**
* @param extractor The extractor to wrap. * @param extractor The extractor to wrap.
@ -84,15 +87,19 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
} }
/** /**
* Returns the {@link SeekMap} most recently output by the extractor, or null. * Returns the {@link SeekMap} most recently output by the extractor, or null if the extractor has
* not output a {@link SeekMap}.
*/ */
@Nullable
public SeekMap getSeekMap() { public SeekMap getSeekMap() {
return seekMap; return seekMap;
} }
/** /**
* Returns the sample {@link Format}s most recently output by the extractor, or null. * Returns the sample {@link Format}s for the tracks identified by the extractor, or null if the
* extractor has not finished identifying tracks.
*/ */
@Nullable
public Format[] getSampleFormats() { public Format[] getSampleFormats() {
return sampleFormats; return sampleFormats;
} }
@ -146,7 +153,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
public void endTracks() { public void endTracks() {
Format[] sampleFormats = new Format[bindingTrackOutputs.size()]; Format[] sampleFormats = new Format[bindingTrackOutputs.size()];
for (int i = 0; i < bindingTrackOutputs.size(); i++) { for (int i = 0; i < bindingTrackOutputs.size(); i++) {
sampleFormats[i] = bindingTrackOutputs.valueAt(i).sampleFormat; sampleFormats[i] = Assertions.checkStateNotNull(bindingTrackOutputs.valueAt(i).sampleFormat);
} }
this.sampleFormats = sampleFormats; this.sampleFormats = sampleFormats;
} }
@ -162,21 +169,21 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
private final int id; private final int id;
private final int type; private final int type;
private final Format manifestFormat; @Nullable private final Format manifestFormat;
private final DummyTrackOutput dummyTrackOutput; private final DummyTrackOutput dummyTrackOutput;
public Format sampleFormat; public @MonotonicNonNull Format sampleFormat;
private TrackOutput trackOutput; private @MonotonicNonNull TrackOutput trackOutput;
private long endTimeUs; private long endTimeUs;
public BindingTrackOutput(int id, int type, Format manifestFormat) { public BindingTrackOutput(int id, int type, @Nullable Format manifestFormat) {
this.id = id; this.id = id;
this.type = type; this.type = type;
this.manifestFormat = manifestFormat; this.manifestFormat = manifestFormat;
dummyTrackOutput = new DummyTrackOutput(); dummyTrackOutput = new DummyTrackOutput();
} }
public void bind(TrackOutputProvider trackOutputProvider, long endTimeUs) { public void bind(@Nullable TrackOutputProvider trackOutputProvider, long endTimeUs) {
if (trackOutputProvider == null) { if (trackOutputProvider == null) {
trackOutput = dummyTrackOutput; trackOutput = dummyTrackOutput;
return; return;
@ -192,29 +199,31 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
public void format(Format format) { public void format(Format format) {
sampleFormat = manifestFormat != null ? format.copyWithManifestFormatInfo(manifestFormat) sampleFormat = manifestFormat != null ? format.copyWithManifestFormatInfo(manifestFormat)
: format; : format;
trackOutput.format(sampleFormat); castNonNull(trackOutput).format(sampleFormat);
} }
@Override @Override
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput) public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException { throws IOException, InterruptedException {
return trackOutput.sampleData(input, length, allowEndOfInput); return castNonNull(trackOutput).sampleData(input, length, allowEndOfInput);
} }
@Override @Override
public void sampleData(ParsableByteArray data, int length) { public void sampleData(ParsableByteArray data, int length) {
trackOutput.sampleData(data, length); castNonNull(trackOutput).sampleData(data, length);
} }
@Override @Override
public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, public void sampleMetadata(
CryptoData cryptoData) { long timeUs,
@C.BufferFlags int flags,
int size,
int offset,
@Nullable CryptoData cryptoData) {
if (endTimeUs != C.TIME_UNSET && timeUs >= endTimeUs) { if (endTimeUs != C.TIME_UNSET && timeUs >= endTimeUs) {
trackOutput = dummyTrackOutput; trackOutput = dummyTrackOutput;
} }
trackOutput.sampleMetadata(timeUs, flags, size, offset, cryptoData); castNonNull(trackOutput).sampleMetadata(timeUs, flags, size, offset, cryptoData);
} }
} }
} }

View File

@ -38,6 +38,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
* A {@link SampleStream} that loads media in {@link Chunk}s, obtained from a {@link ChunkSource}. * A {@link SampleStream} that loads media in {@link Chunk}s, obtained from a {@link ChunkSource}.
@ -61,8 +62,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
public final int primaryTrackType; public final int primaryTrackType;
@Nullable private final int[] embeddedTrackTypes; private final int[] embeddedTrackTypes;
@Nullable private final Format[] embeddedTrackFormats; private final Format[] embeddedTrackFormats;
private final boolean[] embeddedTracksSelected; private final boolean[] embeddedTracksSelected;
private final T chunkSource; private final T chunkSource;
private final SequenceableLoader.Callback<ChunkSampleStream<T>> callback; private final SequenceableLoader.Callback<ChunkSampleStream<T>> callback;
@ -76,7 +77,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
private final SampleQueue[] embeddedSampleQueues; private final SampleQueue[] embeddedSampleQueues;
private final BaseMediaChunkOutput chunkOutput; private final BaseMediaChunkOutput chunkOutput;
private Format primaryDownstreamTrackFormat; private @MonotonicNonNull Format primaryDownstreamTrackFormat;
@Nullable private ReleaseCallback<T> releaseCallback; @Nullable private ReleaseCallback<T> releaseCallback;
private long pendingResetPositionUs; private long pendingResetPositionUs;
private long lastSeekPositionUs; private long lastSeekPositionUs;
@ -113,8 +114,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
LoadErrorHandlingPolicy loadErrorHandlingPolicy, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher) {
this.primaryTrackType = primaryTrackType; this.primaryTrackType = primaryTrackType;
this.embeddedTrackTypes = embeddedTrackTypes; this.embeddedTrackTypes = embeddedTrackTypes == null ? new int[0] : embeddedTrackTypes;
this.embeddedTrackFormats = embeddedTrackFormats; this.embeddedTrackFormats = embeddedTrackFormats == null ? new Format[0] : embeddedTrackFormats;
this.chunkSource = chunkSource; this.chunkSource = chunkSource;
this.callback = callback; this.callback = callback;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
@ -124,7 +125,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
mediaChunks = new ArrayList<>(); mediaChunks = new ArrayList<>();
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
int embeddedTrackCount = embeddedTrackTypes == null ? 0 : embeddedTrackTypes.length; int embeddedTrackCount = this.embeddedTrackTypes.length;
embeddedSampleQueues = new SampleQueue[embeddedTrackCount]; embeddedSampleQueues = new SampleQueue[embeddedTrackCount];
embeddedTracksSelected = new boolean[embeddedTrackCount]; embeddedTracksSelected = new boolean[embeddedTrackCount];
int[] trackTypes = new int[1 + embeddedTrackCount]; int[] trackTypes = new int[1 + embeddedTrackCount];
@ -139,7 +140,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
new SampleQueue(allocator, DrmSessionManager.getDummyDrmSessionManager()); new SampleQueue(allocator, DrmSessionManager.getDummyDrmSessionManager());
embeddedSampleQueues[i] = sampleQueue; embeddedSampleQueues[i] = sampleQueue;
sampleQueues[i + 1] = sampleQueue; sampleQueues[i + 1] = sampleQueue;
trackTypes[i + 1] = embeddedTrackTypes[i]; trackTypes[i + 1] = this.embeddedTrackTypes[i];
} }
chunkOutput = new BaseMediaChunkOutput(trackTypes, sampleQueues); chunkOutput = new BaseMediaChunkOutput(trackTypes, sampleQueues);
@ -251,7 +252,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
// Detect whether the seek is to the start of a chunk that's at least partially buffered. // Detect whether the seek is to the start of a chunk that's at least partially buffered.
BaseMediaChunk seekToMediaChunk = null; @Nullable BaseMediaChunk seekToMediaChunk = null;
for (int i = 0; i < mediaChunks.size(); i++) { for (int i = 0; i < mediaChunks.size(); i++) {
BaseMediaChunk mediaChunk = mediaChunks.get(i); BaseMediaChunk mediaChunk = mediaChunks.get(i);
long mediaChunkStartTimeUs = mediaChunk.startTimeUs; long mediaChunkStartTimeUs = mediaChunk.startTimeUs;
@ -463,7 +464,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
? loadErrorHandlingPolicy.getBlacklistDurationMsFor( ? loadErrorHandlingPolicy.getBlacklistDurationMsFor(
loadable.type, loadDurationMs, error, errorCount) loadable.type, loadDurationMs, error, errorCount)
: C.TIME_UNSET; : C.TIME_UNSET;
LoadErrorAction loadErrorAction = null; @Nullable LoadErrorAction loadErrorAction = null;
if (chunkSource.onChunkLoadError(loadable, cancelable, error, blacklistDurationMs)) { if (chunkSource.onChunkLoadError(loadable, cancelable, error, blacklistDurationMs)) {
if (cancelable) { if (cancelable) {
loadErrorAction = Loader.DONT_RETRY; loadErrorAction = Loader.DONT_RETRY;
@ -533,7 +534,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder); chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
boolean endOfStream = nextChunkHolder.endOfStream; boolean endOfStream = nextChunkHolder.endOfStream;
Chunk loadable = nextChunkHolder.chunk; @Nullable Chunk loadable = nextChunkHolder.chunk;
nextChunkHolder.clear(); nextChunkHolder.clear();
if (endOfStream) { if (endOfStream) {
@ -764,7 +765,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
@Override @Override
public void maybeThrowError() throws IOException { public void maybeThrowError() {
// Do nothing. Errors will be thrown from the primary stream. // Do nothing. Errors will be thrown from the primary stream.
} }

View File

@ -52,16 +52,16 @@ public abstract class DataChunk extends Chunk {
Format trackFormat, Format trackFormat,
int trackSelectionReason, int trackSelectionReason,
@Nullable Object trackSelectionData, @Nullable Object trackSelectionData,
byte[] data) { @Nullable byte[] data) {
super(dataSource, dataSpec, type, trackFormat, trackSelectionReason, trackSelectionData, super(dataSource, dataSpec, type, trackFormat, trackSelectionReason, trackSelectionData,
C.TIME_UNSET, C.TIME_UNSET); C.TIME_UNSET, C.TIME_UNSET);
this.data = data; this.data = data == null ? Util.EMPTY_BYTE_ARRAY : data;
} }
/** /**
* Returns the array in which the data is held. * Returns the array in which the data is held.
* <p> *
* This method should be used for recycling the holder only, and not for reading the data. * <p>This method should be used for recycling the holder only, and not for reading the data.
* *
* @return The array in which the data is held. * @return The array in which the data is held.
*/ */
@ -108,9 +108,7 @@ public abstract class DataChunk extends Chunk {
protected abstract void consume(byte[] data, int limit) throws IOException; protected abstract void consume(byte[] data, int limit) throws IOException;
private void maybeExpandData(int limit) { private void maybeExpandData(int limit) {
if (data == null) { if (data.length < limit + READ_GRANULARITY) {
data = new byte[READ_GRANULARITY];
} else if (data.length < limit + READ_GRANULARITY) {
// The new length is calculated as (data.length + READ_GRANULARITY) rather than // The new length is calculated as (data.length + READ_GRANULARITY) rather than
// (limit + READ_GRANULARITY) in order to avoid small increments in the length. // (limit + READ_GRANULARITY) in order to avoid small increments in the length.
data = Arrays.copyOf(data, data.length + READ_GRANULARITY); data = Arrays.copyOf(data, data.length + READ_GRANULARITY);

View File

@ -1,61 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source.chunk;
import com.google.android.exoplayer2.upstream.DataSpec;
import java.util.List;
/** A {@link MediaChunkIterator} which iterates over a {@link List} of {@link MediaChunk}s. */
public final class MediaChunkListIterator extends BaseMediaChunkIterator {
private final List<? extends MediaChunk> chunks;
private final boolean reverseOrder;
/**
* Creates iterator.
*
* @param chunks The list of chunks to iterate over.
* @param reverseOrder Whether to iterate in reverse order.
*/
public MediaChunkListIterator(List<? extends MediaChunk> chunks, boolean reverseOrder) {
super(0, chunks.size() - 1);
this.chunks = chunks;
this.reverseOrder = reverseOrder;
}
@Override
public DataSpec getDataSpec() {
return getCurrentChunk().dataSpec;
}
@Override
public long getChunkStartTimeUs() {
return getCurrentChunk().startTimeUs;
}
@Override
public long getChunkEndTimeUs() {
return getCurrentChunk().endTimeUs;
}
private MediaChunk getCurrentChunk() {
int index = (int) super.getCurrentIndex();
if (reverseOrder) {
index = chunks.size() - 1 - index;
}
return chunks.get(index);
}
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NonNullApi
package com.google.android.exoplayer2.source.chunk;
import com.google.android.exoplayer2.util.NonNullApi;

View File

@ -1,76 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source.chunk;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.testutil.FakeMediaChunk;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Tests for {@link MediaChunkListIterator}. */
@RunWith(AndroidJUnit4.class)
public class MediaChunkListIteratorTest {
private static final Format TEST_FORMAT = Format.createSampleFormat(null, null, 0);
private FakeMediaChunk testChunk1;
private FakeMediaChunk testChunk2;
@Before
public void setUp() {
testChunk1 = new FakeMediaChunk(TEST_FORMAT, 0, 10);
testChunk2 = new FakeMediaChunk(TEST_FORMAT, 10, 20);
}
@Test
public void iterator_reverseOrderFalse_returnsItemsInNormalOrder() {
MediaChunkListIterator iterator =
new MediaChunkListIterator(
Arrays.asList(testChunk1, testChunk2), /* reverseOrder= */ false);
assertThat(iterator.isEnded()).isFalse();
assertThat(iterator.next()).isTrue();
assertEqual(iterator, testChunk1);
assertThat(iterator.next()).isTrue();
assertEqual(iterator, testChunk2);
assertThat(iterator.next()).isFalse();
assertThat(iterator.isEnded()).isTrue();
}
@Test
public void iterator_reverseOrderTrue_returnsItemsInReverseOrder() {
MediaChunkListIterator iterator =
new MediaChunkListIterator(
Arrays.asList(testChunk1, testChunk2), /* reverseOrder= */ true);
assertThat(iterator.isEnded()).isFalse();
assertThat(iterator.next()).isTrue();
assertEqual(iterator, testChunk2);
assertThat(iterator.next()).isTrue();
assertEqual(iterator, testChunk1);
assertThat(iterator.next()).isFalse();
assertThat(iterator.isEnded()).isTrue();
}
private static void assertEqual(MediaChunkListIterator iterator, FakeMediaChunk chunk) {
assertThat(iterator.getChunkStartTimeUs()).isEqualTo(chunk.startTimeUs);
assertThat(iterator.getChunkEndTimeUs()).isEqualTo(chunk.endTimeUs);
assertThat(iterator.getDataSpec()).isEqualTo(chunk.dataSpec);
}
}

View File

@ -35,6 +35,7 @@ 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.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.ParsingLoadable; import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -102,7 +103,9 @@ public final class DashUtil {
throws IOException, InterruptedException { throws IOException, InterruptedException {
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType, ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
representation, false); representation, false);
return extractorWrapper == null ? null : extractorWrapper.getSampleFormats()[0]; return extractorWrapper == null
? null
: Assertions.checkStateNotNull(extractorWrapper.getSampleFormats())[0];
} }
/** /**