Search in sources :

Example 31 with ParsableByteArray

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

the class Mp3Extractor method setupSeeker.

/**
   * Returns a {@link Seeker} to seek using metadata read from {@code input}, which should provide
   * data from the start of the first frame in the stream. On returning, the input's position will
   * be set to the start of the first frame of audio.
   *
   * @param input The {@link ExtractorInput} from which to read.
   * @throws IOException Thrown if there was an error reading from the stream. Not expected if the
   *     next two frames were already peeked during synchronization.
   * @throws InterruptedException Thrown if reading from the stream was interrupted. Not expected if
   *     the next two frames were already peeked during synchronization.
   * @return a {@link Seeker}.
   */
private Seeker setupSeeker(ExtractorInput input) throws IOException, InterruptedException {
    // Read the first frame which may contain a Xing or VBRI header with seeking metadata.
    ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
    input.peekFully(frame.data, 0, synchronizedHeader.frameSize);
    long position = input.getPosition();
    long length = input.getLength();
    int headerData = 0;
    Seeker seeker = null;
    // Check if there is a Xing header.
    int xingBase = (synchronizedHeader.version & 1) != 0 ? // MPEG 1
    (synchronizedHeader.channels != 1 ? 36 : 21) : // MPEG 2 or 2.5
    (synchronizedHeader.channels != 1 ? 21 : 13);
    if (frame.limit() >= xingBase + 4) {
        frame.setPosition(xingBase);
        headerData = frame.readInt();
    }
    if (headerData == XING_HEADER || headerData == INFO_HEADER) {
        seeker = XingSeeker.create(synchronizedHeader, frame, position, length);
        if (seeker != null && !gaplessInfoHolder.hasGaplessInfo()) {
            // If there is a Xing header, read gapless playback metadata at a fixed offset.
            input.resetPeekPosition();
            input.advancePeekPosition(xingBase + 141);
            input.peekFully(scratch.data, 0, 3);
            scratch.setPosition(0);
            gaplessInfoHolder.setFromXingHeaderValue(scratch.readUnsignedInt24());
        }
        input.skipFully(synchronizedHeader.frameSize);
    } else if (frame.limit() >= 40) {
        // Check if there is a VBRI header.
        // MPEG audio header (4 bytes) + 32 bytes.
        frame.setPosition(36);
        headerData = frame.readInt();
        if (headerData == VBRI_HEADER) {
            seeker = VbriSeeker.create(synchronizedHeader, frame, position, length);
            input.skipFully(synchronizedHeader.frameSize);
        }
    }
    if (seeker == null || (!seeker.isSeekable() && (flags & FLAG_ENABLE_CONSTANT_BITRATE_SEEKING) != 0)) {
        // Repopulate the synchronized header in case we had to skip an invalid seeking header, which
        // would give an invalid CBR bitrate.
        input.resetPeekPosition();
        input.peekFully(scratch.data, 0, 4);
        scratch.setPosition(0);
        MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
        seeker = new ConstantBitrateSeeker(input.getPosition(), synchronizedHeader.bitrate, length);
    }
    return seeker;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray)

Example 32 with ParsableByteArray

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

the class PsshAtomUtil method parsePsshAtom.

/**
   * Parses the UUID and scheme specific data from a PSSH atom. Version 0 and 1 PSSH atoms are
   * supported.
   *
   * @param atom The atom to parse.
   * @return A pair consisting of the parsed UUID and scheme specific data. Null if the input is
   *     not a valid PSSH atom, or if the PSSH atom has an unsupported version.
   */
private static Pair<UUID, byte[]> parsePsshAtom(byte[] atom) {
    ParsableByteArray atomData = new ParsableByteArray(atom);
    if (atomData.limit() < Atom.FULL_HEADER_SIZE + 16 + /* UUID */
    4) /* DataSize */
    {
        // Data too short.
        return null;
    }
    atomData.setPosition(0);
    int atomSize = atomData.readInt();
    if (atomSize != atomData.bytesLeft() + 4) {
        // Not an atom, or incorrect atom size.
        return null;
    }
    int atomType = atomData.readInt();
    if (atomType != Atom.TYPE_pssh) {
        // Not an atom, or incorrect atom type.
        return null;
    }
    int atomVersion = Atom.parseFullAtomVersion(atomData.readInt());
    if (atomVersion > 1) {
        Log.w(TAG, "Unsupported pssh version: " + atomVersion);
        return null;
    }
    UUID uuid = new UUID(atomData.readLong(), atomData.readLong());
    if (atomVersion == 1) {
        int keyIdCount = atomData.readUnsignedIntToInt();
        atomData.skipBytes(16 * keyIdCount);
    }
    int dataSize = atomData.readUnsignedIntToInt();
    if (dataSize != atomData.bytesLeft()) {
        // Incorrect dataSize.
        return null;
    }
    byte[] data = new byte[dataSize];
    atomData.readBytes(data, 0, dataSize);
    return Pair.create(uuid, data);
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) UUID(java.util.UUID)

