mediabunny
Version:
Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.
138 lines (104 loc) • 2.99 kB
text/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 { Reader } from '../reader';
export const MIN_BOX_HEADER_SIZE = 8;
export const MAX_BOX_HEADER_SIZE = 16;
export class IsobmffReader {
pos = 0;
constructor(public reader: Reader) {}
readBytes(length: number) {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + length);
this.pos += length;
return new Uint8Array(view.buffer, offset, length);
}
readU8() {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 1);
this.pos++;
return view.getUint8(offset);
}
readU16() {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 2);
this.pos += 2;
return view.getUint16(offset, false);
}
readI16() {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 2);
this.pos += 2;
return view.getInt16(offset, false);
}
readU24() {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 3);
this.pos += 3;
const high = view.getUint16(offset, false);
const low = view.getUint8(offset + 2);
return high * 0x100 + low;
}
readU32() {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 4);
this.pos += 4;
return view.getUint32(offset, false);
}
readI32() {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 4);
this.pos += 4;
return view.getInt32(offset, false);
}
readU64() {
const high = this.readU32();
const low = this.readU32();
return high * 0x100000000 + low;
}
readI64() {
const high = this.readI32();
const low = this.readU32();
return high * 0x100000000 + low;
}
readF64() {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + 8);
this.pos += 8;
return view.getFloat64(offset, false);
}
readFixed_16_16() {
return this.readI32() / 0x10000;
}
readFixed_2_30() {
return this.readI32() / 0x40000000;
}
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;
}
readIsomVariableInteger() {
let result = 0;
for (let i = 0; i < 4; i++) {
result <<= 7;
const nextByte = this.readU8();
result |= nextByte & 0x7f;
if ((nextByte & 0x80) === 0) {
break;
}
}
return result;
}
readBoxHeader() {
let totalSize = this.readU32();
const name = this.readAscii(4);
let headerSize = 8;
const hasLargeSize = totalSize === 1;
if (hasLargeSize) {
totalSize = this.readU64();
headerSize = 16;
}
return { name, totalSize, headerSize, contentSize: totalSize - headerSize };
}
}