Skip to content

Commit

Permalink
impl ogg parser
Browse files Browse the repository at this point in the history
  • Loading branch information
shinyoshiaki committed Dec 10, 2023
1 parent d852b44 commit 16af492
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/rtp/src/container/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./mp4";
export * from "./webm";
export * from "./ogg";
1 change: 1 addition & 0 deletions packages/rtp/src/container/ogg/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./parser";
103 changes: 103 additions & 0 deletions packages/rtp/src/container/ogg/parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
export interface Page {
segments: Buffer[];
segmentTable: number[];
}

export class OggParser {
pages: Page[] = [];

private checkSegments(page?: Page) {
if (!page) {
return { ok: true };
}
for (let i = 0; i < page.segmentTable.length; i++) {
const segment = page.segments[i];
const table = page.segmentTable[i];
if (segment.length !== table) {
return { invalid: i };
}
}
return { ok: true };
}

exportSegments() {
let i = 0;
const pages: Page[] = [];
for (; i < this.pages.length; i++) {
const page = this.pages[i];
const { invalid } = this.checkSegments(page);
if (invalid) {
break;
}
pages.push(page);
}
this.pages = this.pages.slice(i);
return pages.flatMap((page) => page.segments);
}

read(buf: Buffer) {
for (let index = 0; ; ) {
if (index > buf.length) break;
try {
const lastPage = this.pages.at(-1);
const invalid = this.checkSegments(lastPage).invalid;

if (lastPage && invalid) {
for (let i = invalid; i < lastPage.segmentTable.length; i++) {
const diff = lastPage.segmentTable[i] - lastPage.segments[i].length;
lastPage.segments[i] = Buffer.concat([
lastPage.segments[i],
buf.subarray(index, index + diff),
]);
index += diff;
}
} else {
const magic = buf.subarray(index, index + 4).toString();
index += 4; // skip magic
index += 1; // skip version
const headerType = buf.readUInt8(index);
index += 1; // skip header type
const granulePosition = buf.readBigInt64LE(index);
index += 8; // skip granule position
const bitstreamSerialNumber = buf.readUInt32LE(index);
index += 4; // skip bitstream serial number
const pageSequenceNumber = buf.readUInt32LE(index);
index += 4; // skip page sequence number
const pageChecksum = buf.readUInt32LE(index);
index += 4; // skip page checksum
const pageSegments = buf.readUInt8(index);
index += 1; // skip page segments
const segmentTable = buf.subarray(index, index + pageSegments);
index += pageSegments; // skip segment table

const segments: Buffer[] = [];
for (let i = 0; i < pageSegments; i++) {
const segment = segmentTable.readUInt8(i);
const segmentData = buf.subarray(index, index + segment);
index += segment;
segments.push(segmentData);
}

console.log({
magic,
headerType,
granulePosition,
bitstreamSerialNumber,
pageSequenceNumber,
pageChecksum,
pageSegments,
segmentTable,
});

this.pages.push({
segments,
segmentTable: [...segmentTable.map((s) => s)],
});
}
} catch (error) {
break;
}
}
return this;
}
}

0 comments on commit 16af492

Please sign in to comment.