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

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

@@ -1,8 +1,21 @@
1 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 20
  1. Stores the SSRC of the first video stream created by
8 21
    a) scanning Jingle session-accept/session-invite for existing video SSRC
@@ -33,6 +46,18 @@ var isEnabled = !RTCBrowserType.isFirefox();
33 46
  */
34 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 62
  * Method removes <source> element which describes <tt>localVideoSSRC</tt>
38 63
  * from given Jingle IQ.
@@ -79,21 +104,41 @@ var storeLocalVideoSSRC = function (jingleIq) {
79 104
         $(jingleIq.tree())
80 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 143
      * Method must be called before 'session-initiate' or 'session-invite' is
99 144
      * sent. Scans the IQ for local video SSRC and stores it if detected.
@@ -144,6 +189,25 @@ var LocalVideoSSRCHack = {
144 189
                         new RegExp('a=ssrc:' + newSSRC, 'g'),
145 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 212
         return localDescription;
149 213
     },
@@ -196,4 +260,4 @@ var LocalVideoSSRCHack = {
196 260
     }
197 261
 };
198 262
 
199
-module.exports = LocalVideoSSRCHack;
263
+module.exports = LocalSSRCReplacement;

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

@@ -1,7 +1,7 @@
1 1
 var RTC = require('../RTC/RTC');
2 2
 var RTCBrowserType = require("../RTC/RTCBrowserType.js");
3 3
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
4
-var VideoSSRCHack = require("./VideoSSRCHack");
4
+var SSRCReplacement = require("./LocalSSRCReplacement");
5 5
 
6 6
 function TraceablePeerConnection(ice_config, constraints, session) {
7 7
     var self = this;
@@ -213,7 +213,7 @@ if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) {
213 213
         function() {
214 214
             var desc = this.peerconnection.localDescription;
215 215
 
216
-            desc = VideoSSRCHack.mungeLocalVideoSSRC(desc);
216
+            desc = SSRCReplacement.mungeLocalVideoSSRC(desc);
217 217
             
218 218
             this.trace('getLocalDescription::preTransform', dumpSDP(desc));
219 219
 
@@ -372,7 +372,7 @@ TraceablePeerConnection.prototype.createOffer
372 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 377
             if (config.enableSimulcast && self.simulcast.isSupported()) {
378 378
                 offer = self.simulcast.mungeLocalDescription(offer);
@@ -402,7 +402,7 @@ TraceablePeerConnection.prototype.createAnswer
402 402
             }
403 403
 
404 404
             // munge local video SSRC
405
-            answer = VideoSSRCHack.mungeLocalVideoSSRC(answer);
405
+            answer = SSRCReplacement.mungeLocalVideoSSRC(answer);
406 406
 
407 407
             if (config.enableSimulcast && self.simulcast.isSupported()) {
408 408
                 answer = self.simulcast.mungeLocalDescription(answer);

Loading…
Cancel
Save