mirror of
https://github.com/androidx/media.git
synced 2025-05-03 21:57:46 +08:00
Merge pull request #9543 from KasemJaffer:rf64
PiperOrigin-RevId: 408816643
This commit is contained in:
commit
04517e17d4
@ -11,6 +11,9 @@
|
|||||||
`buildVideoRenderers()` or `buildAudioRenderers()` can access the codec
|
`buildVideoRenderers()` or `buildAudioRenderers()` can access the codec
|
||||||
adapter factory and pass it to `MediaCodecRenderer` instances they
|
adapter factory and pass it to `MediaCodecRenderer` instances they
|
||||||
create.
|
create.
|
||||||
|
* Extractors:
|
||||||
|
* WAV: Add support for RF64 streams
|
||||||
|
([#9543](https://github.com/google/ExoPlayer/issues/9543).
|
||||||
|
|
||||||
### 2.16.0 (2021-11-04)
|
### 2.16.0 (2021-11-04)
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@ public final class WavUtil {
|
|||||||
public static final int FMT_FOURCC = 0x666d7420;
|
public static final int FMT_FOURCC = 0x666d7420;
|
||||||
/** Four character code for "data". */
|
/** Four character code for "data". */
|
||||||
public static final int DATA_FOURCC = 0x64617461;
|
public static final int DATA_FOURCC = 0x64617461;
|
||||||
|
/** Four character code for "RF64". */
|
||||||
|
public static final int RF64_FOURCC = 0x52463634;
|
||||||
|
/** Four character code for "ds64". */
|
||||||
|
public static final int DS64_FOURCC = 0x64733634;
|
||||||
|
|
||||||
/** WAVE type value for integer PCM audio data. */
|
/** WAVE type value for integer PCM audio data. */
|
||||||
public static final int TYPE_PCM = 0x0001;
|
public static final int TYPE_PCM = 0x0001;
|
||||||
|
@ -31,6 +31,7 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
|||||||
import com.google.android.exoplayer2.extractor.PositionHolder;
|
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||||
import com.google.android.exoplayer2.extractor.TrackOutput;
|
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
|
import com.google.android.exoplayer2.util.Log;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
@ -47,6 +48,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
/** Extracts data from WAV byte streams. */
|
/** Extracts data from WAV byte streams. */
|
||||||
public final class WavExtractor implements Extractor {
|
public final class WavExtractor implements Extractor {
|
||||||
|
|
||||||
|
private static final String TAG = "WavExtractor";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When outputting PCM data to a {@link TrackOutput}, we can choose how many frames are grouped
|
* When outputting PCM data to a {@link TrackOutput}, we can choose how many frames are grouped
|
||||||
* into each sample, and hence each sample's duration. This is the target number of samples to
|
* into each sample, and hence each sample's duration. This is the target number of samples to
|
||||||
@ -63,6 +66,7 @@ public final class WavExtractor implements Extractor {
|
|||||||
@Target({ElementType.TYPE_USE})
|
@Target({ElementType.TYPE_USE})
|
||||||
@IntDef({
|
@IntDef({
|
||||||
STATE_READING_FILE_TYPE,
|
STATE_READING_FILE_TYPE,
|
||||||
|
STATE_READING_RF64_SAMPLE_DATA_SIZE,
|
||||||
STATE_READING_FORMAT,
|
STATE_READING_FORMAT,
|
||||||
STATE_SKIPPING_TO_SAMPLE_DATA,
|
STATE_SKIPPING_TO_SAMPLE_DATA,
|
||||||
STATE_READING_SAMPLE_DATA
|
STATE_READING_SAMPLE_DATA
|
||||||
@ -70,19 +74,22 @@ public final class WavExtractor implements Extractor {
|
|||||||
private @interface State {}
|
private @interface State {}
|
||||||
|
|
||||||
private static final int STATE_READING_FILE_TYPE = 0;
|
private static final int STATE_READING_FILE_TYPE = 0;
|
||||||
private static final int STATE_READING_FORMAT = 1;
|
private static final int STATE_READING_RF64_SAMPLE_DATA_SIZE = 1;
|
||||||
private static final int STATE_SKIPPING_TO_SAMPLE_DATA = 2;
|
private static final int STATE_READING_FORMAT = 2;
|
||||||
private static final int STATE_READING_SAMPLE_DATA = 3;
|
private static final int STATE_SKIPPING_TO_SAMPLE_DATA = 3;
|
||||||
|
private static final int STATE_READING_SAMPLE_DATA = 4;
|
||||||
|
|
||||||
private @MonotonicNonNull ExtractorOutput extractorOutput;
|
private @MonotonicNonNull ExtractorOutput extractorOutput;
|
||||||
private @MonotonicNonNull TrackOutput trackOutput;
|
private @MonotonicNonNull TrackOutput trackOutput;
|
||||||
private @State int state;
|
private @State int state;
|
||||||
|
private long rf64SampleDataSize;
|
||||||
private @MonotonicNonNull OutputWriter outputWriter;
|
private @MonotonicNonNull OutputWriter outputWriter;
|
||||||
private int dataStartPosition;
|
private int dataStartPosition;
|
||||||
private long dataEndPosition;
|
private long dataEndPosition;
|
||||||
|
|
||||||
public WavExtractor() {
|
public WavExtractor() {
|
||||||
state = STATE_READING_FILE_TYPE;
|
state = STATE_READING_FILE_TYPE;
|
||||||
|
rf64SampleDataSize = C.LENGTH_UNSET;
|
||||||
dataStartPosition = C.POSITION_UNSET;
|
dataStartPosition = C.POSITION_UNSET;
|
||||||
dataEndPosition = C.POSITION_UNSET;
|
dataEndPosition = C.POSITION_UNSET;
|
||||||
}
|
}
|
||||||
@ -120,6 +127,9 @@ public final class WavExtractor implements Extractor {
|
|||||||
case STATE_READING_FILE_TYPE:
|
case STATE_READING_FILE_TYPE:
|
||||||
readFileType(input);
|
readFileType(input);
|
||||||
return Extractor.RESULT_CONTINUE;
|
return Extractor.RESULT_CONTINUE;
|
||||||
|
case STATE_READING_RF64_SAMPLE_DATA_SIZE:
|
||||||
|
readRf64SampleDataSize(input);
|
||||||
|
return Extractor.RESULT_CONTINUE;
|
||||||
case STATE_READING_FORMAT:
|
case STATE_READING_FORMAT:
|
||||||
readFormat(input);
|
readFormat(input);
|
||||||
return Extractor.RESULT_CONTINUE;
|
return Extractor.RESULT_CONTINUE;
|
||||||
@ -152,6 +162,11 @@ public final class WavExtractor implements Extractor {
|
|||||||
"Unsupported or unrecognized wav file type.", /* cause= */ null);
|
"Unsupported or unrecognized wav file type.", /* cause= */ null);
|
||||||
}
|
}
|
||||||
input.skipFully((int) (input.getPeekPosition() - input.getPosition()));
|
input.skipFully((int) (input.getPeekPosition() - input.getPosition()));
|
||||||
|
state = STATE_READING_RF64_SAMPLE_DATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readRf64SampleDataSize(ExtractorInput input) throws IOException {
|
||||||
|
rf64SampleDataSize = WavHeaderReader.readRf64SampleDataSize(input);
|
||||||
state = STATE_READING_FORMAT;
|
state = STATE_READING_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +209,18 @@ public final class WavExtractor implements Extractor {
|
|||||||
private void skipToSampleData(ExtractorInput input) throws IOException {
|
private void skipToSampleData(ExtractorInput input) throws IOException {
|
||||||
Pair<Long, Long> dataBounds = WavHeaderReader.skipToSampleData(input);
|
Pair<Long, Long> dataBounds = WavHeaderReader.skipToSampleData(input);
|
||||||
dataStartPosition = dataBounds.first.intValue();
|
dataStartPosition = dataBounds.first.intValue();
|
||||||
dataEndPosition = dataBounds.second;
|
long dataSize = dataBounds.second;
|
||||||
|
if (rf64SampleDataSize != C.LENGTH_UNSET && dataSize == 0xFFFFFFFFL) {
|
||||||
|
// Following EBU - Tech 3306-2007, the data size indicated in the ds64 chunk should only be
|
||||||
|
// used if the size of the data chunk is unset.
|
||||||
|
dataSize = rf64SampleDataSize;
|
||||||
|
}
|
||||||
|
dataEndPosition = dataStartPosition + dataSize;
|
||||||
|
long inputLength = input.getLength();
|
||||||
|
if (inputLength != C.LENGTH_UNSET && dataEndPosition > inputLength) {
|
||||||
|
Log.w(TAG, "Data exceeds input length: " + dataEndPosition + ", " + inputLength);
|
||||||
|
dataEndPosition = inputLength;
|
||||||
|
}
|
||||||
Assertions.checkNotNull(outputWriter).init(dataStartPosition, dataEndPosition);
|
Assertions.checkNotNull(outputWriter).init(dataStartPosition, dataEndPosition);
|
||||||
state = STATE_READING_SAMPLE_DATA;
|
state = STATE_READING_SAMPLE_DATA;
|
||||||
}
|
}
|
||||||
|
@ -32,20 +32,19 @@ import java.io.IOException;
|
|||||||
private static final String TAG = "WavHeaderReader";
|
private static final String TAG = "WavHeaderReader";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given {@code input} starts with a RIFF chunk header, followed by a WAVE
|
* Returns whether the given {@code input} starts with a RIFF or RF64 chunk header, followed by a
|
||||||
* tag.
|
* WAVE tag.
|
||||||
*
|
*
|
||||||
* @param input The input stream to peek from. The position should point to the start of the
|
* @param input The input stream to peek from. The position should point to the start of the
|
||||||
* stream.
|
* stream.
|
||||||
* @return Whether the given {@code input} starts with a RIFF chunk header, followed by a WAVE
|
* @return Whether the given {@code input} starts with a RIFF or RF64 chunk header, followed by a
|
||||||
* tag.
|
* WAVE tag.
|
||||||
* @throws IOException If peeking from the input fails.
|
* @throws IOException If peeking from the input fails.
|
||||||
*/
|
*/
|
||||||
public static boolean checkFileType(ExtractorInput input) throws IOException {
|
public static boolean checkFileType(ExtractorInput input) throws IOException {
|
||||||
ParsableByteArray scratch = new ParsableByteArray(ChunkHeader.SIZE_IN_BYTES);
|
ParsableByteArray scratch = new ParsableByteArray(ChunkHeader.SIZE_IN_BYTES);
|
||||||
// Attempt to read the RIFF chunk.
|
|
||||||
ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
|
ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
|
||||||
if (chunkHeader.id != WavUtil.RIFF_FOURCC) {
|
if (chunkHeader.id != WavUtil.RIFF_FOURCC && chunkHeader.id != WavUtil.RF64_FOURCC) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,11 +59,36 @@ import java.io.IOException;
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the ds64 chunk defined in EBU - TECH 3306-2007, if present. If there is no such chunk,
|
||||||
|
* the input's position is left unchanged.
|
||||||
|
*
|
||||||
|
* @param input Input stream to read from. The position should point to the byte following the
|
||||||
|
* WAVE tag.
|
||||||
|
* @throws IOException If reading from the input fails.
|
||||||
|
* @return The value of the data size field in the ds64 chunk, or {@link C#LENGTH_UNSET} if there
|
||||||
|
* is no such chunk.
|
||||||
|
*/
|
||||||
|
public static long readRf64SampleDataSize(ExtractorInput input) throws IOException {
|
||||||
|
ParsableByteArray scratch = new ParsableByteArray(ChunkHeader.SIZE_IN_BYTES);
|
||||||
|
ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
|
||||||
|
if (chunkHeader.id != WavUtil.DS64_FOURCC) {
|
||||||
|
input.resetPeekPosition();
|
||||||
|
return C.LENGTH_UNSET;
|
||||||
|
}
|
||||||
|
input.advancePeekPosition(8); // RIFF size
|
||||||
|
scratch.setPosition(0);
|
||||||
|
input.peekFully(scratch.getData(), 0, 8);
|
||||||
|
long sampleDataSize = scratch.readLittleEndianLong();
|
||||||
|
input.skipFully(ChunkHeader.SIZE_IN_BYTES + (int) chunkHeader.size);
|
||||||
|
return sampleDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and returns a {@code WavFormat}.
|
* Reads and returns a {@code WavFormat}.
|
||||||
*
|
*
|
||||||
* @param input Input stream to read the WAV format from. The position should point to the byte
|
* @param input Input stream to read the WAV format from. The position should point to the byte
|
||||||
* following the WAVE tag.
|
* following the ds64 chunk if present, or to the byte following the WAVE tag otherwise.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
* @return A new {@code WavFormat} read from {@code input}.
|
* @return A new {@code WavFormat} read from {@code input}.
|
||||||
*/
|
*/
|
||||||
@ -104,13 +128,14 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skips to the data in the given WAV input stream, and returns its bounds. After calling, the
|
* Skips to the data in the given WAV input stream, and returns its start position and size. After
|
||||||
* input stream's position will point to the start of sample data in the WAV. If an exception is
|
* calling, the input stream's position will point to the start of sample data in the WAV. If an
|
||||||
* thrown, the input position will be left pointing to a chunk header (that may not be the data
|
* exception is thrown, the input position will be left pointing to a chunk header (that may not
|
||||||
* chunk header).
|
* be the data chunk header).
|
||||||
*
|
*
|
||||||
* @param input The input stream, whose read position must be pointing to a valid chunk header.
|
* @param input The input stream, whose read position must be pointing to a valid chunk header.
|
||||||
* @return The byte positions at which the data starts (inclusive) and ends (exclusive).
|
* @return The byte positions at which the data starts (inclusive) and the size of the data, in
|
||||||
|
* bytes.
|
||||||
* @throws ParserException If an error occurs parsing chunks.
|
* @throws ParserException If an error occurs parsing chunks.
|
||||||
* @throws IOException If reading from the input fails.
|
* @throws IOException If reading from the input fails.
|
||||||
*/
|
*/
|
||||||
@ -125,13 +150,7 @@ import java.io.IOException;
|
|||||||
input.skipFully(ChunkHeader.SIZE_IN_BYTES);
|
input.skipFully(ChunkHeader.SIZE_IN_BYTES);
|
||||||
|
|
||||||
long dataStartPosition = input.getPosition();
|
long dataStartPosition = input.getPosition();
|
||||||
long dataEndPosition = dataStartPosition + chunkHeader.size;
|
return Pair.create(dataStartPosition, chunkHeader.size);
|
||||||
long inputLength = input.getLength();
|
|
||||||
if (inputLength != C.LENGTH_UNSET && dataEndPosition > inputLength) {
|
|
||||||
Log.w(TAG, "Data exceeds input length: " + dataEndPosition + ", " + inputLength);
|
|
||||||
dataEndPosition = inputLength;
|
|
||||||
}
|
|
||||||
return Pair.create(dataStartPosition, dataEndPosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,4 +53,10 @@ public final class WavExtractorTest {
|
|||||||
ExtractorAsserts.assertBehavior(
|
ExtractorAsserts.assertBehavior(
|
||||||
WavExtractor::new, "media/wav/sample_ima_adpcm.wav", simulationConfig);
|
WavExtractor::new, "media/wav/sample_ima_adpcm.wav", simulationConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sample_rf64() throws Exception {
|
||||||
|
ExtractorAsserts.assertBehavior(
|
||||||
|
WavExtractor::new, "media/wav/sample_rf64.wav", simulationConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
36
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.0.dump
vendored
Normal file
36
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.0.dump
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 348625
|
||||||
|
getPosition(0) = [[timeUs=0, position=80]]
|
||||||
|
getPosition(1) = [[timeUs=0, position=80], [timeUs=20, position=84]]
|
||||||
|
getPosition(174312) = [[timeUs=174291, position=33544], [timeUs=174312, position=33548]]
|
||||||
|
getPosition(348625) = [[timeUs=348604, position=67012]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 66936
|
||||||
|
sample count = 4
|
||||||
|
format 0:
|
||||||
|
averageBitrate = 1536000
|
||||||
|
peakBitrate = 1536000
|
||||||
|
sampleMimeType = audio/raw
|
||||||
|
maxInputSize = 19200
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
pcmEncoding = 2
|
||||||
|
sample 0:
|
||||||
|
time = 0
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash EF6C7C27
|
||||||
|
sample 1:
|
||||||
|
time = 100000
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash 5AB97AFC
|
||||||
|
sample 2:
|
||||||
|
time = 200000
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash 37920F33
|
||||||
|
sample 3:
|
||||||
|
time = 300000
|
||||||
|
flags = 1
|
||||||
|
data = length 9336, hash 135F1C30
|
||||||
|
tracksEnded = true
|
32
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.1.dump
vendored
Normal file
32
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.1.dump
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 348625
|
||||||
|
getPosition(0) = [[timeUs=0, position=80]]
|
||||||
|
getPosition(1) = [[timeUs=0, position=80], [timeUs=20, position=84]]
|
||||||
|
getPosition(174312) = [[timeUs=174291, position=33544], [timeUs=174312, position=33548]]
|
||||||
|
getPosition(348625) = [[timeUs=348604, position=67012]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 44628
|
||||||
|
sample count = 3
|
||||||
|
format 0:
|
||||||
|
averageBitrate = 1536000
|
||||||
|
peakBitrate = 1536000
|
||||||
|
sampleMimeType = audio/raw
|
||||||
|
maxInputSize = 19200
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
pcmEncoding = 2
|
||||||
|
sample 0:
|
||||||
|
time = 116208
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash E4B962ED
|
||||||
|
sample 1:
|
||||||
|
time = 216208
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash 4F13D6CF
|
||||||
|
sample 2:
|
||||||
|
time = 316208
|
||||||
|
flags = 1
|
||||||
|
data = length 6228, hash 3FB5F446
|
||||||
|
tracksEnded = true
|
28
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.2.dump
vendored
Normal file
28
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.2.dump
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 348625
|
||||||
|
getPosition(0) = [[timeUs=0, position=80]]
|
||||||
|
getPosition(1) = [[timeUs=0, position=80], [timeUs=20, position=84]]
|
||||||
|
getPosition(174312) = [[timeUs=174291, position=33544], [timeUs=174312, position=33548]]
|
||||||
|
getPosition(348625) = [[timeUs=348604, position=67012]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 22316
|
||||||
|
sample count = 2
|
||||||
|
format 0:
|
||||||
|
averageBitrate = 1536000
|
||||||
|
peakBitrate = 1536000
|
||||||
|
sampleMimeType = audio/raw
|
||||||
|
maxInputSize = 19200
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
pcmEncoding = 2
|
||||||
|
sample 0:
|
||||||
|
time = 232416
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash F82E494B
|
||||||
|
sample 1:
|
||||||
|
time = 332416
|
||||||
|
flags = 1
|
||||||
|
data = length 3116, hash 93C99CFD
|
||||||
|
tracksEnded = true
|
24
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.3.dump
vendored
Normal file
24
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.3.dump
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 348625
|
||||||
|
getPosition(0) = [[timeUs=0, position=80]]
|
||||||
|
getPosition(1) = [[timeUs=0, position=80], [timeUs=20, position=84]]
|
||||||
|
getPosition(174312) = [[timeUs=174291, position=33544], [timeUs=174312, position=33548]]
|
||||||
|
getPosition(348625) = [[timeUs=348604, position=67012]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 4
|
||||||
|
sample count = 1
|
||||||
|
format 0:
|
||||||
|
averageBitrate = 1536000
|
||||||
|
peakBitrate = 1536000
|
||||||
|
sampleMimeType = audio/raw
|
||||||
|
maxInputSize = 19200
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
pcmEncoding = 2
|
||||||
|
sample 0:
|
||||||
|
time = 348625
|
||||||
|
flags = 1
|
||||||
|
data = length 4, hash FFD4C53F
|
||||||
|
tracksEnded = true
|
36
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.unknown_length.dump
vendored
Normal file
36
testdata/src/test/assets/extractordumps/wav/sample_rf64.wav.unknown_length.dump
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 348625
|
||||||
|
getPosition(0) = [[timeUs=0, position=80]]
|
||||||
|
getPosition(1) = [[timeUs=0, position=80], [timeUs=20, position=84]]
|
||||||
|
getPosition(174312) = [[timeUs=174291, position=33544], [timeUs=174312, position=33548]]
|
||||||
|
getPosition(348625) = [[timeUs=348604, position=67012]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 66936
|
||||||
|
sample count = 4
|
||||||
|
format 0:
|
||||||
|
averageBitrate = 1536000
|
||||||
|
peakBitrate = 1536000
|
||||||
|
sampleMimeType = audio/raw
|
||||||
|
maxInputSize = 19200
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
pcmEncoding = 2
|
||||||
|
sample 0:
|
||||||
|
time = 0
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash EF6C7C27
|
||||||
|
sample 1:
|
||||||
|
time = 100000
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash 5AB97AFC
|
||||||
|
sample 2:
|
||||||
|
time = 200000
|
||||||
|
flags = 1
|
||||||
|
data = length 19200, hash 37920F33
|
||||||
|
sample 3:
|
||||||
|
time = 300000
|
||||||
|
flags = 1
|
||||||
|
data = length 9336, hash 135F1C30
|
||||||
|
tracksEnded = true
|
BIN
testdata/src/test/assets/media/wav/sample_rf64.wav
vendored
Normal file
BIN
testdata/src/test/assets/media/wav/sample_rf64.wav
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user