mediasoup-client
Version:
mediasoup client side TypeScript library
130 lines (129 loc) • 4.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRtpEncodings = getRtpEncodings;
exports.addLegacySimulcast = addLegacySimulcast;
function getRtpEncodings({ offerMediaObject, codecs, }) {
const ssrcs = new Set();
for (const line of offerMediaObject.ssrcs ?? []) {
const ssrc = line.id;
if (ssrc) {
ssrcs.add(ssrc);
}
}
if (ssrcs.size === 0) {
throw new Error('no a=ssrc lines found');
}
const ssrcToRtxSsrc = new Map();
// First assume RTX is used.
for (const line of offerMediaObject.ssrcGroups ?? []) {
if (line.semantics !== 'FID') {
continue;
}
const ssrcsStr = line.ssrcs.split(/\s+/);
const ssrc = Number(ssrcsStr[0]);
const rtxSsrc = Number(ssrcsStr[1]);
if (ssrcs.has(ssrc)) {
// Remove both the SSRC and RTX SSRC from the set so later we know
// that they are already handled.
ssrcs.delete(ssrc);
ssrcs.delete(rtxSsrc);
// Add to the map.
ssrcToRtxSsrc.set(ssrc, rtxSsrc);
}
}
// If the set of SSRCs is not empty it means that RTX is not being used, so
// take media SSRCs from there.
for (const ssrc of ssrcs) {
// Add to the map.
ssrcToRtxSsrc.set(ssrc, undefined);
}
const encodings = [];
for (const [ssrc, rtxSsrc] of ssrcToRtxSsrc) {
const encoding = { ssrc };
// Only add RTX SSRC if there are more than 1 codec.
if (rtxSsrc && codecs.length > 1) {
encoding.rtx = { ssrc: rtxSsrc };
}
encodings.push(encoding);
}
return encodings;
}
/**
* Adds multi-ssrc based simulcast into the given SDP media section offer.
*/
function addLegacySimulcast({ offerMediaObject, numStreams, }) {
if (numStreams <= 1) {
throw new TypeError('numStreams must be greater than 1');
}
// Get the SSRC.
const ssrcMsidLine = (offerMediaObject.ssrcs ?? []).find(line => line.attribute === 'msid');
if (!ssrcMsidLine) {
throw new Error('a=ssrc line with msid information not found');
}
const [streamId, trackId] = ssrcMsidLine.value.split(' ');
const firstSsrc = Number(ssrcMsidLine.id);
let firstRtxSsrc;
// Get the SSRC for RTX.
(offerMediaObject.ssrcGroups ?? []).some(line => {
if (line.semantics !== 'FID') {
return false;
}
const ssrcs = line.ssrcs.split(/\s+/);
if (Number(ssrcs[0]) === firstSsrc) {
firstRtxSsrc = Number(ssrcs[1]);
return true;
}
else {
return false;
}
});
const ssrcCnameLine = (offerMediaObject.ssrcs ?? []).find(line => line.attribute === 'cname');
if (!ssrcCnameLine) {
throw new Error('a=ssrc line with cname information not found');
}
const cname = ssrcCnameLine.value;
const ssrcs = [];
const rtxSsrcs = [];
for (let i = 0; i < numStreams; ++i) {
ssrcs.push(firstSsrc + i);
if (firstRtxSsrc) {
rtxSsrcs.push(firstRtxSsrc + i);
}
}
offerMediaObject.ssrcGroups = [];
offerMediaObject.ssrcs = [];
offerMediaObject.ssrcGroups.push({
semantics: 'SIM',
ssrcs: ssrcs.join(' '),
});
for (const ssrc of ssrcs) {
offerMediaObject.ssrcs.push({
id: ssrc,
attribute: 'cname',
value: cname,
});
offerMediaObject.ssrcs.push({
id: ssrc,
attribute: 'msid',
value: `${streamId} ${trackId}`,
});
}
for (let i = 0; i < rtxSsrcs.length; ++i) {
const ssrc = ssrcs[i];
const rtxSsrc = rtxSsrcs[i];
offerMediaObject.ssrcs.push({
id: rtxSsrc,
attribute: 'cname',
value: cname,
});
offerMediaObject.ssrcs.push({
id: rtxSsrc,
attribute: 'msid',
value: `${streamId} ${trackId}`,
});
offerMediaObject.ssrcGroups.push({
semantics: 'FID',
ssrcs: `${ssrc} ${rtxSsrc}`,
});
}
}