mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-30 04:13:51 +02:00
Add new slice-based reader system, port all demuxers to new reader system, add optimized BlobSource
This commit is contained in:
+50
-100
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Reader } from '../reader';
|
||||
import { FileSlice, readI64Le, readU32Le, readU8 } from '../reader2';
|
||||
import { OGGS } from './ogg-misc';
|
||||
|
||||
export const MIN_PAGE_HEADER_SIZE = 27;
|
||||
@@ -26,118 +26,68 @@ export type Page = {
|
||||
lacingValues: Uint8Array;
|
||||
};
|
||||
|
||||
export class OggReader {
|
||||
pos = 0;
|
||||
constructor(public reader: Reader) {}
|
||||
export const readPageHeader = (slice: FileSlice): Page | null => {
|
||||
const startPos = slice.filePos;
|
||||
|
||||
readBytes(length: number) {
|
||||
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + length);
|
||||
this.pos += length;
|
||||
|
||||
return new Uint8Array(view.buffer, offset, length);
|
||||
const capturePattern = readU32Le(slice);
|
||||
if (capturePattern !== OGGS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
readU8() {
|
||||
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 1);
|
||||
this.pos += 1;
|
||||
slice.skip(1); // Version
|
||||
const headerType = readU8(slice);
|
||||
const granulePosition = readI64Le(slice);
|
||||
const serialNumber = readU32Le(slice);
|
||||
const sequenceNumber = readU32Le(slice);
|
||||
const checksum = readU32Le(slice);
|
||||
|
||||
return view.getUint8(offset);
|
||||
const numberPageSegments = readU8(slice);
|
||||
const lacingValues = new Uint8Array(numberPageSegments);
|
||||
|
||||
for (let i = 0; i < numberPageSegments; i++) {
|
||||
lacingValues[i] = readU8(slice);
|
||||
}
|
||||
|
||||
readU32() {
|
||||
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 4);
|
||||
this.pos += 4;
|
||||
const headerSize = 27 + numberPageSegments;
|
||||
const dataSize = lacingValues.reduce((a, b) => a + b, 0);
|
||||
const totalSize = headerSize + dataSize;
|
||||
|
||||
return view.getUint32(offset, true);
|
||||
}
|
||||
return {
|
||||
headerStartPos: startPos,
|
||||
totalSize,
|
||||
dataStartPos: startPos + headerSize,
|
||||
dataSize,
|
||||
headerType,
|
||||
granulePosition,
|
||||
serialNumber,
|
||||
sequenceNumber,
|
||||
checksum,
|
||||
lacingValues,
|
||||
};
|
||||
};
|
||||
|
||||
readI32() {
|
||||
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 4);
|
||||
this.pos += 4;
|
||||
export const findNextPageHeader = (slice: FileSlice, until: number) => {
|
||||
while (slice.filePos < until - (4 - 1)) { // Size of word minus 1
|
||||
const word = readU32Le(slice);
|
||||
const firstByte = word & 0xff;
|
||||
const secondByte = (word >>> 8) & 0xff;
|
||||
const thirdByte = (word >>> 16) & 0xff;
|
||||
const fourthByte = (word >>> 24) & 0xff;
|
||||
|
||||
return view.getInt32(offset, true);
|
||||
}
|
||||
|
||||
readI64() {
|
||||
const low = this.readU32();
|
||||
const high = this.readI32();
|
||||
return high * 0x100000000 + low;
|
||||
}
|
||||
|
||||
readAscii(length: number) {
|
||||
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + length);
|
||||
this.pos += length;
|
||||
|
||||
let str = '';
|
||||
for (let i = 0; i < length; i++) {
|
||||
str += String.fromCharCode(view.getUint8(offset + i));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
readPageHeader(): Page | null {
|
||||
const startPos = this.pos;
|
||||
|
||||
const capturePattern = this.readU32();
|
||||
if (capturePattern !== OGGS) {
|
||||
return null;
|
||||
const O = 0x4f; // 'O'
|
||||
if (firstByte !== O && secondByte !== O && thirdByte !== O && fourthByte !== O) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.pos += 1; // Version
|
||||
const headerType = this.readU8();
|
||||
const granulePosition = this.readI64();
|
||||
const serialNumber = this.readU32();
|
||||
const sequenceNumber = this.readU32();
|
||||
const checksum = this.readU32();
|
||||
slice.skip(-4);
|
||||
|
||||
const numberPageSegments = this.readU8();
|
||||
const lacingValues = new Uint8Array(numberPageSegments);
|
||||
|
||||
for (let i = 0; i < numberPageSegments; i++) {
|
||||
lacingValues[i] = this.readU8();
|
||||
if (word === OGGS) {
|
||||
// We have found the capture pattern
|
||||
return true;
|
||||
}
|
||||
|
||||
const headerSize = 27 + numberPageSegments;
|
||||
const dataSize = lacingValues.reduce((a, b) => a + b, 0);
|
||||
const totalSize = headerSize + dataSize;
|
||||
|
||||
return {
|
||||
headerStartPos: startPos,
|
||||
totalSize,
|
||||
dataStartPos: startPos + headerSize,
|
||||
dataSize,
|
||||
headerType,
|
||||
granulePosition,
|
||||
serialNumber,
|
||||
sequenceNumber,
|
||||
checksum,
|
||||
lacingValues,
|
||||
};
|
||||
slice.skip(1);
|
||||
}
|
||||
|
||||
findNextPageHeader(until: number) {
|
||||
while (this.pos < until - (4 - 1)) { // Size of word minus 1
|
||||
const word = this.readU32();
|
||||
const firstByte = word & 0xff;
|
||||
const secondByte = (word >>> 8) & 0xff;
|
||||
const thirdByte = (word >>> 16) & 0xff;
|
||||
const fourthByte = (word >>> 24) & 0xff;
|
||||
|
||||
const O = 0x4f; // 'O'
|
||||
if (firstByte !== O && secondByte !== O && thirdByte !== O && fourthByte !== O) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.pos -= 4;
|
||||
|
||||
if (word === OGGS) {
|
||||
// We have found the capture pattern
|
||||
return true;
|
||||
}
|
||||
|
||||
this.pos += 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user