diff --git a/modules/RTC/TraceablePeerConnection.js b/modules/RTC/TraceablePeerConnection.js index 30b927eae9..834e8a9a06 100644 --- a/modules/RTC/TraceablePeerConnection.js +++ b/modules/RTC/TraceablePeerConnection.js @@ -1385,16 +1385,12 @@ TraceablePeerConnection.prototype._mungeCodecOrder = function(description) { for (const codec of currentCodecs) { if (this.isP2P) { - // Strip the high profile H264 codecs on mobile clients as they deliver better quality at the expense - // of higher load. - if (codec === CodecMimeType.H264 && browser.isMobileDevice()) { - SDPUtil.stripCodec(mLine, codec, true /* high profile */); - } - - // There are multiple VP9 payload types generated by the browser, more payload types are added if the - // endpoint doesn't have a local video source. Therefore, strip all the high profile codec variants for - // VP9 so that only one payload type for VP9 is negotiated between the peers. - if (codec === CodecMimeType.VP9) { + // 1. Strip the high profile H264 codecs on all clients. macOS started offering encoder for H.264 level + // 5.2 but a decoder only for level 3.1. Therfore, strip all main and high level codecs for H.264. + // 2. There are multiple VP9 payload types generated by the browser, more payload types are added if the + // endpoint doesn't have a local video source. Therefore, strip all the high profile codec variants + // for VP9 so that only one payload type for VP9 is negotiated between the peers. + if (codec === CodecMimeType.H264 || codec === CodecMimeType.VP9) { SDPUtil.stripCodec(mLine, codec, true /* high profile */); } @@ -1407,7 +1403,7 @@ TraceablePeerConnection.prototype._mungeCodecOrder = function(description) { // Reorder the codecs based on the preferred settings. for (const codec of this.codecSettings.codecList.slice().reverse()) { - SDPUtil.preferCodec(mLine, codec); + SDPUtil.preferCodec(mLine, codec, this.isP2P); } } diff --git a/modules/sdp/SDPUtil.js b/modules/sdp/SDPUtil.js index 24e2dc5ea6..2e8a7b4bfb 100644 --- a/modules/sdp/SDPUtil.js +++ b/modules/sdp/SDPUtil.js @@ -617,10 +617,11 @@ const SDPUtil = { * Sets the given codecName as the preferred codec by moving it to the beginning * of the payload types list (modifies the given mline in place). All instances * of the codec are moved up. - * @param {object} mLine the mline object from an sdp as parsed by transform.parse - * @param {string} codecName the name of the preferred codec + * @param {object} mLine the mline object from an sdp as parsed by transform.parse. + * @param {string} codecName the name of the preferred codec. + * @param {boolean} sortPayloadTypes whether the payloadtypes need to be sorted for a given codec. */ - preferCodec(mline, codecName) { + preferCodec(mline, codecName, sortPayloadTypes = false) { if (!mline || !codecName) { return; } @@ -630,6 +631,28 @@ const SDPUtil = { .map(rtp => rtp.payload); if (matchingPayloadTypes) { + if (sortPayloadTypes && codecName === CodecMimeType.H264) { + // Move all the H.264 codecs with packetization-mode=0 to top of the list. + const payloadsWithMode0 = matchingPayloadTypes.filter(payload => { + const fmtp = mline.fmtp.find(item => item.payload === payload); + + if (fmtp) { + return fmtp.config.includes('packetization-mode=0'); + } + + return false; + }); + + for (const pt of payloadsWithMode0.reverse()) { + const idx = matchingPayloadTypes.findIndex(payloadType => payloadType === pt); + + if (idx >= 0) { + matchingPayloadTypes.splice(idx, 1); + matchingPayloadTypes.unshift(pt); + } + } + } + // Call toString() on payloads to get around an issue within SDPTransform that sets // payloads as a number, instead of a string, when there is only one payload. const payloadTypes @@ -686,7 +709,7 @@ const SDPUtil = { if (codec) { return codec.toLowerCase() === CodecMimeType.VP9 ? !item.config.includes('profile-id=0') - : item.config.includes('profile-level-id=64'); + : !item.config.includes('profile-level-id=42'); } return false;