UNPKG

rtp.js

Version:

RTP stack for Node.js and browser written in TypeScript

138 lines (137 loc) 4.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DlrrExtendedReport = void 0; const ExtendedReport_1 = require("./ExtendedReport"); /** * DLRR Extended Report. * * ```text * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | BT=5 | reserved | block length | * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * | SSRC_1 (SSRC of first receiver) | sub- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block * | last RR (LRR) | 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | delay since last RR (DLRR) | * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * | SSRC_2 (SSRC of second receiver) | sub- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block * : ... : 2 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * ``` * * @category RTCP Extended Reports * * @see * - [RFC 3611 section 4.5](https://datatracker.ietf.org/doc/html/rfc3611#section-4.5) */ class DlrrExtendedReport extends ExtendedReport_1.ExtendedReport { // Sub-reports. #subReports = []; /** * @param view - If given it will be parsed. Otherwise an empty DLRR Extended * Report will be created. */ constructor(view) { super(ExtendedReport_1.ExtendedReportType.DLRR, view); if (!this.view) { this.view = new DataView(new ArrayBuffer(ExtendedReport_1.COMMON_HEADER_LENGTH)); // Write report type. this.writeCommonHeader(); return; } if (this.view.byteLength < ExtendedReport_1.COMMON_HEADER_LENGTH) { throw new TypeError('wrong byte length for a DLRR Extended Report'); } // Position relative to the DataView byte offset. let pos = 0; // Move to sub-reports. pos += ExtendedReport_1.COMMON_HEADER_LENGTH; while (pos < this.view.byteLength) { const ssrc = this.view.getUint32(pos); pos += 4; const lrr = this.view.getUint32(pos); pos += 4; const dlrr = this.view.getUint32(pos); pos += 4; this.#subReports.push({ ssrc, lrr, dlrr }); } } /** * Dump DLRR Extended Report info. */ dump() { return { ...super.dump(), subReports: this.getSubReports(), }; } /** * @inheritDoc */ getByteLength() { if (!this.needsSerialization()) { return this.view.byteLength; } let reportLength = ExtendedReport_1.COMMON_HEADER_LENGTH; // Add sub-reports. reportLength += this.#subReports.length * 12; return reportLength; } /** * @inheritDoc */ serialize(buffer, byteOffset) { const view = this.serializeBase(buffer, byteOffset); // Position relative to the DataView byte offset. let pos = 0; // Move to sub-reports. pos += ExtendedReport_1.COMMON_HEADER_LENGTH; // Copy sub-reports. for (const { ssrc, lrr, dlrr } of this.#subReports) { view.setUint32(pos, ssrc); pos += 4; view.setUint32(pos, lrr); pos += 4; view.setUint32(pos, dlrr); pos += 4; } if (pos !== view.byteLength) { throw new RangeError(`filled length (${pos} bytes) does not match the available buffer size (${view.byteLength} bytes)`); } // Update DataView. this.view = view; this.setSerializationNeeded(false); } /** * @inheritDoc */ clone(buffer, byteOffset, serializationBuffer, serializationByteOffset) { const view = this.cloneInternal(buffer, byteOffset, serializationBuffer, serializationByteOffset); return new DlrrExtendedReport(view); } /** * Get sub-reports. */ getSubReports() { return Array.from(this.#subReports); } /** * Set sub-reports. */ setSubReports(subReports) { this.#subReports = Array.from(subReports); this.setSerializationNeeded(true); } /** * Add sub-report. */ addSubReport(subReport) { this.#subReports.push(subReport); this.setSerializationNeeded(true); } } exports.DlrrExtendedReport = DlrrExtendedReport;