Optimize NAL unit search.

I'm not really a fan of micro-optimizations, but given this method
scans through every H264 frame in the HLS case, it seems worthwhile.
The trick here is to examine the first 7 bits of the third byte
first. If they're not all 0s, then we know that we haven't found a
NAL unit, and also that we wont find one at the next two positions.
This allows the loop to increment 3 bytes at a time.

Speedup is around 60% on Art according to some ad-hoc benchmarking.
This commit is contained in:
Oliver Woodman 2015-02-12 12:46:58 +00:00
parent 3568ecaf00
commit f7fb4d4c35

View file

@ -102,6 +102,7 @@ public final class Mp4Util {
/**
* Like {@link #findNalUnit(byte[], int, int, int)} with {@code type == -1}.
*
* @param data The data to search.
* @param startOffset The offset (inclusive) in the data to start the search.
* @param endOffset The offset (exclusive) in the data to end the search.
* @return The offset of the NAL unit, or {@code endOffset} if a NAL unit was not found.
@ -116,17 +117,28 @@ public final class Mp4Util {
* For a NAL unit to be found, its first four bytes must be contained within the part of the
* array being searched.
*
* @param type The type of the NAL unit to search for, or -1 for any NAL unit.
* @param data The data to search.
* @param startOffset The offset (inclusive) in the data to start the search.
* @param endOffset The offset (exclusive) in the data to end the search.
* @param type The type of the NAL unit to search for, or -1 for any NAL unit.
* @return The offset of the NAL unit, or {@code endOffset} if a NAL unit was not found.
*/
public static int findNalUnit(byte[] data, int startOffset, int endOffset, int type) {
for (int i = startOffset; i < endOffset - 3; i++) {
// Check for NAL unit start code prefix == 0x000001.
if ((data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1)
&& (type == -1 || (type == (data[i + 3] & 0x1F)))) {
return i;
int limit = endOffset - 2;
// We're looking for the NAL unit start code prefix 0x000001, followed by a byte that matches
// the specified type. The value of i tracks the index of the third byte in the four bytes
// being examined.
for (int i = startOffset + 2; i < limit; i += 3) {
if ((data[i] & 0xFE) != 0) {
// There isn't a NAL prefix here, or at the next two positions. Do nothing and let the
// loop advance the index by three.
} else if ((data[i - 2] == 0 && data[i - 1] == 0 && data[i] == 1)
&& (type == -1 || (type == (data[i + 1] & 0x1F)))) {
return i - 2;
} else {
// There isn't a NAL prefix here, but there might be at the next position. We should
// only skip forward by one. The loop will skip forward by three, so subtract two here.
i -= 2;
}
}
return endOffset;