UNPKG

rtp.js

Version:

RTP stack for Node.js and browser written in TypeScript

211 lines (210 loc) 7.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PrtExtendedReport = void 0; const ExtendedReport_1 = require("./ExtendedReport"); const bitOps_1 = require("../../../utils/bitOps"); // Common header + SSRC of source + begin seq + end seq. const PRT_EXTENDED_REPORT_MIN_LENGTH = ExtendedReport_1.COMMON_HEADER_LENGTH + 8; /** * Packet Receipt Times 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=3 | rsvd. | T | block length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SSRC of source | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | begin_seq | end_seq | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Receipt time of packet begin_seq | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Receipt time of packet (begin_seq + 1) mod 65536 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * : ... : * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Receipt time of packet (end_seq - 1) mod 65536 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ``` * * @category RTCP Extended Reports * * @see * - [RFC 3611 section 4.3](https://datatracker.ietf.org/doc/html/rfc3611#section-4.3) */ class PrtExtendedReport extends ExtendedReport_1.ExtendedReport { // Receipt times (4 bytes numbers, unparsed). #receiptTimes = []; /** * @param view - If given it will be parsed. Otherwise an empty Packet Receipt * Times Extended Report will be created. */ constructor(view) { super(ExtendedReport_1.ExtendedReportType.PRT, view); if (!this.view) { this.view = new DataView(new ArrayBuffer(PRT_EXTENDED_REPORT_MIN_LENGTH)); // Write report type. this.writeCommonHeader(); return; } if (this.view.byteLength < PRT_EXTENDED_REPORT_MIN_LENGTH) { throw new TypeError('wrong byte length for a Packet Receipt Times Extended Report'); } // Position relative to the DataView byte offset. let pos = 0; // Move to receipt times. pos += PRT_EXTENDED_REPORT_MIN_LENGTH; while (pos < this.view.byteLength) { const receiptTime = this.view.getUint32(pos); this.#receiptTimes.push(receiptTime); pos += 4; } } /** * Dump Packet Receipt Times Extended Report info. */ dump() { return { ...super.dump(), thinning: this.getThinning(), ssrc: this.getSsrc(), beginSeq: this.getBeginSeq(), endSeq: this.getEndSeq(), receiptTimes: this.getReceiptTimes(), }; } /** * @inheritDoc */ getByteLength() { if (!this.needsSerialization()) { return this.view.byteLength; } // Common header + SSRC + begin seq + end seq. let reportLength = PRT_EXTENDED_REPORT_MIN_LENGTH; // Add receipt times. reportLength += this.#receiptTimes.length * 4; return reportLength; } /** * @inheritDoc */ serialize(buffer, byteOffset) { const view = this.serializeBase(buffer, byteOffset); const uint8Array = new Uint8Array(view.buffer, view.byteOffset, view.byteLength); // Position relative to the DataView byte offset. let pos = 0; // Move to the fixed header fields after the common header. pos += ExtendedReport_1.COMMON_HEADER_LENGTH; // Copy the rest of the fixed fields into the new buffer. uint8Array.set(new Uint8Array(this.view.buffer, this.view.byteOffset + pos, PRT_EXTENDED_REPORT_MIN_LENGTH - ExtendedReport_1.COMMON_HEADER_LENGTH), pos); // Move to receipt times. pos += PRT_EXTENDED_REPORT_MIN_LENGTH - ExtendedReport_1.COMMON_HEADER_LENGTH; // Copy receipt times. for (const receiptTime of this.#receiptTimes) { view.setUint32(pos, receiptTime); 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 PrtExtendedReport(view); } /** * Get thinning. */ getThinning() { return (0, bitOps_1.readBitsInDataView)({ view: this.view, pos: 1, mask: 0x0f }); } /** * Set thinning. */ setThinning(thinning) { (0, bitOps_1.writeBitsInDataView)({ view: this.view, pos: 1, mask: 0x0f, value: thinning, }); this.setSerializationNeeded(true); } /** * Get SSRC of source. */ getSsrc() { return this.view.getUint32(4); } /** * Set SSRC of source. */ setSsrc(ssrc) { this.view.setUint32(4, ssrc); this.setSerializationNeeded(true); } /** * Get begin sequence number. */ getBeginSeq() { return this.view.getUint16(8); } /** * Set begin sequence number. */ setBeginSeq(seq) { this.view.setUint16(8, seq); this.setSerializationNeeded(true); } /** * Get end sequence number. */ getEndSeq() { return this.view.getUint16(10); } /** * Set end sequence number. */ setEndSeq(seq) { this.view.setUint16(10, seq); this.setSerializationNeeded(true); } /** * Get receipt times. * * @remarks * - Receipt times are given as a list of 4 byte integers. */ getReceiptTimes() { return Array.from(this.#receiptTimes); } /** * Set receipt times. * * @remarks * - Receipt times must be given as a list of 4 byte integers. */ setReceiptTimes(receiptTimes) { this.#receiptTimes = Array.from(receiptTimes); this.setSerializationNeeded(true); } /** * Add receipt time. * * @remarks * - Receipt time must be given as 4 byte integer. */ addReceiptTime(receiptTime) { this.#receiptTimes.push(receiptTime); this.setSerializationNeeded(true); } } exports.PrtExtendedReport = PrtExtendedReport;