Commit 5c9c15ae by Oliver Woodman

Add support for extracting H.265/HEVC data in MP4 files.

parent ac54b4f6
...@@ -39,7 +39,8 @@ import java.util.List; ...@@ -39,7 +39,8 @@ import java.util.List;
public static final int TYPE_ftyp = Util.getIntegerCodeForString("ftyp"); public static final int TYPE_ftyp = Util.getIntegerCodeForString("ftyp");
public static final int TYPE_avc1 = Util.getIntegerCodeForString("avc1"); public static final int TYPE_avc1 = Util.getIntegerCodeForString("avc1");
public static final int TYPE_avc3 = Util.getIntegerCodeForString("avc3"); public static final int TYPE_avc3 = Util.getIntegerCodeForString("avc3");
public static final int TYPE_esds = Util.getIntegerCodeForString("esds"); public static final int TYPE_hvc1 = Util.getIntegerCodeForString("hvc1");
public static final int TYPE_hev1 = Util.getIntegerCodeForString("hev1");
public static final int TYPE_mdat = Util.getIntegerCodeForString("mdat"); public static final int TYPE_mdat = Util.getIntegerCodeForString("mdat");
public static final int TYPE_mp4a = Util.getIntegerCodeForString("mp4a"); public static final int TYPE_mp4a = Util.getIntegerCodeForString("mp4a");
public static final int TYPE_ac_3 = Util.getIntegerCodeForString("ac-3"); public static final int TYPE_ac_3 = Util.getIntegerCodeForString("ac-3");
...@@ -58,6 +59,8 @@ import java.util.List; ...@@ -58,6 +59,8 @@ import java.util.List;
public static final int TYPE_minf = Util.getIntegerCodeForString("minf"); public static final int TYPE_minf = Util.getIntegerCodeForString("minf");
public static final int TYPE_stbl = Util.getIntegerCodeForString("stbl"); public static final int TYPE_stbl = Util.getIntegerCodeForString("stbl");
public static final int TYPE_avcC = Util.getIntegerCodeForString("avcC"); public static final int TYPE_avcC = Util.getIntegerCodeForString("avcC");
public static final int TYPE_hvcC = Util.getIntegerCodeForString("hvcC");
public static final int TYPE_esds = Util.getIntegerCodeForString("esds");
public static final int TYPE_moof = Util.getIntegerCodeForString("moof"); public static final int TYPE_moof = Util.getIntegerCodeForString("moof");
public static final int TYPE_traf = Util.getIntegerCodeForString("traf"); public static final int TYPE_traf = Util.getIntegerCodeForString("traf");
public static final int TYPE_mvex = Util.getIntegerCodeForString("mvex"); public static final int TYPE_mvex = Util.getIntegerCodeForString("mvex");
......
...@@ -20,8 +20,8 @@ import com.google.android.exoplayer.MediaFormat; ...@@ -20,8 +20,8 @@ import com.google.android.exoplayer.MediaFormat;
import com.google.android.exoplayer.util.Ac3Util; import com.google.android.exoplayer.util.Ac3Util;
import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.CodecSpecificDataUtil; import com.google.android.exoplayer.util.CodecSpecificDataUtil;
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.NalUnitUtil;
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;
...@@ -331,25 +331,22 @@ import java.util.List; ...@@ -331,25 +331,22 @@ import java.util.List;
Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive"); Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive");
int childAtomType = stsd.readInt(); int childAtomType = stsd.readInt();
if (childAtomType == Atom.TYPE_avc1 || childAtomType == Atom.TYPE_avc3 if (childAtomType == Atom.TYPE_avc1 || childAtomType == Atom.TYPE_avc3
|| childAtomType == Atom.TYPE_encv) { || childAtomType == Atom.TYPE_encv || childAtomType == Atom.TYPE_mp4v
parseAvcFromParent(stsd, childStartPosition, childAtomSize, durationUs, holder, i); || childAtomType == Atom.TYPE_hvc1 || childAtomType == Atom.TYPE_hev1) {
parseVideoSampleEntry(stsd, childStartPosition, childAtomSize, durationUs, holder, i);
} else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca } else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca
|| childAtomType == Atom.TYPE_ac_3) { || childAtomType == Atom.TYPE_ac_3) {
parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, durationUs, parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, durationUs,
holder, i); holder, i);
} else if (childAtomType == Atom.TYPE_TTML) { } else if (childAtomType == Atom.TYPE_TTML) {
holder.mediaFormat = MediaFormat.createTtmlFormat(); holder.mediaFormat = MediaFormat.createTtmlFormat();
} else if (childAtomType == Atom.TYPE_mp4v) {
holder.mediaFormat = parseMp4vFromParent(stsd, childStartPosition, childAtomSize,
durationUs);
} }
stsd.setPosition(childStartPosition + childAtomSize); stsd.setPosition(childStartPosition + childAtomSize);
} }
return holder; return holder;
} }
/** Returns the media format for an avc1 box. */ private static void parseVideoSampleEntry(ParsableByteArray parent, int position, int size,
private static void parseAvcFromParent(ParsableByteArray parent, int position, int size,
long durationUs, StsdDataHolder out, int entryIndex) { long durationUs, StsdDataHolder out, int entryIndex) {
parent.setPosition(position + Atom.HEADER_SIZE); parent.setPosition(position + Atom.HEADER_SIZE);
...@@ -361,6 +358,7 @@ import java.util.List; ...@@ -361,6 +358,7 @@ import java.util.List;
List<byte[]> initializationData = null; List<byte[]> initializationData = null;
int childPosition = parent.getPosition(); int childPosition = parent.getPosition();
String mimeType = null;
while (childPosition - position < size) { while (childPosition - position < size) {
parent.setPosition(childPosition); parent.setPosition(childPosition);
int childStartPosition = parent.getPosition(); int childStartPosition = parent.getPosition();
...@@ -372,9 +370,22 @@ import java.util.List; ...@@ -372,9 +370,22 @@ import java.util.List;
Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive"); Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive");
int childAtomType = parent.readInt(); int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_avcC) { if (childAtomType == Atom.TYPE_avcC) {
Assertions.checkState(mimeType == null);
mimeType = MimeTypes.VIDEO_H264;
Pair<List<byte[]>, Integer> avcCData = parseAvcCFromParent(parent, childStartPosition); Pair<List<byte[]>, Integer> avcCData = parseAvcCFromParent(parent, childStartPosition);
initializationData = avcCData.first; initializationData = avcCData.first;
out.nalUnitLengthFieldLength = avcCData.second; out.nalUnitLengthFieldLength = avcCData.second;
} else if (childAtomType == Atom.TYPE_hvcC) {
Assertions.checkState(mimeType == null);
mimeType = MimeTypes.VIDEO_H265;
Pair<List<byte[]>, Integer> hvcCData = parseHvcCFromParent(parent, childStartPosition);
initializationData = hvcCData.first;
out.nalUnitLengthFieldLength = hvcCData.second;
} else if (childAtomType == Atom.TYPE_esds) {
Assertions.checkState(mimeType == null);
mimeType = MimeTypes.VIDEO_MP4V;
initializationData =
Collections.singletonList(parseEsdsFromParent(parent, childStartPosition));
} else if (childAtomType == Atom.TYPE_sinf) { } else if (childAtomType == Atom.TYPE_sinf) {
out.trackEncryptionBoxes[entryIndex] = out.trackEncryptionBoxes[entryIndex] =
parseSinfFromParent(parent, childStartPosition, childAtomSize); parseSinfFromParent(parent, childStartPosition, childAtomSize);
...@@ -383,9 +394,8 @@ import java.util.List; ...@@ -383,9 +394,8 @@ import java.util.List;
} }
childPosition += childAtomSize; childPosition += childAtomSize;
} }
out.mediaFormat = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE, durationUs,
out.mediaFormat = MediaFormat.createVideoFormat(MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE, width, height, pixelWidthHeightRatio, initializationData);
durationUs, width, height, pixelWidthHeightRatio, initializationData);
} }
private static Pair<List<byte[]>, Integer> parseAvcCFromParent(ParsableByteArray parent, private static Pair<List<byte[]>, Integer> parseAvcCFromParent(ParsableByteArray parent,
...@@ -401,15 +411,58 @@ import java.util.List; ...@@ -401,15 +411,58 @@ import java.util.List;
// expose the AVC profile and level somewhere useful; Most likely in MediaFormat. // expose the AVC profile and level somewhere useful; Most likely in MediaFormat.
int numSequenceParameterSets = parent.readUnsignedByte() & 0x1F; int numSequenceParameterSets = parent.readUnsignedByte() & 0x1F;
for (int j = 0; j < numSequenceParameterSets; j++) { for (int j = 0; j < numSequenceParameterSets; j++) {
initializationData.add(H264Util.parseChildNalUnit(parent)); initializationData.add(NalUnitUtil.parseChildNalUnit(parent));
} }
int numPictureParameterSets = parent.readUnsignedByte(); int numPictureParameterSets = parent.readUnsignedByte();
for (int j = 0; j < numPictureParameterSets; j++) { for (int j = 0; j < numPictureParameterSets; j++) {
initializationData.add(H264Util.parseChildNalUnit(parent)); initializationData.add(NalUnitUtil.parseChildNalUnit(parent));
} }
return Pair.create(initializationData, nalUnitLengthFieldLength); return Pair.create(initializationData, nalUnitLengthFieldLength);
} }
private static Pair<List<byte[]>, Integer> parseHvcCFromParent(ParsableByteArray parent,
int position) {
// Skip to the NAL unit length size field.
parent.setPosition(position + Atom.HEADER_SIZE + 21);
int lengthSizeMinusOne = parent.readUnsignedByte() & 0x03;
// Calculate the combined size of all VPS/SPS/PPS bitstreams.
int numberOfArrays = parent.readUnsignedByte();
int csdLength = 0;
int csdStartPosition = parent.getPosition();
for (int i = 0; i < numberOfArrays; i++) {
parent.skipBytes(1); // completeness (1), nal_unit_type (7)
int numberOfNalUnits = parent.readUnsignedShort();
for (int j = 0; j < numberOfNalUnits; j++) {
int nalUnitLength = parent.readUnsignedShort();
csdLength += 4 + nalUnitLength; // Start code and NAL unit.
parent.skipBytes(nalUnitLength);
}
}
// Concatenate the codec-specific data into a single buffer.
parent.setPosition(csdStartPosition);
byte[] buffer = new byte[csdLength];
int bufferPosition = 0;
for (int i = 0; i < numberOfArrays; i++) {
parent.skipBytes(1); // completeness (1), nal_unit_type (7)
int numberOfNalUnits = parent.readUnsignedShort();
for (int j = 0; j < numberOfNalUnits; j++) {
int nalUnitLength = parent.readUnsignedShort();
System.arraycopy(NalUnitUtil.NAL_START_CODE, 0, buffer, bufferPosition,
NalUnitUtil.NAL_START_CODE.length);
bufferPosition += NalUnitUtil.NAL_START_CODE.length;
System.arraycopy(parent.data, parent.getPosition(), buffer, bufferPosition, nalUnitLength);
bufferPosition += nalUnitLength;
parent.skipBytes(nalUnitLength);
}
}
List<byte[]> initializationData = csdLength == 0 ? Collections.<byte[]>emptyList()
: Collections.singletonList(buffer);
return Pair.create(initializationData, lengthSizeMinusOne + 1);
}
private static TrackEncryptionBox parseSinfFromParent(ParsableByteArray parent, int position, private static TrackEncryptionBox parseSinfFromParent(ParsableByteArray parent, int position,
int size) { int size) {
int childPosition = position + Atom.HEADER_SIZE; int childPosition = position + Atom.HEADER_SIZE;
...@@ -462,34 +515,6 @@ import java.util.List; ...@@ -462,34 +515,6 @@ import java.util.List;
return null; return null;
} }
/** Returns the media format for an mp4v box. */
private static MediaFormat parseMp4vFromParent(ParsableByteArray parent, int position, int size,
long durationUs) {
parent.setPosition(position + Atom.HEADER_SIZE);
parent.skipBytes(24);
int width = parent.readUnsignedShort();
int height = parent.readUnsignedShort();
parent.skipBytes(50);
List<byte[]> initializationData = new ArrayList<>(1);
int childPosition = parent.getPosition();
while (childPosition - position < size) {
parent.setPosition(childPosition);
int childStartPosition = parent.getPosition();
int childAtomSize = parent.readInt();
Assertions.checkArgument(childAtomSize > 0, "childAtomSize should be positive");
int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_esds) {
initializationData.add(parseEsdsFromParent(parent, childStartPosition));
}
childPosition += childAtomSize;
}
return MediaFormat.createVideoFormat(
MimeTypes.VIDEO_MP4V, MediaFormat.NO_VALUE, durationUs, width, height, initializationData);
}
private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType, int position, private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType, int position,
int size, long durationUs, StsdDataHolder out, int entryIndex) { int size, long durationUs, StsdDataHolder out, int entryIndex) {
parent.setPosition(position + Atom.HEADER_SIZE); parent.setPosition(position + Atom.HEADER_SIZE);
......
...@@ -26,8 +26,8 @@ import com.google.android.exoplayer.extractor.TrackOutput; ...@@ -26,8 +26,8 @@ import com.google.android.exoplayer.extractor.TrackOutput;
import com.google.android.exoplayer.extractor.mp4.Atom.ContainerAtom; import com.google.android.exoplayer.extractor.mp4.Atom.ContainerAtom;
import com.google.android.exoplayer.extractor.mp4.Atom.LeafAtom; import com.google.android.exoplayer.extractor.mp4.Atom.LeafAtom;
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.NalUnitUtil;
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;
...@@ -106,7 +106,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -106,7 +106,7 @@ public final class FragmentedMp4Extractor implements Extractor {
public FragmentedMp4Extractor(int workaroundFlags) { public FragmentedMp4Extractor(int workaroundFlags) {
this.workaroundFlags = workaroundFlags; this.workaroundFlags = workaroundFlags;
atomHeader = new ParsableByteArray(Atom.HEADER_SIZE); atomHeader = new ParsableByteArray(Atom.HEADER_SIZE);
nalStartCode = new ParsableByteArray(H264Util.NAL_START_CODE); nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE);
nalLength = new ParsableByteArray(4); nalLength = new ParsableByteArray(4);
encryptionSignalByte = new ParsableByteArray(1); encryptionSignalByte = new ParsableByteArray(1);
extendedTypeScratch = new byte[16]; extendedTypeScratch = new byte[16];
......
...@@ -23,7 +23,7 @@ import com.google.android.exoplayer.extractor.SeekMap; ...@@ -23,7 +23,7 @@ import com.google.android.exoplayer.extractor.SeekMap;
import com.google.android.exoplayer.extractor.TrackOutput; import com.google.android.exoplayer.extractor.TrackOutput;
import com.google.android.exoplayer.extractor.mp4.Atom.ContainerAtom; import com.google.android.exoplayer.extractor.mp4.Atom.ContainerAtom;
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.NalUnitUtil;
import com.google.android.exoplayer.util.ParsableByteArray; import com.google.android.exoplayer.util.ParsableByteArray;
import java.io.IOException; import java.io.IOException;
...@@ -72,7 +72,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { ...@@ -72,7 +72,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
public Mp4Extractor() { public Mp4Extractor() {
atomHeader = new ParsableByteArray(Atom.LONG_HEADER_SIZE); atomHeader = new ParsableByteArray(Atom.LONG_HEADER_SIZE);
containerAtoms = new Stack<>(); containerAtoms = new Stack<>();
nalStartCode = new ParsableByteArray(H264Util.NAL_START_CODE); nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE);
nalLength = new ParsableByteArray(4); nalLength = new ParsableByteArray(4);
parserState = STATE_READING_ATOM_HEADER; parserState = STATE_READING_ATOM_HEADER;
} }
......
...@@ -19,8 +19,8 @@ import com.google.android.exoplayer.C; ...@@ -19,8 +19,8 @@ import com.google.android.exoplayer.C;
import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormat;
import com.google.android.exoplayer.extractor.TrackOutput; import com.google.android.exoplayer.extractor.TrackOutput;
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.NalUnitUtil;
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;
...@@ -104,7 +104,7 @@ import java.util.List; ...@@ -104,7 +104,7 @@ import java.util.List;
@Override @Override
public void seek() { public void seek() {
seiReader.seek(); seiReader.seek();
H264Util.clearPrefixFlags(prefixFlags); NalUnitUtil.clearPrefixFlags(prefixFlags);
sps.reset(); sps.reset();
pps.reset(); pps.reset();
sei.reset(); sei.reset();
...@@ -128,7 +128,7 @@ import java.util.List; ...@@ -128,7 +128,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 = H264Util.findNalUnit(dataArray, offset, limit, prefixFlags); int nextNalUnitOffset = NalUnitUtil.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.
...@@ -139,7 +139,7 @@ import java.util.List; ...@@ -139,7 +139,7 @@ import java.util.List;
feedNalUnitTargetBuffersData(dataArray, offset, nextNalUnitOffset); feedNalUnitTargetBuffersData(dataArray, offset, nextNalUnitOffset);
} }
int nalUnitType = H264Util.getNalUnitType(dataArray, nextNalUnitOffset); int nalUnitType = NalUnitUtil.getNalUnitType(dataArray, nextNalUnitOffset);
int bytesWrittenPastNalUnit = limit - nextNalUnitOffset; int bytesWrittenPastNalUnit = limit - nextNalUnitOffset;
switch (nalUnitType) { switch (nalUnitType) {
case NAL_UNIT_TYPE_IDR: case NAL_UNIT_TYPE_IDR:
......
...@@ -33,6 +33,7 @@ public class MimeTypes { ...@@ -33,6 +33,7 @@ public class MimeTypes {
public static final String VIDEO_MP4 = BASE_TYPE_VIDEO + "/mp4"; public static final String VIDEO_MP4 = BASE_TYPE_VIDEO + "/mp4";
public static final String VIDEO_WEBM = BASE_TYPE_VIDEO + "/webm"; public static final String VIDEO_WEBM = BASE_TYPE_VIDEO + "/webm";
public static final String VIDEO_H264 = BASE_TYPE_VIDEO + "/avc"; public static final String VIDEO_H264 = BASE_TYPE_VIDEO + "/avc";
public static final String VIDEO_H265 = BASE_TYPE_VIDEO + "/hevc";
public static final String VIDEO_VP8 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp8"; public static final String VIDEO_VP8 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp8";
public static final String VIDEO_VP9 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp9"; public static final String VIDEO_VP9 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp9";
public static final String VIDEO_MP4V = BASE_TYPE_VIDEO + "/mp4v-es"; public static final String VIDEO_MP4V = BASE_TYPE_VIDEO + "/mp4v-es";
......
...@@ -18,11 +18,11 @@ package com.google.android.exoplayer.util; ...@@ -18,11 +18,11 @@ package com.google.android.exoplayer.util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
/** /**
* Utility methods for handling H264 data. * Utility methods for handling H.264/AVC and H.265/HEVC NAL units.
*/ */
public final class H264Util { public final class NalUnitUtil {
/** Four initial bytes that must prefix H.264/AVC NAL units for decoding. */ /** Four initial bytes that must prefix NAL units for decoding. */
public static final byte[] NAL_START_CODE = new byte[] {0, 0, 0, 1}; public static final byte[] NAL_START_CODE = new byte[] {0, 0, 0, 1};
/** /**
...@@ -173,7 +173,7 @@ public final class H264Util { ...@@ -173,7 +173,7 @@ public final class H264Util {
return result; return result;
} }
private H264Util() { private NalUnitUtil() {
// Prevent instantiation. // Prevent instantiation.
} }
......
...@@ -20,9 +20,9 @@ import junit.framework.TestCase; ...@@ -20,9 +20,9 @@ import junit.framework.TestCase;
import java.util.Arrays; import java.util.Arrays;
/** /**
* Tests for {@link H264Util}. * Tests for {@link NalUnitUtil}.
*/ */
public class H264UtilTest extends TestCase { public class NalUnitUtilTest 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 H264UtilTest extends TestCase { ...@@ -31,19 +31,19 @@ public class H264UtilTest extends TestCase {
byte[] data = buildTestData(); byte[] data = buildTestData();
// Should find NAL unit. // Should find NAL unit.
int result = H264Util.findNalUnit(data, 0, data.length, null); int result = NalUnitUtil.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 = H264Util.findNalUnit(data, 0, TEST_NAL_POSITION + 4, null); result = NalUnitUtil.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 = H264Util.findNalUnit(data, 0, TEST_NAL_POSITION + 3, null); result = NalUnitUtil.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 = H264Util.findNalUnit(data, TEST_NAL_POSITION, data.length, null); result = NalUnitUtil.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 = H264Util.findNalUnit(data, TEST_NAL_POSITION + 1, data.length, null); result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION + 1, data.length, null);
assertEquals(data.length, result); assertEquals(data.length, result);
} }
...@@ -54,9 +54,9 @@ public class H264UtilTest extends TestCase { ...@@ -54,9 +54,9 @@ public class H264UtilTest 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 = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags); int result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(-1, result); assertEquals(-1, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -64,9 +64,9 @@ public class H264UtilTest extends TestCase { ...@@ -64,9 +64,9 @@ public class H264UtilTest 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 = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(-3, result); assertEquals(-3, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -75,11 +75,11 @@ public class H264UtilTest extends TestCase { ...@@ -75,11 +75,11 @@ public class H264UtilTest 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 = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(data2.length, result); assertEquals(data2.length, result);
result = H264Util.findNalUnit(data3, 0, data3.length, prefixFlags); result = NalUnitUtil.findNalUnit(data3, 0, data3.length, prefixFlags);
assertEquals(-2, result); assertEquals(-2, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -89,13 +89,13 @@ public class H264UtilTest extends TestCase { ...@@ -89,13 +89,13 @@ public class H264UtilTest 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 = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags);
assertEquals(data2.length, result); assertEquals(data2.length, result);
result = H264Util.findNalUnit(data3, 0, data3.length, prefixFlags); result = NalUnitUtil.findNalUnit(data3, 0, data3.length, prefixFlags);
assertEquals(data3.length, result); assertEquals(data3.length, result);
result = H264Util.findNalUnit(data4, 0, data4.length, prefixFlags); result = NalUnitUtil.findNalUnit(data4, 0, data4.length, prefixFlags);
assertEquals(-3, result); assertEquals(-3, result);
assertPrefixFlagsCleared(prefixFlags); assertPrefixFlagsCleared(prefixFlags);
...@@ -103,9 +103,9 @@ public class H264UtilTest extends TestCase { ...@@ -103,9 +103,9 @@ public class H264UtilTest 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 = H264Util.findNalUnit(data1, 0, data1.length, prefixFlags); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags);
assertEquals(data1.length, result); assertEquals(data1.length, result);
result = H264Util.findNalUnit(data2, 0, data2.length, prefixFlags); result = NalUnitUtil.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