mirror of
https://github.com/androidx/media.git
synced 2025-05-18 13:09:56 +08:00
Simplify + optimize VorbisBitArray
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=161796758
This commit is contained in:
parent
90398c5811
commit
8378c3dc1f
@ -25,36 +25,26 @@ public final class VorbisBitArrayTest extends TestCase {
|
||||
|
||||
public void testReadBit() {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0x5c, 0x50));
|
||||
|
||||
assertFalse(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
assertTrue(bitArray.readBit());
|
||||
assertTrue(bitArray.readBit());
|
||||
|
||||
assertTrue(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
assertTrue(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
|
||||
assertFalse(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
|
||||
assertTrue(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
assertTrue(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
|
||||
try {
|
||||
assertFalse(bitArray.readBit());
|
||||
fail();
|
||||
} catch (IllegalStateException e) {/* ignored */}
|
||||
}
|
||||
|
||||
public void testSkipBits() {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xF0, 0x0F));
|
||||
|
||||
bitArray.skipBits(10);
|
||||
assertEquals(10, bitArray.getPosition());
|
||||
assertTrue(bitArray.readBit());
|
||||
@ -64,27 +54,10 @@ public final class VorbisBitArrayTest extends TestCase {
|
||||
assertEquals(14, bitArray.getPosition());
|
||||
assertFalse(bitArray.readBit());
|
||||
assertFalse(bitArray.readBit());
|
||||
try {
|
||||
bitArray.readBit();
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testSkipBitsThrowsErrorIfEOB() {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xF0, 0x0F));
|
||||
|
||||
try {
|
||||
bitArray.skipBits(17);
|
||||
fail();
|
||||
} catch (IllegalStateException e) {/* ignored */}
|
||||
}
|
||||
|
||||
public void testGetPosition() throws Exception {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xF0, 0x0F));
|
||||
|
||||
assertEquals(0, bitArray.getPosition());
|
||||
bitArray.readBit();
|
||||
assertEquals(1, bitArray.getPosition());
|
||||
@ -96,35 +69,11 @@ public final class VorbisBitArrayTest extends TestCase {
|
||||
|
||||
public void testSetPosition() throws Exception {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xF0, 0x0F));
|
||||
|
||||
assertEquals(0, bitArray.getPosition());
|
||||
bitArray.setPosition(4);
|
||||
assertEquals(4, bitArray.getPosition());
|
||||
|
||||
bitArray.setPosition(15);
|
||||
assertFalse(bitArray.readBit());
|
||||
try {
|
||||
bitArray.readBit();
|
||||
fail();
|
||||
} catch (IllegalStateException e) {/* ignored */}
|
||||
|
||||
}
|
||||
public void testSetPositionIllegalPositions() throws Exception {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xF0, 0x0F));
|
||||
|
||||
try {
|
||||
bitArray.setPosition(16);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(0, bitArray.getPosition());
|
||||
}
|
||||
|
||||
try {
|
||||
bitArray.setPosition(-1);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(0, bitArray.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public void testReadInt32() {
|
||||
@ -136,13 +85,11 @@ public final class VorbisBitArrayTest extends TestCase {
|
||||
|
||||
public void testReadBits() throws Exception {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0x03, 0x22));
|
||||
|
||||
assertEquals(3, bitArray.readBits(2));
|
||||
bitArray.skipBits(6);
|
||||
assertEquals(2, bitArray.readBits(2));
|
||||
bitArray.skipBits(2);
|
||||
assertEquals(2, bitArray.readBits(2));
|
||||
|
||||
bitArray.reset();
|
||||
assertEquals(0x2203, bitArray.readBits(16));
|
||||
}
|
||||
@ -156,7 +103,6 @@ public final class VorbisBitArrayTest extends TestCase {
|
||||
|
||||
public void testReadBitsBeyondByteBoundaries() throws Exception {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xFF, 0x0F, 0xFF, 0x0F));
|
||||
|
||||
assertEquals(0x0FFF0FFF, bitArray.readBits(32));
|
||||
|
||||
bitArray.reset();
|
||||
@ -188,83 +134,6 @@ public final class VorbisBitArrayTest extends TestCase {
|
||||
assertEquals(0, bitArray.getPosition());
|
||||
bitArray.readBit();
|
||||
assertEquals(1, bitArray.getPosition());
|
||||
|
||||
try {
|
||||
bitArray.readBits(24);
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals(1, bitArray.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public void testLimit() {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xc0, 0x02), 1);
|
||||
|
||||
try {
|
||||
bitArray.skipBits(9);
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals(0, bitArray.getPosition());
|
||||
}
|
||||
|
||||
try {
|
||||
bitArray.readBits(9);
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals(0, bitArray.getPosition());
|
||||
}
|
||||
|
||||
int byteValue = bitArray.readBits(8);
|
||||
assertEquals(0xc0, byteValue);
|
||||
assertEquals(8, bitArray.getPosition());
|
||||
try {
|
||||
bitArray.readBit();
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals(8, bitArray.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public void testBitsLeft() {
|
||||
VorbisBitArray bitArray = new VorbisBitArray(TestUtil.createByteArray(0xc0, 0x02));
|
||||
|
||||
assertEquals(16, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
bitArray.skipBits(1);
|
||||
assertEquals(15, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
bitArray.skipBits(3);
|
||||
assertEquals(12, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
bitArray.setPosition(6);
|
||||
assertEquals(10, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
bitArray.skipBits(1);
|
||||
assertEquals(9, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
bitArray.skipBits(1);
|
||||
assertEquals(8, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
bitArray.readBits(4);
|
||||
assertEquals(4, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
bitArray.readBits(4);
|
||||
assertEquals(0, bitArray.bitsLeft());
|
||||
assertEquals(bitArray.limit(), bitArray.getPosition() + bitArray.bitsLeft());
|
||||
|
||||
try {
|
||||
bitArray.readBit();
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals(0, bitArray.bitsLeft());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,8 +25,9 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
*/
|
||||
/* package */ final class VorbisBitArray {
|
||||
|
||||
public final byte[] data;
|
||||
private final int limit;
|
||||
private final byte[] data;
|
||||
private final int byteLimit;
|
||||
|
||||
private int byteOffset;
|
||||
private int bitOffset;
|
||||
|
||||
@ -36,18 +37,8 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
* @param data the array to wrap.
|
||||
*/
|
||||
public VorbisBitArray(byte[] data) {
|
||||
this(data, data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance that wraps an existing array.
|
||||
*
|
||||
* @param data the array to wrap.
|
||||
* @param limit the limit in bytes.
|
||||
*/
|
||||
public VorbisBitArray(byte[] data, int limit) {
|
||||
this.data = data;
|
||||
this.limit = limit * 8;
|
||||
byteLimit = data.length;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,7 +55,9 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
* @return {@code true} if the bit is set, {@code false} otherwise.
|
||||
*/
|
||||
public boolean readBit() {
|
||||
return readBits(1) == 1;
|
||||
boolean returnValue = (((data[byteOffset] & 0xFF) >> bitOffset) & 0x01) == 1;
|
||||
skipBits(1);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,53 +67,32 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
* @return An integer whose bottom {@code numBits} bits hold the read data.
|
||||
*/
|
||||
public int readBits(int numBits) {
|
||||
Assertions.checkState(getPosition() + numBits <= limit);
|
||||
if (numBits == 0) {
|
||||
return 0;
|
||||
int tempByteOffset = byteOffset;
|
||||
int bitsRead = Math.min(numBits, 8 - bitOffset);
|
||||
int returnValue = ((data[tempByteOffset++] & 0xFF) >> bitOffset) & (0xFF >> (8 - bitsRead));
|
||||
while (bitsRead < numBits) {
|
||||
returnValue |= (data[tempByteOffset++] & 0xFF) << bitsRead;
|
||||
bitsRead += 8;
|
||||
}
|
||||
int result = 0;
|
||||
int bitCount = 0;
|
||||
if (bitOffset != 0) {
|
||||
bitCount = Math.min(numBits, 8 - bitOffset);
|
||||
int mask = 0xFF >>> (8 - bitCount);
|
||||
result = (data[byteOffset] >>> bitOffset) & mask;
|
||||
bitOffset += bitCount;
|
||||
if (bitOffset == 8) {
|
||||
byteOffset++;
|
||||
bitOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (numBits - bitCount > 7) {
|
||||
int numBytes = (numBits - bitCount) / 8;
|
||||
for (int i = 0; i < numBytes; i++) {
|
||||
result |= (data[byteOffset++] & 0xFFL) << bitCount;
|
||||
bitCount += 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (numBits > bitCount) {
|
||||
int bitsOnNextByte = numBits - bitCount;
|
||||
int mask = 0xFF >>> (8 - bitsOnNextByte);
|
||||
result |= (data[byteOffset] & mask) << bitCount;
|
||||
bitOffset += bitsOnNextByte;
|
||||
}
|
||||
return result;
|
||||
returnValue &= 0xFFFFFFFF >>> (32 - numBits);
|
||||
skipBits(numBits);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips {@code numberOfBits} bits.
|
||||
*
|
||||
* @param numberOfBits The number of bits to skip.
|
||||
* @param numBits The number of bits to skip.
|
||||
*/
|
||||
public void skipBits(int numberOfBits) {
|
||||
Assertions.checkState(getPosition() + numberOfBits <= limit);
|
||||
byteOffset += numberOfBits / 8;
|
||||
bitOffset += numberOfBits % 8;
|
||||
public void skipBits(int numBits) {
|
||||
int numBytes = numBits / 8;
|
||||
byteOffset += numBytes;
|
||||
bitOffset += numBits - (numBytes * 8);
|
||||
if (bitOffset > 7) {
|
||||
byteOffset++;
|
||||
bitOffset -= 8;
|
||||
}
|
||||
assertValidOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,23 +108,22 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
* @param position The new reading position in bits.
|
||||
*/
|
||||
public void setPosition(int position) {
|
||||
Assertions.checkArgument(position < limit && position >= 0);
|
||||
byteOffset = position / 8;
|
||||
bitOffset = position - (byteOffset * 8);
|
||||
assertValidOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of remaining bits.
|
||||
*/
|
||||
public int bitsLeft() {
|
||||
return limit - getPosition();
|
||||
return (byteLimit - byteOffset) * 8 - bitOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the limit in bits.
|
||||
**/
|
||||
public int limit() {
|
||||
return limit;
|
||||
private void assertValidOffset() {
|
||||
// It is fine for position to be at the end of the array, but no further.
|
||||
Assertions.checkState(byteOffset >= 0
|
||||
&& (byteOffset < byteLimit || (byteOffset == byteLimit && bitOffset == 0)));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user