UNPKG

rtp.js

Version:

RTP stack for Node.js and browser written in TypeScript

226 lines (225 loc) 7.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FeedbackPacket = exports.PsFeedbackMessageType = exports.RtpFeedbackMessageType = exports.FIXED_HEADER_LENGTH = void 0; exports.getRtcpFeedbackMessageType = getRtcpFeedbackMessageType; const RtcpPacket_1 = require("./RtcpPacket"); const helpers_1 = require("../../utils/helpers"); const bitOps_1 = require("../../utils/bitOps"); // Common RTCP header length + 4 (SSRC of packet sender) + 4 (SSRC of media // source). exports.FIXED_HEADER_LENGTH = RtcpPacket_1.COMMON_HEADER_LENGTH + 8; /** * RTCP Feedback transport layer message types. * * @category RTCP */ var RtpFeedbackMessageType; (function (RtpFeedbackMessageType) { /** * Generic NACK. */ RtpFeedbackMessageType[RtpFeedbackMessageType["NACK"] = 1] = "NACK"; /** * Rapid Resynchronisation Request. */ RtpFeedbackMessageType[RtpFeedbackMessageType["SR_REQ"] = 5] = "SR_REQ"; /** * Explicit Congestion Notification (ECN). */ RtpFeedbackMessageType[RtpFeedbackMessageType["ECN"] = 8] = "ECN"; })(RtpFeedbackMessageType || (exports.RtpFeedbackMessageType = RtpFeedbackMessageType = {})); /** * RTCP Feedback payload specific message types. * * @category RTCP */ var PsFeedbackMessageType; (function (PsFeedbackMessageType) { /** * Picture Loss Indication. */ PsFeedbackMessageType[PsFeedbackMessageType["PLI"] = 1] = "PLI"; /** * Slice Loss Indication. */ PsFeedbackMessageType[PsFeedbackMessageType["SLI"] = 2] = "SLI"; /** * Reference Picture Selection Indication. */ PsFeedbackMessageType[PsFeedbackMessageType["RPSI"] = 3] = "RPSI"; /** * Application layer FB message. */ PsFeedbackMessageType[PsFeedbackMessageType["AFB"] = 15] = "AFB"; })(PsFeedbackMessageType || (exports.PsFeedbackMessageType = PsFeedbackMessageType = {})); /** * Get the RTCP Feedback message type. * * @hidden */ function getRtcpFeedbackMessageType(view) { return (0, bitOps_1.readBitsInDataView)({ view, pos: 0, mask: 0b00011111 }); } function messageTypeToString(packetType, messageType) { switch (packetType) { case RtcpPacket_1.RtcpPacketType.RTPFB: { messageType = messageType; switch (messageType) { case RtpFeedbackMessageType.NACK: { return 'Generic NACK'; } case RtpFeedbackMessageType.SR_REQ: { return 'Rapid Resynchronisation Request'; } case RtpFeedbackMessageType.ECN: { return 'Explicit Congestion Notification (ECN)'; } default: { (0, helpers_1.assertUnreachable)(messageType); } } // @ts-expect-error --- Ignore "error TS7027: Unreachable code detected" // to not conflict with ESLint rules. break; } case RtcpPacket_1.RtcpPacketType.PSFB: { messageType = messageType; switch (messageType) { case PsFeedbackMessageType.PLI: { return 'Picture Loss Indication'; } case PsFeedbackMessageType.SLI: { return 'Slice Loss Indication'; } case PsFeedbackMessageType.RPSI: { return 'Reference Picture Selection Indication'; } case PsFeedbackMessageType.AFB: { return 'Application layer FB message'; } default: { (0, helpers_1.assertUnreachable)(messageType); } } // @ts-expect-error --- Ignore "error TS7027: Unreachable code detected" // to not conflict with ESLint rules. break; } default: { (0, helpers_1.assertUnreachable)(packetType); } } } /** * RTCP Feedback packet. * * ```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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |V=2|P| FMT | PT | length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SSRC of packet sender | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SSRC of media source | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * : Feedback Control Information (FCI) : * : : * ``` * * @category RTCP * * @see * - [RFC 4585 section 6.1](https://datatracker.ietf.org/doc/html/rfc4585#section-6.1) */ class FeedbackPacket extends RtcpPacket_1.RtcpPacket { // RTCP Feedback message type. #messageType; constructor(packetType, messageType, view) { super(packetType, view); this.#messageType = messageType; if (this.view) { if (this.getMessageType() !== this.#messageType) { throw new TypeError(`given buffer view is not a RTCP ${(0, RtcpPacket_1.packetTypeToString)(this.getPacketType())} packet with ${messageTypeToString(packetType, this.#messageType)} message type`); } } } /** * Base RTCP Feedback packet dump. * * @remarks * - Read the info dump type of each RTCP Feedback packet instead. */ dump() { return { ...super.dump(), messageType: this.getMessageType(), senderSsrc: this.getSenderSsrc(), mediaSsrc: this.getMediaSsrc(), }; } /** * Get the RTCP Feedback message type. */ getMessageType() { return (0, bitOps_1.readBitsInDataView)({ view: this.view, pos: 0, mask: 0b00011111 }); } /** * Get sender SSRC. */ getSenderSsrc() { return this.view.getUint32(4); } /** * Set sender SSRC. */ setSenderSsrc(ssrc) { this.view.setUint32(4, ssrc); } /** * Get media SSRC. */ getMediaSsrc() { return this.view.getUint32(8); } /** * Set media SSRC. */ setMediaSsrc(ssrc) { this.view.setUint32(8, ssrc); } writeFixedHeader() { super.writeCommonHeader(); this.setMessageType(); } /** * Serialize base RTCP Feedback packet into a new buffer. */ serializeBase(buffer, byteOffset) { const view = super.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 += RtcpPacket_1.COMMON_HEADER_LENGTH; // Copy the rest of the fixed header into the new buffer. uint8Array.set(new Uint8Array(this.view.buffer, this.view.byteOffset + pos, exports.FIXED_HEADER_LENGTH - RtcpPacket_1.COMMON_HEADER_LENGTH), pos); return view; } /** * Set the RTCP Feedback message type. * * @privateRemarks * - This method is not public since users should not manipulate this field * directly. */ setMessageType() { (0, bitOps_1.writeBitsInDataView)({ view: this.view, pos: 0, mask: 0b00011111, value: this.#messageType, }); } } exports.FeedbackPacket = FeedbackPacket;