Search in sources :

Example 91 with ExtractorInput

use of com.google.android.exoplayer2.extractor.ExtractorInput in project ExoPlayer by google.

the class FlacMetadataReader method readStreamMarker.

/**
 * Reads the FLAC stream marker.
 *
 * @param input Input stream to read the stream marker from.
 * @throws ParserException If an error occurs parsing the stream marker. In this case, the
 *     position of {@code input} is advanced by {@link FlacConstants#STREAM_MARKER_SIZE} bytes.
 * @throws IOException If reading from the input fails. In this case, the position is left
 *     unchanged.
 */
public static void readStreamMarker(ExtractorInput input) throws IOException {
    ParsableByteArray scratch = new ParsableByteArray(FlacConstants.STREAM_MARKER_SIZE);
    input.readFully(scratch.getData(), 0, FlacConstants.STREAM_MARKER_SIZE);
    if (scratch.readUnsignedInt() != STREAM_MARKER) {
        throw ParserException.createForMalformedContainer("Failed to read FLAC stream marker.", /* cause= */
        null);
    }
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray)

Example 92 with ExtractorInput

use of com.google.android.exoplayer2.extractor.ExtractorInput 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;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) PictureFrame(com.google.android.exoplayer2.metadata.flac.PictureFrame) Nullable(androidx.annotation.Nullable) ParsableBitArray(com.google.android.exoplayer2.util.ParsableBitArray)

Example 93 with ExtractorInput

use of com.google.android.exoplayer2.extractor.ExtractorInput in project ExoPlayer by google.

the class FlacMetadataReader method readId3Metadata.

/**
 * Reads ID3 Data.
 *
 * <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 ID3 data from.
 * @param parseData Whether to parse the ID3 frames.
 * @return The parsed ID3 data, or {@code null} if there is no such data or if {@code parseData}
 *     is {@code false}.
 * @throws IOException If reading from the input fails. In this case, the read position is left
 *     unchanged and there is no guarantee on the peek position.
 */
@Nullable
public static Metadata readId3Metadata(ExtractorInput input, boolean parseData) throws IOException {
    input.resetPeekPosition();
    long startingPeekPosition = input.getPeekPosition();
    @Nullable Metadata id3Metadata = peekId3Metadata(input, parseData);
    int peekedId3Bytes = (int) (input.getPeekPosition() - startingPeekPosition);
    input.skipFully(peekedId3Bytes);
    return id3Metadata;
}
Also used : Metadata(com.google.android.exoplayer2.metadata.Metadata) Nullable(androidx.annotation.Nullable) Nullable(androidx.annotation.Nullable)

Example 94 with ExtractorInput

use of com.google.android.exoplayer2.extractor.ExtractorInput in project ExoPlayer by google.

the class FlacMetadataReader method readVorbisCommentMetadataBlock.

private static List<String> readVorbisCommentMetadataBlock(ExtractorInput input, int length) throws IOException {
    ParsableByteArray scratch = new ParsableByteArray(length);
    input.readFully(scratch.getData(), 0, length);
    scratch.skipBytes(FlacConstants.METADATA_BLOCK_HEADER_SIZE);
    CommentHeader commentHeader = VorbisUtil.readVorbisCommentHeader(scratch, /* hasMetadataHeader= */
    false, /* hasFramingBit= */
    false);
    return Arrays.asList(commentHeader.comments);
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) CommentHeader(com.google.android.exoplayer2.extractor.VorbisUtil.CommentHeader)

Example 95 with ExtractorInput

use of com.google.android.exoplayer2.extractor.ExtractorInput in project ExoPlayer by google.

the class FlacMetadataReader method getFrameStartMarker.

/**
 * Returns the frame start marker, consisting of the 2 first bytes of the first frame.
 *
 * <p>The read position of {@code input} is left unchanged and the peek position is aligned with
 * the read position.
 *
 * @param input Input stream to get the start marker from (starting from the read position).
 * @return The frame start marker (which must be the same for all the frames in the stream).
 * @throws ParserException If an error occurs parsing the frame start marker.
 * @throws IOException If peeking from the input fails.
 */
public static int getFrameStartMarker(ExtractorInput input) throws IOException {
    input.resetPeekPosition();
    ParsableByteArray scratch = new ParsableByteArray(2);
    input.peekFully(scratch.getData(), 0, 2);
    int frameStartMarker = scratch.readUnsignedShort();
    int syncCode = frameStartMarker >> 2;
    if (syncCode != SYNC_CODE) {
        input.resetPeekPosition();
        throw ParserException.createForMalformedContainer("First frame does not start with sync code.", /* cause= */
        null);
    }
    input.resetPeekPosition();
    return frameStartMarker;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray)

Aggregations

FakeExtractorInput (com.google.android.exoplayer2.testutil.FakeExtractorInput)85 Test (org.junit.Test)71 ExtractorInput (com.google.android.exoplayer2.extractor.ExtractorInput)53 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)39 FlacStreamMetadataHolder (com.google.android.exoplayer2.extractor.FlacMetadataReader.FlacStreamMetadataHolder)20 DataSpec (com.google.android.exoplayer2.upstream.DataSpec)17 DefaultExtractorInput (com.google.android.exoplayer2.extractor.DefaultExtractorInput)16 Nullable (androidx.annotation.Nullable)15 Metadata (com.google.android.exoplayer2.metadata.Metadata)13 SampleNumberHolder (com.google.android.exoplayer2.extractor.FlacFrameReader.SampleNumberHolder)9 FakeDataSource (com.google.android.exoplayer2.testutil.FakeDataSource)9 EOFException (java.io.EOFException)8 SeekPoint (com.google.android.exoplayer2.extractor.SeekPoint)7 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)7 ParserException (com.google.android.exoplayer2.ParserException)5 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)5 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)5 IOException (java.io.IOException)5 PositionHolder (com.google.android.exoplayer2.extractor.PositionHolder)3 Id3Decoder (com.google.android.exoplayer2.metadata.id3.Id3Decoder)3