mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 19:03:46 +02:00
Support AVC in Annex B format, add AVCDecoderConfigurationRecord extraction logic, add Annex B to AVCC converter, add support for Matroska Clusters with undefined size, & a couple other improvements
This commit is contained in:
+18
-52
@@ -1,5 +1,5 @@
|
||||
import { parseOpusTocByte } from '../codec';
|
||||
import { assert, ilog, readBits, toDataView } from '../misc';
|
||||
import { assert, Bitstream, ilog, toDataView } from '../misc';
|
||||
|
||||
export const OGGS = 0x5367674f; // 'OggS'
|
||||
|
||||
@@ -96,40 +96,6 @@ export const extractSampleMetadata = (
|
||||
|
||||
// Based on vorbis_parser.c from FFmpeg.
|
||||
export const parseModesFromVorbisSetupPacket = (setupHeader: Uint8Array) => {
|
||||
class Bitstream {
|
||||
bytes: Uint8Array;
|
||||
pos: number;
|
||||
|
||||
constructor(bytes: Uint8Array) {
|
||||
this.bytes = bytes;
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
read(n: number): number {
|
||||
const result = readBits(this.bytes, this.pos, this.pos + n);
|
||||
this.pos += n;
|
||||
return result;
|
||||
}
|
||||
|
||||
skip(n: number): void {
|
||||
this.pos += n;
|
||||
}
|
||||
|
||||
getBitsLeft(): number {
|
||||
return this.bytes.length * 8 - this.pos;
|
||||
}
|
||||
|
||||
getBitCount(): number {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
clone(): Bitstream {
|
||||
const clone = new Bitstream(this.bytes);
|
||||
clone.pos = this.pos;
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that this is a Setup header.
|
||||
if (setupHeader.length < 7) {
|
||||
throw new Error('Setup header is too short.');
|
||||
@@ -150,14 +116,14 @@ export const parseModesFromVorbisSetupPacket = (setupHeader: Uint8Array) => {
|
||||
}
|
||||
|
||||
// Initialize a Bitstream on the reversed buffer.
|
||||
const bs = new Bitstream(revBuffer);
|
||||
const bitstream = new Bitstream(revBuffer);
|
||||
|
||||
// --- Find the framing bit.
|
||||
// In FFmpeg code, we scan until get_bits1() returns 1.
|
||||
let gotFramingBit = 0;
|
||||
while (bs.getBitsLeft() > 97) {
|
||||
if (bs.read(1) === 1) {
|
||||
gotFramingBit = bs.getBitCount();
|
||||
while (bitstream.getBitsLeft() > 97) {
|
||||
if (bitstream.readBits(1) === 1) {
|
||||
gotFramingBit = bitstream.pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -170,23 +136,23 @@ export const parseModesFromVorbisSetupPacket = (setupHeader: Uint8Array) => {
|
||||
let modeCount = 0;
|
||||
let gotModeHeader = false;
|
||||
let lastModeCount = 0;
|
||||
while (bs.getBitsLeft() >= 97) {
|
||||
const tempPos = bs.pos;
|
||||
const a = bs.read(8);
|
||||
const b = bs.read(16);
|
||||
const c = bs.read(16);
|
||||
while (bitstream.getBitsLeft() >= 97) {
|
||||
const tempPos = bitstream.pos;
|
||||
const a = bitstream.readBits(8);
|
||||
const b = bitstream.readBits(16);
|
||||
const c = bitstream.readBits(16);
|
||||
// If a > 63 or b or c nonzero, assume we’ve gone too far.
|
||||
if (a > 63 || b !== 0 || c !== 0) {
|
||||
bs.pos = tempPos;
|
||||
bitstream.pos = tempPos;
|
||||
break;
|
||||
}
|
||||
bs.skip(1);
|
||||
bitstream.skipBits(1);
|
||||
modeCount++;
|
||||
if (modeCount > 64) {
|
||||
break;
|
||||
}
|
||||
const bsClone = bs.clone();
|
||||
const candidate = bsClone.read(6) + 1;
|
||||
const bsClone = bitstream.clone();
|
||||
const candidate = bsClone.readBits(6) + 1;
|
||||
if (candidate === modeCount) {
|
||||
gotModeHeader = true;
|
||||
lastModeCount = modeCount;
|
||||
@@ -201,16 +167,16 @@ export const parseModesFromVorbisSetupPacket = (setupHeader: Uint8Array) => {
|
||||
const finalModeCount = lastModeCount;
|
||||
|
||||
// --- Reinitialize the bitstream.
|
||||
bs.pos = 0;
|
||||
bitstream.pos = 0;
|
||||
// Skip the bits up to the found framing bit.
|
||||
bs.skip(gotFramingBit);
|
||||
bitstream.skipBits(gotFramingBit);
|
||||
|
||||
// --- Now read, for each mode (in reverse order), 40 bits then one bit.
|
||||
// That one bit is the mode blockflag.
|
||||
const modeBlockflags = Array(finalModeCount).fill(0) as number[];
|
||||
for (let i = finalModeCount - 1; i >= 0; i--) {
|
||||
bs.skip(40);
|
||||
modeBlockflags[i] = bs.read(1);
|
||||
bitstream.skipBits(40);
|
||||
modeBlockflags[i] = bitstream.readBits(1);
|
||||
}
|
||||
|
||||
return { modeBlockflags };
|
||||
|
||||
Reference in New Issue
Block a user