Browse Source

fix(SDP): Negotiate only baseline H.264 codecs for p2p.

Chrome on macOS recently started offering encoder for higher level (5.2) but decoder only for level 3.1. See https://issues.chromium.org/issues/324930413
Therefore, filter out all H.264 payload types with main and high profiles. Also, sort all H.264 payload types so that same pt is picked for both H.264 encoder and decoder. Fixes random black tile issues across different browsers when H.264 is the preferred codec for p2p.
release-8443
Jaya Allamsetty 1 year ago
parent
commit
a8f8666be3
2 changed files with 34 additions and 15 deletions
  1. 7
    11
      modules/RTC/TraceablePeerConnection.js
  2. 27
    4
      modules/sdp/SDPUtil.js

+ 7
- 11
modules/RTC/TraceablePeerConnection.js View File

@@ -1385,16 +1385,12 @@ TraceablePeerConnection.prototype._mungeCodecOrder = function(description) {
1385 1385
 
1386 1386
         for (const codec of currentCodecs) {
1387 1387
             if (this.isP2P) {
1388
-                // Strip the high profile H264 codecs on mobile clients as they deliver better quality at the expense
1389
-                // of higher load.
1390
-                if (codec === CodecMimeType.H264 && browser.isMobileDevice()) {
1391
-                    SDPUtil.stripCodec(mLine, codec, true /* high profile */);
1392
-                }
1393
-
1394
-                // There are multiple VP9 payload types generated by the browser, more payload types are added if the
1395
-                // endpoint doesn't have a local video source. Therefore, strip all the high profile codec variants for
1396
-                // VP9 so that only one payload type for VP9 is negotiated between the peers.
1397
-                if (codec === CodecMimeType.VP9) {
1388
+                // 1. Strip the high profile H264 codecs on all clients. macOS started offering encoder for H.264 level
1389
+                //     5.2 but a decoder only for level 3.1. Therfore, strip all main and high level codecs for H.264.
1390
+                // 2. There are multiple VP9 payload types generated by the browser, more payload types are added if the
1391
+                //     endpoint doesn't have a local video source. Therefore, strip all the high profile codec variants
1392
+                //     for VP9 so that only one payload type for VP9 is negotiated between the peers.
1393
+                if (codec === CodecMimeType.H264 || codec === CodecMimeType.VP9) {
1398 1394
                     SDPUtil.stripCodec(mLine, codec, true /* high profile */);
1399 1395
                 }
1400 1396
 
@@ -1407,7 +1403,7 @@ TraceablePeerConnection.prototype._mungeCodecOrder = function(description) {
1407 1403
 
1408 1404
         // Reorder the codecs based on the preferred settings.
1409 1405
         for (const codec of this.codecSettings.codecList.slice().reverse()) {
1410
-            SDPUtil.preferCodec(mLine, codec);
1406
+            SDPUtil.preferCodec(mLine, codec, this.isP2P);
1411 1407
         }
1412 1408
     }
1413 1409
 

+ 27
- 4
modules/sdp/SDPUtil.js View File

@@ -617,10 +617,11 @@ const SDPUtil = {
617 617
      * Sets the given codecName as the preferred codec by moving it to the beginning
618 618
      * of the payload types list (modifies the given mline in place). All instances
619 619
      * of the codec are moved up.
620
-     * @param {object} mLine the mline object from an sdp as parsed by transform.parse
621
-     * @param {string} codecName the name of the preferred codec
620
+     * @param {object} mLine the mline object from an sdp as parsed by transform.parse.
621
+     * @param {string} codecName the name of the preferred codec.
622
+     * @param {boolean} sortPayloadTypes whether the payloadtypes need to be sorted for a given codec.
622 623
      */
623
-    preferCodec(mline, codecName) {
624
+    preferCodec(mline, codecName, sortPayloadTypes = false) {
624 625
         if (!mline || !codecName) {
625 626
             return;
626 627
         }
@@ -630,6 +631,28 @@ const SDPUtil = {
630 631
             .map(rtp => rtp.payload);
631 632
 
632 633
         if (matchingPayloadTypes) {
634
+            if (sortPayloadTypes && codecName === CodecMimeType.H264) {
635
+                // Move all the H.264 codecs with packetization-mode=0 to top of the list.
636
+                const payloadsWithMode0 = matchingPayloadTypes.filter(payload => {
637
+                    const fmtp = mline.fmtp.find(item => item.payload === payload);
638
+
639
+                    if (fmtp) {
640
+                        return fmtp.config.includes('packetization-mode=0');
641
+                    }
642
+
643
+                    return false;
644
+                });
645
+
646
+                for (const pt of payloadsWithMode0.reverse()) {
647
+                    const idx = matchingPayloadTypes.findIndex(payloadType => payloadType === pt);
648
+
649
+                    if (idx >= 0) {
650
+                        matchingPayloadTypes.splice(idx, 1);
651
+                        matchingPayloadTypes.unshift(pt);
652
+                    }
653
+                }
654
+            }
655
+
633 656
             // Call toString() on payloads to get around an issue within SDPTransform that sets
634 657
             // payloads as a number, instead of a string, when there is only one payload.
635 658
             const payloadTypes
@@ -686,7 +709,7 @@ const SDPUtil = {
686 709
                     if (codec) {
687 710
                         return codec.toLowerCase() === CodecMimeType.VP9
688 711
                             ? !item.config.includes('profile-id=0')
689
-                            : item.config.includes('profile-level-id=64');
712
+                            : !item.config.includes('profile-level-id=42');
690 713
                     }
691 714
 
692 715
                     return false;

Loading…
Cancel
Save