diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java
index 58397b3e21..1e498cb677 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacFrameReader.java
@@ -22,7 +22,10 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
-/** Reads and peeks FLAC frame elements. */
+/**
+ * Reads and peeks FLAC frame elements according to the FLAC format specification.
+ */
public final class FlacFrameReader {
/** Holds a sample number. */
@@ -35,10 +38,10 @@ public final class FlacFrameReader {
* Checks whether the given FLAC frame header is valid and, if so, reads it and writes the frame
* first sample number in {@code sampleNumberHolder}.
*
- *
If the header is valid, the position of {@code scratch} is moved to the byte following it.
+ *
If the header is valid, the position of {@code data} is moved to the byte following it.
* Otherwise, there is no guarantee on the position.
*
- * @param scratch The array to read the data from, whose position must correspond to the frame
+ * @param data The array to read the data from, whose position must correspond to the frame
* header.
* @param flacStreamMetadata The stream metadata.
* @param frameStartMarker The frame start marker of the stream.
@@ -46,13 +49,13 @@ public final class FlacFrameReader {
* @return Whether the frame header is valid.
*/
public static boolean checkAndReadFrameHeader(
- ParsableByteArray scratch,
+ ParsableByteArray data,
FlacStreamMetadata flacStreamMetadata,
int frameStartMarker,
SampleNumberHolder sampleNumberHolder) {
- int frameStartPosition = scratch.getPosition();
+ int frameStartPosition = data.getPosition();
- long frameHeaderBytes = scratch.readUnsignedInt();
+ long frameHeaderBytes = data.readUnsignedInt();
if (frameHeaderBytes >>> 16 != frameStartMarker) {
return false;
}
@@ -67,10 +70,10 @@ public final class FlacFrameReader {
&& checkBitsPerSample(bitsPerSampleKey, flacStreamMetadata)
&& !reservedBit
&& checkAndReadFirstSampleNumber(
- scratch, flacStreamMetadata, isBlockSizeVariable, sampleNumberHolder)
- && checkAndReadBlockSizeSamples(scratch, flacStreamMetadata, blockSizeKey)
- && checkAndReadSampleRate(scratch, flacStreamMetadata, sampleRateKey)
- && checkAndReadCrc(scratch, frameStartPosition);
+ data, flacStreamMetadata, isBlockSizeVariable, sampleNumberHolder)
+ && checkAndReadBlockSizeSamples(data, flacStreamMetadata, blockSizeKey)
+ && checkAndReadSampleRate(data, flacStreamMetadata, sampleRateKey)
+ && checkAndReadCrc(data, frameStartPosition);
}
/**
@@ -161,12 +164,12 @@ public final class FlacFrameReader {
/**
* Reads the given block size.
*
- * @param scratch The array to read the data from, whose position must correspond to the block
- * size bits.
+ * @param data The array to read the data from, whose position must correspond to the block size
+ * bits.
* @param blockSizeKey The key in the block size lookup table.
* @return The block size in samples.
*/
- public static int readFrameBlockSizeSamplesFromKey(ParsableByteArray scratch, int blockSizeKey) {
+ public static int readFrameBlockSizeSamplesFromKey(ParsableByteArray data, int blockSizeKey) {
switch (blockSizeKey) {
case 1:
return 192;
@@ -176,9 +179,9 @@ public final class FlacFrameReader {
case 5:
return 576 << (blockSizeKey - 2);
case 6:
- return scratch.readUnsignedByte() + 1;
+ return data.readUnsignedByte() + 1;
case 7:
- return scratch.readUnsignedShort() + 1;
+ return data.readUnsignedShort() + 1;
case 8:
case 9:
case 10:
@@ -230,10 +233,10 @@ public final class FlacFrameReader {
* Checks whether the given sample number is valid and, if so, reads it and writes it in {@code
* sampleNumberHolder}.
*
- *
If the sample number is valid, the position of {@code scratch} is moved to the byte
- * following it. Otherwise, there is no guarantee on the position.
+ *
If the sample number is valid, the position of {@code data} is moved to the byte following
+ * it. Otherwise, there is no guarantee on the position.
*
- * @param scratch The array to read the data from, whose position must correspond to the sample
+ * @param data The array to read the data from, whose position must correspond to the sample
* number data.
* @param flacStreamMetadata The stream metadata.
* @param isBlockSizeVariable Whether the stream blocking strategy is variable block size or fixed
@@ -242,13 +245,13 @@ public final class FlacFrameReader {
* @return Whether the sample number is valid.
*/
private static boolean checkAndReadFirstSampleNumber(
- ParsableByteArray scratch,
+ ParsableByteArray data,
FlacStreamMetadata flacStreamMetadata,
boolean isBlockSizeVariable,
SampleNumberHolder sampleNumberHolder) {
long utf8Value;
try {
- utf8Value = scratch.readUtf8EncodedLong();
+ utf8Value = data.readUtf8EncodedLong();
} catch (NumberFormatException e) {
return false;
}
@@ -262,18 +265,18 @@ public final class FlacFrameReader {
* Checks whether the given frame block size key and block size bits are valid and, if so, reads
* the block size bits.
*
- *
If the block size is valid, the position of {@code scratch} is moved to the byte following
- * the block size bits. Otherwise, there is no guarantee on the position.
+ *
If the block size is valid, the position of {@code data} is moved to the byte following the
+ * block size bits. Otherwise, there is no guarantee on the position.
*
- * @param scratch The array to read the data from, whose position must correspond to the block
- * size bits.
+ * @param data The array to read the data from, whose position must correspond to the block size
+ * bits.
* @param flacStreamMetadata The stream metadata.
* @param blockSizeKey The key in the block size lookup table.
* @return Whether the block size is valid.
*/
private static boolean checkAndReadBlockSizeSamples(
- ParsableByteArray scratch, FlacStreamMetadata flacStreamMetadata, int blockSizeKey) {
- int blockSizeSamples = readFrameBlockSizeSamplesFromKey(scratch, blockSizeKey);
+ ParsableByteArray data, FlacStreamMetadata flacStreamMetadata, int blockSizeKey) {
+ int blockSizeSamples = readFrameBlockSizeSamplesFromKey(data, blockSizeKey);
return blockSizeSamples != -1 && blockSizeSamples <= flacStreamMetadata.maxBlockSizeSamples;
}
@@ -281,26 +284,25 @@ public final class FlacFrameReader {
* Checks whether the given sample rate key and sample rate bits are valid and, if so, reads the
* sample rate bits.
*
- *
If the sample rate is valid, the position of {@code scratch} is moved to the byte following
- * the sample rate bits. Otherwise, there is no guarantee on the position.
+ *
If the sample rate is valid, the position of {@code data} is moved to the byte following the
+ * sample rate bits. Otherwise, there is no guarantee on the position.
*
- * @param scratch The array to read the data from, whose position must indicate the sample rate
- * bits.
+ * @param data The array to read the data from, whose position must indicate the sample rate bits.
* @param flacStreamMetadata The stream metadata.
* @param sampleRateKey The key in the sample rate lookup table.
* @return Whether the sample rate is valid.
*/
private static boolean checkAndReadSampleRate(
- ParsableByteArray scratch, FlacStreamMetadata flacStreamMetadata, int sampleRateKey) {
+ ParsableByteArray data, FlacStreamMetadata flacStreamMetadata, int sampleRateKey) {
int expectedSampleRate = flacStreamMetadata.sampleRate;
if (sampleRateKey == 0) {
return true;
} else if (sampleRateKey <= 11) {
return sampleRateKey == flacStreamMetadata.sampleRateLookupKey;
} else if (sampleRateKey == 12) {
- return scratch.readUnsignedByte() * 1000 == expectedSampleRate;
+ return data.readUnsignedByte() * 1000 == expectedSampleRate;
} else if (sampleRateKey <= 14) {
- int sampleRate = scratch.readUnsignedShort();
+ int sampleRate = data.readUnsignedShort();
if (sampleRateKey == 14) {
sampleRate *= 10;
}
@@ -313,20 +315,20 @@ public final class FlacFrameReader {
/**
* Checks whether the given CRC is valid and, if so, reads it.
*
- *
If the CRC is valid, the position of {@code scratch} is moved to the byte following it.
+ *
If the CRC is valid, the position of {@code data} is moved to the byte following it.
* Otherwise, there is no guarantee on the position.
*
- *
The {@code scratch} array must contain the whole frame header.
+ *
The {@code data} array must contain the whole frame header.
*
- * @param scratch The array to read the data from, whose position must indicate the CRC.
- * @param frameStartPosition The frame start offset in {@code scratch}.
+ * @param data The array to read the data from, whose position must indicate the CRC.
+ * @param frameStartPosition The frame start offset in {@code data}.
* @return Whether the CRC is valid.
*/
- private static boolean checkAndReadCrc(ParsableByteArray scratch, int frameStartPosition) {
- int crc = scratch.readUnsignedByte();
- int frameEndPosition = scratch.getPosition();
+ private static boolean checkAndReadCrc(ParsableByteArray data, int frameStartPosition) {
+ int crc = data.readUnsignedByte();
+ int frameEndPosition = data.getPosition();
int expectedCrc =
- Util.crc8(scratch.data, frameStartPosition, frameEndPosition - 1, /* initialValue= */ 0);
+ Util.crc8(data.data, frameStartPosition, frameEndPosition - 1, /* initialValue= */ 0);
return crc == expectedCrc;
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java
index c3b0d75300..49d4558ddc 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacMetadataReader.java
@@ -32,7 +32,10 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-/** Reads and peeks FLAC stream metadata elements from an {@link ExtractorInput}. */
+/**
+ * Reads and peeks FLAC stream metadata elements according to the FLAC format specification.
+ */
public final class FlacMetadataReader {
/** Holds a {@link FlacStreamMetadata}. */
@@ -47,9 +50,7 @@ public final class FlacMetadataReader {
private static final int STREAM_MARKER = 0x664C6143; // ASCII for "fLaC"
private static final int SYNC_CODE = 0x3FFE;
- private static final int STREAM_INFO_TYPE = 0;
- private static final int VORBIS_COMMENT_TYPE = 4;
- private static final int PICTURE_TYPE = 6;
+ private static final int SEEK_POINT_SIZE = 18;
/**
* Peeks ID3 Data.
@@ -167,18 +168,21 @@ public final class FlacMetadataReader {
boolean isLastMetadataBlock = scratch.readBit();
int type = scratch.readBits(7);
int length = FlacConstants.METADATA_BLOCK_HEADER_SIZE + scratch.readBits(24);
- if (type == STREAM_INFO_TYPE) {
+ if (type == FlacConstants.METADATA_TYPE_STREAM_INFO) {
metadataHolder.flacStreamMetadata = readStreamInfoBlock(input);
} else {
FlacStreamMetadata flacStreamMetadata = metadataHolder.flacStreamMetadata;
if (flacStreamMetadata == null) {
throw new IllegalArgumentException();
}
- if (type == VORBIS_COMMENT_TYPE) {
+ if (type == FlacConstants.METADATA_TYPE_SEEK_TABLE) {
+ FlacStreamMetadata.SeekTable seekTable = readSeekTableMetadataBlock(input, length);
+ metadataHolder.flacStreamMetadata = flacStreamMetadata.copyWithSeekTable(seekTable);
+ } else if (type == FlacConstants.METADATA_TYPE_VORBIS_COMMENT) {
List vorbisComments = readVorbisCommentMetadataBlock(input, length);
metadataHolder.flacStreamMetadata =
flacStreamMetadata.copyWithVorbisComments(vorbisComments);
- } else if (type == PICTURE_TYPE) {
+ } else if (type == FlacConstants.METADATA_TYPE_PICTURE) {
PictureFrame pictureFrame = readPictureMetadataBlock(input, length);
metadataHolder.flacStreamMetadata =
flacStreamMetadata.copyWithPictureFrames(Collections.singletonList(pictureFrame));
@@ -190,6 +194,42 @@ public final class FlacMetadataReader {
return isLastMetadataBlock;
}
+ /**
+ * Reads a FLAC seek table metadata block.
+ *
+ * The position of {@code data} is moved to the byte following the seek table metadata block
+ * (placeholder points included).
+ *
+ * @param data The array to read the data from, whose position must correspond to the seek table
+ * metadata block (header included).
+ * @return The seek table, without the placeholder points.
+ */
+ public static FlacStreamMetadata.SeekTable readSeekTableMetadataBlock(ParsableByteArray data) {
+ data.skipBytes(1);
+ int length = data.readUnsignedInt24();
+
+ long seekTableEndPosition = data.getPosition() + length;
+ int seekPointCount = length / SEEK_POINT_SIZE;
+ long[] pointSampleNumbers = new long[seekPointCount];
+ long[] pointOffsets = new long[seekPointCount];
+ for (int i = 0; i < seekPointCount; i++) {
+ // The sample number is expected to fit in a signed long, except if it is a placeholder, in
+ // which case its value is -1.
+ long sampleNumber = data.readLong();
+ if (sampleNumber == -1) {
+ pointSampleNumbers = Arrays.copyOf(pointSampleNumbers, i);
+ pointOffsets = Arrays.copyOf(pointOffsets, i);
+ break;
+ }
+ pointSampleNumbers[i] = sampleNumber;
+ pointOffsets[i] = data.readLong();
+ data.skipBytes(2);
+ }
+
+ data.skipBytes((int) (seekTableEndPosition - data.getPosition()));
+ return new FlacStreamMetadata.SeekTable(pointSampleNumbers, pointOffsets);
+ }
+
/**
* Returns the frame start marker, consisting of the 2 first bytes of the first frame.
*
@@ -227,6 +267,13 @@ public final class FlacMetadataReader {
scratchData, /* offset= */ FlacConstants.METADATA_BLOCK_HEADER_SIZE);
}
+ private static FlacStreamMetadata.SeekTable readSeekTableMetadataBlock(
+ ExtractorInput input, int length) throws IOException, InterruptedException {
+ ParsableByteArray scratch = new ParsableByteArray(length);
+ input.readFully(scratch.data, 0, length);
+ return readSeekTableMetadataBlock(scratch);
+ }
+
private static List readVorbisCommentMetadataBlock(ExtractorInput input, int length)
throws IOException, InterruptedException {
ParsableByteArray scratch = new ParsableByteArray(length);
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacSeekTableSeekMap.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacSeekTableSeekMap.java
new file mode 100644
index 0000000000..a711f09e2f
--- /dev/null
+++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/FlacSeekTableSeekMap.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.exoplayer2.extractor;
+
+import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.util.Assertions;
+import com.google.android.exoplayer2.util.FlacStreamMetadata;
+import com.google.android.exoplayer2.util.Util;
+
+/**
+ * A {@link SeekMap} implementation for FLAC streams that contain a seek table.
+ */
+public final class FlacSeekTableSeekMap implements SeekMap {
+
+ private final FlacStreamMetadata flacStreamMetadata;
+ private final long firstFrameOffset;
+
+ /**
+ * Creates a seek map from the FLAC stream seek table.
+ *
+ * @param flacStreamMetadata The stream metadata.
+ * @param firstFrameOffset The byte offset of the first frame in the stream.
+ */
+ public FlacSeekTableSeekMap(FlacStreamMetadata flacStreamMetadata, long firstFrameOffset) {
+ this.flacStreamMetadata = flacStreamMetadata;
+ this.firstFrameOffset = firstFrameOffset;
+ }
+
+ @Override
+ public boolean isSeekable() {
+ return true;
+ }
+
+ @Override
+ public long getDurationUs() {
+ return flacStreamMetadata.getDurationUs();
+ }
+
+ @Override
+ public SeekPoints getSeekPoints(long timeUs) {
+ Assertions.checkNotNull(flacStreamMetadata.seekTable);
+ long[] pointSampleNumbers = flacStreamMetadata.seekTable.pointSampleNumbers;
+ long[] pointOffsets = flacStreamMetadata.seekTable.pointOffsets;
+
+ long targetSampleNumber = flacStreamMetadata.getSampleNumber(timeUs);
+ int index =
+ Util.binarySearchFloor(
+ pointSampleNumbers,
+ targetSampleNumber,
+ /* inclusive= */ true,
+ /* stayInBounds= */ false);
+
+ long seekPointSampleNumber = index == -1 ? 0 : pointSampleNumbers[index];
+ long seekPointOffsetFromFirstFrame = index == -1 ? 0 : pointOffsets[index];
+ SeekPoint seekPoint = getSeekPoint(seekPointSampleNumber, seekPointOffsetFromFirstFrame);
+ if (seekPoint.timeUs == timeUs || index == pointSampleNumbers.length - 1) {
+ return new SeekPoints(seekPoint);
+ } else {
+ SeekPoint secondSeekPoint =
+ getSeekPoint(pointSampleNumbers[index + 1], pointOffsets[index + 1]);
+ return new SeekPoints(seekPoint, secondSeekPoint);
+ }
+ }
+
+ private SeekPoint getSeekPoint(long sampleNumber, long offsetFromFirstFrame) {
+ long seekTimeUs = sampleNumber * C.MICROS_PER_SECOND / flacStreamMetadata.sampleRate;
+ long seekPosition = firstFrameOffset + offsetFromFirstFrame;
+ return new SeekPoint(seekTimeUs, seekPosition);
+ }
+}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java
index 078fdddbd1..831a900b94 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/FlacExtractor.java
@@ -27,6 +27,7 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.extractor.FlacFrameReader;
import com.google.android.exoplayer2.extractor.FlacFrameReader.SampleNumberHolder;
import com.google.android.exoplayer2.extractor.FlacMetadataReader;
+import com.google.android.exoplayer2.extractor.FlacSeekTableSeekMap;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput;
@@ -41,7 +42,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
-// TODO: implement seeking using the optional seek table.
/**
* Extracts data from FLAC container format.
*
@@ -175,11 +175,10 @@ public final class FlacExtractor implements Extractor {
public void seek(long position, long timeUs) {
if (position == 0) {
state = STATE_READ_ID3_METADATA;
- currentFrameFirstSampleNumber = 0;
} else if (binarySearchSeeker != null) {
- currentFrameFirstSampleNumber = SAMPLE_NUMBER_UNKNOWN;
binarySearchSeeker.setSeekTargetUs(timeUs);
}
+ currentFrameFirstSampleNumber = timeUs == 0 ? 0 : SAMPLE_NUMBER_UNKNOWN;
currentFrameBytesWritten = 0;
scratch.reset();
}
@@ -231,7 +230,7 @@ public final class FlacExtractor implements Extractor {
castNonNull(extractorOutput)
.seekMap(
getSeekMap(
- /* firstFramePosition= */ (int) input.getPosition(),
+ /* firstFramePosition= */ input.getPosition(),
/* streamLength= */ input.getLength()));
state = STATE_READ_FRAMES;
@@ -242,7 +241,7 @@ public final class FlacExtractor implements Extractor {
Assertions.checkNotNull(trackOutput);
Assertions.checkNotNull(flacStreamMetadata);
- // Handle pending seek if necessary.
+ // Handle pending binary search seek if necessary.
if (binarySearchSeeker != null && binarySearchSeeker.isSeeking()) {
return binarySearchSeeker.handlePendingSeek(input, seekPosition);
}
@@ -299,39 +298,42 @@ public final class FlacExtractor implements Extractor {
return Extractor.RESULT_CONTINUE;
}
- private SeekMap getSeekMap(int firstFramePosition, long streamLength) {
+ private SeekMap getSeekMap(long firstFramePosition, long streamLength) {
Assertions.checkNotNull(flacStreamMetadata);
- if (streamLength == C.LENGTH_UNSET || flacStreamMetadata.totalSamples == 0) {
+ if (flacStreamMetadata.seekTable != null) {
+ return new FlacSeekTableSeekMap(flacStreamMetadata, firstFramePosition);
+ } else if (streamLength != C.LENGTH_UNSET && flacStreamMetadata.totalSamples > 0) {
+ binarySearchSeeker =
+ new FlacBinarySearchSeeker(
+ flacStreamMetadata, frameStartMarker, firstFramePosition, streamLength);
+ return binarySearchSeeker.getSeekMap();
+ } else {
return new SeekMap.Unseekable(flacStreamMetadata.getDurationUs());
}
- binarySearchSeeker =
- new FlacBinarySearchSeeker(
- flacStreamMetadata, frameStartMarker, firstFramePosition, streamLength);
- return binarySearchSeeker.getSeekMap();
}
/**
- * Searches for the start of a frame in {@code scratch}.
+ * Searches for the start of a frame in {@code data}.
*
*
* - If the search is successful, the position is set to the start of the found frame.
*
- Otherwise, the position is set to the first unsearched byte.
*
*
- * @param scratch The array to be searched.
- * @param foundEndOfInput If the end of input was met when filling in the {@code scratch}.
+ * @param data The array to be searched.
+ * @param foundEndOfInput If the end of input was met when filling in the {@code data}.
* @return The number of the first sample in the frame found, or {@code SAMPLE_NUMBER_UNKNOWN} if
* the search was not successful.
*/
- private long findFrame(ParsableByteArray scratch, boolean foundEndOfInput) {
+ private long findFrame(ParsableByteArray data, boolean foundEndOfInput) {
Assertions.checkNotNull(flacStreamMetadata);
- int frameOffset = scratch.getPosition();
- while (frameOffset <= scratch.limit() - FlacConstants.MAX_FRAME_HEADER_SIZE) {
- scratch.setPosition(frameOffset);
+ int frameOffset = data.getPosition();
+ while (frameOffset <= data.limit() - FlacConstants.MAX_FRAME_HEADER_SIZE) {
+ data.setPosition(frameOffset);
if (FlacFrameReader.checkAndReadFrameHeader(
- scratch, flacStreamMetadata, frameStartMarker, sampleNumberHolder)) {
- scratch.setPosition(frameOffset);
+ data, flacStreamMetadata, frameStartMarker, sampleNumberHolder)) {
+ data.setPosition(frameOffset);
return sampleNumberHolder.sampleNumber;
}
frameOffset++;
@@ -339,9 +341,9 @@ public final class FlacExtractor implements Extractor {
if (foundEndOfInput) {
// Reached the end of the file. Assume it's the end of the frame.
- scratch.setPosition(scratch.limit());
+ data.setPosition(data.limit());
} else {
- scratch.setPosition(frameOffset);
+ data.setPosition(frameOffset);
}
return SAMPLE_NUMBER_UNKNOWN;
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java
index 9889c7f220..f99b2420cc 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java
@@ -17,8 +17,11 @@ package com.google.android.exoplayer2.extractor.ogg;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.FlacFrameReader;
+import com.google.android.exoplayer2.extractor.FlacMetadataReader;
+import com.google.android.exoplayer2.extractor.FlacSeekTableSeekMap;
import com.google.android.exoplayer2.extractor.SeekMap;
-import com.google.android.exoplayer2.extractor.SeekPoint;
+import com.google.android.exoplayer2.util.Assertions;
+import com.google.android.exoplayer2.util.FlacConstants;
import com.google.android.exoplayer2.util.FlacStreamMetadata;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;
@@ -31,7 +34,6 @@ import java.util.Arrays;
/* package */ final class FlacReader extends StreamReader {
private static final byte AUDIO_PACKET_TYPE = (byte) 0xFF;
- private static final byte SEEKTABLE_PACKET_TYPE = 0x03;
private static final int FRAME_HEADER_SAMPLE_NUMBER_OFFSET = 4;
@@ -71,9 +73,11 @@ import java.util.Arrays;
streamMetadata = new FlacStreamMetadata(data, 17);
byte[] metadata = Arrays.copyOfRange(data, 9, packet.limit());
setupData.format = streamMetadata.getFormat(metadata, /* id3Metadata= */ null);
- } else if ((data[0] & 0x7F) == SEEKTABLE_PACKET_TYPE) {
+ } else if ((data[0] & 0x7F) == FlacConstants.METADATA_TYPE_SEEK_TABLE) {
flacOggSeeker = new FlacOggSeeker();
- flacOggSeeker.parseSeekTable(packet);
+ FlacStreamMetadata.SeekTable seekTable =
+ FlacMetadataReader.readSeekTableMetadataBlock(packet);
+ streamMetadata = streamMetadata.copyWithSeekTable(seekTable);
} else if (isAudioPacket(data)) {
if (flacOggSeeker != null) {
flacOggSeeker.setFirstFrameOffset(position);
@@ -96,13 +100,8 @@ import java.util.Arrays;
return result;
}
- private class FlacOggSeeker implements OggSeeker, SeekMap {
+ private class FlacOggSeeker implements OggSeeker {
- private static final int METADATA_LENGTH_OFFSET = 1;
- private static final int SEEK_POINT_SIZE = 18;
-
- private long[] seekPointGranules;
- private long[] seekPointOffsets;
private long firstFrameOffset;
private long pendingSeekGranule;
@@ -115,27 +114,6 @@ import java.util.Arrays;
this.firstFrameOffset = firstFrameOffset;
}
- /**
- * Parses a FLAC file seek table metadata structure and initializes internal fields.
- *
- * @param data A {@link ParsableByteArray} including whole seek table metadata block. Its
- * position should be set to the beginning of the block.
- * @see FLAC format
- * METADATA_BLOCK_SEEKTABLE
- */
- public void parseSeekTable(ParsableByteArray data) {
- data.skipBytes(METADATA_LENGTH_OFFSET);
- int length = data.readUnsignedInt24();
- int numberOfSeekPoints = length / SEEK_POINT_SIZE;
- seekPointGranules = new long[numberOfSeekPoints];
- seekPointOffsets = new long[numberOfSeekPoints];
- for (int i = 0; i < numberOfSeekPoints; i++) {
- seekPointGranules[i] = data.readLong();
- seekPointOffsets[i] = data.readLong();
- data.skipBytes(2); // Skip "Number of samples in the target frame."
- }
- }
-
@Override
public long read(ExtractorInput input) throws IOException, InterruptedException {
if (pendingSeekGranule >= 0) {
@@ -148,40 +126,16 @@ import java.util.Arrays;
@Override
public void startSeek(long targetGranule) {
+ Assertions.checkNotNull(streamMetadata.seekTable);
+ long[] seekPointGranules = streamMetadata.seekTable.pointSampleNumbers;
int index = Util.binarySearchFloor(seekPointGranules, targetGranule, true, true);
pendingSeekGranule = seekPointGranules[index];
}
@Override
public SeekMap createSeekMap() {
- return this;
- }
-
- @Override
- public boolean isSeekable() {
- return true;
- }
-
- @Override
- public SeekPoints getSeekPoints(long timeUs) {
- long granule = convertTimeToGranule(timeUs);
- int index = Util.binarySearchFloor(seekPointGranules, granule, true, true);
- long seekTimeUs = convertGranuleToTime(seekPointGranules[index]);
- long seekPosition = firstFrameOffset + seekPointOffsets[index];
- SeekPoint seekPoint = new SeekPoint(seekTimeUs, seekPosition);
- if (seekTimeUs >= timeUs || index == seekPointGranules.length - 1) {
- return new SeekPoints(seekPoint);
- } else {
- long secondSeekTimeUs = convertGranuleToTime(seekPointGranules[index + 1]);
- long secondSeekPosition = firstFrameOffset + seekPointOffsets[index + 1];
- SeekPoint secondSeekPoint = new SeekPoint(secondSeekTimeUs, secondSeekPosition);
- return new SeekPoints(seekPoint, secondSeekPoint);
- }
- }
-
- @Override
- public long getDurationUs() {
- return streamMetadata.getDurationUs();
+ Assertions.checkState(firstFrameOffset != -1);
+ return new FlacSeekTableSeekMap(streamMetadata, firstFrameOffset);
}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/FlacConstants.java b/library/core/src/main/java/com/google/android/exoplayer2/util/FlacConstants.java
index 75b153d6f9..0d36d78ff9 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/util/FlacConstants.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/util/FlacConstants.java
@@ -29,5 +29,14 @@ public final class FlacConstants {
/** Maximum size of a FLAC frame header in bytes. */
public static final int MAX_FRAME_HEADER_SIZE = 16;
+ /** Stream info metadata block type. */
+ public static final int METADATA_TYPE_STREAM_INFO = 0;
+ /** Seek table metadata block type. */
+ public static final int METADATA_TYPE_SEEK_TABLE = 3;
+ /** Vorbis comment metadata block type. */
+ public static final int METADATA_TYPE_VORBIS_COMMENT = 4;
+ /** Picture metadata block type. */
+ public static final int METADATA_TYPE_PICTURE = 6;
+
private FlacConstants() {}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java b/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java
index a0b26f8e56..deced8ebe6 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java
@@ -30,6 +30,8 @@ import java.util.List;
*
* @see FLAC format
* METADATA_BLOCK_STREAMINFO
+ * @see FLAC format
+ * METADATA_BLOCK_SEEKTABLE
* @see FLAC format
* METADATA_BLOCK_VORBIS_COMMENT
* @see FLAC format
@@ -37,6 +39,19 @@ import java.util.List;
*/
public final class FlacStreamMetadata {
+ /** A FLAC seek table. */
+ public static class SeekTable {
+ /** Seek points sample numbers. */
+ public final long[] pointSampleNumbers;
+ /** Seek points byte offsets from the first frame. */
+ public final long[] pointOffsets;
+
+ public SeekTable(long[] pointSampleNumbers, long[] pointOffsets) {
+ this.pointSampleNumbers = pointSampleNumbers;
+ this.pointOffsets = pointOffsets;
+ }
+ }
+
private static final String TAG = "FlacStreamMetadata";
/** Indicates that a value is not in the corresponding lookup table. */
@@ -79,7 +94,8 @@ public final class FlacStreamMetadata {
public final int bitsPerSampleLookupKey;
/** Total number of samples, or 0 if the value is unknown. */
public final long totalSamples;
-
+ /** Seek table, or {@code null} if it is not provided. */
+ @Nullable public final SeekTable seekTable;
/** Content metadata, or {@code null} if it is not provided. */
@Nullable private final Metadata metadata;
@@ -102,6 +118,7 @@ public final class FlacStreamMetadata {
bitsPerSample = scratch.readBits(5) + 1;
bitsPerSampleLookupKey = getBitsPerSampleLookupKey(bitsPerSample);
totalSamples = scratch.readBitsToLong(36);
+ seekTable = null;
metadata = null;
}
@@ -126,6 +143,7 @@ public final class FlacStreamMetadata {
channels,
bitsPerSample,
totalSamples,
+ /* seekTable= */ null,
buildMetadata(vorbisComments, pictureFrames));
}
@@ -138,6 +156,7 @@ public final class FlacStreamMetadata {
int channels,
int bitsPerSample,
long totalSamples,
+ @Nullable SeekTable seekTable,
@Nullable Metadata metadata) {
this.minBlockSizeSamples = minBlockSizeSamples;
this.maxBlockSizeSamples = maxBlockSizeSamples;
@@ -149,6 +168,7 @@ public final class FlacStreamMetadata {
this.bitsPerSample = bitsPerSample;
this.bitsPerSampleLookupKey = getBitsPerSampleLookupKey(bitsPerSample);
this.totalSamples = totalSamples;
+ this.seekTable = seekTable;
this.metadata = metadata;
}
@@ -239,6 +259,21 @@ public final class FlacStreamMetadata {
return metadata == null ? other : metadata.copyWithAppendedEntriesFrom(other);
}
+ /** Returns a copy of {@code this} with the seek table replaced by the one given. */
+ public FlacStreamMetadata copyWithSeekTable(@Nullable SeekTable seekTable) {
+ return new FlacStreamMetadata(
+ minBlockSizeSamples,
+ maxBlockSizeSamples,
+ minFrameSize,
+ maxFrameSize,
+ sampleRate,
+ channels,
+ bitsPerSample,
+ totalSamples,
+ seekTable,
+ metadata);
+ }
+
/** Returns a copy of {@code this} with the given Vorbis comments added to the metadata. */
public FlacStreamMetadata copyWithVorbisComments(List vorbisComments) {
@Nullable
@@ -254,6 +289,7 @@ public final class FlacStreamMetadata {
channels,
bitsPerSample,
totalSamples,
+ seekTable,
appendedMetadata);
}
@@ -272,6 +308,7 @@ public final class FlacStreamMetadata {
channels,
bitsPerSample,
totalSamples,
+ seekTable,
appendedMetadata);
}
diff --git a/library/core/src/test/assets/flac/bear.flac.3.dump b/library/core/src/test/assets/flac/bear.flac.3.dump
index cf1f7e9946..7553b6bdcb 100644
--- a/library/core/src/test/assets/flac/bear.flac.3.dump
+++ b/library/core/src/test/assets/flac/bear.flac.3.dump
@@ -27,9 +27,13 @@ track 0:
metadata = null
initializationData:
data = length 42, hash 83F6895
- total output bytes = 445
- sample count = 1
+ total output bytes = 3829
+ sample count = 2
sample 0:
+ time = 2645333
+ flags = 1
+ data = length 3384, hash 938BCDD9
+ sample 1:
time = 2730666
flags = 1
data = length 445, hash A388E3D6
diff --git a/library/core/src/test/assets/flac/bear_no_min_max_frame_size.flac.3.dump b/library/core/src/test/assets/flac/bear_no_min_max_frame_size.flac.3.dump
index 1704e4df0c..b27b4b7295 100644
--- a/library/core/src/test/assets/flac/bear_no_min_max_frame_size.flac.3.dump
+++ b/library/core/src/test/assets/flac/bear_no_min_max_frame_size.flac.3.dump
@@ -27,9 +27,13 @@ track 0:
metadata = null
initializationData:
data = length 42, hash 9218FDB7
- total output bytes = 445
- sample count = 1
+ total output bytes = 3829
+ sample count = 2
sample 0:
+ time = 2645333
+ flags = 1
+ data = length 3384, hash 938BCDD9
+ sample 1:
time = 2730666
flags = 1
data = length 445, hash A388E3D6
diff --git a/library/core/src/test/assets/flac/bear_no_min_max_frame_size.flac.unklen.dump b/library/core/src/test/assets/flac/bear_no_min_max_frame_size.flac.unklen.dump
deleted file mode 100644
index 4ef7138487..0000000000
--- a/library/core/src/test/assets/flac/bear_no_min_max_frame_size.flac.unklen.dump
+++ /dev/null
@@ -1,164 +0,0 @@
-seekMap:
- isSeekable = false
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=0]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = -1
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- metadata = null
- initializationData:
- data = length 42, hash 9218FDB7
- total output bytes = 164431
- sample count = 33
- sample 0:
- time = 0
- flags = 1
- data = length 5030, hash D2B60530
- sample 1:
- time = 85333
- flags = 1
- data = length 5066, hash 4C932A54
- sample 2:
- time = 170666
- flags = 1
- data = length 5112, hash 7E5A7B61
- sample 3:
- time = 256000
- flags = 1
- data = length 5044, hash 7EF93F13
- sample 4:
- time = 341333
- flags = 1
- data = length 4943, hash DE7E27F8
- sample 5:
- time = 426666
- flags = 1
- data = length 5121, hash 6D0D0B40
- sample 6:
- time = 512000
- flags = 1
- data = length 5068, hash 9924644F
- sample 7:
- time = 597333
- flags = 1
- data = length 5143, hash 6C34F0CE
- sample 8:
- time = 682666
- flags = 1
- data = length 5109, hash E3B7BEFB
- sample 9:
- time = 768000
- flags = 1
- data = length 5129, hash 44111D9B
- sample 10:
- time = 853333
- flags = 1
- data = length 5031, hash 9D55EA53
- sample 11:
- time = 938666
- flags = 1
- data = length 5119, hash E1CB9BA6
- sample 12:
- time = 1024000
- flags = 1
- data = length 5360, hash 17265C5D
- sample 13:
- time = 1109333
- flags = 1
- data = length 5340, hash A90FDDF1
- sample 14:
- time = 1194666
- flags = 1
- data = length 5162, hash 31F65AD5
- sample 15:
- time = 1280000
- flags = 1
- data = length 5168, hash F2394F2D
- sample 16:
- time = 1365333
- flags = 1
- data = length 5776, hash 58437AB3
- sample 17:
- time = 1450666
- flags = 1
- data = length 5394, hash EBAB20A8
- sample 18:
- time = 1536000
- flags = 1
- data = length 5168, hash BF37C7A5
- sample 19:
- time = 1621333
- flags = 1
- data = length 5324, hash 59546B7B
- sample 20:
- time = 1706666
- flags = 1
- data = length 5172, hash 6036EF0B
- sample 21:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 22:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 23:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 24:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 25:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 26:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 27:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 28:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 29:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 30:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 31:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 32:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_no_num_samples.flac.0.dump b/library/core/src/test/assets/flac/bear_no_num_samples.flac.0.dump
index 45b75392b3..0a1736f3e2 100644
--- a/library/core/src/test/assets/flac/bear_no_num_samples.flac.0.dump
+++ b/library/core/src/test/assets/flac/bear_no_num_samples.flac.0.dump
@@ -1,7 +1,7 @@
seekMap:
- isSeekable = false
+ isSeekable = true
duration = UNSET TIME
- getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(0) = [[timeUs=0, position=8880]]
numberOfTracks = 1
track 0:
format:
diff --git a/library/core/src/test/assets/flac/bear_no_seek_table_no_num_samples.flac b/library/core/src/test/assets/flac/bear_no_seek_table_no_num_samples.flac
new file mode 100644
index 0000000000..0f1dff1e84
Binary files /dev/null and b/library/core/src/test/assets/flac/bear_no_seek_table_no_num_samples.flac differ
diff --git a/library/core/src/test/assets/flac/bear.flac.unklen.dump b/library/core/src/test/assets/flac/bear_no_seek_table_no_num_samples.flac.0.dump
similarity index 98%
rename from library/core/src/test/assets/flac/bear.flac.unklen.dump
rename to library/core/src/test/assets/flac/bear_no_seek_table_no_num_samples.flac.0.dump
index bd8f1827e4..45b75392b3 100644
--- a/library/core/src/test/assets/flac/bear.flac.unklen.dump
+++ b/library/core/src/test/assets/flac/bear_no_seek_table_no_num_samples.flac.0.dump
@@ -1,6 +1,6 @@
seekMap:
isSeekable = false
- duration = 2741000
+ duration = UNSET TIME
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 1
track 0:
@@ -26,7 +26,7 @@ track 0:
drmInitData = -
metadata = null
initializationData:
- data = length 42, hash 83F6895
+ data = length 42, hash 49FA2C21
total output bytes = 164431
sample count = 33
sample 0:
diff --git a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac
index 2fc58661eb..e2e0b6a83d 100644
Binary files a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac and b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac differ
diff --git a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.0.dump b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.0.dump
index 4aab67d304..932cb8dc69 100644
--- a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.0.dump
+++ b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.0.dump
@@ -1,7 +1,7 @@
seekMap:
isSeekable = true
duration = 2741000
- getPosition(0) = [[timeUs=0, position=8288]]
+ getPosition(0) = [[timeUs=0, position=8230]]
numberOfTracks = 1
track 0:
format:
diff --git a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.1.dump b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.1.dump
index 95321cb88b..7b5cc6c31e 100644
--- a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.1.dump
+++ b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.1.dump
@@ -1,7 +1,7 @@
seekMap:
isSeekable = true
duration = 2741000
- getPosition(0) = [[timeUs=0, position=8288]]
+ getPosition(0) = [[timeUs=0, position=8230]]
numberOfTracks = 1
track 0:
format:
diff --git a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.2.dump b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.2.dump
index eae20735e3..4e2d478a57 100644
--- a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.2.dump
+++ b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.2.dump
@@ -1,7 +1,7 @@
seekMap:
isSeekable = true
duration = 2741000
- getPosition(0) = [[timeUs=0, position=8288]]
+ getPosition(0) = [[timeUs=0, position=8230]]
numberOfTracks = 1
track 0:
format:
diff --git a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.3.dump b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.3.dump
index 2f3a34e246..3870f8d88e 100644
--- a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.3.dump
+++ b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.3.dump
@@ -1,7 +1,7 @@
seekMap:
isSeekable = true
duration = 2741000
- getPosition(0) = [[timeUs=0, position=8288]]
+ getPosition(0) = [[timeUs=0, position=8230]]
numberOfTracks = 1
track 0:
format:
@@ -27,9 +27,13 @@ track 0:
metadata = null
initializationData:
data = length 42, hash 7249A1B8
- total output bytes = 548
- sample count = 1
+ total output bytes = 3385
+ sample count = 2
sample 0:
+ time = 2618181
+ flags = 1
+ data = length 2837, hash 10F1716E
+ sample 1:
time = 2722909
flags = 1
data = length 548, hash B46F603C
diff --git a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.unklen.dump b/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.unklen.dump
deleted file mode 100644
index e6caad8e84..0000000000
--- a/library/core/src/test/assets/flac/bear_uncommon_sample_rate.flac.unklen.dump
+++ /dev/null
@@ -1,140 +0,0 @@
-seekMap:
- isSeekable = false
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=0]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1408000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 6456
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 44000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- metadata = null
- initializationData:
- data = length 42, hash 7249A1B8
- total output bytes = 144086
- sample count = 27
- sample 0:
- time = 0
- flags = 1
- data = length 5415, hash 915DBC66
- sample 1:
- time = 104727
- flags = 1
- data = length 5529, hash EFD564F7
- sample 2:
- time = 209454
- flags = 1
- data = length 5480, hash ADA922FB
- sample 3:
- time = 314181
- flags = 1
- data = length 5290, hash 7BCEA5FC
- sample 4:
- time = 418909
- flags = 1
- data = length 5579, hash DBB36F37
- sample 5:
- time = 523636
- flags = 1
- data = length 5423, hash AB53F799
- sample 6:
- time = 628363
- flags = 1
- data = length 5583, hash 7243C284
- sample 7:
- time = 733090
- flags = 1
- data = length 5547, hash 9DA9C99E
- sample 8:
- time = 837818
- flags = 1
- data = length 5414, hash 90768345
- sample 9:
- time = 942545
- flags = 1
- data = length 5531, hash 1CD2FF67
- sample 10:
- time = 1047272
- flags = 1
- data = length 5870, hash A9A5CAEE
- sample 11:
- time = 1152000
- flags = 1
- data = length 5667, hash 875566A1
- sample 12:
- time = 1256727
- flags = 1
- data = length 5614, hash 5573694C
- sample 13:
- time = 1361454
- flags = 1
- data = length 6456, hash 921F3DE7
- sample 14:
- time = 1466181
- flags = 1
- data = length 5817, hash EBECBD16
- sample 15:
- time = 1570909
- flags = 1
- data = length 5751, hash 4A7D4C6B
- sample 16:
- time = 1675636
- flags = 1
- data = length 5620, hash B78F8E8D
- sample 17:
- time = 1780363
- flags = 1
- data = length 5535, hash 8187C107
- sample 18:
- time = 1885090
- flags = 1
- data = length 5517, hash 79FF36CB
- sample 19:
- time = 1989818
- flags = 1
- data = length 5716, hash 349FC281
- sample 20:
- time = 2094545
- flags = 1
- data = length 5556, hash BE97B2CA
- sample 21:
- time = 2199272
- flags = 1
- data = length 5703, hash 531F9FE3
- sample 22:
- time = 2304000
- flags = 1
- data = length 5652, hash 1277485D
- sample 23:
- time = 2408727
- flags = 1
- data = length 5607, hash 14862CB6
- sample 24:
- time = 2513454
- flags = 1
- data = length 5829, hash FCAF2F1C
- sample 25:
- time = 2618181
- flags = 1
- data = length 2837, hash 10F1716E
- sample 26:
- time = 2722909
- flags = 1
- data = length 548, hash B46F603C
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_id3.flac.1.dump b/library/core/src/test/assets/flac/bear_with_id3.flac.1.dump
deleted file mode 100644
index e30ade2d9c..0000000000
--- a/library/core/src/test/assets/flac/bear_with_id3.flac.1.dump
+++ /dev/null
@@ -1,123 +0,0 @@
-seekMap:
- isSeekable = true
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=55284]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 113666
- sample count = 23
- sample 0:
- time = 853333
- flags = 1
- data = length 5031, hash 9D55EA53
- sample 1:
- time = 938666
- flags = 1
- data = length 5119, hash E1CB9BA6
- sample 2:
- time = 1024000
- flags = 1
- data = length 5360, hash 17265C5D
- sample 3:
- time = 1109333
- flags = 1
- data = length 5340, hash A90FDDF1
- sample 4:
- time = 1194666
- flags = 1
- data = length 5162, hash 31F65AD5
- sample 5:
- time = 1280000
- flags = 1
- data = length 5168, hash F2394F2D
- sample 6:
- time = 1365333
- flags = 1
- data = length 5776, hash 58437AB3
- sample 7:
- time = 1450666
- flags = 1
- data = length 5394, hash EBAB20A8
- sample 8:
- time = 1536000
- flags = 1
- data = length 5168, hash BF37C7A5
- sample 9:
- time = 1621333
- flags = 1
- data = length 5324, hash 59546B7B
- sample 10:
- time = 1706666
- flags = 1
- data = length 5172, hash 6036EF0B
- sample 11:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 12:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 13:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 14:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 15:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 16:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 17:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 18:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 19:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 20:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 21:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 22:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_id3.flac.2.dump b/library/core/src/test/assets/flac/bear_with_id3.flac.2.dump
deleted file mode 100644
index bd3280baa5..0000000000
--- a/library/core/src/test/assets/flac/bear_with_id3.flac.2.dump
+++ /dev/null
@@ -1,79 +0,0 @@
-seekMap:
- isSeekable = true
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=55284]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 55652
- sample count = 12
- sample 0:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 1:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 2:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 3:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 4:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 5:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 6:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 7:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 8:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 9:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 10:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 11:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_id3.flac.3.dump b/library/core/src/test/assets/flac/bear_with_id3.flac.3.dump
deleted file mode 100644
index ceabd2f50e..0000000000
--- a/library/core/src/test/assets/flac/bear_with_id3.flac.3.dump
+++ /dev/null
@@ -1,35 +0,0 @@
-seekMap:
- isSeekable = true
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=55284]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 445
- sample count = 1
- sample 0:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_id3.flac.unklen.dump b/library/core/src/test/assets/flac/bear_with_id3.flac.unklen.dump
deleted file mode 100644
index e35dcc2081..0000000000
--- a/library/core/src/test/assets/flac/bear_with_id3.flac.unklen.dump
+++ /dev/null
@@ -1,163 +0,0 @@
-seekMap:
- isSeekable = false
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=0]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 164431
- sample count = 33
- sample 0:
- time = 0
- flags = 1
- data = length 5030, hash D2B60530
- sample 1:
- time = 85333
- flags = 1
- data = length 5066, hash 4C932A54
- sample 2:
- time = 170666
- flags = 1
- data = length 5112, hash 7E5A7B61
- sample 3:
- time = 256000
- flags = 1
- data = length 5044, hash 7EF93F13
- sample 4:
- time = 341333
- flags = 1
- data = length 4943, hash DE7E27F8
- sample 5:
- time = 426666
- flags = 1
- data = length 5121, hash 6D0D0B40
- sample 6:
- time = 512000
- flags = 1
- data = length 5068, hash 9924644F
- sample 7:
- time = 597333
- flags = 1
- data = length 5143, hash 6C34F0CE
- sample 8:
- time = 682666
- flags = 1
- data = length 5109, hash E3B7BEFB
- sample 9:
- time = 768000
- flags = 1
- data = length 5129, hash 44111D9B
- sample 10:
- time = 853333
- flags = 1
- data = length 5031, hash 9D55EA53
- sample 11:
- time = 938666
- flags = 1
- data = length 5119, hash E1CB9BA6
- sample 12:
- time = 1024000
- flags = 1
- data = length 5360, hash 17265C5D
- sample 13:
- time = 1109333
- flags = 1
- data = length 5340, hash A90FDDF1
- sample 14:
- time = 1194666
- flags = 1
- data = length 5162, hash 31F65AD5
- sample 15:
- time = 1280000
- flags = 1
- data = length 5168, hash F2394F2D
- sample 16:
- time = 1365333
- flags = 1
- data = length 5776, hash 58437AB3
- sample 17:
- time = 1450666
- flags = 1
- data = length 5394, hash EBAB20A8
- sample 18:
- time = 1536000
- flags = 1
- data = length 5168, hash BF37C7A5
- sample 19:
- time = 1621333
- flags = 1
- data = length 5324, hash 59546B7B
- sample 20:
- time = 1706666
- flags = 1
- data = length 5172, hash 6036EF0B
- sample 21:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 22:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 23:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 24:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 25:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 26:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 27:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 28:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 29:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 30:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 31:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 32:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_id3_disabled.flac.3.dump b/library/core/src/test/assets/flac/bear_with_id3_disabled.flac.3.dump
index 2260aebd8e..4fd2cb37f6 100644
--- a/library/core/src/test/assets/flac/bear_with_id3_disabled.flac.3.dump
+++ b/library/core/src/test/assets/flac/bear_with_id3_disabled.flac.3.dump
@@ -27,9 +27,13 @@ track 0:
metadata = null
initializationData:
data = length 42, hash 83F6895
- total output bytes = 445
- sample count = 1
+ total output bytes = 3829
+ sample count = 2
sample 0:
+ time = 2645333
+ flags = 1
+ data = length 3384, hash 938BCDD9
+ sample 1:
time = 2730666
flags = 1
data = length 445, hash A388E3D6
diff --git a/library/core/src/test/assets/flac/bear_with_id3_disabled.flac.unklen.dump b/library/core/src/test/assets/flac/bear_with_id3_disabled.flac.unklen.dump
deleted file mode 100644
index bd8f1827e4..0000000000
--- a/library/core/src/test/assets/flac/bear_with_id3_disabled.flac.unklen.dump
+++ /dev/null
@@ -1,164 +0,0 @@
-seekMap:
- isSeekable = false
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=0]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- metadata = null
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 164431
- sample count = 33
- sample 0:
- time = 0
- flags = 1
- data = length 5030, hash D2B60530
- sample 1:
- time = 85333
- flags = 1
- data = length 5066, hash 4C932A54
- sample 2:
- time = 170666
- flags = 1
- data = length 5112, hash 7E5A7B61
- sample 3:
- time = 256000
- flags = 1
- data = length 5044, hash 7EF93F13
- sample 4:
- time = 341333
- flags = 1
- data = length 4943, hash DE7E27F8
- sample 5:
- time = 426666
- flags = 1
- data = length 5121, hash 6D0D0B40
- sample 6:
- time = 512000
- flags = 1
- data = length 5068, hash 9924644F
- sample 7:
- time = 597333
- flags = 1
- data = length 5143, hash 6C34F0CE
- sample 8:
- time = 682666
- flags = 1
- data = length 5109, hash E3B7BEFB
- sample 9:
- time = 768000
- flags = 1
- data = length 5129, hash 44111D9B
- sample 10:
- time = 853333
- flags = 1
- data = length 5031, hash 9D55EA53
- sample 11:
- time = 938666
- flags = 1
- data = length 5119, hash E1CB9BA6
- sample 12:
- time = 1024000
- flags = 1
- data = length 5360, hash 17265C5D
- sample 13:
- time = 1109333
- flags = 1
- data = length 5340, hash A90FDDF1
- sample 14:
- time = 1194666
- flags = 1
- data = length 5162, hash 31F65AD5
- sample 15:
- time = 1280000
- flags = 1
- data = length 5168, hash F2394F2D
- sample 16:
- time = 1365333
- flags = 1
- data = length 5776, hash 58437AB3
- sample 17:
- time = 1450666
- flags = 1
- data = length 5394, hash EBAB20A8
- sample 18:
- time = 1536000
- flags = 1
- data = length 5168, hash BF37C7A5
- sample 19:
- time = 1621333
- flags = 1
- data = length 5324, hash 59546B7B
- sample 20:
- time = 1706666
- flags = 1
- data = length 5172, hash 6036EF0B
- sample 21:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 22:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 23:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 24:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 25:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 26:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 27:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 28:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 29:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 30:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 31:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 32:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_id3_enabled.flac.3.dump b/library/core/src/test/assets/flac/bear_with_id3_enabled.flac.3.dump
index b5069a4581..51c667d2f9 100644
--- a/library/core/src/test/assets/flac/bear_with_id3_enabled.flac.3.dump
+++ b/library/core/src/test/assets/flac/bear_with_id3_enabled.flac.3.dump
@@ -27,9 +27,13 @@ track 0:
metadata = entries=[TXXX: description=ID: value=105519843, TIT2: description=null: value=那么爱你为什么, TPE1: description=null: value=阿强, TALB: description=null: value=华丽的外衣, TXXX: description=ID: value=105519843, APIC: mimeType=image/jpeg, description=]
initializationData:
data = length 42, hash 83F6895
- total output bytes = 445
- sample count = 1
+ total output bytes = 3829
+ sample count = 2
sample 0:
+ time = 2645333
+ flags = 1
+ data = length 3384, hash 938BCDD9
+ sample 1:
time = 2730666
flags = 1
data = length 445, hash A388E3D6
diff --git a/library/core/src/test/assets/flac/bear_with_id3_enabled.flac.unklen.dump b/library/core/src/test/assets/flac/bear_with_id3_enabled.flac.unklen.dump
deleted file mode 100644
index 47402623c1..0000000000
--- a/library/core/src/test/assets/flac/bear_with_id3_enabled.flac.unklen.dump
+++ /dev/null
@@ -1,164 +0,0 @@
-seekMap:
- isSeekable = false
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=0]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- metadata = entries=[TXXX: description=ID: value=105519843, TIT2: description=null: value=那么爱你为什么, TPE1: description=null: value=阿强, TALB: description=null: value=华丽的外衣, TXXX: description=ID: value=105519843, APIC: mimeType=image/jpeg, description=]
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 164431
- sample count = 33
- sample 0:
- time = 0
- flags = 1
- data = length 5030, hash D2B60530
- sample 1:
- time = 85333
- flags = 1
- data = length 5066, hash 4C932A54
- sample 2:
- time = 170666
- flags = 1
- data = length 5112, hash 7E5A7B61
- sample 3:
- time = 256000
- flags = 1
- data = length 5044, hash 7EF93F13
- sample 4:
- time = 341333
- flags = 1
- data = length 4943, hash DE7E27F8
- sample 5:
- time = 426666
- flags = 1
- data = length 5121, hash 6D0D0B40
- sample 6:
- time = 512000
- flags = 1
- data = length 5068, hash 9924644F
- sample 7:
- time = 597333
- flags = 1
- data = length 5143, hash 6C34F0CE
- sample 8:
- time = 682666
- flags = 1
- data = length 5109, hash E3B7BEFB
- sample 9:
- time = 768000
- flags = 1
- data = length 5129, hash 44111D9B
- sample 10:
- time = 853333
- flags = 1
- data = length 5031, hash 9D55EA53
- sample 11:
- time = 938666
- flags = 1
- data = length 5119, hash E1CB9BA6
- sample 12:
- time = 1024000
- flags = 1
- data = length 5360, hash 17265C5D
- sample 13:
- time = 1109333
- flags = 1
- data = length 5340, hash A90FDDF1
- sample 14:
- time = 1194666
- flags = 1
- data = length 5162, hash 31F65AD5
- sample 15:
- time = 1280000
- flags = 1
- data = length 5168, hash F2394F2D
- sample 16:
- time = 1365333
- flags = 1
- data = length 5776, hash 58437AB3
- sample 17:
- time = 1450666
- flags = 1
- data = length 5394, hash EBAB20A8
- sample 18:
- time = 1536000
- flags = 1
- data = length 5168, hash BF37C7A5
- sample 19:
- time = 1621333
- flags = 1
- data = length 5324, hash 59546B7B
- sample 20:
- time = 1706666
- flags = 1
- data = length 5172, hash 6036EF0B
- sample 21:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 22:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 23:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 24:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 25:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 26:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 27:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 28:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 29:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 30:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 31:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 32:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_picture.flac.3.dump b/library/core/src/test/assets/flac/bear_with_picture.flac.3.dump
index 8a3c80c935..d5cb96739e 100644
--- a/library/core/src/test/assets/flac/bear_with_picture.flac.3.dump
+++ b/library/core/src/test/assets/flac/bear_with_picture.flac.3.dump
@@ -27,9 +27,13 @@ track 0:
metadata = entries=[Picture: mimeType=image/png, description=]
initializationData:
data = length 42, hash 83F6895
- total output bytes = 445
- sample count = 1
+ total output bytes = 3829
+ sample count = 2
sample 0:
+ time = 2645333
+ flags = 1
+ data = length 3384, hash 938BCDD9
+ sample 1:
time = 2730666
flags = 1
data = length 445, hash A388E3D6
diff --git a/library/core/src/test/assets/flac/bear_with_picture.flac.unklen.dump b/library/core/src/test/assets/flac/bear_with_picture.flac.unklen.dump
deleted file mode 100644
index 93e33e7c23..0000000000
--- a/library/core/src/test/assets/flac/bear_with_picture.flac.unklen.dump
+++ /dev/null
@@ -1,164 +0,0 @@
-seekMap:
- isSeekable = false
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=0]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- metadata = entries=[Picture: mimeType=image/png, description=]
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 164431
- sample count = 33
- sample 0:
- time = 0
- flags = 1
- data = length 5030, hash D2B60530
- sample 1:
- time = 85333
- flags = 1
- data = length 5066, hash 4C932A54
- sample 2:
- time = 170666
- flags = 1
- data = length 5112, hash 7E5A7B61
- sample 3:
- time = 256000
- flags = 1
- data = length 5044, hash 7EF93F13
- sample 4:
- time = 341333
- flags = 1
- data = length 4943, hash DE7E27F8
- sample 5:
- time = 426666
- flags = 1
- data = length 5121, hash 6D0D0B40
- sample 6:
- time = 512000
- flags = 1
- data = length 5068, hash 9924644F
- sample 7:
- time = 597333
- flags = 1
- data = length 5143, hash 6C34F0CE
- sample 8:
- time = 682666
- flags = 1
- data = length 5109, hash E3B7BEFB
- sample 9:
- time = 768000
- flags = 1
- data = length 5129, hash 44111D9B
- sample 10:
- time = 853333
- flags = 1
- data = length 5031, hash 9D55EA53
- sample 11:
- time = 938666
- flags = 1
- data = length 5119, hash E1CB9BA6
- sample 12:
- time = 1024000
- flags = 1
- data = length 5360, hash 17265C5D
- sample 13:
- time = 1109333
- flags = 1
- data = length 5340, hash A90FDDF1
- sample 14:
- time = 1194666
- flags = 1
- data = length 5162, hash 31F65AD5
- sample 15:
- time = 1280000
- flags = 1
- data = length 5168, hash F2394F2D
- sample 16:
- time = 1365333
- flags = 1
- data = length 5776, hash 58437AB3
- sample 17:
- time = 1450666
- flags = 1
- data = length 5394, hash EBAB20A8
- sample 18:
- time = 1536000
- flags = 1
- data = length 5168, hash BF37C7A5
- sample 19:
- time = 1621333
- flags = 1
- data = length 5324, hash 59546B7B
- sample 20:
- time = 1706666
- flags = 1
- data = length 5172, hash 6036EF0B
- sample 21:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 22:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 23:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 24:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 25:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 26:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 27:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 28:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 29:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 30:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 31:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 32:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/assets/flac/bear_with_vorbis_comments.flac.3.dump b/library/core/src/test/assets/flac/bear_with_vorbis_comments.flac.3.dump
index 86f6da89fe..8d8fd28e3f 100644
--- a/library/core/src/test/assets/flac/bear_with_vorbis_comments.flac.3.dump
+++ b/library/core/src/test/assets/flac/bear_with_vorbis_comments.flac.3.dump
@@ -27,9 +27,13 @@ track 0:
metadata = entries=[VC: TITLE=test title, VC: ARTIST=test artist]
initializationData:
data = length 42, hash 83F6895
- total output bytes = 445
- sample count = 1
+ total output bytes = 3829
+ sample count = 2
sample 0:
+ time = 2645333
+ flags = 1
+ data = length 3384, hash 938BCDD9
+ sample 1:
time = 2730666
flags = 1
data = length 445, hash A388E3D6
diff --git a/library/core/src/test/assets/flac/bear_with_vorbis_comments.flac.unklen.dump b/library/core/src/test/assets/flac/bear_with_vorbis_comments.flac.unklen.dump
deleted file mode 100644
index f7f67b12ab..0000000000
--- a/library/core/src/test/assets/flac/bear_with_vorbis_comments.flac.unklen.dump
+++ /dev/null
@@ -1,164 +0,0 @@
-seekMap:
- isSeekable = false
- duration = 2741000
- getPosition(0) = [[timeUs=0, position=0]]
-numberOfTracks = 1
-track 0:
- format:
- bitrate = 1536000
- id = null
- containerMimeType = null
- sampleMimeType = audio/flac
- maxInputSize = 5776
- width = -1
- height = -1
- frameRate = -1.0
- rotationDegrees = 0
- pixelWidthHeightRatio = 1.0
- channelCount = 2
- sampleRate = 48000
- pcmEncoding = -1
- encoderDelay = 0
- encoderPadding = 0
- subsampleOffsetUs = 9223372036854775807
- selectionFlags = 0
- language = null
- drmInitData = -
- metadata = entries=[VC: TITLE=test title, VC: ARTIST=test artist]
- initializationData:
- data = length 42, hash 83F6895
- total output bytes = 164431
- sample count = 33
- sample 0:
- time = 0
- flags = 1
- data = length 5030, hash D2B60530
- sample 1:
- time = 85333
- flags = 1
- data = length 5066, hash 4C932A54
- sample 2:
- time = 170666
- flags = 1
- data = length 5112, hash 7E5A7B61
- sample 3:
- time = 256000
- flags = 1
- data = length 5044, hash 7EF93F13
- sample 4:
- time = 341333
- flags = 1
- data = length 4943, hash DE7E27F8
- sample 5:
- time = 426666
- flags = 1
- data = length 5121, hash 6D0D0B40
- sample 6:
- time = 512000
- flags = 1
- data = length 5068, hash 9924644F
- sample 7:
- time = 597333
- flags = 1
- data = length 5143, hash 6C34F0CE
- sample 8:
- time = 682666
- flags = 1
- data = length 5109, hash E3B7BEFB
- sample 9:
- time = 768000
- flags = 1
- data = length 5129, hash 44111D9B
- sample 10:
- time = 853333
- flags = 1
- data = length 5031, hash 9D55EA53
- sample 11:
- time = 938666
- flags = 1
- data = length 5119, hash E1CB9BA6
- sample 12:
- time = 1024000
- flags = 1
- data = length 5360, hash 17265C5D
- sample 13:
- time = 1109333
- flags = 1
- data = length 5340, hash A90FDDF1
- sample 14:
- time = 1194666
- flags = 1
- data = length 5162, hash 31F65AD5
- sample 15:
- time = 1280000
- flags = 1
- data = length 5168, hash F2394F2D
- sample 16:
- time = 1365333
- flags = 1
- data = length 5776, hash 58437AB3
- sample 17:
- time = 1450666
- flags = 1
- data = length 5394, hash EBAB20A8
- sample 18:
- time = 1536000
- flags = 1
- data = length 5168, hash BF37C7A5
- sample 19:
- time = 1621333
- flags = 1
- data = length 5324, hash 59546B7B
- sample 20:
- time = 1706666
- flags = 1
- data = length 5172, hash 6036EF0B
- sample 21:
- time = 1792000
- flags = 1
- data = length 5102, hash 5A131071
- sample 22:
- time = 1877333
- flags = 1
- data = length 5111, hash 3D9EBB3B
- sample 23:
- time = 1962666
- flags = 1
- data = length 5113, hash 61101D4F
- sample 24:
- time = 2048000
- flags = 1
- data = length 5229, hash D2E55742
- sample 25:
- time = 2133333
- flags = 1
- data = length 5162, hash 7F2E97FA
- sample 26:
- time = 2218666
- flags = 1
- data = length 5255, hash D92A782
- sample 27:
- time = 2304000
- flags = 1
- data = length 5196, hash 98FE5138
- sample 28:
- time = 2389333
- flags = 1
- data = length 5214, hash 3D35C38C
- sample 29:
- time = 2474666
- flags = 1
- data = length 5211, hash 7E25420F
- sample 30:
- time = 2560000
- flags = 1
- data = length 5230, hash 2AD96FBC
- sample 31:
- time = 2645333
- flags = 1
- data = length 3384, hash 938BCDD9
- sample 32:
- time = 2730666
- flags = 1
- data = length 445, hash A388E3D6
-tracksEnded = true
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java
index 9389f776f9..97bfc949de 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/extractor/flac/FlacExtractorTest.java
@@ -20,7 +20,6 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.testutil.ExtractorAsserts;
-import com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory;
import com.google.android.exoplayer2.testutil.TestUtil;
import java.io.IOException;
import org.junit.Test;
@@ -32,41 +31,49 @@ public class FlacExtractorTest {
@Test
public void testSample() throws Exception {
- assertBehavior(FlacExtractor::new, "flac/bear.flac");
+ ExtractorAsserts.assertBehavior(FlacExtractor::new, "flac/bear.flac");
}
@Test
public void testSampleWithId3HeaderAndId3Enabled() throws Exception {
- assertBehavior(FlacExtractor::new, "flac/bear_with_id3_enabled.flac");
+ ExtractorAsserts.assertBehavior(FlacExtractor::new, "flac/bear_with_id3_enabled.flac");
}
@Test
public void testSampleWithId3HeaderAndId3Disabled() throws Exception {
// bear_with_id3_disabled.flac is identical to bear_with_id3_enabled.flac, but the dump file is
// different due to setting FLAG_DISABLE_ID3_METADATA.
- assertBehavior(
+ ExtractorAsserts.assertBehavior(
() -> new FlacExtractor(FlacExtractor.FLAG_DISABLE_ID3_METADATA),
"flac/bear_with_id3_disabled.flac");
}
+ @Test
+ public void testSampleUnseekable() throws Exception {
+ ExtractorAsserts.assertBehavior(
+ FlacExtractor::new, "flac/bear_no_seek_table_no_num_samples.flac");
+ }
+
@Test
public void testSampleWithVorbisComments() throws Exception {
- assertBehavior(FlacExtractor::new, "flac/bear_with_vorbis_comments.flac");
+ ExtractorAsserts.assertBehavior(FlacExtractor::new, "flac/bear_with_vorbis_comments.flac");
}
@Test
public void testSampleWithPicture() throws Exception {
- assertBehavior(FlacExtractor::new, "flac/bear_with_picture.flac");
+ ExtractorAsserts.assertBehavior(FlacExtractor::new, "flac/bear_with_picture.flac");
}
@Test
public void testOneMetadataBlock() throws Exception {
- assertBehavior(FlacExtractor::new, "flac/bear_one_metadata_block.flac");
+ // Don't simulate IO errors as it is too slow when using the binary search seek map (see
+ // [Internal: b/145994869]).
+ assertBehaviorWithoutSimulatingIOErrors("flac/bear_one_metadata_block.flac");
}
@Test
public void testNoMinMaxFrameSize() throws Exception {
- assertBehavior(FlacExtractor::new, "flac/bear_no_min_max_frame_size.flac");
+ ExtractorAsserts.assertBehavior(FlacExtractor::new, "flac/bear_no_min_max_frame_size.flac");
}
@Test
@@ -76,24 +83,63 @@ public class FlacExtractorTest {
@Test
public void testUncommonSampleRate() throws Exception {
- assertBehavior(FlacExtractor::new, "flac/bear_uncommon_sample_rate.flac");
+ ExtractorAsserts.assertBehavior(FlacExtractor::new, "flac/bear_uncommon_sample_rate.flac");
}
- private void assertBehavior(ExtractorFactory factory, String file)
+ private static void assertBehaviorWithoutSimulatingIOErrors(String file)
throws IOException, InterruptedException {
// Check behavior prior to initialization.
- Extractor extractor = factory.create();
+ Extractor extractor = new FlacExtractor();
extractor.seek(0, 0);
extractor.release();
+
// Assert output.
Context context = ApplicationProvider.getApplicationContext();
byte[] data = TestUtil.getByteArray(context, file);
- // Don't simulate IO errors as it is too slow (see b/145994869).
- ExtractorAsserts.assertOutput(factory.create(), file, data, context, true, false, false, false);
- ExtractorAsserts.assertOutput(factory.create(), file, data, context, true, false, false, true);
- ExtractorAsserts.assertOutput(factory.create(), file, data, context, true, false, true, false);
- ExtractorAsserts.assertOutput(factory.create(), file, data, context, true, false, true, true);
ExtractorAsserts.assertOutput(
- factory.create(), file, data, context, false, false, false, false);
+ new FlacExtractor(),
+ file,
+ data,
+ context,
+ /* sniffFirst= */ true,
+ /* simulateIOErrors= */ false,
+ /* simulateUnknownLength= */ false,
+ /* simulatePartialReads= */ false);
+ ExtractorAsserts.assertOutput(
+ new FlacExtractor(),
+ file,
+ data,
+ context,
+ /* sniffFirst= */ true,
+ /* simulateIOErrors= */ false,
+ /* simulateUnknownLength= */ false,
+ /* simulatePartialReads= */ true);
+ ExtractorAsserts.assertOutput(
+ new FlacExtractor(),
+ file,
+ data,
+ context,
+ /* sniffFirst= */ true,
+ /* simulateIOErrors= */ false,
+ /* simulateUnknownLength= */ true,
+ /* simulatePartialReads= */ false);
+ ExtractorAsserts.assertOutput(
+ new FlacExtractor(),
+ file,
+ data,
+ context,
+ /* sniffFirst= */ true,
+ /* simulateIOErrors= */ false,
+ /* simulateUnknownLength= */ true,
+ /* simulatePartialReads= */ true);
+ ExtractorAsserts.assertOutput(
+ new FlacExtractor(),
+ file,
+ data,
+ context,
+ /* sniffFirst= */ false,
+ /* simulateIOErrors= */ false,
+ /* simulateUnknownLength= */ false,
+ /* simulatePartialReads= */ false);
}
}
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java
index a721e81db9..050898a20e 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java
+++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java
@@ -208,18 +208,21 @@ public final class ExtractorAsserts {
extractorOutput.assertOutput(context, file + ".0" + DUMP_EXTENSION);
}
- // If the SeekMap is seekable, test seeking to 4 positions in the stream.
+ // If the SeekMap is seekable, test seeking in the stream.
SeekMap seekMap = extractorOutput.seekMap;
if (seekMap.isSeekable()) {
long durationUs = seekMap.getDurationUs();
for (int j = 0; j < 4; j++) {
extractorOutput.clearTrackOutputs();
- long timeUs = (durationUs * j) / 3;
+ long timeUs = durationUs == C.TIME_UNSET ? 0 : (durationUs * j) / 3;
long position = seekMap.getSeekPoints(timeUs).first.position;
input.reset();
input.setPosition((int) position);
consumeTestData(extractor, input, timeUs, extractorOutput, false);
extractorOutput.assertOutput(context, file + '.' + j + DUMP_EXTENSION);
+ if (durationUs == C.TIME_UNSET) {
+ break;
+ }
}
}