mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-28 11:23:45 +02:00
94 lines
2.3 KiB
TypeScript
94 lines
2.3 KiB
TypeScript
/*!
|
|
* Copyright (c) 2025-present, Vanilagy and contributors
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
import { FileSlice, readI64Le, readU32Le, readU8 } from '../reader';
|
|
import { OGGS } from './ogg-misc';
|
|
|
|
export const MIN_PAGE_HEADER_SIZE = 27;
|
|
export const MAX_PAGE_HEADER_SIZE = 27 + 255;
|
|
export const MAX_PAGE_SIZE = MAX_PAGE_HEADER_SIZE + 255 * 255;
|
|
|
|
export type Page = {
|
|
headerStartPos: number;
|
|
totalSize: number;
|
|
dataStartPos: number;
|
|
dataSize: number;
|
|
headerType: number;
|
|
granulePosition: number;
|
|
serialNumber: number;
|
|
sequenceNumber: number;
|
|
checksum: number;
|
|
lacingValues: Uint8Array;
|
|
};
|
|
|
|
export const readPageHeader = (slice: FileSlice): Page | null => {
|
|
const startPos = slice.filePos;
|
|
|
|
const capturePattern = readU32Le(slice);
|
|
if (capturePattern !== OGGS) {
|
|
return null;
|
|
}
|
|
|
|
slice.skip(1); // Version
|
|
const headerType = readU8(slice);
|
|
const granulePosition = readI64Le(slice);
|
|
const serialNumber = readU32Le(slice);
|
|
const sequenceNumber = readU32Le(slice);
|
|
const checksum = readU32Le(slice);
|
|
|
|
const numberPageSegments = readU8(slice);
|
|
const lacingValues = new Uint8Array(numberPageSegments);
|
|
|
|
for (let i = 0; i < numberPageSegments; i++) {
|
|
lacingValues[i] = readU8(slice);
|
|
}
|
|
|
|
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,
|
|
};
|
|
};
|
|
|
|
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;
|
|
|
|
const O = 0x4f; // 'O'
|
|
if (firstByte !== O && secondByte !== O && thirdByte !== O && fourthByte !== O) {
|
|
continue;
|
|
}
|
|
|
|
slice.skip(-4);
|
|
|
|
if (word === OGGS) {
|
|
// We have found the capture pattern
|
|
return true;
|
|
}
|
|
|
|
slice.skip(1);
|
|
}
|
|
|
|
return false;
|
|
};
|