UNPKG

rtp.js

Version:

RTP stack for Node.js and browser written in TypeScript

122 lines (121 loc) 5.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Serializable = void 0; const helpers_1 = require("../utils/helpers"); /** * Class holding a serializable buffer view. All RTP and RTCP packets inherit * from this class, and also items in some RTCP packets. */ class Serializable { // Buffer view holding the packet or item content. // @ts-expect-error --- 'view' has not initializer and is not assigned in // constructor. view; // Whether serialization is needed due to recent modifications. #serializationNeeded = false; constructor(view) { if (view) { this.view = view; } } /** * Serializable dump. */ dump() { return { byteLength: this.getByteLength(), }; } /** * Get a buffer view containing the serialized content of the packet or item. * * @param serializationBuffer - Buffer in which the content will be serialized * in case serialization is needed. If not given, a new one will internally * allocated. * @param serializationByteOffset - Byte offset of the given `serializationBuffer` * where serialization (if needed) will start. * * @remarks * - The internal buffer is serialized if needed (to apply pending * modifications) by internally calling {@link serialize}. * * @throws * - If buffer serialization is needed and it fails due to invalid * content. */ getView(serializationBuffer, serializationByteOffset) { if (this.needsSerialization()) { this.serialize(serializationBuffer, serializationByteOffset); } return this.view; } /** * Whether serialization is needed, meaning that the current buffer view * doesn't represent the current content of the packet or item (due to * modifications not applied yet). Calling {@link serialize} or {@link getView} * will serialize the packet or the item. */ needsSerialization() { return this.#serializationNeeded; } setSerializationNeeded(flag) { this.#serializationNeeded = flag; } /** * This method returns a buffer (plus byte offset) for the child to serialize. * If a buffer (and optionally a byte offset) is given, this method will verify * whether the serialized content can fit into it and will throw otherwise. */ getSerializationBuffer(buffer, byteOffset = 0) { const byteLength = this.getByteLength(); if (buffer) { if (buffer.byteLength - byteOffset < byteLength) { throw new RangeError(`given buffer available space (${buffer.byteLength - byteOffset} bytes) is less than length required for serialization (${byteLength} bytes)`); } // If the given buffer is the same as the one internally used by the view // of this packet, we must assert that the new serialization would not // happen in bytes where the packet currently exists. // Here we must take into account the given byte offset and the byte // offset of the view, the current packet length and the expected packet // length after the serialization. if (buffer === this.view.buffer && ((byteOffset >= this.view.byteOffset && byteOffset <= this.view.byteOffset + this.view.byteLength - 1) || (byteOffset + byteLength - 1 >= this.view.byteOffset && byteOffset + byteLength <= this.view.byteOffset + this.view.byteLength - 1))) { throw new RangeError('given buffer is the same as the internal buffer of the packet and given byteLength would make serialization override existing packet data'); } const uint8Array = new Uint8Array(buffer, byteOffset, byteLength); // If a buffer is given, ensure the required length is filled with zeroes. uint8Array.fill(0); } else { // The buffer is guaranteed to be filled with zeros. buffer = new ArrayBuffer(byteLength); } return { buffer, byteOffset, byteLength }; } cloneInternal(buffer, byteOffset = 0, serializationBuffer, serializationByteOffset) { if (this.needsSerialization()) { this.serialize(serializationBuffer, serializationByteOffset); } let view; // If buffer is given, let's check whether it holds enough space for the // content. if (buffer) { if (buffer.byteLength - byteOffset < this.view.byteLength) { throw new RangeError(`given buffer available space (${buffer.byteLength - byteOffset} bytes) is less than length required for clonation (${this.view.byteLength} bytes)`); } // Copy the content into the given buffer. const uint8Array = new Uint8Array(buffer, byteOffset, this.view.byteLength); uint8Array.set(new Uint8Array(this.view.buffer, this.view.byteOffset, this.view.byteLength), 0); view = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength); } else { view = (0, helpers_1.clone)(this.view); } return view; } } exports.Serializable = Serializable;