Commit 61443b2f by Oliver Woodman

Relocate content of Mp4Util to more sensible locations.

- Atom related stuff in Mp4Util is moved to Atom.
- Remainder of Mp4Util is renamed to H264Util.
parent fea2140d
...@@ -26,9 +26,9 @@ import com.google.android.exoplayer.mp4.Atom; ...@@ -26,9 +26,9 @@ import com.google.android.exoplayer.mp4.Atom;
import com.google.android.exoplayer.mp4.Atom.ContainerAtom; import com.google.android.exoplayer.mp4.Atom.ContainerAtom;
import com.google.android.exoplayer.mp4.Atom.LeafAtom; import com.google.android.exoplayer.mp4.Atom.LeafAtom;
import com.google.android.exoplayer.mp4.CommonMp4AtomParsers; import com.google.android.exoplayer.mp4.CommonMp4AtomParsers;
import com.google.android.exoplayer.mp4.Mp4Util;
import com.google.android.exoplayer.mp4.Track; import com.google.android.exoplayer.mp4.Track;
import com.google.android.exoplayer.upstream.NonBlockingInputStream; import com.google.android.exoplayer.upstream.NonBlockingInputStream;
import com.google.android.exoplayer.util.H264Util;
import com.google.android.exoplayer.util.MimeTypes; import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.ParsableByteArray; import com.google.android.exoplayer.util.ParsableByteArray;
import com.google.android.exoplayer.util.Util; import com.google.android.exoplayer.util.Util;
...@@ -157,7 +157,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -157,7 +157,7 @@ public final class FragmentedMp4Extractor implements Extractor {
public FragmentedMp4Extractor(int workaroundFlags) { public FragmentedMp4Extractor(int workaroundFlags) {
this.workaroundFlags = workaroundFlags; this.workaroundFlags = workaroundFlags;
parserState = STATE_READING_ATOM_HEADER; parserState = STATE_READING_ATOM_HEADER;
atomHeader = new ParsableByteArray(Mp4Util.ATOM_HEADER_SIZE); atomHeader = new ParsableByteArray(Atom.ATOM_HEADER_SIZE);
extendedTypeScratch = new byte[16]; extendedTypeScratch = new byte[16];
containerAtoms = new Stack<ContainerAtom>(); containerAtoms = new Stack<ContainerAtom>();
fragmentRun = new TrackFragment(); fragmentRun = new TrackFragment();
...@@ -259,14 +259,14 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -259,14 +259,14 @@ public final class FragmentedMp4Extractor implements Extractor {
} }
private int readAtomHeader(NonBlockingInputStream inputStream) { private int readAtomHeader(NonBlockingInputStream inputStream) {
int remainingBytes = Mp4Util.ATOM_HEADER_SIZE - atomBytesRead; int remainingBytes = Atom.ATOM_HEADER_SIZE - atomBytesRead;
int bytesRead = inputStream.read(atomHeader.data, atomBytesRead, remainingBytes); int bytesRead = inputStream.read(atomHeader.data, atomBytesRead, remainingBytes);
if (bytesRead == -1) { if (bytesRead == -1) {
return RESULT_END_OF_STREAM; return RESULT_END_OF_STREAM;
} }
rootAtomBytesRead += bytesRead; rootAtomBytesRead += bytesRead;
atomBytesRead += bytesRead; atomBytesRead += bytesRead;
if (atomBytesRead != Mp4Util.ATOM_HEADER_SIZE) { if (atomBytesRead != Atom.ATOM_HEADER_SIZE) {
return RESULT_NEED_MORE_DATA; return RESULT_NEED_MORE_DATA;
} }
...@@ -288,10 +288,10 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -288,10 +288,10 @@ public final class FragmentedMp4Extractor implements Extractor {
if (CONTAINER_TYPES.contains(atomTypeInteger)) { if (CONTAINER_TYPES.contains(atomTypeInteger)) {
enterState(STATE_READING_ATOM_HEADER); enterState(STATE_READING_ATOM_HEADER);
containerAtoms.add(new ContainerAtom(atomType, containerAtoms.add(new ContainerAtom(atomType,
rootAtomBytesRead + atomSize - Mp4Util.ATOM_HEADER_SIZE)); rootAtomBytesRead + atomSize - Atom.ATOM_HEADER_SIZE));
} else { } else {
atomData = new ParsableByteArray(atomSize); atomData = new ParsableByteArray(atomSize);
System.arraycopy(atomHeader.data, 0, atomData.data, 0, Mp4Util.ATOM_HEADER_SIZE); System.arraycopy(atomHeader.data, 0, atomData.data, 0, Atom.ATOM_HEADER_SIZE);
enterState(STATE_READING_ATOM_PAYLOAD); enterState(STATE_READING_ATOM_PAYLOAD);
} }
} else { } else {
...@@ -360,7 +360,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -360,7 +360,7 @@ public final class FragmentedMp4Extractor implements Extractor {
LeafAtom child = moovChildren.get(i); LeafAtom child = moovChildren.get(i);
if (child.type == Atom.TYPE_pssh) { if (child.type == Atom.TYPE_pssh) {
ParsableByteArray psshAtom = child.data; ParsableByteArray psshAtom = child.data;
psshAtom.setPosition(Mp4Util.FULL_ATOM_HEADER_SIZE); psshAtom.setPosition(Atom.FULL_ATOM_HEADER_SIZE);
UUID uuid = new UUID(psshAtom.readLong(), psshAtom.readLong()); UUID uuid = new UUID(psshAtom.readLong(), psshAtom.readLong());
int dataSize = psshAtom.readInt(); int dataSize = psshAtom.readInt();
byte[] data = new byte[dataSize]; byte[] data = new byte[dataSize];
...@@ -399,7 +399,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -399,7 +399,7 @@ public final class FragmentedMp4Extractor implements Extractor {
* Parses a trex atom (defined in 14496-12). * Parses a trex atom (defined in 14496-12).
*/ */
private static DefaultSampleValues parseTrex(ParsableByteArray trex) { private static DefaultSampleValues parseTrex(ParsableByteArray trex) {
trex.setPosition(Mp4Util.FULL_ATOM_HEADER_SIZE + 4); trex.setPosition(Atom.FULL_ATOM_HEADER_SIZE + 4);
int defaultSampleDescriptionIndex = trex.readUnsignedIntToInt() - 1; int defaultSampleDescriptionIndex = trex.readUnsignedIntToInt() - 1;
int defaultSampleDuration = trex.readUnsignedIntToInt(); int defaultSampleDuration = trex.readUnsignedIntToInt();
int defaultSampleSize = trex.readUnsignedIntToInt(); int defaultSampleSize = trex.readUnsignedIntToInt();
...@@ -453,9 +453,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -453,9 +453,9 @@ public final class FragmentedMp4Extractor implements Extractor {
private static void parseSaiz(TrackEncryptionBox encryptionBox, ParsableByteArray saiz, private static void parseSaiz(TrackEncryptionBox encryptionBox, ParsableByteArray saiz,
TrackFragment out) { TrackFragment out) {
int vectorSize = encryptionBox.initializationVectorSize; int vectorSize = encryptionBox.initializationVectorSize;
saiz.setPosition(Mp4Util.ATOM_HEADER_SIZE); saiz.setPosition(Atom.ATOM_HEADER_SIZE);
int fullAtom = saiz.readInt(); int fullAtom = saiz.readInt();
int flags = Mp4Util.parseFullAtomFlags(fullAtom); int flags = Atom.parseFullAtomFlags(fullAtom);
if ((flags & 0x01) == 1) { if ((flags & 0x01) == 1) {
saiz.skip(8); saiz.skip(8);
} }
...@@ -490,9 +490,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -490,9 +490,9 @@ public final class FragmentedMp4Extractor implements Extractor {
*/ */
private static DefaultSampleValues parseTfhd(DefaultSampleValues extendsDefaults, private static DefaultSampleValues parseTfhd(DefaultSampleValues extendsDefaults,
ParsableByteArray tfhd) { ParsableByteArray tfhd) {
tfhd.setPosition(Mp4Util.ATOM_HEADER_SIZE); tfhd.setPosition(Atom.ATOM_HEADER_SIZE);
int fullAtom = tfhd.readInt(); int fullAtom = tfhd.readInt();
int flags = Mp4Util.parseFullAtomFlags(fullAtom); int flags = Atom.parseFullAtomFlags(fullAtom);
tfhd.skip(4); // trackId tfhd.skip(4); // trackId
if ((flags & 0x01 /* base_data_offset_present */) != 0) { if ((flags & 0x01 /* base_data_offset_present */) != 0) {
...@@ -519,9 +519,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -519,9 +519,9 @@ public final class FragmentedMp4Extractor implements Extractor {
* media, expressed in the media's timescale. * media, expressed in the media's timescale.
*/ */
private static long parseTfdt(ParsableByteArray tfdt) { private static long parseTfdt(ParsableByteArray tfdt) {
tfdt.setPosition(Mp4Util.ATOM_HEADER_SIZE); tfdt.setPosition(Atom.ATOM_HEADER_SIZE);
int fullAtom = tfdt.readInt(); int fullAtom = tfdt.readInt();
int version = Mp4Util.parseFullAtomVersion(fullAtom); int version = Atom.parseFullAtomVersion(fullAtom);
return version == 1 ? tfdt.readUnsignedLongToLong() : tfdt.readUnsignedInt(); return version == 1 ? tfdt.readUnsignedLongToLong() : tfdt.readUnsignedInt();
} }
...@@ -536,9 +536,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -536,9 +536,9 @@ public final class FragmentedMp4Extractor implements Extractor {
*/ */
private static void parseTrun(Track track, DefaultSampleValues defaultSampleValues, private static void parseTrun(Track track, DefaultSampleValues defaultSampleValues,
long decodeTime, int workaroundFlags, ParsableByteArray trun, TrackFragment out) { long decodeTime, int workaroundFlags, ParsableByteArray trun, TrackFragment out) {
trun.setPosition(Mp4Util.ATOM_HEADER_SIZE); trun.setPosition(Atom.ATOM_HEADER_SIZE);
int fullAtom = trun.readInt(); int fullAtom = trun.readInt();
int flags = Mp4Util.parseFullAtomFlags(fullAtom); int flags = Atom.parseFullAtomFlags(fullAtom);
int sampleCount = trun.readUnsignedIntToInt(); int sampleCount = trun.readUnsignedIntToInt();
if ((flags & 0x01 /* data_offset_present */) != 0) { if ((flags & 0x01 /* data_offset_present */) != 0) {
...@@ -596,7 +596,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -596,7 +596,7 @@ public final class FragmentedMp4Extractor implements Extractor {
private static void parseUuid(ParsableByteArray uuid, TrackFragment out, private static void parseUuid(ParsableByteArray uuid, TrackFragment out,
byte[] extendedTypeScratch) { byte[] extendedTypeScratch) {
uuid.setPosition(Mp4Util.ATOM_HEADER_SIZE); uuid.setPosition(Atom.ATOM_HEADER_SIZE);
uuid.readBytes(extendedTypeScratch, 0, 16); uuid.readBytes(extendedTypeScratch, 0, 16);
// Currently this parser only supports Microsoft's PIFF SampleEncryptionBox. // Currently this parser only supports Microsoft's PIFF SampleEncryptionBox.
...@@ -615,9 +615,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -615,9 +615,9 @@ public final class FragmentedMp4Extractor implements Extractor {
} }
private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out) { private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out) {
senc.setPosition(Mp4Util.ATOM_HEADER_SIZE + offset); senc.setPosition(Atom.ATOM_HEADER_SIZE + offset);
int fullAtom = senc.readInt(); int fullAtom = senc.readInt();
int flags = Mp4Util.parseFullAtomFlags(fullAtom); int flags = Atom.parseFullAtomFlags(fullAtom);
if ((flags & 0x01 /* override_track_encryption_box_parameters */) != 0) { if ((flags & 0x01 /* override_track_encryption_box_parameters */) != 0) {
// TODO: Implement this. // TODO: Implement this.
...@@ -639,9 +639,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -639,9 +639,9 @@ public final class FragmentedMp4Extractor implements Extractor {
* Parses a sidx atom (defined in 14496-12). * Parses a sidx atom (defined in 14496-12).
*/ */
private static SegmentIndex parseSidx(ParsableByteArray atom) { private static SegmentIndex parseSidx(ParsableByteArray atom) {
atom.setPosition(Mp4Util.ATOM_HEADER_SIZE); atom.setPosition(Atom.ATOM_HEADER_SIZE);
int fullAtom = atom.readInt(); int fullAtom = atom.readInt();
int version = Mp4Util.parseFullAtomVersion(fullAtom); int version = Atom.parseFullAtomVersion(fullAtom);
atom.skip(4); atom.skip(4);
long timescale = atom.readUnsignedInt(); long timescale = atom.readUnsignedInt();
...@@ -781,7 +781,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -781,7 +781,7 @@ public final class FragmentedMp4Extractor implements Extractor {
if (track.type == Track.TYPE_VIDEO) { if (track.type == Track.TYPE_VIDEO) {
// The mp4 file contains length-prefixed NAL units, but the decoder wants start code // The mp4 file contains length-prefixed NAL units, but the decoder wants start code
// delimited content. // delimited content.
Mp4Util.replaceLengthPrefixesWithAvcStartCodes(outputData, sampleSize); H264Util.replaceLengthPrefixesWithAvcStartCodes(outputData, sampleSize);
} }
out.size = sampleSize; out.size = sampleSize;
} }
......
...@@ -18,8 +18,8 @@ package com.google.android.exoplayer.hls.parser; ...@@ -18,8 +18,8 @@ package com.google.android.exoplayer.hls.parser;
import com.google.android.exoplayer.C; import com.google.android.exoplayer.C;
import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormat;
import com.google.android.exoplayer.hls.parser.HlsExtractor.TrackOutput; import com.google.android.exoplayer.hls.parser.HlsExtractor.TrackOutput;
import com.google.android.exoplayer.mp4.Mp4Util;
import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.H264Util;
import com.google.android.exoplayer.util.MimeTypes; import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.ParsableBitArray; import com.google.android.exoplayer.util.ParsableBitArray;
import com.google.android.exoplayer.util.ParsableByteArray; import com.google.android.exoplayer.util.ParsableByteArray;
...@@ -73,7 +73,7 @@ import java.util.List; ...@@ -73,7 +73,7 @@ import java.util.List;
// Scan the appended data, processing NAL units as they are encountered // Scan the appended data, processing NAL units as they are encountered
while (offset < limit) { while (offset < limit) {
int nextNalUnitOffset = Mp4Util.findNalUnit(dataArray, offset, limit, prefixFlags); int nextNalUnitOffset = H264Util.findNalUnit(dataArray, offset, limit, prefixFlags);
if (nextNalUnitOffset < limit) { if (nextNalUnitOffset < limit) {
// We've seen the start of a NAL unit. // We've seen the start of a NAL unit.
...@@ -84,7 +84,7 @@ import java.util.List; ...@@ -84,7 +84,7 @@ import java.util.List;
feedNalUnitTargetBuffersData(dataArray, offset, nextNalUnitOffset); feedNalUnitTargetBuffersData(dataArray, offset, nextNalUnitOffset);
} }
int nalUnitType = Mp4Util.getNalUnitType(dataArray, nextNalUnitOffset); int nalUnitType = H264Util.getNalUnitType(dataArray, nextNalUnitOffset);
int nalUnitOffsetInData = nextNalUnitOffset - limit; int nalUnitOffsetInData = nextNalUnitOffset - limit;
if (nalUnitType == NAL_UNIT_TYPE_AUD) { if (nalUnitType == NAL_UNIT_TYPE_AUD) {
if (output.isWritingSample()) { if (output.isWritingSample()) {
......
...@@ -24,6 +24,18 @@ import java.util.List; ...@@ -24,6 +24,18 @@ import java.util.List;
public abstract class Atom { public abstract class Atom {
/** Size of an atom header, in bytes. */
public static final int ATOM_HEADER_SIZE = 8;
/** Size of a long atom header, in bytes. */
public static final int LONG_ATOM_HEADER_SIZE = 16;
/** Size of a full atom header, in bytes. */
public static final int FULL_ATOM_HEADER_SIZE = 12;
/** Value for the first 32 bits of atomSize when the atom size is actually a long value. */
public static final int LONG_SIZE_PREFIX = 1;
public static final int TYPE_ftyp = getAtomTypeInteger("ftyp"); public static final int TYPE_ftyp = getAtomTypeInteger("ftyp");
public static final int TYPE_avc1 = getAtomTypeInteger("avc1"); public static final int TYPE_avc1 = getAtomTypeInteger("avc1");
public static final int TYPE_avc3 = getAtomTypeInteger("avc3"); public static final int TYPE_avc3 = getAtomTypeInteger("avc3");
...@@ -154,6 +166,20 @@ public abstract class Atom { ...@@ -154,6 +166,20 @@ public abstract class Atom {
} }
/**
* Parses the version number out of the additional integer component of a full atom.
*/
public static int parseFullAtomVersion(int fullAtomInt) {
return 0x000000FF & (fullAtomInt >> 24);
}
/**
* Parses the atom flags out of the additional integer component of a full atom.
*/
public static int parseFullAtomFlags(int fullAtomInt) {
return 0x00FFFFFF & fullAtomInt;
}
private static String getAtomTypeString(int type) { private static String getAtomTypeString(int type) {
return "" + (char) (type >> 24) return "" + (char) (type >> 24)
+ (char) ((type >> 16) & 0xFF) + (char) ((type >> 16) & 0xFF)
......
...@@ -22,6 +22,9 @@ import com.google.android.exoplayer.util.Util; ...@@ -22,6 +22,9 @@ import com.google.android.exoplayer.util.Util;
/** Sample table for a track in an MP4 file. */ /** Sample table for a track in an MP4 file. */
public final class Mp4TrackSampleTable { public final class Mp4TrackSampleTable {
/** Sample index when no sample is available. */
public static final int NO_SAMPLE = -1;
/** Sample offsets in bytes. */ /** Sample offsets in bytes. */
public final long[] offsets; public final long[] offsets;
/** Sample sizes in bytes. */ /** Sample sizes in bytes. */
...@@ -53,7 +56,7 @@ public final class Mp4TrackSampleTable { ...@@ -53,7 +56,7 @@ public final class Mp4TrackSampleTable {
* timestamp, if one is available. * timestamp, if one is available.
* *
* @param timeUs Timestamp adjacent to which to find a synchronization sample. * @param timeUs Timestamp adjacent to which to find a synchronization sample.
* @return Index of the synchronization sample, or {@link Mp4Util#NO_SAMPLE} if none. * @return Index of the synchronization sample, or {@link #NO_SAMPLE} if none.
*/ */
public int getIndexOfEarlierOrEqualSynchronizationSample(long timeUs) { public int getIndexOfEarlierOrEqualSynchronizationSample(long timeUs) {
int startIndex = Util.binarySearchFloor(timestampsUs, timeUs, true, false); int startIndex = Util.binarySearchFloor(timestampsUs, timeUs, true, false);
...@@ -63,7 +66,7 @@ public final class Mp4TrackSampleTable { ...@@ -63,7 +66,7 @@ public final class Mp4TrackSampleTable {
} }
} }
return Mp4Util.NO_SAMPLE; return NO_SAMPLE;
} }
/** /**
...@@ -71,7 +74,7 @@ public final class Mp4TrackSampleTable { ...@@ -71,7 +74,7 @@ public final class Mp4TrackSampleTable {
* if one is available. * if one is available.
* *
* @param timeUs Timestamp adjacent to which to find a synchronization sample. * @param timeUs Timestamp adjacent to which to find a synchronization sample.
* @return index Index of the synchronization sample, or {@link Mp4Util#NO_SAMPLE} if none. * @return index Index of the synchronization sample, or {@link #NO_SAMPLE} if none.
*/ */
public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) { public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) {
int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false); int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false);
...@@ -81,7 +84,7 @@ public final class Mp4TrackSampleTable { ...@@ -81,7 +84,7 @@ public final class Mp4TrackSampleTable {
} }
} }
return Mp4Util.NO_SAMPLE; return NO_SAMPLE;
} }
} }
...@@ -25,7 +25,6 @@ import com.google.android.exoplayer.mp4.Atom; ...@@ -25,7 +25,6 @@ import com.google.android.exoplayer.mp4.Atom;
import com.google.android.exoplayer.mp4.Atom.ContainerAtom; import com.google.android.exoplayer.mp4.Atom.ContainerAtom;
import com.google.android.exoplayer.mp4.CommonMp4AtomParsers; import com.google.android.exoplayer.mp4.CommonMp4AtomParsers;
import com.google.android.exoplayer.mp4.Mp4TrackSampleTable; import com.google.android.exoplayer.mp4.Mp4TrackSampleTable;
import com.google.android.exoplayer.mp4.Mp4Util;
import com.google.android.exoplayer.mp4.Track; import com.google.android.exoplayer.mp4.Track;
import com.google.android.exoplayer.upstream.BufferPool; import com.google.android.exoplayer.upstream.BufferPool;
import com.google.android.exoplayer.upstream.BufferedNonBlockingInputStream; import com.google.android.exoplayer.upstream.BufferedNonBlockingInputStream;
...@@ -35,6 +34,7 @@ import com.google.android.exoplayer.upstream.DataSpec; ...@@ -35,6 +34,7 @@ import com.google.android.exoplayer.upstream.DataSpec;
import com.google.android.exoplayer.upstream.Loader; import com.google.android.exoplayer.upstream.Loader;
import com.google.android.exoplayer.upstream.Loader.Loadable; import com.google.android.exoplayer.upstream.Loader.Loadable;
import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.H264Util;
import com.google.android.exoplayer.util.MimeTypes; import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.ParsableByteArray; import com.google.android.exoplayer.util.ParsableByteArray;
import com.google.android.exoplayer.util.Util; import com.google.android.exoplayer.util.Util;
...@@ -58,6 +58,8 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -58,6 +58,8 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
private static final String TAG = "Mp4SampleExtractor"; private static final String TAG = "Mp4SampleExtractor";
private static final String LOADER_THREAD_NAME = "Mp4SampleExtractor"; private static final String LOADER_THREAD_NAME = "Mp4SampleExtractor";
private static final int NO_TRACK = -1;
// Reading results // Reading results
private static final int RESULT_NEED_MORE_DATA = 1; private static final int RESULT_NEED_MORE_DATA = 1;
private static final int RESULT_END_OF_STREAM = 2; private static final int RESULT_END_OF_STREAM = 2;
...@@ -167,7 +169,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -167,7 +169,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
// TODO: Implement Allocator here so it is possible to check there is only one buffer at a time. // TODO: Implement Allocator here so it is possible to check there is only one buffer at a time.
bufferPool = new BufferPool(readAheadAllocationSize); bufferPool = new BufferPool(readAheadAllocationSize);
loader = new Loader(LOADER_THREAD_NAME); loader = new Loader(LOADER_THREAD_NAME);
atomHeader = new ParsableByteArray(Mp4Util.LONG_ATOM_HEADER_SIZE); atomHeader = new ParsableByteArray(Atom.LONG_ATOM_HEADER_SIZE);
containerAtoms = new Stack<Atom.ContainerAtom>(); containerAtoms = new Stack<Atom.ContainerAtom>();
parserState = STATE_READING_ATOM_HEADER; parserState = STATE_READING_ATOM_HEADER;
...@@ -206,12 +208,12 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -206,12 +208,12 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
// Get the timestamp of the earliest currently-selected sample. // Get the timestamp of the earliest currently-selected sample.
int earliestSampleTrackIndex = getTrackIndexOfEarliestCurrentSample(); int earliestSampleTrackIndex = getTrackIndexOfEarliestCurrentSample();
if (earliestSampleTrackIndex == Mp4Util.NO_TRACK) { if (earliestSampleTrackIndex == NO_TRACK) {
tracks[trackIndex].sampleIndex = 0; tracks[trackIndex].sampleIndex = 0;
return; return;
} }
if (earliestSampleTrackIndex == Mp4Util.NO_SAMPLE) { if (earliestSampleTrackIndex == Mp4TrackSampleTable.NO_SAMPLE) {
tracks[trackIndex].sampleIndex = Mp4Util.NO_SAMPLE; tracks[trackIndex].sampleIndex = Mp4TrackSampleTable.NO_SAMPLE;
return; return;
} }
long timestampUs = long timestampUs =
...@@ -281,7 +283,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -281,7 +283,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
Mp4TrackSampleTable sampleTable = tracks[trackIndex].sampleTable; Mp4TrackSampleTable sampleTable = tracks[trackIndex].sampleTable;
int sampleIndex = sampleTable.getIndexOfEarlierOrEqualSynchronizationSample(positionUs); int sampleIndex = sampleTable.getIndexOfEarlierOrEqualSynchronizationSample(positionUs);
if (sampleIndex == Mp4Util.NO_SAMPLE) { if (sampleIndex == Mp4TrackSampleTable.NO_SAMPLE) {
sampleIndex = sampleTable.getIndexOfLaterOrEqualSynchronizationSample(positionUs); sampleIndex = sampleTable.getIndexOfLaterOrEqualSynchronizationSample(positionUs);
} }
tracks[trackIndex].sampleIndex = sampleIndex; tracks[trackIndex].sampleIndex = sampleIndex;
...@@ -333,7 +335,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -333,7 +335,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
int sampleIndex = track.sampleIndex; int sampleIndex = track.sampleIndex;
// Check for the end of the stream. // Check for the end of the stream.
if (sampleIndex == Mp4Util.NO_SAMPLE) { if (sampleIndex == Mp4TrackSampleTable.NO_SAMPLE) {
// TODO: Should END_OF_STREAM be returned as soon as this track has no more samples, or as // TODO: Should END_OF_STREAM be returned as soon as this track has no more samples, or as
// soon as no tracks have a sample (as implemented here)? // soon as no tracks have a sample (as implemented here)?
return hasSampleInAnySelectedTrack() ? SampleSource.NOTHING_READ : SampleSource.END_OF_STREAM; return hasSampleInAnySelectedTrack() ? SampleSource.NOTHING_READ : SampleSource.END_OF_STREAM;
...@@ -395,7 +397,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -395,7 +397,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
if (MimeTypes.VIDEO_H264.equals(tracks[trackIndex].track.mediaFormat.mimeType)) { if (MimeTypes.VIDEO_H264.equals(tracks[trackIndex].track.mediaFormat.mimeType)) {
// The mp4 file contains length-prefixed access units, but the decoder wants start code // The mp4 file contains length-prefixed access units, but the decoder wants start code
// delimited content. // delimited content.
Mp4Util.replaceLengthPrefixesWithAvcStartCodes(sampleHolder.data, sampleSize); H264Util.replaceLengthPrefixesWithAvcStartCodes(sampleHolder.data, sampleSize);
} }
sampleHolder.size = sampleSize; sampleHolder.size = sampleSize;
} }
...@@ -411,7 +413,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -411,7 +413,7 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
// Advance to the next sample, checking if this was the last sample. // Advance to the next sample, checking if this was the last sample.
track.sampleIndex = track.sampleIndex =
sampleIndex + 1 == track.sampleTable.getSampleCount() ? Mp4Util.NO_SAMPLE : sampleIndex + 1; sampleIndex + 1 == track.sampleTable.getSampleCount() ? Mp4TrackSampleTable.NO_SAMPLE : sampleIndex + 1;
// Reset the loading error counter if we read past the offset at which the error was thrown. // Reset the loading error counter if we read past the offset at which the error was thrown.
if (dataSourceStream.getReadPosition() > loadErrorPosition) { if (dataSourceStream.getReadPosition() > loadErrorPosition) {
...@@ -489,12 +491,12 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -489,12 +491,12 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
} }
/** /**
* Returns the index of the track that contains the earliest current sample, or * Returns the index of the track that contains the earliest current sample, or {@link #NO_TRACK}
* {@link Mp4Util#NO_TRACK} if no track is selected, or {@link Mp4Util#NO_SAMPLE} if no samples * if no track is selected, or {@link Mp4TrackSampleTable#NO_SAMPLE} if no samples remain in
* remain in selected tracks. * selected tracks.
*/ */
private int getTrackIndexOfEarliestCurrentSample() { private int getTrackIndexOfEarliestCurrentSample() {
int earliestSampleTrackIndex = Mp4Util.NO_TRACK; int earliestSampleTrackIndex = NO_TRACK;
long earliestSampleOffset = Long.MAX_VALUE; long earliestSampleOffset = Long.MAX_VALUE;
for (int trackIndex = 0; trackIndex < tracks.length; trackIndex++) { for (int trackIndex = 0; trackIndex < tracks.length; trackIndex++) {
Mp4Track track = tracks[trackIndex]; Mp4Track track = tracks[trackIndex];
...@@ -503,10 +505,10 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -503,10 +505,10 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
} }
int sampleIndex = track.sampleIndex; int sampleIndex = track.sampleIndex;
if (sampleIndex == Mp4Util.NO_SAMPLE) { if (sampleIndex == Mp4TrackSampleTable.NO_SAMPLE) {
if (earliestSampleTrackIndex == Mp4Util.NO_TRACK) { if (earliestSampleTrackIndex == NO_TRACK) {
// A track is selected, but it has no more samples. // A track is selected, but it has no more samples.
earliestSampleTrackIndex = Mp4Util.NO_SAMPLE; earliestSampleTrackIndex = Mp4TrackSampleTable.NO_SAMPLE;
} }
continue; continue;
} }
...@@ -524,7 +526,8 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -524,7 +526,8 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
private boolean hasSampleInAnySelectedTrack() { private boolean hasSampleInAnySelectedTrack() {
boolean hasSample = false; boolean hasSample = false;
for (int trackIndex = 0; trackIndex < tracks.length; trackIndex++) { for (int trackIndex = 0; trackIndex < tracks.length; trackIndex++) {
if (tracks[trackIndex].selected && tracks[trackIndex].sampleIndex != Mp4Util.NO_SAMPLE) { if (tracks[trackIndex].selected && tracks[trackIndex].sampleIndex
!= Mp4TrackSampleTable.NO_SAMPLE) {
hasSample = true; hasSample = true;
break; break;
} }
...@@ -556,10 +559,10 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -556,10 +559,10 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
// The size value is either 4 or 8 bytes long (in which case atomSize = Mp4Util.LONG_ATOM_SIZE). // The size value is either 4 or 8 bytes long (in which case atomSize = Mp4Util.LONG_ATOM_SIZE).
int remainingBytes; int remainingBytes;
if (atomSize != Mp4Util.LONG_ATOM_SIZE) { if (atomSize != Atom.LONG_SIZE_PREFIX) {
remainingBytes = Mp4Util.ATOM_HEADER_SIZE - atomBytesRead; remainingBytes = Atom.ATOM_HEADER_SIZE - atomBytesRead;
} else { } else {
remainingBytes = Mp4Util.LONG_ATOM_HEADER_SIZE - atomBytesRead; remainingBytes = Atom.LONG_ATOM_HEADER_SIZE - atomBytesRead;
} }
int bytesRead = inputStream.read(atomHeader.data, atomBytesRead, remainingBytes); int bytesRead = inputStream.read(atomHeader.data, atomBytesRead, remainingBytes);
...@@ -568,17 +571,17 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -568,17 +571,17 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
} }
rootAtomBytesRead += bytesRead; rootAtomBytesRead += bytesRead;
atomBytesRead += bytesRead; atomBytesRead += bytesRead;
if (atomBytesRead < Mp4Util.ATOM_HEADER_SIZE if (atomBytesRead < Atom.ATOM_HEADER_SIZE
|| (atomSize == Mp4Util.LONG_ATOM_SIZE && atomBytesRead < Mp4Util.LONG_ATOM_HEADER_SIZE)) { || (atomSize == Atom.LONG_SIZE_PREFIX && atomBytesRead < Atom.LONG_ATOM_HEADER_SIZE)) {
return RESULT_NEED_MORE_DATA; return RESULT_NEED_MORE_DATA;
} }
atomHeader.setPosition(0); atomHeader.setPosition(0);
atomSize = atomHeader.readUnsignedInt(); atomSize = atomHeader.readUnsignedInt();
atomType = atomHeader.readInt(); atomType = atomHeader.readInt();
if (atomSize == Mp4Util.LONG_ATOM_SIZE) { if (atomSize == Atom.LONG_SIZE_PREFIX) {
// The extended atom size is contained in the next 8 bytes, so try to read it now. // The extended atom size is contained in the next 8 bytes, so try to read it now.
if (atomBytesRead < Mp4Util.LONG_ATOM_HEADER_SIZE) { if (atomBytesRead < Atom.LONG_ATOM_HEADER_SIZE) {
return readAtomHeader(); return readAtomHeader();
} }
...@@ -587,18 +590,18 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac ...@@ -587,18 +590,18 @@ public final class Mp4SampleExtractor implements SampleExtractor, Loader.Callbac
Integer atomTypeInteger = atomType; // Avoids boxing atomType twice. Integer atomTypeInteger = atomType; // Avoids boxing atomType twice.
if (CONTAINER_TYPES.contains(atomTypeInteger)) { if (CONTAINER_TYPES.contains(atomTypeInteger)) {
if (atomSize == Mp4Util.LONG_ATOM_SIZE) { if (atomSize == Atom.LONG_SIZE_PREFIX) {
containerAtoms.add(new ContainerAtom( containerAtoms.add(new ContainerAtom(
atomType, rootAtomBytesRead + atomSize - Mp4Util.LONG_ATOM_HEADER_SIZE)); atomType, rootAtomBytesRead + atomSize - Atom.LONG_ATOM_HEADER_SIZE));
} else { } else {
containerAtoms.add(new ContainerAtom( containerAtoms.add(new ContainerAtom(
atomType, rootAtomBytesRead + atomSize - Mp4Util.ATOM_HEADER_SIZE)); atomType, rootAtomBytesRead + atomSize - Atom.ATOM_HEADER_SIZE));
} }
enterState(STATE_READING_ATOM_HEADER); enterState(STATE_READING_ATOM_HEADER);
} else if (LEAF_ATOM_TYPES.contains(atomTypeInteger)) { } else if (LEAF_ATOM_TYPES.contains(atomTypeInteger)) {
Assertions.checkState(atomSize <= Integer.MAX_VALUE); Assertions.checkState(atomSize <= Integer.MAX_VALUE);
atomData = new ParsableByteArray((int) atomSize); atomData = new ParsableByteArray((int) atomSize);
System.arraycopy(atomHeader.data, 0, atomData.data, 0, Mp4Util.ATOM_HEADER_SIZE); System.arraycopy(atomHeader.data, 0, atomData.data, 0, Atom.ATOM_HEADER_SIZE);
enterState(STATE_READING_ATOM_PAYLOAD); enterState(STATE_READING_ATOM_PAYLOAD);
} else { } else {
atomData = null; atomData = null;
......
...@@ -13,16 +13,16 @@ ...@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer.mp4; package com.google.android.exoplayer.util;
import junit.framework.TestCase; import junit.framework.TestCase;
import java.util.Arrays; import java.util.Arrays;
/** /**
* Tests for {@link Mp4Util}. * Tests for {@link H264Util}.
*/ */
public class Mp4UtilTest extends TestCase { public class H264UtilTest extends TestCase {
private static final int TEST_PARTIAL_NAL_POSITION = 4; private static final int TEST_PARTIAL_NAL_POSITION = 4;
private static final int TEST_NAL_POSITION = 10; private static final int TEST_NAL_POSITION = 10;
...@@ -31,19 +31,19 @@ public class Mp4UtilTest extends TestCase { ...@@ -31,19 +31,19 @@ public class Mp4UtilTest extends TestCase {
byte[] data = buildTestData(); byte[] data = buildTestData();
// Should find NAL unit. // Should find NAL unit.
int result = Mp4Util.findNalUnit(data, 0, data.length); int result = H264Util.findNalUnit(data, 0, data.length, null);
assertEquals(TEST_NAL_POSITION, result); assertEquals(TEST_NAL_POSITION, result);
// Should find NAL unit whose prefix ends one byte before the limit. // Should find NAL unit whose prefix ends one byte before the limit.
result = Mp4Util.findNalUnit(data, 0, TEST_NAL_POSITION + 4); result = H264Util.findNalUnit(data, 0, TEST_NAL_POSITION + 4, null);
assertEquals(TEST_NAL_POSITION, result); assertEquals(TEST_NAL_POSITION, result);
// Shouldn't find NAL unit whose prefix ends at the limit (since the limit is exclusive). // Shouldn't find NAL unit whose prefix ends at the limit (since the limit is exclusive).
result = Mp4Util.findNalUnit(data, 0, TEST_NAL_POSITION + 3); result = H264Util.findNalUnit(data, 0, TEST_NAL_POSITION + 3, null);
assertEquals(TEST_NAL_POSITION + 3, result); assertEquals(TEST_NAL_POSITION + 3, result);
// Should find NAL unit whose prefix starts at the offset. // Should find NAL unit whose prefix starts at the offset.
result = Mp4Util.findNalUnit(data, TEST_NAL_POSITION, data.length); result = H264Util.findNalUnit(data, TEST_NAL_POSITION, data.length, null);
assertEquals(TEST_NAL_POSITION, result); assertEquals(TEST_NAL_POSITION, result);
// Shouldn't find NAL unit whose prefix starts one byte past the offset. // Shouldn't find NAL unit whose prefix starts one byte past the offset.
result = Mp4Util.findNalUnit(data, TEST_NAL_POSITION + 1, data.length); result = H264Util.findNalUnit(data, TEST_NAL_POSITION + 1, data.length, null);
assertEquals(data.length, result); assertEquals(data.length, result);
} }
...@@ -54,9 +54,9 @@ public class Mp4UtilTest extends TestCase { ...@@ -54,9 +54,9 @@ public class Mp4UtilTest extends TestCase {
boolean[] prefixFlags = new boolean[3]; boolean[] prefixFlags = new boolean[3];
byte[] data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); byte[] data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1);
byte[] data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, data.length); byte[] data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, data.length);
int result = Mp4Util.findNalUnit(data1, 0, data1.length, prefixFlags); int result = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = Mp4Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(-1, result); assertEquals(-1, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -64,9 +64,9 @@ public class Mp4UtilTest extends TestCase { ...@@ -64,9 +64,9 @@ public class Mp4UtilTest extends TestCase {
prefixFlags = new boolean[3]; prefixFlags = new boolean[3];
data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 3); data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 3);
data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 3, data.length); data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 3, data.length);
result = Mp4Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = Mp4Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(-3, result); assertEquals(-3, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -75,11 +75,11 @@ public class Mp4UtilTest extends TestCase { ...@@ -75,11 +75,11 @@ public class Mp4UtilTest extends TestCase {
data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1);
data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2); data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2);
byte[] data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length); byte[] data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length);
result = Mp4Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = Mp4Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(data2.length, result); assertEquals(data2.length, result);
result = Mp4Util.findNalUnit(data3, 0, data3.length, prefixFlags); result = H264Util.findNalUnit(data3, 0, data3.length, prefixFlags);
assertEquals(-2, result); assertEquals(-2, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -89,13 +89,13 @@ public class Mp4UtilTest extends TestCase { ...@@ -89,13 +89,13 @@ public class Mp4UtilTest extends TestCase {
data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2); data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2);
data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, TEST_NAL_POSITION + 3); data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, TEST_NAL_POSITION + 3);
byte[] data4 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length); byte[] data4 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length);
result = Mp4Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = Mp4Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(data2.length, result); assertEquals(data2.length, result);
result = Mp4Util.findNalUnit(data3, 0, data3.length, prefixFlags); result = H264Util.findNalUnit(data3, 0, data3.length, prefixFlags);
assertEquals(data3.length, result); assertEquals(data3.length, result);
result = Mp4Util.findNalUnit(data4, 0, data4.length, prefixFlags); result = H264Util.findNalUnit(data4, 0, data4.length, prefixFlags);
assertEquals(-3, result); assertEquals(-3, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -103,9 +103,9 @@ public class Mp4UtilTest extends TestCase { ...@@ -103,9 +103,9 @@ public class Mp4UtilTest extends TestCase {
prefixFlags = new boolean[3]; prefixFlags = new boolean[3];
data1 = Arrays.copyOfRange(data, 0, TEST_PARTIAL_NAL_POSITION + 2); data1 = Arrays.copyOfRange(data, 0, TEST_PARTIAL_NAL_POSITION + 2);
data2 = Arrays.copyOfRange(data, TEST_PARTIAL_NAL_POSITION + 2, data.length); data2 = Arrays.copyOfRange(data, TEST_PARTIAL_NAL_POSITION + 2, data.length);
result = Mp4Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = Mp4Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(4, result); assertEquals(4, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment