Skip to content

Commit

Permalink
fix: vorbis packet structure, resolve #84
Browse files Browse the repository at this point in the history
  • Loading branch information
eshaz committed Jun 9, 2023
1 parent c1ef281 commit 60101e3
Show file tree
Hide file tree
Showing 32 changed files with 984 additions and 657 deletions.
131 changes: 89 additions & 42 deletions demo/flac-decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -3171,6 +3171,7 @@
onCodec(this[codec]);

this._identificationHeader = null;
this._setupComplete = false;

this._mode = {
count: 0,
Expand All @@ -3184,23 +3185,26 @@
}

[parseOggPage](oggPage) {
const oggPageSegments = frameStore.get(oggPage)[segments];

if (oggPage[pageSequenceNumber] === 0) {
// Identification header

this._headerCache[enable]();
this._identificationHeader = oggPage[data$1];
} else if (oggPage[pageSequenceNumber] === 1) {
// gather WEBM CodecPrivate data
if (oggPageSegments[1]) {
this._vorbisComments = oggPageSegments[0];
this._vorbisSetup = oggPageSegments[1];

this._mode = this._parseSetupHeader(oggPageSegments[1]);
}
} else {
oggPage[codecFrames] = oggPageSegments.map((segment) => {
oggPage[codecFrames] = [];

for (const oggPageSegment of frameStore.get(oggPage)[segments]) {
if (oggPageSegment[0] === 1) {
// Identification header

this._headerCache[enable]();
this._identificationHeader = oggPage[data$1];
this._setupComplete = false;
} else if (oggPageSegment[0] === 3) {
// comment header

this._vorbisComments = oggPageSegment;
} else if (oggPageSegment[0] === 5) {
// setup header

this._vorbisSetup = oggPageSegment;
this._mode = this._parseSetupHeader(oggPageSegment);
this._setupComplete = true;
} else if (this._setupComplete) {
const header = VorbisHeader[getHeaderFromUint8Array](
this._identificationHeader,
this._headerCache,
Expand All @@ -3209,18 +3213,20 @@
);

if (header) {
return new VorbisFrame(
segment,
header,
this._getSamples(segment, header)
oggPage[codecFrames].push(
new VorbisFrame(
oggPageSegment,
header,
this._getSamples(oggPageSegment, header)
)
);
} else {
this._codecParser[logError](
"Failed to parse Ogg Vorbis Header",
"Not a valid Ogg Vorbis file"
);
}

this._codecParser[logError](
"Failed to parse Ogg Vorbis Header",
"Not a valid Ogg Vorbis file"
);
});
}
}

return oggPage;
Expand Down Expand Up @@ -3360,17 +3366,15 @@
*/


class OggParser extends Parser {
class OggStream {
constructor(codecParser, headerCache, onCodec) {
super(codecParser, headerCache);

this._codecParser = codecParser;
this._headerCache = headerCache;
this._onCodec = onCodec;
this.Frame = OggPage;
this.Header = OggPageHeader;
this._codec = null;
this._continuedPacket = new uint8Array();

this._pageSequenceNumber = 0;
this._continuedPacket = new uint8Array();
this._codec = null;
this._isSupported = null;
}

get [codec]() {
Expand All @@ -3389,13 +3393,11 @@
}
}

_checkForIdentifier({ data }) {
_checkCodecSupport({ data }) {
const idString = bytesToString(data[subarray](0, 8));

switch (idString) {
case "fishead\0":
case "fisbone\0":
case "index\0\0\0":
return false; // ignore ogg skeleton packets
case "OpusHead":
this._updateCodec("opus", OpusParser);
Expand All @@ -3406,6 +3408,8 @@
case /^\x01vorbis/.test(idString) && idString:
this._updateCodec(vorbis, VorbisParser);
return true;
default:
return false;
}
}

Expand All @@ -3426,16 +3430,18 @@
this._pageSequenceNumber = oggPage[pageSequenceNumber];
}

*[parseFrame]() {
const oggPage = yield* this[fixedLengthFrameSync](true);
_parsePage(oggPage) {
if (this._isSupported === null) {
this._pageSequenceNumber = oggPage[pageSequenceNumber];
this._isSupported = this._checkCodecSupport(oggPage);
}

this._checkPageSequenceNumber(oggPage);

const oggPageStore = frameStore.get(oggPage);
const headerData = headerStore.get(oggPageStore[header]);

let offset = 0;

oggPageStore[segments] = headerData[pageSegmentTable].map((segmentLength) =>
oggPage[data$1][subarray](offset, (offset += segmentLength))
);
Expand All @@ -3461,14 +3467,55 @@
);
}

if (this._codec || this._checkForIdentifier(oggPage)) {
if (this._isSupported) {
const frame = this._parser[parseOggPage](oggPage);
this._codecParser[mapFrameStats](frame);

return frame;
} else {
return oggPage;
}
}
}

class OggParser extends Parser {
constructor(codecParser, headerCache, onCodec) {
super(codecParser, headerCache);

this._onCodec = onCodec;
this.Frame = OggPage;
this.Header = OggPageHeader;

this._streams = new Map();
this._currentSerialNumber = null;
}

get [codec]() {
const oggStream = this._streams.get(this._currentSerialNumber);

return oggStream ? oggStream.codec : "";
}

*[parseFrame]() {
const oggPage = yield* this[fixedLengthFrameSync](true);
this._currentSerialNumber = oggPage[streamSerialNumber];

let oggStream = this._streams.get(this._currentSerialNumber);
if (!oggStream) {
oggStream = new OggStream(
this._codecParser,
this._headerCache,
this._onCodec
);
this._streams.set(this._currentSerialNumber, oggStream);
}

if (oggPage[isLastPage]) this._streams.delete(this._currentSerialNumber);

return oggStream._parsePage(oggPage);
}
}

/* Copyright 2020-2023 Ethan Halsall
This file is part of codec-parser.
Expand Down
4 changes: 2 additions & 2 deletions demo/flac-decoder.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demo/flac-decoder.min.js.map

Large diffs are not rendered by default.

Loading

0 comments on commit 60101e3

Please sign in to comment.