UNPKG

mediasoup

Version:

Cutting Edge WebRTC Video Conferencing

332 lines (331 loc) 15.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.serializeRtpParameters = serializeRtpParameters; exports.serializeRtpEncodingParameters = serializeRtpEncodingParameters; exports.serializeParameters = serializeParameters; exports.parseRtcpFeedback = parseRtcpFeedback; exports.parseParameters = parseParameters; exports.parseRtpCodecParameters = parseRtpCodecParameters; exports.rtpHeaderExtensionUriFromFbs = rtpHeaderExtensionUriFromFbs; exports.rtpHeaderExtensionUriToFbs = rtpHeaderExtensionUriToFbs; exports.parseRtpHeaderExtensionParameters = parseRtpHeaderExtensionParameters; exports.parseRtpEncodingParameters = parseRtpEncodingParameters; exports.parseRtpParameters = parseRtpParameters; const fbsUtils = require("./fbsUtils"); const rtp_parameters_1 = require("./fbs/rtp-parameters"); function serializeRtpParameters(builder, rtpParameters) { const codecs = []; const headerExtensions = []; for (const codec of rtpParameters.codecs) { const mimeTypeOffset = builder.createString(codec.mimeType); const parameters = serializeParameters(builder, codec.parameters); const parametersOffset = rtp_parameters_1.RtpCodecParameters.createParametersVector(builder, parameters); const rtcpFeedback = []; for (const rtcp of codec.rtcpFeedback ?? []) { const typeOffset = builder.createString(rtcp.type); const rtcpParametersOffset = builder.createString(rtcp.parameter); rtcpFeedback.push(rtp_parameters_1.RtcpFeedback.createRtcpFeedback(builder, typeOffset, rtcpParametersOffset)); } const rtcpFeedbackOffset = rtp_parameters_1.RtpCodecParameters.createRtcpFeedbackVector(builder, rtcpFeedback); codecs.push(rtp_parameters_1.RtpCodecParameters.createRtpCodecParameters(builder, mimeTypeOffset, codec.payloadType, codec.clockRate, Number(codec.channels), parametersOffset, rtcpFeedbackOffset)); } const codecsOffset = rtp_parameters_1.RtpParameters.createCodecsVector(builder, codecs); // RtpHeaderExtensionParameters. for (const headerExtension of rtpParameters.headerExtensions ?? []) { const uri = rtpHeaderExtensionUriToFbs(headerExtension.uri); const parameters = serializeParameters(builder, headerExtension.parameters); const parametersOffset = rtp_parameters_1.RtpCodecParameters.createParametersVector(builder, parameters); headerExtensions.push(rtp_parameters_1.RtpHeaderExtensionParameters.createRtpHeaderExtensionParameters(builder, uri, headerExtension.id, Boolean(headerExtension.encrypt), parametersOffset)); } const headerExtensionsOffset = rtp_parameters_1.RtpParameters.createHeaderExtensionsVector(builder, headerExtensions); // RtpEncodingParameters. const encodingsOffset = serializeRtpEncodingParameters(builder, rtpParameters.encodings ?? []); // RtcpParameters. const { cname, reducedSize } = rtpParameters.rtcp ?? { reducedSize: true }; const cnameOffset = builder.createString(cname); const rtcpOffset = rtp_parameters_1.RtcpParameters.createRtcpParameters(builder, cnameOffset, Boolean(reducedSize)); const midOffset = builder.createString(rtpParameters.mid); const msidOffset = builder.createString(rtpParameters.msid); rtp_parameters_1.RtpParameters.startRtpParameters(builder); rtp_parameters_1.RtpParameters.addMid(builder, midOffset); rtp_parameters_1.RtpParameters.addCodecs(builder, codecsOffset); rtp_parameters_1.RtpParameters.addHeaderExtensions(builder, headerExtensionsOffset); rtp_parameters_1.RtpParameters.addEncodings(builder, encodingsOffset); rtp_parameters_1.RtpParameters.addRtcp(builder, rtcpOffset); rtp_parameters_1.RtpParameters.addMsid(builder, msidOffset); return rtp_parameters_1.RtpParameters.endRtpParameters(builder); } function serializeRtpEncodingParameters(builder, rtpEncodingParameters = []) { const encodings = []; for (const encoding of rtpEncodingParameters) { // Prepare Rid. const ridOffset = builder.createString(encoding.rid); // Prepare Rtx. let rtxOffset; if (encoding.rtx) { rtxOffset = rtp_parameters_1.Rtx.createRtx(builder, encoding.rtx.ssrc); } // Prepare scalability mode. let scalabilityModeOffset; if (encoding.scalabilityMode) { scalabilityModeOffset = builder.createString(encoding.scalabilityMode); } // Start serialization. rtp_parameters_1.RtpEncodingParameters.startRtpEncodingParameters(builder); // Add SSRC. if (encoding.ssrc) { rtp_parameters_1.RtpEncodingParameters.addSsrc(builder, encoding.ssrc); } // Add Rid. rtp_parameters_1.RtpEncodingParameters.addRid(builder, ridOffset); // Add payload type. if (encoding.codecPayloadType) { rtp_parameters_1.RtpEncodingParameters.addCodecPayloadType(builder, encoding.codecPayloadType); } // Add RTX. if (rtxOffset) { rtp_parameters_1.RtpEncodingParameters.addRtx(builder, rtxOffset); } // Add DTX. if (encoding.dtx !== undefined) { rtp_parameters_1.RtpEncodingParameters.addDtx(builder, encoding.dtx); } // Add scalability ode. if (scalabilityModeOffset) { rtp_parameters_1.RtpEncodingParameters.addScalabilityMode(builder, scalabilityModeOffset); } // Add max bitrate. if (encoding.maxBitrate !== undefined) { rtp_parameters_1.RtpEncodingParameters.addMaxBitrate(builder, encoding.maxBitrate); } // End serialization. encodings.push(rtp_parameters_1.RtpEncodingParameters.endRtpEncodingParameters(builder)); } return rtp_parameters_1.RtpParameters.createEncodingsVector(builder, encodings); } function serializeParameters(builder, parameters) { const fbsParameters = []; for (const key of Object.keys(parameters)) { const value = parameters[key]; const keyOffset = builder.createString(key); let parameterOffset; if (typeof value === 'boolean') { parameterOffset = rtp_parameters_1.Parameter.createParameter(builder, keyOffset, rtp_parameters_1.Value.Boolean, value === true ? 1 : 0); } else if (typeof value === 'number') { // Integer. if (value % 1 === 0) { const valueOffset = rtp_parameters_1.Integer32.createInteger32(builder, value); parameterOffset = rtp_parameters_1.Parameter.createParameter(builder, keyOffset, rtp_parameters_1.Value.Integer32, valueOffset); } // Float. else { const valueOffset = rtp_parameters_1.Double.createDouble(builder, value); parameterOffset = rtp_parameters_1.Parameter.createParameter(builder, keyOffset, rtp_parameters_1.Value.Double, valueOffset); } } else if (typeof value === 'string') { const valueOffset = rtp_parameters_1.String.createString(builder, builder.createString(value)); parameterOffset = rtp_parameters_1.Parameter.createParameter(builder, keyOffset, rtp_parameters_1.Value.String, valueOffset); } else if (Array.isArray(value)) { const valueOffset = rtp_parameters_1.Integer32Array.createValueVector(builder, value); parameterOffset = rtp_parameters_1.Parameter.createParameter(builder, keyOffset, rtp_parameters_1.Value.Integer32Array, valueOffset); } else { throw new Error(`invalid parameter type [key:'${key}', value:${value}]`); } fbsParameters.push(parameterOffset); } return fbsParameters; } function parseRtcpFeedback(data) { return { type: data.type(), parameter: data.parameter() ?? undefined, }; } // eslint-disable-next-line @typescript-eslint/no-explicit-any function parseParameters(data) { const parameters = {}; for (let i = 0; i < data.parametersLength(); i++) { const fbsParameter = data.parameters(i); switch (fbsParameter.valueType()) { case rtp_parameters_1.Value.Boolean: { const value = new rtp_parameters_1.Boolean(); fbsParameter.value(value); parameters[String(fbsParameter.name())] = value.value(); break; } case rtp_parameters_1.Value.Integer32: { const value = new rtp_parameters_1.Integer32(); fbsParameter.value(value); parameters[String(fbsParameter.name())] = value.value(); break; } case rtp_parameters_1.Value.Double: { const value = new rtp_parameters_1.Double(); fbsParameter.value(value); parameters[String(fbsParameter.name())] = value.value(); break; } case rtp_parameters_1.Value.String: { const value = new rtp_parameters_1.String(); fbsParameter.value(value); parameters[String(fbsParameter.name())] = value.value(); break; } case rtp_parameters_1.Value.Integer32Array: { const value = new rtp_parameters_1.Integer32Array(); fbsParameter.value(value); parameters[String(fbsParameter.name())] = value.valueArray(); break; } } } return parameters; } function parseRtpCodecParameters(data) { const parameters = parseParameters(data); let rtcpFeedback = []; if (data.rtcpFeedbackLength() > 0) { rtcpFeedback = fbsUtils.parseVector(data, 'rtcpFeedback', parseRtcpFeedback); } return { mimeType: data.mimeType(), payloadType: data.payloadType(), clockRate: data.clockRate(), channels: data.channels() ?? undefined, parameters, rtcpFeedback, }; } function rtpHeaderExtensionUriFromFbs(uri) { switch (uri) { case rtp_parameters_1.RtpHeaderExtensionUri.Mid: { return 'urn:ietf:params:rtp-hdrext:sdes:mid'; } case rtp_parameters_1.RtpHeaderExtensionUri.RtpStreamId: { return 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id'; } case rtp_parameters_1.RtpHeaderExtensionUri.RepairRtpStreamId: { return 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id'; } case rtp_parameters_1.RtpHeaderExtensionUri.AbsSendTime: { return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time'; } case rtp_parameters_1.RtpHeaderExtensionUri.TransportWideCcDraft01: { return 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01'; } case rtp_parameters_1.RtpHeaderExtensionUri.SsrcAudioLevel: { return 'urn:ietf:params:rtp-hdrext:ssrc-audio-level'; } case rtp_parameters_1.RtpHeaderExtensionUri.DependencyDescriptor: { return 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension'; } case rtp_parameters_1.RtpHeaderExtensionUri.VideoOrientation: { return 'urn:3gpp:video-orientation'; } case rtp_parameters_1.RtpHeaderExtensionUri.TimeOffset: { return 'urn:ietf:params:rtp-hdrext:toffset'; } case rtp_parameters_1.RtpHeaderExtensionUri.AbsCaptureTime: { return 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time'; } case rtp_parameters_1.RtpHeaderExtensionUri.PlayoutDelay: { return 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay'; } case rtp_parameters_1.RtpHeaderExtensionUri.MediasoupPacketId: { return 'urn:mediasoup:params:rtp-hdrext:packet-id'; } } } function rtpHeaderExtensionUriToFbs(uri) { switch (uri) { case 'urn:ietf:params:rtp-hdrext:sdes:mid': { return rtp_parameters_1.RtpHeaderExtensionUri.Mid; } case 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id': { return rtp_parameters_1.RtpHeaderExtensionUri.RtpStreamId; } case 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id': { return rtp_parameters_1.RtpHeaderExtensionUri.RepairRtpStreamId; } case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time': { return rtp_parameters_1.RtpHeaderExtensionUri.AbsSendTime; } case 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01': { return rtp_parameters_1.RtpHeaderExtensionUri.TransportWideCcDraft01; } case 'urn:ietf:params:rtp-hdrext:ssrc-audio-level': { return rtp_parameters_1.RtpHeaderExtensionUri.SsrcAudioLevel; } case 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension': { return rtp_parameters_1.RtpHeaderExtensionUri.DependencyDescriptor; } case 'urn:3gpp:video-orientation': { return rtp_parameters_1.RtpHeaderExtensionUri.VideoOrientation; } case 'urn:ietf:params:rtp-hdrext:toffset': { return rtp_parameters_1.RtpHeaderExtensionUri.TimeOffset; } case 'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time': { return rtp_parameters_1.RtpHeaderExtensionUri.AbsCaptureTime; } case 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay': { return rtp_parameters_1.RtpHeaderExtensionUri.PlayoutDelay; } case 'urn:mediasoup:params:rtp-hdrext:packet-id': { return rtp_parameters_1.RtpHeaderExtensionUri.MediasoupPacketId; } default: { throw new TypeError(`invalid RtpHeaderExtensionUri: ${uri}`); } } } function parseRtpHeaderExtensionParameters(data) { return { uri: rtpHeaderExtensionUriFromFbs(data.uri()), id: data.id(), encrypt: data.encrypt(), parameters: parseParameters(data), }; } function parseRtpEncodingParameters(data) { return { ssrc: data.ssrc() ?? undefined, rid: data.rid() || undefined, codecPayloadType: data.codecPayloadType() !== null ? data.codecPayloadType() : undefined, rtx: data.rtx() ? { ssrc: data.rtx().ssrc() } : undefined, dtx: data.dtx(), scalabilityMode: data.scalabilityMode() || undefined, maxBitrate: data.maxBitrate() !== null ? data.maxBitrate() : undefined, }; } function parseRtpParameters(data) { const codecs = fbsUtils.parseVector(data, 'codecs', parseRtpCodecParameters); let headerExtensions = []; if (data.headerExtensionsLength() > 0) { headerExtensions = fbsUtils.parseVector(data, 'headerExtensions', parseRtpHeaderExtensionParameters); } let encodings = []; if (data.encodingsLength() > 0) { encodings = fbsUtils.parseVector(data, 'encodings', parseRtpEncodingParameters); } let rtcp; if (data.rtcp()) { const fbsRtcp = data.rtcp(); rtcp = { cname: fbsRtcp.cname() || undefined, reducedSize: fbsRtcp.reducedSize(), }; } return { mid: data.mid() || undefined, codecs, headerExtensions, encodings, rtcp, msid: data.msid() || undefined, }; }