Search in sources :

Example 1 with ContainerAtom

use of androidx.media3.extractor.mp4.Atom.ContainerAtom in project ExoPlayer by google.

the class FragmentedMp4Extractor method parseTraf.

/**
   * Parses a traf atom (defined in 14496-12).
   */
private static void parseTraf(ContainerAtom traf, SparseArray<TrackBundle> trackBundleArray, @Flags int flags, byte[] extendedTypeScratch) throws ParserException {
    LeafAtom tfhd = traf.getLeafAtomOfType(Atom.TYPE_tfhd);
    TrackBundle trackBundle = parseTfhd(tfhd.data, trackBundleArray, flags);
    if (trackBundle == null) {
        return;
    }
    TrackFragment fragment = trackBundle.fragment;
    long decodeTime = fragment.nextFragmentDecodeTime;
    trackBundle.reset();
    LeafAtom tfdtAtom = traf.getLeafAtomOfType(Atom.TYPE_tfdt);
    if (tfdtAtom != null && (flags & FLAG_WORKAROUND_IGNORE_TFDT_BOX) == 0) {
        decodeTime = parseTfdt(traf.getLeafAtomOfType(Atom.TYPE_tfdt).data);
    }
    parseTruns(traf, trackBundle, decodeTime, flags);
    LeafAtom saiz = traf.getLeafAtomOfType(Atom.TYPE_saiz);
    if (saiz != null) {
        TrackEncryptionBox trackEncryptionBox = trackBundle.track.sampleDescriptionEncryptionBoxes[fragment.header.sampleDescriptionIndex];
        parseSaiz(trackEncryptionBox, saiz.data, fragment);
    }
    LeafAtom saio = traf.getLeafAtomOfType(Atom.TYPE_saio);
    if (saio != null) {
        parseSaio(saio.data, fragment);
    }
    LeafAtom senc = traf.getLeafAtomOfType(Atom.TYPE_senc);
    if (senc != null) {
        parseSenc(senc.data, fragment);
    }
    LeafAtom sbgp = traf.getLeafAtomOfType(Atom.TYPE_sbgp);
    LeafAtom sgpd = traf.getLeafAtomOfType(Atom.TYPE_sgpd);
    if (sbgp != null && sgpd != null) {
        parseSgpd(sbgp.data, sgpd.data, fragment);
    }
    int leafChildrenSize = traf.leafChildren.size();
    for (int i = 0; i < leafChildrenSize; i++) {
        LeafAtom atom = traf.leafChildren.get(i);
        if (atom.type == Atom.TYPE_uuid) {
            parseUuid(atom.data, fragment, extendedTypeScratch);
        }
    }
}
Also used : LeafAtom(com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom)

Example 2 with ContainerAtom

use of androidx.media3.extractor.mp4.Atom.ContainerAtom in project ExoPlayer by google.

the class FragmentedMp4Extractor method parseTruns.

private static void parseTruns(ContainerAtom traf, TrackBundle trackBundle, long decodeTime, @Flags int flags) {
    int trunCount = 0;
    int totalSampleCount = 0;
    List<LeafAtom> leafChildren = traf.leafChildren;
    int leafChildrenSize = leafChildren.size();
    for (int i = 0; i < leafChildrenSize; i++) {
        LeafAtom atom = leafChildren.get(i);
        if (atom.type == Atom.TYPE_trun) {
            ParsableByteArray trunData = atom.data;
            trunData.setPosition(Atom.FULL_HEADER_SIZE);
            int trunSampleCount = trunData.readUnsignedIntToInt();
            if (trunSampleCount > 0) {
                totalSampleCount += trunSampleCount;
                trunCount++;
            }
        }
    }
    trackBundle.currentTrackRunIndex = 0;
    trackBundle.currentSampleInTrackRun = 0;
    trackBundle.currentSampleIndex = 0;
    trackBundle.fragment.initTables(trunCount, totalSampleCount);
    int trunIndex = 0;
    int trunStartPosition = 0;
    for (int i = 0; i < leafChildrenSize; i++) {
        LeafAtom trun = leafChildren.get(i);
        if (trun.type == Atom.TYPE_trun) {
            trunStartPosition = parseTrun(trackBundle, trunIndex++, decodeTime, flags, trun.data, trunStartPosition);
        }
    }
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) LeafAtom(com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom)

Example 3 with ContainerAtom

use of androidx.media3.extractor.mp4.Atom.ContainerAtom in project ExoPlayer by google.

the class FragmentedMp4Extractor method parseTraf.

/**
 * Parses a traf atom (defined in 14496-12).
 */
