Initial commit
This commit is contained in:
118
node_modules/prism-media/src/opus/OggDemuxer.js
generated
vendored
Normal file
118
node_modules/prism-media/src/opus/OggDemuxer.js
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
const { Transform } = require('stream');
|
||||
|
||||
const OGG_PAGE_HEADER_SIZE = 26;
|
||||
const STREAM_STRUCTURE_VERSION = 0;
|
||||
|
||||
const charCode = x => x.charCodeAt(0);
|
||||
const OGGS_HEADER = Buffer.from([...'OggS'].map(charCode));
|
||||
const OPUS_HEAD = Buffer.from([...'OpusHead'].map(charCode));
|
||||
const OPUS_TAGS = Buffer.from([...'OpusTags'].map(charCode));
|
||||
|
||||
/**
|
||||
* Demuxes an Ogg stream (containing Opus audio) to output an Opus stream.
|
||||
* @extends {TransformStream}
|
||||
* @memberof opus
|
||||
*/
|
||||
class OggDemuxer extends Transform {
|
||||
/**
|
||||
* Creates a new OggOpus demuxer.
|
||||
* @param {Object} [options] options that you would pass to a regular Transform stream.
|
||||
* @memberof opus
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
super(Object.assign({ readableObjectMode: true }, options));
|
||||
this._remainder = null;
|
||||
this._head = null;
|
||||
this._bitstream = null;
|
||||
}
|
||||
|
||||
_transform(chunk, encoding, done) {
|
||||
if (this._remainder) {
|
||||
chunk = Buffer.concat([this._remainder, chunk]);
|
||||
this._remainder = null;
|
||||
}
|
||||
|
||||
while (chunk) {
|
||||
const result = this._readPage(chunk);
|
||||
if (result) chunk = result;
|
||||
else break;
|
||||
}
|
||||
this._remainder = chunk;
|
||||
done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a page from a buffer
|
||||
* @private
|
||||
* @param {Buffer} chunk the chunk containing the page
|
||||
* @returns {boolean|Buffer} if a buffer, it will be a slice of the excess data of the original, otherwise it will be
|
||||
* false and would indicate that there is not enough data to go ahead with reading this page.
|
||||
*/
|
||||
_readPage(chunk) {
|
||||
if (chunk.length < OGG_PAGE_HEADER_SIZE) {
|
||||
return false;
|
||||
}
|
||||
if (!chunk.slice(0, 4).equals(OGGS_HEADER)) {
|
||||
throw Error(`capture_pattern is not ${OGGS_HEADER}`);
|
||||
}
|
||||
if (chunk.readUInt8(4) !== STREAM_STRUCTURE_VERSION) {
|
||||
throw Error(`stream_structure_version is not ${STREAM_STRUCTURE_VERSION}`);
|
||||
}
|
||||
|
||||
if (chunk.length < 27) return false;
|
||||
const pageSegments = chunk.readUInt8(26);
|
||||
if (chunk.length < 27 + pageSegments) return false;
|
||||
const table = chunk.slice(27, 27 + pageSegments);
|
||||
const bitstream = chunk.readUInt32BE(14);
|
||||
|
||||
let sizes = [], totalSize = 0;
|
||||
|
||||
for (let i = 0; i < pageSegments;) {
|
||||
let size = 0, x = 255;
|
||||
while (x === 255) {
|
||||
if (i >= table.length) return false;
|
||||
x = table.readUInt8(i);
|
||||
i++;
|
||||
size += x;
|
||||
}
|
||||
sizes.push(size);
|
||||
totalSize += size;
|
||||
}
|
||||
|
||||
if (chunk.length < 27 + pageSegments + totalSize) return false;
|
||||
|
||||
let start = 27 + pageSegments;
|
||||
for (const size of sizes) {
|
||||
const segment = chunk.slice(start, start + size);
|
||||
const header = segment.slice(0, 8);
|
||||
if (this._head) {
|
||||
if (header.equals(OPUS_TAGS)) this.emit('tags', segment);
|
||||
else if (this._bitstream === bitstream) this.push(segment);
|
||||
} else if (header.equals(OPUS_HEAD)) {
|
||||
this.emit('head', segment);
|
||||
this._head = segment;
|
||||
this._bitstream = bitstream;
|
||||
} else {
|
||||
this.emit('unknownSegment', segment);
|
||||
}
|
||||
start += size;
|
||||
}
|
||||
return chunk.slice(start);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emitted when the demuxer encounters the opus head.
|
||||
* @event OggDemuxer#head
|
||||
* @memberof opus
|
||||
* @param {Buffer} segment a buffer containing the opus head data.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Emitted when the demuxer encounters opus tags.
|
||||
* @event OggDemuxer#tags
|
||||
* @memberof opus
|
||||
* @param {Buffer} segment a buffer containing the opus tags.
|
||||
*/
|
||||
|
||||
module.exports = OggDemuxer;
|
Reference in New Issue
Block a user