Skip to content

Commit

Permalink
Optimize ParsableNalUnitBitArray
Browse files Browse the repository at this point in the history
Apply the same learnings as in ParsableBitArray.

Issue: #3040

-------------
Created by MOE: https:/google/moe
MOE_MIGRATED_REVID=161674119
  • Loading branch information
ojw28 authored and Oliver Woodman committed Jul 15, 2017
1 parent fba0546 commit 17e73bd
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public void testReadExpGolombWithEscaping() {
ParsableNalUnitBitArray array =
new ParsableNalUnitBitArray(createByteArray(0, 0, 3, 128, 0), 0, 5);
assertFalse(array.canReadExpGolombCodedNum());
array.skipBits(1);
array.skipBit();
assertTrue(array.canReadExpGolombCodedNum());
assertEquals(32767, array.readUnsignedExpGolombCodedInt());
assertFalse(array.canReadBits(1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ public void appendToNalUnit(byte[] data, int offset, int limit) {
if (!bitArray.canReadBits(8)) {
return;
}
bitArray.skipBits(1); // forbidden_zero_bit
bitArray.skipBit(); // forbidden_zero_bit
int nalRefIdc = bitArray.readBits(2);
bitArray.skipBits(5); // nal_unit_type

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ private static Format parseMediaFormat(String formatId, NalUnitTargetBuffer vps,
ParsableNalUnitBitArray bitArray = new ParsableNalUnitBitArray(sps.nalData, 0, sps.nalLength);
bitArray.skipBits(40 + 4); // NAL header, sps_video_parameter_set_id
int maxSubLayersMinus1 = bitArray.readBits(3);
bitArray.skipBits(1); // sps_temporal_id_nesting_flag
bitArray.skipBit(); // sps_temporal_id_nesting_flag

// profile_tier_level(1, sps_max_sub_layers_minus1)
bitArray.skipBits(88); // if (profilePresentFlag) {...}
Expand All @@ -247,7 +247,7 @@ private static Format parseMediaFormat(String formatId, NalUnitTargetBuffer vps,
bitArray.readUnsignedExpGolombCodedInt(); // sps_seq_parameter_set_id
int chromaFormatIdc = bitArray.readUnsignedExpGolombCodedInt();
if (chromaFormatIdc == 3) {
bitArray.skipBits(1); // separate_colour_plane_flag
bitArray.skipBit(); // separate_colour_plane_flag
}
int picWidthInLumaSamples = bitArray.readUnsignedExpGolombCodedInt();
int picHeightInLumaSamples = bitArray.readUnsignedExpGolombCodedInt();
Expand Down Expand Up @@ -288,7 +288,7 @@ private static Format parseMediaFormat(String formatId, NalUnitTargetBuffer vps,
bitArray.skipBits(8);
bitArray.readUnsignedExpGolombCodedInt(); // log2_min_pcm_luma_coding_block_size_minus3
bitArray.readUnsignedExpGolombCodedInt(); // log2_diff_max_min_pcm_luma_coding_block_size
bitArray.skipBits(1); // pcm_loop_filter_disabled_flag
bitArray.skipBit(); // pcm_loop_filter_disabled_flag
}
// Skips all short term reference picture sets.
skipShortTermRefPicSets(bitArray);
Expand Down Expand Up @@ -365,11 +365,11 @@ private static void skipShortTermRefPicSets(ParsableNalUnitBitArray bitArray) {
interRefPicSetPredictionFlag = bitArray.readBit();
}
if (interRefPicSetPredictionFlag) {
bitArray.skipBits(1); // delta_rps_sign
bitArray.skipBit(); // delta_rps_sign
bitArray.readUnsignedExpGolombCodedInt(); // abs_delta_rps_minus1
for (int j = 0; j <= previousNumDeltaPocs; j++) {
if (bitArray.readBit()) { // used_by_curr_pic_flag[j]
bitArray.skipBits(1); // use_delta_flag[j]
bitArray.skipBit(); // use_delta_flag[j]
}
}
} else {
Expand All @@ -378,11 +378,11 @@ private static void skipShortTermRefPicSets(ParsableNalUnitBitArray bitArray) {
previousNumDeltaPocs = numNegativePics + numPositivePics;
for (int i = 0; i < numNegativePics; i++) {
bitArray.readUnsignedExpGolombCodedInt(); // delta_poc_s0_minus1[i]
bitArray.skipBits(1); // used_by_curr_pic_s0_flag[i]
bitArray.skipBit(); // used_by_curr_pic_s0_flag[i]
}
for (int i = 0; i < numPositivePics; i++) {
bitArray.readUnsignedExpGolombCodedInt(); // delta_poc_s1_minus1[i]
bitArray.skipBits(1); // used_by_curr_pic_s1_flag[i]
bitArray.skipBit(); // used_by_curr_pic_s1_flag[i]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ public static SpsData parseSpsNalUnit(byte[] nalData, int nalOffset, int nalLimi
}
data.readUnsignedExpGolombCodedInt(); // bit_depth_luma_minus8
data.readUnsignedExpGolombCodedInt(); // bit_depth_chroma_minus8
data.skipBits(1); // qpprime_y_zero_transform_bypass_flag
data.skipBit(); // qpprime_y_zero_transform_bypass_flag
boolean seqScalingMatrixPresentFlag = data.readBit();
if (seqScalingMatrixPresentFlag) {
int limit = (chromaFormatIdc != 3) ? 8 : 12;
Expand Down Expand Up @@ -295,17 +295,17 @@ public static SpsData parseSpsNalUnit(byte[] nalData, int nalOffset, int nalLimi
}
}
data.readUnsignedExpGolombCodedInt(); // max_num_ref_frames
data.skipBits(1); // gaps_in_frame_num_value_allowed_flag
data.skipBit(); // gaps_in_frame_num_value_allowed_flag

int picWidthInMbs = data.readUnsignedExpGolombCodedInt() + 1;
int picHeightInMapUnits = data.readUnsignedExpGolombCodedInt() + 1;
boolean frameMbsOnlyFlag = data.readBit();
int frameHeightInMbs = (2 - (frameMbsOnlyFlag ? 1 : 0)) * picHeightInMapUnits;
if (!frameMbsOnlyFlag) {
data.skipBits(1); // mb_adaptive_frame_field_flag
data.skipBit(); // mb_adaptive_frame_field_flag
}

data.skipBits(1); // direct_8x8_inference_flag
data.skipBit(); // direct_8x8_inference_flag
int frameWidth = picWidthInMbs * 16;
int frameHeight = frameHeightInMbs * 16;
boolean frameCroppingFlag = data.readBit();
Expand Down Expand Up @@ -368,7 +368,7 @@ public static PpsData parsePpsNalUnit(byte[] nalData, int nalOffset, int nalLimi
data.skipBits(8); // nal_unit
int picParameterSetId = data.readUnsignedExpGolombCodedInt();
int seqParameterSetId = data.readUnsignedExpGolombCodedInt();
data.skipBits(1); // entropy_coding_mode_flag
data.skipBit(); // entropy_coding_mode_flag
boolean bottomFieldPicOrderInFramePresentFlag = data.readBit();
return new PpsData(picParameterSetId, seqParameterSetId, bottomFieldPicOrderInFramePresentFlag);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,27 @@ public void reset(byte[] data, int offset, int limit) {
assertValidOffset();
}

/**
* Skips a single bit.
*/
public void skipBit() {
if (++bitOffset == 8) {
bitOffset = 0;
byteOffset += shouldSkipByte(byteOffset + 1) ? 2 : 1;
}
assertValidOffset();
}

/**
* Skips bits and moves current reading position forward.
*
* @param n The number of bits to skip.
* @param numBits The number of bits to skip.
*/
public void skipBits(int n) {
public void skipBits(int numBits) {
int oldByteOffset = byteOffset;
byteOffset += (n / 8);
bitOffset += (n % 8);
int numBytes = numBits / 8;
byteOffset += numBytes;
bitOffset += numBits - (numBytes * 8);
if (bitOffset > 7) {
byteOffset++;
bitOffset -= 8;
Expand All @@ -81,13 +93,14 @@ public void skipBits(int n) {
* Returns whether it's possible to read {@code n} bits starting from the current offset. The
* offset is not modified.
*
* @param n The number of bits.
* @param numBits The number of bits.
* @return Whether it is possible to read {@code n} bits.
*/
public boolean canReadBits(int n) {
public boolean canReadBits(int numBits) {
int oldByteOffset = byteOffset;
int newByteOffset = byteOffset + (n / 8);
int newBitOffset = bitOffset + (n % 8);
int numBytes = numBits / 8;
int newByteOffset = byteOffset + numBytes;
int newBitOffset = bitOffset + numBits - (numBytes * 8);
if (newBitOffset > 7) {
newByteOffset++;
newBitOffset -= 8;
Expand All @@ -108,7 +121,9 @@ public boolean canReadBits(int n) {
* @return Whether the bit is set.
*/
public boolean readBit() {
return readBits(1) == 1;
boolean returnValue = (data[byteOffset] & (0x80 >> bitOffset)) != 0;
skipBit();
return returnValue;
}

/**
Expand All @@ -118,50 +133,19 @@ public boolean readBit() {
* @return An integer whose bottom n bits hold the read data.
*/
public int readBits(int numBits) {
if (numBits == 0) {
return 0;
}

int returnValue = 0;

// Read as many whole bytes as we can.
int wholeBytes = (numBits / 8);
for (int i = 0; i < wholeBytes; i++) {
int nextByteOffset = shouldSkipByte(byteOffset + 1) ? byteOffset + 2 : byteOffset + 1;
int byteValue;
if (bitOffset != 0) {
byteValue = ((data[byteOffset] & 0xFF) << bitOffset)
| ((data[nextByteOffset] & 0xFF) >>> (8 - bitOffset));
} else {
byteValue = data[byteOffset];
}
numBits -= 8;
returnValue |= (byteValue & 0xFF) << numBits;
byteOffset = nextByteOffset;
bitOffset += numBits;
while (bitOffset > 8) {
bitOffset -= 8;
returnValue |= (data[byteOffset] & 0xFF) << bitOffset;
byteOffset += shouldSkipByte(byteOffset + 1) ? 2 : 1;
}

// Read any remaining bits.
if (numBits > 0) {
int nextBit = bitOffset + numBits;
byte writeMask = (byte) (0xFF >> (8 - numBits));
int nextByteOffset = shouldSkipByte(byteOffset + 1) ? byteOffset + 2 : byteOffset + 1;

if (nextBit > 8) {
// Combine bits from current byte and next byte.
returnValue |= ((((data[byteOffset] & 0xFF) << (nextBit - 8)
| ((data[nextByteOffset] & 0xFF) >> (16 - nextBit))) & writeMask));
byteOffset = nextByteOffset;
} else {
// Bits to be read only within current byte.
returnValue |= (((data[byteOffset] & 0xFF) >> (8 - nextBit)) & writeMask);
if (nextBit == 8) {
byteOffset = nextByteOffset;
}
}

bitOffset = nextBit % 8;
returnValue |= (data[byteOffset] & 0xFF) >> 8 - bitOffset;
returnValue &= 0xFFFFFFFF >>> (32 - numBits);
if (bitOffset == 8) {
bitOffset = 0;
byteOffset += shouldSkipByte(byteOffset + 1) ? 2 : 1;
}

assertValidOffset();
return returnValue;
}
Expand Down Expand Up @@ -220,7 +204,6 @@ private boolean shouldSkipByte(int offset) {
private void assertValidOffset() {
// It is fine for position to be at the end of the array, but no further.
Assertions.checkState(byteOffset >= 0
&& (bitOffset >= 0 && bitOffset < 8)
&& (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0)));
}

Expand Down

0 comments on commit 17e73bd

Please sign in to comment.