mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add ParsableByteArray#ensureCapacity() method that keeps data
#exofixit PiperOrigin-RevId: 344845328
This commit is contained in:
parent
7e635d9560
commit
84a7ffc12a
@ -19,6 +19,7 @@ import androidx.annotation.Nullable;
|
||||
import com.google.common.base.Charsets;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Wraps a byte array, providing a set of methods for parsing data from it. Numerical values are
|
||||
@ -100,8 +101,21 @@ public final class ParsableByteArray {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes yet to be read.
|
||||
* Ensures the backing array is at least {@code requiredCapacity} long.
|
||||
*
|
||||
* <p>{@link #getPosition() position}, {@link #limit() limit}, and all data in the underlying
|
||||
* array (including that beyond {@link #limit()}) are preserved.
|
||||
*
|
||||
* <p>This might replace or wipe the {@link #getData() underlying array}, potentially invalidating
|
||||
* any local references.
|
||||
*/
|
||||
public void ensureCapacity(int requiredCapacity) {
|
||||
if (requiredCapacity > capacity()) {
|
||||
data = Arrays.copyOf(data, requiredCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the number of bytes yet to be read. */
|
||||
public int bytesLeft() {
|
||||
return limit - position;
|
||||
}
|
||||
@ -148,8 +162,8 @@ public final class ParsableByteArray {
|
||||
*
|
||||
* <p>Changes to this array are reflected in the results of the {@code read...()} methods.
|
||||
*
|
||||
* <p>This reference must be assumed to become invalid when {@link #reset} is called (because the
|
||||
* array might get reallocated).
|
||||
* <p>This reference must be assumed to become invalid when {@link #reset} or {@link
|
||||
* #ensureCapacity} are called (because the array might get reallocated).
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
|
@ -2214,9 +2214,8 @@ public final class Util {
|
||||
if (input.bytesLeft() <= 0) {
|
||||
return false;
|
||||
}
|
||||
byte[] outputData = output.getData();
|
||||
if (outputData.length < input.bytesLeft()) {
|
||||
outputData = new byte[2 * input.bytesLeft()];
|
||||
if (output.capacity() < input.bytesLeft()) {
|
||||
output.ensureCapacity(2 * input.bytesLeft());
|
||||
}
|
||||
if (inflater == null) {
|
||||
inflater = new Inflater();
|
||||
@ -2225,16 +2224,17 @@ public final class Util {
|
||||
try {
|
||||
int outputSize = 0;
|
||||
while (true) {
|
||||
outputSize += inflater.inflate(outputData, outputSize, outputData.length - outputSize);
|
||||
outputSize +=
|
||||
inflater.inflate(output.getData(), outputSize, output.capacity() - outputSize);
|
||||
if (inflater.finished()) {
|
||||
output.reset(outputData, outputSize);
|
||||
output.setLimit(outputSize);
|
||||
return true;
|
||||
}
|
||||
if (inflater.needsDictionary() || inflater.needsInput()) {
|
||||
return false;
|
||||
}
|
||||
if (outputSize == outputData.length) {
|
||||
outputData = Arrays.copyOf(outputData, outputData.length * 2);
|
||||
if (outputSize == output.capacity()) {
|
||||
output.ensureCapacity(output.capacity() * 2);
|
||||
}
|
||||
}
|
||||
} catch (DataFormatException e) {
|
||||
|
@ -20,6 +20,7 @@ import static java.nio.charset.Charset.forName;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import org.junit.Test;
|
||||
@ -38,6 +39,36 @@ public final class ParsableByteArrayTest {
|
||||
return testArray;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureCapacity_doesntReallocateNeedlesslyAndPreservesPositionAndLimit() {
|
||||
ParsableByteArray array = getTestDataArray();
|
||||
byte[] dataBefore = array.getData();
|
||||
byte[] copyOfDataBefore = dataBefore.clone();
|
||||
|
||||
array.setPosition(3);
|
||||
array.setLimit(4);
|
||||
array.ensureCapacity(array.capacity() - 1);
|
||||
|
||||
assertThat(array.getData()).isSameInstanceAs(dataBefore);
|
||||
assertThat(array.getData()).isEqualTo(copyOfDataBefore);
|
||||
assertThat(array.getPosition()).isEqualTo(3);
|
||||
assertThat(array.limit()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureCapacity_preservesDataPositionAndLimitWhenReallocating() {
|
||||
ParsableByteArray array = getTestDataArray();
|
||||
byte[] copyOfDataBefore = array.getData().clone();
|
||||
|
||||
array.setPosition(3);
|
||||
array.setLimit(4);
|
||||
array.ensureCapacity(array.capacity() + 1);
|
||||
|
||||
assertThat(array.getData()).isEqualTo(Bytes.concat(copyOfDataBefore, new byte[] {0}));
|
||||
assertThat(array.getPosition()).isEqualTo(3);
|
||||
assertThat(array.limit()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readShort() {
|
||||
testReadShort((short) -1);
|
||||
|
@ -1341,9 +1341,7 @@ public class MatroskaExtractor implements Extractor {
|
||||
return;
|
||||
}
|
||||
if (scratch.capacity() < requiredLength) {
|
||||
scratch.reset(
|
||||
Arrays.copyOf(scratch.getData(), max(scratch.getData().length * 2, requiredLength)),
|
||||
scratch.limit());
|
||||
scratch.ensureCapacity(max(scratch.capacity() * 2, requiredLength));
|
||||
}
|
||||
input.readFully(scratch.getData(), scratch.limit(), requiredLength - scratch.limit());
|
||||
scratch.setLimit(requiredLength);
|
||||
|
@ -87,11 +87,7 @@ import java.util.Arrays;
|
||||
int size = calculatePacketSize(currentSegmentIndex);
|
||||
int segmentIndex = currentSegmentIndex + segmentCount;
|
||||
if (size > 0) {
|
||||
if (packetArray.capacity() < packetArray.limit() + size) {
|
||||
packetArray.reset(
|
||||
Arrays.copyOf(packetArray.getData(), packetArray.limit() + size),
|
||||
/* limit= */ packetArray.limit());
|
||||
}
|
||||
packetArray.ensureCapacity(packetArray.limit() + size);
|
||||
input.readFully(packetArray.getData(), packetArray.limit(), size);
|
||||
packetArray.setLimit(packetArray.limit() + size);
|
||||
populated = pageHeader.laces[segmentIndex - 1] != 255;
|
||||
|
@ -23,7 +23,6 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
|
||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
import com.google.android.exoplayer2.util.TimestampAdjuster;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Reads section data packets and feeds the whole sections to a given {@link SectionPayloadReader}.
|
||||
@ -107,12 +106,9 @@ public final class SectionReader implements TsPayloadReader {
|
||||
(((secondHeaderByte & 0x0F) << 8) | thirdHeaderByte) + SECTION_HEADER_LENGTH;
|
||||
if (sectionData.capacity() < totalSectionLength) {
|
||||
// Ensure there is enough space to keep the whole section.
|
||||
byte[] bytes = sectionData.getData();
|
||||
int limit = min(MAX_SECTION_LENGTH, max(totalSectionLength, bytes.length * 2));
|
||||
if (limit > bytes.length) {
|
||||
bytes = Arrays.copyOf(sectionData.getData(), limit);
|
||||
}
|
||||
sectionData.reset(bytes, limit);
|
||||
int limit =
|
||||
min(MAX_SECTION_LENGTH, max(totalSectionLength, sectionData.capacity() * 2));
|
||||
sectionData.ensureCapacity(limit);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user