Skip to content

Commit

Permalink
fix support for browsers that do not support unadvertised codecs
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 committed Jun 2, 2024
1 parent ef57505 commit 6d542dd
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 24 deletions.
14 changes: 6 additions & 8 deletions internal/servers/webrtc/publish_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,10 @@
const sections = sdp.split('m=');

for (let i = 0; i < sections.length; i++) {
const section = sections[i];
if (section.startsWith('video')) {
sections[i] = setCodec(section, videoForm.codec.value);
} else if (section.startsWith('audio')) {
sections[i] = setAudioBitrate(setCodec(section, audioForm.codec.value), audioForm.bitrate.value, audioForm.voice.checked);
if (sections[i].startsWith('video')) {
sections[i] = setCodec(sections[i], videoForm.codec.value);
} else if (sections[i].startsWith('audio')) {
sections[i] = setAudioBitrate(setCodec(sections[i], audioForm.codec.value), audioForm.bitrate.value, audioForm.voice.checked);
}
}

Expand All @@ -391,9 +390,8 @@
const sections = sdp.split('m=');

for (let i = 0; i < sections.length; i++) {
const section = sections[i];
if (section.startsWith('video')) {
sections[i] = setVideoBitrate(section, videoForm.bitrate.value);
if (sections[i].startsWith('video')) {
sections[i] = setVideoBitrate(sections[i], videoForm.bitrate.value);
}
}

Expand Down
102 changes: 86 additions & 16 deletions internal/servers/webrtc/read_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
const video = document.getElementById('video');
const message = document.getElementById('message');

let nonAdvertisedCodecs = [];
let pc = null;
let restartTimeout = null;
let sessionUrl = '';
Expand Down Expand Up @@ -87,14 +88,14 @@
}) : []
);

const parseOffer = (offer) => {
const parseOffer = (sdp) => {
const ret = {
iceUfrag: '',
icePwd: '',
medias: [],
};

for (const line of offer.split('\r\n')) {
for (const line of sdp.split('\r\n')) {
if (line.startsWith('m=')) {
ret.medias.push(line.slice('m='.length));
} else if (ret.iceUfrag === '' && line.startsWith('a=ice-ufrag:')) {
Expand All @@ -110,13 +111,13 @@
const enableStereoPcmau = (section) => {
let lines = section.split('\r\n');

lines[0] += " 118";
lines.splice(lines.length - 1, 0, "a=rtpmap:118 PCMU/8000/2");
lines.splice(lines.length - 1, 0, "a=rtcp-fb:118 transport-cc");
lines[0] += ' 118';
lines.splice(lines.length - 1, 0, 'a=rtpmap:118 PCMU/8000/2');
lines.splice(lines.length - 1, 0, 'a=rtcp-fb:118 transport-cc');

lines[0] += " 119";
lines.splice(lines.length - 1, 0, "a=rtpmap:119 PCMA/8000/2");
lines.splice(lines.length - 1, 0, "a=rtcp-fb:119 transport-cc");
lines[0] += ' 119';
lines.splice(lines.length - 1, 0, 'a=rtpmap:119 PCMA/8000/2');
lines.splice(lines.length - 1, 0, 'a=rtcp-fb:119 transport-cc');

return lines.join('\r\n');
};
Expand Down Expand Up @@ -150,17 +151,22 @@
return lines.join('\r\n');
};

const editOffer = (offer) => {
const sections = offer.sdp.split('m=');
const editOffer = (sdp) => {
const sections = sdp.split('m=');

for (let i = 0; i < sections.length; i++) {
const section = sections[i];
if (section.startsWith('audio')) {
sections[i] = enableStereoPcmau(enableStereoOpus(section));
if (sections[i].startsWith('audio')) {
sections[i] = enableStereoOpus(sections[i]);

if (nonAdvertisedCodecs.includes('pcma/8000/2')) {
sections[i] = enableStereoPcmau(sections[i]);
}

break;
}
}

offer.sdp = sections.join('m=');
return sections.join('m=');
};

const generateSdpFragment = (od, candidates) => {
Expand Down Expand Up @@ -197,6 +203,70 @@
requestICEServers();
};

const supportsNonAdvertisedCodec = (codec, fmtp) => (
new Promise((resolve, reject) => {
const pc = new RTCPeerConnection({ iceServers: [] });
pc.addTransceiver('audio', { direction: 'recvonly' });
pc.createOffer()
.then((offer) => {
if (offer.sdp.includes(' ' + codec)) { // codec is advertised, there's no need to add it manually
resolve(false);
return;
}
const sections = offer.sdp.split('m=audio');
const lines = sections[1].split('\r\n');
lines[0] += ' 118';
lines.splice(lines.length - 1, 0, 'a=rtpmap:118 ' + codec);
if (fmtp !== undefined) {
lines.splice(lines.length - 1, 0, 'a=fmtp:118 ' + fmtp);
}
sections[1] = lines.join('\r\n');
offer.sdp = sections.join('m=audio');
return pc.setLocalDescription(offer);
})
.then(() => {
return pc.setRemoteDescription(new RTCSessionDescription({
type: 'answer',
sdp: 'v=0\r\n'
+ 'o=- 6539324223450680508 0 IN IP4 0.0.0.0\r\n'
+ 's=-\r\n'
+ 't=0 0\r\n'
+ 'a=fingerprint:sha-256 0D:9F:78:15:42:B5:4B:E6:E2:94:3E:5B:37:78:E1:4B:54:59:A3:36:3A:E5:05:EB:27:EE:8F:D2:2D:41:29:25\r\n'
+ 'm=audio 9 UDP/TLS/RTP/SAVPF 118\r\n'
+ 'c=IN IP4 0.0.0.0\r\n'
+ 'a=ice-pwd:7c3bf4770007e7432ee4ea4d697db675\r\n'
+ 'a=ice-ufrag:29e036dc\r\n'
+ 'a=sendonly\r\n'
+ 'a=rtcp-mux\r\n'
+ 'a=rtpmap:118 ' + codec + '\r\n'
+ ((fmtp !== undefined) ? 'a=fmtp:118 ' + fmtp + '\r\n' : ''),
}));
})
.then(() => {
resolve(true);
})
.catch((err) => {
resolve(false);
})
.finally(() => {
pc.close();
});
})
);

const getNonAdvertisedCodecs = () => {
Promise.all([
['pcma/8000/2'],
['multiopus/48000/6', 'channel_mapping=0,4,1,2,3,5;num_streams=4;coupled_streams=2'],
['L16/48000/2']
].map((c) => supportsNonAdvertisedCodec(c[0], c[1]).then((r) => (r) ? c[0] : false)))
.then((c) => c.filter((e) => e !== false))
.then((codecs) => {
nonAdvertisedCodecs = codecs;
loadStream();
});
};

const onError = (err) => {
if (restartTimeout === null) {
setMessage(err + ', retrying in some seconds');
Expand Down Expand Up @@ -309,7 +379,7 @@
const createOffer = () => {
pc.createOffer()
.then((offer) => {
editOffer(offer);
offer.sdp = editOffer(offer.sdp);
offerData = parseOffer(offer.sdp);
pc.setLocalDescription(offer);
sendOffer(offer);
Expand Down Expand Up @@ -380,7 +450,7 @@

const init = () => {
loadAttributesFromQuery();
loadStream();
getNonAdvertisedCodecs();
};

window.addEventListener('DOMContentLoaded', init);
Expand Down

0 comments on commit 6d542dd

Please sign in to comment.