[mirotalksfu] - update dep
هذا الالتزام موجود في:
@@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h
|
||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||
* @version 1.3.71
|
||||
* @version 1.3.72
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||
* @version 1.3.71
|
||||
* @version 1.3.72
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -11562,7 +11562,9 @@
|
||||
// RTP (1).
|
||||
candidateObject.component = 1;
|
||||
candidateObject.foundation = candidate.foundation;
|
||||
candidateObject.ip = candidate.ip;
|
||||
// Be ready for new candidate.address field in mediasoup server side
|
||||
// field and keep backward compatibility with deprecated candidate.ip.
|
||||
candidateObject.ip = candidate.address ?? candidate.ip;
|
||||
candidateObject.port = candidate.port;
|
||||
candidateObject.priority = candidate.priority;
|
||||
candidateObject.transport = candidate.protocol;
|
||||
@@ -13095,7 +13097,7 @@
|
||||
/**
|
||||
* Expose mediasoup-client version.
|
||||
*/
|
||||
exports.version = '3.7.2';
|
||||
exports.version = '3.7.4';
|
||||
/**
|
||||
* Expose parseScalabilityMode() function.
|
||||
*/
|
||||
@@ -13162,18 +13164,9 @@
|
||||
exports.getSendingRtpParameters =
|
||||
exports.getRecvRtpCapabilities =
|
||||
exports.getExtendedRtpCapabilities =
|
||||
exports.validateSctpStreamParameters =
|
||||
exports.validateSctpParameters =
|
||||
exports.validateNumSctpStreams =
|
||||
exports.validateSctpCapabilities =
|
||||
exports.validateRtcpParameters =
|
||||
exports.validateRtpEncodingParameters =
|
||||
exports.validateRtpHeaderExtensionParameters =
|
||||
exports.validateRtpCodecParameters =
|
||||
exports.validateSctpStreamParameters =
|
||||
exports.validateRtpParameters =
|
||||
exports.validateRtpHeaderExtension =
|
||||
exports.validateRtcpFeedback =
|
||||
exports.validateRtpCodecCapability =
|
||||
exports.validateRtpCapabilities =
|
||||
void 0;
|
||||
const h264 = __importStar(require('h264-profile-level-id'));
|
||||
@@ -13210,125 +13203,6 @@
|
||||
}
|
||||
}
|
||||
exports.validateRtpCapabilities = validateRtpCapabilities;
|
||||
/**
|
||||
* Validates RtpCodecCapability. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpCodecCapability(codec) {
|
||||
const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i');
|
||||
if (typeof codec !== 'object') {
|
||||
throw new TypeError('codec is not an object');
|
||||
}
|
||||
// mimeType is mandatory.
|
||||
if (!codec.mimeType || typeof codec.mimeType !== 'string') {
|
||||
throw new TypeError('missing codec.mimeType');
|
||||
}
|
||||
const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType);
|
||||
if (!mimeTypeMatch) {
|
||||
throw new TypeError('invalid codec.mimeType');
|
||||
}
|
||||
// Just override kind with media component of mimeType.
|
||||
codec.kind = mimeTypeMatch[1].toLowerCase();
|
||||
// preferredPayloadType is optional.
|
||||
if (codec.preferredPayloadType && typeof codec.preferredPayloadType !== 'number') {
|
||||
throw new TypeError('invalid codec.preferredPayloadType');
|
||||
}
|
||||
// clockRate is mandatory.
|
||||
if (typeof codec.clockRate !== 'number') {
|
||||
throw new TypeError('missing codec.clockRate');
|
||||
}
|
||||
// channels is optional. If unset, set it to 1 (just if audio).
|
||||
if (codec.kind === 'audio') {
|
||||
if (typeof codec.channels !== 'number') {
|
||||
codec.channels = 1;
|
||||
}
|
||||
} else {
|
||||
delete codec.channels;
|
||||
}
|
||||
// parameters is optional. If unset, set it to an empty object.
|
||||
if (!codec.parameters || typeof codec.parameters !== 'object') {
|
||||
codec.parameters = {};
|
||||
}
|
||||
for (const key of Object.keys(codec.parameters)) {
|
||||
let value = codec.parameters[key];
|
||||
if (value === undefined) {
|
||||
codec.parameters[key] = '';
|
||||
value = '';
|
||||
}
|
||||
if (typeof value !== 'string' && typeof value !== 'number') {
|
||||
throw new TypeError(`invalid codec parameter [key:${key}s, value:${value}]`);
|
||||
}
|
||||
// Specific parameters validation.
|
||||
if (key === 'apt') {
|
||||
if (typeof value !== 'number') {
|
||||
throw new TypeError('invalid codec apt parameter');
|
||||
}
|
||||
}
|
||||
}
|
||||
// rtcpFeedback is optional. If unset, set it to an empty array.
|
||||
if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) {
|
||||
codec.rtcpFeedback = [];
|
||||
}
|
||||
for (const fb of codec.rtcpFeedback) {
|
||||
validateRtcpFeedback(fb);
|
||||
}
|
||||
}
|
||||
exports.validateRtpCodecCapability = validateRtpCodecCapability;
|
||||
/**
|
||||
* Validates RtcpFeedback. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtcpFeedback(fb) {
|
||||
if (typeof fb !== 'object') {
|
||||
throw new TypeError('fb is not an object');
|
||||
}
|
||||
// type is mandatory.
|
||||
if (!fb.type || typeof fb.type !== 'string') {
|
||||
throw new TypeError('missing fb.type');
|
||||
}
|
||||
// parameter is optional. If unset set it to an empty string.
|
||||
if (!fb.parameter || typeof fb.parameter !== 'string') {
|
||||
fb.parameter = '';
|
||||
}
|
||||
}
|
||||
exports.validateRtcpFeedback = validateRtcpFeedback;
|
||||
/**
|
||||
* Validates RtpHeaderExtension. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpHeaderExtension(ext) {
|
||||
if (typeof ext !== 'object') {
|
||||
throw new TypeError('ext is not an object');
|
||||
}
|
||||
// kind is mandatory.
|
||||
if (ext.kind !== 'audio' && ext.kind !== 'video') {
|
||||
throw new TypeError('invalid ext.kind');
|
||||
}
|
||||
// uri is mandatory.
|
||||
if (!ext.uri || typeof ext.uri !== 'string') {
|
||||
throw new TypeError('missing ext.uri');
|
||||
}
|
||||
// preferredId is mandatory.
|
||||
if (typeof ext.preferredId !== 'number') {
|
||||
throw new TypeError('missing ext.preferredId');
|
||||
}
|
||||
// preferredEncrypt is optional. If unset set it to false.
|
||||
if (ext.preferredEncrypt && typeof ext.preferredEncrypt !== 'boolean') {
|
||||
throw new TypeError('invalid ext.preferredEncrypt');
|
||||
} else if (!ext.preferredEncrypt) {
|
||||
ext.preferredEncrypt = false;
|
||||
}
|
||||
// direction is optional. If unset set it to sendrecv.
|
||||
if (ext.direction && typeof ext.direction !== 'string') {
|
||||
throw new TypeError('invalid ext.direction');
|
||||
} else if (!ext.direction) {
|
||||
ext.direction = 'sendrecv';
|
||||
}
|
||||
}
|
||||
exports.validateRtpHeaderExtension = validateRtpHeaderExtension;
|
||||
/**
|
||||
* Validates RtpParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
@@ -13376,226 +13250,6 @@
|
||||
validateRtcpParameters(params.rtcp);
|
||||
}
|
||||
exports.validateRtpParameters = validateRtpParameters;
|
||||
/**
|
||||
* Validates RtpCodecParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpCodecParameters(codec) {
|
||||
const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i');
|
||||
if (typeof codec !== 'object') {
|
||||
throw new TypeError('codec is not an object');
|
||||
}
|
||||
// mimeType is mandatory.
|
||||
if (!codec.mimeType || typeof codec.mimeType !== 'string') {
|
||||
throw new TypeError('missing codec.mimeType');
|
||||
}
|
||||
const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType);
|
||||
if (!mimeTypeMatch) {
|
||||
throw new TypeError('invalid codec.mimeType');
|
||||
}
|
||||
// payloadType is mandatory.
|
||||
if (typeof codec.payloadType !== 'number') {
|
||||
throw new TypeError('missing codec.payloadType');
|
||||
}
|
||||
// clockRate is mandatory.
|
||||
if (typeof codec.clockRate !== 'number') {
|
||||
throw new TypeError('missing codec.clockRate');
|
||||
}
|
||||
const kind = mimeTypeMatch[1].toLowerCase();
|
||||
// channels is optional. If unset, set it to 1 (just if audio).
|
||||
if (kind === 'audio') {
|
||||
if (typeof codec.channels !== 'number') {
|
||||
codec.channels = 1;
|
||||
}
|
||||
} else {
|
||||
delete codec.channels;
|
||||
}
|
||||
// parameters is optional. If unset, set it to an empty object.
|
||||
if (!codec.parameters || typeof codec.parameters !== 'object') {
|
||||
codec.parameters = {};
|
||||
}
|
||||
for (const key of Object.keys(codec.parameters)) {
|
||||
let value = codec.parameters[key];
|
||||
if (value === undefined) {
|
||||
codec.parameters[key] = '';
|
||||
value = '';
|
||||
}
|
||||
if (typeof value !== 'string' && typeof value !== 'number') {
|
||||
throw new TypeError(`invalid codec parameter [key:${key}s, value:${value}]`);
|
||||
}
|
||||
// Specific parameters validation.
|
||||
if (key === 'apt') {
|
||||
if (typeof value !== 'number') {
|
||||
throw new TypeError('invalid codec apt parameter');
|
||||
}
|
||||
}
|
||||
}
|
||||
// rtcpFeedback is optional. If unset, set it to an empty array.
|
||||
if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) {
|
||||
codec.rtcpFeedback = [];
|
||||
}
|
||||
for (const fb of codec.rtcpFeedback) {
|
||||
validateRtcpFeedback(fb);
|
||||
}
|
||||
}
|
||||
exports.validateRtpCodecParameters = validateRtpCodecParameters;
|
||||
/**
|
||||
* Validates RtpHeaderExtensionParameteters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpHeaderExtensionParameters(ext) {
|
||||
if (typeof ext !== 'object') {
|
||||
throw new TypeError('ext is not an object');
|
||||
}
|
||||
// uri is mandatory.
|
||||
if (!ext.uri || typeof ext.uri !== 'string') {
|
||||
throw new TypeError('missing ext.uri');
|
||||
}
|
||||
// id is mandatory.
|
||||
if (typeof ext.id !== 'number') {
|
||||
throw new TypeError('missing ext.id');
|
||||
}
|
||||
// encrypt is optional. If unset set it to false.
|
||||
if (ext.encrypt && typeof ext.encrypt !== 'boolean') {
|
||||
throw new TypeError('invalid ext.encrypt');
|
||||
} else if (!ext.encrypt) {
|
||||
ext.encrypt = false;
|
||||
}
|
||||
// parameters is optional. If unset, set it to an empty object.
|
||||
if (!ext.parameters || typeof ext.parameters !== 'object') {
|
||||
ext.parameters = {};
|
||||
}
|
||||
for (const key of Object.keys(ext.parameters)) {
|
||||
let value = ext.parameters[key];
|
||||
if (value === undefined) {
|
||||
ext.parameters[key] = '';
|
||||
value = '';
|
||||
}
|
||||
if (typeof value !== 'string' && typeof value !== 'number') {
|
||||
throw new TypeError('invalid header extension parameter');
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.validateRtpHeaderExtensionParameters = validateRtpHeaderExtensionParameters;
|
||||
/**
|
||||
* Validates RtpEncodingParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpEncodingParameters(encoding) {
|
||||
if (typeof encoding !== 'object') {
|
||||
throw new TypeError('encoding is not an object');
|
||||
}
|
||||
// ssrc is optional.
|
||||
if (encoding.ssrc && typeof encoding.ssrc !== 'number') {
|
||||
throw new TypeError('invalid encoding.ssrc');
|
||||
}
|
||||
// rid is optional.
|
||||
if (encoding.rid && typeof encoding.rid !== 'string') {
|
||||
throw new TypeError('invalid encoding.rid');
|
||||
}
|
||||
// rtx is optional.
|
||||
if (encoding.rtx && typeof encoding.rtx !== 'object') {
|
||||
throw new TypeError('invalid encoding.rtx');
|
||||
} else if (encoding.rtx) {
|
||||
// RTX ssrc is mandatory if rtx is present.
|
||||
if (typeof encoding.rtx.ssrc !== 'number') {
|
||||
throw new TypeError('missing encoding.rtx.ssrc');
|
||||
}
|
||||
}
|
||||
// dtx is optional. If unset set it to false.
|
||||
if (!encoding.dtx || typeof encoding.dtx !== 'boolean') {
|
||||
encoding.dtx = false;
|
||||
}
|
||||
// scalabilityMode is optional.
|
||||
if (encoding.scalabilityMode && typeof encoding.scalabilityMode !== 'string') {
|
||||
throw new TypeError('invalid encoding.scalabilityMode');
|
||||
}
|
||||
}
|
||||
exports.validateRtpEncodingParameters = validateRtpEncodingParameters;
|
||||
/**
|
||||
* Validates RtcpParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtcpParameters(rtcp) {
|
||||
if (typeof rtcp !== 'object') {
|
||||
throw new TypeError('rtcp is not an object');
|
||||
}
|
||||
// cname is optional.
|
||||
if (rtcp.cname && typeof rtcp.cname !== 'string') {
|
||||
throw new TypeError('invalid rtcp.cname');
|
||||
}
|
||||
// reducedSize is optional. If unset set it to true.
|
||||
if (!rtcp.reducedSize || typeof rtcp.reducedSize !== 'boolean') {
|
||||
rtcp.reducedSize = true;
|
||||
}
|
||||
}
|
||||
exports.validateRtcpParameters = validateRtcpParameters;
|
||||
/**
|
||||
* Validates SctpCapabilities. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateSctpCapabilities(caps) {
|
||||
if (typeof caps !== 'object') {
|
||||
throw new TypeError('caps is not an object');
|
||||
}
|
||||
// numStreams is mandatory.
|
||||
if (!caps.numStreams || typeof caps.numStreams !== 'object') {
|
||||
throw new TypeError('missing caps.numStreams');
|
||||
}
|
||||
validateNumSctpStreams(caps.numStreams);
|
||||
}
|
||||
exports.validateSctpCapabilities = validateSctpCapabilities;
|
||||
/**
|
||||
* Validates NumSctpStreams. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateNumSctpStreams(numStreams) {
|
||||
if (typeof numStreams !== 'object') {
|
||||
throw new TypeError('numStreams is not an object');
|
||||
}
|
||||
// OS is mandatory.
|
||||
if (typeof numStreams.OS !== 'number') {
|
||||
throw new TypeError('missing numStreams.OS');
|
||||
}
|
||||
// MIS is mandatory.
|
||||
if (typeof numStreams.MIS !== 'number') {
|
||||
throw new TypeError('missing numStreams.MIS');
|
||||
}
|
||||
}
|
||||
exports.validateNumSctpStreams = validateNumSctpStreams;
|
||||
/**
|
||||
* Validates SctpParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateSctpParameters(params) {
|
||||
if (typeof params !== 'object') {
|
||||
throw new TypeError('params is not an object');
|
||||
}
|
||||
// port is mandatory.
|
||||
if (typeof params.port !== 'number') {
|
||||
throw new TypeError('missing params.port');
|
||||
}
|
||||
// OS is mandatory.
|
||||
if (typeof params.OS !== 'number') {
|
||||
throw new TypeError('missing params.OS');
|
||||
}
|
||||
// MIS is mandatory.
|
||||
if (typeof params.MIS !== 'number') {
|
||||
throw new TypeError('missing params.MIS');
|
||||
}
|
||||
// maxMessageSize is mandatory.
|
||||
if (typeof params.maxMessageSize !== 'number') {
|
||||
throw new TypeError('missing params.maxMessageSize');
|
||||
}
|
||||
}
|
||||
exports.validateSctpParameters = validateSctpParameters;
|
||||
/**
|
||||
* Validates SctpStreamParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
@@ -13642,6 +13296,22 @@
|
||||
}
|
||||
}
|
||||
exports.validateSctpStreamParameters = validateSctpStreamParameters;
|
||||
/**
|
||||
* Validates SctpCapabilities. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateSctpCapabilities(caps) {
|
||||
if (typeof caps !== 'object') {
|
||||
throw new TypeError('caps is not an object');
|
||||
}
|
||||
// numStreams is mandatory.
|
||||
if (!caps.numStreams || typeof caps.numStreams !== 'object') {
|
||||
throw new TypeError('missing caps.numStreams');
|
||||
}
|
||||
validateNumSctpStreams(caps.numStreams);
|
||||
}
|
||||
exports.validateSctpCapabilities = validateSctpCapabilities;
|
||||
/**
|
||||
* Generate extended RTP capabilities for sending and receiving.
|
||||
*/
|
||||
@@ -14006,6 +13676,294 @@
|
||||
);
|
||||
}
|
||||
exports.canReceive = canReceive;
|
||||
/**
|
||||
* Validates RtpCodecCapability. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpCodecCapability(codec) {
|
||||
const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i');
|
||||
if (typeof codec !== 'object') {
|
||||
throw new TypeError('codec is not an object');
|
||||
}
|
||||
// mimeType is mandatory.
|
||||
if (!codec.mimeType || typeof codec.mimeType !== 'string') {
|
||||
throw new TypeError('missing codec.mimeType');
|
||||
}
|
||||
const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType);
|
||||
if (!mimeTypeMatch) {
|
||||
throw new TypeError('invalid codec.mimeType');
|
||||
}
|
||||
// Just override kind with media component of mimeType.
|
||||
codec.kind = mimeTypeMatch[1].toLowerCase();
|
||||
// preferredPayloadType is optional.
|
||||
if (codec.preferredPayloadType && typeof codec.preferredPayloadType !== 'number') {
|
||||
throw new TypeError('invalid codec.preferredPayloadType');
|
||||
}
|
||||
// clockRate is mandatory.
|
||||
if (typeof codec.clockRate !== 'number') {
|
||||
throw new TypeError('missing codec.clockRate');
|
||||
}
|
||||
// channels is optional. If unset, set it to 1 (just if audio).
|
||||
if (codec.kind === 'audio') {
|
||||
if (typeof codec.channels !== 'number') {
|
||||
codec.channels = 1;
|
||||
}
|
||||
} else {
|
||||
delete codec.channels;
|
||||
}
|
||||
// parameters is optional. If unset, set it to an empty object.
|
||||
if (!codec.parameters || typeof codec.parameters !== 'object') {
|
||||
codec.parameters = {};
|
||||
}
|
||||
for (const key of Object.keys(codec.parameters)) {
|
||||
let value = codec.parameters[key];
|
||||
if (value === undefined) {
|
||||
codec.parameters[key] = '';
|
||||
value = '';
|
||||
}
|
||||
if (typeof value !== 'string' && typeof value !== 'number') {
|
||||
throw new TypeError(`invalid codec parameter [key:${key}s, value:${value}]`);
|
||||
}
|
||||
// Specific parameters validation.
|
||||
if (key === 'apt') {
|
||||
if (typeof value !== 'number') {
|
||||
throw new TypeError('invalid codec apt parameter');
|
||||
}
|
||||
}
|
||||
}
|
||||
// rtcpFeedback is optional. If unset, set it to an empty array.
|
||||
if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) {
|
||||
codec.rtcpFeedback = [];
|
||||
}
|
||||
for (const fb of codec.rtcpFeedback) {
|
||||
validateRtcpFeedback(fb);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates RtcpFeedback. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtcpFeedback(fb) {
|
||||
if (typeof fb !== 'object') {
|
||||
throw new TypeError('fb is not an object');
|
||||
}
|
||||
// type is mandatory.
|
||||
if (!fb.type || typeof fb.type !== 'string') {
|
||||
throw new TypeError('missing fb.type');
|
||||
}
|
||||
// parameter is optional. If unset set it to an empty string.
|
||||
if (!fb.parameter || typeof fb.parameter !== 'string') {
|
||||
fb.parameter = '';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates RtpHeaderExtension. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpHeaderExtension(ext) {
|
||||
if (typeof ext !== 'object') {
|
||||
throw new TypeError('ext is not an object');
|
||||
}
|
||||
// kind is mandatory.
|
||||
if (ext.kind !== 'audio' && ext.kind !== 'video') {
|
||||
throw new TypeError('invalid ext.kind');
|
||||
}
|
||||
// uri is mandatory.
|
||||
if (!ext.uri || typeof ext.uri !== 'string') {
|
||||
throw new TypeError('missing ext.uri');
|
||||
}
|
||||
// preferredId is mandatory.
|
||||
if (typeof ext.preferredId !== 'number') {
|
||||
throw new TypeError('missing ext.preferredId');
|
||||
}
|
||||
// preferredEncrypt is optional. If unset set it to false.
|
||||
if (ext.preferredEncrypt && typeof ext.preferredEncrypt !== 'boolean') {
|
||||
throw new TypeError('invalid ext.preferredEncrypt');
|
||||
} else if (!ext.preferredEncrypt) {
|
||||
ext.preferredEncrypt = false;
|
||||
}
|
||||
// direction is optional. If unset set it to sendrecv.
|
||||
if (ext.direction && typeof ext.direction !== 'string') {
|
||||
throw new TypeError('invalid ext.direction');
|
||||
} else if (!ext.direction) {
|
||||
ext.direction = 'sendrecv';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates RtpCodecParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpCodecParameters(codec) {
|
||||
const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i');
|
||||
if (typeof codec !== 'object') {
|
||||
throw new TypeError('codec is not an object');
|
||||
}
|
||||
// mimeType is mandatory.
|
||||
if (!codec.mimeType || typeof codec.mimeType !== 'string') {
|
||||
throw new TypeError('missing codec.mimeType');
|
||||
}
|
||||
const mimeTypeMatch = MimeTypeRegex.exec(codec.mimeType);
|
||||
if (!mimeTypeMatch) {
|
||||
throw new TypeError('invalid codec.mimeType');
|
||||
}
|
||||
// payloadType is mandatory.
|
||||
if (typeof codec.payloadType !== 'number') {
|
||||
throw new TypeError('missing codec.payloadType');
|
||||
}
|
||||
// clockRate is mandatory.
|
||||
if (typeof codec.clockRate !== 'number') {
|
||||
throw new TypeError('missing codec.clockRate');
|
||||
}
|
||||
const kind = mimeTypeMatch[1].toLowerCase();
|
||||
// channels is optional. If unset, set it to 1 (just if audio).
|
||||
if (kind === 'audio') {
|
||||
if (typeof codec.channels !== 'number') {
|
||||
codec.channels = 1;
|
||||
}
|
||||
} else {
|
||||
delete codec.channels;
|
||||
}
|
||||
// parameters is optional. If unset, set it to an empty object.
|
||||
if (!codec.parameters || typeof codec.parameters !== 'object') {
|
||||
codec.parameters = {};
|
||||
}
|
||||
for (const key of Object.keys(codec.parameters)) {
|
||||
let value = codec.parameters[key];
|
||||
if (value === undefined) {
|
||||
codec.parameters[key] = '';
|
||||
value = '';
|
||||
}
|
||||
if (typeof value !== 'string' && typeof value !== 'number') {
|
||||
throw new TypeError(`invalid codec parameter [key:${key}s, value:${value}]`);
|
||||
}
|
||||
// Specific parameters validation.
|
||||
if (key === 'apt') {
|
||||
if (typeof value !== 'number') {
|
||||
throw new TypeError('invalid codec apt parameter');
|
||||
}
|
||||
}
|
||||
}
|
||||
// rtcpFeedback is optional. If unset, set it to an empty array.
|
||||
if (!codec.rtcpFeedback || !Array.isArray(codec.rtcpFeedback)) {
|
||||
codec.rtcpFeedback = [];
|
||||
}
|
||||
for (const fb of codec.rtcpFeedback) {
|
||||
validateRtcpFeedback(fb);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates RtpHeaderExtensionParameteters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpHeaderExtensionParameters(ext) {
|
||||
if (typeof ext !== 'object') {
|
||||
throw new TypeError('ext is not an object');
|
||||
}
|
||||
// uri is mandatory.
|
||||
if (!ext.uri || typeof ext.uri !== 'string') {
|
||||
throw new TypeError('missing ext.uri');
|
||||
}
|
||||
// id is mandatory.
|
||||
if (typeof ext.id !== 'number') {
|
||||
throw new TypeError('missing ext.id');
|
||||
}
|
||||
// encrypt is optional. If unset set it to false.
|
||||
if (ext.encrypt && typeof ext.encrypt !== 'boolean') {
|
||||
throw new TypeError('invalid ext.encrypt');
|
||||
} else if (!ext.encrypt) {
|
||||
ext.encrypt = false;
|
||||
}
|
||||
// parameters is optional. If unset, set it to an empty object.
|
||||
if (!ext.parameters || typeof ext.parameters !== 'object') {
|
||||
ext.parameters = {};
|
||||
}
|
||||
for (const key of Object.keys(ext.parameters)) {
|
||||
let value = ext.parameters[key];
|
||||
if (value === undefined) {
|
||||
ext.parameters[key] = '';
|
||||
value = '';
|
||||
}
|
||||
if (typeof value !== 'string' && typeof value !== 'number') {
|
||||
throw new TypeError('invalid header extension parameter');
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates RtpEncodingParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtpEncodingParameters(encoding) {
|
||||
if (typeof encoding !== 'object') {
|
||||
throw new TypeError('encoding is not an object');
|
||||
}
|
||||
// ssrc is optional.
|
||||
if (encoding.ssrc && typeof encoding.ssrc !== 'number') {
|
||||
throw new TypeError('invalid encoding.ssrc');
|
||||
}
|
||||
// rid is optional.
|
||||
if (encoding.rid && typeof encoding.rid !== 'string') {
|
||||
throw new TypeError('invalid encoding.rid');
|
||||
}
|
||||
// rtx is optional.
|
||||
if (encoding.rtx && typeof encoding.rtx !== 'object') {
|
||||
throw new TypeError('invalid encoding.rtx');
|
||||
} else if (encoding.rtx) {
|
||||
// RTX ssrc is mandatory if rtx is present.
|
||||
if (typeof encoding.rtx.ssrc !== 'number') {
|
||||
throw new TypeError('missing encoding.rtx.ssrc');
|
||||
}
|
||||
}
|
||||
// dtx is optional. If unset set it to false.
|
||||
if (!encoding.dtx || typeof encoding.dtx !== 'boolean') {
|
||||
encoding.dtx = false;
|
||||
}
|
||||
// scalabilityMode is optional.
|
||||
if (encoding.scalabilityMode && typeof encoding.scalabilityMode !== 'string') {
|
||||
throw new TypeError('invalid encoding.scalabilityMode');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates RtcpParameters. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateRtcpParameters(rtcp) {
|
||||
if (typeof rtcp !== 'object') {
|
||||
throw new TypeError('rtcp is not an object');
|
||||
}
|
||||
// cname is optional.
|
||||
if (rtcp.cname && typeof rtcp.cname !== 'string') {
|
||||
throw new TypeError('invalid rtcp.cname');
|
||||
}
|
||||
// reducedSize is optional. If unset set it to true.
|
||||
if (!rtcp.reducedSize || typeof rtcp.reducedSize !== 'boolean') {
|
||||
rtcp.reducedSize = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates NumSctpStreams. It may modify given data by adding missing
|
||||
* fields with default values.
|
||||
* It throws if invalid.
|
||||
*/
|
||||
function validateNumSctpStreams(numStreams) {
|
||||
if (typeof numStreams !== 'object') {
|
||||
throw new TypeError('numStreams is not an object');
|
||||
}
|
||||
// OS is mandatory.
|
||||
if (typeof numStreams.OS !== 'number') {
|
||||
throw new TypeError('missing numStreams.OS');
|
||||
}
|
||||
// MIS is mandatory.
|
||||
if (typeof numStreams.MIS !== 'number') {
|
||||
throw new TypeError('missing numStreams.MIS');
|
||||
}
|
||||
}
|
||||
function isRtxCodec(codec) {
|
||||
if (!codec) {
|
||||
return false;
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم