Make DataSource extend DataReader and upcast uses

This means DataSource.read now may throw InterruptedException.

PiperOrigin-RevId: 300523430
This commit is contained in:
aquilescanta 2020-03-12 11:47:47 +00:00 committed by Oliver Woodman
parent 93e203f970
commit 1f202f0aee
6 changed files with 37 additions and 49 deletions

View file

@ -23,6 +23,11 @@ public interface DataReader {
/**
* Reads up to {@code length} bytes of data from the input.
*
* <p>If {@code readLength} is zero then 0 is returned. Otherwise, if no data is available because
* the end of the opened range has been reached, then {@link C#RESULT_END_OF_INPUT} is returned.
* Otherwise, the call will block until at least one byte of data has been read and the number of
* bytes read is returned.
*
* @param target A target array into which data should be written.
* @param offset The offset into the target array at which to write.
* @param length The maximum number of bytes to read from the input.

View file

@ -23,10 +23,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* A component from which streams of data can be read.
*/
public interface DataSource {
/** Reads data from URI-identified resources. */
public interface DataSource extends DataReader {
/**
* A factory for {@link DataSource} instances.
@ -63,24 +61,6 @@ public interface DataSource {
*/
long open(DataSpec dataSpec) throws IOException;
/**
* Reads up to {@code readLength} bytes of data and stores them into {@code buffer}, starting at
* index {@code offset}.
*
* <p>If {@code readLength} is zero then 0 is returned. Otherwise, if no data is available because
* the end of the opened range has been reached, then {@link C#RESULT_END_OF_INPUT} is returned.
* Otherwise, the call will block until at least one byte of data has been read and the number of
* bytes read is returned.
*
* @param buffer The buffer into which the read data should be stored.
* @param offset The start offset into {@code buffer} at which data should be written.
* @param readLength The maximum number of bytes to read.
* @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if no data is available
* because the end of the opened range has been reached.
* @throws IOException If an error occurs reading from the source.
*/
int read(byte[] buffer, int offset, int readLength) throws IOException;
/**
* When the source is open, returns the {@link Uri} from which data is being read. The returned
* {@link Uri} will be identical to the one passed {@link #open(DataSpec)} in the {@link DataSpec}

View file

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source;
import android.net.Uri;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
@ -23,7 +24,7 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.EOFException;
@ -50,9 +51,10 @@ import java.io.IOException;
}
@Override
public void init(DataSource dataSource, long position, long length, ExtractorOutput output)
public void init(
DataReader dataReader, Uri uri, long position, long length, ExtractorOutput output)
throws IOException {
extractorInput = new DefaultExtractorInput(dataSource, position, length);
extractorInput = new DefaultExtractorInput(dataReader, position, length);
if (extractor != null) {
return;
}
@ -76,7 +78,7 @@ import java.io.IOException;
"None of the available extractors ("
+ Util.getCommaDelimitedSimpleClassNames(extractors)
+ ") could read the stream.",
Assertions.checkNotNull(dataSource.getUri()));
Assertions.checkNotNull(uri));
}
}
extractor.init(output);

View file

@ -15,11 +15,12 @@
*/
package com.google.android.exoplayer2.source;
import android.net.Uri;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataReader;
import java.io.IOException;
/** Extracts the contents of a container file from a progressive media stream. */
@ -28,15 +29,16 @@ import java.io.IOException;
/**
* Initializes the underlying infrastructure for reading from the input.
*
* @param dataSource The {@link DataSource} from which data should be read.
* @param position The initial position of the {@code dataSource} in the stream.
* @param dataReader The {@link DataReader} from which data should be read.
* @param uri The {@link Uri} from which the media is obtained.
* @param position The initial position of the {@code dataReader} in the stream.
* @param length The length of the stream, or {@link C#LENGTH_UNSET} if length is unknown.
* @param output The {@link ExtractorOutput} that will be used to initialize the selected
* extractor.
* @throws UnrecognizedInputFormatException Thrown if the input format could not be detected.
* @throws IOException Thrown if the input could not be read.
*/
void init(DataSource dataSource, long position, long length, ExtractorOutput output)
void init(DataReader dataReader, Uri uri, long position, long length, ExtractorOutput output)
throws IOException;
/** Releases any held resources. */

View file

@ -976,7 +976,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
icyTrackOutput = icyTrack();
icyTrackOutput.format(ICY_FORMAT);
}
progressiveMediaExtractor.init(extractorDataSource, position, length, extractorOutput);
progressiveMediaExtractor.init(
extractorDataSource, uri, position, length, extractorOutput);
if (icyHeaders != null) {
progressiveMediaExtractor.disableSeekingOnMp3Streams();

View file

@ -16,7 +16,7 @@
package com.google.android.exoplayer2.extractor;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.EOFException;
@ -24,9 +24,7 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Arrays;
/**
* An {@link ExtractorInput} that wraps a {@link DataSource}.
*/
/** An {@link ExtractorInput} that wraps a {@link DataReader}. */
public final class DefaultExtractorInput implements ExtractorInput {
private static final int PEEK_MIN_FREE_SPACE_AFTER_RESIZE = 64 * 1024;
@ -34,7 +32,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
private static final int SCRATCH_SPACE_SIZE = 4096;
private final byte[] scratchSpace;
private final DataSource dataSource;
private final DataReader dataReader;
private final long streamLength;
private long position;
@ -43,12 +41,12 @@ public final class DefaultExtractorInput implements ExtractorInput {
private int peekBufferLength;
/**
* @param dataSource The wrapped {@link DataSource}.
* @param dataReader The wrapped {@link DataReader}.
* @param position The initial position in the stream.
* @param length The length of the stream, or {@link C#LENGTH_UNSET} if it is unknown.
*/
public DefaultExtractorInput(DataSource dataSource, long position, long length) {
this.dataSource = dataSource;
public DefaultExtractorInput(DataReader dataReader, long position, long length) {
this.dataReader = dataReader;
this.position = position;
this.streamLength = length;
peekBuffer = new byte[PEEK_MIN_FREE_SPACE_AFTER_RESIZE];
@ -60,7 +58,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
int bytesRead = readFromPeekBuffer(target, offset, length);
if (bytesRead == 0) {
bytesRead =
readFromDataSource(
readFromUpstream(
target, offset, length, /* bytesAlreadyRead= */ 0, /* allowEndOfInput= */ true);
}
commitBytesRead(bytesRead);
@ -72,7 +70,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
throws IOException {
int bytesRead = readFromPeekBuffer(target, offset, length);
while (bytesRead < length && bytesRead != C.RESULT_END_OF_INPUT) {
bytesRead = readFromDataSource(target, offset, length, bytesRead, allowEndOfInput);
bytesRead = readFromUpstream(target, offset, length, bytesRead, allowEndOfInput);
}
commitBytesRead(bytesRead);
return bytesRead != C.RESULT_END_OF_INPUT;
@ -88,7 +86,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
int bytesSkipped = skipFromPeekBuffer(length);
if (bytesSkipped == 0) {
bytesSkipped =
readFromDataSource(scratchSpace, 0, Math.min(length, scratchSpace.length), 0, true);
readFromUpstream(scratchSpace, 0, Math.min(length, scratchSpace.length), 0, true);
}
commitBytesRead(bytesSkipped);
return bytesSkipped;
@ -100,7 +98,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
while (bytesSkipped < length && bytesSkipped != C.RESULT_END_OF_INPUT) {
int minLength = Math.min(length, bytesSkipped + scratchSpace.length);
bytesSkipped =
readFromDataSource(scratchSpace, -bytesSkipped, minLength, bytesSkipped, allowEndOfInput);
readFromUpstream(scratchSpace, -bytesSkipped, minLength, bytesSkipped, allowEndOfInput);
}
commitBytesRead(bytesSkipped);
return bytesSkipped != C.RESULT_END_OF_INPUT;
@ -118,7 +116,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
int bytesPeeked;
if (peekBufferRemainingBytes == 0) {
bytesPeeked =
readFromDataSource(
readFromUpstream(
peekBuffer,
peekBufferPosition,
length,
@ -156,8 +154,8 @@ public final class DefaultExtractorInput implements ExtractorInput {
ensureSpaceForPeek(length);
int bytesPeeked = peekBufferLength - peekBufferPosition;
while (bytesPeeked < length) {
bytesPeeked = readFromDataSource(peekBuffer, peekBufferPosition, length, bytesPeeked,
allowEndOfInput);
bytesPeeked =
readFromUpstream(peekBuffer, peekBufferPosition, length, bytesPeeked, allowEndOfInput);
if (bytesPeeked == C.RESULT_END_OF_INPUT) {
return false;
}
@ -259,7 +257,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
}
/**
* Starts or continues a read from the data source.
* Starts or continues a read from the data reader.
*
* @param target A target array into which data should be written.
* @param offset The offset into the target array at which to write.
@ -275,13 +273,13 @@ public final class DefaultExtractorInput implements ExtractorInput {
* read and {@code allowEndOfInput} is false.
* @throws IOException If an error occurs reading from the input.
*/
private int readFromDataSource(
private int readFromUpstream(
byte[] target, int offset, int length, int bytesAlreadyRead, boolean allowEndOfInput)
throws IOException {
if (Thread.interrupted()) {
throw new InterruptedIOException();
}
int bytesRead = dataSource.read(target, offset + bytesAlreadyRead, length - bytesAlreadyRead);
int bytesRead = dataReader.read(target, offset + bytesAlreadyRead, length - bytesAlreadyRead);
if (bytesRead == C.RESULT_END_OF_INPUT) {
if (bytesAlreadyRead == 0 && allowEndOfInput) {
return C.RESULT_END_OF_INPUT;