浏览代码

feat(h264): add ability to disable H.264 (#610)

This is performed by stripping all traces of H.264 from the local SDP before
passing it to `setLocalDescription`.
dev1
Saúl Ibarra Corretgé 8 年前
父节点
当前提交
1387e283d4
共有 6 个文件被更改,包括 86 次插入4 次删除
  1. 1
    0
      doc/API.md
  2. 2
    0
      modules/RTC/RTC.js
  3. 10
    3
      modules/RTC/TraceablePeerConnection.js
  4. 5
    1
      modules/xmpp/JingleSessionPC.js
  5. 55
    0
      modules/xmpp/SDPUtil.js
  6. 13
    0
      modules/xmpp/SDPUtil.spec.js

+ 1
- 0
doc/API.md 查看文件

@@ -56,6 +56,7 @@ The ```options``` parameter is JS object with the following properties:
56 56
     - `callStatsCustomScriptUrl` - (optional) custom url to access callstats client script
57 57
     - `callStatsConfIDNamespace` - (optional) a namespace to prepend the callstats conference ID with. Defaults to the window.location.hostname
58 58
     - `disableRtx` - (optional) boolean property (default to false).  Enables/disable the use of RTX.
59
+    - `disableH264` - (optional) boolean property (default to false).  If enabled, strips the H.264 codec from the local SDP.
59 60
     - `preferH264` - (optional) boolean property (default to false).  Enables/disable preferring the first instance of an h264 codec in an offer by moving it to the front of the codec list.
60 61
 
61 62
 * ```JitsiMeetJS.JitsiConnection``` - the ```JitsiConnection``` constructor. You can use that to create new server connection.

+ 2
- 0
modules/RTC/RTC.js 查看文件

@@ -374,6 +374,8 @@ export default class RTC extends Listenable {
374 374
      *      the simulcast.
375 375
      * @param {boolean} options.disableRtx If set to 'true' will disable the
376 376
      *      RTX.
377
+     * @param {boolean} options.disableH264 If set to 'true' H264 will be
378
+     *      disabled by removing it from the SDP.
377 379
      * @param {boolean} options.preferH264 If set to 'true' H264 will be
378 380
      *      preferred over other video codecs.
379 381
      * @return {TraceablePeerConnection}

+ 10
- 3
modules/RTC/TraceablePeerConnection.js 查看文件

@@ -45,6 +45,8 @@ const SIM_LAYER_RIDS = [ SIM_LAYER_1_RID, SIM_LAYER_2_RID, SIM_LAYER_3_RID ];
45 45
  * @param {boolean} options.disableRtx if set to 'true' will disable the RTX
46 46
  * @param {boolean} options.enableFirefoxSimulcast if set to 'true' will enable
47 47
  * experimental simulcast support on Firefox.
48
+ * @param {boolean} options.disableH264 If set to 'true' H264 will be
49
+ *      disabled by removing it from the SDP.
48 50
  * @param {boolean} options.preferH264 if set to 'true' H264 will be preferred
49 51
  * over other video codecs.
50 52
  *
@@ -1572,14 +1574,19 @@ TraceablePeerConnection.prototype.setLocalDescription = function(
1572 1574
 
1573 1575
     this.trace('setLocalDescription::preTransform', dumpSDP(localSdp));
1574 1576
 
1575
-    if (this.options.preferH264) {
1577
+    if (this.options.disableH264 || this.options.preferH264) {
1576 1578
         const parsedSdp = transform.parse(localSdp.sdp);
1577 1579
         const videoMLine = parsedSdp.media.find(m => m.type === 'video');
1578 1580
 
1579
-        SDPUtil.preferVideoCodec(videoMLine, 'h264');
1581
+        if (this.options.disableH264) {
1582
+            SDPUtil.stripVideoCodec(videoMLine, 'h264');
1583
+        } else {
1584
+            SDPUtil.preferVideoCodec(videoMLine, 'h264');
1585
+        }
1586
+
1580 1587
         localSdp.sdp = transform.write(parsedSdp);
1581 1588
 
1582
-        this.trace('setLocalDescription::postTransform (preferH264)',
1589
+        this.trace('setLocalDescription::postTransform (H264)',
1583 1590
             dumpSDP(localSdp));
1584 1591
     }
1585 1592
 

+ 5
- 1
modules/xmpp/JingleSessionPC.js 查看文件

@@ -247,6 +247,8 @@ export default class JingleSessionPC extends JingleSession {
247 247
                     // simulcast needs to be disabled for P2P (121) calls
248 248
                     disableSimulcast: true,
249 249
                     disableRtx: this.room.options.disableRtx,
250
+                    disableH264: this.room.options.p2p
251
+                        && this.room.options.p2p.disableH264,
250 252
                     preferH264: this.room.options.p2p
251 253
                         && this.room.options.p2p.preferH264
252 254
                 });
@@ -259,8 +261,10 @@ export default class JingleSessionPC extends JingleSession {
259 261
                     // H264 does not support simulcast, so it needs to be
260 262
                     // disabled.
261 263
                     disableSimulcast: this.room.options.disableSimulcast
262
-                        || this.room.options.preferH264,
264
+                        || (this.room.options.preferH264
265
+                            && !this.room.options.disableH264),
263 266
                     disableRtx: this.room.options.disableRtx,
267
+                    disableH264: this.room.options.disableH264,
264 268
                     preferH264: this.room.options.preferH264,
265 269
                     enableFirefoxSimulcast: this.room.options.testing
266 270
                         && this.room.options.testing.enableFirefoxSimulcast

+ 55
- 0
modules/xmpp/SDPUtil.js 查看文件

@@ -595,6 +595,61 @@ const SDPUtil = {
595 595
             payloadTypes.unshift(payloadType);
596 596
             videoMLine.payloads = payloadTypes.join(' ');
597 597
         }
598
+    },
599
+
600
+    /**
601
+     * Strips the given codec from the given mline. All related RTX payload
602
+     * types are also stripped. If the resulting mline would have no codecs,
603
+     * it's disabled.
604
+     *
605
+     * @param {object} videoMLine the video mline object from an sdp as parsed
606
+     * by transform.parse.
607
+     * @param {string} codecName the name of the codec which will be stripped.
608
+     */
609
+    stripVideoCodec(videoMLine, codecName) {
610
+        if (!codecName) {
611
+            return;
612
+        }
613
+
614
+        const removePts = [];
615
+
616
+        for (const rtp of videoMLine.rtp) {
617
+            if (rtp.codec
618
+                && rtp.codec.toLowerCase() === codecName.toLowerCase()) {
619
+                removePts.push(rtp.payload);
620
+            }
621
+        }
622
+
623
+        if (removePts.length > 0) {
624
+            // We also need to remove the payload types that are related to RTX
625
+            // for the codecs we want to disable.
626
+            const rtxApts = removePts.map(item => `apt=${item}`);
627
+            const rtxPts = videoMLine.fmtp.filter(
628
+                item => rtxApts.indexOf(item.config) !== -1);
629
+
630
+            removePts.push(...rtxPts.map(item => item.payload));
631
+
632
+            const allPts = videoMLine.payloads.split(' ').map(Number);
633
+            const keepPts = allPts.filter(pt => removePts.indexOf(pt) === -1);
634
+
635
+            if (keepPts.length === 0) {
636
+                // There are no other video codecs, disable the stream.
637
+                videoMLine.port = 0;
638
+                videoMLine.direction = 'inactive';
639
+                videoMLine.payloads = '*';
640
+            } else {
641
+                videoMLine.payloads = keepPts.join(' ');
642
+            }
643
+
644
+            videoMLine.rtp = videoMLine.rtp.filter(
645
+                item => keepPts.indexOf(item.payload) !== -1);
646
+            videoMLine.fmtp = videoMLine.fmtp.filter(
647
+                item => keepPts.indexOf(item.payload) !== -1);
648
+            if (videoMLine.rtcpFb) {
649
+                videoMLine.rtcpFb = videoMLine.rtcpFb.filter(
650
+                    item => keepPts.indexOf(item.payload) !== -1);
651
+            }
652
+        }
598 653
     }
599 654
 };
600 655
 

+ 13
- 0
modules/xmpp/SDPUtil.spec.js 查看文件

@@ -22,4 +22,17 @@ describe('SDPUtil', () => {
22 22
             expect(newPayloadTypesOrder[0]).toEqual(126);
23 23
         });
24 24
     });
25
+
26
+    describe('stripVideoCodec', () => {
27
+        it('should remove a codec', () => {
28
+            const sdp = SampleSdpStrings.multiCodecVideoSdp;
29
+            const videoMLine = sdp.media.find(m => m.type === 'video');
30
+
31
+            SDPUtil.stripVideoCodec(videoMLine, 'H264');
32
+            const newPayloadTypes = videoMLine.payloads.split(' ').map(Number);
33
+
34
+            expect(newPayloadTypes.length).toEqual(1);
35
+            expect(newPayloadTypes[0]).toEqual(100);
36
+        });
37
+    });
25 38
 });

正在加载...
取消
保存