mirror of
https://github.com/androidx/media.git
synced 2025-05-17 12:39:52 +08:00
Add non-null by default to source.chunk
PiperOrigin-RevId: 289859343
This commit is contained in:
parent
4a5d788fa6
commit
090aed3aca
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,7 @@ 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,9 +69,7 @@ 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user