Search in sources :

Example 6 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class MpegAudioReader method readHeaderRemainder.

/**
   * Attempts to read the remaining two bytes of the frame header.
   * <p>
   * If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
   * the media format is output if this has not previously occurred, the four header bytes are
   * output as sample data, and the position of the source is advanced to the byte that immediately
   * follows the header.
   * <p>
   * If a frame header is read in full but cannot be parsed then the state is changed to
   * {@link #STATE_READING_HEADER}.
   * <p>
   * If a frame header is not read in full then the position of the source is advanced to the limit,
   * and the method should be called again with the next source to continue the read.
   *
   * @param source The source from which to read.
   */
private void readHeaderRemainder(ParsableByteArray source) {
    int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
    source.readBytes(headerScratch.data, frameBytesRead, bytesToRead);
    frameBytesRead += bytesToRead;
    if (frameBytesRead < HEADER_SIZE) {
        // We haven't read the whole header yet.
        return;
    }
    headerScratch.setPosition(0);
    boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header);
    if (!parsedHeader) {
        // We thought we'd located a frame header, but we hadn't.
        frameBytesRead = 0;
        state = STATE_READING_HEADER;
        return;
    }
    frameSize = header.frameSize;
    if (!hasOutputFormat) {
        frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
        Format format = Format.createAudioSampleFormat(formatId, header.mimeType, null, Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate, null, null, 0, language);
        output.format(format);
        hasOutputFormat = true;
    }
    headerScratch.setPosition(0);
    output.sampleData(headerScratch, HEADER_SIZE);
    state = STATE_READING_FRAME;
}
Also used : Format(com.google.android.exoplayer2.Format)

Example 7 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class SeiReader method createTracks.

public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) {
    for (int i = 0; i < outputs.length; i++) {
        idGenerator.generateNewId();
        TrackOutput output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_TEXT);
        Format channelFormat = closedCaptionFormats.get(i);
        String channelMimeType = channelFormat.sampleMimeType;
        Assertions.checkArgument(MimeTypes.APPLICATION_CEA608.equals(channelMimeType) || MimeTypes.APPLICATION_CEA708.equals(channelMimeType), "Invalid closed caption mime type provided: " + channelMimeType);
        output.format(Format.createTextSampleFormat(idGenerator.getFormatId(), channelMimeType, null, Format.NO_VALUE, channelFormat.selectionFlags, channelFormat.language, channelFormat.accessibilityChannel, null));
        outputs[i] = output;
    }
}
Also used : Format(com.google.android.exoplayer2.Format) TrackOutput(com.google.android.exoplayer2.extractor.TrackOutput)

Example 8 with Format

use of com.google.android.exoplayer2.Format 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 9 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class Mp4Extractor method processMoovAtom.

/**
   * Updates the stored track metadata to reflect the contents of the specified moov atom.
   */
private void processMoovAtom(ContainerAtom moov) throws ParserException {
    long durationUs = C.TIME_UNSET;
    List<Mp4Track> tracks = new ArrayList<>();
    long earliestSampleOffset = Long.MAX_VALUE;
    Metadata metadata = null;
    GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder();
    Atom.LeafAtom udta = moov.getLeafAtomOfType(Atom.TYPE_udta);
    if (udta != null) {
        metadata = AtomParsers.parseUdta(udta, isQuickTime);
        if (metadata != null) {
            gaplessInfoHolder.setFromMetadata(metadata);
        }
    }
    for (int i = 0; i < moov.containerChildren.size(); i++) {
        Atom.ContainerAtom atom = moov.containerChildren.get(i);
        if (atom.type != Atom.TYPE_trak) {
            continue;
        }
        Track track = AtomParsers.parseTrak(atom, moov.getLeafAtomOfType(Atom.TYPE_mvhd), C.TIME_UNSET, null, isQuickTime);
        if (track == null) {
            continue;
        }
        Atom.ContainerAtom stblAtom = atom.getContainerAtomOfType(Atom.TYPE_mdia).getContainerAtomOfType(Atom.TYPE_minf).getContainerAtomOfType(Atom.TYPE_stbl);
        TrackSampleTable trackSampleTable = AtomParsers.parseStbl(track, stblAtom, gaplessInfoHolder);
        if (trackSampleTable.sampleCount == 0) {
            continue;
        }
        Mp4Track mp4Track = new Mp4Track(track, trackSampleTable, extractorOutput.track(i, track.type));
        // Each sample has up to three bytes of overhead for the start code that replaces its length.
        // Allow ten source samples per output sample, like the platform extractor.
        int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
        Format format = track.format.copyWithMaxInputSize(maxInputSize);
        if (track.type == C.TRACK_TYPE_AUDIO) {
            if (gaplessInfoHolder.hasGaplessInfo()) {
                format = format.copyWithGaplessInfo(gaplessInfoHolder.encoderDelay, gaplessInfoHolder.encoderPadding);
            }
            if (metadata != null) {
                format = format.copyWithMetadata(metadata);
            }
        }
        mp4Track.trackOutput.format(format);
        durationUs = Math.max(durationUs, track.durationUs);
        tracks.add(mp4Track);
        long firstSampleOffset = trackSampleTable.offsets[0];
        if (firstSampleOffset < earliestSampleOffset) {
            earliestSampleOffset = firstSampleOffset;
        }
    }
    this.durationUs = durationUs;
    this.tracks = tracks.toArray(new Mp4Track[tracks.size()]);
    extractorOutput.endTracks();
    extractorOutput.seekMap(this);
}
Also used : ArrayList(java.util.ArrayList) Metadata(com.google.android.exoplayer2.metadata.Metadata) ContainerAtom(com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom) ContainerAtom(com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom) Format(com.google.android.exoplayer2.Format) GaplessInfoHolder(com.google.android.exoplayer2.extractor.GaplessInfoHolder)

Example 10 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class AudioTagPayloadReader method parseHeader.

@Override
protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatException {
    if (!hasParsedAudioDataHeader) {
        int header = data.readUnsignedByte();
        audioFormat = (header >> 4) & 0x0F;
        // TODO: Add support for MP3.
        if (audioFormat == AUDIO_FORMAT_ALAW || audioFormat == AUDIO_FORMAT_ULAW) {
            String type = audioFormat == AUDIO_FORMAT_ALAW ? MimeTypes.AUDIO_ALAW : MimeTypes.AUDIO_ULAW;
            int pcmEncoding = (header & 0x01) == 1 ? C.ENCODING_PCM_16BIT : C.ENCODING_PCM_8BIT;
            Format format = Format.createAudioSampleFormat(null, type, null, Format.NO_VALUE, Format.NO_VALUE, 1, 8000, pcmEncoding, null, null, 0, null);
            output.format(format);
            hasOutputFormat = true;
        } else if (audioFormat != AUDIO_FORMAT_AAC) {
            throw new UnsupportedFormatException("Audio format not supported: " + audioFormat);
        }
        hasParsedAudioDataHeader = true;
    } else {
        // Skip header if it was parsed previously.
        data.skipBytes(1);
    }
    return true;
}
Also used : Format(com.google.android.exoplayer2.Format)

Aggregations

Format (com.google.android.exoplayer2.Format)44 Point (android.graphics.Point)8 ArrayList (java.util.ArrayList)8 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)7 DataSpec (com.google.android.exoplayer2.upstream.DataSpec)5 SuppressLint (android.annotation.SuppressLint)4 MediaFormat (android.media.MediaFormat)4 ParserException (com.google.android.exoplayer2.ParserException)4 DrmInitData (com.google.android.exoplayer2.drm.DrmInitData)4 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)4 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)3 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)3 Representation (com.google.android.exoplayer2.source.dash.manifest.Representation)3 SchemeData (com.google.android.exoplayer2.drm.DrmInitData.SchemeData)2 MediaCodecInfo (com.google.android.exoplayer2.mediacodec.MediaCodecInfo)2 Metadata (com.google.android.exoplayer2.metadata.Metadata)2 ContainerMediaChunk (com.google.android.exoplayer2.source.chunk.ContainerMediaChunk)2 AdaptationSet (com.google.android.exoplayer2.source.dash.manifest.AdaptationSet)2 RangedUri (com.google.android.exoplayer2.source.dash.manifest.RangedUri)2 SingleSegmentBase (com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase)2