use of com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable in project ExoPlayer by google.
the class FlacMetadataReader method readMetadataBlock.
/**
* Reads one FLAC metadata block.
*
* <p>If no exception is thrown, the peek position of {@code input} is aligned with the read
* position.
*
* @param input Input stream to read the metadata block from (header included).
* @param metadataHolder A holder for the metadata read. If the stream info block (which must be
* the first metadata block) is read, the holder contains a new instance representing the
* stream info data. If the block read is a Vorbis comment block or a picture block, the
* holder contains a copy of the existing stream metadata with the corresponding metadata
* added. Otherwise, the metadata in the holder is unchanged.
* @return Whether the block read is the last metadata block.
* @throws IllegalArgumentException If the block read is not a stream info block and the metadata
* in {@code metadataHolder} is {@code null}. In this case, the read position will be at the
* start of a metadata block and there is no guarantee on the peek position.
* @throws IOException If reading from the input fails. In this case, the read position will be at
* the start of a metadata block and there is no guarantee on the peek position.
*/
public static boolean readMetadataBlock(ExtractorInput input, FlacStreamMetadataHolder metadataHolder) throws IOException {
input.resetPeekPosition();
ParsableBitArray scratch = new ParsableBitArray(new byte[4]);
input.peekFully(scratch.data, 0, FlacConstants.METADATA_BLOCK_HEADER_SIZE);
boolean isLastMetadataBlock = scratch.readBit();
int type = scratch.readBits(7);
int length = FlacConstants.METADATA_BLOCK_HEADER_SIZE + scratch.readBits(24);
if (type == FlacConstants.METADATA_TYPE_STREAM_INFO) {
metadataHolder.flacStreamMetadata = readStreamInfoBlock(input);
} else {
@Nullable FlacStreamMetadata flacStreamMetadata = metadataHolder.flacStreamMetadata;
if (flacStreamMetadata == null) {
throw new IllegalArgumentException();
}
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 == FlacConstants.METADATA_TYPE_PICTURE) {
ParsableByteArray pictureBlock = new ParsableByteArray(length);
input.readFully(pictureBlock.getData(), 0, length);
pictureBlock.skipBytes(FlacConstants.METADATA_BLOCK_HEADER_SIZE);
PictureFrame pictureFrame = PictureFrame.fromPictureBlock(pictureBlock);
metadataHolder.flacStreamMetadata = flacStreamMetadata.copyWithPictureFrames(ImmutableList.of(pictureFrame));
} else {
input.skipFully(length);
}
}
return isLastMetadataBlock;
}
use of com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable in project ExoPlayer by google.
the class FlacMetadataReaderTest method readSeekTableMetadataBlock_returnsCorrectSeekPoints.
@Test
public void readSeekTableMetadataBlock_returnsCorrectSeekPoints() throws Exception {
ExtractorInput input = buildExtractorInput("media/flac/bear.flac");
// Skip to seek table block.
input.skipFully(FlacConstants.STREAM_MARKER_SIZE + FlacConstants.STREAM_INFO_BLOCK_SIZE);
int seekTableBlockSize = 598;
ParsableByteArray scratch = new ParsableByteArray(seekTableBlockSize);
input.read(scratch.getData(), 0, seekTableBlockSize);
FlacStreamMetadata.SeekTable seekTable = FlacMetadataReader.readSeekTableMetadataBlock(scratch);
assertThat(seekTable.pointOffsets[0]).isEqualTo(0);
assertThat(seekTable.pointSampleNumbers[0]).isEqualTo(0);
assertThat(seekTable.pointOffsets[31]).isEqualTo(160602);
assertThat(seekTable.pointSampleNumbers[31]).isEqualTo(126976);
}
use of com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable in project ExoPlayer by google.
the class FlacMetadataReaderTest method readSeekTableMetadataBlock_ignoresPlaceholders.
@Test
public void readSeekTableMetadataBlock_ignoresPlaceholders() throws IOException {
byte[] fileData = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), "media/flac/bear.flac");
ParsableByteArray scratch = new ParsableByteArray(fileData);
// Skip to seek table block.
scratch.skipBytes(FlacConstants.STREAM_MARKER_SIZE + FlacConstants.STREAM_INFO_BLOCK_SIZE);
FlacStreamMetadata.SeekTable seekTable = FlacMetadataReader.readSeekTableMetadataBlock(scratch);
// Seek point at index 32 is a placeholder.
assertThat(seekTable.pointSampleNumbers).hasLength(32);
}
use of com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable in project ExoPlayer by google.
the class FlacReader method readHeaders.
@Override
@EnsuresNonNullIf(expression = "#3.format", result = false)
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) {
byte[] data = packet.getData();
@Nullable FlacStreamMetadata streamMetadata = this.streamMetadata;
if (streamMetadata == null) {
streamMetadata = new FlacStreamMetadata(data, 17);
this.streamMetadata = streamMetadata;
byte[] metadata = Arrays.copyOfRange(data, 9, packet.limit());
setupData.format = streamMetadata.getFormat(metadata, /* id3Metadata= */
null);
return true;
}
if ((data[0] & 0x7F) == FlacConstants.METADATA_TYPE_SEEK_TABLE) {
SeekTable seekTable = FlacMetadataReader.readSeekTableMetadataBlock(packet);
streamMetadata = streamMetadata.copyWithSeekTable(seekTable);
this.streamMetadata = streamMetadata;
flacOggSeeker = new FlacOggSeeker(streamMetadata, seekTable);
return true;
}
if (isAudioPacket(data)) {
if (flacOggSeeker != null) {
flacOggSeeker.setFirstFrameOffset(position);
setupData.oggSeeker = flacOggSeeker;
}
checkNotNull(setupData.format);
return false;
}
return true;
}
Aggregations