FlacMetadataReader { public static boolean readMetadataBlock( ExtractorInput input, FlacStreamMetadataHolder metadataHolder) throws IOException, InterruptedException { 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 { 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) { PictureFrame pictureFrame = readPictureMetadataBlock(input, length); metadataHolder.flacStreamMetadata = flacStreamMetadata.copyWithPictureFrames(Collections.singletonList(pictureFrame)); } else { input.skipFully(length); } } return isLastMetadataBlock; } private  FlacMetadataReader(); @Nullable static Metadata peekId3Metadata(ExtractorInput input, boolean parseData); static boolean checkAndPeekStreamMarker(ExtractorInput input); @Nullable static Metadata readId3Metadata(ExtractorInput input, boolean parseData); static void readStreamMarker(ExtractorInput input); static boolean readMetadataBlock(
      ExtractorInput input, FlacStreamMetadataHolder metadataHolder); static FlacStreamMetadata.SeekTable readSeekTableMetadataBlock(ParsableByteArray data); static int getFrameStartMarker(ExtractorInput input);  }
@Test public void readMetadataBlock_updatesReadPositionAndAlignsPeekPosition() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear.flac"); input.skipFully(FlacConstants.STREAM_MARKER_SIZE); input.advancePeekPosition(FlacConstants.STREAM_INFO_BLOCK_SIZE + 1); FlacMetadataReader.readMetadataBlock( input, new FlacStreamMetadataHolder( null)); assertThat(input.getPosition()).isNotEqualTo(0); assertThat(input.getPeekPosition()).isEqualTo(input.getPosition()); }
@Test public void readMetadataBlock_lastMetadataBlock_isTrue() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear_one_metadata_block.flac"); input.skipFully(FlacConstants.STREAM_MARKER_SIZE); boolean result = FlacMetadataReader.readMetadataBlock( input, new FlacStreamMetadataHolder( null)); assertThat(result).isTrue(); }
@Test public void readMetadataBlock_notLastMetadataBlock_isFalse() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear.flac"); input.skipFully(FlacConstants.STREAM_MARKER_SIZE); boolean result = FlacMetadataReader.readMetadataBlock( input, new FlacStreamMetadataHolder( null)); assertThat(result).isFalse(); }
@Test public void readMetadataBlock_streamInfoBlock_setsStreamMetadata() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear.flac"); input.skipFully(FlacConstants.STREAM_MARKER_SIZE); FlacStreamMetadataHolder metadataHolder = new FlacStreamMetadataHolder( null); FlacMetadataReader.readMetadataBlock(input, metadataHolder); assertThat(metadataHolder.flacStreamMetadata).isNotNull(); assertThat(metadataHolder.flacStreamMetadata.sampleRate).isEqualTo(48000); }
@Test public void readMetadataBlock_seekTableBlock_updatesStreamMetadata() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear.flac"); input.skipFully(FlacConstants.STREAM_MARKER_SIZE + FlacConstants.STREAM_INFO_BLOCK_SIZE); FlacStreamMetadataHolder metadataHolder = new FlacStreamMetadataHolder(buildStreamMetadata()); long originalSampleRate = metadataHolder.flacStreamMetadata.sampleRate; FlacMetadataReader.readMetadataBlock(input, metadataHolder); assertThat(metadataHolder.flacStreamMetadata).isNotNull(); assertThat(metadataHolder.flacStreamMetadata.sampleRate).isEqualTo(originalSampleRate); assertThat(metadataHolder.flacStreamMetadata.seekTable).isNotNull(); assertThat(metadataHolder.flacStreamMetadata.seekTable.pointSampleNumbers.length).isEqualTo(32); }
@Test public void readMetadataBlock_vorbisCommentBlock_updatesStreamMetadata() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear_with_vorbis_comments.flac"); input.skipFully(640); FlacStreamMetadataHolder metadataHolder = new FlacStreamMetadataHolder(buildStreamMetadata()); long originalSampleRate = metadataHolder.flacStreamMetadata.sampleRate; FlacMetadataReader.readMetadataBlock(input, metadataHolder); assertThat(metadataHolder.flacStreamMetadata).isNotNull(); assertThat(metadataHolder.flacStreamMetadata.sampleRate).isEqualTo(originalSampleRate); Metadata metadata = metadataHolder.flacStreamMetadata.getMetadataCopyWithAppendedEntriesFrom(null); assertThat(metadata).isNotNull(); VorbisComment vorbisComment = (VorbisComment) metadata.get(0); assertThat(vorbisComment.key).isEqualTo("TITLE"); assertThat(vorbisComment.value).isEqualTo("test title"); }
@Test public void readMetadataBlock_pictureBlock_updatesStreamMetadata() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear_with_picture.flac"); input.skipFully(640); FlacStreamMetadataHolder metadataHolder = new FlacStreamMetadataHolder(buildStreamMetadata()); long originalSampleRate = metadataHolder.flacStreamMetadata.sampleRate; FlacMetadataReader.readMetadataBlock(input, metadataHolder); assertThat(metadataHolder.flacStreamMetadata).isNotNull(); assertThat(metadataHolder.flacStreamMetadata.sampleRate).isEqualTo(originalSampleRate); Metadata metadata = metadataHolder.flacStreamMetadata.getMetadataCopyWithAppendedEntriesFrom(null); assertThat(metadata).isNotNull(); PictureFrame pictureFrame = (PictureFrame) metadata.get(0); assertThat(pictureFrame.pictureType).isEqualTo(3); assertThat(pictureFrame.mimeType).isEqualTo("image/png"); assertThat(pictureFrame.description).isEqualTo(""); assertThat(pictureFrame.width).isEqualTo(371); assertThat(pictureFrame.height).isEqualTo(320); assertThat(pictureFrame.depth).isEqualTo(24); assertThat(pictureFrame.colors).isEqualTo(0); assertThat(pictureFrame.pictureData).hasLength(30943); }
@Test public void readMetadataBlock_blockToSkip_updatesReadPosition() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear.flac"); input.skipFully(640); FlacStreamMetadataHolder metadataHolder = new FlacStreamMetadataHolder(buildStreamMetadata()); FlacMetadataReader.readMetadataBlock(input, metadataHolder); assertThat(input.getPosition()).isGreaterThan(new Long(640)); assertThat(input.getPeekPosition()).isEqualTo(input.getPosition()); }
@Test(expected = IllegalArgumentException.class) public void readMetadataBlock_nonStreamInfoBlockWithNullStreamMetadata_throwsException() throws Exception { ExtractorInput input = buildExtractorInput("flac/bear.flac"); input.skipFully(FlacConstants.STREAM_MARKER_SIZE + FlacConstants.STREAM_INFO_BLOCK_SIZE); FlacMetadataReader.readMetadataBlock( input, new FlacStreamMetadataHolder( null)); }