Commit 08132656 by aquilescanta Committed by Oliver Woodman

Make SampleDataQueue methods that read data static

Non-functional change which makes it easier to read sample data without altering
the read position.

PiperOrigin-RevId: 352323477
parent 9faa393a
...@@ -122,32 +122,38 @@ import java.util.Arrays; ...@@ -122,32 +122,38 @@ import java.util.Arrays;
*/ */
public void readToBuffer(DecoderInputBuffer buffer, SampleExtrasHolder extrasHolder) { public void readToBuffer(DecoderInputBuffer buffer, SampleExtrasHolder extrasHolder) {
// Read encryption data if the sample is encrypted. // Read encryption data if the sample is encrypted.
AllocationNode readAllocationNode = this.readAllocationNode;
if (buffer.isEncrypted()) { if (buffer.isEncrypted()) {
readEncryptionData(buffer, extrasHolder); readAllocationNode = readEncryptionData(readAllocationNode, buffer, extrasHolder, scratch);
} }
// Read sample data, extracting supplemental data into a separate buffer if needed. // Read sample data, extracting supplemental data into a separate buffer if needed.
if (buffer.hasSupplementalData()) { if (buffer.hasSupplementalData()) {
// If there is supplemental data, the sample data is prefixed by its size. // If there is supplemental data, the sample data is prefixed by its size.
scratch.reset(4); scratch.reset(4);
readData(extrasHolder.offset, scratch.getData(), 4); readAllocationNode = readData(readAllocationNode, extrasHolder.offset, scratch.getData(), 4);
int sampleSize = scratch.readUnsignedIntToInt(); int sampleSize = scratch.readUnsignedIntToInt();
extrasHolder.offset += 4; extrasHolder.offset += 4;
extrasHolder.size -= 4; extrasHolder.size -= 4;
// Write the sample data. // Write the sample data.
buffer.ensureSpaceForWrite(sampleSize); buffer.ensureSpaceForWrite(sampleSize);
readData(extrasHolder.offset, buffer.data, sampleSize); readAllocationNode =
readData(readAllocationNode, extrasHolder.offset, buffer.data, sampleSize);
extrasHolder.offset += sampleSize; extrasHolder.offset += sampleSize;
extrasHolder.size -= sampleSize; extrasHolder.size -= sampleSize;
// Write the remaining data as supplemental data. // Write the remaining data as supplemental data.
buffer.resetSupplementalData(extrasHolder.size); buffer.resetSupplementalData(extrasHolder.size);
readData(extrasHolder.offset, buffer.supplementalData, extrasHolder.size); readAllocationNode =
readData(
readAllocationNode, extrasHolder.offset, buffer.supplementalData, extrasHolder.size);
} else { } else {
// Write the sample data. // Write the sample data.
buffer.ensureSpaceForWrite(extrasHolder.size); buffer.ensureSpaceForWrite(extrasHolder.size);
readData(extrasHolder.offset, buffer.data, extrasHolder.size); readAllocationNode =
readData(readAllocationNode, extrasHolder.offset, buffer.data, extrasHolder.size);
} }
this.readAllocationNode = readAllocationNode;
} }
/** /**
...@@ -211,21 +217,82 @@ import java.util.Arrays; ...@@ -211,21 +217,82 @@ import java.util.Arrays;
// Private methods. // Private methods.
/** /**
* Reads encryption data for the current sample. * Clears allocation nodes starting from {@code fromNode}.
*
* @param fromNode The node from which to clear.
*/
private void clearAllocationNodes(AllocationNode fromNode) {
if (!fromNode.wasInitialized) {
return;
}
// Bulk release allocations for performance (it's significantly faster when using
// DefaultAllocator because the allocator's lock only needs to be acquired and released once)
// [Internal: See b/29542039].
int allocationCount =
(writeAllocationNode.wasInitialized ? 1 : 0)
+ ((int) (writeAllocationNode.startPosition - fromNode.startPosition)
/ allocationLength);
Allocation[] allocationsToRelease = new Allocation[allocationCount];
AllocationNode currentNode = fromNode;
for (int i = 0; i < allocationsToRelease.length; i++) {
allocationsToRelease[i] = currentNode.allocation;
currentNode = currentNode.clear();
}
allocator.release(allocationsToRelease);
}
/**
* Called before writing sample data to {@link #writeAllocationNode}. May cause {@link
* #writeAllocationNode} to be initialized.
*
* @param length The number of bytes that the caller wishes to write.
* @return The number of bytes that the caller is permitted to write, which may be less than
* {@code length}.
*/
private int preAppend(int length) {
if (!writeAllocationNode.wasInitialized) {
writeAllocationNode.initialize(
allocator.allocate(),
new AllocationNode(writeAllocationNode.endPosition, allocationLength));
}
return min(length, (int) (writeAllocationNode.endPosition - totalBytesWritten));
}
/**
* Called after writing sample data. May cause {@link #writeAllocationNode} to be advanced.
*
* @param length The number of bytes that were written.
*/
private void postAppend(int length) {
totalBytesWritten += length;
if (totalBytesWritten == writeAllocationNode.endPosition) {
writeAllocationNode = writeAllocationNode.next;
}
}
/**
* Reads encryption data for the sample described by {@code extrasHolder}.
* *
* <p>The encryption data is written into {@link DecoderInputBuffer#cryptoInfo}, and {@link * <p>The encryption data is written into {@link DecoderInputBuffer#cryptoInfo}, and {@link
* SampleExtrasHolder#size} is adjusted to subtract the number of bytes that were read. The same * SampleExtrasHolder#size} is adjusted to subtract the number of bytes that were read. The same
* value is added to {@link SampleExtrasHolder#offset}. * value is added to {@link SampleExtrasHolder#offset}.
* *
* @param allocationNode The first {@link AllocationNode} containing data yet to be read.
* @param buffer The buffer into which the encryption data should be written. * @param buffer The buffer into which the encryption data should be written.
* @param extrasHolder The extras holder whose offset should be read and subsequently adjusted. * @param extrasHolder The extras holder whose offset should be read and subsequently adjusted.
* @param scratch A scratch {@link ParsableByteArray}.
* @return The first {@link AllocationNode} that contains unread bytes after this method returns.
*/ */
private void readEncryptionData(DecoderInputBuffer buffer, SampleExtrasHolder extrasHolder) { private static AllocationNode readEncryptionData(
AllocationNode allocationNode,
DecoderInputBuffer buffer,
SampleExtrasHolder extrasHolder,
ParsableByteArray scratch) {
long offset = extrasHolder.offset; long offset = extrasHolder.offset;
// Read the signal byte. // Read the signal byte.
scratch.reset(1); scratch.reset(1);
readData(offset, scratch.getData(), 1); allocationNode = readData(allocationNode, offset, scratch.getData(), 1);
offset++; offset++;
byte signalByte = scratch.getData()[0]; byte signalByte = scratch.getData()[0];
boolean subsampleEncryption = (signalByte & 0x80) != 0; boolean subsampleEncryption = (signalByte & 0x80) != 0;
...@@ -239,14 +306,14 @@ import java.util.Arrays; ...@@ -239,14 +306,14 @@ import java.util.Arrays;
// Zero out cryptoInfo.iv so that if ivSize < 16, the remaining bytes are correctly set to 0. // Zero out cryptoInfo.iv so that if ivSize < 16, the remaining bytes are correctly set to 0.
Arrays.fill(cryptoInfo.iv, (byte) 0); Arrays.fill(cryptoInfo.iv, (byte) 0);
} }
readData(offset, cryptoInfo.iv, ivSize); allocationNode = readData(allocationNode, offset, cryptoInfo.iv, ivSize);
offset += ivSize; offset += ivSize;
// Read the subsample count, if present. // Read the subsample count, if present.
int subsampleCount; int subsampleCount;
if (subsampleEncryption) { if (subsampleEncryption) {
scratch.reset(2); scratch.reset(2);
readData(offset, scratch.getData(), 2); allocationNode = readData(allocationNode, offset, scratch.getData(), 2);
offset += 2; offset += 2;
subsampleCount = scratch.readUnsignedShort(); subsampleCount = scratch.readUnsignedShort();
} else { } else {
...@@ -265,7 +332,7 @@ import java.util.Arrays; ...@@ -265,7 +332,7 @@ import java.util.Arrays;
if (subsampleEncryption) { if (subsampleEncryption) {
int subsampleDataLength = 6 * subsampleCount; int subsampleDataLength = 6 * subsampleCount;
scratch.reset(subsampleDataLength); scratch.reset(subsampleDataLength);
readData(offset, scratch.getData(), subsampleDataLength); allocationNode = readData(allocationNode, offset, scratch.getData(), subsampleDataLength);
offset += subsampleDataLength; offset += subsampleDataLength;
scratch.setPosition(0); scratch.setPosition(0);
for (int i = 0; i < subsampleCount; i++) { for (int i = 0; i < subsampleCount; i++) {
...@@ -293,120 +360,76 @@ import java.util.Arrays; ...@@ -293,120 +360,76 @@ import java.util.Arrays;
int bytesRead = (int) (offset - extrasHolder.offset); int bytesRead = (int) (offset - extrasHolder.offset);
extrasHolder.offset += bytesRead; extrasHolder.offset += bytesRead;
extrasHolder.size -= bytesRead; extrasHolder.size -= bytesRead;
return allocationNode;
} }
/** /**
* Reads data from the front of the rolling buffer. * Reads data from {@code allocationNode} and its following nodes.
* *
* @param allocationNode The first {@link AllocationNode} containing data yet to be read.
* @param absolutePosition The absolute position from which data should be read. * @param absolutePosition The absolute position from which data should be read.
* @param target The buffer into which data should be written. * @param target The buffer into which data should be written.
* @param length The number of bytes to read. * @param length The number of bytes to read.
* @return The first {@link AllocationNode} that contains unread bytes after this method returns.
*/ */
private void readData(long absolutePosition, ByteBuffer target, int length) { private static AllocationNode readData(
advanceReadTo(absolutePosition); AllocationNode allocationNode, long absolutePosition, ByteBuffer target, int length) {
allocationNode = getNodeContainingPosition(allocationNode, absolutePosition);
int remaining = length; int remaining = length;
while (remaining > 0) { while (remaining > 0) {
int toCopy = min(remaining, (int) (readAllocationNode.endPosition - absolutePosition)); int toCopy = min(remaining, (int) (allocationNode.endPosition - absolutePosition));
Allocation allocation = readAllocationNode.allocation; Allocation allocation = allocationNode.allocation;
target.put(allocation.data, readAllocationNode.translateOffset(absolutePosition), toCopy); target.put(allocation.data, allocationNode.translateOffset(absolutePosition), toCopy);
remaining -= toCopy; remaining -= toCopy;
absolutePosition += toCopy; absolutePosition += toCopy;
if (absolutePosition == readAllocationNode.endPosition) { if (absolutePosition == allocationNode.endPosition) {
readAllocationNode = readAllocationNode.next; allocationNode = allocationNode.next;
} }
} }
return allocationNode;
} }
/** /**
* Reads data from the front of the rolling buffer. * Reads data from {@code allocationNode} and its following nodes.
* *
* @param allocationNode The first {@link AllocationNode} containing data yet to be read.
* @param absolutePosition The absolute position from which data should be read. * @param absolutePosition The absolute position from which data should be read.
* @param target The array into which data should be written. * @param target The array into which data should be written.
* @param length The number of bytes to read. * @param length The number of bytes to read.
* @return The first {@link AllocationNode} that contains unread bytes after this method returns.
*/ */
private void readData(long absolutePosition, byte[] target, int length) { private static AllocationNode readData(
advanceReadTo(absolutePosition); AllocationNode allocationNode, long absolutePosition, byte[] target, int length) {
allocationNode = getNodeContainingPosition(allocationNode, absolutePosition);
int remaining = length; int remaining = length;
while (remaining > 0) { while (remaining > 0) {
int toCopy = min(remaining, (int) (readAllocationNode.endPosition - absolutePosition)); int toCopy = min(remaining, (int) (allocationNode.endPosition - absolutePosition));
Allocation allocation = readAllocationNode.allocation; Allocation allocation = allocationNode.allocation;
System.arraycopy( System.arraycopy(
allocation.data, allocation.data,
readAllocationNode.translateOffset(absolutePosition), allocationNode.translateOffset(absolutePosition),
target, target,
length - remaining, length - remaining,
toCopy); toCopy);
remaining -= toCopy; remaining -= toCopy;
absolutePosition += toCopy; absolutePosition += toCopy;
if (absolutePosition == readAllocationNode.endPosition) { if (absolutePosition == allocationNode.endPosition) {
readAllocationNode = readAllocationNode.next; allocationNode = allocationNode.next;
} }
} }
return allocationNode;
} }
/** /**
* Advances the read position to the specified absolute position. * Returns the {@link AllocationNode} in {@code allocationNode}'s chain which contains the given
* * {@code absolutePosition}.
* @param absolutePosition The position to which {@link #readAllocationNode} should be advanced.
*/
private void advanceReadTo(long absolutePosition) {
while (absolutePosition >= readAllocationNode.endPosition) {
readAllocationNode = readAllocationNode.next;
}
}
/**
* Clears allocation nodes starting from {@code fromNode}.
*
* @param fromNode The node from which to clear.
*/ */
private void clearAllocationNodes(AllocationNode fromNode) { private static AllocationNode getNodeContainingPosition(
if (!fromNode.wasInitialized) { AllocationNode allocationNode, long absolutePosition) {
return; while (absolutePosition >= allocationNode.endPosition) {
} allocationNode = allocationNode.next;
// Bulk release allocations for performance (it's significantly faster when using
// DefaultAllocator because the allocator's lock only needs to be acquired and released once)
// [Internal: See b/29542039].
int allocationCount =
(writeAllocationNode.wasInitialized ? 1 : 0)
+ ((int) (writeAllocationNode.startPosition - fromNode.startPosition)
/ allocationLength);
Allocation[] allocationsToRelease = new Allocation[allocationCount];
AllocationNode currentNode = fromNode;
for (int i = 0; i < allocationsToRelease.length; i++) {
allocationsToRelease[i] = currentNode.allocation;
currentNode = currentNode.clear();
}
allocator.release(allocationsToRelease);
}
/**
* Called before writing sample data to {@link #writeAllocationNode}. May cause {@link
* #writeAllocationNode} to be initialized.
*
* @param length The number of bytes that the caller wishes to write.
* @return The number of bytes that the caller is permitted to write, which may be less than
* {@code length}.
*/
private int preAppend(int length) {
if (!writeAllocationNode.wasInitialized) {
writeAllocationNode.initialize(
allocator.allocate(),
new AllocationNode(writeAllocationNode.endPosition, allocationLength));
}
return min(length, (int) (writeAllocationNode.endPosition - totalBytesWritten));
}
/**
* Called after writing sample data. May cause {@link #writeAllocationNode} to be advanced.
*
* @param length The number of bytes that were written.
*/
private void postAppend(int length) {
totalBytesWritten += length;
if (totalBytesWritten == writeAllocationNode.endPosition) {
writeAllocationNode = writeAllocationNode.next;
} }
return allocationNode;
} }
/** A node in a linked list of {@link Allocation}s held by the output. */ /** A node in a linked list of {@link Allocation}s held by the output. */
......
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