UNPKG

ebml-stream

Version:
97 lines (96 loc) 3.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = require("stream"); const tools_1 = require("./tools"); const EbmlElementType_1 = require("./models/enums/EbmlElementType"); const EbmlTagPosition_1 = require("./models/enums/EbmlTagPosition"); const EbmlTagFactory_1 = require("./models/EbmlTagFactory"); class EbmlStreamDecoderOptions { constructor() { this.bufferTagIds = []; } } exports.EbmlStreamDecoderOptions = EbmlStreamDecoderOptions; class EbmlStreamDecoder extends stream_1.Transform { constructor(options = {}) { super(Object.assign({}, options, { readableObjectMode: true })); this._currentBufferOffset = 0; this._tagStack = []; this._buffer = Buffer.alloc(0); this._bufferTagIds = []; this._bufferTagIds = options.bufferTagIds || []; } get buffer() { return this._buffer; } _transform(chunk, enc, done) { this._buffer = Buffer.concat([this._buffer, Buffer.from(chunk)]); while (this.parseTags()) ; done(); } parseTags() { const currentTag = this.readTagHeader(this._buffer); if (!currentTag) { return false; } if (currentTag.type === EbmlElementType_1.EbmlElementType.Master && !this._bufferTagIds.some(i => i === currentTag.id)) { this._tagStack.push(currentTag); this.emitTag(currentTag, EbmlTagPosition_1.EbmlTagPosition.Start); this.advanceBuffer(currentTag.tagHeaderLength); return true; } else { if (this._buffer.length < currentTag.tagHeaderLength + currentTag.size) { return false; } const data = this._buffer.slice(currentTag.tagHeaderLength, currentTag.tagHeaderLength + currentTag.size); this.emitTag(currentTag, EbmlTagPosition_1.EbmlTagPosition.Content, data); this.advanceBuffer(currentTag.tagHeaderLength + currentTag.size); while (this._tagStack.length > 0) { const nextTag = this._tagStack[this._tagStack.length - 1]; if (this._currentBufferOffset < (nextTag.absoluteStart + nextTag.tagHeaderLength + nextTag.size)) { break; } this.emitTag(nextTag, EbmlTagPosition_1.EbmlTagPosition.End); this._tagStack.pop(); } } return true; } advanceBuffer(length) { this._currentBufferOffset += length; this._buffer = this._buffer.slice(length); } readTagHeader(buffer, offset = 0) { if (buffer.length == 0) { return null; } const tag = tools_1.Tools.readVint(buffer, offset); if (tag == null) { return null; } const size = tools_1.Tools.readVint(buffer, offset + tag.length); if (size == null) { return null; } const tagIdHex = tools_1.Tools.readHexString(buffer, offset, offset + tag.length); const tagId = Number.parseInt(tagIdHex, 16); let tagObject = EbmlTagFactory_1.EbmlTagFactory.create(tagId); tagObject.size = size.value; return Object.assign(tagObject, { absoluteStart: this._currentBufferOffset + offset, tagHeaderLength: tag.length + size.length }); } emitTag(tag, position, data) { let emittedTag = EbmlTagFactory_1.EbmlTagFactory.create(tag.id); emittedTag.size = tag.size; emittedTag.position = position; if (position === EbmlTagPosition_1.EbmlTagPosition.Content) { emittedTag.parseContent(data); } this.push(emittedTag); } } exports.EbmlStreamDecoder = EbmlStreamDecoder;