googlevideo
Version:
A set of utilities for working with Google Video APIs.
83 lines (82 loc) • 3.1 kB
JavaScript
export class ChunkedDataBuffer {
constructor(chunks = []) {
this.chunks = [];
this.currentChunkOffset = this.currentChunkIndex = 0;
this.currentDataView = undefined;
this.totalLength = 0;
chunks.forEach((chunk) => {
this.append(chunk);
});
}
getLength() {
return this.totalLength;
}
append(chunk) {
if (this.canMergeWithLastChunk(chunk)) {
const lastChunk = this.chunks[this.chunks.length - 1];
this.chunks[this.chunks.length - 1] = new Uint8Array(lastChunk.buffer, lastChunk.byteOffset, lastChunk.length + chunk.length);
this.resetFocus();
}
else {
this.chunks.push(chunk);
}
this.totalLength += chunk.length;
}
split(position) {
const extractedBuffer = new ChunkedDataBuffer();
const remainingBuffer = new ChunkedDataBuffer();
const iterator = this.chunks[Symbol.iterator]();
let item = iterator.next();
while (!item.done) {
const chunk = item.value;
if (position >= chunk.length) {
extractedBuffer.append(chunk);
position -= chunk.length;
}
else if (position > 0) {
extractedBuffer.append(new Uint8Array(chunk.buffer, chunk.byteOffset, position));
remainingBuffer.append(new Uint8Array(chunk.buffer, chunk.byteOffset + position, chunk.length - position));
position = 0;
}
else {
remainingBuffer.append(chunk);
}
item = iterator.next();
}
return { extractedBuffer, remainingBuffer };
}
isFocused(position) {
return position >= this.currentChunkOffset && position < this.currentChunkOffset + this.chunks[this.currentChunkIndex].length;
}
focus(position) {
if (!this.isFocused(position)) {
if (position < this.currentChunkOffset)
this.resetFocus();
while (this.currentChunkOffset + this.chunks[this.currentChunkIndex].length <= position &&
this.currentChunkIndex < this.chunks.length - 1) {
this.currentChunkOffset += this.chunks[this.currentChunkIndex].length;
this.currentChunkIndex += 1;
}
this.currentDataView = undefined;
}
}
canReadBytes(position, length) {
return position + length <= this.totalLength;
}
getUint8(position) {
this.focus(position);
return this.chunks[this.currentChunkIndex][position - this.currentChunkOffset];
}
canMergeWithLastChunk(chunk) {
if (this.chunks.length === 0)
return false;
const lastChunk = this.chunks[this.chunks.length - 1];
return (lastChunk.buffer === chunk.buffer &&
lastChunk.byteOffset + lastChunk.length === chunk.byteOffset);
}
resetFocus() {
this.currentDataView = undefined;
this.currentChunkIndex = 0;
this.currentChunkOffset = 0;
}
}