Search in sources :

Example 16 with FlacStreamMetadata

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

the class FlacStreamMetadataTest method parseEmptyVorbisComments.

@Test
public void parseEmptyVorbisComments() {
    ArrayList<String> commentsList = new ArrayList<>();
    Metadata metadata = new FlacStreamMetadata(/* minBlockSizeSamples= */
    0, /* maxBlockSizeSamples= */
    0, /* minFrameSize= */
    0, /* maxFrameSize= */
    0, /* sampleRate= */
    0, /* channels= */
    0, /* bitsPerSample= */
    0, /* totalSamples= */
    0, commentsList, /* pictureFrames= */
    new ArrayList<>()).getMetadataCopyWithAppendedEntriesFrom(/* other= */
    null);
    assertThat(metadata).isNull();
}
Also used : ArrayList(java.util.ArrayList) Metadata(com.google.android.exoplayer2.metadata.Metadata) Test(org.junit.Test)

Example 17 with FlacStreamMetadata

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

the class FlacStreamMetadataTest method parseVorbisCommentWithEqualsInValue.

@Test
public void parseVorbisCommentWithEqualsInValue() {
    ArrayList<String> commentsList = new ArrayList<>();
    commentsList.add("Title=So=ng");
    Metadata metadata = new FlacStreamMetadata(/* minBlockSizeSamples= */
    0, /* maxBlockSizeSamples= */
    0, /* minFrameSize= */
    0, /* maxFrameSize= */
    0, /* sampleRate= */
    0, /* channels= */
    0, /* bitsPerSample= */
    0, /* totalSamples= */
    0, commentsList, /* pictureFrames= */
    new ArrayList<>()).getMetadataCopyWithAppendedEntriesFrom(/* other= */
    null);
    assertThat(metadata.length()).isEqualTo(1);
    VorbisComment commentFrame = (VorbisComment) metadata.get(0);
    assertThat(commentFrame.key).isEqualTo("Title");
    assertThat(commentFrame.value).isEqualTo("So=ng");
}
Also used : ArrayList(java.util.ArrayList) Metadata(com.google.android.exoplayer2.metadata.Metadata) VorbisComment(com.google.android.exoplayer2.metadata.vorbis.VorbisComment) Test(org.junit.Test)

Example 18 with FlacStreamMetadata

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

the class FlacExtractor method outputSeekMap.

/**
 * Outputs a {@link SeekMap} and returns a {@link FlacBinarySearchSeeker} if one is required to
 * handle seeks.
 */
@Nullable
private static FlacBinarySearchSeeker outputSeekMap(FlacDecoderJni decoderJni, FlacStreamMetadata streamMetadata, long streamLength, ExtractorOutput output, OutputFrameHolder outputFrameHolder) {
    boolean haveSeekTable = decoderJni.getSeekPoints(/* timeUs= */
    0) != null;
    FlacBinarySearchSeeker binarySearchSeeker = null;
    SeekMap seekMap;
    if (haveSeekTable) {
        seekMap = new FlacSeekMap(streamMetadata.getDurationUs(), decoderJni);
    } else if (streamLength != C.LENGTH_UNSET && streamMetadata.totalSamples > 0) {
        long firstFramePosition = decoderJni.getDecodePosition();
        binarySearchSeeker = new FlacBinarySearchSeeker(streamMetadata, firstFramePosition, streamLength, decoderJni, outputFrameHolder);
        seekMap = binarySearchSeeker.getSeekMap();
    } else {
        seekMap = new SeekMap.Unseekable(streamMetadata.getDurationUs());
    }
    output.seekMap(seekMap);
    return binarySearchSeeker;
}
Also used : SeekMap(com.google.android.exoplayer2.extractor.SeekMap) Nullable(androidx.annotation.Nullable)

Example 19 with FlacStreamMetadata

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

the class FlacExtractor method decodeStreamMetadata.

// Requires initialized.
@RequiresNonNull({ "decoderJni", "extractorOutput", "trackOutput" })
// Ensures stream metadata decoded.
@EnsuresNonNull({ "streamMetadata", "outputFrameHolder" })
@SuppressWarnings("nullness:contracts.postcondition")
private void decodeStreamMetadata(ExtractorInput input) throws IOException {
    if (streamMetadataDecoded) {
        return;
    }
    FlacDecoderJni flacDecoderJni = decoderJni;
    FlacStreamMetadata streamMetadata;
    try {
        streamMetadata = flacDecoderJni.decodeStreamMetadata();
    } catch (IOException e) {
        flacDecoderJni.reset(/* newPosition= */
        0);
        input.setRetryPosition(/* position= */
        0, e);
        throw e;
    }
    streamMetadataDecoded = true;
    if (this.streamMetadata == null) {
        this.streamMetadata = streamMetadata;
        outputBuffer.reset(streamMetadata.getMaxDecodedFrameSize());
        outputFrameHolder = new OutputFrameHolder(ByteBuffer.wrap(outputBuffer.getData()));
        binarySearchSeeker = outputSeekMap(flacDecoderJni, streamMetadata, input.getLength(), extractorOutput, outputFrameHolder);
        @Nullable Metadata metadata = streamMetadata.getMetadataCopyWithAppendedEntriesFrom(id3Metadata);
        outputFormat(streamMetadata, metadata, trackOutput);
    }
}
Also used : FlacStreamMetadata(com.google.android.exoplayer2.extractor.FlacStreamMetadata) Metadata(com.google.android.exoplayer2.metadata.Metadata) IOException(java.io.IOException) FlacStreamMetadata(com.google.android.exoplayer2.extractor.FlacStreamMetadata) Nullable(androidx.annotation.Nullable) OutputFrameHolder(com.google.android.exoplayer2.ext.flac.FlacBinarySearchSeeker.OutputFrameHolder) EnsuresNonNull(org.checkerframework.checker.nullness.qual.EnsuresNonNull) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 20 with FlacStreamMetadata

use of com.google.android.exoplayer2.extractor.FlacStreamMetadata 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)

Aggregations

Test (org.junit.Test)20 FlacStreamMetadataHolder (com.google.android.exoplayer2.extractor.FlacMetadataReader.FlacStreamMetadataHolder)16 FakeExtractorInput (com.google.android.exoplayer2.testutil.FakeExtractorInput)16 SampleNumberHolder (com.google.android.exoplayer2.extractor.FlacFrameReader.SampleNumberHolder)9 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)7 Metadata (com.google.android.exoplayer2.metadata.Metadata)5 Nullable (androidx.annotation.Nullable)4 ArrayList (java.util.ArrayList)4 FlacStreamMetadata (com.google.android.exoplayer2.extractor.FlacStreamMetadata)3 VorbisComment (com.google.android.exoplayer2.metadata.vorbis.VorbisComment)3 Format (com.google.android.exoplayer2.Format)2 OutputFrameHolder (com.google.android.exoplayer2.ext.flac.FlacBinarySearchSeeker.OutputFrameHolder)1 SeekTable (com.google.android.exoplayer2.extractor.FlacStreamMetadata.SeekTable)1 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)1 PictureFrame (com.google.android.exoplayer2.metadata.flac.PictureFrame)1 ParsableBitArray (com.google.android.exoplayer2.util.ParsableBitArray)1 ImmutableList (com.google.common.collect.ImmutableList)1 IOException (java.io.IOException)1 List (java.util.List)1 EnsuresNonNull (org.checkerframework.checker.nullness.qual.EnsuresNonNull)1