private static void parseTraf(ContainerAtom traf, SparseArray<TrackBundle> trackBundles, boolean haveSideloadedTrack, @Flags int flags, byte[] extendedTypeScratch) throws ParserException {
    LeafAtom tfhd = checkNotNull(traf.getLeafAtomOfType(Atom.TYPE_tfhd));
    @Nullable TrackBundle trackBundle = parseTfhd(tfhd.data, trackBundles, haveSideloadedTrack);
    if (trackBundle == null) {
        return;
    }
    TrackFragment fragment = trackBundle.fragment;
    long fragmentDecodeTime = fragment.nextFragmentDecodeTime;
    boolean fragmentDecodeTimeIncludesMoov = fragment.nextFragmentDecodeTimeIncludesMoov;
    trackBundle.resetFragmentInfo();
    trackBundle.currentlyInFragment = true;
    @Nullable LeafAtom tfdtAtom = traf.getLeafAtomOfType(Atom.TYPE_tfdt);
    if (tfdtAtom != null && (flags & FLAG_WORKAROUND_IGNORE_TFDT_BOX) == 0) {
        fragment.nextFragmentDecodeTime = parseTfdt(tfdtAtom.data);
        fragment.nextFragmentDecodeTimeIncludesMoov = true;
    } else {
        fragment.nextFragmentDecodeTime = fragmentDecodeTime;
        fragment.nextFragmentDecodeTimeIncludesMoov = fragmentDecodeTimeIncludesMoov;
    }
    parseTruns(traf, trackBundle, flags);
    @Nullable TrackEncryptionBox encryptionBox = trackBundle.moovSampleTable.track.getSampleDescriptionEncryptionBox(checkNotNull(fragment.header).sampleDescriptionIndex);
    @Nullable LeafAtom saiz = traf.getLeafAtomOfType(Atom.TYPE_saiz);
    if (saiz != null) {
        parseSaiz(checkNotNull(encryptionBox), saiz.data, fragment);
    }
    @Nullable LeafAtom saio = traf.getLeafAtomOfType(Atom.TYPE_saio);
    if (saio != null) {
        parseSaio(saio.data, fragment);
    }
    @Nullable LeafAtom senc = traf.getLeafAtomOfType(Atom.TYPE_senc);
    if (senc != null) {
        parseSenc(senc.data, fragment);
    }
    parseSampleGroups(traf, encryptionBox != null ? encryptionBox.schemeType : null, fragment);
    int leafChildrenSize = traf.leafChildren.size();
    for (int i = 0; i < leafChildrenSize; i++) {
        LeafAtom atom = traf.leafChildren.get(i);
        if (atom.type == Atom.TYPE_uuid) {
            parseUuid(atom.data, fragment, extendedTypeScratch);
        }
    }
}
Also used : LeafAtom(com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom) Nullable(androidx.annotation.Nullable)

Example 4 with ContainerAtom

use of androidx.media3.extractor.mp4.Atom.ContainerAtom in project ExoPlayer by google.

the class FragmentedMp4Extractor method readAtomHeader.

