mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Implement seeking from seektable in FLAC extractor
PiperOrigin-RevId: 285799995
This commit is contained in:
parent
2fe3e188a9
commit
3e4baa101c
@ -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 <a
|
||||
* href="https://xiph.org/flac/format.html">FLAC format specification</a>.
|
||||
*/
|
||||
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}.
|
||||
*
|
||||
* <p>If the header is valid, the position of {@code scratch} is moved to the byte following it.
|
||||
* <p>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}.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>If the CRC is valid, the position of {@code scratch} is moved to the byte following it.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>The {@code scratch} array must contain the whole frame header.
|
||||
* <p>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;
|
||||
}
|
||||
|
||||
|
@ -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 <a
|
||||
* href="https://xiph.org/flac/format.html">FLAC format specification</a>.
|
||||
*/
|
||||
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<String> 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.
|
||||
*
|
||||
* <p>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<String> readVorbisCommentMetadataBlock(ExtractorInput input, int length)
|
||||
throws IOException, InterruptedException {
|
||||
ParsableByteArray scratch = new ParsableByteArray(length);
|
||||
|
@ -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 <a
|
||||
* href="https://xiph.org/flac/format.html#metadata_block_seektable">seek table</a>.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
@ -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}.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If the search is successful, the position is set to the start of the found frame.
|
||||
* <li>Otherwise, the position is set to the first unsearched byte.
|
||||
* </ul>
|
||||
*
|
||||
* @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;
|
||||
|
@ -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 <a href="https://xiph.org/flac/format.html#metadata_block_seektable">FLAC format
|
||||
* METADATA_BLOCK_SEEKTABLE</a>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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() {}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ import java.util.List;
|
||||
*
|
||||
* @see <a href="https://xiph.org/flac/format.html#metadata_block_streaminfo">FLAC format
|
||||
* METADATA_BLOCK_STREAMINFO</a>
|
||||
* @see <a href="https://xiph.org/flac/format.html#metadata_block_seektable">FLAC format
|
||||
* METADATA_BLOCK_SEEKTABLE</a>
|
||||
* @see <a href="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">FLAC format
|
||||
* METADATA_BLOCK_VORBIS_COMMENT</a>
|
||||
* @see <a href="https://xiph.org/flac/format.html#metadata_block_picture">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<String> 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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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:
|
||||
|
Binary file not shown.
@ -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:
|
Binary file not shown.
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user