Search in sources :

Example 81 with ExtractorInput

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

the class DefaultOggSeekerUtilMethodsTest method testSkipToNextPage.

public void testSkipToNextPage() throws Exception {
    FakeExtractorInput extractorInput = TestData.createInput(TestUtil.joinByteArrays(TestUtil.buildTestData(4000, random), new byte[] { 'O', 'g', 'g', 'S' }, TestUtil.buildTestData(4000, random)), false);
    skipToNextPage(extractorInput);
    assertEquals(4000, extractorInput.getPosition());
}
Also used : FakeExtractorInput(com.google.android.exoplayer2.testutil.FakeExtractorInput)

Example 82 with ExtractorInput

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

the class WavExtractor method read.

@Override
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException {
    if (wavHeader == null) {
        wavHeader = WavHeaderReader.peek(input);
        if (wavHeader == null) {
            // Should only happen if the media wasn't sniffed.
            throw new ParserException("Unsupported or unrecognized wav header.");
        }
        Format format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_RAW, null, wavHeader.getBitrate(), MAX_INPUT_SIZE, wavHeader.getNumChannels(), wavHeader.getSampleRateHz(), wavHeader.getEncoding(), null, null, 0, null);
        trackOutput.format(format);
        bytesPerFrame = wavHeader.getBytesPerFrame();
    }
    if (!wavHeader.hasDataBounds()) {
        WavHeaderReader.skipToData(input, wavHeader);
        extractorOutput.seekMap(this);
    }
    int bytesAppended = trackOutput.sampleData(input, MAX_INPUT_SIZE - pendingBytes, true);
    if (bytesAppended != RESULT_END_OF_INPUT) {
        pendingBytes += bytesAppended;
    }
    // Samples must consist of a whole number of frames.
    int pendingFrames = pendingBytes / bytesPerFrame;
    if (pendingFrames > 0) {
        long timeUs = wavHeader.getTimeUs(input.getPosition() - pendingBytes);
        int size = pendingFrames * bytesPerFrame;
        pendingBytes -= size;
        trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, size, pendingBytes, null);
    }
    return bytesAppended == RESULT_END_OF_INPUT ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
Also used : ParserException(com.google.android.exoplayer2.ParserException) Format(com.google.android.exoplayer2.Format)

Example 83 with ExtractorInput

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

the class WavHeaderReader method skipToData.

/**
   * Skips to the data in the given WAV input stream and returns its data size. After calling, the
   * input stream's position will point to the start of sample data in the WAV.
   * <p>
   * If an exception is thrown, the input position will be left pointing to a chunk header.
   *
   * @param input Input stream to skip to the data chunk in. Its peek position must be pointing to
   *     a valid chunk header.
   * @param wavHeader WAV header to populate with data bounds.
   * @throws ParserException If an error occurs parsing chunks.
   * @throws IOException If reading from the input fails.
   * @throws InterruptedException If interrupted while reading from input.
   */
public static void skipToData(ExtractorInput input, WavHeader wavHeader) throws IOException, InterruptedException {
    Assertions.checkNotNull(input);
    Assertions.checkNotNull(wavHeader);
    // Make sure the peek position is set to the read position before we peek the first header.
    input.resetPeekPosition();
    ParsableByteArray scratch = new ParsableByteArray(ChunkHeader.SIZE_IN_BYTES);
    // Skip all chunks until we hit the data header.
    ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
    while (chunkHeader.id != Util.getIntegerCodeForString("data")) {
        Log.w(TAG, "Ignoring unknown WAV chunk: " + chunkHeader.id);
        long bytesToSkip = ChunkHeader.SIZE_IN_BYTES + chunkHeader.size;
        // Override size of RIFF chunk, since it describes its size as the entire file.
        if (chunkHeader.id == Util.getIntegerCodeForString("RIFF")) {
            bytesToSkip = ChunkHeader.SIZE_IN_BYTES + 4;
        }
        if (bytesToSkip > Integer.MAX_VALUE) {
            throw new ParserException("Chunk is too large (~2GB+) to skip; id: " + chunkHeader.id);
        }
        input.skipFully((int) bytesToSkip);
        chunkHeader = ChunkHeader.peek(input, scratch);
    }
    // Skip past the "data" header.
    input.skipFully(ChunkHeader.SIZE_IN_BYTES);
    wavHeader.setDataBounds(input.getPosition(), chunkHeader.size);
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ParserException(com.google.android.exoplayer2.ParserException)

Example 84 with ExtractorInput

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

the class RawCcExtractor method parseTimestampAndSampleCount.

private boolean parseTimestampAndSampleCount(ExtractorInput input) throws IOException, InterruptedException {
    dataScratch.reset();
    if (version == 0) {
        if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V0 + 1, true)) {
            return false;
        }
        // version 0 timestamps are 45kHz, so we need to convert them into us
        timestampUs = dataScratch.readUnsignedInt() * 1000 / 45;
    } else if (version == 1) {
        if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V1 + 1, true)) {
            return false;
        }
        timestampUs = dataScratch.readLong();
    } else {
        throw new ParserException("Unsupported version number: " + version);
    }
    remainingSampleCount = dataScratch.readUnsignedByte();
    sampleBytesWritten = 0;
    return true;
}
Also used : ParserException(com.google.android.exoplayer2.ParserException)

Example 85 with ExtractorInput

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

the class AdtsExtractor method sniff.

@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
    // Skip any ID3 headers.
    ParsableByteArray scratch = new ParsableByteArray(10);
    ParsableBitArray scratchBits = new ParsableBitArray(scratch.data);
    int startPosition = 0;
    while (true) {
        input.peekFully(scratch.data, 0, 10);
        scratch.setPosition(0);
        if (scratch.readUnsignedInt24() != ID3_TAG) {
            break;
        }
        scratch.skipBytes(3);
        int length = scratch.readSynchSafeInt();
        startPosition += 10 + length;
        input.advancePeekPosition(length);
    }
    input.resetPeekPosition();
    input.advancePeekPosition(startPosition);
    // Try to find four or more consecutive AAC audio frames, exceeding the MPEG TS packet size.
    int headerPosition = startPosition;
    int validFramesSize = 0;
    int validFramesCount = 0;
    while (true) {
        input.peekFully(scratch.data, 0, 2);
        scratch.setPosition(0);
        int syncBytes = scratch.readUnsignedShort();
        if ((syncBytes & 0xFFF6) != 0xFFF0) {
            validFramesCount = 0;
            validFramesSize = 0;
            input.resetPeekPosition();
            if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
                return false;
            }
            input.advancePeekPosition(headerPosition);
        } else {
            if (++validFramesCount >= 4 && validFramesSize > 188) {
                return true;
            }
            // Skip the frame.
            input.peekFully(scratch.data, 0, 4);
            scratchBits.setPosition(14);
            int frameSize = scratchBits.readBits(13);
            // Either the stream is malformed OR we're not parsing an ADTS stream.
            if (frameSize <= 6) {
                return false;
            }
            input.advancePeekPosition(frameSize - 6);
            validFramesSize += frameSize;
        }
    }
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ParsableBitArray(com.google.android.exoplayer2.util.ParsableBitArray)

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