Commit 508e13e0 by Oliver Woodman

Clean up + optimize ParsableByteArray.

parent 9092fad8
...@@ -36,12 +36,12 @@ import com.google.android.exoplayer.util.Util; ...@@ -36,12 +36,12 @@ import com.google.android.exoplayer.util.Util;
long basePosition = position + mpegAudioHeader.frameSize; long basePosition = position + mpegAudioHeader.frameSize;
// Read the VBRI header. // Read the VBRI header.
frame.skip(32); frame.skipBytes(32);
int headerData = frame.readInt(); int headerData = frame.readInt();
if (headerData != VBRI_HEADER) { if (headerData != VBRI_HEADER) {
return null; return null;
} }
frame.skip(10); frame.skipBytes(10);
int numFrames = frame.readInt(); int numFrames = frame.readInt();
if (numFrames <= 0) { if (numFrames <= 0) {
return null; return null;
......
...@@ -56,7 +56,7 @@ import com.google.android.exoplayer.util.Util; ...@@ -56,7 +56,7 @@ import com.google.android.exoplayer.util.Util;
xingBase = 9; xingBase = 9;
} }
} }
frame.skip(4 + xingBase); frame.skipBytes(4 + xingBase);
int headerData = frame.readInt(); int headerData = frame.readInt();
if (headerData != XING_HEADER && headerData != INFO_HEADER) { if (headerData != XING_HEADER && headerData != INFO_HEADER) {
return null; return null;
...@@ -80,7 +80,7 @@ import com.google.android.exoplayer.util.Util; ...@@ -80,7 +80,7 @@ import com.google.android.exoplayer.util.Util;
long sizeBytes = frame.readUnsignedIntToInt(); long sizeBytes = frame.readUnsignedIntToInt();
// Read table-of-contents as (flags & 4) == 4. // Read table-of-contents as (flags & 4) == 4.
frame.skip(1); frame.skipBytes(1);
long[] tableOfContents = new long[99]; long[] tableOfContents = new long[99];
for (int i = 0; i < 99; i++) { for (int i = 0; i < 99; i++) {
tableOfContents[i] = frame.readUnsignedByte(); tableOfContents[i] = frame.readUnsignedByte();
......
...@@ -121,7 +121,7 @@ import java.util.List; ...@@ -121,7 +121,7 @@ import java.util.List;
int remainingSamplesPerChunkChanges = stsc.readUnsignedIntToInt() - 1; int remainingSamplesPerChunkChanges = stsc.readUnsignedIntToInt() - 1;
Assertions.checkState(stsc.readInt() == 1, "stsc first chunk must be 1"); Assertions.checkState(stsc.readInt() == 1, "stsc first chunk must be 1");
int samplesPerChunk = stsc.readUnsignedIntToInt(); int samplesPerChunk = stsc.readUnsignedIntToInt();
stsc.skip(4); // Skip the sample description index. stsc.skipBytes(4); // Skip the sample description index.
int nextSamplesPerChunkChangeChunkIndex = -1; int nextSamplesPerChunkChangeChunkIndex = -1;
if (remainingSamplesPerChunkChanges > 0) { if (remainingSamplesPerChunkChanges > 0) {
// Store the chunk index when the samples-per-chunk will next change. // Store the chunk index when the samples-per-chunk will next change.
...@@ -220,7 +220,7 @@ import java.util.List; ...@@ -220,7 +220,7 @@ import java.util.List;
// Change the samples-per-chunk if required. // Change the samples-per-chunk if required.
if (chunkIndex == nextSamplesPerChunkChangeChunkIndex) { if (chunkIndex == nextSamplesPerChunkChangeChunkIndex) {
samplesPerChunk = stsc.readUnsignedIntToInt(); samplesPerChunk = stsc.readUnsignedIntToInt();
stsc.skip(4); // Skip the sample description index. stsc.skipBytes(4); // Skip the sample description index.
remainingSamplesPerChunkChanges--; remainingSamplesPerChunkChanges--;
if (remainingSamplesPerChunkChanges > 0) { if (remainingSamplesPerChunkChanges > 0) {
nextSamplesPerChunkChangeChunkIndex = stsc.readUnsignedIntToInt() - 1; nextSamplesPerChunkChangeChunkIndex = stsc.readUnsignedIntToInt() - 1;
...@@ -260,7 +260,7 @@ import java.util.List; ...@@ -260,7 +260,7 @@ import java.util.List;
int fullAtom = mvhd.readInt(); int fullAtom = mvhd.readInt();
int version = Atom.parseFullAtomVersion(fullAtom); int version = Atom.parseFullAtomVersion(fullAtom);
mvhd.skip(version == 0 ? 8 : 16); mvhd.skipBytes(version == 0 ? 8 : 16);
return mvhd.readUnsignedInt(); return mvhd.readUnsignedInt();
} }
...@@ -276,10 +276,10 @@ import java.util.List; ...@@ -276,10 +276,10 @@ import java.util.List;
int fullAtom = tkhd.readInt(); int fullAtom = tkhd.readInt();
int version = Atom.parseFullAtomVersion(fullAtom); int version = Atom.parseFullAtomVersion(fullAtom);
tkhd.skip(version == 0 ? 8 : 16); tkhd.skipBytes(version == 0 ? 8 : 16);
int trackId = tkhd.readInt(); int trackId = tkhd.readInt();
tkhd.skip(4); tkhd.skipBytes(4);
boolean durationUnknown = true; boolean durationUnknown = true;
int durationPosition = tkhd.getPosition(); int durationPosition = tkhd.getPosition();
...@@ -292,7 +292,7 @@ import java.util.List; ...@@ -292,7 +292,7 @@ import java.util.List;
} }
long duration; long duration;
if (durationUnknown) { if (durationUnknown) {
tkhd.skip(durationByteCount); tkhd.skipBytes(durationByteCount);
duration = -1; duration = -1;
} else { } else {
duration = version == 0 ? tkhd.readUnsignedInt() : tkhd.readUnsignedLongToLong(); duration = version == 0 ? tkhd.readUnsignedInt() : tkhd.readUnsignedLongToLong();
...@@ -323,7 +323,7 @@ import java.util.List; ...@@ -323,7 +323,7 @@ import java.util.List;
int fullAtom = mdhd.readInt(); int fullAtom = mdhd.readInt();
int version = Atom.parseFullAtomVersion(fullAtom); int version = Atom.parseFullAtomVersion(fullAtom);
mdhd.skip(version == 0 ? 8 : 16); mdhd.skipBytes(version == 0 ? 8 : 16);
return mdhd.readUnsignedInt(); return mdhd.readUnsignedInt();
} }
...@@ -365,11 +365,11 @@ import java.util.List; ...@@ -365,11 +365,11 @@ import java.util.List;
int position, int size, long durationUs) { int position, int size, long durationUs) {
parent.setPosition(position + Atom.HEADER_SIZE); parent.setPosition(position + Atom.HEADER_SIZE);
parent.skip(24); parent.skipBytes(24);
int width = parent.readUnsignedShort(); int width = parent.readUnsignedShort();
int height = parent.readUnsignedShort(); int height = parent.readUnsignedShort();
float pixelWidthHeightRatio = 1; float pixelWidthHeightRatio = 1;
parent.skip(50); parent.skipBytes(50);
List<byte[]> initializationData = null; List<byte[]> initializationData = null;
TrackEncryptionBox trackEncryptionBox = null; TrackEncryptionBox trackEncryptionBox = null;
...@@ -434,7 +434,7 @@ import java.util.List; ...@@ -434,7 +434,7 @@ import java.util.List;
if (childAtomType == Atom.TYPE_frma) { if (childAtomType == Atom.TYPE_frma) {
parent.readInt(); // dataFormat. parent.readInt(); // dataFormat.
} else if (childAtomType == Atom.TYPE_schm) { } else if (childAtomType == Atom.TYPE_schm) {
parent.skip(4); parent.skipBytes(4);
parent.readInt(); // schemeType. Expect cenc parent.readInt(); // schemeType. Expect cenc
parent.readInt(); // schemeVersion. Expect 0x00010000 parent.readInt(); // schemeVersion. Expect 0x00010000
} else if (childAtomType == Atom.TYPE_schi) { } else if (childAtomType == Atom.TYPE_schi) {
...@@ -461,7 +461,7 @@ import java.util.List; ...@@ -461,7 +461,7 @@ import java.util.List;
int childAtomSize = parent.readInt(); int childAtomSize = parent.readInt();
int childAtomType = parent.readInt(); int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_tenc) { if (childAtomType == Atom.TYPE_tenc) {
parent.skip(4); parent.skipBytes(4);
int firstInt = parent.readInt(); int firstInt = parent.readInt();
boolean defaultIsEncrypted = (firstInt >> 8) == 1; boolean defaultIsEncrypted = (firstInt >> 8) == 1;
int defaultInitVectorSize = firstInt & 0xFF; int defaultInitVectorSize = firstInt & 0xFF;
...@@ -479,10 +479,10 @@ import java.util.List; ...@@ -479,10 +479,10 @@ import java.util.List;
long durationUs) { long durationUs) {
parent.setPosition(position + Atom.HEADER_SIZE); parent.setPosition(position + Atom.HEADER_SIZE);
parent.skip(24); parent.skipBytes(24);
int width = parent.readUnsignedShort(); int width = parent.readUnsignedShort();
int height = parent.readUnsignedShort(); int height = parent.readUnsignedShort();
parent.skip(50); parent.skipBytes(50);
List<byte[]> initializationData = new ArrayList<byte[]>(1); List<byte[]> initializationData = new ArrayList<byte[]>(1);
int childPosition = parent.getPosition(); int childPosition = parent.getPosition();
...@@ -505,10 +505,10 @@ import java.util.List; ...@@ -505,10 +505,10 @@ import java.util.List;
private static Pair<MediaFormat, TrackEncryptionBox> parseAudioSampleEntry( private static Pair<MediaFormat, TrackEncryptionBox> parseAudioSampleEntry(
ParsableByteArray parent, int atomType, int position, int size, long durationUs) { ParsableByteArray parent, int atomType, int position, int size, long durationUs) {
parent.setPosition(position + Atom.HEADER_SIZE); parent.setPosition(position + Atom.HEADER_SIZE);
parent.skip(16); parent.skipBytes(16);
int channelCount = parent.readUnsignedShort(); int channelCount = parent.readUnsignedShort();
int sampleSize = parent.readUnsignedShort(); int sampleSize = parent.readUnsignedShort();
parent.skip(4); parent.skipBytes(4);
int sampleRate = parent.readUnsignedFixedPoint1616(); int sampleRate = parent.readUnsignedFixedPoint1616();
int bitrate = MediaFormat.NO_VALUE; int bitrate = MediaFormat.NO_VALUE;
...@@ -571,34 +571,34 @@ import java.util.List; ...@@ -571,34 +571,34 @@ import java.util.List;
private static byte[] parseEsdsFromParent(ParsableByteArray parent, int position) { private static byte[] parseEsdsFromParent(ParsableByteArray parent, int position) {
parent.setPosition(position + Atom.HEADER_SIZE + 4); parent.setPosition(position + Atom.HEADER_SIZE + 4);
// Start of the ES_Descriptor (defined in 14496-1) // Start of the ES_Descriptor (defined in 14496-1)
parent.skip(1); // ES_Descriptor tag parent.skipBytes(1); // ES_Descriptor tag
int varIntByte = parent.readUnsignedByte(); int varIntByte = parent.readUnsignedByte();
while (varIntByte > 127) { while (varIntByte > 127) {
varIntByte = parent.readUnsignedByte(); varIntByte = parent.readUnsignedByte();
} }
parent.skip(2); // ES_ID parent.skipBytes(2); // ES_ID
int flags = parent.readUnsignedByte(); int flags = parent.readUnsignedByte();
if ((flags & 0x80 /* streamDependenceFlag */) != 0) { if ((flags & 0x80 /* streamDependenceFlag */) != 0) {
parent.skip(2); parent.skipBytes(2);
} }
if ((flags & 0x40 /* URL_Flag */) != 0) { if ((flags & 0x40 /* URL_Flag */) != 0) {
parent.skip(parent.readUnsignedShort()); parent.skipBytes(parent.readUnsignedShort());
} }
if ((flags & 0x20 /* OCRstreamFlag */) != 0) { if ((flags & 0x20 /* OCRstreamFlag */) != 0) {
parent.skip(2); parent.skipBytes(2);
} }
// Start of the DecoderConfigDescriptor (defined in 14496-1) // Start of the DecoderConfigDescriptor (defined in 14496-1)
parent.skip(1); // DecoderConfigDescriptor tag parent.skipBytes(1); // DecoderConfigDescriptor tag
varIntByte = parent.readUnsignedByte(); varIntByte = parent.readUnsignedByte();
while (varIntByte > 127) { while (varIntByte > 127) {
varIntByte = parent.readUnsignedByte(); varIntByte = parent.readUnsignedByte();
} }
parent.skip(13); parent.skipBytes(13);
// Start of AudioSpecificConfig (defined in 14496-3) // Start of AudioSpecificConfig (defined in 14496-3)
parent.skip(1); // AudioSpecificConfig tag parent.skipBytes(1); // AudioSpecificConfig tag
varIntByte = parent.readUnsignedByte(); varIntByte = parent.readUnsignedByte();
int varInt = varIntByte & 0x7F; int varInt = varIntByte & 0x7F;
while (varIntByte > 127) { while (varIntByte > 127) {
......
...@@ -342,7 +342,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -342,7 +342,7 @@ public final class FragmentedMp4Extractor implements Extractor {
int fullAtom = saiz.readInt(); int fullAtom = saiz.readInt();
int flags = Atom.parseFullAtomFlags(fullAtom); int flags = Atom.parseFullAtomFlags(fullAtom);
if ((flags & 0x01) == 1) { if ((flags & 0x01) == 1) {
saiz.skip(8); saiz.skipBytes(8);
} }
int defaultSampleInfoSize = saiz.readUnsignedByte(); int defaultSampleInfoSize = saiz.readUnsignedByte();
...@@ -379,9 +379,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -379,9 +379,9 @@ public final class FragmentedMp4Extractor implements Extractor {
int fullAtom = tfhd.readInt(); int fullAtom = tfhd.readInt();
int flags = Atom.parseFullAtomFlags(fullAtom); int flags = Atom.parseFullAtomFlags(fullAtom);
tfhd.skip(4); // trackId tfhd.skipBytes(4); // trackId
if ((flags & 0x01 /* base_data_offset_present */) != 0) { if ((flags & 0x01 /* base_data_offset_present */) != 0) {
tfhd.skip(8); tfhd.skipBytes(8);
} }
int defaultSampleDescriptionIndex = int defaultSampleDescriptionIndex =
...@@ -427,7 +427,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -427,7 +427,7 @@ public final class FragmentedMp4Extractor implements Extractor {
int sampleCount = trun.readUnsignedIntToInt(); int sampleCount = trun.readUnsignedIntToInt();
if ((flags & 0x01 /* data_offset_present */) != 0) { if ((flags & 0x01 /* data_offset_present */) != 0) {
trun.skip(4); trun.skipBytes(4);
} }
boolean firstSampleFlagsPresent = (flags & 0x04 /* first_sample_flags_present */) != 0; boolean firstSampleFlagsPresent = (flags & 0x04 /* first_sample_flags_present */) != 0;
...@@ -528,7 +528,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -528,7 +528,7 @@ public final class FragmentedMp4Extractor implements Extractor {
int fullAtom = atom.readInt(); int fullAtom = atom.readInt();
int version = Atom.parseFullAtomVersion(fullAtom); int version = Atom.parseFullAtomVersion(fullAtom);
atom.skip(4); atom.skipBytes(4);
long timescale = atom.readUnsignedInt(); long timescale = atom.readUnsignedInt();
long earliestPresentationTime; long earliestPresentationTime;
long offset = inputPosition; long offset = inputPosition;
...@@ -540,7 +540,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -540,7 +540,7 @@ public final class FragmentedMp4Extractor implements Extractor {
offset += atom.readUnsignedLongToLong(); offset += atom.readUnsignedLongToLong();
} }
atom.skip(2); atom.skipBytes(2);
int referenceCount = atom.readUnsignedShort(); int referenceCount = atom.readUnsignedShort();
int[] sizes = new int[referenceCount]; int[] sizes = new int[referenceCount];
...@@ -569,7 +569,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -569,7 +569,7 @@ public final class FragmentedMp4Extractor implements Extractor {
timeUs = Util.scaleLargeTimestamp(time, C.MICROS_PER_SECOND, timescale); timeUs = Util.scaleLargeTimestamp(time, C.MICROS_PER_SECOND, timescale);
durationsUs[i] = timeUs - timesUs[i]; durationsUs[i] = timeUs - timesUs[i];
atom.skip(4); atom.skipBytes(4);
offset += sizes[i]; offset += sizes[i];
} }
...@@ -670,7 +670,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -670,7 +670,7 @@ public final class FragmentedMp4Extractor implements Extractor {
} }
// Write the subsample encryption data. // Write the subsample encryption data.
int subsampleCount = sampleEncryptionData.readUnsignedShort(); int subsampleCount = sampleEncryptionData.readUnsignedShort();
sampleEncryptionData.skip(-2); sampleEncryptionData.skipBytes(-2);
int subsampleDataLength = 2 + 6 * subsampleCount; int subsampleDataLength = 2 + 6 * subsampleCount;
trackOutput.sampleData(sampleEncryptionData, subsampleDataLength); trackOutput.sampleData(sampleEncryptionData, subsampleDataLength);
return 1 + vectorSize + subsampleDataLength; return 1 + vectorSize + subsampleDataLength;
......
...@@ -37,7 +37,7 @@ import com.google.android.exoplayer.util.ParsableByteArray; ...@@ -37,7 +37,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
@Override @Override
public void consume(ParsableByteArray seiBuffer, long pesTimeUs, boolean startOfPacket) { public void consume(ParsableByteArray seiBuffer, long pesTimeUs, boolean startOfPacket) {
// Skip the NAL prefix and type. // Skip the NAL prefix and type.
seiBuffer.skip(4); seiBuffer.skipBytes(4);
int b; int b;
while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) { while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) {
...@@ -58,7 +58,7 @@ import com.google.android.exoplayer.util.ParsableByteArray; ...@@ -58,7 +58,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
output.sampleData(seiBuffer, payloadSize); output.sampleData(seiBuffer, payloadSize);
output.sampleMetadata(pesTimeUs, C.SAMPLE_FLAG_SYNC, payloadSize, 0, null); output.sampleMetadata(pesTimeUs, C.SAMPLE_FLAG_SYNC, payloadSize, 0, null);
} else { } else {
seiBuffer.skip(payloadSize); seiBuffer.skipBytes(payloadSize);
} }
} }
} }
......
...@@ -104,7 +104,7 @@ public final class TsExtractor implements Extractor { ...@@ -104,7 +104,7 @@ public final class TsExtractor implements Extractor {
// Skip the adaptation field. // Skip the adaptation field.
if (adaptationFieldExists) { if (adaptationFieldExists) {
int adaptationFieldLength = tsPacketBuffer.readUnsignedByte(); int adaptationFieldLength = tsPacketBuffer.readUnsignedByte();
tsPacketBuffer.skip(adaptationFieldLength); tsPacketBuffer.skipBytes(adaptationFieldLength);
} }
// Read the payload. // Read the payload.
...@@ -172,7 +172,7 @@ public final class TsExtractor implements Extractor { ...@@ -172,7 +172,7 @@ public final class TsExtractor implements Extractor {
// Skip pointer. // Skip pointer.
if (payloadUnitStartIndicator) { if (payloadUnitStartIndicator) {
int pointerField = data.readUnsignedByte(); int pointerField = data.readUnsignedByte();
data.skip(pointerField); data.skipBytes(pointerField);
} }
data.readBytes(patScratch, 3); data.readBytes(patScratch, 3);
...@@ -180,7 +180,7 @@ public final class TsExtractor implements Extractor { ...@@ -180,7 +180,7 @@ public final class TsExtractor implements Extractor {
int sectionLength = patScratch.readBits(12); int sectionLength = patScratch.readBits(12);
// transport_stream_id (16), reserved (2), version_number (5), current_next_indicator (1), // transport_stream_id (16), reserved (2), version_number (5), current_next_indicator (1),
// section_number (8), last_section_number (8) // section_number (8), last_section_number (8)
data.skip(5); data.skipBytes(5);
int programCount = (sectionLength - 9) / 4; int programCount = (sectionLength - 9) / 4;
for (int i = 0; i < programCount; i++) { for (int i = 0; i < programCount; i++) {
...@@ -212,7 +212,7 @@ public final class TsExtractor implements Extractor { ...@@ -212,7 +212,7 @@ public final class TsExtractor implements Extractor {
// Skip pointer. // Skip pointer.
if (payloadUnitStartIndicator) { if (payloadUnitStartIndicator) {
int pointerField = data.readUnsignedByte(); int pointerField = data.readUnsignedByte();
data.skip(pointerField); data.skipBytes(pointerField);
} }
data.readBytes(pmtScratch, 3); data.readBytes(pmtScratch, 3);
...@@ -222,14 +222,14 @@ public final class TsExtractor implements Extractor { ...@@ -222,14 +222,14 @@ public final class TsExtractor implements Extractor {
// program_number (16), reserved (2), version_number (5), current_next_indicator (1), // program_number (16), reserved (2), version_number (5), current_next_indicator (1),
// section_number (8), last_section_number (8), reserved (3), PCR_PID (13) // section_number (8), last_section_number (8), reserved (3), PCR_PID (13)
// Skip the rest of the PMT header. // Skip the rest of the PMT header.
data.skip(7); data.skipBytes(7);
data.readBytes(pmtScratch, 2); data.readBytes(pmtScratch, 2);
pmtScratch.skipBits(4); pmtScratch.skipBits(4);
int programInfoLength = pmtScratch.readBits(12); int programInfoLength = pmtScratch.readBits(12);
// Skip the descriptors. // Skip the descriptors.
data.skip(programInfoLength); data.skipBytes(programInfoLength);
int entriesSize = sectionLength - 9 /* Size of the rest of the fields before descriptors */ int entriesSize = sectionLength - 9 /* Size of the rest of the fields before descriptors */
- programInfoLength - 4 /* CRC size */; - programInfoLength - 4 /* CRC size */;
...@@ -242,7 +242,7 @@ public final class TsExtractor implements Extractor { ...@@ -242,7 +242,7 @@ public final class TsExtractor implements Extractor {
int esInfoLength = pmtScratch.readBits(12); int esInfoLength = pmtScratch.readBits(12);
// Skip the descriptors. // Skip the descriptors.
data.skip(esInfoLength); data.skipBytes(esInfoLength);
entriesSize -= esInfoLength + 5; entriesSize -= esInfoLength + 5;
if (streamReaders.get(streamType) != null) { if (streamReaders.get(streamType) != null) {
...@@ -341,7 +341,7 @@ public final class TsExtractor implements Extractor { ...@@ -341,7 +341,7 @@ public final class TsExtractor implements Extractor {
while (data.bytesLeft() > 0) { while (data.bytesLeft() > 0) {
switch (state) { switch (state) {
case STATE_FINDING_HEADER: case STATE_FINDING_HEADER:
data.skip(data.bytesLeft()); data.skipBytes(data.bytesLeft());
break; break;
case STATE_READING_HEADER: case STATE_READING_HEADER:
if (continueRead(data, pesScratch.getData(), HEADER_SIZE)) { if (continueRead(data, pesScratch.getData(), HEADER_SIZE)) {
...@@ -398,7 +398,7 @@ public final class TsExtractor implements Extractor { ...@@ -398,7 +398,7 @@ public final class TsExtractor implements Extractor {
if (bytesToRead <= 0) { if (bytesToRead <= 0) {
return true; return true;
} else if (target == null) { } else if (target == null) {
source.skip(bytesToRead); source.skipBytes(bytesToRead);
} else { } else {
source.readBytes(target, bytesRead, bytesToRead); source.readBytes(target, bytesRead, bytesToRead);
} }
......
...@@ -57,7 +57,7 @@ public class Id3Parser implements MetadataParser<Map<String, Object>> { ...@@ -57,7 +57,7 @@ public class Id3Parser implements MetadataParser<Map<String, Object>> {
} }
// Skip frame flags. // Skip frame flags.
id3Data.skip(2); id3Data.skipBytes(2);
// Check Frame ID == TXXX. // Check Frame ID == TXXX.
if (frameId0 == 'T' && frameId1 == 'X' && frameId2 == 'X' && frameId3 == 'X') { if (frameId0 == 'T' && frameId1 == 'X' && frameId2 == 'X' && frameId3 == 'X') {
int encoding = id3Data.readUnsignedByte(); int encoding = id3Data.readUnsignedByte();
...@@ -168,7 +168,7 @@ public class Id3Parser implements MetadataParser<Map<String, Object>> { ...@@ -168,7 +168,7 @@ public class Id3Parser implements MetadataParser<Map<String, Object>> {
throw new ParserException(String.format( throw new ParserException(String.format(
"Unexpected ID3 file identifier, expected \"ID3\", actual \"%c%c%c\".", id1, id2, id3)); "Unexpected ID3 file identifier, expected \"ID3\", actual \"%c%c%c\".", id1, id2, id3));
} }
id3Buffer.skip(2); // Skip version. id3Buffer.skipBytes(2); // Skip version.
int flags = id3Buffer.readUnsignedByte(); int flags = id3Buffer.readUnsignedByte();
int id3Size = id3Buffer.readSynchSafeInt(); int id3Size = id3Buffer.readSynchSafeInt();
...@@ -177,7 +177,7 @@ public class Id3Parser implements MetadataParser<Map<String, Object>> { ...@@ -177,7 +177,7 @@ public class Id3Parser implements MetadataParser<Map<String, Object>> {
if ((flags & 0x2) != 0) { if ((flags & 0x2) != 0) {
int extendedHeaderSize = id3Buffer.readSynchSafeInt(); int extendedHeaderSize = id3Buffer.readSynchSafeInt();
if (extendedHeaderSize > 4) { if (extendedHeaderSize > 4) {
id3Buffer.skip(extendedHeaderSize - 4); id3Buffer.skipBytes(extendedHeaderSize - 4);
} }
id3Size -= extendedHeaderSize; id3Size -= extendedHeaderSize;
} }
......
...@@ -48,7 +48,7 @@ public final class H264Util { ...@@ -48,7 +48,7 @@ public final class H264Util {
public static byte[] parseChildNalUnit(ParsableByteArray atom) { public static byte[] parseChildNalUnit(ParsableByteArray atom) {
int length = atom.readUnsignedShort(); int length = atom.readUnsignedShort();
int offset = atom.getPosition(); int offset = atom.getPosition();
atom.skip(length); atom.skipBytes(length);
return CodecSpecificDataUtil.buildNalUnit(atom.data, offset, length); return CodecSpecificDataUtil.buildNalUnit(atom.data, offset, length);
} }
......
...@@ -123,9 +123,7 @@ public final class ParsableByteArray { ...@@ -123,9 +123,7 @@ public final class ParsableByteArray {
* @throws IllegalArgumentException Thrown if the new position is neither in nor at the end of the * @throws IllegalArgumentException Thrown if the new position is neither in nor at the end of the
* array. * array.
*/ */
// TODO: Rename to skipBytes so that it's clearer how much data is being skipped in code where public void skipBytes(int bytes) {
// both ParsableBitArray and ParsableByteArray are in use.
public void skip(int bytes) {
setPosition(position + bytes); setPosition(position + bytes);
} }
...@@ -136,8 +134,6 @@ public final class ParsableByteArray { ...@@ -136,8 +134,6 @@ public final class ParsableByteArray {
* @param bitArray The {@link ParsableBitArray} into which the bytes should be read. * @param bitArray The {@link ParsableBitArray} into which the bytes should be read.
* @param length The number of bytes to write. * @param length The number of bytes to write.
*/ */
// TODO: It's possible to have bitArray directly index into the same array as is being wrapped
// by this instance. Decide whether it's worth doing this.
public void readBytes(ParsableBitArray bitArray, int length) { public void readBytes(ParsableBitArray bitArray, int length) {
readBytes(bitArray.getData(), 0, length); readBytes(bitArray.getData(), 0, length);
bitArray.setPosition(0); bitArray.setPosition(0);
...@@ -165,52 +161,55 @@ public final class ParsableByteArray { ...@@ -165,52 +161,55 @@ public final class ParsableByteArray {
/** Reads the next byte as an unsigned value. */ /** Reads the next byte as an unsigned value. */
public int readUnsignedByte() { public int readUnsignedByte() {
int result = shiftIntoInt(data, position, 1); return (data[position++] & 0xFF);
position += 1;
return result;
} }
/** Reads the next two bytes as an unsigned value. */ /** Reads the next two bytes as an unsigned value. */
public int readUnsignedShort() { public int readUnsignedShort() {
int result = shiftIntoInt(data, position, 2); return (data[position++] & 0xFF) << 8
position += 2; | (data[position++] & 0xFF);
return result;
} }
/** Reads the next three bytes as an unsigned value. */ /** Reads the next three bytes as an unsigned value. */
public int readUnsignedInt24() { public int readUnsignedInt24() {
int result = shiftIntoInt(data, position, 3); return (data[position++] & 0xFF) << 16
position += 3; | (data[position++] & 0xFF) << 8
return result; | (data[position++] & 0xFF);
} }
/** Reads the next four bytes as an unsigned value. */ /** Reads the next four bytes as an unsigned value. */
public long readUnsignedInt() { public long readUnsignedInt() {
long result = shiftIntoLong(data, position, 4); return (data[position++] & 0xFFL) << 24
position += 4; | (data[position++] & 0xFFL) << 16
return result; | (data[position++] & 0xFFL) << 8
| (data[position++] & 0xFFL);
} }
/** Reads the next four bytes as a signed value. */ /** Reads the next four bytes as a signed value. */
public int readInt() { public int readInt() {
// shiftIntoInt inlined as performance optimization.
return (data[position++] & 0xFF) << 24 return (data[position++] & 0xFF) << 24
| (data[position++] & 0xFF) << 16 | (data[position++] & 0xFF) << 16
| (data[position++] & 0xFF) << 8 | (data[position++] & 0xFF) << 8
| data[position++] & 0xFF; | (data[position++] & 0xFF);
} }
/** Reads the next eight bytes as a signed value. */ /** Reads the next eight bytes as a signed value. */
public long readLong() { public long readLong() {
long result = shiftIntoLong(data, position, 8); return (data[position++] & 0xFFL) << 56
position += 8; | (data[position++] & 0xFFL) << 48
return result; | (data[position++] & 0xFFL) << 40
| (data[position++] & 0xFFL) << 32
| (data[position++] & 0xFFL) << 24
| (data[position++] & 0xFFL) << 16
| (data[position++] & 0xFFL) << 8
| (data[position++] & 0xFFL);
} }
/** Reads the next four bytes, returning the integer portion of the fixed point 16.16 integer. */ /** Reads the next four bytes, returning the integer portion of the fixed point 16.16 integer. */
public int readUnsignedFixedPoint1616() { public int readUnsignedFixedPoint1616() {
int result = shiftIntoInt(data, position, 2); int result = (data[position++] & 0xFF) << 8
position += 4; | (data[position++] & 0xFF);
position += 2; // Skip the non-integer portion.
return result; return result;
} }
...@@ -233,16 +232,12 @@ public final class ParsableByteArray { ...@@ -233,16 +232,12 @@ public final class ParsableByteArray {
/** /**
* Reads the next four bytes as an unsigned integer into an integer, if the top bit is a zero. * Reads the next four bytes as an unsigned integer into an integer, if the top bit is a zero.
* *
* @throws IllegalArgumentException Thrown if the top bit of the input data is set. * @throws IllegalStateException Thrown if the top bit of the input data is set.
*/ */
public int readUnsignedIntToInt() { public int readUnsignedIntToInt() {
// shiftIntoInt inlined as performance optimization. int result = readInt();
final int result = (data[position++] & 0xFF) << 24
| (data[position++] & 0xFF) << 16
| (data[position++] & 0xFF) << 8
| data[position++] & 0xFF;
if (result < 0) { if (result < 0) {
throw new IllegalArgumentException("Top bit not zero: " + result); throw new IllegalStateException("Top bit not zero: " + result);
} }
return result; return result;
} }
...@@ -250,33 +245,12 @@ public final class ParsableByteArray { ...@@ -250,33 +245,12 @@ public final class ParsableByteArray {
/** /**
* Reads the next eight bytes as an unsigned long into a long, if the top bit is a zero. * Reads the next eight bytes as an unsigned long into a long, if the top bit is a zero.
* *
* @throws IllegalArgumentException Thrown if the top bit of the input data is set. * @throws IllegalStateException Thrown if the top bit of the input data is set.
*/ */
public long readUnsignedLongToLong() { public long readUnsignedLongToLong() {
long result = shiftIntoLong(data, position, 8); long result = readLong();
position += 8;
if (result < 0) { if (result < 0) {
throw new IllegalArgumentException("Top bit not zero: " + result); throw new IllegalStateException("Top bit not zero: " + result);
}
return result;
}
/** Reads {@code length} bytes into an int at {@code offset} in {@code bytes}. */
private static int shiftIntoInt(byte[] bytes, int offset, int length) {
int result = 0xFF & bytes[offset];
for (int i = offset + 1; i < offset + length; i++) {
result <<= 8;
result |= 0xFF & bytes[i];
}
return result;
}
/** Reads {@code length} bytes into a long at {@code offset} in {@code bytes}. */
private static long shiftIntoLong(byte[] bytes, int offset, int length) {
long result = 0xFF & bytes[offset];
for (int i = offset + 1; i < offset + length; i++) {
result <<= 8;
result |= 0xFF & bytes[i];
} }
return result; return result;
} }
......
...@@ -57,7 +57,7 @@ public class UrlTemplateTest extends TestCase { ...@@ -57,7 +57,7 @@ public class UrlTemplateTest extends TestCase {
String template = "$IllegalId$"; String template = "$IllegalId$";
try { try {
UrlTemplate.compile(template); UrlTemplate.compile(template);
assertTrue(false); fail();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Expected. // Expected.
} }
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer.util; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer.util;
import junit.framework.TestCase; import junit.framework.TestCase;
import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
/** /**
...@@ -24,49 +25,176 @@ import java.util.Arrays; ...@@ -24,49 +25,176 @@ import java.util.Arrays;
*/ */
public class ParsableByteArrayTest extends TestCase { public class ParsableByteArrayTest extends TestCase {
private static final byte[] ARRAY_ELEMENTS = private static final byte[] TEST_DATA =
new byte[] {0x0F, (byte) 0xFF, (byte) 0x42, (byte) 0x0F, 0x00, 0x00, 0x00, 0x00}; new byte[] {0x0F, (byte) 0xFF, (byte) 0x42, (byte) 0x0F, 0x00, 0x00, 0x00, 0x00};
private ParsableByteArray parsableByteArray; private static ParsableByteArray getTestDataArray() {
ParsableByteArray testArray = new ParsableByteArray(TEST_DATA.length);
@Override System.arraycopy(TEST_DATA, 0, testArray.data, 0, TEST_DATA.length);
public void setUp() { return testArray;
parsableByteArray = new ParsableByteArray(ARRAY_ELEMENTS.length);
System.arraycopy(ARRAY_ELEMENTS, 0, parsableByteArray.data, 0, ARRAY_ELEMENTS.length);
} }
public void testReadInt() { public void testReadInt() {
// When reading a signed integer testReadInt(0);
int value = parsableByteArray.readInt(); testReadInt(1);
testReadInt(-1);
testReadInt(Integer.MIN_VALUE);
testReadInt(Integer.MAX_VALUE);
}
private static void testReadInt(int testValue) {
ParsableByteArray testArray = new ParsableByteArray(
ByteBuffer.allocate(4).putInt(testValue).array());
int readValue = testArray.readInt();
// Assert that the value we read was the value we wrote.
assertEquals(testValue, readValue);
// And that the position advanced as expected.
assertEquals(4, testArray.getPosition());
// Then the read value is equal to the array elements interpreted as an int. // And that skipping back and reading gives the same results.
assertEquals((0xFF & ARRAY_ELEMENTS[0]) << 24 | (0xFF & ARRAY_ELEMENTS[1]) << 16 testArray.skipBytes(-4);
| (0xFF & ARRAY_ELEMENTS[2]) << 8 | (0xFF & ARRAY_ELEMENTS[3]), value); readValue = testArray.readInt();
assertEquals(testValue, readValue);
assertEquals(4, testArray.getPosition());
} }
public void testSkipBack() { public void testReadUnsignedInt() {
// When reading an unsigned integer testReadUnsignedInt(0);
long value = parsableByteArray.readUnsignedInt(); testReadUnsignedInt(1);
testReadUnsignedInt(Integer.MAX_VALUE);
testReadUnsignedInt(Integer.MAX_VALUE + 1L);
testReadUnsignedInt(0xFFFFFFFFL);
}
private static void testReadUnsignedInt(long testValue) {
ParsableByteArray testArray = new ParsableByteArray(
Arrays.copyOfRange(ByteBuffer.allocate(8).putLong(testValue).array(), 4, 8));
long readValue = testArray.readUnsignedInt();
// Assert that the value we read was the value we wrote.
assertEquals(testValue, readValue);
// And that the position advanced as expected.
assertEquals(4, testArray.getPosition());
// Then skipping back and reading gives the same value. // And that skipping back and reading gives the same results.
parsableByteArray.skip(-4); testArray.skipBytes(-4);
assertEquals(value, parsableByteArray.readUnsignedInt()); readValue = testArray.readUnsignedInt();
assertEquals(testValue, readValue);
assertEquals(4, testArray.getPosition());
}
public void testReadUnsignedIntToInt() {
testReadUnsignedIntToInt(0);
testReadUnsignedIntToInt(1);
testReadUnsignedIntToInt(Integer.MAX_VALUE);
try {
testReadUnsignedIntToInt(-1);
fail();
} catch (IllegalStateException e) {
// Expected.
}
try {
testReadUnsignedIntToInt(Integer.MIN_VALUE);
fail();
} catch (IllegalStateException e) {
// Expected.
}
}
private static void testReadUnsignedIntToInt(int testValue) {
ParsableByteArray testArray = new ParsableByteArray(
ByteBuffer.allocate(4).putInt(testValue).array());
int readValue = testArray.readUnsignedIntToInt();
// Assert that the value we read was the value we wrote.
assertEquals(testValue, readValue);
// And that the position advanced as expected.
assertEquals(4, testArray.getPosition());
// And that skipping back and reading gives the same results.
testArray.skipBytes(-4);
readValue = testArray.readUnsignedIntToInt();
assertEquals(testValue, readValue);
assertEquals(4, testArray.getPosition());
}
public void testReadUnsignedLongToLong() {
testReadUnsignedLongToLong(0);
testReadUnsignedLongToLong(1);
testReadUnsignedLongToLong(Long.MAX_VALUE);
try {
testReadUnsignedLongToLong(-1);
fail();
} catch (IllegalStateException e) {
// Expected.
}
try {
testReadUnsignedLongToLong(Long.MIN_VALUE);
fail();
} catch (IllegalStateException e) {
// Expected.
}
}
private static void testReadUnsignedLongToLong(long testValue) {
ParsableByteArray testArray = new ParsableByteArray(
ByteBuffer.allocate(8).putLong(testValue).array());
long readValue = testArray.readUnsignedLongToLong();
// Assert that the value we read was the value we wrote.
assertEquals(testValue, readValue);
// And that the position advanced as expected.
assertEquals(8, testArray.getPosition());
// And that skipping back and reading gives the same results.
testArray.skipBytes(-8);
readValue = testArray.readUnsignedLongToLong();
assertEquals(testValue, readValue);
assertEquals(8, testArray.getPosition());
}
public void testReadLong() {
testReadLong(0);
testReadLong(1);
testReadLong(-1);
testReadLong(Long.MIN_VALUE);
testReadLong(Long.MAX_VALUE);
}
private static void testReadLong(long testValue) {
ParsableByteArray testArray = new ParsableByteArray(
ByteBuffer.allocate(8).putLong(testValue).array());
long readValue = testArray.readLong();
// Assert that the value we read was the value we wrote.
assertEquals(testValue, readValue);
// And that the position advanced as expected.
assertEquals(8, testArray.getPosition());
// And that skipping back and reading gives the same results.
testArray.skipBytes(-8);
readValue = testArray.readLong();
assertEquals(testValue, readValue);
assertEquals(8, testArray.getPosition());
} }
public void testReadingMovesPosition() { public void testReadingMovesPosition() {
ParsableByteArray parsableByteArray = getTestDataArray();
// Given an array at the start // Given an array at the start
assertEquals(0, parsableByteArray.getPosition()); assertEquals(0, parsableByteArray.getPosition());
// When reading an integer, the position advances // When reading an integer, the position advances
parsableByteArray.readUnsignedInt(); parsableByteArray.readUnsignedInt();
assertEquals(4, parsableByteArray.getPosition()); assertEquals(4, parsableByteArray.getPosition());
} }
public void testOutOfBoundsThrows() { public void testOutOfBoundsThrows() {
ParsableByteArray parsableByteArray = getTestDataArray();
// Given an array at the end // Given an array at the end
parsableByteArray.readUnsignedLongToLong(); parsableByteArray.readUnsignedLongToLong();
assertEquals(ARRAY_ELEMENTS.length, parsableByteArray.getPosition()); assertEquals(TEST_DATA.length, parsableByteArray.getPosition());
// Then reading more data throws. // Then reading more data throws.
try { try {
parsableByteArray.readUnsignedInt(); parsableByteArray.readUnsignedInt();
...@@ -77,21 +205,23 @@ public class ParsableByteArrayTest extends TestCase { ...@@ -77,21 +205,23 @@ public class ParsableByteArrayTest extends TestCase {
} }
public void testModificationsAffectParsableArray() { public void testModificationsAffectParsableArray() {
ParsableByteArray parsableByteArray = getTestDataArray();
// When modifying the wrapped byte array // When modifying the wrapped byte array
byte[] data = parsableByteArray.data; byte[] data = parsableByteArray.data;
long readValue = parsableByteArray.readUnsignedInt(); long readValue = parsableByteArray.readUnsignedInt();
data[0] = (byte) (ARRAY_ELEMENTS[0] + 1); data[0] = (byte) (TEST_DATA[0] + 1);
parsableByteArray.setPosition(0); parsableByteArray.setPosition(0);
// Then the parsed value changes. // Then the parsed value changes.
assertFalse(parsableByteArray.readUnsignedInt() == readValue); assertFalse(parsableByteArray.readUnsignedInt() == readValue);
} }
public void testReadingUnsignedLongWithMsbSetThrows() { public void testReadingUnsignedLongWithMsbSetThrows() {
ParsableByteArray parsableByteArray = getTestDataArray();
// Given an array with the most-significant bit set on the top byte // Given an array with the most-significant bit set on the top byte
byte[] data = parsableByteArray.data; byte[] data = parsableByteArray.data;
data[0] = (byte) 0x80; data[0] = (byte) 0x80;
// Then reading an unsigned long throws. // Then reading an unsigned long throws.
try { try {
parsableByteArray.readUnsignedLongToLong(); parsableByteArray.readUnsignedLongToLong();
...@@ -102,21 +232,23 @@ public class ParsableByteArrayTest extends TestCase { ...@@ -102,21 +232,23 @@ public class ParsableByteArrayTest extends TestCase {
} }
public void testReadUnsignedFixedPoint1616() { public void testReadUnsignedFixedPoint1616() {
ParsableByteArray parsableByteArray = getTestDataArray();
// When reading the integer part of a 16.16 fixed point value // When reading the integer part of a 16.16 fixed point value
int value = parsableByteArray.readUnsignedFixedPoint1616(); int value = parsableByteArray.readUnsignedFixedPoint1616();
// Then the read value is equal to the array elements interpreted as a short. // Then the read value is equal to the array elements interpreted as a short.
assertEquals((0xFF & ARRAY_ELEMENTS[0]) << 8 | (ARRAY_ELEMENTS[1] & 0xFF), value); assertEquals((0xFF & TEST_DATA[0]) << 8 | (TEST_DATA[1] & 0xFF), value);
assertEquals(4, parsableByteArray.getPosition()); assertEquals(4, parsableByteArray.getPosition());
} }
public void testReadingBytesReturnsCopy() { public void testReadingBytesReturnsCopy() {
ParsableByteArray parsableByteArray = getTestDataArray();
// When reading all the bytes back // When reading all the bytes back
int length = parsableByteArray.limit(); int length = parsableByteArray.limit();
assertEquals(ARRAY_ELEMENTS.length, length); assertEquals(TEST_DATA.length, length);
byte[] copy = new byte[length]; byte[] copy = new byte[length];
parsableByteArray.readBytes(copy, 0, length); parsableByteArray.readBytes(copy, 0, length);
// Then the array elements are the same. // Then the array elements are the same.
assertTrue(Arrays.equals(parsableByteArray.data, copy)); assertTrue(Arrays.equals(parsableByteArray.data, copy));
} }
......
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