private boolean readAtomHeader(ExtractorInput input) throws IOException {
    if (atomHeaderBytesRead == 0) {
        // Read the standard length atom header.
        if (!input.readFully(atomHeader.getData(), 0, Atom.HEADER_SIZE, true)) {
            return false;
        }
        atomHeaderBytesRead = Atom.HEADER_SIZE;
        atomHeader.setPosition(0);
        atomSize = atomHeader.readUnsignedInt();
        atomType = atomHeader.readInt();
    }
    if (atomSize == Atom.DEFINES_LARGE_SIZE) {
        // Read the large size.
        int headerBytesRemaining = Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE;
        input.readFully(atomHeader.getData(), Atom.HEADER_SIZE, headerBytesRemaining);
        atomHeaderBytesRead += headerBytesRemaining;
        atomSize = atomHeader.readUnsignedLongToLong();
    } else if (atomSize == Atom.EXTENDS_TO_END_SIZE) {
        // The atom extends to the end of the file. Note that if the atom is within a container we can
        // work out its size even if the input length is unknown.
        long endPosition = input.getLength();
        if (endPosition == C.LENGTH_UNSET && !containerAtoms.isEmpty()) {
            endPosition = containerAtoms.peek().endPosition;
        }
        if (endPosition != C.LENGTH_UNSET) {
            atomSize = endPosition - input.getPosition() + atomHeaderBytesRead;
        }
    }
    if (atomSize < atomHeaderBytesRead) {
        throw ParserException.createForUnsupportedContainerFeature("Atom size less than header length (unsupported).");
    }
    long atomPosition = input.getPosition() - atomHeaderBytesRead;
    if (atomType == Atom.TYPE_moof || atomType == Atom.TYPE_mdat) {
        if (!haveOutputSeekMap) {
            // This must be the first moof or mdat in the stream.
            extractorOutput.seekMap(new SeekMap.Unseekable(durationUs, atomPosition));
            haveOutputSeekMap = true;
        }
    }
    if (atomType == Atom.TYPE_moof) {
        // The data positions may be updated when parsing the tfhd/trun.
        int trackCount = trackBundles.size();
        for (int i = 0; i < trackCount; i++) {
            TrackFragment fragment = trackBundles.valueAt(i).fragment;
            fragment.atomPosition = atomPosition;
            fragment.auxiliaryDataPosition = atomPosition;
            fragment.dataPosition = atomPosition;
        }
    }
    if (atomType == Atom.TYPE_mdat) {
        currentTrackBundle = null;
        endOfMdatPosition = atomPosition + atomSize;
        parserState = STATE_READING_ENCRYPTION_DATA;
        return true;
    }
    if (shouldParseContainerAtom(atomType)) {
        long endPosition = input.getPosition() + atomSize - Atom.HEADER_SIZE;
        containerAtoms.push(new ContainerAtom(atomType, endPosition));
        if (atomSize == atomHeaderBytesRead) {
            processAtomEnded(endPosition);
        } else {
            // Start reading the first child atom.
            enterReadingAtomHeaderState();
        }
    } else if (shouldParseLeafAtom(atomType)) {
        if (atomHeaderBytesRead != Atom.HEADER_SIZE) {
            throw ParserException.createForUnsupportedContainerFeature("Leaf atom defines extended atom size (unsupported).");
        }
        if (atomSize > Integer.MAX_VALUE) {
            throw ParserException.createForUnsupportedContainerFeature("Leaf atom with length > 2147483647 (unsupported).");
        }
        ParsableByteArray atomData = new ParsableByteArray((int) atomSize);
        System.arraycopy(atomHeader.getData(), 0, atomData.getData(), 0, Atom.HEADER_SIZE);
        this.atomData = atomData;
        parserState = STATE_READING_ATOM_PAYLOAD;
    } else {
        if (atomSize > Integer.MAX_VALUE) {
            throw ParserException.createForUnsupportedContainerFeature("Skipping atom with length > 2147483647 (unsupported).");
        }
        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) SeekMap(com.google.android.exoplayer2.extractor.SeekMap)

Example 5 with ContainerAtom

use of androidx.media3.extractor.mp4.Atom.ContainerAtom in project ExoPlayer by google.

the class FragmentedMp4Extractor method parseTruns.

private static void parseTruns(ContainerAtom traf, TrackBundle trackBundle, @Flags int flags) throws ParserException {
    int trunCount = 0;
    int totalSampleCount = 0;
    List<LeafAtom> leafChildren = traf.leafChildren;
    int leafChildrenSize = leafChildren.size();
    for (int i = 0; i < leafChildrenSize; i++) {
        LeafAtom atom = leafChildren.get(i);
        if (atom.type == Atom.TYPE_trun) {
            ParsableByteArray trunData = atom.data;
            trunData.setPosition(Atom.FULL_HEADER_SIZE);
            int trunSampleCount = trunData.readUnsignedIntToInt();
            if (trunSampleCount > 0) {
                totalSampleCount += trunSampleCount;
                trunCount++;
            }
        }
    }
    trackBundle.currentTrackRunIndex = 0;
    trackBundle.currentSampleInTrackRun = 0;
    trackBundle.currentSampleIndex = 0;
    trackBundle.fragment.initTables(trunCount, totalSampleCount);
    int trunIndex = 0;
    int trunStartPosition = 0;
    for (int i = 0; i < leafChildrenSize; i++) {
        LeafAtom trun = leafChildren.get(i);
        if (trun.type == Atom.TYPE_trun) {
            trunStartPosition = parseTrun(trackBundle, trunIndex++, flags, trun.data, trunStartPosition);
        }
    }
}
Also used : ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) LeafAtom(com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom)

Aggregations

ContainerAtom (com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom)17 LeafAtom (com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom)12 Nullable (androidx.annotation.Nullable)11 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)11 SeekPoint (com.google.android.exoplayer2.extractor.SeekPoint)8 ArrayList (java.util.ArrayList)6 ContainerAtom (androidx.media3.extractor.mp4.Atom.ContainerAtom)5 SparseArray (android.util.SparseArray)4 ParsableByteArray (androidx.media3.common.util.ParsableByteArray)4 LeafAtom (androidx.media3.extractor.mp4.Atom.LeafAtom)4 ParserException (com.google.android.exoplayer2.ParserException)4 GaplessInfoHolder (com.google.android.exoplayer2.extractor.GaplessInfoHolder)4 SuppressLint (android.annotation.SuppressLint)3 ContainerAtom (com.google.android.exoplayer.parser.mp4.Atom.ContainerAtom)3 Format (com.google.android.exoplayer2.Format)3 DrmInitData (com.google.android.exoplayer2.drm.DrmInitData)3 SeekMap (com.google.android.exoplayer2.extractor.SeekMap)3 Metadata (com.google.android.exoplayer2.metadata.Metadata)3 DrmInitData (androidx.media3.common.DrmInitData)2 GaplessInfoHolder (androidx.media3.extractor.GaplessInfoHolder)2