public final class

Id3Peeker

extends java.lang.Object

 java.lang.Object

↳androidx.media3.extractor.Id3Peeker

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-extractor', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-extractor
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-extractor:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

Peeks data from the beginning of an ExtractorInput to determine if there is any ID3 tag.

Summary

Constructors
publicId3Peeker()

Methods
public MetadatapeekId3Data(ExtractorInput input, Id3Decoder.FramePredicate id3FramePredicate)

Peeks ID3 data from the input and parses the first ID3 tag.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public Id3Peeker()

Methods

public Metadata peekId3Data(ExtractorInput input, Id3Decoder.FramePredicate id3FramePredicate)

Peeks ID3 data from the input and parses the first ID3 tag.

Parameters:

input: The ExtractorInput from which data should be peeked.
id3FramePredicate: Determines which ID3 frames are decoded. May be null to decode all frames.

Returns:

The first ID3 tag decoded into a Metadata object. May be null if ID3 tag is not present in the input.

Source

/*
 * Copyright (C) 2018 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 androidx.media3.extractor;

import androidx.annotation.Nullable;
import androidx.media3.common.Metadata;
import androidx.media3.common.util.ParsableByteArray;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.extractor.metadata.id3.Id3Decoder;
import java.io.EOFException;
import java.io.IOException;

/**
 * Peeks data from the beginning of an {@link ExtractorInput} to determine if there is any ID3 tag.
 */
@UnstableApi
public final class Id3Peeker {

  private final ParsableByteArray scratch;

  public Id3Peeker() {
    scratch = new ParsableByteArray(Id3Decoder.ID3_HEADER_LENGTH);
  }

  /**
   * Peeks ID3 data from the input and parses the first ID3 tag.
   *
   * @param input The {@link ExtractorInput} from which data should be peeked.
   * @param id3FramePredicate Determines which ID3 frames are decoded. May be null to decode all
   *     frames.
   * @return The first ID3 tag decoded into a {@link Metadata} object. May be null if ID3 tag is not
   *     present in the input.
   * @throws IOException If an error occurred peeking from the input.
   */
  @Nullable
  public Metadata peekId3Data(
      ExtractorInput input, @Nullable Id3Decoder.FramePredicate id3FramePredicate)
      throws IOException {
    int peekedId3Bytes = 0;
    @Nullable Metadata metadata = null;
    while (true) {
      try {
        input.peekFully(scratch.getData(), /* offset= */ 0, Id3Decoder.ID3_HEADER_LENGTH);
      } catch (EOFException e) {
        // If input has less than ID3_HEADER_LENGTH, ignore the rest.
        break;
      }
      scratch.setPosition(0);
      if (scratch.readUnsignedInt24() != Id3Decoder.ID3_TAG) {
        // Not an ID3 tag.
        break;
      }
      scratch.skipBytes(3); // Skip major version, minor version and flags.
      int framesLength = scratch.readSynchSafeInt();
      int tagLength = Id3Decoder.ID3_HEADER_LENGTH + framesLength;

      if (metadata == null) {
        byte[] id3Data = new byte[tagLength];
        System.arraycopy(scratch.getData(), 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;
  }
}