Consider udta box as leaf

The MP4 standard considers the udta box as a regular container box. Quicktime, however,
considers it as a container (of only leaf atoms) that can have a terminating 32 bit
integer with value 0. Since this breaks the principle of not having content in container
boxes, this CL considers the udta box as a leaf box that contains other boxes and does
the parsing manually.

Issue: #1315
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=117237255
This commit is contained in:
olly 2016-03-15 07:28:17 -07:00 committed by Oliver Woodman
parent bbceb459fd
commit f5b7ea676d
2 changed files with 31 additions and 13 deletions

View File

@ -335,28 +335,46 @@ import java.util.List;
* Parses a udta atom.
*
* @param udtaAtom The udta (user data) atom to parse.
* @param isQuickTime True for QuickTime media. False otherwise.
* @return Gapless playback information stored in the user data, or {@code null} if not present.
*/
public static GaplessInfo parseUdta(Atom.ContainerAtom udtaAtom) {
Atom.LeafAtom metaAtom = udtaAtom.getLeafAtomOfType(Atom.TYPE_meta);
if (metaAtom == null) {
public static GaplessInfo parseUdta(Atom.LeafAtom udtaAtom, boolean isQuickTime) {
if (isQuickTime) {
// Meta boxes are regular boxes rather than full boxes in QuickTime. For now, don't try and
// parse one.
return null;
}
ParsableByteArray data = metaAtom.data;
data.setPosition(Atom.FULL_HEADER_SIZE);
ParsableByteArray udtaData = udtaAtom.data;
udtaData.setPosition(Atom.HEADER_SIZE);
while (udtaData.bytesLeft() >= Atom.HEADER_SIZE) {
int atomSize = udtaData.readInt();
int atomType = udtaData.readInt();
if (atomType == Atom.TYPE_meta) {
udtaData.setPosition(udtaData.getPosition() - Atom.HEADER_SIZE);
udtaData.setLimit(udtaData.getPosition() + atomSize);
return parseMetaAtom(udtaData);
} else {
udtaData.skipBytes(atomSize - Atom.HEADER_SIZE);
}
}
return null;
}
private static GaplessInfo parseMetaAtom(ParsableByteArray data) {
data.skipBytes(Atom.FULL_HEADER_SIZE);
ParsableByteArray ilst = new ParsableByteArray();
while (data.bytesLeft() > 0) {
int length = data.readInt() - Atom.HEADER_SIZE;
int type = data.readInt();
if (type == Atom.TYPE_ilst) {
ilst.reset(data.data, data.getPosition() + length);
while (data.bytesLeft() >= Atom.HEADER_SIZE) {
int payloadSize = data.readInt() - Atom.HEADER_SIZE;
int atomType = data.readInt();
if (atomType == Atom.TYPE_ilst) {
ilst.reset(data.data, data.getPosition() + payloadSize);
ilst.setPosition(data.getPosition());
GaplessInfo gaplessInfo = parseIlst(ilst);
if (gaplessInfo != null) {
return gaplessInfo;
}
}
data.skipBytes(length);
data.skipBytes(payloadSize);
}
return null;
}

View File

@ -293,9 +293,9 @@ public final class Mp4Extractor implements Extractor, SeekMap {
List<Mp4Track> tracks = new ArrayList<>();
long earliestSampleOffset = Long.MAX_VALUE;
GaplessInfo gaplessInfo = null;
Atom.ContainerAtom udta = moov.getContainerAtomOfType(Atom.TYPE_udta);
Atom.LeafAtom udta = moov.getLeafAtomOfType(Atom.TYPE_udta);
if (udta != null) {
gaplessInfo = AtomParsers.parseUdta(udta);
gaplessInfo = AtomParsers.parseUdta(udta, isQuickTime);
}
for (int i = 0; i < moov.containerChildren.size(); i++) {
Atom.ContainerAtom atom = moov.containerChildren.get(i);