mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-20 02:00:05 -08:00
webrtc: fix codec collision in Chrome (#4394)
Fix error "A BUNDLE group contains a codec collision for payload_type='96. All codecs must share the same type, encoding name, clock rate and parameters. (INVALID_PARAMETER)"
This commit is contained in:
parent
a05da3a205
commit
848a8b1031
1 changed files with 30 additions and 23 deletions
|
|
@ -95,25 +95,28 @@
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
const findFreePayloadType = (firstLine) => {
|
const reservePayloadType = (payloadTypes) => {
|
||||||
const payloadTypes = firstLine.split(' ').slice(3);
|
// everything is valid between 30 and 127, except for interval between 64 and 95
|
||||||
for (let i = 96; i <= 127; i++) {
|
// https://chromium.googlesource.com/external/webrtc/+/refs/heads/master/call/payload_type.h#29
|
||||||
if (!payloadTypes.includes(i.toString())) {
|
for (let i = 30; i <= 127; i++) {
|
||||||
return i.toString();
|
if ((i <= 63 || i >= 96) && !payloadTypes.includes(i.toString())) {
|
||||||
|
const pl = i.toString();
|
||||||
|
payloadTypes.push(pl);
|
||||||
|
return pl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw Error('unable to find a free payload type');
|
throw Error('unable to find a free payload type');
|
||||||
};
|
};
|
||||||
|
|
||||||
const enableStereoPcmau = (section) => {
|
const enableStereoPcmau = (payloadTypes, section) => {
|
||||||
let lines = section.split('\r\n');
|
let lines = section.split('\r\n');
|
||||||
|
|
||||||
let payloadType = findFreePayloadType(lines[0]);
|
let payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} PCMU/8000/2`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} PCMU/8000/2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} PCMA/8000/2`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} PCMA/8000/2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
@ -121,40 +124,40 @@
|
||||||
return lines.join('\r\n');
|
return lines.join('\r\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
const enableMultichannelOpus = (section) => {
|
const enableMultichannelOpus = (payloadTypes, section) => {
|
||||||
let lines = section.split('\r\n');
|
let lines = section.split('\r\n');
|
||||||
|
|
||||||
let payloadType = findFreePayloadType(lines[0]);
|
let payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/3`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/3`);
|
||||||
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,2,1;num_streams=2;coupled_streams=1`);
|
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,2,1;num_streams=2;coupled_streams=1`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/4`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/4`);
|
||||||
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,1,2,3;num_streams=2;coupled_streams=2`);
|
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,1,2,3;num_streams=2;coupled_streams=2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/5`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/5`);
|
||||||
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,4,1,2,3;num_streams=3;coupled_streams=2`);
|
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,4,1,2,3;num_streams=3;coupled_streams=2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/6`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/6`);
|
||||||
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,4,1,2,3,5;num_streams=4;coupled_streams=2`);
|
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,4,1,2,3,5;num_streams=4;coupled_streams=2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/7`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/7`);
|
||||||
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,4,1,2,3,5,6;num_streams=4;coupled_streams=4`);
|
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,4,1,2,3,5,6;num_streams=4;coupled_streams=4`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/8`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} multiopus/48000/8`);
|
||||||
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,6,1,4,5,2,3,7;num_streams=5;coupled_streams=4`);
|
lines.splice(lines.length - 1, 0, `a=fmtp:${payloadType} channel_mapping=0,6,1,4,5,2,3,7;num_streams=5;coupled_streams=4`);
|
||||||
|
|
@ -163,20 +166,20 @@
|
||||||
return lines.join('\r\n');
|
return lines.join('\r\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
const enableL16 = (section) => {
|
const enableL16 = (payloadTypes, section) => {
|
||||||
let lines = section.split('\r\n');
|
let lines = section.split('\r\n');
|
||||||
|
|
||||||
let payloadType = findFreePayloadType(lines[0]);
|
let payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/8000/2`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/8000/2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/16000/2`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/16000/2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
||||||
payloadType = findFreePayloadType(lines[0]);
|
payloadType = reservePayloadType(payloadTypes);
|
||||||
lines[0] += ` ${payloadType}`;
|
lines[0] += ` ${payloadType}`;
|
||||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/48000/2`);
|
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/48000/2`);
|
||||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||||
|
|
@ -216,18 +219,22 @@
|
||||||
const editOffer = (sdp, nonAdvertisedCodecs) => {
|
const editOffer = (sdp, nonAdvertisedCodecs) => {
|
||||||
const sections = sdp.split('m=');
|
const sections = sdp.split('m=');
|
||||||
|
|
||||||
for (let i = 0; i < sections.length; i++) {
|
const payloadTypes = sections.slice(1)
|
||||||
|
.map((s) => s.split('\r\n')[0].split(' ').slice(3))
|
||||||
|
.reduce((prev, cur) => [...prev, ...cur], []);
|
||||||
|
|
||||||
|
for (let i = 1; i < sections.length; i++) {
|
||||||
if (sections[i].startsWith('audio')) {
|
if (sections[i].startsWith('audio')) {
|
||||||
sections[i] = enableStereoOpus(sections[i]);
|
sections[i] = enableStereoOpus(sections[i]);
|
||||||
|
|
||||||
if (nonAdvertisedCodecs.includes('pcma/8000/2')) {
|
if (nonAdvertisedCodecs.includes('pcma/8000/2')) {
|
||||||
sections[i] = enableStereoPcmau(sections[i]);
|
sections[i] = enableStereoPcmau(payloadTypes, sections[i]);
|
||||||
}
|
}
|
||||||
if (nonAdvertisedCodecs.includes('multiopus/48000/6')) {
|
if (nonAdvertisedCodecs.includes('multiopus/48000/6')) {
|
||||||
sections[i] = enableMultichannelOpus(sections[i]);
|
sections[i] = enableMultichannelOpus(payloadTypes, sections[i]);
|
||||||
}
|
}
|
||||||
if (nonAdvertisedCodecs.includes('L16/48000/2')) {
|
if (nonAdvertisedCodecs.includes('L16/48000/2')) {
|
||||||
sections[i] = enableL16(sections[i]);
|
sections[i] = enableL16(payloadTypes, sections[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue