Id3Peeker { @Nullable public Metadata peekId3Data( ExtractorInput input, @Nullable Id3Decoder.FramePredicate id3FramePredicate) throws IOException, InterruptedException { int peekedId3Bytes = 0; Metadata metadata = null; while (true) { try { input.peekFully(scratch.data, 0, Id3Decoder.ID3_HEADER_LENGTH); } catch (EOFException e) { break; } scratch.setPosition(0); if (scratch.readUnsignedInt24() != Id3Decoder.ID3_TAG) { break; } scratch.skipBytes(3); int framesLength = scratch.readSynchSafeInt(); int tagLength = Id3Decoder.ID3_HEADER_LENGTH + framesLength; if (metadata == null) { byte[] id3Data = new byte[tagLength]; System.arraycopy(scratch.data, 0, id3Data, 0, Id3Decoder.ID3_HEADER_LENGTH); input.peekFully(id3Data, Id3Decoder.ID3_HEADER_LENGTH, framesLength); metadata = new Id3Decoder(id3FramePredicate).decode(id3Data, tagLength); } else { input.advancePeekPosition(framesLength); } peekedId3Bytes += tagLength; } input.resetPeekPosition(); input.advancePeekPosition(peekedId3Bytes); return metadata; } Id3Peeker(); @Nullable Metadata peekId3Data(
      ExtractorInput input, @Nullable Id3Decoder.FramePredicate id3FramePredicate);  }
@Test public void testPeekId3Data_returnNull_ifId3TagNotPresentAtBeginningOfInput() throws IOException, InterruptedException { Id3Peeker id3Peeker = new Id3Peeker(); FakeExtractorInput input = new FakeExtractorInput.Builder() .setData(new byte[] {1, 'I', 'D', '3', 2, 3, 4, 5, 6, 7, 8, 9, 10}) .build(); Metadata metadata = id3Peeker.peekId3Data(input, null); assertThat(metadata).isNull(); }
@Test public void testPeekId3Data_returnId3Tag_ifId3TagPresent() throws IOException, InterruptedException { Id3Peeker id3Peeker = new Id3Peeker(); byte[] rawId3 = Id3DecoderTest.buildSingleFrameTag( "APIC", new byte[] { 3, 105, 109, 97, 103, 101, 47, 106, 112, 101, 103, 0, 16, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }); FakeExtractorInput input = new FakeExtractorInput.Builder().setData(rawId3).build(); Metadata metadata = id3Peeker.peekId3Data(input, null); assertThat(metadata.length()).isEqualTo(1); ApicFrame apicFrame = (ApicFrame) metadata.get(0); assertThat(apicFrame.mimeType).isEqualTo("image/jpeg"); assertThat(apicFrame.pictureType).isEqualTo(16); assertThat(apicFrame.description).isEqualTo("Hello World"); assertThat(apicFrame.pictureData).hasLength(10); assertThat(apicFrame.pictureData).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}); }
@Test public void testPeekId3Data_returnId3TagAccordingToGivenPredicate_ifId3TagPresent() throws IOException, InterruptedException { Id3Peeker id3Peeker = new Id3Peeker(); byte[] rawId3 = Id3DecoderTest.buildMultiFramesTag( new Id3DecoderTest.FrameSpec( "COMM", new byte[] { 3, 101, 110, 103, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 0, 116, 101, 120, 116, 0 }), new Id3DecoderTest.FrameSpec( "APIC", new byte[] { 3, 105, 109, 97, 103, 101, 47, 106, 112, 101, 103, 0, 16, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 })); FakeExtractorInput input = new FakeExtractorInput.Builder().setData(rawId3).build(); Metadata metadata = id3Peeker.peekId3Data( input, (majorVersion, id0, id1, id2, id3) -> id0 == 'C' && id1 == 'O' && id2 == 'M' && id3 == 'M'); assertThat(metadata.length()).isEqualTo(1); CommentFrame commentFrame = (CommentFrame) metadata.get(0); assertThat(commentFrame.language).isEqualTo("eng"); assertThat(commentFrame.description).isEqualTo("description"); assertThat(commentFrame.text).isEqualTo("text"); }