Example 33 with ParsableByteArray

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

the class FlacReader method readHeaders.

@Override
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) throws IOException, InterruptedException {
    byte[] data = packet.data;
    if (streamInfo == null) {
        streamInfo = new FlacStreamInfo(data, 17);
        byte[] metadata = Arrays.copyOfRange(data, 9, packet.limit());
        // Set the last metadata block flag, ignore the other blocks
        metadata[4] = (byte) 0x80;
        List<byte[]> initializationData = Collections.singletonList(metadata);
        setupData.format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_FLAC, null, Format.NO_VALUE, streamInfo.bitRate(), streamInfo.channels, streamInfo.sampleRate, initializationData, null, 0, null);
    } else if ((data[0] & 0x7F) == SEEKTABLE_PACKET_TYPE) {
        flacOggSeeker = new FlacOggSeeker();
        flacOggSeeker.parseSeekTable(packet);
    } else if (isAudioPacket(data)) {
        if (flacOggSeeker != null) {
            flacOggSeeker.setFirstFrameOffset(position);
            setupData.oggSeeker = flacOggSeeker;
        }
        return false;
    }
    return true;
}
Also used : FlacStreamInfo(com.google.android.exoplayer2.util.FlacStreamInfo)

Example 34 with ParsableByteArray

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

the class OggExtractor method sniff.

@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
    try {
        OggPageHeader header = new OggPageHeader();
        if (!header.populate(input, true) || (header.type & 0x02) != 0x02) {
            return false;
        }
        int length = Math.min(header.bodySize, MAX_VERIFICATION_BYTES);
        ParsableByteArray scratch = new ParsableByteArray(length);
        input.peekFully(scratch.data, 0, length);
        if (FlacReader.verifyBitstreamType(resetPosition(scratch))) {
            streamReader = new FlacReader();
        } else if (VorbisReader.verifyBitstreamType(resetPosition(scratch))) {
            streamReader = new VorbisReader();
        } else if (OpusReader.verifyBitstreamType(resetPosition(scratch))) {
            streamReader = new OpusReader();
        } else {
            return false;
        }
        return true;
    } catch (ParserException e) {
        return false;
    }
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ParserException(com.google.android.exoplayer2.ParserException)

Example 35 with ParsableByteArray

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

the class FfmpegDecoder method decode.

@Override
public FfmpegDecoderException decode(DecoderInputBuffer inputBuffer, SimpleOutputBuffer outputBuffer, boolean reset) {
    if (reset) {
        nativeContext = ffmpegReset(nativeContext, extraData);
        if (nativeContext == 0) {
            return new FfmpegDecoderException("Error resetting (see logcat).");
        }
    }
    ByteBuffer inputData = inputBuffer.data;
    int inputSize = inputData.limit();
    ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, OUTPUT_BUFFER_SIZE);
    int result = ffmpegDecode(nativeContext, inputData, inputSize, outputData, OUTPUT_BUFFER_SIZE);
    if (result < 0) {
        return new FfmpegDecoderException("Error decoding (see logcat). Code: " + result);
    }
    if (!hasOutputFormat) {
        channelCount = ffmpegGetChannelCount(nativeContext);
        sampleRate = ffmpegGetSampleRate(nativeContext);
        if (sampleRate == 0 && "alac".equals(codecName)) {
            // ALAC decoder did not set the sample rate in earlier versions of FFMPEG.
            // See https://trac.ffmpeg.org/ticket/6096
            ParsableByteArray parsableExtraData = new ParsableByteArray(extraData);
            parsableExtraData.setPosition(extraData.length - 4);
            sampleRate = parsableExtraData.readUnsignedIntToInt();
        }
        hasOutputFormat = true;
    }
    outputBuffer.data.position(0);
    outputBuffer.data.limit(result);
    return null;
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) ByteBuffer(java.nio.ByteBuffer)

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