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;
|
||||
};
|
||||
|
||||
const findFreePayloadType = (firstLine) => {
|
||||
const payloadTypes = firstLine.split(' ').slice(3);
|
||||
for (let i = 96; i <= 127; i++) {
|
||||
if (!payloadTypes.includes(i.toString())) {
|
||||
return i.toString();
|
||||
const reservePayloadType = (payloadTypes) => {
|
||||
// everything is valid between 30 and 127, except for interval between 64 and 95
|
||||
// https://chromium.googlesource.com/external/webrtc/+/refs/heads/master/call/payload_type.h#29
|
||||
for (let i = 30; i <= 127; i++) {
|
||||
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');
|
||||
};
|
||||
|
||||
const enableStereoPcmau = (section) => {
|
||||
const enableStereoPcmau = (payloadTypes, section) => {
|
||||
let lines = section.split('\r\n');
|
||||
|
||||
let payloadType = findFreePayloadType(lines[0]);
|
||||
let payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} PCMU/8000/2`);
|
||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} PCMA/8000/2`);
|
||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
|
@ -121,40 +124,40 @@
|
|||
return lines.join('\r\n');
|
||||
};
|
||||
|
||||
const enableMultichannelOpus = (section) => {
|
||||
const enableMultichannelOpus = (payloadTypes, section) => {
|
||||
let lines = section.split('\r\n');
|
||||
|
||||
let payloadType = findFreePayloadType(lines[0]);
|
||||
let payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
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=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
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=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
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=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
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=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
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=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
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`);
|
||||
|
|
@ -163,20 +166,20 @@
|
|||
return lines.join('\r\n');
|
||||
};
|
||||
|
||||
const enableL16 = (section) => {
|
||||
const enableL16 = (payloadTypes, section) => {
|
||||
let lines = section.split('\r\n');
|
||||
|
||||
let payloadType = findFreePayloadType(lines[0]);
|
||||
let payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/8000/2`);
|
||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/16000/2`);
|
||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
||||
payloadType = findFreePayloadType(lines[0]);
|
||||
payloadType = reservePayloadType(payloadTypes);
|
||||
lines[0] += ` ${payloadType}`;
|
||||
lines.splice(lines.length - 1, 0, `a=rtpmap:${payloadType} L16/48000/2`);
|
||||
lines.splice(lines.length - 1, 0, `a=rtcp-fb:${payloadType} transport-cc`);
|
||||
|
|
@ -216,18 +219,22 @@
|
|||
const editOffer = (sdp, nonAdvertisedCodecs) => {
|
||||
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')) {
|
||||
sections[i] = enableStereoOpus(sections[i]);
|
||||
|
||||
if (nonAdvertisedCodecs.includes('pcma/8000/2')) {
|
||||
sections[i] = enableStereoPcmau(sections[i]);
|
||||
sections[i] = enableStereoPcmau(payloadTypes, sections[i]);
|
||||
}
|
||||
if (nonAdvertisedCodecs.includes('multiopus/48000/6')) {
|
||||
sections[i] = enableMultichannelOpus(sections[i]);
|
||||
sections[i] = enableMultichannelOpus(payloadTypes, sections[i]);
|
||||
}
|
||||
if (nonAdvertisedCodecs.includes('L16/48000/2')) {
|
||||
sections[i] = enableL16(sections[i]);
|
||||
sections[i] = enableL16(payloadTypes, sections[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue