DataReader: replace InterruptedException with InterruptedIOException
PiperOrigin-RevId: 299092243
This commit is contained in:
parent
fbf865726c
commit
47b62e8c02
@ -49,8 +49,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
.createDataSource();
|
.createDataSource();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flacExtractorReads_seekTable_returnSeekableSeekMap()
|
public void flacExtractorReads_seekTable_returnSeekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_SEEK_TABLE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_SEEK_TABLE);
|
||||||
|
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -61,7 +60,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekToZero() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekToZero() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -78,7 +77,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekToEoF() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekToEoF() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -95,7 +94,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekingBackward() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekingBackward() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -114,7 +113,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekingForward() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekingForward() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -133,8 +132,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flacExtractorReads_binarySearch_returnSeekableSeekMap()
|
public void flacExtractorReads_binarySearch_returnSeekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_BINARY_SEARCH);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_BINARY_SEARCH);
|
||||||
|
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -145,7 +143,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekToZero() throws IOException, InterruptedException {
|
public void seeking_binarySearch_handlesSeekToZero() throws IOException {
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -162,7 +160,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekToEoF() throws IOException, InterruptedException {
|
public void seeking_binarySearch_handlesSeekToEoF() throws IOException {
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -179,8 +177,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekingBackward()
|
public void seeking_binarySearch_handlesSeekingBackward() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -199,8 +196,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekingForward()
|
public void seeking_binarySearch_handlesSeekingForward() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -219,8 +215,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flacExtractorReads_unseekable_returnUnseekableSeekMap()
|
public void flacExtractorReads_unseekable_returnUnseekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_UNSEEKABLE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_UNSEEKABLE);
|
||||||
|
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -235,7 +230,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
long targetSeekTimeUs,
|
long targetSeekTimeUs,
|
||||||
int firstFrameIndexAfterSeek)
|
int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
int expectedFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
int expectedFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
||||||
|
|
||||||
@ -252,7 +247,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
long targetSeekTimeUs,
|
long targetSeekTimeUs,
|
||||||
int firstFrameIndexAfterSeek)
|
int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
int maxFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
int maxFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
||||||
|
|
||||||
@ -276,8 +271,7 @@ public final class FlacExtractorSeekTest {
|
|||||||
assertThat(frameFound).isTrue();
|
assertThat(frameFound).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FakeTrackOutput getExpectedTrackOutput(String fileName)
|
private static FakeTrackOutput getExpectedTrackOutput(String fileName) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
return TestUtil.extractAllSamplesFromFile(
|
return TestUtil.extractAllSamplesFromFile(
|
||||||
new FlacExtractor(), ApplicationProvider.getApplicationContext(), fileName)
|
new FlacExtractor(), ApplicationProvider.getApplicationContext(), fileName)
|
||||||
.trackOutputs
|
.trackOutputs
|
||||||
|
@ -100,7 +100,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetSampleIndex)
|
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetSampleIndex)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
ByteBuffer outputBuffer = outputFrameHolder.byteBuffer;
|
ByteBuffer outputBuffer = outputFrameHolder.byteBuffer;
|
||||||
long searchPosition = input.getPosition();
|
long searchPosition = input.getPosition();
|
||||||
decoderJni.reset(searchPosition);
|
decoderJni.reset(searchPosition);
|
||||||
|
@ -63,7 +63,7 @@ import java.util.List;
|
|||||||
streamMetadata = decoderJni.decodeStreamMetadata();
|
streamMetadata = decoderJni.decodeStreamMetadata();
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
throw new FlacDecoderException("Failed to decode StreamInfo", e);
|
throw new FlacDecoderException("Failed to decode StreamInfo", e);
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException e) {
|
||||||
// Never happens.
|
// Never happens.
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ import java.util.List;
|
|||||||
decoderJni.decodeSample(outputData);
|
decoderJni.decodeSample(outputData);
|
||||||
} catch (FlacDecoderJni.FlacFrameDecodeException e) {
|
} catch (FlacDecoderJni.FlacFrameDecodeException e) {
|
||||||
return new FlacDecoderException("Frame decoding failed", e);
|
return new FlacDecoderException("Frame decoding failed", e);
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException e) {
|
||||||
// Never happens.
|
// Never happens.
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ import java.nio.ByteBuffer;
|
|||||||
* read from the source, then 0 is returned.
|
* read from the source, then 0 is returned.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused") // Called from native code.
|
@SuppressWarnings("unused") // Called from native code.
|
||||||
public int read(ByteBuffer target) throws IOException, InterruptedException {
|
public int read(ByteBuffer target) throws IOException {
|
||||||
int byteCount = target.remaining();
|
int byteCount = target.remaining();
|
||||||
if (byteBufferData != null) {
|
if (byteBufferData != null) {
|
||||||
byteCount = Math.min(byteCount, byteBufferData.remaining());
|
byteCount = Math.min(byteCount, byteBufferData.remaining());
|
||||||
@ -145,7 +145,7 @@ import java.nio.ByteBuffer;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Decodes and consumes the metadata from the FLAC stream. */
|
/** Decodes and consumes the metadata from the FLAC stream. */
|
||||||
public FlacStreamMetadata decodeStreamMetadata() throws IOException, InterruptedException {
|
public FlacStreamMetadata decodeStreamMetadata() throws IOException {
|
||||||
FlacStreamMetadata streamMetadata = flacDecodeMetadata(nativeDecoderContext);
|
FlacStreamMetadata streamMetadata = flacDecodeMetadata(nativeDecoderContext);
|
||||||
if (streamMetadata == null) {
|
if (streamMetadata == null) {
|
||||||
throw new ParserException("Failed to decode stream metadata");
|
throw new ParserException("Failed to decode stream metadata");
|
||||||
@ -161,7 +161,7 @@ import java.nio.ByteBuffer;
|
|||||||
* @param retryPosition If any error happens, the input will be rewound to {@code retryPosition}.
|
* @param retryPosition If any error happens, the input will be rewound to {@code retryPosition}.
|
||||||
*/
|
*/
|
||||||
public void decodeSampleWithBacktrackPosition(ByteBuffer output, long retryPosition)
|
public void decodeSampleWithBacktrackPosition(ByteBuffer output, long retryPosition)
|
||||||
throws InterruptedException, IOException, FlacFrameDecodeException {
|
throws IOException, FlacFrameDecodeException {
|
||||||
try {
|
try {
|
||||||
decodeSample(output);
|
decodeSample(output);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -177,8 +177,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
/** Decodes and consumes the next sample from the FLAC stream into the given byte buffer. */
|
/** Decodes and consumes the next sample from the FLAC stream into the given byte buffer. */
|
||||||
@SuppressWarnings("ByteBufferBackingArray")
|
@SuppressWarnings("ByteBufferBackingArray")
|
||||||
public void decodeSample(ByteBuffer output)
|
public void decodeSample(ByteBuffer output) throws IOException, FlacFrameDecodeException {
|
||||||
throws IOException, InterruptedException, FlacFrameDecodeException {
|
|
||||||
output.clear();
|
output.clear();
|
||||||
int frameSize =
|
int frameSize =
|
||||||
output.isDirect()
|
output.isDirect()
|
||||||
@ -266,8 +265,7 @@ import java.nio.ByteBuffer;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int readFromExtractorInput(
|
private int readFromExtractorInput(
|
||||||
ExtractorInput extractorInput, byte[] tempBuffer, int offset, int length)
|
ExtractorInput extractorInput, byte[] tempBuffer, int offset, int length) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
int read = extractorInput.read(tempBuffer, offset, length);
|
int read = extractorInput.read(tempBuffer, offset, length);
|
||||||
if (read == C.RESULT_END_OF_INPUT) {
|
if (read == C.RESULT_END_OF_INPUT) {
|
||||||
endOfExtractorInput = true;
|
endOfExtractorInput = true;
|
||||||
@ -278,14 +276,11 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
private native long flacInit();
|
private native long flacInit();
|
||||||
|
|
||||||
private native FlacStreamMetadata flacDecodeMetadata(long context)
|
private native FlacStreamMetadata flacDecodeMetadata(long context) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
private native int flacDecodeToBuffer(long context, ByteBuffer outputBuffer)
|
private native int flacDecodeToBuffer(long context, ByteBuffer outputBuffer) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
private native int flacDecodeToArray(long context, byte[] outputArray)
|
private native int flacDecodeToArray(long context, byte[] outputArray) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
private native long flacGetDecodePosition(long context);
|
private native long flacGetDecodePosition(long context);
|
||||||
|
|
||||||
|
@ -113,14 +113,13 @@ public final class FlacExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
id3Metadata = FlacMetadataReader.peekId3Metadata(input, /* parseData= */ !id3MetadataDisabled);
|
id3Metadata = FlacMetadataReader.peekId3Metadata(input, /* parseData= */ !id3MetadataDisabled);
|
||||||
return FlacMetadataReader.checkAndPeekStreamMarker(input);
|
return FlacMetadataReader.checkAndPeekStreamMarker(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(final ExtractorInput input, PositionHolder seekPosition)
|
public int read(final ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (input.getPosition() == 0 && !id3MetadataDisabled && id3Metadata == null) {
|
if (input.getPosition() == 0 && !id3MetadataDisabled && id3Metadata == null) {
|
||||||
id3Metadata = FlacMetadataReader.peekId3Metadata(input, /* parseData= */ true);
|
id3Metadata = FlacMetadataReader.peekId3Metadata(input, /* parseData= */ true);
|
||||||
}
|
}
|
||||||
@ -185,7 +184,7 @@ public final class FlacExtractor implements Extractor {
|
|||||||
@RequiresNonNull({"decoderJni", "extractorOutput", "trackOutput"}) // Requires initialized.
|
@RequiresNonNull({"decoderJni", "extractorOutput", "trackOutput"}) // Requires initialized.
|
||||||
@EnsuresNonNull({"streamMetadata", "outputFrameHolder"}) // Ensures stream metadata decoded.
|
@EnsuresNonNull({"streamMetadata", "outputFrameHolder"}) // Ensures stream metadata decoded.
|
||||||
@SuppressWarnings({"contracts.postcondition.not.satisfied"})
|
@SuppressWarnings({"contracts.postcondition.not.satisfied"})
|
||||||
private void decodeStreamMetadata(ExtractorInput input) throws InterruptedException, IOException {
|
private void decodeStreamMetadata(ExtractorInput input) throws IOException {
|
||||||
if (streamMetadataDecoded) {
|
if (streamMetadataDecoded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -225,7 +224,7 @@ public final class FlacExtractor implements Extractor {
|
|||||||
ParsableByteArray outputBuffer,
|
ParsableByteArray outputBuffer,
|
||||||
OutputFrameHolder outputFrameHolder,
|
OutputFrameHolder outputFrameHolder,
|
||||||
TrackOutput trackOutput)
|
TrackOutput trackOutput)
|
||||||
throws InterruptedException, IOException {
|
throws IOException {
|
||||||
int seekResult = binarySearchSeeker.handlePendingSeek(input, seekPosition);
|
int seekResult = binarySearchSeeker.handlePendingSeek(input, seekPosition);
|
||||||
ByteBuffer outputByteBuffer = outputFrameHolder.byteBuffer;
|
ByteBuffer outputByteBuffer = outputFrameHolder.byteBuffer;
|
||||||
if (seekResult == RESULT_CONTINUE && outputByteBuffer.limit() > 0) {
|
if (seekResult == RESULT_CONTINUE && outputByteBuffer.limit() > 0) {
|
||||||
|
@ -30,7 +30,6 @@ public interface DataReader {
|
|||||||
* may be less than {@code length} because the end of the input (or available data) was
|
* may be less than {@code length} because the end of the input (or available data) was
|
||||||
* reached, the method was interrupted, or the operation was aborted early for another reason.
|
* reached, the method was interrupted, or the operation was aborted early for another reason.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
int read(byte[] target, int offset, int length) throws IOException, InterruptedException;
|
int read(byte[] target, int offset, int length) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(DataSource dataSource, long position, long length, ExtractorOutput output)
|
public void init(DataSource dataSource, long position, long length, ExtractorOutput output)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
extractorInput = new DefaultExtractorInput(dataSource, position, length);
|
extractorInput = new DefaultExtractorInput(dataSource, position, length);
|
||||||
if (extractor != null) {
|
if (extractor != null) {
|
||||||
return;
|
return;
|
||||||
@ -109,7 +109,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(PositionHolder positionHolder) throws IOException, InterruptedException {
|
public int read(PositionHolder positionHolder) throws IOException {
|
||||||
return Assertions.checkNotNull(extractor)
|
return Assertions.checkNotNull(extractor)
|
||||||
.read(Assertions.checkNotNull(extractorInput), positionHolder);
|
.read(Assertions.checkNotNull(extractorInput), positionHolder);
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,9 @@ import java.io.IOException;
|
|||||||
* extractor.
|
* extractor.
|
||||||
* @throws UnrecognizedInputFormatException Thrown if the input format could not be detected.
|
* @throws UnrecognizedInputFormatException Thrown if the input format could not be detected.
|
||||||
* @throws IOException Thrown if the input could not be read.
|
* @throws IOException Thrown if the input could not be read.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
void init(DataSource dataSource, long position, long length, ExtractorOutput output)
|
void init(DataSource dataSource, long position, long length, ExtractorOutput output)
|
||||||
throws IOException, InterruptedException;
|
throws IOException;
|
||||||
|
|
||||||
/** Releases any held resources. */
|
/** Releases any held resources. */
|
||||||
void release();
|
void release();
|
||||||
@ -71,7 +70,6 @@ import java.io.IOException;
|
|||||||
* hold the position of the required data.
|
* hold the position of the required data.
|
||||||
* @return One of the {@link Extractor}{@code .RESULT_*} values.
|
* @return One of the {@link Extractor}{@code .RESULT_*} values.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
int read(PositionHolder positionHolder) throws IOException, InterruptedException;
|
int read(PositionHolder positionHolder) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ import com.google.android.exoplayer2.util.MimeTypes;
|
|||||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InterruptedIOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -950,7 +951,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() throws IOException, InterruptedException {
|
public void load() throws IOException {
|
||||||
int result = Extractor.RESULT_CONTINUE;
|
int result = Extractor.RESULT_CONTINUE;
|
||||||
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
||||||
try {
|
try {
|
||||||
@ -978,7 +979,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
pendingExtractorSeek = false;
|
pendingExtractorSeek = false;
|
||||||
}
|
}
|
||||||
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
||||||
|
try {
|
||||||
loadCondition.block();
|
loadCondition.block();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new InterruptedIOException();
|
||||||
|
}
|
||||||
result = progressiveMediaExtractor.read(positionHolder);
|
result = progressiveMediaExtractor.read(positionHolder);
|
||||||
long currentInputPosition = progressiveMediaExtractor.getCurrentInputPosition();
|
long currentInputPosition = progressiveMediaExtractor.getCurrentInputPosition();
|
||||||
if (currentInputPosition > position + continueLoadingCheckIntervalBytes) {
|
if (currentInputPosition > position + continueLoadingCheckIntervalBytes) {
|
||||||
|
@ -177,8 +177,7 @@ import java.util.Arrays;
|
|||||||
return totalBytesWritten;
|
return totalBytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
public int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
length = preAppend(length);
|
length = preAppend(length);
|
||||||
int bytesAppended =
|
int bytesAppended =
|
||||||
input.read(
|
input.read(
|
||||||
|
@ -470,7 +470,7 @@ public class SampleQueue implements TrackOutput {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
public final int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
return sampleDataQueue.sampleData(input, length, allowEndOfInput);
|
return sampleDataQueue.sampleData(input, length, allowEndOfInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
return castNonNull(trackOutput).sampleData(input, length, allowEndOfInput);
|
return castNonNull(trackOutput).sampleData(input, length, allowEndOfInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ public class ContainerMediaChunk extends BaseMediaChunk {
|
|||||||
|
|
||||||
@SuppressWarnings("NonAtomicVolatileUpdate")
|
@SuppressWarnings("NonAtomicVolatileUpdate")
|
||||||
@Override
|
@Override
|
||||||
public final void load() throws IOException, InterruptedException {
|
public final void load() throws IOException {
|
||||||
if (nextLoadPosition == 0) {
|
if (nextLoadPosition == 0) {
|
||||||
// Configure the output and set it as the target for the extractor wrapper.
|
// Configure the output and set it as the target for the extractor wrapper.
|
||||||
BaseMediaChunkOutput output = getOutput();
|
BaseMediaChunkOutput output = getOutput();
|
||||||
|
@ -77,7 +77,7 @@ public abstract class DataChunk extends Chunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void load() throws IOException, InterruptedException {
|
public final void load() throws IOException {
|
||||||
try {
|
try {
|
||||||
dataSource.open(dataSpec);
|
dataSource.open(dataSpec);
|
||||||
int limit = 0;
|
int limit = 0;
|
||||||
|
@ -83,7 +83,7 @@ public final class InitializationChunk extends Chunk {
|
|||||||
|
|
||||||
@SuppressWarnings("NonAtomicVolatileUpdate")
|
@SuppressWarnings("NonAtomicVolatileUpdate")
|
||||||
@Override
|
@Override
|
||||||
public void load() throws IOException, InterruptedException {
|
public void load() throws IOException {
|
||||||
if (nextLoadPosition == 0) {
|
if (nextLoadPosition == 0) {
|
||||||
extractorWrapper.init(
|
extractorWrapper.init(
|
||||||
trackOutputProvider, /* startTimeUs= */ C.TIME_UNSET, /* endTimeUs= */ C.TIME_UNSET);
|
trackOutputProvider, /* startTimeUs= */ C.TIME_UNSET, /* endTimeUs= */ C.TIME_UNSET);
|
||||||
|
@ -91,7 +91,7 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
|
|||||||
|
|
||||||
@SuppressWarnings("NonAtomicVolatileUpdate")
|
@SuppressWarnings("NonAtomicVolatileUpdate")
|
||||||
@Override
|
@Override
|
||||||
public void load() throws IOException, InterruptedException {
|
public void load() throws IOException {
|
||||||
BaseMediaChunkOutput output = getOutput();
|
BaseMediaChunkOutput output = getOutput();
|
||||||
output.setSampleOffsetUs(0);
|
output.setSampleOffsetUs(0);
|
||||||
TrackOutput trackOutput = output.track(0, trackType);
|
TrackOutput trackOutput = output.track(0, trackType);
|
||||||
|
@ -63,10 +63,8 @@ public final class Loader implements LoaderErrorThrower {
|
|||||||
* Performs the load, returning on completion or cancellation.
|
* Performs the load, returning on completion or cancellation.
|
||||||
*
|
*
|
||||||
* @throws IOException If the input could not be loaded.
|
* @throws IOException If the input could not be loaded.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
void load() throws IOException, InterruptedException;
|
void load() throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -400,12 +398,6 @@ public final class Loader implements LoaderErrorThrower {
|
|||||||
if (!released) {
|
if (!released) {
|
||||||
obtainMessage(MSG_IO_EXCEPTION, e).sendToTarget();
|
obtainMessage(MSG_IO_EXCEPTION, e).sendToTarget();
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// The load was canceled.
|
|
||||||
Assertions.checkState(canceled);
|
|
||||||
if (!released) {
|
|
||||||
sendEmptyMessage(MSG_END_OF_SOURCE);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// This should never happen, but handle it anyway.
|
// This should never happen, but handle it anyway.
|
||||||
Log.e(TAG, "Unexpected exception loading stream", e);
|
Log.e(TAG, "Unexpected exception loading stream", e);
|
||||||
|
@ -80,11 +80,10 @@ public final class DashUtil {
|
|||||||
* @param period The {@link Period}.
|
* @param period The {@link Period}.
|
||||||
* @return The loaded {@link DrmInitData}, or null if none is defined.
|
* @return The loaded {@link DrmInitData}, or null if none is defined.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
|
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int primaryTrackType = C.TRACK_TYPE_VIDEO;
|
int primaryTrackType = C.TRACK_TYPE_VIDEO;
|
||||||
Representation representation = getFirstRepresentation(period, primaryTrackType);
|
Representation representation = getFirstRepresentation(period, primaryTrackType);
|
||||||
if (representation == null) {
|
if (representation == null) {
|
||||||
@ -110,12 +109,10 @@ public final class DashUtil {
|
|||||||
* @param representation The representation which initialization chunk belongs to.
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
* @return the sample {@link Format} of the given representation.
|
* @return the sample {@link Format} of the given representation.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Format loadSampleFormat(
|
public static Format loadSampleFormat(
|
||||||
DataSource dataSource, int trackType, Representation representation)
|
DataSource dataSource, int trackType, Representation representation) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
||||||
representation, false);
|
representation, false);
|
||||||
return extractorWrapper == null
|
return extractorWrapper == null
|
||||||
@ -134,12 +131,10 @@ public final class DashUtil {
|
|||||||
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
|
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
|
||||||
* index data exists.
|
* index data exists.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static ChunkIndex loadChunkIndex(
|
public static ChunkIndex loadChunkIndex(
|
||||||
DataSource dataSource, int trackType, Representation representation)
|
DataSource dataSource, int trackType, Representation representation) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
||||||
representation, true);
|
representation, true);
|
||||||
return extractorWrapper == null ? null : (ChunkIndex) extractorWrapper.getSeekMap();
|
return extractorWrapper == null ? null : (ChunkIndex) extractorWrapper.getSeekMap();
|
||||||
@ -157,12 +152,11 @@ public final class DashUtil {
|
|||||||
* @return A {@link ChunkExtractorWrapper} for the {@code representation}, or null if no
|
* @return A {@link ChunkExtractorWrapper} for the {@code representation}, or null if no
|
||||||
* initialization or (if requested) index data exists.
|
* initialization or (if requested) index data exists.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private static ChunkExtractorWrapper loadInitializationData(
|
private static ChunkExtractorWrapper loadInitializationData(
|
||||||
DataSource dataSource, int trackType, Representation representation, boolean loadIndex)
|
DataSource dataSource, int trackType, Representation representation, boolean loadIndex)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
RangedUri initializationUri = representation.getInitializationUri();
|
RangedUri initializationUri = representation.getInitializationUri();
|
||||||
if (initializationUri == null) {
|
if (initializationUri == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -188,9 +182,12 @@ public final class DashUtil {
|
|||||||
return extractorWrapper;
|
return extractorWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadInitializationData(DataSource dataSource,
|
private static void loadInitializationData(
|
||||||
Representation representation, ChunkExtractorWrapper extractorWrapper, RangedUri requestUri)
|
DataSource dataSource,
|
||||||
throws IOException, InterruptedException {
|
Representation representation,
|
||||||
|
ChunkExtractorWrapper extractorWrapper,
|
||||||
|
RangedUri requestUri)
|
||||||
|
throws IOException {
|
||||||
DataSpec dataSpec = DashUtil.buildDataSpec(representation, requestUri);
|
DataSpec dataSpec = DashUtil.buildDataSpec(representation, requestUri);
|
||||||
InitializationChunk initializationChunk = new InitializationChunk(dataSource, dataSpec,
|
InitializationChunk initializationChunk = new InitializationChunk(dataSource, dataSpec,
|
||||||
representation.format, C.SELECTION_REASON_UNKNOWN, null /* trackSelectionData */,
|
representation.format, C.SELECTION_REASON_UNKNOWN, null /* trackSelectionData */,
|
||||||
|
@ -296,7 +296,7 @@ public final class PlayerEmsgHandler implements Handler.Callback {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
return sampleQueue.sampleData(input, length, allowEndOfInput);
|
return sampleQueue.sampleData(input, length, allowEndOfInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,10 +49,9 @@ public abstract class BinarySearchSeeker {
|
|||||||
* @param targetTimestamp The target timestamp.
|
* @param targetTimestamp The target timestamp.
|
||||||
* @return A {@link TimestampSearchResult} that describes the result of the search.
|
* @return A {@link TimestampSearchResult} that describes the result of the search.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetTimestamp)
|
TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetTimestamp)
|
||||||
throws IOException, InterruptedException;
|
throws IOException;
|
||||||
|
|
||||||
/** Called when a seek operation finishes. */
|
/** Called when a seek operation finishes. */
|
||||||
default void onSeekFinished() {}
|
default void onSeekFinished() {}
|
||||||
@ -169,10 +168,9 @@ public abstract class BinarySearchSeeker {
|
|||||||
* to hold the position of the required seek.
|
* to hold the position of the required seek.
|
||||||
* @return One of the {@code RESULT_} values defined in {@link Extractor}.
|
* @return One of the {@code RESULT_} values defined in {@link Extractor}.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
public int handlePendingSeek(ExtractorInput input, PositionHolder seekPositionHolder)
|
public int handlePendingSeek(ExtractorInput input, PositionHolder seekPositionHolder)
|
||||||
throws InterruptedException, IOException {
|
throws IOException {
|
||||||
while (true) {
|
while (true) {
|
||||||
SeekOperationParams seekOperationParams =
|
SeekOperationParams seekOperationParams =
|
||||||
Assertions.checkStateNotNull(this.seekOperationParams);
|
Assertions.checkStateNotNull(this.seekOperationParams);
|
||||||
@ -241,7 +239,7 @@ public abstract class BinarySearchSeeker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected final boolean skipInputUntilPosition(ExtractorInput input, long position)
|
protected final boolean skipInputUntilPosition(ExtractorInput input, long position)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long bytesToSkip = position - input.getPosition();
|
long bytesToSkip = position - input.getPosition();
|
||||||
if (bytesToSkip >= 0 && bytesToSkip <= MAX_SKIP_BYTES) {
|
if (bytesToSkip >= 0 && bytesToSkip <= MAX_SKIP_BYTES) {
|
||||||
input.skipFully((int) bytesToSkip);
|
input.skipFully((int) bytesToSkip);
|
||||||
|
@ -21,6 +21,7 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InterruptedIOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +56,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] target, int offset, int length) throws IOException, InterruptedException {
|
public int read(byte[] target, int offset, int length) throws IOException {
|
||||||
int bytesRead = readFromPeekBuffer(target, offset, length);
|
int bytesRead = readFromPeekBuffer(target, offset, length);
|
||||||
if (bytesRead == 0) {
|
if (bytesRead == 0) {
|
||||||
bytesRead =
|
bytesRead =
|
||||||
@ -68,7 +69,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean readFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
public boolean readFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int bytesRead = readFromPeekBuffer(target, offset, length);
|
int bytesRead = readFromPeekBuffer(target, offset, length);
|
||||||
while (bytesRead < length && bytesRead != C.RESULT_END_OF_INPUT) {
|
while (bytesRead < length && bytesRead != C.RESULT_END_OF_INPUT) {
|
||||||
bytesRead = readFromDataSource(target, offset, length, bytesRead, allowEndOfInput);
|
bytesRead = readFromDataSource(target, offset, length, bytesRead, allowEndOfInput);
|
||||||
@ -78,13 +79,12 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readFully(byte[] target, int offset, int length)
|
public void readFully(byte[] target, int offset, int length) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
readFully(target, offset, length, false);
|
readFully(target, offset, length, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int skip(int length) throws IOException, InterruptedException {
|
public int skip(int length) throws IOException {
|
||||||
int bytesSkipped = skipFromPeekBuffer(length);
|
int bytesSkipped = skipFromPeekBuffer(length);
|
||||||
if (bytesSkipped == 0) {
|
if (bytesSkipped == 0) {
|
||||||
bytesSkipped =
|
bytesSkipped =
|
||||||
@ -95,8 +95,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean skipFully(int length, boolean allowEndOfInput)
|
public boolean skipFully(int length, boolean allowEndOfInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
int bytesSkipped = skipFromPeekBuffer(length);
|
int bytesSkipped = skipFromPeekBuffer(length);
|
||||||
while (bytesSkipped < length && bytesSkipped != C.RESULT_END_OF_INPUT) {
|
while (bytesSkipped < length && bytesSkipped != C.RESULT_END_OF_INPUT) {
|
||||||
int minLength = Math.min(length, bytesSkipped + scratchSpace.length);
|
int minLength = Math.min(length, bytesSkipped + scratchSpace.length);
|
||||||
@ -108,12 +107,12 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skipFully(int length) throws IOException, InterruptedException {
|
public void skipFully(int length) throws IOException {
|
||||||
skipFully(length, false);
|
skipFully(length, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int peek(byte[] target, int offset, int length) throws IOException, InterruptedException {
|
public int peek(byte[] target, int offset, int length) throws IOException {
|
||||||
ensureSpaceForPeek(length);
|
ensureSpaceForPeek(length);
|
||||||
int peekBufferRemainingBytes = peekBufferLength - peekBufferPosition;
|
int peekBufferRemainingBytes = peekBufferLength - peekBufferPosition;
|
||||||
int bytesPeeked;
|
int bytesPeeked;
|
||||||
@ -139,7 +138,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean peekFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
public boolean peekFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
if (!advancePeekPosition(length, allowEndOfInput)) {
|
if (!advancePeekPosition(length, allowEndOfInput)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -148,14 +147,12 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void peekFully(byte[] target, int offset, int length)
|
public void peekFully(byte[] target, int offset, int length) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
peekFully(target, offset, length, false);
|
peekFully(target, offset, length, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean advancePeekPosition(int length, boolean allowEndOfInput)
|
public boolean advancePeekPosition(int length, boolean allowEndOfInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
ensureSpaceForPeek(length);
|
ensureSpaceForPeek(length);
|
||||||
int bytesPeeked = peekBufferLength - peekBufferPosition;
|
int bytesPeeked = peekBufferLength - peekBufferPosition;
|
||||||
while (bytesPeeked < length) {
|
while (bytesPeeked < length) {
|
||||||
@ -171,7 +168,7 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void advancePeekPosition(int length) throws IOException, InterruptedException {
|
public void advancePeekPosition(int length) throws IOException {
|
||||||
advancePeekPosition(length, false);
|
advancePeekPosition(length, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,18 +268,18 @@ public final class DefaultExtractorInput implements ExtractorInput {
|
|||||||
* @param allowEndOfInput True if encountering the end of the input having read no data is
|
* @param allowEndOfInput True if encountering the end of the input having read no data is
|
||||||
* allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
|
* allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
|
||||||
* should be considered an error, causing an {@link EOFException} to be thrown.
|
* should be considered an error, causing an {@link EOFException} to be thrown.
|
||||||
* @return The total number of bytes read so far, or {@link C#RESULT_END_OF_INPUT} if
|
* @return The total number of bytes read so far, or {@link C#RESULT_END_OF_INPUT} if {@code
|
||||||
* {@code allowEndOfInput} is true and the input has ended having read no bytes.
|
* allowEndOfInput} is true and the input has ended having read no bytes.
|
||||||
* @throws EOFException If the end of input was encountered having partially satisfied the read
|
* @throws EOFException If the end of input was encountered having partially satisfied the read
|
||||||
* (i.e. having read at least one byte, but fewer than {@code length}), or if no bytes were
|
* (i.e. having read at least one byte, but fewer than {@code length}), or if no bytes were
|
||||||
* read and {@code allowEndOfInput} is false.
|
* read and {@code allowEndOfInput} is false.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
private int readFromDataSource(byte[] target, int offset, int length, int bytesAlreadyRead,
|
private int readFromDataSource(
|
||||||
boolean allowEndOfInput) throws InterruptedException, IOException {
|
byte[] target, int offset, int length, int bytesAlreadyRead, boolean allowEndOfInput)
|
||||||
|
throws IOException {
|
||||||
if (Thread.interrupted()) {
|
if (Thread.interrupted()) {
|
||||||
throw new InterruptedException();
|
throw new InterruptedIOException();
|
||||||
}
|
}
|
||||||
int bytesRead = dataSource.read(target, offset + bytesAlreadyRead, length - bytesAlreadyRead);
|
int bytesRead = dataSource.read(target, offset + bytesAlreadyRead, length - bytesAlreadyRead);
|
||||||
if (bytesRead == C.RESULT_END_OF_INPUT) {
|
if (bytesRead == C.RESULT_END_OF_INPUT) {
|
||||||
|
@ -43,8 +43,7 @@ public final class DummyTrackOutput implements TrackOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
public int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
int bytesToSkipByReading = Math.min(readBuffer.length, length);
|
int bytesToSkipByReading = Math.min(readBuffer.length, length);
|
||||||
int bytesSkipped = input.read(readBuffer, /* offset= */ 0, bytesToSkipByReading);
|
int bytesSkipped = input.read(readBuffer, /* offset= */ 0, bytesToSkipByReading);
|
||||||
if (bytesSkipped == C.RESULT_END_OF_INPUT) {
|
if (bytesSkipped == C.RESULT_END_OF_INPUT) {
|
||||||
|
@ -57,16 +57,15 @@ public interface Extractor {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this extractor can extract samples from the {@link ExtractorInput}, which must
|
* Returns whether this extractor can extract samples from the {@link ExtractorInput}, which must
|
||||||
* provide data from the start of the stream.
|
* provide data from the start of the stream.
|
||||||
* <p>
|
*
|
||||||
* If {@code true} is returned, the {@code input}'s reading position may have been modified.
|
* <p>If {@code true} is returned, the {@code input}'s reading position may have been modified.
|
||||||
* Otherwise, only its peek position may have been modified.
|
* Otherwise, only its peek position may have been modified.
|
||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} from which data should be peeked/read.
|
* @param input The {@link ExtractorInput} from which data should be peeked/read.
|
||||||
* @return Whether this extractor can read the provided input.
|
* @return Whether this extractor can read the provided input.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
boolean sniff(ExtractorInput input) throws IOException, InterruptedException;
|
boolean sniff(ExtractorInput input) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the extractor with an {@link ExtractorOutput}. Called at most once.
|
* Initializes the extractor with an {@link ExtractorOutput}. Called at most once.
|
||||||
@ -89,20 +88,18 @@ public interface Extractor {
|
|||||||
* {@link #RESULT_SEEK} is returned. If the extractor reached the end of the data provided by the
|
* {@link #RESULT_SEEK} is returned. If the extractor reached the end of the data provided by the
|
||||||
* {@link ExtractorInput}, then {@link #RESULT_END_OF_INPUT} is returned.
|
* {@link ExtractorInput}, then {@link #RESULT_END_OF_INPUT} is returned.
|
||||||
*
|
*
|
||||||
* <p>When this method throws an {@link IOException} or an {@link InterruptedException},
|
* <p>When this method throws an {@link IOException}, extraction may continue by providing an
|
||||||
* extraction may continue by providing an {@link ExtractorInput} with an unchanged {@link
|
* {@link ExtractorInput} with an unchanged {@link ExtractorInput#getPosition() read position} to
|
||||||
* ExtractorInput#getPosition() read position} to a subsequent call to this method.
|
* a subsequent call to this method.
|
||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} from which data should be read.
|
* @param input The {@link ExtractorInput} from which data should be read.
|
||||||
* @param seekPosition If {@link #RESULT_SEEK} is returned, this holder is updated to hold the
|
* @param seekPosition If {@link #RESULT_SEEK} is returned, this holder is updated to hold the
|
||||||
* position of the required data.
|
* position of the required data.
|
||||||
* @return One of the {@code RESULT_} values defined in this interface.
|
* @return One of the {@code RESULT_} values defined in this interface.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@ReadResult
|
@ReadResult
|
||||||
int read(ExtractorInput input, PositionHolder seekPosition)
|
int read(ExtractorInput input, PositionHolder seekPosition) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the extractor that a seek has occurred.
|
* Notifies the extractor that a seek has occurred.
|
||||||
|
@ -68,8 +68,8 @@ public interface ExtractorInput extends DataReader {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads up to {@code length} bytes from the input and resets the peek position.
|
* Reads up to {@code length} bytes from the input and resets the peek position.
|
||||||
* <p>
|
*
|
||||||
* This method blocks until at least one byte of data can be read, the end of the input is
|
* <p>This method blocks until at least one byte of data can be read, the end of the input is
|
||||||
* detected, or an exception is thrown.
|
* detected, or an exception is thrown.
|
||||||
*
|
*
|
||||||
* @param target A target array into which data should be written.
|
* @param target A target array into which data should be written.
|
||||||
@ -77,9 +77,9 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* @param length The maximum number of bytes to read from the input.
|
* @param length The maximum number of bytes to read from the input.
|
||||||
* @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
|
* @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
int read(byte[] target, int offset, int length) throws IOException, InterruptedException;
|
@Override
|
||||||
|
int read(byte[] target, int offset, int length) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #read(byte[], int, int)}, but reads the requested {@code length} in full.
|
* Like {@link #read(byte[], int, int)}, but reads the requested {@code length} in full.
|
||||||
@ -97,10 +97,9 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* (i.e. having read at least one byte, but fewer than {@code length}), or if no bytes were
|
* (i.e. having read at least one byte, but fewer than {@code length}), or if no bytes were
|
||||||
* read and {@code allowEndOfInput} is false.
|
* read and {@code allowEndOfInput} is false.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
boolean readFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
boolean readFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent to {@link #readFully(byte[], int, int, boolean) readFully(target, offset, length,
|
* Equivalent to {@link #readFully(byte[], int, int, boolean) readFully(target, offset, length,
|
||||||
@ -111,9 +110,8 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* @param length The number of bytes to read from the input.
|
* @param length The number of bytes to read from the input.
|
||||||
* @throws EOFException If the end of input was encountered.
|
* @throws EOFException If the end of input was encountered.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
void readFully(byte[] target, int offset, int length) throws IOException, InterruptedException;
|
void readFully(byte[] target, int offset, int length) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #read(byte[], int, int)}, except the data is skipped instead of read.
|
* Like {@link #read(byte[], int, int)}, except the data is skipped instead of read.
|
||||||
@ -121,9 +119,8 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* @param length The maximum number of bytes to skip from the input.
|
* @param length The maximum number of bytes to skip from the input.
|
||||||
* @return The number of bytes skipped, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
|
* @return The number of bytes skipped, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
int skip(int length) throws IOException, InterruptedException;
|
int skip(int length) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #readFully(byte[], int, int, boolean)}, except the data is skipped instead of read.
|
* Like {@link #readFully(byte[], int, int, boolean)}, except the data is skipped instead of read.
|
||||||
@ -139,22 +136,20 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* (i.e. having skipped at least one byte, but fewer than {@code length}), or if no bytes were
|
* (i.e. having skipped at least one byte, but fewer than {@code length}), or if no bytes were
|
||||||
* skipped and {@code allowEndOfInput} is false.
|
* skipped and {@code allowEndOfInput} is false.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
boolean skipFully(int length, boolean allowEndOfInput) throws IOException, InterruptedException;
|
boolean skipFully(int length, boolean allowEndOfInput) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #readFully(byte[], int, int)}, except the data is skipped instead of read.
|
* Like {@link #readFully(byte[], int, int)}, except the data is skipped instead of read.
|
||||||
* <p>
|
*
|
||||||
* Encountering the end of input is always considered an error, and will result in an
|
* <p>Encountering the end of input is always considered an error, and will result in an {@link
|
||||||
* {@link EOFException} being thrown.
|
* EOFException} being thrown.
|
||||||
*
|
*
|
||||||
* @param length The number of bytes to skip from the input.
|
* @param length The number of bytes to skip from the input.
|
||||||
* @throws EOFException If the end of input was encountered.
|
* @throws EOFException If the end of input was encountered.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
void skipFully(int length) throws IOException, InterruptedException;
|
void skipFully(int length) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peeks up to {@code length} bytes from the peek position. The current read position is left
|
* Peeks up to {@code length} bytes from the peek position. The current read position is left
|
||||||
@ -172,9 +167,8 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* @param length The maximum number of bytes to peek from the input.
|
* @param length The maximum number of bytes to peek from the input.
|
||||||
* @return The number of bytes peeked, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
|
* @return The number of bytes peeked, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
|
||||||
* @throws IOException If an error occurs peeking from the input.
|
* @throws IOException If an error occurs peeking from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
int peek(byte[] target, int offset, int length) throws IOException, InterruptedException;
|
int peek(byte[] target, int offset, int length) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #peek(byte[], int, int)}, but peeks the requested {@code length} in full.
|
* Like {@link #peek(byte[], int, int)}, but peeks the requested {@code length} in full.
|
||||||
@ -192,10 +186,9 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* (i.e. having peeked at least one byte, but fewer than {@code length}), or if no bytes were
|
* (i.e. having peeked at least one byte, but fewer than {@code length}), or if no bytes were
|
||||||
* peeked and {@code allowEndOfInput} is false.
|
* peeked and {@code allowEndOfInput} is false.
|
||||||
* @throws IOException If an error occurs peeking from the input.
|
* @throws IOException If an error occurs peeking from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
boolean peekFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
boolean peekFully(byte[] target, int offset, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException;
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent to {@link #peekFully(byte[], int, int, boolean) peekFully(target, offset, length,
|
* Equivalent to {@link #peekFully(byte[], int, int, boolean) peekFully(target, offset, length,
|
||||||
@ -206,9 +199,8 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* @param length The number of bytes to peek from the input.
|
* @param length The number of bytes to peek from the input.
|
||||||
* @throws EOFException If the end of input was encountered.
|
* @throws EOFException If the end of input was encountered.
|
||||||
* @throws IOException If an error occurs peeking from the input.
|
* @throws IOException If an error occurs peeking from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
void peekFully(byte[] target, int offset, int length) throws IOException, InterruptedException;
|
void peekFully(byte[] target, int offset, int length) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Advances the peek position by {@code length} bytes. Like {@link #peekFully(byte[], int, int,
|
* Advances the peek position by {@code length} bytes. Like {@link #peekFully(byte[], int, int,
|
||||||
@ -225,10 +217,8 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* advanced by at least one byte, but fewer than {@code length}), or if the end of input was
|
* advanced by at least one byte, but fewer than {@code length}), or if the end of input was
|
||||||
* encountered before advancing and {@code allowEndOfInput} is false.
|
* encountered before advancing and {@code allowEndOfInput} is false.
|
||||||
* @throws IOException If an error occurs advancing the peek position.
|
* @throws IOException If an error occurs advancing the peek position.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
boolean advancePeekPosition(int length, boolean allowEndOfInput)
|
boolean advancePeekPosition(int length, boolean allowEndOfInput) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Advances the peek position by {@code length} bytes. Like {@link #peekFully(byte[], int, int)}
|
* Advances the peek position by {@code length} bytes. Like {@link #peekFully(byte[], int, int)}
|
||||||
@ -237,9 +227,8 @@ public interface ExtractorInput extends DataReader {
|
|||||||
* @param length The number of bytes to peek from the input.
|
* @param length The number of bytes to peek from the input.
|
||||||
* @throws EOFException If the end of input was encountered.
|
* @throws EOFException If the end of input was encountered.
|
||||||
* @throws IOException If an error occurs peeking from the input.
|
* @throws IOException If an error occurs peeking from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
void advancePeekPosition(int length) throws IOException, InterruptedException;
|
void advancePeekPosition(int length) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the peek position to equal the current read position.
|
* Resets the peek position to equal the current read position.
|
||||||
|
@ -33,10 +33,9 @@ import java.io.IOException;
|
|||||||
* @param length The maximum number of bytes to peek from the input.
|
* @param length The maximum number of bytes to peek from the input.
|
||||||
* @return The number of bytes peeked.
|
* @return The number of bytes peeked.
|
||||||
* @throws IOException If an error occurs peeking from the input.
|
* @throws IOException If an error occurs peeking from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
public static int peekToLength(ExtractorInput input, byte[] target, int offset, int length)
|
public static int peekToLength(ExtractorInput input, byte[] target, int offset, int length)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int totalBytesPeeked = 0;
|
int totalBytesPeeked = 0;
|
||||||
while (totalBytesPeeked < length) {
|
while (totalBytesPeeked < length) {
|
||||||
int bytesPeeked = input.peek(target, offset + totalBytesPeeked, length - totalBytesPeeked);
|
int bytesPeeked = input.peek(target, offset + totalBytesPeeked, length - totalBytesPeeked);
|
||||||
|
@ -93,7 +93,7 @@ public final class FlacFrameReader {
|
|||||||
FlacStreamMetadata flacStreamMetadata,
|
FlacStreamMetadata flacStreamMetadata,
|
||||||
int frameStartMarker,
|
int frameStartMarker,
|
||||||
SampleNumberHolder sampleNumberHolder)
|
SampleNumberHolder sampleNumberHolder)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long originalPeekPosition = input.getPeekPosition();
|
long originalPeekPosition = input.getPeekPosition();
|
||||||
|
|
||||||
byte[] frameStartBytes = new byte[2];
|
byte[] frameStartBytes = new byte[2];
|
||||||
@ -132,11 +132,9 @@ public final class FlacFrameReader {
|
|||||||
* @return The frame first sample number.
|
* @return The frame first sample number.
|
||||||
* @throws ParserException If an error occurs parsing the sample number.
|
* @throws ParserException If an error occurs parsing the sample number.
|
||||||
* @throws IOException If peeking from the input fails.
|
* @throws IOException If peeking from the input fails.
|
||||||
* @throws InterruptedException If interrupted while peeking from input.
|
|
||||||
*/
|
*/
|
||||||
public static long getFirstSampleNumber(
|
public static long getFirstSampleNumber(
|
||||||
ExtractorInput input, FlacStreamMetadata flacStreamMetadata)
|
ExtractorInput input, FlacStreamMetadata flacStreamMetadata) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
input.advancePeekPosition(1);
|
input.advancePeekPosition(1);
|
||||||
byte[] blockingStrategyByte = new byte[1];
|
byte[] blockingStrategyByte = new byte[1];
|
||||||
|
@ -60,12 +60,10 @@ public final class FlacMetadataReader {
|
|||||||
* is {@code false}.
|
* is {@code false}.
|
||||||
* @throws IOException If peeking from the input fails. In this case, there is no guarantee on the
|
* @throws IOException If peeking from the input fails. In this case, there is no guarantee on the
|
||||||
* peek position.
|
* peek position.
|
||||||
* @throws InterruptedException If interrupted while peeking from input. In this case, there is no
|
|
||||||
* guarantee on the peek position.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Metadata peekId3Metadata(ExtractorInput input, boolean parseData)
|
public static Metadata peekId3Metadata(ExtractorInput input, boolean parseData)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
@Nullable
|
@Nullable
|
||||||
Id3Decoder.FramePredicate id3FramePredicate = parseData ? null : Id3Decoder.NO_FRAMES_PREDICATE;
|
Id3Decoder.FramePredicate id3FramePredicate = parseData ? null : Id3Decoder.NO_FRAMES_PREDICATE;
|
||||||
@Nullable Metadata id3Metadata = new Id3Peeker().peekId3Data(input, id3FramePredicate);
|
@Nullable Metadata id3Metadata = new Id3Peeker().peekId3Data(input, id3FramePredicate);
|
||||||
@ -79,11 +77,8 @@ public final class FlacMetadataReader {
|
|||||||
* @return Whether the data peeked is the FLAC stream marker.
|
* @return Whether the data peeked is the FLAC stream marker.
|
||||||
* @throws IOException If peeking from the input fails. In this case, the peek position is left
|
* @throws IOException If peeking from the input fails. In this case, the peek position is left
|
||||||
* unchanged.
|
* unchanged.
|
||||||
* @throws InterruptedException If interrupted while peeking from input. In this case, the peek
|
|
||||||
* position is left unchanged.
|
|
||||||
*/
|
*/
|
||||||
public static boolean checkAndPeekStreamMarker(ExtractorInput input)
|
public static boolean checkAndPeekStreamMarker(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
ParsableByteArray scratch = new ParsableByteArray(FlacConstants.STREAM_MARKER_SIZE);
|
ParsableByteArray scratch = new ParsableByteArray(FlacConstants.STREAM_MARKER_SIZE);
|
||||||
input.peekFully(scratch.data, 0, FlacConstants.STREAM_MARKER_SIZE);
|
input.peekFully(scratch.data, 0, FlacConstants.STREAM_MARKER_SIZE);
|
||||||
return scratch.readUnsignedInt() == STREAM_MARKER;
|
return scratch.readUnsignedInt() == STREAM_MARKER;
|
||||||
@ -101,12 +96,10 @@ public final class FlacMetadataReader {
|
|||||||
* is {@code false}.
|
* is {@code false}.
|
||||||
* @throws IOException If reading from the input fails. In this case, the read position is left
|
* @throws IOException If reading from the input fails. In this case, the read position is left
|
||||||
* unchanged and there is no guarantee on the peek position.
|
* unchanged and there is no guarantee on the peek position.
|
||||||
* @throws InterruptedException If interrupted while reading from input. In this case, the read
|
|
||||||
* position is left unchanged and there is no guarantee on the peek position.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Metadata readId3Metadata(ExtractorInput input, boolean parseData)
|
public static Metadata readId3Metadata(ExtractorInput input, boolean parseData)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
long startingPeekPosition = input.getPeekPosition();
|
long startingPeekPosition = input.getPeekPosition();
|
||||||
@Nullable Metadata id3Metadata = peekId3Metadata(input, parseData);
|
@Nullable Metadata id3Metadata = peekId3Metadata(input, parseData);
|
||||||
@ -123,11 +116,8 @@ public final class FlacMetadataReader {
|
|||||||
* position of {@code input} is advanced by {@link FlacConstants#STREAM_MARKER_SIZE} bytes.
|
* position of {@code input} is advanced by {@link FlacConstants#STREAM_MARKER_SIZE} bytes.
|
||||||
* @throws IOException If reading from the input fails. In this case, the position is left
|
* @throws IOException If reading from the input fails. In this case, the position is left
|
||||||
* unchanged.
|
* unchanged.
|
||||||
* @throws InterruptedException If interrupted while reading from input. In this case, the
|
|
||||||
* position is left unchanged.
|
|
||||||
*/
|
*/
|
||||||
public static void readStreamMarker(ExtractorInput input)
|
public static void readStreamMarker(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
ParsableByteArray scratch = new ParsableByteArray(FlacConstants.STREAM_MARKER_SIZE);
|
ParsableByteArray scratch = new ParsableByteArray(FlacConstants.STREAM_MARKER_SIZE);
|
||||||
input.readFully(scratch.data, 0, FlacConstants.STREAM_MARKER_SIZE);
|
input.readFully(scratch.data, 0, FlacConstants.STREAM_MARKER_SIZE);
|
||||||
if (scratch.readUnsignedInt() != STREAM_MARKER) {
|
if (scratch.readUnsignedInt() != STREAM_MARKER) {
|
||||||
@ -153,13 +143,9 @@ public final class FlacMetadataReader {
|
|||||||
* start of a metadata block and there is no guarantee on the peek position.
|
* start of a metadata block and there is no guarantee on the peek position.
|
||||||
* @throws IOException If reading from the input fails. In this case, the read position will be at
|
* @throws IOException If reading from the input fails. In this case, the read position will be at
|
||||||
* the start of a metadata block and there is no guarantee on the peek position.
|
* the start of a metadata block and there is no guarantee on the peek position.
|
||||||
* @throws InterruptedException If interrupted while reading from input. In this case, the read
|
|
||||||
* position will be at the start of a metadata block and there is no guarantee on the peek
|
|
||||||
* position.
|
|
||||||
*/
|
*/
|
||||||
public static boolean readMetadataBlock(
|
public static boolean readMetadataBlock(
|
||||||
ExtractorInput input, FlacStreamMetadataHolder metadataHolder)
|
ExtractorInput input, FlacStreamMetadataHolder metadataHolder) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
ParsableBitArray scratch = new ParsableBitArray(new byte[4]);
|
ParsableBitArray scratch = new ParsableBitArray(new byte[4]);
|
||||||
input.peekFully(scratch.data, 0, FlacConstants.METADATA_BLOCK_HEADER_SIZE);
|
input.peekFully(scratch.data, 0, FlacConstants.METADATA_BLOCK_HEADER_SIZE);
|
||||||
@ -239,10 +225,8 @@ public final class FlacMetadataReader {
|
|||||||
* @return The frame start marker (which must be the same for all the frames in the stream).
|
* @return The frame start marker (which must be the same for all the frames in the stream).
|
||||||
* @throws ParserException If an error occurs parsing the frame start marker.
|
* @throws ParserException If an error occurs parsing the frame start marker.
|
||||||
* @throws IOException If peeking from the input fails.
|
* @throws IOException If peeking from the input fails.
|
||||||
* @throws InterruptedException If interrupted while peeking from input.
|
|
||||||
*/
|
*/
|
||||||
public static int getFrameStartMarker(ExtractorInput input)
|
public static int getFrameStartMarker(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
ParsableByteArray scratch = new ParsableByteArray(2);
|
ParsableByteArray scratch = new ParsableByteArray(2);
|
||||||
input.peekFully(scratch.data, 0, 2);
|
input.peekFully(scratch.data, 0, 2);
|
||||||
@ -258,8 +242,7 @@ public final class FlacMetadataReader {
|
|||||||
return frameStartMarker;
|
return frameStartMarker;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FlacStreamMetadata readStreamInfoBlock(ExtractorInput input)
|
private static FlacStreamMetadata readStreamInfoBlock(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
byte[] scratchData = new byte[FlacConstants.STREAM_INFO_BLOCK_SIZE];
|
byte[] scratchData = new byte[FlacConstants.STREAM_INFO_BLOCK_SIZE];
|
||||||
input.readFully(scratchData, 0, FlacConstants.STREAM_INFO_BLOCK_SIZE);
|
input.readFully(scratchData, 0, FlacConstants.STREAM_INFO_BLOCK_SIZE);
|
||||||
return new FlacStreamMetadata(
|
return new FlacStreamMetadata(
|
||||||
@ -267,14 +250,14 @@ public final class FlacMetadataReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static FlacStreamMetadata.SeekTable readSeekTableMetadataBlock(
|
private static FlacStreamMetadata.SeekTable readSeekTableMetadataBlock(
|
||||||
ExtractorInput input, int length) throws IOException, InterruptedException {
|
ExtractorInput input, int length) throws IOException {
|
||||||
ParsableByteArray scratch = new ParsableByteArray(length);
|
ParsableByteArray scratch = new ParsableByteArray(length);
|
||||||
input.readFully(scratch.data, 0, length);
|
input.readFully(scratch.data, 0, length);
|
||||||
return readSeekTableMetadataBlock(scratch);
|
return readSeekTableMetadataBlock(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> readVorbisCommentMetadataBlock(ExtractorInput input, int length)
|
private static List<String> readVorbisCommentMetadataBlock(ExtractorInput input, int length)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
ParsableByteArray scratch = new ParsableByteArray(length);
|
ParsableByteArray scratch = new ParsableByteArray(length);
|
||||||
input.readFully(scratch.data, 0, length);
|
input.readFully(scratch.data, 0, length);
|
||||||
scratch.skipBytes(FlacConstants.METADATA_BLOCK_HEADER_SIZE);
|
scratch.skipBytes(FlacConstants.METADATA_BLOCK_HEADER_SIZE);
|
||||||
@ -285,7 +268,7 @@ public final class FlacMetadataReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static PictureFrame readPictureMetadataBlock(ExtractorInput input, int length)
|
private static PictureFrame readPictureMetadataBlock(ExtractorInput input, int length)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
ParsableByteArray scratch = new ParsableByteArray(length);
|
ParsableByteArray scratch = new ParsableByteArray(length);
|
||||||
input.readFully(scratch.data, 0, length);
|
input.readFully(scratch.data, 0, length);
|
||||||
scratch.skipBytes(FlacConstants.METADATA_BLOCK_HEADER_SIZE);
|
scratch.skipBytes(FlacConstants.METADATA_BLOCK_HEADER_SIZE);
|
||||||
|
@ -43,12 +43,11 @@ public final class Id3Peeker {
|
|||||||
* @return The first ID3 tag decoded into a {@link Metadata} object. May be null if ID3 tag is not
|
* @return The first ID3 tag decoded into a {@link Metadata} object. May be null if ID3 tag is not
|
||||||
* present in the input.
|
* present in the input.
|
||||||
* @throws IOException If an error occurred peeking from the input.
|
* @throws IOException If an error occurred peeking from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public Metadata peekId3Data(
|
public Metadata peekId3Data(
|
||||||
ExtractorInput input, @Nullable Id3Decoder.FramePredicate id3FramePredicate)
|
ExtractorInput input, @Nullable Id3Decoder.FramePredicate id3FramePredicate)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int peekedId3Bytes = 0;
|
int peekedId3Bytes = 0;
|
||||||
@Nullable Metadata metadata = null;
|
@Nullable Metadata metadata = null;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -111,10 +111,8 @@ public interface TrackOutput {
|
|||||||
* should be considered an error, causing an {@link EOFException} to be thrown.
|
* should be considered an error, causing an {@link EOFException} to be thrown.
|
||||||
* @return The number of bytes appended.
|
* @return The number of bytes appended.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to write sample data to the output.
|
* Called to write sample data to the output.
|
||||||
|
@ -160,7 +160,7 @@ public final class AmrExtractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
return readAmrHeader(input);
|
return readAmrHeader(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,8 +172,7 @@ public final class AmrExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
assertInitialized();
|
assertInitialized();
|
||||||
if (input.getPosition() == 0) {
|
if (input.getPosition() == 0) {
|
||||||
if (!readAmrHeader(input)) {
|
if (!readAmrHeader(input)) {
|
||||||
@ -227,7 +226,7 @@ public final class AmrExtractor implements Extractor {
|
|||||||
* @param input The {@link ExtractorInput} from which data should be peeked/read.
|
* @param input The {@link ExtractorInput} from which data should be peeked/read.
|
||||||
* @return Whether the AMR header has been read.
|
* @return Whether the AMR header has been read.
|
||||||
*/
|
*/
|
||||||
private boolean readAmrHeader(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean readAmrHeader(ExtractorInput input) throws IOException {
|
||||||
if (peekAmrSignature(input, amrSignatureNb)) {
|
if (peekAmrSignature(input, amrSignatureNb)) {
|
||||||
isWideBand = false;
|
isWideBand = false;
|
||||||
input.skipFully(amrSignatureNb.length);
|
input.skipFully(amrSignatureNb.length);
|
||||||
@ -241,8 +240,8 @@ public final class AmrExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Peeks from the beginning of the input to see if the given AMR signature exists. */
|
/** Peeks from the beginning of the input to see if the given AMR signature exists. */
|
||||||
private boolean peekAmrSignature(ExtractorInput input, byte[] amrSignature)
|
private static boolean peekAmrSignature(ExtractorInput input, byte[] amrSignature)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
byte[] header = new byte[amrSignature.length];
|
byte[] header = new byte[amrSignature.length];
|
||||||
input.peekFully(header, 0, amrSignature.length);
|
input.peekFully(header, 0, amrSignature.length);
|
||||||
@ -266,7 +265,7 @@ public final class AmrExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiresNonNull("trackOutput")
|
@RequiresNonNull("trackOutput")
|
||||||
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
|
private int readSample(ExtractorInput extractorInput) throws IOException {
|
||||||
if (currentSampleBytesRemaining == 0) {
|
if (currentSampleBytesRemaining == 0) {
|
||||||
try {
|
try {
|
||||||
currentSampleSize = peekNextSampleSize(extractorInput);
|
currentSampleSize = peekNextSampleSize(extractorInput);
|
||||||
@ -304,8 +303,7 @@ public final class AmrExtractor implements Extractor {
|
|||||||
return RESULT_CONTINUE;
|
return RESULT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int peekNextSampleSize(ExtractorInput extractorInput)
|
private int peekNextSampleSize(ExtractorInput extractorInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
extractorInput.resetPeekPosition();
|
extractorInput.resetPeekPosition();
|
||||||
extractorInput.peekFully(scratch, /* offset= */ 0, /* length= */ 1);
|
extractorInput.peekFully(scratch, /* offset= */ 0, /* length= */ 1);
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetSampleNumber)
|
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetSampleNumber)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long searchPosition = input.getPosition();
|
long searchPosition = input.getPosition();
|
||||||
|
|
||||||
// Find left frame.
|
// Find left frame.
|
||||||
@ -110,10 +110,8 @@ import java.io.IOException;
|
|||||||
* the stream if no frame was found.
|
* the stream if no frame was found.
|
||||||
* @throws IOException If peeking from the input fails. In this case, there is no guarantee on
|
* @throws IOException If peeking from the input fails. In this case, there is no guarantee on
|
||||||
* the peek position.
|
* the peek position.
|
||||||
* @throws InterruptedException If interrupted while peeking from input. In this case, there is
|
|
||||||
* no guarantee on the peek position.
|
|
||||||
*/
|
*/
|
||||||
private long findNextFrame(ExtractorInput input) throws IOException, InterruptedException {
|
private long findNextFrame(ExtractorInput input) throws IOException {
|
||||||
while (input.getPeekPosition() < input.getLength() - FlacConstants.MIN_FRAME_HEADER_SIZE
|
while (input.getPeekPosition() < input.getLength() - FlacConstants.MIN_FRAME_HEADER_SIZE
|
||||||
&& !FlacFrameReader.checkFrameHeaderFromPeek(
|
&& !FlacFrameReader.checkFrameHeaderFromPeek(
|
||||||
input, flacStreamMetadata, frameStartMarker, sampleNumberHolder)) {
|
input, flacStreamMetadata, frameStartMarker, sampleNumberHolder)) {
|
||||||
|
@ -134,7 +134,7 @@ public final class FlacExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
FlacMetadataReader.peekId3Metadata(input, /* parseData= */ false);
|
FlacMetadataReader.peekId3Metadata(input, /* parseData= */ false);
|
||||||
return FlacMetadataReader.checkAndPeekStreamMarker(input);
|
return FlacMetadataReader.checkAndPeekStreamMarker(input);
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ public final class FlacExtractor implements Extractor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @ReadResult int read(ExtractorInput input, PositionHolder seekPosition)
|
public @ReadResult int read(ExtractorInput input, PositionHolder seekPosition)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_READ_ID3_METADATA:
|
case STATE_READ_ID3_METADATA:
|
||||||
readId3Metadata(input);
|
readId3Metadata(input);
|
||||||
@ -191,24 +191,23 @@ public final class FlacExtractor implements Extractor {
|
|||||||
|
|
||||||
// Private methods.
|
// Private methods.
|
||||||
|
|
||||||
private void readId3Metadata(ExtractorInput input) throws IOException, InterruptedException {
|
private void readId3Metadata(ExtractorInput input) throws IOException {
|
||||||
id3Metadata = FlacMetadataReader.readId3Metadata(input, /* parseData= */ !id3MetadataDisabled);
|
id3Metadata = FlacMetadataReader.readId3Metadata(input, /* parseData= */ !id3MetadataDisabled);
|
||||||
state = STATE_GET_STREAM_MARKER_AND_INFO_BLOCK_BYTES;
|
state = STATE_GET_STREAM_MARKER_AND_INFO_BLOCK_BYTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getStreamMarkerAndInfoBlockBytes(ExtractorInput input)
|
private void getStreamMarkerAndInfoBlockBytes(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
input.peekFully(streamMarkerAndInfoBlock, 0, streamMarkerAndInfoBlock.length);
|
input.peekFully(streamMarkerAndInfoBlock, 0, streamMarkerAndInfoBlock.length);
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
state = STATE_READ_STREAM_MARKER;
|
state = STATE_READ_STREAM_MARKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readStreamMarker(ExtractorInput input) throws IOException, InterruptedException {
|
private void readStreamMarker(ExtractorInput input) throws IOException {
|
||||||
FlacMetadataReader.readStreamMarker(input);
|
FlacMetadataReader.readStreamMarker(input);
|
||||||
state = STATE_READ_METADATA_BLOCKS;
|
state = STATE_READ_METADATA_BLOCKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readMetadataBlocks(ExtractorInput input) throws IOException, InterruptedException {
|
private void readMetadataBlocks(ExtractorInput input) throws IOException {
|
||||||
boolean isLastMetadataBlock = false;
|
boolean isLastMetadataBlock = false;
|
||||||
FlacMetadataReader.FlacStreamMetadataHolder metadataHolder =
|
FlacMetadataReader.FlacStreamMetadataHolder metadataHolder =
|
||||||
new FlacMetadataReader.FlacStreamMetadataHolder(flacStreamMetadata);
|
new FlacMetadataReader.FlacStreamMetadataHolder(flacStreamMetadata);
|
||||||
@ -226,7 +225,7 @@ public final class FlacExtractor implements Extractor {
|
|||||||
state = STATE_GET_FRAME_START_MARKER;
|
state = STATE_GET_FRAME_START_MARKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getFrameStartMarker(ExtractorInput input) throws IOException, InterruptedException {
|
private void getFrameStartMarker(ExtractorInput input) throws IOException {
|
||||||
frameStartMarker = FlacMetadataReader.getFrameStartMarker(input);
|
frameStartMarker = FlacMetadataReader.getFrameStartMarker(input);
|
||||||
castNonNull(extractorOutput)
|
castNonNull(extractorOutput)
|
||||||
.seekMap(
|
.seekMap(
|
||||||
@ -238,7 +237,7 @@ public final class FlacExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private @ReadResult int readFrames(ExtractorInput input, PositionHolder seekPosition)
|
private @ReadResult int readFrames(ExtractorInput input, PositionHolder seekPosition)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
Assertions.checkNotNull(trackOutput);
|
Assertions.checkNotNull(trackOutput);
|
||||||
Assertions.checkNotNull(flacStreamMetadata);
|
Assertions.checkNotNull(flacStreamMetadata);
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ public final class FlvExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
// Check if file starts with "FLV" tag
|
// Check if file starts with "FLV" tag
|
||||||
input.peekFully(scratch.data, 0, 3);
|
input.peekFully(scratch.data, 0, 3);
|
||||||
scratch.setPosition(0);
|
scratch.setPosition(0);
|
||||||
@ -144,8 +144,7 @@ public final class FlvExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException,
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
InterruptedException {
|
|
||||||
Assertions.checkStateNotNull(extractorOutput); // Asserts that init has been called.
|
Assertions.checkStateNotNull(extractorOutput); // Asserts that init has been called.
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -180,10 +179,9 @@ public final class FlvExtractor implements Extractor {
|
|||||||
* @param input The {@link ExtractorInput} from which to read.
|
* @param input The {@link ExtractorInput} from which to read.
|
||||||
* @return True if header was read successfully. False if the end of stream was reached.
|
* @return True if header was read successfully. False if the end of stream was reached.
|
||||||
* @throws IOException If an error occurred reading or parsing data from the source.
|
* @throws IOException If an error occurred reading or parsing data from the source.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@RequiresNonNull("extractorOutput")
|
@RequiresNonNull("extractorOutput")
|
||||||
private boolean readFlvHeader(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean readFlvHeader(ExtractorInput input) throws IOException {
|
||||||
if (!input.readFully(headerBuffer.data, 0, FLV_HEADER_SIZE, true)) {
|
if (!input.readFully(headerBuffer.data, 0, FLV_HEADER_SIZE, true)) {
|
||||||
// We've reached the end of the stream.
|
// We've reached the end of the stream.
|
||||||
return false;
|
return false;
|
||||||
@ -215,9 +213,8 @@ public final class FlvExtractor implements Extractor {
|
|||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} from which to read.
|
* @param input The {@link ExtractorInput} from which to read.
|
||||||
* @throws IOException If an error occurred skipping data from the source.
|
* @throws IOException If an error occurred skipping data from the source.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
private void skipToTagHeader(ExtractorInput input) throws IOException, InterruptedException {
|
private void skipToTagHeader(ExtractorInput input) throws IOException {
|
||||||
input.skipFully(bytesToNextTagHeader);
|
input.skipFully(bytesToNextTagHeader);
|
||||||
bytesToNextTagHeader = 0;
|
bytesToNextTagHeader = 0;
|
||||||
state = STATE_READING_TAG_HEADER;
|
state = STATE_READING_TAG_HEADER;
|
||||||
@ -229,9 +226,8 @@ public final class FlvExtractor implements Extractor {
|
|||||||
* @param input The {@link ExtractorInput} from which to read.
|
* @param input The {@link ExtractorInput} from which to read.
|
||||||
* @return True if tag header was read successfully. Otherwise, false.
|
* @return True if tag header was read successfully. Otherwise, false.
|
||||||
* @throws IOException If an error occurred reading or parsing data from the source.
|
* @throws IOException If an error occurred reading or parsing data from the source.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
private boolean readTagHeader(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean readTagHeader(ExtractorInput input) throws IOException {
|
||||||
if (!input.readFully(tagHeaderBuffer.data, 0, FLV_TAG_HEADER_SIZE, true)) {
|
if (!input.readFully(tagHeaderBuffer.data, 0, FLV_TAG_HEADER_SIZE, true)) {
|
||||||
// We've reached the end of the stream.
|
// We've reached the end of the stream.
|
||||||
return false;
|
return false;
|
||||||
@ -253,10 +249,9 @@ public final class FlvExtractor implements Extractor {
|
|||||||
* @param input The {@link ExtractorInput} from which to read.
|
* @param input The {@link ExtractorInput} from which to read.
|
||||||
* @return True if the data was consumed by a reader. False if it was skipped.
|
* @return True if the data was consumed by a reader. False if it was skipped.
|
||||||
* @throws IOException If an error occurred reading or parsing data from the source.
|
* @throws IOException If an error occurred reading or parsing data from the source.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
@RequiresNonNull("extractorOutput")
|
@RequiresNonNull("extractorOutput")
|
||||||
private boolean readTagData(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean readTagData(ExtractorInput input) throws IOException {
|
||||||
boolean wasConsumed = true;
|
boolean wasConsumed = true;
|
||||||
boolean wasSampleOutput = false;
|
boolean wasSampleOutput = false;
|
||||||
long timestampUs = getCurrentTimestampUs();
|
long timestampUs = getCurrentTimestampUs();
|
||||||
@ -287,8 +282,7 @@ public final class FlvExtractor implements Extractor {
|
|||||||
return wasConsumed;
|
return wasConsumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ParsableByteArray prepareTagData(ExtractorInput input) throws IOException,
|
private ParsableByteArray prepareTagData(ExtractorInput input) throws IOException {
|
||||||
InterruptedException {
|
|
||||||
if (tagDataSize > tagData.capacity()) {
|
if (tagDataSize > tagData.capacity()) {
|
||||||
tagData.reset(new byte[Math.max(tagData.capacity() * 2, tagDataSize)], 0);
|
tagData.reset(new byte[Math.max(tagData.capacity() * 2, tagDataSize)], 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -79,7 +79,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean read(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean read(ExtractorInput input) throws IOException {
|
||||||
Assertions.checkStateNotNull(processor);
|
Assertions.checkStateNotNull(processor);
|
||||||
while (true) {
|
while (true) {
|
||||||
MasterElement head = masterElementsStack.peek();
|
MasterElement head = masterElementsStack.peek();
|
||||||
@ -160,11 +160,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
* @throws EOFException If the end of input was encountered when searching for the next level 1
|
* @throws EOFException If the end of input was encountered when searching for the next level 1
|
||||||
* element.
|
* element.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
@RequiresNonNull("processor")
|
@RequiresNonNull("processor")
|
||||||
private long maybeResyncToNextLevel1Element(ExtractorInput input)
|
private long maybeResyncToNextLevel1Element(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
while (true) {
|
while (true) {
|
||||||
input.peekFully(scratch, 0, MAX_ID_BYTES);
|
input.peekFully(scratch, 0, MAX_ID_BYTES);
|
||||||
@ -187,10 +185,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
* @param byteLength The length of the integer being read.
|
* @param byteLength The length of the integer being read.
|
||||||
* @return The read integer value.
|
* @return The read integer value.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
private long readInteger(ExtractorInput input, int byteLength)
|
private long readInteger(ExtractorInput input, int byteLength) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
input.readFully(scratch, 0, byteLength);
|
input.readFully(scratch, 0, byteLength);
|
||||||
long value = 0;
|
long value = 0;
|
||||||
for (int i = 0; i < byteLength; i++) {
|
for (int i = 0; i < byteLength; i++) {
|
||||||
@ -206,10 +202,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
* @param byteLength The length of the float being read.
|
* @param byteLength The length of the float being read.
|
||||||
* @return The read float value.
|
* @return The read float value.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
private double readFloat(ExtractorInput input, int byteLength)
|
private double readFloat(ExtractorInput input, int byteLength) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
long integerValue = readInteger(input, byteLength);
|
long integerValue = readInteger(input, byteLength);
|
||||||
double floatValue;
|
double floatValue;
|
||||||
if (byteLength == VALID_FLOAT32_ELEMENT_SIZE_BYTES) {
|
if (byteLength == VALID_FLOAT32_ELEMENT_SIZE_BYTES) {
|
||||||
@ -228,10 +222,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
* @param byteLength The length of the string being read, including zero padding.
|
* @param byteLength The length of the string being read, including zero padding.
|
||||||
* @return The read string value.
|
* @return The read string value.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
private String readString(ExtractorInput input, int byteLength)
|
private static String readString(ExtractorInput input, int byteLength) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (byteLength == 0) {
|
if (byteLength == 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -130,21 +130,18 @@ public interface EbmlProcessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a binary element is encountered.
|
* Called when a binary element is encountered.
|
||||||
* <p>
|
*
|
||||||
* The element header (containing the element ID and content size) will already have been read.
|
* <p>The element header (containing the element ID and content size) will already have been read.
|
||||||
* Implementations are required to consume the whole remainder of the element, which is
|
* Implementations are required to consume the whole remainder of the element, which is {@code
|
||||||
* {@code contentSize} bytes in length, before returning. Implementations are permitted to fail
|
* contentSize} bytes in length, before returning. Implementations are permitted to fail (by
|
||||||
* (by throwing an exception) having partially consumed the data, however if they do this, they
|
* throwing an exception) having partially consumed the data, however if they do this, they must
|
||||||
* must consume the remainder of the content when called again.
|
* consume the remainder of the content when called again.
|
||||||
*
|
*
|
||||||
* @param id The element ID.
|
* @param id The element ID.
|
||||||
* @param contentsSize The element's content size.
|
* @param contentsSize The element's content size.
|
||||||
* @param input The {@link ExtractorInput} from which data should be read.
|
* @param input The {@link ExtractorInput} from which data should be read.
|
||||||
* @throws ParserException If a parsing error occurs.
|
* @throws ParserException If a parsing error occurs.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
void binaryElement(int id, int contentsSize, ExtractorInput input)
|
void binaryElement(int id, int contentsSize, ExtractorInput input) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,6 @@ import java.io.IOException;
|
|||||||
* @return True if data can continue to be read. False if the end of the input was encountered.
|
* @return True if data can continue to be read. False if the end of the input was encountered.
|
||||||
* @throws ParserException If parsing fails.
|
* @throws ParserException If parsing fails.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
boolean read(ExtractorInput input) throws IOException, InterruptedException;
|
boolean read(ExtractorInput input) throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -420,7 +420,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public final boolean sniff(ExtractorInput input) throws IOException {
|
||||||
return new Sniffer().sniff(input);
|
return new Sniffer().sniff(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,8 +448,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int read(ExtractorInput input, PositionHolder seekPosition)
|
public final int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
haveOutputSample = false;
|
haveOutputSample = false;
|
||||||
boolean continueReading = true;
|
boolean continueReading = true;
|
||||||
while (continueReading && !haveOutputSample) {
|
while (continueReading && !haveOutputSample) {
|
||||||
@ -1051,8 +1050,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
* @see EbmlProcessor#binaryElement(int, int, ExtractorInput)
|
* @see EbmlProcessor#binaryElement(int, int, ExtractorInput)
|
||||||
*/
|
*/
|
||||||
@CallSuper
|
@CallSuper
|
||||||
protected void binaryElement(int id, int contentSize, ExtractorInput input)
|
protected void binaryElement(int id, int contentSize, ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case ID_SEEK_ID:
|
case ID_SEEK_ID:
|
||||||
Arrays.fill(seekEntryIdBytes.data, (byte) 0);
|
Arrays.fill(seekEntryIdBytes.data, (byte) 0);
|
||||||
@ -1231,7 +1229,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
|
|
||||||
protected void handleBlockAdditionalData(
|
protected void handleBlockAdditionalData(
|
||||||
Track track, int blockAdditionalId, ExtractorInput input, int contentSize)
|
Track track, int blockAdditionalId, ExtractorInput input, int contentSize)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
if (blockAdditionalId == BLOCK_ADDITIONAL_ID_VP9_ITU_T_35
|
if (blockAdditionalId == BLOCK_ADDITIONAL_ID_VP9_ITU_T_35
|
||||||
&& CODEC_ID_VP9.equals(track.codecId)) {
|
&& CODEC_ID_VP9.equals(track.codecId)) {
|
||||||
blockAdditionalData.reset(contentSize);
|
blockAdditionalData.reset(contentSize);
|
||||||
@ -1282,8 +1280,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
* Ensures {@link #scratch} contains at least {@code requiredLength} bytes of data, reading from
|
* Ensures {@link #scratch} contains at least {@code requiredLength} bytes of data, reading from
|
||||||
* the extractor input if necessary.
|
* the extractor input if necessary.
|
||||||
*/
|
*/
|
||||||
private void readScratch(ExtractorInput input, int requiredLength)
|
private void readScratch(ExtractorInput input, int requiredLength) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (scratch.limit() >= requiredLength) {
|
if (scratch.limit() >= requiredLength) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1303,10 +1300,8 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
* @param size The size of the sample data on the input side.
|
* @param size The size of the sample data on the input side.
|
||||||
* @return The final size of the written sample.
|
* @return The final size of the written sample.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
private int writeSampleData(ExtractorInput input, Track track, int size)
|
private int writeSampleData(ExtractorInput input, Track track, int size) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (CODEC_ID_SUBRIP.equals(track.codecId)) {
|
if (CODEC_ID_SUBRIP.equals(track.codecId)) {
|
||||||
writeSubtitleSampleData(input, SUBRIP_PREFIX, size);
|
writeSubtitleSampleData(input, SUBRIP_PREFIX, size);
|
||||||
return finishWriteSampleData();
|
return finishWriteSampleData();
|
||||||
@ -1506,7 +1501,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeSubtitleSampleData(ExtractorInput input, byte[] samplePrefix, int size)
|
private void writeSubtitleSampleData(ExtractorInput input, byte[] samplePrefix, int size)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int sizeWithPrefix = samplePrefix.length + size;
|
int sizeWithPrefix = samplePrefix.length + size;
|
||||||
if (subtitleSample.capacity() < sizeWithPrefix) {
|
if (subtitleSample.capacity() < sizeWithPrefix) {
|
||||||
// Initialize subripSample to contain the required prefix and have space to hold a subtitle
|
// Initialize subripSample to contain the required prefix and have space to hold a subtitle
|
||||||
@ -1581,7 +1576,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
* pending {@link #sampleStrippedBytes} and any remaining data read from {@code input}.
|
* pending {@link #sampleStrippedBytes} and any remaining data read from {@code input}.
|
||||||
*/
|
*/
|
||||||
private void writeToTarget(ExtractorInput input, byte[] target, int offset, int length)
|
private void writeToTarget(ExtractorInput input, byte[] target, int offset, int length)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int pendingStrippedBytes = Math.min(length, sampleStrippedBytes.bytesLeft());
|
int pendingStrippedBytes = Math.min(length, sampleStrippedBytes.bytesLeft());
|
||||||
input.readFully(target, offset + pendingStrippedBytes, length - pendingStrippedBytes);
|
input.readFully(target, offset + pendingStrippedBytes, length - pendingStrippedBytes);
|
||||||
if (pendingStrippedBytes > 0) {
|
if (pendingStrippedBytes > 0) {
|
||||||
@ -1594,7 +1589,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
* {@link #sampleStrippedBytes} or data read from {@code input}.
|
* {@link #sampleStrippedBytes} or data read from {@code input}.
|
||||||
*/
|
*/
|
||||||
private int writeToOutput(ExtractorInput input, TrackOutput output, int length)
|
private int writeToOutput(ExtractorInput input, TrackOutput output, int length)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int bytesWritten;
|
int bytesWritten;
|
||||||
int strippedBytesLeft = sampleStrippedBytes.bytesLeft();
|
int strippedBytesLeft = sampleStrippedBytes.bytesLeft();
|
||||||
if (strippedBytesLeft > 0) {
|
if (strippedBytesLeft > 0) {
|
||||||
@ -1774,8 +1769,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void binaryElement(int id, int contentsSize, ExtractorInput input)
|
public void binaryElement(int id, int contentsSize, ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
MatroskaExtractor.this.binaryElement(id, contentsSize, input);
|
MatroskaExtractor.this.binaryElement(id, contentsSize, input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1803,7 +1797,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
chunkSampleCount = 0;
|
chunkSampleCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startSample(ExtractorInput input) throws IOException, InterruptedException {
|
public void startSample(ExtractorInput input) throws IOException {
|
||||||
if (foundSyncframe) {
|
if (foundSyncframe) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,8 @@ import java.io.IOException;
|
|||||||
scratch = new ParsableByteArray(8);
|
scratch = new ParsableByteArray(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @see com.google.android.exoplayer2.extractor.Extractor#sniff(ExtractorInput) */
|
||||||
* @see com.google.android.exoplayer2.extractor.Extractor#sniff(ExtractorInput)
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
*/
|
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
|
||||||
long inputLength = input.getLength();
|
long inputLength = input.getLength();
|
||||||
int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
|
int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
|
||||||
? SEARCH_LENGTH : inputLength);
|
? SEARCH_LENGTH : inputLength);
|
||||||
@ -86,10 +84,8 @@ import java.io.IOException;
|
|||||||
return peekLength == headerStart + headerSize;
|
return peekLength == headerStart + headerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Peeks a variable-length unsigned EBML integer from the input. */
|
||||||
* Peeks a variable-length unsigned EBML integer from the input.
|
private long readUint(ExtractorInput input) throws IOException {
|
||||||
*/
|
|
||||||
private long readUint(ExtractorInput input) throws IOException, InterruptedException {
|
|
||||||
input.peekFully(scratch.data, 0, 1);
|
input.peekFully(scratch.data, 0, 1);
|
||||||
int value = scratch.data[0] & 0xFF;
|
int value = scratch.data[0] & 0xFF;
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
|
@ -56,15 +56,15 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads an EBML variable-length integer (varint) from an {@link ExtractorInput} such that
|
* Reads an EBML variable-length integer (varint) from an {@link ExtractorInput} such that reading
|
||||||
* reading can be resumed later if an error occurs having read only some of it.
|
* can be resumed later if an error occurs having read only some of it.
|
||||||
* <p>
|
*
|
||||||
* If an value is successfully read, then the reader will automatically reset itself ready to
|
* <p>If an value is successfully read, then the reader will automatically reset itself ready to
|
||||||
* read another value.
|
* read another value.
|
||||||
* <p>
|
*
|
||||||
* If an {@link IOException} or {@link InterruptedException} is throw, the read can be resumed
|
* <p>If an {@link IOException} is thrown, the read can be resumed later by calling this method
|
||||||
* later by calling this method again, passing an {@link ExtractorInput} providing data starting
|
* again, passing an {@link ExtractorInput} providing data starting where the previous one left
|
||||||
* where the previous one left off.
|
* off.
|
||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} from which the integer should be read.
|
* @param input The {@link ExtractorInput} from which the integer should be read.
|
||||||
* @param allowEndOfInput True if encountering the end of the input having read no data is
|
* @param allowEndOfInput True if encountering the end of the input having read no data is
|
||||||
@ -76,10 +76,13 @@ import java.io.IOException;
|
|||||||
* and the end of the input was encountered, or {@link C#RESULT_MAX_LENGTH_EXCEEDED} if the
|
* and the end of the input was encountered, or {@link C#RESULT_MAX_LENGTH_EXCEEDED} if the
|
||||||
* length of the varint exceeded maximumAllowedLength.
|
* length of the varint exceeded maximumAllowedLength.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
public long readUnsignedVarint(ExtractorInput input, boolean allowEndOfInput,
|
public long readUnsignedVarint(
|
||||||
boolean removeLengthMask, int maximumAllowedLength) throws IOException, InterruptedException {
|
ExtractorInput input,
|
||||||
|
boolean allowEndOfInput,
|
||||||
|
boolean removeLengthMask,
|
||||||
|
int maximumAllowedLength)
|
||||||
|
throws IOException {
|
||||||
if (state == STATE_BEGIN_READING) {
|
if (state == STATE_BEGIN_READING) {
|
||||||
// Read the first byte to establish the length.
|
// Read the first byte to establish the length.
|
||||||
if (!input.readFully(scratch, 0, 1, allowEndOfInput)) {
|
if (!input.readFully(scratch, 0, 1, allowEndOfInput)) {
|
||||||
|
@ -182,7 +182,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
return synchronize(input, true);
|
return synchronize(input, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,8 +213,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
assertInitialized();
|
assertInitialized();
|
||||||
int readResult = readInternal(input);
|
int readResult = readInternal(input);
|
||||||
if (readResult == RESULT_END_OF_INPUT && seeker instanceof IndexSeeker) {
|
if (readResult == RESULT_END_OF_INPUT && seeker instanceof IndexSeeker) {
|
||||||
@ -240,7 +239,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
@RequiresNonNull({"extractorOutput", "currentTrackOutput", "realTrackOutput"})
|
@RequiresNonNull({"extractorOutput", "currentTrackOutput", "realTrackOutput"})
|
||||||
private int readInternal(ExtractorInput input) throws IOException, InterruptedException {
|
private int readInternal(ExtractorInput input) throws IOException {
|
||||||
if (synchronizedHeaderData == 0) {
|
if (synchronizedHeaderData == 0) {
|
||||||
try {
|
try {
|
||||||
synchronize(input, false);
|
synchronize(input, false);
|
||||||
@ -273,7 +272,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiresNonNull({"currentTrackOutput", "realTrackOutput", "seeker"})
|
@RequiresNonNull({"currentTrackOutput", "realTrackOutput", "seeker"})
|
||||||
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
|
private int readSample(ExtractorInput extractorInput) throws IOException {
|
||||||
if (sampleBytesRemaining == 0) {
|
if (sampleBytesRemaining == 0) {
|
||||||
extractorInput.resetPeekPosition();
|
extractorInput.resetPeekPosition();
|
||||||
if (peekEndOfStreamOrHeader(extractorInput)) {
|
if (peekEndOfStreamOrHeader(extractorInput)) {
|
||||||
@ -329,8 +328,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
return basisTimeUs + samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate;
|
return basisTimeUs + samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean synchronize(ExtractorInput input, boolean sniffing)
|
private boolean synchronize(ExtractorInput input, boolean sniffing) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
int validFrameCount = 0;
|
int validFrameCount = 0;
|
||||||
int candidateSynchronizedHeaderData = 0;
|
int candidateSynchronizedHeaderData = 0;
|
||||||
int peekedId3Bytes = 0;
|
int peekedId3Bytes = 0;
|
||||||
@ -407,8 +405,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
* Returns whether the extractor input is peeking the end of the stream. If {@code false},
|
* Returns whether the extractor input is peeking the end of the stream. If {@code false},
|
||||||
* populates the scratch buffer with the next four bytes.
|
* populates the scratch buffer with the next four bytes.
|
||||||
*/
|
*/
|
||||||
private boolean peekEndOfStreamOrHeader(ExtractorInput extractorInput)
|
private boolean peekEndOfStreamOrHeader(ExtractorInput extractorInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (seeker != null) {
|
if (seeker != null) {
|
||||||
long dataEndPosition = seeker.getDataEndPosition();
|
long dataEndPosition = seeker.getDataEndPosition();
|
||||||
if (dataEndPosition != C.POSITION_UNSET
|
if (dataEndPosition != C.POSITION_UNSET
|
||||||
@ -424,7 +421,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Seeker computeSeeker(ExtractorInput input) throws IOException, InterruptedException {
|
private Seeker computeSeeker(ExtractorInput input) throws IOException {
|
||||||
// Read past any seek frame and set the seeker based on metadata or a seek frame. Metadata
|
// Read past any seek frame and set the seeker based on metadata or a seek frame. Metadata
|
||||||
// takes priority as it can provide greater precision.
|
// takes priority as it can provide greater precision.
|
||||||
Seeker seekFrameSeeker = maybeReadSeekFrame(input);
|
Seeker seekFrameSeeker = maybeReadSeekFrame(input);
|
||||||
@ -471,11 +468,9 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
* @return A {@link Seeker} if seeking metadata was present and valid, or {@code null} otherwise.
|
* @return A {@link Seeker} if seeking metadata was present and valid, or {@code null} otherwise.
|
||||||
* @throws IOException Thrown if there was an error reading from the stream. Not expected if the
|
* @throws IOException Thrown if there was an error reading from the stream. Not expected if the
|
||||||
* next two frames were already peeked during synchronization.
|
* next two frames were already peeked during synchronization.
|
||||||
* @throws InterruptedException Thrown if reading from the stream was interrupted. Not expected if
|
|
||||||
* the next two frames were already peeked during synchronization.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException, InterruptedException {
|
private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException {
|
||||||
ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
|
ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
|
||||||
input.peekFully(frame.data, 0, synchronizedHeader.frameSize);
|
input.peekFully(frame.data, 0, synchronizedHeader.frameSize);
|
||||||
int xingBase = (synchronizedHeader.version & 1) != 0
|
int xingBase = (synchronizedHeader.version & 1) != 0
|
||||||
@ -509,11 +504,8 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
return seeker;
|
return seeker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate. */
|
||||||
* Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate.
|
private Seeker getConstantBitrateSeeker(ExtractorInput input) throws IOException {
|
||||||
*/
|
|
||||||
private Seeker getConstantBitrateSeeker(ExtractorInput input)
|
|
||||||
throws IOException, InterruptedException {
|
|
||||||
input.peekFully(scratch.data, 0, 4);
|
input.peekFully(scratch.data, 0, 4);
|
||||||
scratch.setPosition(0);
|
scratch.setPosition(0);
|
||||||
synchronizedHeader.setForHeaderData(scratch.readInt());
|
synchronizedHeader.setForHeaderData(scratch.readInt());
|
||||||
|
@ -268,7 +268,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
return Sniffer.sniffFragmented(input);
|
return Sniffer.sniffFragmented(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,8 +303,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (parserState) {
|
switch (parserState) {
|
||||||
case STATE_READING_ATOM_HEADER:
|
case STATE_READING_ATOM_HEADER:
|
||||||
@ -331,7 +330,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
|||||||
atomHeaderBytesRead = 0;
|
atomHeaderBytesRead = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean readAtomHeader(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean readAtomHeader(ExtractorInput input) throws IOException {
|
||||||
if (atomHeaderBytesRead == 0) {
|
if (atomHeaderBytesRead == 0) {
|
||||||
// Read the standard length atom header.
|
// Read the standard length atom header.
|
||||||
if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
|
if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
|
||||||
@ -419,7 +418,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readAtomPayload(ExtractorInput input) throws IOException, InterruptedException {
|
private void readAtomPayload(ExtractorInput input) throws IOException {
|
||||||
int atomPayloadSize = (int) atomSize - atomHeaderBytesRead;
|
int atomPayloadSize = (int) atomSize - atomHeaderBytesRead;
|
||||||
if (atomData != null) {
|
if (atomData != null) {
|
||||||
input.readFully(atomData.data, Atom.HEADER_SIZE, atomPayloadSize);
|
input.readFully(atomData.data, Atom.HEADER_SIZE, atomPayloadSize);
|
||||||
@ -1170,7 +1169,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
|||||||
new ChunkIndex(sizes, offsets, durationsUs, timesUs));
|
new ChunkIndex(sizes, offsets, durationsUs, timesUs));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readEncryptionData(ExtractorInput input) throws IOException, InterruptedException {
|
private void readEncryptionData(ExtractorInput input) throws IOException {
|
||||||
TrackBundle nextTrackBundle = null;
|
TrackBundle nextTrackBundle = null;
|
||||||
long nextDataOffset = Long.MAX_VALUE;
|
long nextDataOffset = Long.MAX_VALUE;
|
||||||
int trackBundlesSize = trackBundles.size();
|
int trackBundlesSize = trackBundles.size();
|
||||||
@ -1208,9 +1207,8 @@ public class FragmentedMp4Extractor implements Extractor {
|
|||||||
* @return Whether a sample was read. The read sample may have been output or skipped. False
|
* @return Whether a sample was read. The read sample may have been output or skipped. False
|
||||||
* indicates that there are no samples left to read in the current mdat.
|
* indicates that there are no samples left to read in the current mdat.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
private boolean readSample(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean readSample(ExtractorInput input) throws IOException {
|
||||||
if (parserState == STATE_READING_SAMPLE_START) {
|
if (parserState == STATE_READING_SAMPLE_START) {
|
||||||
if (currentTrackBundle == null) {
|
if (currentTrackBundle == null) {
|
||||||
@Nullable TrackBundle currentTrackBundle = getNextFragmentRun(trackBundles);
|
@Nullable TrackBundle currentTrackBundle = getNextFragmentRun(trackBundles);
|
||||||
|
@ -146,7 +146,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
return Sniffer.sniffUnfragmented(input);
|
return Sniffer.sniffUnfragmented(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,8 +176,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (parserState) {
|
switch (parserState) {
|
||||||
case STATE_READING_ATOM_HEADER:
|
case STATE_READING_ATOM_HEADER:
|
||||||
@ -270,7 +269,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
atomHeaderBytesRead = 0;
|
atomHeaderBytesRead = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean readAtomHeader(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean readAtomHeader(ExtractorInput input) throws IOException {
|
||||||
if (atomHeaderBytesRead == 0) {
|
if (atomHeaderBytesRead == 0) {
|
||||||
// Read the standard length atom header.
|
// Read the standard length atom header.
|
||||||
if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
|
if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
|
||||||
@ -341,7 +340,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
* restart loading at the position in {@code positionHolder}. Otherwise, the atom is read/skipped.
|
* restart loading at the position in {@code positionHolder}. Otherwise, the atom is read/skipped.
|
||||||
*/
|
*/
|
||||||
private boolean readAtomPayload(ExtractorInput input, PositionHolder positionHolder)
|
private boolean readAtomPayload(ExtractorInput input, PositionHolder positionHolder)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long atomPayloadSize = atomSize - atomHeaderBytesRead;
|
long atomPayloadSize = atomSize - atomHeaderBytesRead;
|
||||||
long atomEndPosition = input.getPosition() + atomPayloadSize;
|
long atomEndPosition = input.getPosition() + atomPayloadSize;
|
||||||
boolean seekRequired = false;
|
boolean seekRequired = false;
|
||||||
@ -485,22 +484,20 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to extract the next sample in the current mdat atom for the specified track.
|
* Attempts to extract the next sample in the current mdat atom for the specified track.
|
||||||
* <p>
|
*
|
||||||
* Returns {@link #RESULT_SEEK} if the source should be reloaded from the position in
|
* <p>Returns {@link #RESULT_SEEK} if the source should be reloaded from the position in {@code
|
||||||
* {@code positionHolder}.
|
* positionHolder}.
|
||||||
* <p>
|
*
|
||||||
* Returns {@link #RESULT_END_OF_INPUT} if no samples are left. Otherwise, returns
|
* <p>Returns {@link #RESULT_END_OF_INPUT} if no samples are left. Otherwise, returns {@link
|
||||||
* {@link #RESULT_CONTINUE}.
|
* #RESULT_CONTINUE}.
|
||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} from which to read data.
|
* @param input The {@link ExtractorInput} from which to read data.
|
||||||
* @param positionHolder If {@link #RESULT_SEEK} is returned, this holder is updated to hold the
|
* @param positionHolder If {@link #RESULT_SEEK} is returned, this holder is updated to hold the
|
||||||
* position of the required data.
|
* position of the required data.
|
||||||
* @return One of the {@code RESULT_*} flags in {@link Extractor}.
|
* @return One of the {@code RESULT_*} flags in {@link Extractor}.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
private int readSample(ExtractorInput input, PositionHolder positionHolder)
|
private int readSample(ExtractorInput input, PositionHolder positionHolder) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
long inputPosition = input.getPosition();
|
long inputPosition = input.getPosition();
|
||||||
if (sampleTrackIndex == C.INDEX_UNSET) {
|
if (sampleTrackIndex == C.INDEX_UNSET) {
|
||||||
sampleTrackIndex = getTrackIndexOfNextReadSample(inputPosition);
|
sampleTrackIndex = getTrackIndexOfNextReadSample(inputPosition);
|
||||||
@ -663,8 +660,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
* we can't rely on the file type though. Instead we must check the 8 bytes after the common
|
* we can't rely on the file type though. Instead we must check the 8 bytes after the common
|
||||||
* header bytes ourselves.
|
* header bytes ourselves.
|
||||||
*/
|
*/
|
||||||
private void maybeSkipRemainingMetaAtomHeaderBytes(ExtractorInput input)
|
private void maybeSkipRemainingMetaAtomHeaderBytes(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
scratch.reset(8);
|
scratch.reset(8);
|
||||||
// Peek the next 8 bytes which can be either
|
// Peek the next 8 bytes which can be either
|
||||||
// (iso) [1 byte version + 3 bytes flags][4 byte size of next atom]
|
// (iso) [1 byte version + 3 bytes flags][4 byte size of next atom]
|
||||||
|
@ -66,10 +66,8 @@ import java.io.IOException;
|
|||||||
* @param input The extractor input from which to peek data. The peek position will be modified.
|
* @param input The extractor input from which to peek data. The peek position will be modified.
|
||||||
* @return Whether the input appears to be in the fragmented MP4 format.
|
* @return Whether the input appears to be in the fragmented MP4 format.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
public static boolean sniffFragmented(ExtractorInput input)
|
public static boolean sniffFragmented(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
return sniffInternal(input, true);
|
return sniffInternal(input, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,15 +78,13 @@ import java.io.IOException;
|
|||||||
* @param input The extractor input from which to peek data. The peek position will be modified.
|
* @param input The extractor input from which to peek data. The peek position will be modified.
|
||||||
* @return Whether the input appears to be in the unfragmented MP4 format.
|
* @return Whether the input appears to be in the unfragmented MP4 format.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
public static boolean sniffUnfragmented(ExtractorInput input)
|
public static boolean sniffUnfragmented(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
return sniffInternal(input, false);
|
return sniffInternal(input, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean sniffInternal(ExtractorInput input, boolean fragmented)
|
private static boolean sniffInternal(ExtractorInput input, boolean fragmented)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long inputLength = input.getLength();
|
long inputLength = input.getLength();
|
||||||
int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
|
int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH
|
||||||
? SEARCH_LENGTH : inputLength);
|
? SEARCH_LENGTH : inputLength);
|
||||||
|
@ -169,7 +169,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
*
|
*
|
||||||
* @param input An {@link ExtractorInput} from which to read the encryption data.
|
* @param input An {@link ExtractorInput} from which to read the encryption data.
|
||||||
*/
|
*/
|
||||||
public void fillEncryptionData(ExtractorInput input) throws IOException, InterruptedException {
|
public void fillEncryptionData(ExtractorInput input) throws IOException {
|
||||||
input.readFully(sampleEncryptionData.data, 0, sampleEncryptionData.limit());
|
input.readFully(sampleEncryptionData.data, 0, sampleEncryptionData.limit());
|
||||||
sampleEncryptionData.setPosition(0);
|
sampleEncryptionData.setPosition(0);
|
||||||
sampleEncryptionDataNeedsFill = false;
|
sampleEncryptionDataNeedsFill = false;
|
||||||
|
@ -88,7 +88,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long read(ExtractorInput input) throws IOException, InterruptedException {
|
public long read(ExtractorInput input) throws IOException {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_IDLE:
|
case STATE_IDLE:
|
||||||
return -1;
|
return -1;
|
||||||
@ -148,9 +148,8 @@ import java.io.IOException;
|
|||||||
* @return The byte position from which data should be provided for the next step, or {@link
|
* @return The byte position from which data should be provided for the next step, or {@link
|
||||||
* C#POSITION_UNSET} if the search has converged.
|
* C#POSITION_UNSET} if the search has converged.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
private long getNextSeekPosition(ExtractorInput input) throws IOException, InterruptedException {
|
private long getNextSeekPosition(ExtractorInput input) throws IOException {
|
||||||
if (start == end) {
|
if (start == end) {
|
||||||
return C.POSITION_UNSET;
|
return C.POSITION_UNSET;
|
||||||
}
|
}
|
||||||
@ -199,10 +198,8 @@ import java.io.IOException;
|
|||||||
* @param input The {@link ExtractorInput} to read from.
|
* @param input The {@link ExtractorInput} to read from.
|
||||||
* @throws ParserException If populating the page header fails.
|
* @throws ParserException If populating the page header fails.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
private void skipToPageOfTargetGranule(ExtractorInput input)
|
private void skipToPageOfTargetGranule(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
pageHeader.populate(input, /* quiet= */ false);
|
pageHeader.populate(input, /* quiet= */ false);
|
||||||
while (pageHeader.granulePosition <= targetGranule) {
|
while (pageHeader.granulePosition <= targetGranule) {
|
||||||
input.skipFully(pageHeader.headerSize + pageHeader.bodySize);
|
input.skipFully(pageHeader.headerSize + pageHeader.bodySize);
|
||||||
@ -218,11 +215,10 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* @param input The {@code ExtractorInput} to skip to the next page.
|
* @param input The {@code ExtractorInput} to skip to the next page.
|
||||||
* @throws IOException If peeking/reading from the input fails.
|
* @throws IOException If peeking/reading from the input fails.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
* @throws EOFException If the next page can't be found before the end of the input.
|
* @throws EOFException If the next page can't be found before the end of the input.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void skipToNextPage(ExtractorInput input) throws IOException, InterruptedException {
|
void skipToNextPage(ExtractorInput input) throws IOException {
|
||||||
if (!skipToNextPage(input, payloadEndPosition)) {
|
if (!skipToNextPage(input, payloadEndPosition)) {
|
||||||
// Not found until eof.
|
// Not found until eof.
|
||||||
throw new EOFException();
|
throw new EOFException();
|
||||||
@ -236,10 +232,8 @@ import java.io.IOException;
|
|||||||
* @param limit The limit up to which the search should take place.
|
* @param limit The limit up to which the search should take place.
|
||||||
* @return Whether the next page was found.
|
* @return Whether the next page was found.
|
||||||
* @throws IOException If peeking/reading from the input fails.
|
* @throws IOException If peeking/reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while peeking/reading from the input.
|
|
||||||
*/
|
*/
|
||||||
private boolean skipToNextPage(ExtractorInput input, long limit)
|
private boolean skipToNextPage(ExtractorInput input, long limit) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
limit = Math.min(limit + 3, payloadEndPosition);
|
limit = Math.min(limit + 3, payloadEndPosition);
|
||||||
byte[] buffer = new byte[2048];
|
byte[] buffer = new byte[2048];
|
||||||
int peekLength = buffer.length;
|
int peekLength = buffer.length;
|
||||||
@ -275,10 +269,9 @@ import java.io.IOException;
|
|||||||
* @param input The {@link ExtractorInput} to read from.
|
* @param input The {@link ExtractorInput} to read from.
|
||||||
* @return The total number of samples of this input.
|
* @return The total number of samples of this input.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
long readGranuleOfLastPage(ExtractorInput input) throws IOException, InterruptedException {
|
long readGranuleOfLastPage(ExtractorInput input) throws IOException {
|
||||||
skipToNextPage(input);
|
skipToNextPage(input);
|
||||||
pageHeader.reset();
|
pageHeader.reset();
|
||||||
while ((pageHeader.type & 0x04) != 0x04 && input.getPosition() < payloadEndPosition) {
|
while ((pageHeader.type & 0x04) != 0x04 && input.getPosition() < payloadEndPosition) {
|
||||||
|
@ -44,7 +44,7 @@ public class OggExtractor implements Extractor {
|
|||||||
private boolean streamReaderInitialized;
|
private boolean streamReaderInitialized;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
try {
|
try {
|
||||||
return sniffInternal(input);
|
return sniffInternal(input);
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
@ -70,8 +70,7 @@ public class OggExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Assertions.checkStateNotNull(output); // Asserts that init has been called.
|
Assertions.checkStateNotNull(output); // Asserts that init has been called.
|
||||||
if (streamReader == null) {
|
if (streamReader == null) {
|
||||||
if (!sniffInternal(input)) {
|
if (!sniffInternal(input)) {
|
||||||
@ -89,7 +88,7 @@ public class OggExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@EnsuresNonNullIf(expression = "streamReader", result = true)
|
@EnsuresNonNullIf(expression = "streamReader", result = true)
|
||||||
private boolean sniffInternal(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean sniffInternal(ExtractorInput input) throws IOException {
|
||||||
OggPageHeader header = new OggPageHeader();
|
OggPageHeader header = new OggPageHeader();
|
||||||
if (!header.populate(input, true) || (header.type & 0x02) != 0x02) {
|
if (!header.populate(input, true) || (header.type & 0x02) != 0x02) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -55,9 +55,8 @@ import java.util.Arrays;
|
|||||||
* @return {@code true} if the read was successful. The read fails if the end of the input is
|
* @return {@code true} if the read was successful. The read fails if the end of the input is
|
||||||
* encountered without reading data.
|
* encountered without reading data.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
public boolean populate(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean populate(ExtractorInput input) throws IOException {
|
||||||
Assertions.checkState(input != null);
|
Assertions.checkState(input != null);
|
||||||
|
|
||||||
if (populated) {
|
if (populated) {
|
||||||
|
@ -82,10 +82,8 @@ import java.io.IOException;
|
|||||||
* @return Whether the read was successful. The read fails if the end of the input is encountered
|
* @return Whether the read was successful. The read fails if the end of the input is encountered
|
||||||
* without reading data.
|
* without reading data.
|
||||||
* @throws IOException If reading data fails or the stream is invalid.
|
* @throws IOException If reading data fails or the stream is invalid.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
public boolean populate(ExtractorInput input, boolean quiet)
|
public boolean populate(ExtractorInput input, boolean quiet) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
scratch.reset();
|
scratch.reset();
|
||||||
reset();
|
reset();
|
||||||
boolean hasEnoughBytes = input.getLength() == C.LENGTH_UNSET
|
boolean hasEnoughBytes = input.getLength() == C.LENGTH_UNSET
|
||||||
|
@ -43,17 +43,15 @@ import java.io.IOException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from the {@link ExtractorInput} to build the {@link SeekMap} or to continue a seek.
|
* Reads data from the {@link ExtractorInput} to build the {@link SeekMap} or to continue a seek.
|
||||||
* <p/>
|
*
|
||||||
* If more data is required or if the position of the input needs to be modified then a position
|
* <p>If more data is required or if the position of the input needs to be modified then a
|
||||||
* from which data should be provided is returned. Else a negative value is returned. If a seek
|
* position from which data should be provided is returned. Else a negative value is returned. If
|
||||||
* has been completed then the value returned is -(currentGranule + 2). Else it is -1.
|
* a seek has been completed then the value returned is -(currentGranule + 2). Else it is -1.
|
||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} to read from.
|
* @param input The {@link ExtractorInput} to read from.
|
||||||
* @return A non-negative position to seek the {@link ExtractorInput} to, or -(currentGranule + 2)
|
* @return A non-negative position to seek the {@link ExtractorInput} to, or -(currentGranule + 2)
|
||||||
* if the progressive seek has completed, or -1 otherwise.
|
* if the progressive seek has completed, or -1 otherwise.
|
||||||
* @throws IOException If reading from the {@link ExtractorInput} fails.
|
* @throws IOException If reading from the {@link ExtractorInput} fails.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
|
||||||
*/
|
*/
|
||||||
long read(ExtractorInput input) throws IOException, InterruptedException;
|
long read(ExtractorInput input) throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -101,11 +101,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @see Extractor#read(ExtractorInput, PositionHolder) */
|
||||||
* @see Extractor#read(ExtractorInput, PositionHolder)
|
final int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
*/
|
|
||||||
final int read(ExtractorInput input, PositionHolder seekPosition)
|
|
||||||
throws IOException, InterruptedException {
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_READ_HEADERS:
|
case STATE_READ_HEADERS:
|
||||||
return readHeaders(input);
|
return readHeaders(input);
|
||||||
@ -121,7 +118,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readHeaders(ExtractorInput input) throws IOException, InterruptedException {
|
private int readHeaders(ExtractorInput input) throws IOException {
|
||||||
boolean readingHeaders = true;
|
boolean readingHeaders = true;
|
||||||
while (readingHeaders) {
|
while (readingHeaders) {
|
||||||
if (!oggPacket.populate(input)) {
|
if (!oggPacket.populate(input)) {
|
||||||
@ -166,8 +163,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
return Extractor.RESULT_CONTINUE;
|
return Extractor.RESULT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readPayload(ExtractorInput input, PositionHolder seekPosition)
|
private int readPayload(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
long position = oggSeeker.read(input);
|
long position = oggSeeker.read(input);
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
seekPosition.position = position;
|
seekPosition.position = position;
|
||||||
@ -238,8 +234,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* @param setupData Setup data to be filled.
|
* @param setupData Setup data to be filled.
|
||||||
* @return Whether the packet contains header data.
|
* @return Whether the packet contains header data.
|
||||||
*/
|
*/
|
||||||
protected abstract boolean readHeaders(ParsableByteArray packet, long position,
|
protected abstract boolean readHeaders(
|
||||||
SetupData setupData) throws IOException, InterruptedException;
|
ParsableByteArray packet, long position, SetupData setupData) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called on end of seeking.
|
* Called on end of seeking.
|
||||||
|
@ -71,15 +71,14 @@ public final class RawCcExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
dataScratch.reset();
|
dataScratch.reset();
|
||||||
input.peekFully(dataScratch.data, 0, HEADER_SIZE);
|
input.peekFully(dataScratch.data, 0, HEADER_SIZE);
|
||||||
return dataScratch.readInt() == HEADER_ID;
|
return dataScratch.readInt() == HEADER_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Assertions.checkStateNotNull(trackOutput); // Asserts that init has been called.
|
Assertions.checkStateNotNull(trackOutput); // Asserts that init has been called.
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (parserState) {
|
switch (parserState) {
|
||||||
@ -118,7 +117,7 @@ public final class RawCcExtractor implements Extractor {
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean parseHeader(ExtractorInput input) throws IOException, InterruptedException {
|
private boolean parseHeader(ExtractorInput input) throws IOException {
|
||||||
dataScratch.reset();
|
dataScratch.reset();
|
||||||
if (input.readFully(dataScratch.data, 0, HEADER_SIZE, true)) {
|
if (input.readFully(dataScratch.data, 0, HEADER_SIZE, true)) {
|
||||||
if (dataScratch.readInt() != HEADER_ID) {
|
if (dataScratch.readInt() != HEADER_ID) {
|
||||||
@ -132,8 +131,7 @@ public final class RawCcExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean parseTimestampAndSampleCount(ExtractorInput input) throws IOException,
|
private boolean parseTimestampAndSampleCount(ExtractorInput input) throws IOException {
|
||||||
InterruptedException {
|
|
||||||
dataScratch.reset();
|
dataScratch.reset();
|
||||||
if (version == 0) {
|
if (version == 0) {
|
||||||
if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V0 + 1, true)) {
|
if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V0 + 1, true)) {
|
||||||
@ -156,7 +154,7 @@ public final class RawCcExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiresNonNull("trackOutput")
|
@RequiresNonNull("trackOutput")
|
||||||
private void parseSamples(ExtractorInput input) throws IOException, InterruptedException {
|
private void parseSamples(ExtractorInput input) throws IOException {
|
||||||
for (; remainingSampleCount > 0; remainingSampleCount--) {
|
for (; remainingSampleCount > 0; remainingSampleCount--) {
|
||||||
dataScratch.reset();
|
dataScratch.reset();
|
||||||
input.readFully(dataScratch.data, 0, 3);
|
input.readFully(dataScratch.data, 0, 3);
|
||||||
|
@ -61,7 +61,7 @@ public final class Ac3Extractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
// Skip any ID3 headers.
|
// Skip any ID3 headers.
|
||||||
ParsableByteArray scratch = new ParsableByteArray(ID3_HEADER_LENGTH);
|
ParsableByteArray scratch = new ParsableByteArray(ID3_HEADER_LENGTH);
|
||||||
int startPosition = 0;
|
int startPosition = 0;
|
||||||
@ -124,8 +124,7 @@ public final class Ac3Extractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException,
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
InterruptedException {
|
|
||||||
int bytesRead = input.read(sampleData.data, 0, MAX_SYNC_FRAME_SIZE);
|
int bytesRead = input.read(sampleData.data, 0, MAX_SYNC_FRAME_SIZE);
|
||||||
if (bytesRead == C.RESULT_END_OF_INPUT) {
|
if (bytesRead == C.RESULT_END_OF_INPUT) {
|
||||||
return RESULT_END_OF_INPUT;
|
return RESULT_END_OF_INPUT;
|
||||||
|
@ -68,7 +68,7 @@ public final class Ac4Extractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
// Skip any ID3 headers.
|
// Skip any ID3 headers.
|
||||||
ParsableByteArray scratch = new ParsableByteArray(ID3_HEADER_LENGTH);
|
ParsableByteArray scratch = new ParsableByteArray(ID3_HEADER_LENGTH);
|
||||||
int startPosition = 0;
|
int startPosition = 0;
|
||||||
@ -132,8 +132,7 @@ public final class Ac4Extractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
int bytesRead = input.read(sampleData.data, /* offset= */ 0, /* length= */ READ_BUFFER_SIZE);
|
int bytesRead = input.read(sampleData.data, /* offset= */ 0, /* length= */ READ_BUFFER_SIZE);
|
||||||
if (bytesRead == C.RESULT_END_OF_INPUT) {
|
if (bytesRead == C.RESULT_END_OF_INPUT) {
|
||||||
return RESULT_END_OF_INPUT;
|
return RESULT_END_OF_INPUT;
|
||||||
|
@ -120,7 +120,7 @@ public final class AdtsExtractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
// Skip any ID3 headers.
|
// Skip any ID3 headers.
|
||||||
int startPosition = peekId3Header(input);
|
int startPosition = peekId3Header(input);
|
||||||
|
|
||||||
@ -179,8 +179,7 @@ public final class AdtsExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Assertions.checkStateNotNull(extractorOutput); // Asserts that init has been called.
|
Assertions.checkStateNotNull(extractorOutput); // Asserts that init has been called.
|
||||||
|
|
||||||
long inputLength = input.getLength();
|
long inputLength = input.getLength();
|
||||||
@ -212,7 +211,7 @@ public final class AdtsExtractor implements Extractor {
|
|||||||
return RESULT_CONTINUE;
|
return RESULT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int peekId3Header(ExtractorInput input) throws IOException, InterruptedException {
|
private int peekId3Header(ExtractorInput input) throws IOException {
|
||||||
int firstFramePosition = 0;
|
int firstFramePosition = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
input.peekFully(scratch.data, /* offset= */ 0, ID3_HEADER_LENGTH);
|
input.peekFully(scratch.data, /* offset= */ 0, ID3_HEADER_LENGTH);
|
||||||
@ -256,8 +255,7 @@ public final class AdtsExtractor implements Extractor {
|
|||||||
hasOutputSeekMap = true;
|
hasOutputSeekMap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateAverageFrameSize(ExtractorInput input)
|
private void calculateAverageFrameSize(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (hasCalculatedAverageFrameSize) {
|
if (hasCalculatedAverageFrameSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetTimestamp)
|
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetTimestamp)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long inputPosition = input.getPosition();
|
long inputPosition = input.getPosition();
|
||||||
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);
|
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);
|
||||||
|
|
||||||
|
@ -81,11 +81,9 @@ import java.io.IOException;
|
|||||||
* to hold the position of the required seek.
|
* to hold the position of the required seek.
|
||||||
* @return One of the {@code RESULT_} values defined in {@link Extractor}.
|
* @return One of the {@code RESULT_} values defined in {@link Extractor}.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
public @Extractor.ReadResult int readDuration(
|
public @Extractor.ReadResult int readDuration(
|
||||||
ExtractorInput input, PositionHolder seekPositionHolder)
|
ExtractorInput input, PositionHolder seekPositionHolder) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (!isLastScrValueRead) {
|
if (!isLastScrValueRead) {
|
||||||
return readLastScrValue(input, seekPositionHolder);
|
return readLastScrValue(input, seekPositionHolder);
|
||||||
}
|
}
|
||||||
@ -137,7 +135,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
|
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
|
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
|
||||||
int searchStartPosition = 0;
|
int searchStartPosition = 0;
|
||||||
if (input.getPosition() != searchStartPosition) {
|
if (input.getPosition() != searchStartPosition) {
|
||||||
@ -173,7 +171,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
|
private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long inputLength = input.getLength();
|
long inputLength = input.getLength();
|
||||||
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
|
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
|
||||||
long searchStartPosition = inputLength - bytesToSearch;
|
long searchStartPosition = inputLength - bytesToSearch;
|
||||||
|
@ -89,7 +89,7 @@ public final class PsExtractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
byte[] scratch = new byte[14];
|
byte[] scratch = new byte[14];
|
||||||
input.peekFully(scratch, 0, 14);
|
input.peekFully(scratch, 0, 14);
|
||||||
|
|
||||||
@ -162,8 +162,7 @@ public final class PsExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Assertions.checkStateNotNull(output); // Asserts init has been called.
|
Assertions.checkStateNotNull(output); // Asserts init has been called.
|
||||||
|
|
||||||
long inputLength = input.getLength();
|
long inputLength = input.getLength();
|
||||||
|
@ -74,7 +74,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetTimestamp)
|
public TimestampSearchResult searchForTimestamp(ExtractorInput input, long targetTimestamp)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long inputPosition = input.getPosition();
|
long inputPosition = input.getPosition();
|
||||||
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);
|
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength() - inputPosition);
|
||||||
|
|
||||||
|
@ -74,11 +74,9 @@ import java.io.IOException;
|
|||||||
* @param pcrPid The PID of the packet stream within this TS stream that contains PCR values.
|
* @param pcrPid The PID of the packet stream within this TS stream that contains PCR values.
|
||||||
* @return One of the {@code RESULT_} values defined in {@link Extractor}.
|
* @return One of the {@code RESULT_} values defined in {@link Extractor}.
|
||||||
* @throws IOException If an error occurred reading from the input.
|
* @throws IOException If an error occurred reading from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
public @Extractor.ReadResult int readDuration(
|
public @Extractor.ReadResult int readDuration(
|
||||||
ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
|
ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
if (pcrPid <= 0) {
|
if (pcrPid <= 0) {
|
||||||
return finishReadDuration(input);
|
return finishReadDuration(input);
|
||||||
}
|
}
|
||||||
@ -124,7 +122,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int readFirstPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
|
private int readFirstPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
|
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
|
||||||
int searchStartPosition = 0;
|
int searchStartPosition = 0;
|
||||||
if (input.getPosition() != searchStartPosition) {
|
if (input.getPosition() != searchStartPosition) {
|
||||||
@ -159,7 +157,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int readLastPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
|
private int readLastPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long inputLength = input.getLength();
|
long inputLength = input.getLength();
|
||||||
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
|
int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
|
||||||
long searchStartPosition = inputLength - bytesToSearch;
|
long searchStartPosition = inputLength - bytesToSearch;
|
||||||
|
@ -190,7 +190,7 @@ public final class TsExtractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
byte[] buffer = tsPacketBuffer.data;
|
byte[] buffer = tsPacketBuffer.data;
|
||||||
input.peekFully(buffer, 0, TS_PACKET_SIZE * SNIFF_TS_PACKET_COUNT);
|
input.peekFully(buffer, 0, TS_PACKET_SIZE * SNIFF_TS_PACKET_COUNT);
|
||||||
for (int startPosCandidate = 0; startPosCandidate < TS_PACKET_SIZE; startPosCandidate++) {
|
for (int startPosCandidate = 0; startPosCandidate < TS_PACKET_SIZE; startPosCandidate++) {
|
||||||
@ -253,7 +253,7 @@ public final class TsExtractor implements Extractor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @ReadResult int read(ExtractorInput input, PositionHolder seekPosition)
|
public @ReadResult int read(ExtractorInput input, PositionHolder seekPosition)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long inputLength = input.getLength();
|
long inputLength = input.getLength();
|
||||||
if (tracksEnded) {
|
if (tracksEnded) {
|
||||||
boolean canReadDuration = inputLength != C.LENGTH_UNSET && mode != MODE_HLS;
|
boolean canReadDuration = inputLength != C.LENGTH_UNSET && mode != MODE_HLS;
|
||||||
@ -372,8 +372,7 @@ public final class TsExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fillBufferWithAtLeastOnePacket(ExtractorInput input)
|
private boolean fillBufferWithAtLeastOnePacket(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
byte[] data = tsPacketBuffer.data;
|
byte[] data = tsPacketBuffer.data;
|
||||||
// Shift bytes to the start of the buffer if there isn't enough space left at the end.
|
// Shift bytes to the start of the buffer if there isn't enough space left at the end.
|
||||||
if (BUFFER_SIZE - tsPacketBuffer.getPosition() < TS_PACKET_SIZE) {
|
if (BUFFER_SIZE - tsPacketBuffer.getPosition() < TS_PACKET_SIZE) {
|
||||||
|
@ -61,7 +61,7 @@ public final class WavExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
return WavHeaderReader.peek(input) != null;
|
return WavHeaderReader.peek(input) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,8 +85,7 @@ public final class WavExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
assertInitialized();
|
assertInitialized();
|
||||||
if (outputWriter == null) {
|
if (outputWriter == null) {
|
||||||
WavHeader header = WavHeaderReader.peek(input);
|
WavHeader header = WavHeaderReader.peek(input);
|
||||||
@ -176,10 +175,8 @@ public final class WavExtractor implements Extractor {
|
|||||||
* @param bytesLeft The number of sample data bytes left to be read from the input.
|
* @param bytesLeft The number of sample data bytes left to be read from the input.
|
||||||
* @return Whether the end of the sample data has been reached.
|
* @return Whether the end of the sample data has been reached.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread has been interrupted.
|
|
||||||
*/
|
*/
|
||||||
boolean sampleData(ExtractorInput input, long bytesLeft)
|
boolean sampleData(ExtractorInput input, long bytesLeft) throws IOException;
|
||||||
throws IOException, InterruptedException;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class PassthroughOutputWriter implements OutputWriter {
|
private static final class PassthroughOutputWriter implements OutputWriter {
|
||||||
@ -253,8 +250,7 @@ public final class WavExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sampleData(ExtractorInput input, long bytesLeft)
|
public boolean sampleData(ExtractorInput input, long bytesLeft) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
// Write sample data until we've reached the target sample size, or the end of the data.
|
// Write sample data until we've reached the target sample size, or the end of the data.
|
||||||
boolean endOfSampleData = bytesLeft == 0;
|
boolean endOfSampleData = bytesLeft == 0;
|
||||||
while (!endOfSampleData && pendingOutputBytes < targetSampleSizeBytes) {
|
while (!endOfSampleData && pendingOutputBytes < targetSampleSizeBytes) {
|
||||||
@ -397,8 +393,7 @@ public final class WavExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sampleData(ExtractorInput input, long bytesLeft)
|
public boolean sampleData(ExtractorInput input, long bytesLeft) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
// Calculate the number of additional frames that we need on the output side to complete a
|
// Calculate the number of additional frames that we need on the output side to complete a
|
||||||
// sample of the target size.
|
// sample of the target size.
|
||||||
int targetFramesRemaining =
|
int targetFramesRemaining =
|
||||||
|
@ -38,12 +38,11 @@ import java.io.IOException;
|
|||||||
* @param input Input stream to peek the WAV header from.
|
* @param input Input stream to peek the WAV header from.
|
||||||
* @throws ParserException If the input file is an incorrect RIFF WAV.
|
* @throws ParserException If the input file is an incorrect RIFF WAV.
|
||||||
* @throws IOException If peeking from the input fails.
|
* @throws IOException If peeking from the input fails.
|
||||||
* @throws InterruptedException If interrupted while peeking from input.
|
|
||||||
* @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a
|
* @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a
|
||||||
* supported WAV format.
|
* supported WAV format.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static WavHeader peek(ExtractorInput input) throws IOException, InterruptedException {
|
public static WavHeader peek(ExtractorInput input) throws IOException {
|
||||||
Assertions.checkNotNull(input);
|
Assertions.checkNotNull(input);
|
||||||
|
|
||||||
// Allocate a scratch buffer large enough to store the format chunk.
|
// Allocate a scratch buffer large enough to store the format chunk.
|
||||||
@ -108,10 +107,8 @@ import java.io.IOException;
|
|||||||
* @return The byte positions at which the data starts (inclusive) and ends (exclusive).
|
* @return The byte positions at which the data starts (inclusive) and ends (exclusive).
|
||||||
* @throws ParserException If an error occurs parsing chunks.
|
* @throws ParserException If an error occurs parsing chunks.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from input.
|
|
||||||
*/
|
*/
|
||||||
public static Pair<Long, Long> skipToData(ExtractorInput input)
|
public static Pair<Long, Long> skipToData(ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Assertions.checkNotNull(input);
|
Assertions.checkNotNull(input);
|
||||||
|
|
||||||
// Make sure the peek position is set to the read position before we peek the first header.
|
// Make sure the peek position is set to the read position before we peek the first header.
|
||||||
@ -174,11 +171,10 @@ import java.io.IOException;
|
|||||||
* @param input Input stream to peek the chunk header from.
|
* @param input Input stream to peek the chunk header from.
|
||||||
* @param scratch Buffer for temporary use.
|
* @param scratch Buffer for temporary use.
|
||||||
* @throws IOException If peeking from the input fails.
|
* @throws IOException If peeking from the input fails.
|
||||||
* @throws InterruptedException If interrupted while peeking from input.
|
|
||||||
* @return A new {@code ChunkHeader} peeked from {@code input}.
|
* @return A new {@code ChunkHeader} peeked from {@code input}.
|
||||||
*/
|
*/
|
||||||
public static ChunkHeader peek(ExtractorInput input, ParsableByteArray scratch)
|
public static ChunkHeader peek(ExtractorInput input, ParsableByteArray scratch)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
input.peekFully(scratch.data, /* offset= */ 0, /* length= */ SIZE_IN_BYTES);
|
input.peekFully(scratch.data, /* offset= */ 0, /* length= */ SIZE_IN_BYTES);
|
||||||
scratch.setPosition(0);
|
scratch.setPosition(0);
|
||||||
|
|
||||||
|
@ -307,8 +307,7 @@ public class FlacFrameReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ExtractorInput buildExtractorInputReadingFromFirstFrame(
|
private ExtractorInput buildExtractorInputReadingFromFirstFrame(
|
||||||
String file, FlacStreamMetadataHolder streamMetadataHolder)
|
String file, FlacStreamMetadataHolder streamMetadataHolder) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
ExtractorInput input = buildExtractorInput(file);
|
ExtractorInput input = buildExtractorInput(file);
|
||||||
|
|
||||||
input.skipFully(FlacConstants.STREAM_MARKER_SIZE);
|
input.skipFully(FlacConstants.STREAM_MARKER_SIZE);
|
||||||
|
@ -35,8 +35,7 @@ import org.junit.runner.RunWith;
|
|||||||
public final class Id3PeekerTest {
|
public final class Id3PeekerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void peekId3Data_returnNull_ifId3TagNotPresentAtBeginningOfInput()
|
public void peekId3Data_returnNull_ifId3TagNotPresentAtBeginningOfInput() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Id3Peeker id3Peeker = new Id3Peeker();
|
Id3Peeker id3Peeker = new Id3Peeker();
|
||||||
FakeExtractorInput input =
|
FakeExtractorInput input =
|
||||||
new FakeExtractorInput.Builder()
|
new FakeExtractorInput.Builder()
|
||||||
@ -48,7 +47,7 @@ public final class Id3PeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void peekId3Data_returnId3Tag_ifId3TagPresent() throws IOException, InterruptedException {
|
public void peekId3Data_returnId3Tag_ifId3TagPresent() throws IOException {
|
||||||
Id3Peeker id3Peeker = new Id3Peeker();
|
Id3Peeker id3Peeker = new Id3Peeker();
|
||||||
FakeExtractorInput input =
|
FakeExtractorInput input =
|
||||||
new FakeExtractorInput.Builder()
|
new FakeExtractorInput.Builder()
|
||||||
@ -69,7 +68,7 @@ public final class Id3PeekerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void peekId3Data_returnId3TagAccordingToGivenPredicate_ifId3TagPresent()
|
public void peekId3Data_returnId3TagAccordingToGivenPredicate_ifId3TagPresent()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
Id3Peeker id3Peeker = new Id3Peeker();
|
Id3Peeker id3Peeker = new Id3Peeker();
|
||||||
FakeExtractorInput input =
|
FakeExtractorInput input =
|
||||||
new FakeExtractorInput.Builder()
|
new FakeExtractorInput.Builder()
|
||||||
|
@ -56,8 +56,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void amrExtractorReads_returnSeekableSeekMap_forNarrowBandAmr()
|
public void amrExtractorReads_returnSeekableSeekMap_forNarrowBandAmr() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = NARROW_BAND_AMR_FILE;
|
String fileName = NARROW_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -77,7 +76,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingToPositionInFile_extractsCorrectFrame_forNarrowBandAmr()
|
public void seeking_handlesSeekingToPositionInFile_extractsCorrectFrame_forNarrowBandAmr()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
String fileName = NARROW_BAND_AMR_FILE;
|
String fileName = NARROW_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -103,8 +102,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekToEoF_extractsLastFrame_forNarrowBandAmr()
|
public void seeking_handlesSeekToEoF_extractsLastFrame_forNarrowBandAmr() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = NARROW_BAND_AMR_FILE;
|
String fileName = NARROW_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -131,7 +129,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingBackward_extractsCorrectFrames_forNarrowBandAmr()
|
public void seeking_handlesSeekingBackward_extractsCorrectFrames_forNarrowBandAmr()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
String fileName = NARROW_BAND_AMR_FILE;
|
String fileName = NARROW_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -160,7 +158,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingForward_extractsCorrectFrames_forNarrowBandAmr()
|
public void seeking_handlesSeekingForward_extractsCorrectFrames_forNarrowBandAmr()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
String fileName = NARROW_BAND_AMR_FILE;
|
String fileName = NARROW_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -189,7 +187,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesRandomSeeks_extractsCorrectFrames_forNarrowBandAmr()
|
public void seeking_handlesRandomSeeks_extractsCorrectFrames_forNarrowBandAmr()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
String fileName = NARROW_BAND_AMR_FILE;
|
String fileName = NARROW_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -217,8 +215,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void amrExtractorReads_returnSeekableSeekMap_forWideBandAmr()
|
public void amrExtractorReads_returnSeekableSeekMap_forWideBandAmr() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = WIDE_BAND_AMR_FILE;
|
String fileName = WIDE_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -238,7 +235,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingToPositionInFile_extractsCorrectFrame_forWideBandAmr()
|
public void seeking_handlesSeekingToPositionInFile_extractsCorrectFrame_forWideBandAmr()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
String fileName = WIDE_BAND_AMR_FILE;
|
String fileName = WIDE_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -264,8 +261,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekToEoF_extractsLastFrame_forWideBandAmr()
|
public void seeking_handlesSeekToEoF_extractsLastFrame_forWideBandAmr() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = WIDE_BAND_AMR_FILE;
|
String fileName = WIDE_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -292,7 +288,7 @@ public final class AmrExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingBackward_extractsCorrectFrames_forWideBandAmr()
|
public void seeking_handlesSeekingBackward_extractsCorrectFrames_forWideBandAmr()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
String fileName = WIDE_BAND_AMR_FILE;
|
String fileName = WIDE_BAND_AMR_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
|
@ -42,7 +42,7 @@ public final class AmrExtractorTest {
|
|||||||
private static final Random RANDOM = new Random(1234);
|
private static final Random RANDOM = new Random(1234);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sniff_nonAmrSignature_returnFalse() throws IOException, InterruptedException {
|
public void sniff_nonAmrSignature_returnFalse() throws IOException {
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
FakeExtractorInput input = fakeExtractorInputWithData(Util.getUtf8Bytes("0#!AMR\n123"));
|
FakeExtractorInput input = fakeExtractorInputWithData(Util.getUtf8Bytes("0#!AMR\n123"));
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ public final class AmrExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void read_nonAmrSignature_throwParserException() throws IOException, InterruptedException {
|
public void read_nonAmrSignature_throwParserException() throws IOException {
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
FakeExtractorInput input = fakeExtractorInputWithData(Util.getUtf8Bytes("0#!AMR-WB\n"));
|
FakeExtractorInput input = fakeExtractorInputWithData(Util.getUtf8Bytes("0#!AMR-WB\n"));
|
||||||
|
|
||||||
@ -64,8 +64,7 @@ public final class AmrExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void read_amrNb_returnParserException_forInvalidFrameType()
|
public void read_amrNb_returnParserException_forInvalidFrameType() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
|
|
||||||
// Frame type 12-14 for narrow band is reserved for future usage.
|
// Frame type 12-14 for narrow band is reserved for future usage.
|
||||||
@ -82,8 +81,7 @@ public final class AmrExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void read_amrWb_returnParserException_forInvalidFrameType()
|
public void read_amrWb_returnParserException_forInvalidFrameType() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
|
|
||||||
// Frame type 10-13 for wide band is reserved for future usage.
|
// Frame type 10-13 for wide band is reserved for future usage.
|
||||||
@ -100,8 +98,7 @@ public final class AmrExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void read_amrNb_returnEndOfInput_ifInputEncountersEoF()
|
public void read_amrNb_returnEndOfInput_ifInputEncountersEoF() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
|
|
||||||
byte[] amrFrame = newNarrowBandAmrFrameWithType(3);
|
byte[] amrFrame = newNarrowBandAmrFrameWithType(3);
|
||||||
@ -116,8 +113,7 @@ public final class AmrExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void read_amrWb_returnEndOfInput_ifInputEncountersEoF()
|
public void read_amrWb_returnEndOfInput_ifInputEncountersEoF() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
|
|
||||||
byte[] amrFrame = newWideBandAmrFrameWithType(5);
|
byte[] amrFrame = newWideBandAmrFrameWithType(5);
|
||||||
@ -132,8 +128,7 @@ public final class AmrExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void read_amrNb_returnParserException_forInvalidFrameHeader()
|
public void read_amrNb_returnParserException_forInvalidFrameHeader() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
|
|
||||||
byte[] invalidHeaderFrame = newNarrowBandAmrFrameWithType(4);
|
byte[] invalidHeaderFrame = newNarrowBandAmrFrameWithType(4);
|
||||||
@ -154,8 +149,7 @@ public final class AmrExtractorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void read_amrWb_returnParserException_forInvalidFrameHeader()
|
public void read_amrWb_returnParserException_forInvalidFrameHeader() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
AmrExtractor amrExtractor = setupAmrExtractorWithOutput();
|
||||||
|
|
||||||
byte[] invalidHeaderFrame = newWideBandAmrFrameWithType(6);
|
byte[] invalidHeaderFrame = newWideBandAmrFrameWithType(6);
|
||||||
|
@ -49,8 +49,7 @@ public class FlacExtractorSeekTest {
|
|||||||
.createDataSource();
|
.createDataSource();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flacExtractorReads_seekTable_returnSeekableSeekMap()
|
public void flacExtractorReads_seekTable_returnSeekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_SEEK_TABLE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_SEEK_TABLE);
|
||||||
|
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -61,7 +60,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekToZero() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekToZero() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -78,7 +77,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekToEoF() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekToEoF() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -95,7 +94,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekingBackward() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekingBackward() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -114,7 +113,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_seekTable_handlesSeekingForward() throws IOException, InterruptedException {
|
public void seeking_seekTable_handlesSeekingForward() throws IOException {
|
||||||
String fileName = TEST_FILE_SEEK_TABLE;
|
String fileName = TEST_FILE_SEEK_TABLE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -133,8 +132,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flacExtractorReads_binarySearch_returnSeekableSeekMap()
|
public void flacExtractorReads_binarySearch_returnSeekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_BINARY_SEARCH);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_BINARY_SEARCH);
|
||||||
|
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -145,7 +143,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekToZero() throws IOException, InterruptedException {
|
public void seeking_binarySearch_handlesSeekToZero() throws IOException {
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -162,7 +160,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekToEoF() throws IOException, InterruptedException {
|
public void seeking_binarySearch_handlesSeekToEoF() throws IOException {
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -179,8 +177,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekingBackward()
|
public void seeking_binarySearch_handlesSeekingBackward() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -199,8 +196,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_binarySearch_handlesSeekingForward()
|
public void seeking_binarySearch_handlesSeekingForward() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE_BINARY_SEARCH;
|
String fileName = TEST_FILE_BINARY_SEARCH;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -219,8 +215,7 @@ public class FlacExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flacExtractorReads_unseekable_returnUnseekableSeekMap()
|
public void flacExtractorReads_unseekable_returnUnseekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_UNSEEKABLE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_UNSEEKABLE);
|
||||||
|
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -235,7 +230,7 @@ public class FlacExtractorSeekTest {
|
|||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
long targetSeekTimeUs,
|
long targetSeekTimeUs,
|
||||||
int firstFrameIndexAfterSeek)
|
int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
int expectedFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
int expectedFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
||||||
|
|
||||||
@ -252,7 +247,7 @@ public class FlacExtractorSeekTest {
|
|||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
long targetSeekTimeUs,
|
long targetSeekTimeUs,
|
||||||
int firstFrameIndexAfterSeek)
|
int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
int maxFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
int maxFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
||||||
|
|
||||||
@ -276,8 +271,7 @@ public class FlacExtractorSeekTest {
|
|||||||
assertThat(frameFound).isTrue();
|
assertThat(frameFound).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FakeTrackOutput getExpectedTrackOutput(String fileName)
|
private static FakeTrackOutput getExpectedTrackOutput(String fileName) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
return TestUtil.extractAllSamplesFromFile(
|
return TestUtil.extractAllSamplesFromFile(
|
||||||
new FlacExtractor(), ApplicationProvider.getApplicationContext(), fileName)
|
new FlacExtractor(), ApplicationProvider.getApplicationContext(), fileName)
|
||||||
.trackOutputs
|
.trackOutputs
|
||||||
|
@ -33,7 +33,7 @@ import org.junit.runner.RunWith;
|
|||||||
public class DefaultEbmlReaderTest {
|
public class DefaultEbmlReaderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void masterElement() throws IOException, InterruptedException {
|
public void masterElement() throws IOException {
|
||||||
ExtractorInput input = createTestInput(0x1A, 0x45, 0xDF, 0xA3, 0x84, 0x42, 0x85, 0x81, 0x01);
|
ExtractorInput input = createTestInput(0x1A, 0x45, 0xDF, 0xA3, 0x84, 0x42, 0x85, 0x81, 0x01);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
expected.startMasterElement(TestProcessor.ID_EBML, 5, 4);
|
expected.startMasterElement(TestProcessor.ID_EBML, 5, 4);
|
||||||
@ -43,7 +43,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void masterElementEmpty() throws IOException, InterruptedException {
|
public void masterElementEmpty() throws IOException {
|
||||||
ExtractorInput input = createTestInput(0x18, 0x53, 0x80, 0x67, 0x80);
|
ExtractorInput input = createTestInput(0x18, 0x53, 0x80, 0x67, 0x80);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
expected.startMasterElement(TestProcessor.ID_SEGMENT, 5, 0);
|
expected.startMasterElement(TestProcessor.ID_SEGMENT, 5, 0);
|
||||||
@ -52,7 +52,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unsignedIntegerElement() throws IOException, InterruptedException {
|
public void unsignedIntegerElement() throws IOException {
|
||||||
// 0xFE is chosen because for signed integers it should be interpreted as -2
|
// 0xFE is chosen because for signed integers it should be interpreted as -2
|
||||||
ExtractorInput input = createTestInput(0x42, 0xF7, 0x81, 0xFE);
|
ExtractorInput input = createTestInput(0x42, 0xF7, 0x81, 0xFE);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
@ -61,7 +61,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unsignedIntegerElementLarge() throws IOException, InterruptedException {
|
public void unsignedIntegerElementLarge() throws IOException {
|
||||||
ExtractorInput input =
|
ExtractorInput input =
|
||||||
createTestInput(0x42, 0xF7, 0x88, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
|
createTestInput(0x42, 0xF7, 0x88, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
@ -70,8 +70,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unsignedIntegerElementTooLargeBecomesNegative()
|
public void unsignedIntegerElementTooLargeBecomesNegative() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
ExtractorInput input =
|
ExtractorInput input =
|
||||||
createTestInput(0x42, 0xF7, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
|
createTestInput(0x42, 0xF7, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
@ -80,7 +79,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void stringElement() throws IOException, InterruptedException {
|
public void stringElement() throws IOException {
|
||||||
ExtractorInput input = createTestInput(0x42, 0x82, 0x86, 0x41, 0x62, 0x63, 0x31, 0x32, 0x33);
|
ExtractorInput input = createTestInput(0x42, 0x82, 0x86, 0x41, 0x62, 0x63, 0x31, 0x32, 0x33);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
expected.stringElement(TestProcessor.ID_DOC_TYPE, "Abc123");
|
expected.stringElement(TestProcessor.ID_DOC_TYPE, "Abc123");
|
||||||
@ -96,7 +95,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void stringElementEmpty() throws IOException, InterruptedException {
|
public void stringElementEmpty() throws IOException {
|
||||||
ExtractorInput input = createTestInput(0x42, 0x82, 0x80);
|
ExtractorInput input = createTestInput(0x42, 0x82, 0x80);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
expected.stringElement(TestProcessor.ID_DOC_TYPE, "");
|
expected.stringElement(TestProcessor.ID_DOC_TYPE, "");
|
||||||
@ -104,7 +103,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void floatElementFourBytes() throws IOException, InterruptedException {
|
public void floatElementFourBytes() throws IOException {
|
||||||
ExtractorInput input =
|
ExtractorInput input =
|
||||||
createTestInput(0x44, 0x89, 0x84, 0x3F, 0x80, 0x00, 0x00);
|
createTestInput(0x44, 0x89, 0x84, 0x3F, 0x80, 0x00, 0x00);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
@ -113,7 +112,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void floatElementEightBytes() throws IOException, InterruptedException {
|
public void floatElementEightBytes() throws IOException {
|
||||||
ExtractorInput input =
|
ExtractorInput input =
|
||||||
createTestInput(0x44, 0x89, 0x88, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
createTestInput(0x44, 0x89, 0x88, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
@ -122,7 +121,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void binaryElement() throws IOException, InterruptedException {
|
public void binaryElement() throws IOException {
|
||||||
ExtractorInput input =
|
ExtractorInput input =
|
||||||
createTestInput(0xA3, 0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
|
createTestInput(0xA3, 0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
|
||||||
TestProcessor expected = new TestProcessor();
|
TestProcessor expected = new TestProcessor();
|
||||||
@ -134,7 +133,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void assertEvents(ExtractorInput input, List<String> expectedEvents)
|
private static void assertEvents(ExtractorInput input, List<String> expectedEvents)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
DefaultEbmlReader reader = new DefaultEbmlReader();
|
DefaultEbmlReader reader = new DefaultEbmlReader();
|
||||||
TestProcessor output = new TestProcessor();
|
TestProcessor output = new TestProcessor();
|
||||||
reader.init(output);
|
reader.init(output);
|
||||||
@ -232,8 +231,7 @@ public class DefaultEbmlReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void binaryElement(int id, int contentSize, ExtractorInput input)
|
public void binaryElement(int id, int contentSize, ExtractorInput input) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
byte[] bytes = new byte[contentSize];
|
byte[] bytes = new byte[contentSize];
|
||||||
input.readFully(bytes, 0, contentSize);
|
input.readFully(bytes, 0, contentSize);
|
||||||
events.add(formatEvent(id, "bytes=" + Arrays.toString(bytes)));
|
events.add(formatEvent(id, "bytes=" + Arrays.toString(bytes)));
|
||||||
|
@ -85,7 +85,7 @@ public final class VarintReaderTest {
|
|||||||
private static final long VALUE_8_BYTE_MAX_WITH_MASK = 0x1FFFFFFFFFFFFFFL;
|
private static final long VALUE_8_BYTE_MAX_WITH_MASK = 0x1FFFFFFFFFFFFFFL;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readVarintEndOfInputAtStart() throws IOException, InterruptedException {
|
public void readVarintEndOfInputAtStart() throws IOException {
|
||||||
VarintReader reader = new VarintReader();
|
VarintReader reader = new VarintReader();
|
||||||
// Build an input with no data.
|
// Build an input with no data.
|
||||||
ExtractorInput input = new FakeExtractorInput.Builder()
|
ExtractorInput input = new FakeExtractorInput.Builder()
|
||||||
@ -104,7 +104,7 @@ public final class VarintReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readVarintExceedsMaximumAllowedLength() throws IOException, InterruptedException {
|
public void readVarintExceedsMaximumAllowedLength() throws IOException {
|
||||||
VarintReader reader = new VarintReader();
|
VarintReader reader = new VarintReader();
|
||||||
ExtractorInput input = new FakeExtractorInput.Builder()
|
ExtractorInput input = new FakeExtractorInput.Builder()
|
||||||
.setData(DATA_8_BYTE_0)
|
.setData(DATA_8_BYTE_0)
|
||||||
@ -115,7 +115,7 @@ public final class VarintReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readVarint() throws IOException, InterruptedException {
|
public void readVarint() throws IOException {
|
||||||
VarintReader reader = new VarintReader();
|
VarintReader reader = new VarintReader();
|
||||||
testReadVarint(reader, true, DATA_1_BYTE_0, 1, 0);
|
testReadVarint(reader, true, DATA_1_BYTE_0, 1, 0);
|
||||||
testReadVarint(reader, true, DATA_2_BYTE_0, 2, 0);
|
testReadVarint(reader, true, DATA_2_BYTE_0, 2, 0);
|
||||||
@ -152,7 +152,7 @@ public final class VarintReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readVarintFlaky() throws IOException, InterruptedException {
|
public void readVarintFlaky() throws IOException {
|
||||||
VarintReader reader = new VarintReader();
|
VarintReader reader = new VarintReader();
|
||||||
testReadVarintFlaky(reader, true, DATA_1_BYTE_0, 1, 0);
|
testReadVarintFlaky(reader, true, DATA_1_BYTE_0, 1, 0);
|
||||||
testReadVarintFlaky(reader, true, DATA_2_BYTE_0, 2, 0);
|
testReadVarintFlaky(reader, true, DATA_2_BYTE_0, 2, 0);
|
||||||
@ -188,8 +188,9 @@ public final class VarintReaderTest {
|
|||||||
testReadVarintFlaky(reader, false, DATA_8_BYTE_MAX, 8, VALUE_8_BYTE_MAX_WITH_MASK);
|
testReadVarintFlaky(reader, false, DATA_8_BYTE_MAX, 8, VALUE_8_BYTE_MAX_WITH_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testReadVarint(VarintReader reader, boolean removeMask, byte[] data,
|
private static void testReadVarint(
|
||||||
int expectedLength, long expectedValue) throws IOException, InterruptedException {
|
VarintReader reader, boolean removeMask, byte[] data, int expectedLength, long expectedValue)
|
||||||
|
throws IOException {
|
||||||
ExtractorInput input = new FakeExtractorInput.Builder()
|
ExtractorInput input = new FakeExtractorInput.Builder()
|
||||||
.setData(data)
|
.setData(data)
|
||||||
.setSimulateUnknownLength(true)
|
.setSimulateUnknownLength(true)
|
||||||
@ -199,8 +200,9 @@ public final class VarintReaderTest {
|
|||||||
assertThat(result).isEqualTo(expectedValue);
|
assertThat(result).isEqualTo(expectedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testReadVarintFlaky(VarintReader reader, boolean removeMask, byte[] data,
|
private static void testReadVarintFlaky(
|
||||||
int expectedLength, long expectedValue) throws IOException, InterruptedException {
|
VarintReader reader, boolean removeMask, byte[] data, int expectedLength, long expectedValue)
|
||||||
|
throws IOException {
|
||||||
ExtractorInput input = new FakeExtractorInput.Builder()
|
ExtractorInput input = new FakeExtractorInput.Builder()
|
||||||
.setData(data)
|
.setData(data)
|
||||||
.setSimulateUnknownLength(true)
|
.setSimulateUnknownLength(true)
|
||||||
|
@ -57,7 +57,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void mp3ExtractorReads_returnSeekableCbrSeeker() throws IOException, InterruptedException {
|
public void mp3ExtractorReads_returnSeekableCbrSeeker() throws IOException {
|
||||||
Uri fileUri = TestUtil.buildAssetUri(CONSTANT_FRAME_SIZE_TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(CONSTANT_FRAME_SIZE_TEST_FILE);
|
||||||
|
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -68,7 +68,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekToZero() throws IOException, InterruptedException {
|
public void seeking_handlesSeekToZero() throws IOException {
|
||||||
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -85,7 +85,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekToEoF() throws IOException, InterruptedException {
|
public void seeking_handlesSeekToEoF() throws IOException {
|
||||||
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -102,7 +102,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingBackward() throws IOException, InterruptedException {
|
public void seeking_handlesSeekingBackward() throws IOException {
|
||||||
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -121,7 +121,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingForward() throws IOException, InterruptedException {
|
public void seeking_handlesSeekingForward() throws IOException {
|
||||||
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
String fileName = CONSTANT_FRAME_SIZE_TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -140,8 +140,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_variableFrameSize_seeksNearlyExactlyToCorrectFrame()
|
public void seeking_variableFrameSize_seeksNearlyExactlyToCorrectFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = VARIABLE_FRAME_SIZE_TEST_FILE;
|
String fileName = VARIABLE_FRAME_SIZE_TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
|
||||||
@ -162,7 +161,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
long targetSeekTimeUs,
|
long targetSeekTimeUs,
|
||||||
int firstFrameIndexAfterSeek)
|
int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
int exactFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
int exactFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
||||||
|
|
||||||
@ -175,7 +174,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
long targetSeekTimeUs,
|
long targetSeekTimeUs,
|
||||||
int firstFrameIndexAfterSeek)
|
int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
int exactFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
int exactFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
||||||
|
|
||||||
@ -197,8 +196,7 @@ public class ConstantBitrateSeekerTest {
|
|||||||
assertThat(foundPreviousFrame || foundExactFrame || foundNextFrame).isTrue();
|
assertThat(foundPreviousFrame || foundExactFrame || foundNextFrame).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FakeTrackOutput getExpectedTrackOutput(String fileName)
|
private static FakeTrackOutput getExpectedTrackOutput(String fileName) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
return TestUtil.extractAllSamplesFromFile(
|
return TestUtil.extractAllSamplesFromFile(
|
||||||
new Mp3Extractor(), ApplicationProvider.getApplicationContext(), fileName)
|
new Mp3Extractor(), ApplicationProvider.getApplicationContext(), fileName)
|
||||||
.trackOutputs
|
.trackOutputs
|
||||||
|
@ -157,7 +157,7 @@ public class IndexSeekerTest {
|
|||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
long targetSeekTimeUs,
|
long targetSeekTimeUs,
|
||||||
int firstFrameIndexAfterSeek)
|
int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
int exactFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
int exactFrameIndex = getFrameIndex(expectedTrackOutput, targetSeekTimeUs);
|
||||||
long exactFrameTimeUs = expectedTrackOutput.getSampleTimeUs(exactFrameIndex);
|
long exactFrameTimeUs = expectedTrackOutput.getSampleTimeUs(exactFrameIndex);
|
||||||
@ -168,7 +168,7 @@ public class IndexSeekerTest {
|
|||||||
|
|
||||||
private static void assertFirstFrameAfterSeekHasCorrectData(
|
private static void assertFirstFrameAfterSeekHasCorrectData(
|
||||||
String fileName, FakeTrackOutput trackOutput, int firstFrameIndexAfterSeek)
|
String fileName, FakeTrackOutput trackOutput, int firstFrameIndexAfterSeek)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
FakeTrackOutput expectedTrackOutput = getExpectedTrackOutput(fileName);
|
||||||
long foundTimeUs = trackOutput.getSampleTimeUs(firstFrameIndexAfterSeek);
|
long foundTimeUs = trackOutput.getSampleTimeUs(firstFrameIndexAfterSeek);
|
||||||
int foundFrameIndex = getFrameIndex(expectedTrackOutput, foundTimeUs);
|
int foundFrameIndex = getFrameIndex(expectedTrackOutput, foundTimeUs);
|
||||||
@ -181,8 +181,7 @@ public class IndexSeekerTest {
|
|||||||
expectedTrackOutput.getSampleCryptoData(foundFrameIndex));
|
expectedTrackOutput.getSampleCryptoData(foundFrameIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FakeTrackOutput getExpectedTrackOutput(String fileName)
|
private static FakeTrackOutput getExpectedTrackOutput(String fileName) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
return extractAllSamplesFromFile(
|
return extractAllSamplesFromFile(
|
||||||
new Mp3Extractor(FLAG_ENABLE_INDEX_SEEKING),
|
new Mp3Extractor(FLAG_ENABLE_INDEX_SEEKING),
|
||||||
ApplicationProvider.getApplicationContext(),
|
ApplicationProvider.getApplicationContext(),
|
||||||
|
@ -170,7 +170,7 @@ public final class DefaultOggSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readGranuleOfLastPage() throws IOException, InterruptedException {
|
public void readGranuleOfLastPage() throws IOException {
|
||||||
// This test stream has three headers with granule numbers 20000, 40000 and 60000.
|
// This test stream has three headers with granule numbers 20000, 40000 and 60000.
|
||||||
byte[] data = getByteArray(ApplicationProvider.getApplicationContext(), "ogg/three_headers");
|
byte[] data = getByteArray(ApplicationProvider.getApplicationContext(), "ogg/three_headers");
|
||||||
FakeExtractorInput input = createInput(data, /* simulateUnknownLength= */ false);
|
FakeExtractorInput input = createInput(data, /* simulateUnknownLength= */ false);
|
||||||
@ -200,8 +200,7 @@ public final class DefaultOggSeekerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void skipToNextPage(ExtractorInput extractorInput)
|
private static void skipToNextPage(ExtractorInput extractorInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
DefaultOggSeeker oggSeeker =
|
DefaultOggSeeker oggSeeker =
|
||||||
new DefaultOggSeeker(
|
new DefaultOggSeeker(
|
||||||
/* streamReader= */ new FlacReader(),
|
/* streamReader= */ new FlacReader(),
|
||||||
@ -221,7 +220,7 @@ public final class DefaultOggSeekerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void assertReadGranuleOfLastPage(FakeExtractorInput input, int expected)
|
private static void assertReadGranuleOfLastPage(FakeExtractorInput input, int expected)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
DefaultOggSeeker oggSeeker =
|
DefaultOggSeeker oggSeeker =
|
||||||
new DefaultOggSeeker(
|
new DefaultOggSeeker(
|
||||||
/* streamReader= */ new FlacReader(),
|
/* streamReader= */ new FlacReader(),
|
||||||
@ -251,7 +250,7 @@ public final class DefaultOggSeekerTest {
|
|||||||
|
|
||||||
private static long seekTo(
|
private static long seekTo(
|
||||||
FakeExtractorInput input, DefaultOggSeeker oggSeeker, long targetGranule, int initialPosition)
|
FakeExtractorInput input, DefaultOggSeeker oggSeeker, long targetGranule, int initialPosition)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long nextSeekPosition = initialPosition;
|
long nextSeekPosition = initialPosition;
|
||||||
oggSeeker.startSeek(targetGranule);
|
oggSeeker.startSeek(targetGranule);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -89,8 +89,7 @@ public final class OggExtractorTest {
|
|||||||
assertSniff(data, /* expectedResult= */ false);
|
assertSniff(data, /* expectedResult= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertSniff(byte[] data, boolean expectedResult)
|
private void assertSniff(byte[] data, boolean expectedResult) throws IOException {
|
||||||
throws InterruptedException, IOException {
|
|
||||||
FakeExtractorInput input =
|
FakeExtractorInput input =
|
||||||
new FakeExtractorInput.Builder()
|
new FakeExtractorInput.Builder()
|
||||||
.setData(data)
|
.setData(data)
|
||||||
|
@ -167,7 +167,7 @@ public final class OggPacketTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseRealFile() throws IOException, InterruptedException {
|
public void parseRealFile() throws IOException {
|
||||||
byte[] data = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TEST_FILE);
|
byte[] data = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TEST_FILE);
|
||||||
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
|
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
|
||||||
int packetCounter = 0;
|
int packetCounter = 0;
|
||||||
@ -187,18 +187,17 @@ public final class OggPacketTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertReadPacket(FakeExtractorInput extractorInput, byte[] expected)
|
private void assertReadPacket(FakeExtractorInput extractorInput, byte[] expected)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
assertThat(readPacket(extractorInput)).isTrue();
|
assertThat(readPacket(extractorInput)).isTrue();
|
||||||
ParsableByteArray payload = oggPacket.getPayload();
|
ParsableByteArray payload = oggPacket.getPayload();
|
||||||
assertThat(Arrays.copyOf(payload.data, payload.limit())).isEqualTo(expected);
|
assertThat(Arrays.copyOf(payload.data, payload.limit())).isEqualTo(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertReadEof(FakeExtractorInput extractorInput)
|
private void assertReadEof(FakeExtractorInput extractorInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
assertThat(readPacket(extractorInput)).isFalse();
|
assertThat(readPacket(extractorInput)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean readPacket(FakeExtractorInput input) throws InterruptedException, IOException {
|
private boolean readPacket(FakeExtractorInput input) throws IOException {
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
return oggPacket.populate(input);
|
return oggPacket.populate(input);
|
||||||
|
@ -56,8 +56,7 @@ public final class VorbisReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readSetupHeaders_withIOExceptions_readSuccess()
|
public void readSetupHeaders_withIOExceptions_readSuccess() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
// initial two pages of bytes which by spec contain the three Vorbis header packets:
|
// initial two pages of bytes which by spec contain the three Vorbis header packets:
|
||||||
// identification, comment and setup header.
|
// identification, comment and setup header.
|
||||||
byte[] data =
|
byte[] data =
|
||||||
@ -99,7 +98,7 @@ public final class VorbisReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static VorbisSetup readSetupHeaders(VorbisReader reader, ExtractorInput input)
|
private static VorbisSetup readSetupHeaders(VorbisReader reader, ExtractorInput input)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
OggPacket oggPacket = new OggPacket();
|
OggPacket oggPacket = new OggPacket();
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
|
@ -54,7 +54,7 @@ public final class AdtsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adtsExtractorReads_returnSeekableSeekMap() throws IOException, InterruptedException {
|
public void adtsExtractorReads_returnSeekableSeekMap() throws IOException {
|
||||||
String fileName = TEST_FILE;
|
String fileName = TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -73,8 +73,7 @@ public final class AdtsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingToPositionInFile_extractsCorrectSample()
|
public void seeking_handlesSeekingToPositionInFile_extractsCorrectSample() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE;
|
String fileName = TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -100,8 +99,7 @@ public final class AdtsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekToEoF_extractsLastSample()
|
public void seeking_handlesSeekToEoF_extractsLastSample() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE;
|
String fileName = TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -127,8 +125,7 @@ public final class AdtsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingBackward_extractsCorrectSamples()
|
public void seeking_handlesSeekingBackward_extractsCorrectSamples() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE;
|
String fileName = TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -156,8 +153,7 @@ public final class AdtsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesSeekingForward_extractsCorrectSamples()
|
public void seeking_handlesSeekingForward_extractsCorrectSamples() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE;
|
String fileName = TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
@ -185,8 +181,7 @@ public final class AdtsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seeking_handlesRandomSeeks_extractsCorrectSamples()
|
public void seeking_handlesRandomSeeks_extractsCorrectSamples() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
String fileName = TEST_FILE;
|
String fileName = TEST_FILE;
|
||||||
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
Uri fileUri = TestUtil.buildAssetUri(fileName);
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
|
@ -47,7 +47,7 @@ public final class PsDurationReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readDuration_returnsCorrectDuration() throws IOException, InterruptedException {
|
public void readDuration_returnsCorrectDuration() throws IOException {
|
||||||
FakeExtractorInput input =
|
FakeExtractorInput input =
|
||||||
new FakeExtractorInput.Builder()
|
new FakeExtractorInput.Builder()
|
||||||
.setData(
|
.setData(
|
||||||
@ -66,8 +66,7 @@ public final class PsDurationReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readDuration_midStream_returnsCorrectDuration()
|
public void readDuration_midStream_returnsCorrectDuration() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
FakeExtractorInput input =
|
FakeExtractorInput input =
|
||||||
new FakeExtractorInput.Builder()
|
new FakeExtractorInput.Builder()
|
||||||
.setData(
|
.setData(
|
||||||
|
@ -60,7 +60,7 @@ public final class PsExtractorSeekTest {
|
|||||||
private long totalInputLength;
|
private long totalInputLength;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws IOException, InterruptedException {
|
public void setUp() throws IOException {
|
||||||
expectedOutput = new FakeExtractorOutput();
|
expectedOutput = new FakeExtractorOutput();
|
||||||
positionHolder = new PositionHolder();
|
positionHolder = new PositionHolder();
|
||||||
extractAllSamplesFromFileToExpectedOutput(
|
extractAllSamplesFromFileToExpectedOutput(
|
||||||
@ -74,8 +74,7 @@ public final class PsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void psExtractorReads_nonSeekTableFile_returnSeekableSeekMap()
|
public void psExtractorReads_nonSeekTableFile_returnSeekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
PsExtractor extractor = new PsExtractor();
|
PsExtractor extractor = new PsExtractor();
|
||||||
|
|
||||||
SeekMap seekMap = extractSeekMapAndTracks(extractor, new FakeExtractorOutput());
|
SeekMap seekMap = extractSeekMapAndTracks(extractor, new FakeExtractorOutput());
|
||||||
@ -87,7 +86,7 @@ public final class PsExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesSeekingToPositionInFile_extractsCorrectFrame()
|
public void handlePendingSeek_handlesSeekingToPositionInFile_extractsCorrectFrame()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
PsExtractor extractor = new PsExtractor();
|
PsExtractor extractor = new PsExtractor();
|
||||||
|
|
||||||
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
||||||
@ -118,8 +117,7 @@ public final class PsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesSeekingBackward_extractsCorrectFrame()
|
public void handlePendingSeek_handlesSeekingBackward_extractsCorrectFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
PsExtractor extractor = new PsExtractor();
|
PsExtractor extractor = new PsExtractor();
|
||||||
|
|
||||||
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
||||||
@ -138,8 +136,7 @@ public final class PsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesSeekingForward_extractsCorrectFrame()
|
public void handlePendingSeek_handlesSeekingForward_extractsCorrectFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
PsExtractor extractor = new PsExtractor();
|
PsExtractor extractor = new PsExtractor();
|
||||||
|
|
||||||
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
||||||
@ -158,8 +155,7 @@ public final class PsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesRandomSeeks_extractsCorrectFrame()
|
public void handlePendingSeek_handlesRandomSeeks_extractsCorrectFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
PsExtractor extractor = new PsExtractor();
|
PsExtractor extractor = new PsExtractor();
|
||||||
|
|
||||||
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
||||||
@ -179,7 +175,7 @@ public final class PsExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesRandomSeeksAfterReadingFileOnce_extractsCorrectFrame()
|
public void handlePendingSeek_handlesRandomSeeksAfterReadingFileOnce_extractsCorrectFrame()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
PsExtractor extractor = new PsExtractor();
|
PsExtractor extractor = new PsExtractor();
|
||||||
|
|
||||||
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
FakeExtractorOutput extractorOutput = new FakeExtractorOutput();
|
||||||
@ -216,7 +212,7 @@ public final class PsExtractorSeekTest {
|
|||||||
*/
|
*/
|
||||||
private int seekToTimeUs(
|
private int seekToTimeUs(
|
||||||
PsExtractor psExtractor, SeekMap seekMap, long seekTimeUs, FakeTrackOutput trackOutput)
|
PsExtractor psExtractor, SeekMap seekMap, long seekTimeUs, FakeTrackOutput trackOutput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int numSampleBeforeSeek = trackOutput.getSampleCount();
|
int numSampleBeforeSeek = trackOutput.getSampleCount();
|
||||||
SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
|
SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
|
||||||
|
|
||||||
@ -250,7 +246,7 @@ public final class PsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SeekMap extractSeekMapAndTracks(PsExtractor extractor, FakeExtractorOutput output)
|
private SeekMap extractSeekMapAndTracks(PsExtractor extractor, FakeExtractorOutput output)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
ExtractorInput input = getExtractorInputFromPosition(0);
|
ExtractorInput input = getExtractorInputFromPosition(0);
|
||||||
extractor.init(output);
|
extractor.init(output);
|
||||||
int readResult = Extractor.RESULT_CONTINUE;
|
int readResult = Extractor.RESULT_CONTINUE;
|
||||||
@ -278,7 +274,7 @@ public final class PsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void readInputFileOnce(PsExtractor extractor, FakeExtractorOutput extractorOutput)
|
private void readInputFileOnce(PsExtractor extractor, FakeExtractorOutput extractorOutput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
extractor.init(extractorOutput);
|
extractor.init(extractorOutput);
|
||||||
int readResult = Extractor.RESULT_CONTINUE;
|
int readResult = Extractor.RESULT_CONTINUE;
|
||||||
ExtractorInput input = getExtractorInputFromPosition(0);
|
ExtractorInput input = getExtractorInputFromPosition(0);
|
||||||
@ -348,7 +344,7 @@ public final class PsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void extractAllSamplesFromFileToExpectedOutput(Context context, String fileName)
|
private void extractAllSamplesFromFileToExpectedOutput(Context context, String fileName)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
byte[] data = TestUtil.getByteArray(context, fileName);
|
byte[] data = TestUtil.getByteArray(context, fileName);
|
||||||
|
|
||||||
PsExtractor extractor = new PsExtractor();
|
PsExtractor extractor = new PsExtractor();
|
||||||
|
@ -71,8 +71,7 @@ public final class TsDurationReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readDuration_midStream_returnsCorrectDuration()
|
public void readDuration_midStream_returnsCorrectDuration() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
FakeExtractorInput input =
|
FakeExtractorInput input =
|
||||||
new FakeExtractorInput.Builder()
|
new FakeExtractorInput.Builder()
|
||||||
.setData(
|
.setData(
|
||||||
|
@ -53,7 +53,7 @@ public final class TsExtractorSeekTest {
|
|||||||
private PositionHolder positionHolder;
|
private PositionHolder positionHolder;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws IOException, InterruptedException {
|
public void setUp() throws IOException {
|
||||||
positionHolder = new PositionHolder();
|
positionHolder = new PositionHolder();
|
||||||
expectedTrackOutput =
|
expectedTrackOutput =
|
||||||
TestUtil.extractAllSamplesFromFile(
|
TestUtil.extractAllSamplesFromFile(
|
||||||
@ -67,8 +67,7 @@ public final class TsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tsExtractorReads_nonSeekTableFile_returnSeekableSeekMap()
|
public void tsExtractorReads_nonSeekTableFile_returnSeekableSeekMap() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
||||||
TsExtractor extractor = new TsExtractor();
|
TsExtractor extractor = new TsExtractor();
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ public final class TsExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesSeekingToPositionInFile_extractsCorrectFrame()
|
public void handlePendingSeek_handlesSeekingToPositionInFile_extractsCorrectFrame()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
TsExtractor extractor = new TsExtractor();
|
TsExtractor extractor = new TsExtractor();
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
||||||
|
|
||||||
@ -101,8 +100,7 @@ public final class TsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesSeekToEoF_extractsLastFrame()
|
public void handlePendingSeek_handlesSeekToEoF_extractsLastFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
TsExtractor extractor = new TsExtractor();
|
TsExtractor extractor = new TsExtractor();
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
||||||
|
|
||||||
@ -122,8 +120,7 @@ public final class TsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesSeekingBackward_extractsCorrectFrame()
|
public void handlePendingSeek_handlesSeekingBackward_extractsCorrectFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
TsExtractor extractor = new TsExtractor();
|
TsExtractor extractor = new TsExtractor();
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
||||||
|
|
||||||
@ -145,8 +142,7 @@ public final class TsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesSeekingForward_extractsCorrectFrame()
|
public void handlePendingSeek_handlesSeekingForward_extractsCorrectFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
TsExtractor extractor = new TsExtractor();
|
TsExtractor extractor = new TsExtractor();
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
||||||
|
|
||||||
@ -168,8 +164,7 @@ public final class TsExtractorSeekTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesRandomSeeks_extractsCorrectFrame()
|
public void handlePendingSeek_handlesRandomSeeks_extractsCorrectFrame() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
TsExtractor extractor = new TsExtractor();
|
TsExtractor extractor = new TsExtractor();
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
||||||
|
|
||||||
@ -192,7 +187,7 @@ public final class TsExtractorSeekTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePendingSeek_handlesRandomSeeksAfterReadingFileOnce_extractsCorrectFrame()
|
public void handlePendingSeek_handlesRandomSeeksAfterReadingFileOnce_extractsCorrectFrame()
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
TsExtractor extractor = new TsExtractor();
|
TsExtractor extractor = new TsExtractor();
|
||||||
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE);
|
||||||
|
|
||||||
@ -217,8 +212,7 @@ public final class TsExtractorSeekTest {
|
|||||||
// Internal methods
|
// Internal methods
|
||||||
|
|
||||||
private void readInputFileOnce(
|
private void readInputFileOnce(
|
||||||
TsExtractor extractor, FakeExtractorOutput extractorOutput, Uri fileUri)
|
TsExtractor extractor, FakeExtractorOutput extractorOutput, Uri fileUri) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
extractor.init(extractorOutput);
|
extractor.init(extractorOutput);
|
||||||
int readResult = Extractor.RESULT_CONTINUE;
|
int readResult = Extractor.RESULT_CONTINUE;
|
||||||
ExtractorInput input = TestUtil.getExtractorInputFromPosition(dataSource, 0, fileUri);
|
ExtractorInput input = TestUtil.getExtractorInputFromPosition(dataSource, 0, fileUri);
|
||||||
|
@ -91,7 +91,7 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
|||||||
TimestampAdjuster timestampAdjuster,
|
TimestampAdjuster timestampAdjuster,
|
||||||
Map<String, List<String>> responseHeaders,
|
Map<String, List<String>> responseHeaders,
|
||||||
ExtractorInput extractorInput)
|
ExtractorInput extractorInput)
|
||||||
throws InterruptedException, IOException {
|
throws IOException {
|
||||||
|
|
||||||
if (previousExtractor != null) {
|
if (previousExtractor != null) {
|
||||||
// A extractor has already been successfully used. Return one of the same type.
|
// A extractor has already been successfully used. Return one of the same type.
|
||||||
@ -315,7 +315,7 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean sniffQuietly(Extractor extractor, ExtractorInput input)
|
private static boolean sniffQuietly(Extractor extractor, ExtractorInput input)
|
||||||
throws InterruptedException, IOException {
|
throws IOException {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
try {
|
try {
|
||||||
result = extractor.sniff(input);
|
result = extractor.sniff(input);
|
||||||
|
@ -77,7 +77,6 @@ public interface HlsExtractorFactory {
|
|||||||
* extractor's {@link Extractor#read(ExtractorInput, PositionHolder)}. Must only be used to
|
* extractor's {@link Extractor#read(ExtractorInput, PositionHolder)}. Must only be used to
|
||||||
* call {@link Extractor#sniff(ExtractorInput)}.
|
* call {@link Extractor#sniff(ExtractorInput)}.
|
||||||
* @return A {@link Result}.
|
* @return A {@link Result}.
|
||||||
* @throws InterruptedException If the thread is interrupted while sniffing.
|
|
||||||
* @throws IOException If an I/O error is encountered while sniffing.
|
* @throws IOException If an I/O error is encountered while sniffing.
|
||||||
*/
|
*/
|
||||||
Result createExtractor(
|
Result createExtractor(
|
||||||
@ -88,5 +87,5 @@ public interface HlsExtractorFactory {
|
|||||||
TimestampAdjuster timestampAdjuster,
|
TimestampAdjuster timestampAdjuster,
|
||||||
Map<String, List<String>> responseHeaders,
|
Map<String, List<String>> responseHeaders,
|
||||||
ExtractorInput sniffingExtractorInput)
|
ExtractorInput sniffingExtractorInput)
|
||||||
throws InterruptedException, IOException;
|
throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ import com.google.android.exoplayer2.util.UriUtil;
|
|||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InterruptedIOException;
|
||||||
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;
|
||||||
@ -297,7 +298,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() throws IOException, InterruptedException {
|
public void load() throws IOException {
|
||||||
// output == null means init() hasn't been called.
|
// output == null means init() hasn't been called.
|
||||||
Assertions.checkNotNull(output);
|
Assertions.checkNotNull(output);
|
||||||
if (extractor == null && previousExtractor != null) {
|
if (extractor == null && previousExtractor != null) {
|
||||||
@ -317,7 +318,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
@RequiresNonNull("output")
|
@RequiresNonNull("output")
|
||||||
private void maybeLoadInitData() throws IOException, InterruptedException {
|
private void maybeLoadInitData() throws IOException {
|
||||||
if (!initDataLoadRequired) {
|
if (!initDataLoadRequired) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -330,9 +331,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiresNonNull("output")
|
@RequiresNonNull("output")
|
||||||
private void loadMedia() throws IOException, InterruptedException {
|
private void loadMedia() throws IOException {
|
||||||
if (!isMasterTimestampSource) {
|
if (!isMasterTimestampSource) {
|
||||||
|
try {
|
||||||
timestampAdjuster.waitUntilInitialized();
|
timestampAdjuster.waitUntilInitialized();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new InterruptedIOException();
|
||||||
|
}
|
||||||
} else if (timestampAdjuster.getFirstSampleTimestampUs() == TimestampAdjuster.DO_NOT_OFFSET) {
|
} else if (timestampAdjuster.getFirstSampleTimestampUs() == TimestampAdjuster.DO_NOT_OFFSET) {
|
||||||
// We're the master and we haven't set the desired first sample timestamp yet.
|
// We're the master and we haven't set the desired first sample timestamp yet.
|
||||||
timestampAdjuster.setFirstSampleTimestampUs(startTimeUs);
|
timestampAdjuster.setFirstSampleTimestampUs(startTimeUs);
|
||||||
@ -347,8 +352,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
*/
|
*/
|
||||||
@RequiresNonNull("output")
|
@RequiresNonNull("output")
|
||||||
private void feedDataToExtractor(
|
private void feedDataToExtractor(
|
||||||
DataSource dataSource, DataSpec dataSpec, boolean dataIsEncrypted)
|
DataSource dataSource, DataSpec dataSpec, boolean dataIsEncrypted) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
// If we previously fed part of this chunk to the extractor, we need to skip it this time. For
|
// If we previously fed part of this chunk to the extractor, we need to skip it this time. For
|
||||||
// encrypted content we need to skip the data by reading it through the source, so as to ensure
|
// encrypted content we need to skip the data by reading it through the source, so as to ensure
|
||||||
// correct decryption of the remainder of the chunk. For clear content, we can request the
|
// correct decryption of the remainder of the chunk. For clear content, we can request the
|
||||||
@ -383,7 +387,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
@RequiresNonNull("output")
|
@RequiresNonNull("output")
|
||||||
@EnsuresNonNull("extractor")
|
@EnsuresNonNull("extractor")
|
||||||
private DefaultExtractorInput prepareExtraction(DataSource dataSource, DataSpec dataSpec)
|
private DefaultExtractorInput prepareExtraction(DataSource dataSource, DataSpec dataSpec)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
long bytesToRead = dataSource.open(dataSpec);
|
long bytesToRead = dataSource.open(dataSpec);
|
||||||
DefaultExtractorInput extractorInput =
|
DefaultExtractorInput extractorInput =
|
||||||
new DefaultExtractorInput(dataSource, dataSpec.position, bytesToRead);
|
new DefaultExtractorInput(dataSource, dataSpec.position, bytesToRead);
|
||||||
@ -421,16 +425,15 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peek the presentation timestamp of the first sample in the chunk from an ID3 PRIV as defined
|
* Peek the presentation timestamp of the first sample in the chunk from an ID3 PRIV as defined in
|
||||||
* in the HLS spec, version 20, Section 3.4. Returns {@link C#TIME_UNSET} if the frame is not
|
* the HLS spec, version 20, Section 3.4. Returns {@link C#TIME_UNSET} if the frame is not found.
|
||||||
* found. This method only modifies the peek position.
|
* This method only modifies the peek position.
|
||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} to obtain the PRIV frame from.
|
* @param input The {@link ExtractorInput} to obtain the PRIV frame from.
|
||||||
* @return The parsed, adjusted timestamp in microseconds
|
* @return The parsed, adjusted timestamp in microseconds
|
||||||
* @throws IOException If an error occurred peeking from the input.
|
* @throws IOException If an error occurred peeking from the input.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
private long peekId3PrivTimestamp(ExtractorInput input) throws IOException, InterruptedException {
|
private long peekId3PrivTimestamp(ExtractorInput input) throws IOException {
|
||||||
input.resetPeekPosition();
|
input.resetPeekPosition();
|
||||||
try {
|
try {
|
||||||
input.peekFully(scratchId3Data.data, 0, Id3Decoder.ID3_HEADER_LENGTH);
|
input.peekFully(scratchId3Data.data, 0, Id3Decoder.ID3_HEADER_LENGTH);
|
||||||
|
@ -1460,7 +1460,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
ensureBufferCapacity(bufferPosition + length);
|
ensureBufferCapacity(bufferPosition + length);
|
||||||
int numBytesRead = input.read(buffer, bufferPosition, length);
|
int numBytesRead = input.read(buffer, bufferPosition, length);
|
||||||
if (numBytesRead == C.RESULT_END_OF_INPUT) {
|
if (numBytesRead == C.RESULT_END_OF_INPUT) {
|
||||||
|
@ -72,7 +72,7 @@ public final class WebvttExtractor implements Extractor {
|
|||||||
// Extractor implementation.
|
// Extractor implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
public boolean sniff(ExtractorInput input) throws IOException {
|
||||||
// Check whether there is a header without BOM.
|
// Check whether there is a header without BOM.
|
||||||
input.peekFully(
|
input.peekFully(
|
||||||
sampleData, /* offset= */ 0, /* length= */ HEADER_MIN_LENGTH, /* allowEndOfInput= */ false);
|
sampleData, /* offset= */ 0, /* length= */ HEADER_MIN_LENGTH, /* allowEndOfInput= */ false);
|
||||||
@ -108,8 +108,7 @@ public final class WebvttExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
// output == null suggests init() hasn't been called
|
// output == null suggests init() hasn't been called
|
||||||
Assertions.checkNotNull(output);
|
Assertions.checkNotNull(output);
|
||||||
int currentFileSize = (int) input.getLength();
|
int currentFileSize = (int) input.getLength();
|
||||||
|
@ -31,39 +31,39 @@ import org.junit.runner.RunWith;
|
|||||||
public class WebvttExtractorTest {
|
public class WebvttExtractorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sniff_sniffsWebvttHeaderWithTrailingSpace() throws IOException, InterruptedException {
|
public void sniff_sniffsWebvttHeaderWithTrailingSpace() throws IOException {
|
||||||
byte[] data = new byte[] {'W', 'E', 'B', 'V', 'T', 'T', ' ', '\t'};
|
byte[] data = new byte[] {'W', 'E', 'B', 'V', 'T', 'T', ' ', '\t'};
|
||||||
assertThat(sniffData(data)).isTrue();
|
assertThat(sniffData(data)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sniff_discardsByteOrderMark() throws IOException, InterruptedException {
|
public void sniff_discardsByteOrderMark() throws IOException {
|
||||||
byte[] data =
|
byte[] data =
|
||||||
new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'W', 'E', 'B', 'V', 'T', 'T', '\n', ' '};
|
new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'W', 'E', 'B', 'V', 'T', 'T', '\n', ' '};
|
||||||
assertThat(sniffData(data)).isTrue();
|
assertThat(sniffData(data)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sniff_failsForIncorrectBom() throws IOException, InterruptedException {
|
public void sniff_failsForIncorrectBom() throws IOException {
|
||||||
byte[] data =
|
byte[] data =
|
||||||
new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBB, 'W', 'E', 'B', 'V', 'T', 'T', '\n'};
|
new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBB, 'W', 'E', 'B', 'V', 'T', 'T', '\n'};
|
||||||
assertThat(sniffData(data)).isFalse();
|
assertThat(sniffData(data)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sniff_failsForIncompleteHeader() throws IOException, InterruptedException {
|
public void sniff_failsForIncompleteHeader() throws IOException {
|
||||||
byte[] data = new byte[] {'W', 'E', 'B', 'V', 'T', '\n'};
|
byte[] data = new byte[] {'W', 'E', 'B', 'V', 'T', '\n'};
|
||||||
assertThat(sniffData(data)).isFalse();
|
assertThat(sniffData(data)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sniff_failsForIncorrectHeader() throws IOException, InterruptedException {
|
public void sniff_failsForIncorrectHeader() throws IOException {
|
||||||
byte[] data =
|
byte[] data =
|
||||||
new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'W', 'e', 'B', 'V', 'T', 'T', '\n'};
|
new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'W', 'e', 'B', 'V', 'T', 'T', '\n'};
|
||||||
assertThat(sniffData(data)).isFalse();
|
assertThat(sniffData(data)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean sniffData(byte[] data) throws IOException, InterruptedException {
|
private static boolean sniffData(byte[] data) throws IOException {
|
||||||
ExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
|
ExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
|
||||||
try {
|
try {
|
||||||
return new WebvttExtractor(/* language= */ null, new TimestampAdjuster(0)).sniff(input);
|
return new WebvttExtractor(/* language= */ null, new TimestampAdjuster(0)).sniff(input);
|
||||||
|
@ -188,7 +188,7 @@ public final class DashWidevineOfflineTest {
|
|||||||
testRunner.setActionSchedule(schedule).run();
|
testRunner.setActionSchedule(schedule).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadLicense() throws InterruptedException, DrmSessionException, IOException {
|
private void downloadLicense() throws IOException {
|
||||||
DataSource dataSource = httpDataSourceFactory.createDataSource();
|
DataSource dataSource = httpDataSourceFactory.createDataSource();
|
||||||
DashManifest dashManifest = DashUtil.loadManifest(dataSource,
|
DashManifest dashManifest = DashUtil.loadManifest(dataSource,
|
||||||
Uri.parse(DashTestData.WIDEVINE_H264_MANIFEST));
|
Uri.parse(DashTestData.WIDEVINE_H264_MANIFEST));
|
||||||
|
@ -52,11 +52,9 @@ public final class ExtractorAsserts {
|
|||||||
* @param input The extractor input.
|
* @param input The extractor input.
|
||||||
* @param expectedResult The expected return value.
|
* @param expectedResult The expected return value.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
public static void assertSniff(
|
public static void assertSniff(
|
||||||
Extractor extractor, FakeExtractorInput input, boolean expectedResult)
|
Extractor extractor, FakeExtractorInput input, boolean expectedResult) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
assertThat(extractor.sniff(input)).isEqualTo(expectedResult);
|
assertThat(extractor.sniff(input)).isEqualTo(expectedResult);
|
||||||
@ -82,10 +80,8 @@ public final class ExtractorAsserts {
|
|||||||
* class which is to be tested.
|
* class which is to be tested.
|
||||||
* @param file The path to the input sample.
|
* @param file The path to the input sample.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
public static void assertBehavior(ExtractorFactory factory, String file)
|
public static void assertBehavior(ExtractorFactory factory, String file) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
assertBehavior(factory, file, ApplicationProvider.getApplicationContext());
|
assertBehavior(factory, file, ApplicationProvider.getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,10 +100,9 @@ public final class ExtractorAsserts {
|
|||||||
* @param file The path to the input sample.
|
* @param file The path to the input sample.
|
||||||
* @param context To be used to load the sample file.
|
* @param context To be used to load the sample file.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
public static void assertBehavior(ExtractorFactory factory, String file, Context context)
|
public static void assertBehavior(ExtractorFactory factory, String file, Context context)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
assertBehavior(factory, file, context, file);
|
assertBehavior(factory, file, context, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,11 +122,10 @@ public final class ExtractorAsserts {
|
|||||||
* @param context To be used to load the sample file.
|
* @param context To be used to load the sample file.
|
||||||
* @param dumpFilesPrefix The dump files prefix appended to the dump files path.
|
* @param dumpFilesPrefix The dump files prefix appended to the dump files path.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
public static void assertBehavior(
|
public static void assertBehavior(
|
||||||
ExtractorFactory factory, String file, Context context, String dumpFilesPrefix)
|
ExtractorFactory factory, String file, Context context, String dumpFilesPrefix)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
// Check behavior prior to initialization.
|
// Check behavior prior to initialization.
|
||||||
Extractor extractor = factory.create();
|
Extractor extractor = factory.create();
|
||||||
extractor.seek(0, 0);
|
extractor.seek(0, 0);
|
||||||
@ -153,11 +147,10 @@ public final class ExtractorAsserts {
|
|||||||
* @param data Content of the input file.
|
* @param data Content of the input file.
|
||||||
* @param context To be used to load the sample file.
|
* @param context To be used to load the sample file.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
public static void assertOutput(
|
public static void assertOutput(
|
||||||
ExtractorFactory factory, String dumpFilesPrefix, byte[] data, Context context)
|
ExtractorFactory factory, String dumpFilesPrefix, byte[] data, Context context)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
assertOutput(factory.create(), dumpFilesPrefix, data, context, true, false, false, false);
|
assertOutput(factory.create(), dumpFilesPrefix, data, context, true, false, false, false);
|
||||||
assertOutput(factory.create(), dumpFilesPrefix, data, context, true, false, false, true);
|
assertOutput(factory.create(), dumpFilesPrefix, data, context, true, false, false, true);
|
||||||
assertOutput(factory.create(), dumpFilesPrefix, data, context, true, false, true, false);
|
assertOutput(factory.create(), dumpFilesPrefix, data, context, true, false, true, false);
|
||||||
@ -184,7 +177,6 @@ public final class ExtractorAsserts {
|
|||||||
* @param simulatePartialReads Whether to simulate partial reads.
|
* @param simulatePartialReads Whether to simulate partial reads.
|
||||||
* @return The {@link FakeExtractorOutput} used in the test.
|
* @return The {@link FakeExtractorOutput} used in the test.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
public static FakeExtractorOutput assertOutput(
|
public static FakeExtractorOutput assertOutput(
|
||||||
Extractor extractor,
|
Extractor extractor,
|
||||||
@ -195,7 +187,7 @@ public final class ExtractorAsserts {
|
|||||||
boolean simulateIOErrors,
|
boolean simulateIOErrors,
|
||||||
boolean simulateUnknownLength,
|
boolean simulateUnknownLength,
|
||||||
boolean simulatePartialReads)
|
boolean simulatePartialReads)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data)
|
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data)
|
||||||
.setSimulateIOErrors(simulateIOErrors)
|
.setSimulateIOErrors(simulateIOErrors)
|
||||||
.setSimulateUnknownLength(simulateUnknownLength)
|
.setSimulateUnknownLength(simulateUnknownLength)
|
||||||
@ -254,7 +246,6 @@ public final class ExtractorAsserts {
|
|||||||
* @param context To be used to load the sample file.
|
* @param context To be used to load the sample file.
|
||||||
* @param expectedThrowable Expected {@link Throwable} class.
|
* @param expectedThrowable Expected {@link Throwable} class.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
* @see #assertThrows(Extractor, byte[], Class, boolean, boolean, boolean)
|
* @see #assertThrows(Extractor, byte[], Class, boolean, boolean, boolean)
|
||||||
*/
|
*/
|
||||||
public static void assertThrows(
|
public static void assertThrows(
|
||||||
@ -262,7 +253,7 @@ public final class ExtractorAsserts {
|
|||||||
String sampleFile,
|
String sampleFile,
|
||||||
Context context,
|
Context context,
|
||||||
Class<? extends Throwable> expectedThrowable)
|
Class<? extends Throwable> expectedThrowable)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
byte[] fileData = TestUtil.getByteArray(context, sampleFile);
|
byte[] fileData = TestUtil.getByteArray(context, sampleFile);
|
||||||
assertThrows(factory, fileData, expectedThrowable);
|
assertThrows(factory, fileData, expectedThrowable);
|
||||||
}
|
}
|
||||||
@ -276,12 +267,11 @@ public final class ExtractorAsserts {
|
|||||||
* @param fileData Content of the input file.
|
* @param fileData Content of the input file.
|
||||||
* @param expectedThrowable Expected {@link Throwable} class.
|
* @param expectedThrowable Expected {@link Throwable} class.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
* @see #assertThrows(Extractor, byte[], Class, boolean, boolean, boolean)
|
* @see #assertThrows(Extractor, byte[], Class, boolean, boolean, boolean)
|
||||||
*/
|
*/
|
||||||
private static void assertThrows(
|
private static void assertThrows(
|
||||||
ExtractorFactory factory, byte[] fileData, Class<? extends Throwable> expectedThrowable)
|
ExtractorFactory factory, byte[] fileData, Class<? extends Throwable> expectedThrowable)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
assertThrows(factory.create(), fileData, expectedThrowable, false, false, false);
|
assertThrows(factory.create(), fileData, expectedThrowable, false, false, false);
|
||||||
assertThrows(factory.create(), fileData, expectedThrowable, true, false, false);
|
assertThrows(factory.create(), fileData, expectedThrowable, true, false, false);
|
||||||
assertThrows(factory.create(), fileData, expectedThrowable, false, true, false);
|
assertThrows(factory.create(), fileData, expectedThrowable, false, true, false);
|
||||||
@ -302,7 +292,6 @@ public final class ExtractorAsserts {
|
|||||||
* @param simulateUnknownLength If true simulates unknown input length.
|
* @param simulateUnknownLength If true simulates unknown input length.
|
||||||
* @param simulatePartialReads If true simulates partial reads.
|
* @param simulatePartialReads If true simulates partial reads.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @throws InterruptedException If interrupted while reading from the input.
|
|
||||||
*/
|
*/
|
||||||
private static void assertThrows(
|
private static void assertThrows(
|
||||||
Extractor extractor,
|
Extractor extractor,
|
||||||
@ -311,7 +300,7 @@ public final class ExtractorAsserts {
|
|||||||
boolean simulateIOErrors,
|
boolean simulateIOErrors,
|
||||||
boolean simulateUnknownLength,
|
boolean simulateUnknownLength,
|
||||||
boolean simulatePartialReads)
|
boolean simulatePartialReads)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(fileData)
|
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(fileData)
|
||||||
.setSimulateIOErrors(simulateIOErrors)
|
.setSimulateIOErrors(simulateIOErrors)
|
||||||
.setSimulateUnknownLength(simulateUnknownLength)
|
.setSimulateUnknownLength(simulateUnknownLength)
|
||||||
@ -329,17 +318,22 @@ public final class ExtractorAsserts {
|
|||||||
|
|
||||||
private ExtractorAsserts() {}
|
private ExtractorAsserts() {}
|
||||||
|
|
||||||
private static FakeExtractorOutput consumeTestData(Extractor extractor, FakeExtractorInput input,
|
private static FakeExtractorOutput consumeTestData(
|
||||||
long timeUs, boolean retryFromStartIfLive) throws IOException, InterruptedException {
|
Extractor extractor, FakeExtractorInput input, long timeUs, boolean retryFromStartIfLive)
|
||||||
|
throws IOException {
|
||||||
FakeExtractorOutput output = new FakeExtractorOutput();
|
FakeExtractorOutput output = new FakeExtractorOutput();
|
||||||
extractor.init(output);
|
extractor.init(output);
|
||||||
consumeTestData(extractor, input, timeUs, output, retryFromStartIfLive);
|
consumeTestData(extractor, input, timeUs, output, retryFromStartIfLive);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void consumeTestData(Extractor extractor, FakeExtractorInput input, long timeUs,
|
private static void consumeTestData(
|
||||||
FakeExtractorOutput output, boolean retryFromStartIfLive)
|
Extractor extractor,
|
||||||
throws IOException, InterruptedException {
|
FakeExtractorInput input,
|
||||||
|
long timeUs,
|
||||||
|
FakeExtractorOutput output,
|
||||||
|
boolean retryFromStartIfLive)
|
||||||
|
throws IOException {
|
||||||
extractor.seek(input.getPosition(), timeUs);
|
extractor.seek(input.getPosition(), timeUs);
|
||||||
PositionHolder seekPositionHolder = new PositionHolder();
|
PositionHolder seekPositionHolder = new PositionHolder();
|
||||||
int readResult = Extractor.RESULT_CONTINUE;
|
int readResult = Extractor.RESULT_CONTINUE;
|
||||||
|
@ -67,8 +67,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int sampleData(DataReader input, int length, boolean allowEndOfInput)
|
public int sampleData(DataReader input, int length, boolean allowEndOfInput) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
byte[] newData = new byte[length];
|
byte[] newData = new byte[length];
|
||||||
int bytesAppended = input.read(newData, 0, length);
|
int bytesAppended = input.read(newData, 0, length);
|
||||||
if (bytesAppended == C.RESULT_END_OF_INPUT) {
|
if (bytesAppended == C.RESULT_END_OF_INPUT) {
|
||||||
|
@ -341,11 +341,10 @@ public class TestUtil {
|
|||||||
* @return The extracted {@link SeekMap}.
|
* @return The extracted {@link SeekMap}.
|
||||||
* @throws IOException If an error occurred reading from the input, or if the extractor finishes
|
* @throws IOException If an error occurred reading from the input, or if the extractor finishes
|
||||||
* reading from input without extracting any {@link SeekMap}.
|
* reading from input without extracting any {@link SeekMap}.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
public static SeekMap extractSeekMap(
|
public static SeekMap extractSeekMap(
|
||||||
Extractor extractor, FakeExtractorOutput output, DataSource dataSource, Uri uri)
|
Extractor extractor, FakeExtractorOutput output, DataSource dataSource, Uri uri)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
ExtractorInput input = getExtractorInputFromPosition(dataSource, /* position= */ 0, uri);
|
ExtractorInput input = getExtractorInputFromPosition(dataSource, /* position= */ 0, uri);
|
||||||
extractor.init(output);
|
extractor.init(output);
|
||||||
PositionHolder positionHolder = new PositionHolder();
|
PositionHolder positionHolder = new PositionHolder();
|
||||||
@ -382,11 +381,9 @@ public class TestUtil {
|
|||||||
* @return The {@link FakeTrackOutput} containing the extracted samples.
|
* @return The {@link FakeTrackOutput} containing the extracted samples.
|
||||||
* @throws IOException If an error occurred reading from the input, or if the extractor finishes
|
* @throws IOException If an error occurred reading from the input, or if the extractor finishes
|
||||||
* reading from input without extracting any {@link SeekMap}.
|
* reading from input without extracting any {@link SeekMap}.
|
||||||
* @throws InterruptedException If the thread was interrupted.
|
|
||||||
*/
|
*/
|
||||||
public static FakeExtractorOutput extractAllSamplesFromFile(
|
public static FakeExtractorOutput extractAllSamplesFromFile(
|
||||||
Extractor extractor, Context context, String fileName)
|
Extractor extractor, Context context, String fileName) throws IOException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
byte[] data = TestUtil.getByteArray(context, fileName);
|
byte[] data = TestUtil.getByteArray(context, fileName);
|
||||||
FakeExtractorOutput expectedOutput = new FakeExtractorOutput();
|
FakeExtractorOutput expectedOutput = new FakeExtractorOutput();
|
||||||
extractor.init(expectedOutput);
|
extractor.init(expectedOutput);
|
||||||
@ -428,7 +425,7 @@ public class TestUtil {
|
|||||||
DataSource dataSource,
|
DataSource dataSource,
|
||||||
FakeTrackOutput trackOutput,
|
FakeTrackOutput trackOutput,
|
||||||
Uri uri)
|
Uri uri)
|
||||||
throws IOException, InterruptedException {
|
throws IOException {
|
||||||
int numSampleBeforeSeek = trackOutput.getSampleCount();
|
int numSampleBeforeSeek = trackOutput.getSampleCount();
|
||||||
SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
|
SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user