Search in sources :

Example 6 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class WavHeaderReader method peek.

/**
   * Peeks and returns a {@code WavHeader}.
   *
   * @param input Input stream to peek the WAV header from.
   * @throws ParserException If the input file is an incorrect RIFF WAV.
   * @throws IOException If peeking from the input fails.
   * @throws InterruptedException If interrupted while peeking from input.
   * @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a
   *     supported WAV format.
   */
public static WavHeader peek(ExtractorInput input) throws IOException, InterruptedException {
    Assertions.checkNotNull(input);
    // Allocate a scratch buffer large enough to store the format chunk.
    ParsableByteArray scratch = new ParsableByteArray(16);
    // Attempt to read the RIFF chunk.
    ChunkHeader chunkHeader = ChunkHeader.peek(input, scratch);
    if (chunkHeader.id != Util.getIntegerCodeForString("RIFF")) {
        return null;
    }
    input.peekFully(scratch.data, 0, 4);
    scratch.setPosition(0);
    int riffFormat = scratch.readInt();
    if (riffFormat != Util.getIntegerCodeForString("WAVE")) {
        Log.e(TAG, "Unsupported RIFF format: " + riffFormat);
        return null;
    }
    // Skip chunks until we find the format chunk.
    chunkHeader = ChunkHeader.peek(input, scratch);
    while (chunkHeader.id != Util.getIntegerCodeForString("fmt ")) {
        input.advancePeekPosition((int) chunkHeader.size);
        chunkHeader = ChunkHeader.peek(input, scratch);
    }
    Assertions.checkState(chunkHeader.size >= 16);
    input.peekFully(scratch.data, 0, 16);
    scratch.setPosition(0);
    int type = scratch.readLittleEndianUnsignedShort();
    int numChannels = scratch.readLittleEndianUnsignedShort();
    int sampleRateHz = scratch.readLittleEndianUnsignedIntToInt();
    int averageBytesPerSecond = scratch.readLittleEndianUnsignedIntToInt();
    int blockAlignment = scratch.readLittleEndianUnsignedShort();
    int bitsPerSample = scratch.readLittleEndianUnsignedShort();
    int expectedBlockAlignment = numChannels * bitsPerSample / 8;
    if (blockAlignment != expectedBlockAlignment) {
        throw new ParserException("Expected block alignment: " + expectedBlockAlignment + "; got: " + blockAlignment);
    }
    @C.PcmEncoding int encoding = Util.getPcmEncoding(bitsPerSample);
    if (encoding == C.ENCODING_INVALID) {
        Log.e(TAG, "Unsupported WAV bit depth: " + bitsPerSample);
        return null;
    }
    if (type != TYPE_PCM && type != TYPE_WAVE_FORMAT_EXTENSIBLE) {
        Log.e(TAG, "Unsupported WAV format type: " + type);
        return null;
    }
    // If present, skip extensionSize, validBitsPerSample, channelMask, subFormatGuid, ...
    input.advancePeekPosition((int) chunkHeader.size - 16);
    return new WavHeader(numChannels, sampleRateHz, averageBytesPerSecond, blockAlignment, bitsPerSample, encoding);
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ParserException(com.google.android.exoplayer2.ParserException)

Example 7 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class MetadataUtil method parseUint8Attribute.

private static Id3Frame parseUint8Attribute(int type, String id, ParsableByteArray data, boolean isTextInformationFrame, boolean isBoolean) {
    int value = parseUint8AttributeValue(data);
    if (isBoolean) {
        value = Math.min(1, value);
    }
    if (value >= 0) {
        return isTextInformationFrame ? new TextInformationFrame(id, null, Integer.toString(value)) : new CommentFrame(LANGUAGE_UNDEFINED, id, Integer.toString(value));
    }
    Log.w(TAG, "Failed to parse uint8 attribute: " + Atom.getAtomTypeString(type));
    return null;
}
Also used : CommentFrame(com.google.android.exoplayer2.metadata.id3.CommentFrame) TextInformationFrame(com.google.android.exoplayer2.metadata.id3.TextInformationFrame)

Example 8 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class Mp4Extractor method readAtomHeader.

private boolean readAtomHeader(ExtractorInput input) throws IOException, InterruptedException {
    if (atomHeaderBytesRead == 0) {
        // Read the standard length atom header.
        if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
            return false;
        }
        atomHeaderBytesRead = Atom.HEADER_SIZE;
        atomHeader.setPosition(0);
        atomSize = atomHeader.readUnsignedInt();
        atomType = atomHeader.readInt();
    }
    if (atomSize == Atom.LONG_SIZE_PREFIX) {
        // Read the extended atom size.
        int headerBytesRemaining = Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE;
        input.readFully(atomHeader.data, Atom.HEADER_SIZE, headerBytesRemaining);
        atomHeaderBytesRead += headerBytesRemaining;
        atomSize = atomHeader.readUnsignedLongToLong();
    }
    if (shouldParseContainerAtom(atomType)) {
        long endPosition = input.getPosition() + atomSize - atomHeaderBytesRead;
        containerAtoms.add(new ContainerAtom(atomType, endPosition));
        if (atomSize == atomHeaderBytesRead) {
            processAtomEnded(endPosition);
        } else {
            // Start reading the first child atom.
            enterReadingAtomHeaderState();
        }
    } else if (shouldParseLeafAtom(atomType)) {
        // We don't support parsing of leaf atoms that define extended atom sizes, or that have
        // lengths greater than Integer.MAX_VALUE.
        Assertions.checkState(atomHeaderBytesRead == Atom.HEADER_SIZE);
        Assertions.checkState(atomSize <= Integer.MAX_VALUE);
        atomData = new ParsableByteArray((int) atomSize);
        System.arraycopy(atomHeader.data, 0, atomData.data, 0, Atom.HEADER_SIZE);
        parserState = STATE_READING_ATOM_PAYLOAD;
    } else {
        atomData = null;
        parserState = STATE_READING_ATOM_PAYLOAD;
    }
    return true;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ContainerAtom(com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom)

Example 9 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class Sniffer method sniffInternal.

private static boolean sniffInternal(ExtractorInput input, boolean fragmented) throws IOException, InterruptedException {
    long inputLength = input.getLength();
    int bytesToSearch = (int) (inputLength == C.LENGTH_UNSET || inputLength > SEARCH_LENGTH ? SEARCH_LENGTH : inputLength);
    ParsableByteArray buffer = new ParsableByteArray(64);
    int bytesSearched = 0;
    boolean foundGoodFileType = false;
    boolean isFragmented = false;
    while (bytesSearched < bytesToSearch) {
        // Read an atom header.
        int headerSize = Atom.HEADER_SIZE;
        buffer.reset(headerSize);
        input.peekFully(buffer.data, 0, headerSize);
        long atomSize = buffer.readUnsignedInt();
        int atomType = buffer.readInt();
        if (atomSize == Atom.LONG_SIZE_PREFIX) {
            headerSize = Atom.LONG_HEADER_SIZE;
            input.peekFully(buffer.data, Atom.HEADER_SIZE, Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE);
            buffer.setLimit(Atom.LONG_HEADER_SIZE);
            atomSize = buffer.readUnsignedLongToLong();
        }
        if (atomSize < headerSize) {
            // The file is invalid because the atom size is too small for its header.
            return false;
        }
        bytesSearched += headerSize;
        if (atomType == Atom.TYPE_moov) {
            // Check for an mvex atom inside the moov atom to identify whether the file is fragmented.
            continue;
        }
        if (atomType == Atom.TYPE_moof || atomType == Atom.TYPE_mvex) {
            // The movie is fragmented. Stop searching as we must have read any ftyp atom already.
            isFragmented = true;
            break;
        }
        if (bytesSearched + atomSize - headerSize >= bytesToSearch) {
            // Stop searching as peeking this atom would exceed the search limit.
            break;
        }
        int atomDataSize = (int) (atomSize - headerSize);
        bytesSearched += atomDataSize;
        if (atomType == Atom.TYPE_ftyp) {
            // Parse the atom and check the file type/brand is compatible with the extractors.
            if (atomDataSize < 8) {
                return false;
            }
            buffer.reset(atomDataSize);
            input.peekFully(buffer.data, 0, atomDataSize);
            int brandsCount = atomDataSize / 4;
            for (int i = 0; i < brandsCount; i++) {
                if (i == 1) {
                    // This index refers to the minorVersion, not a brand, so skip it.
                    buffer.skipBytes(4);
                } else if (isCompatibleBrand(buffer.readInt())) {
                    foundGoodFileType = true;
                    break;
                }
            }
            if (!foundGoodFileType) {
                // The types were not compatible and there is only one ftyp atom, so reject the file.
                return false;
            }
        } else if (atomDataSize != 0) {
            // Skip the atom.
            input.advancePeekPosition(atomDataSize);
        }
    }
    return foundGoodFileType && fragmented == isFragmented;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray)

Example 10 with ParsableByteArray

use of com.google.android.exoplayer2.util.ParsableByteArray in project ExoPlayer by google.

the class TrackFragment method initEncryptionData.

/**
   * Configures the fragment to be one that defines encryption data of the specified length.
   * <p>
   * {@link #definesEncryptionData} is set to true, {@link #sampleEncryptionDataLength} is set to
   * the specified length, and {@link #sampleEncryptionData} is resized if necessary such that it
   * is at least this length.
   *
   * @param length The length in bytes of the encryption data.
   */
public void initEncryptionData(int length) {
    if (sampleEncryptionData == null || sampleEncryptionData.limit() < length) {
        sampleEncryptionData = new ParsableByteArray(length);
    }
    sampleEncryptionDataLength = length;
    definesEncryptionData = true;
    sampleEncryptionDataNeedsFill = true;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray)

Aggregations

ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)48 ParserException (com.google.android.exoplayer2.ParserException)11 Format (com.google.android.exoplayer2.Format)6 ArrayList (java.util.ArrayList)4 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)3 Metadata (com.google.android.exoplayer2.metadata.Metadata)3 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)2 ContainerAtom (com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom)2 FlacStreamInfo (com.google.android.exoplayer2.util.FlacStreamInfo)2 AvcConfig (com.google.android.exoplayer2.video.AvcConfig)2 ByteBuffer (java.nio.ByteBuffer)2 Matcher (java.util.regex.Matcher)2 Spanned (android.text.Spanned)1 ChunkIndex (com.google.android.exoplayer2.extractor.ChunkIndex)1 MpegAudioHeader (com.google.android.exoplayer2.extractor.MpegAudioHeader)1 LeafAtom (com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom)1 TrackIdGenerator (com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator)1 CommentFrame (com.google.android.exoplayer2.metadata.id3.CommentFrame)1 TextInformationFrame (com.google.android.exoplayer2.metadata.id3.TextInformationFrame)1 FakeExtractorOutput (com.google.android.exoplayer2.testutil.FakeExtractorOutput)1