Browse Source

Fixes SSRC=1 issue. Renames VideoSSRCHack to LocalSSRCReplacement.

master
paweldomas 10 years ago
parent
commit
fb875423a9

+ 7
- 7
modules/xmpp/JingleSession.js View File

7
 var transform = require("sdp-transform");
7
 var transform = require("sdp-transform");
8
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
8
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
9
 var RTCBrowserType = require("../RTC/RTCBrowserType");
9
 var RTCBrowserType = require("../RTC/RTCBrowserType");
10
-var VideoSSRCHack = require("./VideoSSRCHack");
10
+var SSRCReplacement = require("./LocalSSRCReplacement");
11
 
11
 
12
 // Jingle stuff
12
 // Jingle stuff
13
 function JingleSession(me, sid, connection, service, eventEmitter) {
13
 function JingleSession(me, sid, connection, service, eventEmitter) {
254
             //console.log('setLocalDescription success');
254
             //console.log('setLocalDescription success');
255
             self.setLocalDescription();
255
             self.setLocalDescription();
256
 
256
 
257
-            VideoSSRCHack.processSessionInit(accept);
257
+            SSRCReplacement.processSessionInit(accept);
258
 
258
 
259
             self.connection.sendIQ(accept,
259
             self.connection.sendIQ(accept,
260
                 function () {
260
                 function () {
348
                     self.initiator == self.me ? 'initiator' : 'responder',
348
                     self.initiator == self.me ? 'initiator' : 'responder',
349
                     ssrc);
349
                     ssrc);
350
 
350
 
351
-                VideoSSRCHack.processSessionInit(init);
351
+                SSRCReplacement.processSessionInit(init);
352
 
352
 
353
                 self.connection.sendIQ(init,
353
                 self.connection.sendIQ(init,
354
                     function () {
354
                     function () {
467
             this.initiator == this.me ? 'initiator' : 'responder',
467
             this.initiator == this.me ? 'initiator' : 'responder',
468
             this.localStreamsSSRC);
468
             this.localStreamsSSRC);
469
 
469
 
470
-        VideoSSRCHack.processSessionInit(init);
470
+        SSRCReplacement.processSessionInit(init);
471
 
471
 
472
         self.connection.sendIQ(init,
472
         self.connection.sendIQ(init,
473
             function () {
473
             function () {
733
                     self.initiator == self.me ? 'initiator' : 'responder',
733
                     self.initiator == self.me ? 'initiator' : 'responder',
734
                     ssrcs);
734
                     ssrcs);
735
 
735
 
736
-                VideoSSRCHack.processSessionInit(accept);
736
+                SSRCReplacement.processSessionInit(accept);
737
 
737
 
738
                 self.connection.sendIQ(accept,
738
                 self.connection.sendIQ(accept,
739
                     function () {
739
                     function () {
1135
     // Let 'source-remove' IQ through the hack and see if we're allowed to send
1135
     // Let 'source-remove' IQ through the hack and see if we're allowed to send
1136
     // it in the current form
1136
     // it in the current form
1137
     if (removed)
1137
     if (removed)
1138
-        remove = VideoSSRCHack.processSourceRemove(remove);
1138
+        remove = SSRCReplacement.processSourceRemove(remove);
1139
 
1139
 
1140
     if (removed && remove) {
1140
     if (removed && remove) {
1141
         console.info("Sending source-remove", remove);
1141
         console.info("Sending source-remove", remove);
1166
     // Let 'source-add' IQ through the hack and see if we're allowed to send
1166
     // Let 'source-add' IQ through the hack and see if we're allowed to send
1167
     // it in the current form
1167
     // it in the current form
1168
     if (added)
1168
     if (added)
1169
-        add = VideoSSRCHack.processSourceAdd(add);
1169
+        add = SSRCReplacement.processSourceAdd(add);
1170
 
1170
 
1171
     if (added && add) {
1171
     if (added && add) {
1172
         console.info("Sending source-add", add);
1172
         console.info("Sending source-add", add);

modules/xmpp/VideoSSRCHack.js → modules/xmpp/LocalSSRCReplacement.js View File

1
 /* global $ */
1
 /* global $ */
2
 
2
 
3
 /*
3
 /*
4
- The purpose of this hack is to re-use SSRC of first video stream ever created
5
- for any video streams created later on. In order to do that this hack:
4
+ Here we do modifications of local video SSRCs. There are 2 situations we have
5
+ to handle:
6
+
7
+ 1. We generate SSRC for local recvonly video stream. This is the case when we
8
+    have no local camera and it is not generated automatically, but SSRC=1 is
9
+    used implicitly. If that happens RTCP packets will be dropped by the JVB
10
+    and we won't be able to request video key frames correctly.
11
+
12
+ 2. A hack to re-use SSRC of the first video stream for any new stream created
13
+    in future. It turned out that Chrome may keep on using the SSRC of removed
14
+    video stream in RTCP even though a new one has been created. So we just
15
+    want to avoid that by re-using it. Jingle 'source-remove'/'source-add'
16
+    notifications are blocked once first video SSRC is advertised to the focus.
17
+
18
+ What this hack does:
6
 
19
 
7
  1. Stores the SSRC of the first video stream created by
20
  1. Stores the SSRC of the first video stream created by
8
    a) scanning Jingle session-accept/session-invite for existing video SSRC
21
    a) scanning Jingle session-accept/session-invite for existing video SSRC
33
  */
46
  */
34
 var localVideoSSRC;
47
 var localVideoSSRC;
35
 
48
 
49
+/**
50
+ * SSRC used for recvonly video stream when we have no local camera.
51
+ * This is in order to tell Chrome what SSRC should be used in RTCP requests
52
+ * instead of 1.
53
+ */
54
+var localRecvOnlySSRC;
55
+
56
+/**
57
+ * cname for <tt>localRecvOnlySSRC</tt>
58
+ */
59
+var localRecvOnlyCName;
60
+
36
 /**
61
 /**
37
  * Method removes <source> element which describes <tt>localVideoSSRC</tt>
62
  * Method removes <source> element which describes <tt>localVideoSSRC</tt>
38
  * from given Jingle IQ.
63
  * from given Jingle IQ.
79
         $(jingleIq.tree())
104
         $(jingleIq.tree())
80
             .find('>jingle>content[name="video"]>description>source');
105
             .find('>jingle>content[name="video"]>description>source');
81
 
106
 
82
-    console.info('Video desc: ', videoSSRCs);
83
-    if (!videoSSRCs.length)
84
-        return;
85
-
86
-    var ssrc = videoSSRCs.attr('ssrc');
87
-    if (ssrc) {
88
-        localVideoSSRC = ssrc;
89
-        console.info(
90
-            'Stored local video SSRC for future re-use: ' + localVideoSSRC);
91
-    } else {
92
-        console.error('No "ssrc" attribute present in <source> element');
93
-    }
107
+    videoSSRCs.each(function (idx, ssrcElem) {
108
+        if (localVideoSSRC)
109
+            return;
110
+        // We consider SSRC real only if it has msid attribute
111
+        // recvonly streams in FF do not have it as well as local SSRCs
112
+        // we generate for recvonly streams in Chrome
113
+        var ssrSel = $(ssrcElem);
114
+        var msid = ssrSel.find('>parameter[name="msid"]');
115
+        if (msid.length) {
116
+            var ssrcVal = ssrSel.attr('ssrc');
117
+            if (ssrcVal) {
118
+                localVideoSSRC = ssrcVal;
119
+                console.info('Stored local video SSRC' +
120
+                             ' for future re-use: ' + localVideoSSRC);
121
+            }
122
+        }
123
+    });
94
 };
124
 };
95
 
125
 
96
-var LocalVideoSSRCHack = {
126
+/**
127
+ * Generates new SSRC for local video recvonly stream.
128
+ * FIXME what about eventual SSRC collision ?
129
+ */
130
+function generateRecvonlySSRC() {
131
+    //
132
+    localRecvOnlySSRC =
133
+        Math.random().toString(10).substring(2, 11);
134
+    localRecvOnlyCName =
135
+        Math.random().toString(36).substring(2);
136
+    console.info(
137
+        "Generated local recvonly SSRC: " + localRecvOnlySSRC +
138
+        ", cname: " + localRecvOnlyCName);
139
+}
140
+
141
+var LocalSSRCReplacement = {
97
     /**
142
     /**
98
      * Method must be called before 'session-initiate' or 'session-invite' is
143
      * Method must be called before 'session-initiate' or 'session-invite' is
99
      * sent. Scans the IQ for local video SSRC and stores it if detected.
144
      * sent. Scans the IQ for local video SSRC and stores it if detected.
144
                         new RegExp('a=ssrc:' + newSSRC, 'g'),
189
                         new RegExp('a=ssrc:' + newSSRC, 'g'),
145
                         'a=ssrc:' + localVideoSSRC);
190
                         'a=ssrc:' + localVideoSSRC);
146
             }
191
             }
192
+        } else {
193
+            // Make sure we have any SSRC for recvonly video stream
194
+            var sdp = new SDP(localDescription.sdp);
195
+
196
+            if (sdp.media[1] && sdp.media[1].indexOf('a=ssrc:') === -1 &&
197
+                sdp.media[1].indexOf('a=recvonly') !== -1) {
198
+
199
+                if (!localRecvOnlySSRC) {
200
+                    generateRecvonlySSRC();
201
+                }
202
+
203
+                console.info('No SSRC in video recvonly stream' +
204
+                             ' - adding SSRC: ' + localRecvOnlySSRC);
205
+
206
+                sdp.media[1] += 'a=ssrc:' + localRecvOnlySSRC +
207
+                                ' cname:' + localRecvOnlyCName + '\r\n';
208
+
209
+                localDescription.sdp = sdp.session + sdp.media.join('');
210
+            }
147
         }
211
         }
148
         return localDescription;
212
         return localDescription;
149
     },
213
     },
196
     }
260
     }
197
 };
261
 };
198
 
262
 
199
-module.exports = LocalVideoSSRCHack;
263
+module.exports = LocalSSRCReplacement;

+ 4
- 4
modules/xmpp/TraceablePeerConnection.js View File

1
 var RTC = require('../RTC/RTC');
1
 var RTC = require('../RTC/RTC');
2
 var RTCBrowserType = require("../RTC/RTCBrowserType.js");
2
 var RTCBrowserType = require("../RTC/RTCBrowserType.js");
3
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
3
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
4
-var VideoSSRCHack = require("./VideoSSRCHack");
4
+var SSRCReplacement = require("./LocalSSRCReplacement");
5
 
5
 
6
 function TraceablePeerConnection(ice_config, constraints, session) {
6
 function TraceablePeerConnection(ice_config, constraints, session) {
7
     var self = this;
7
     var self = this;
213
         function() {
213
         function() {
214
             var desc = this.peerconnection.localDescription;
214
             var desc = this.peerconnection.localDescription;
215
 
215
 
216
-            desc = VideoSSRCHack.mungeLocalVideoSSRC(desc);
216
+            desc = SSRCReplacement.mungeLocalVideoSSRC(desc);
217
             
217
             
218
             this.trace('getLocalDescription::preTransform', dumpSDP(desc));
218
             this.trace('getLocalDescription::preTransform', dumpSDP(desc));
219
 
219
 
372
                 self.trace('createOfferOnSuccess::postTransform (Plan B)', dumpSDP(offer));
372
                 self.trace('createOfferOnSuccess::postTransform (Plan B)', dumpSDP(offer));
373
             }
373
             }
374
 
374
 
375
-            offer = VideoSSRCHack.mungeLocalVideoSSRC(offer);
375
+            offer = SSRCReplacement.mungeLocalVideoSSRC(offer);
376
 
376
 
377
             if (config.enableSimulcast && self.simulcast.isSupported()) {
377
             if (config.enableSimulcast && self.simulcast.isSupported()) {
378
                 offer = self.simulcast.mungeLocalDescription(offer);
378
                 offer = self.simulcast.mungeLocalDescription(offer);
402
             }
402
             }
403
 
403
 
404
             // munge local video SSRC
404
             // munge local video SSRC
405
-            answer = VideoSSRCHack.mungeLocalVideoSSRC(answer);
405
+            answer = SSRCReplacement.mungeLocalVideoSSRC(answer);
406
 
406
 
407
             if (config.enableSimulcast && self.simulcast.isSupported()) {
407
             if (config.enableSimulcast && self.simulcast.isSupported()) {
408
                 answer = self.simulcast.mungeLocalDescription(answer);
408
                 answer = self.simulcast.mungeLocalDescription(answer);

Loading…
Cancel
Save