use of com.google.android.exoplayer2.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);
}
}
}
use of com.google.android.exoplayer2.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);
}
}
}
use of com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom in project ExoPlayer by google.
the class FragmentedMp4Extractor method onMoofContainerAtomRead.
private void onMoofContainerAtomRead(ContainerAtom moof) throws ParserException {
parseMoof(moof, trackBundles, sideloadedTrack != null, flags, scratchBytes);
@Nullable DrmInitData drmInitData = getDrmInitDataFromAtoms(moof.leafChildren);
if (drmInitData != null) {
int trackCount = trackBundles.size();
for (int i = 0; i < trackCount; i++) {
trackBundles.valueAt(i).updateDrmInitData(drmInitData);
}
}
// If we have a pending seek, advance tracks to their preceding sync frames.
if (pendingSeekTimeUs != C.TIME_UNSET) {
int trackCount = trackBundles.size();
for (int i = 0; i < trackCount; i++) {
trackBundles.valueAt(i).seek(pendingSeekTimeUs);
}
pendingSeekTimeUs = C.TIME_UNSET;
}
}
use of com.google.android.exoplayer2.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);
}
}
}
use of com.google.android.exoplayer2.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;
}
Aggregations