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;
*/
public void readToBuffer(DecoderInputBuffer buffer, SampleExtrasHolder extrasHolder) {
// Read encryption data if the sample is encrypted.
AllocationNode readAllocationNode = this.readAllocationNode;
if (buffer.isEncrypted()) {
readEncryptionData(buffer, extrasHolder);
readAllocationNode = readEncryptionData(readAllocationNode, buffer, extrasHolder, scratch);
}
// Read sample data, extracting supplemental data into a separate buffer if needed.
if (buffer.hasSupplementalData()) {
// If there is supplemental data, the sample data is prefixed by its size.
scratch.reset(4);
readData(extrasHolder.offset, scratch.getData(), 4);
readAllocationNode = readData(readAllocationNode, extrasHolder.offset, scratch.getData(), 4);
int sampleSize = scratch.readUnsignedIntToInt();
extrasHolder.offset += 4;
extrasHolder.size -= 4;
// Write the sample data.
buffer.ensureSpaceForWrite(sampleSize);
readData(extrasHolder.offset, buffer.data, sampleSize);
readAllocationNode =
readData(readAllocationNode, extrasHolder.offset, buffer.data, sampleSize);
extrasHolder.offset += sampleSize;
extrasHolder.size -= sampleSize;
// Write the remaining data as supplemental data.
buffer.resetSupplementalData(extrasHolder.size);
readData(extrasHolder.offset, buffer.supplementalData, extrasHolder.size);
readAllocationNode =
readData(
readAllocationNode, extrasHolder.offset, buffer.supplementalData, extrasHolder.size);
} else {
// Write the sample data.
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;
// 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
* SampleExtrasHolder#size} is adjusted to subtract the number of bytes that were read. The same
* 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 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;
// Read the signal byte.
scratch.reset(1);
readData(offset, scratch.getData(), 1);
allocationNode = readData(allocationNode, offset, scratch.getData(), 1);
offset++;
byte signalByte = scratch.getData()[0];
boolean subsampleEncryption = (signalByte & 0x80) != 0;
......@@ -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.
Arrays.fill(cryptoInfo.iv, (byte) 0);
}
readData(offset, cryptoInfo.iv, ivSize);
allocationNode = readData(allocationNode, offset, cryptoInfo.iv, ivSize);
offset += ivSize;
// Read the subsample count, if present.
int subsampleCount;
if (subsampleEncryption) {
scratch.reset(2);
readData(offset, scratch.getData(), 2);
allocationNode = readData(allocationNode, offset, scratch.getData(), 2);
offset += 2;
subsampleCount = scratch.readUnsignedShort();
} else {
......@@ -265,7 +332,7 @@ import java.util.Arrays;
if (subsampleEncryption) {
int subsampleDataLength = 6 * subsampleCount;
scratch.reset(subsampleDataLength);
readData(offset, scratch.getData(), subsampleDataLength);
allocationNode = readData(allocationNode, offset, scratch.getData(), subsampleDataLength);
offset += subsampleDataLength;
scratch.setPosition(0);
for (int i = 0; i < subsampleCount; i++) {
......@@ -293,120 +360,76 @@ import java.util.Arrays;
int bytesRead = (int) (offset - extrasHolder.offset);
extrasHolder.offset += 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 target The buffer into which data should be written.
* @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) {
advanceReadTo(absolutePosition);
private static AllocationNode readData(
AllocationNode allocationNode, long absolutePosition, ByteBuffer target, int length) {
allocationNode = getNodeContainingPosition(allocationNode, absolutePosition);
int remaining = length;
while (remaining > 0) {
int toCopy = min(remaining, (int) (readAllocationNode.endPosition - absolutePosition));
Allocation allocation = readAllocationNode.allocation;
target.put(allocation.data, readAllocationNode.translateOffset(absolutePosition), toCopy);
int toCopy = min(remaining, (int) (allocationNode.endPosition - absolutePosition));
Allocation allocation = allocationNode.allocation;
target.put(allocation.data, allocationNode.translateOffset(absolutePosition), toCopy);
remaining -= toCopy;
absolutePosition += toCopy;
if (absolutePosition == readAllocationNode.endPosition) {
readAllocationNode = readAllocationNode.next;
if (absolutePosition == allocationNode.endPosition) {
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 target The array into which data should be written.
* @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) {
advanceReadTo(absolutePosition);
private static AllocationNode readData(
AllocationNode allocationNode, long absolutePosition, byte[] target, int length) {
allocationNode = getNodeContainingPosition(allocationNode, absolutePosition);
int remaining = length;
while (remaining > 0) {
int toCopy = min(remaining, (int) (readAllocationNode.endPosition - absolutePosition));
Allocation allocation = readAllocationNode.allocation;
int toCopy = min(remaining, (int) (allocationNode.endPosition - absolutePosition));
Allocation allocation = allocationNode.allocation;
System.arraycopy(
allocation.data,
readAllocationNode.translateOffset(absolutePosition),
allocationNode.translateOffset(absolutePosition),
target,
length - remaining,
toCopy);
remaining -= toCopy;
absolutePosition += toCopy;
if (absolutePosition == readAllocationNode.endPosition) {
readAllocationNode = readAllocationNode.next;
if (absolutePosition == allocationNode.endPosition) {
allocationNode = allocationNode.next;
}
}
return allocationNode;
}
/**
* Advances the read position to the specified absolute position.
*
* @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.
* Returns the {@link AllocationNode} in {@code allocationNode}'s chain which contains the given
* {@code absolutePosition}.
*/
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;
private static AllocationNode getNodeContainingPosition(
AllocationNode allocationNode, long absolutePosition) {
while (absolutePosition >= allocationNode.endPosition) {
allocationNode = allocationNode.next;
}
return allocationNode;
}
/** 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