Просмотр исходного кода

Narrows the gap between strophe.jingle and our code.

j8
George Politis 11 лет назад
Родитель
Сommit
1938280e27
2 измененных файлов: 211 добавлений и 264 удалений
  1. 0
    250
      libs/strophe/strophe.jingle.adapter.js
  2. 211
    14
      libs/strophe/strophe.jingle.session.js

+ 0
- 250
libs/strophe/strophe.jingle.adapter.js Просмотреть файл

@@ -7,30 +7,6 @@ function TraceablePeerConnection(ice_config, constraints) {
7 7
     this.statsinterval = null;
8 8
     this.maxstats = 0; // limit to 300 values, i.e. 5 minutes; set to 0 to disable
9 9
 
10
-    /**
11
-     * Array of ssrcs that will be added on next modifySources call.
12
-     * @type {Array}
13
-     */
14
-    this.addssrc = [];
15
-    /**
16
-     * Array of ssrcs that will be added on next modifySources call.
17
-     * @type {Array}
18
-     */
19
-    this.removessrc = [];
20
-    /**
21
-     * Pending operation that will be done during modifySources call.
22
-     * Currently 'mute'/'unmute' operations are supported.
23
-     *
24
-     * @type {String}
25
-     */
26
-    this.pendingop = null;
27
-
28
-    /**
29
-     * Flag indicates that peer connection stream have changed and modifySources should proceed.
30
-     * @type {boolean}
31
-     */
32
-    this.switchstreams = false;
33
-
34 10
     // override as desired
35 11
     this.trace = function (what, info) {
36 12
         //console.warn('WTRACE', what, info);
@@ -213,232 +189,6 @@ TraceablePeerConnection.prototype.setRemoteDescription = function (description,
213 189
      */
214 190
 };
215 191
 
216
-TraceablePeerConnection.prototype.hardMuteVideo = function (muted) {
217
-    this.pendingop = muted ? 'mute' : 'unmute';
218
-};
219
-
220
-TraceablePeerConnection.prototype.enqueueAddSsrc = function(channel, ssrcLines) {
221
-    if (!this.addssrc[channel]) {
222
-        this.addssrc[channel] = '';
223
-    }
224
-    this.addssrc[channel] += ssrcLines;
225
-};
226
-
227
-TraceablePeerConnection.prototype.addSource = function (elem) {
228
-    console.log('addssrc', new Date().getTime());
229
-    console.log('ice', this.iceConnectionState);
230
-    var sdp = new SDP(this.remoteDescription.sdp);
231
-    var mySdp = new SDP(this.peerconnection.localDescription.sdp);
232
-
233
-    var self = this;
234
-    $(elem).each(function (idx, content) {
235
-        var name = $(content).attr('name');
236
-        var lines = '';
237
-        tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
238
-            var semantics = this.getAttribute('semantics');
239
-            var ssrcs = $(this).find('>source').map(function () {
240
-                return this.getAttribute('ssrc');
241
-            }).get();
242
-
243
-            if (ssrcs.length != 0) {
244
-                lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
245
-            }
246
-        });
247
-        tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
248
-        tmp.each(function () {
249
-            var ssrc = $(this).attr('ssrc');
250
-            if(mySdp.containsSSRC(ssrc)){
251
-                /**
252
-                 * This happens when multiple participants change their streams at the same time and
253
-                 * ColibriFocus.modifySources have to wait for stable state. In the meantime multiple
254
-                 * addssrc are scheduled for update IQ. See
255
-                 */
256
-                console.warn("Got add stream request for my own ssrc: "+ssrc);
257
-                return;
258
-            }
259
-            $(this).find('>parameter').each(function () {
260
-                lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
261
-                if ($(this).attr('value') && $(this).attr('value').length)
262
-                    lines += ':' + $(this).attr('value');
263
-                lines += '\r\n';
264
-            });
265
-        });
266
-        sdp.media.forEach(function(media, idx) {
267
-            if (!SDPUtil.find_line(media, 'a=mid:' + name))
268
-                return;
269
-            sdp.media[idx] += lines;
270
-            self.enqueueAddSsrc(idx, lines);
271
-        });
272
-        sdp.raw = sdp.session + sdp.media.join('');
273
-    });
274
-};
275
-
276
-TraceablePeerConnection.prototype.enqueueRemoveSsrc = function(channel, ssrcLines) {
277
-    if (!this.removessrc[channel]){
278
-        this.removessrc[channel] = '';
279
-    }
280
-    this.removessrc[channel] += ssrcLines;
281
-};
282
-
283
-TraceablePeerConnection.prototype.removeSource = function (elem) {
284
-    console.log('removessrc', new Date().getTime());
285
-    console.log('ice', this.iceConnectionState);
286
-    var sdp = new SDP(this.remoteDescription.sdp);
287
-    var mySdp = new SDP(this.peerconnection.localDescription.sdp);
288
-
289
-    var self = this;
290
-    $(elem).each(function (idx, content) {
291
-        var name = $(content).attr('name');
292
-        var lines = '';
293
-        tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
294
-            var semantics = this.getAttribute('semantics');
295
-            var ssrcs = $(this).find('>source').map(function () {
296
-                return this.getAttribute('ssrc');
297
-            }).get();
298
-
299
-            if (ssrcs.length != 0) {
300
-                lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
301
-            }
302
-        });
303
-        tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
304
-        tmp.each(function () {
305
-            var ssrc = $(this).attr('ssrc');
306
-            // This should never happen, but can be useful for bug detection
307
-            if(mySdp.containsSSRC(ssrc)){
308
-                console.error("Got remove stream request for my own ssrc: "+ssrc);
309
-                return;
310
-            }
311
-            $(this).find('>parameter').each(function () {
312
-                lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
313
-                if ($(this).attr('value') && $(this).attr('value').length)
314
-                    lines += ':' + $(this).attr('value');
315
-                lines += '\r\n';
316
-            });
317
-        });
318
-        sdp.media.forEach(function(media, idx) {
319
-            if (!SDPUtil.find_line(media, 'a=mid:' + name))
320
-                return;
321
-            sdp.media[idx] += lines;
322
-            self.enqueueRemoveSsrc(idx, lines);
323
-        });
324
-        sdp.raw = sdp.session + sdp.media.join('');
325
-    });
326
-};
327
-
328
-TraceablePeerConnection.prototype.modifySources = function(successCallback) {
329
-    var self = this;
330
-    if (this.signalingState == 'closed') return;
331
-    if (!(this.addssrc.length || this.removessrc.length || this.pendingop !== null || this.switchstreams)){
332
-        // There is nothing to do since scheduled job might have been executed by another succeeding call
333
-        if(successCallback){
334
-            successCallback();
335
-        }
336
-        return;
337
-    }
338
-
339
-    // FIXME: this is a big hack
340
-    // https://code.google.com/p/webrtc/issues/detail?id=2688
341
-    // ^ has been fixed.
342
-    if (!(this.signalingState == 'stable' && this.iceConnectionState == 'connected')) {
343
-        console.warn('modifySources not yet', this.signalingState, this.iceConnectionState);
344
-        this.wait = true;
345
-        window.setTimeout(function() { self.modifySources(successCallback); }, 250);
346
-        return;
347
-    }
348
-    if (this.wait) {
349
-        window.setTimeout(function() { self.modifySources(successCallback); }, 2500);
350
-        this.wait = false;
351
-        return;
352
-    }
353
-
354
-    // Reset switch streams flag
355
-    this.switchstreams = false;
356
-
357
-    var sdp = new SDP(this.remoteDescription.sdp);
358
-
359
-    // add sources
360
-    this.addssrc.forEach(function(lines, idx) {
361
-        sdp.media[idx] += lines;
362
-    });
363
-    this.addssrc = [];
364
-
365
-    // remove sources
366
-    this.removessrc.forEach(function(lines, idx) {
367
-        lines = lines.split('\r\n');
368
-        lines.pop(); // remove empty last element;
369
-        lines.forEach(function(line) {
370
-            sdp.media[idx] = sdp.media[idx].replace(line + '\r\n', '');
371
-        });
372
-    });
373
-    this.removessrc = [];
374
-
375
-    // FIXME:
376
-    // this was a hack for the situation when only one peer exists
377
-    // in the conference.
378
-    // check if still required and remove
379
-    if (sdp.media[0])
380
-        sdp.media[0] = sdp.media[0].replace('a=recvonly', 'a=sendrecv');
381
-    if (sdp.media[1])
382
-        sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
383
-
384
-    sdp.raw = sdp.session + sdp.media.join('');
385
-    this.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}),
386
-        function() {
387
-
388
-            if(self.signalingState == 'closed') {
389
-                console.error("createAnswer attempt on closed state");
390
-                return;
391
-            }
392
-
393
-            self.createAnswer(
394
-                function(modifiedAnswer) {
395
-                    // change video direction, see https://github.com/jitsi/jitmeet/issues/41
396
-                    if (self.pendingop !== null) {
397
-                        var sdp = new SDP(modifiedAnswer.sdp);
398
-                        if (sdp.media.length > 1) {
399
-                            switch(self.pendingop) {
400
-                                case 'mute':
401
-                                    sdp.media[1] = sdp.media[1].replace('a=sendrecv', 'a=recvonly');
402
-                                    break;
403
-                                case 'unmute':
404
-                                    sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
405
-                                    break;
406
-                            }
407
-                            sdp.raw = sdp.session + sdp.media.join('');
408
-                            modifiedAnswer.sdp = sdp.raw;
409
-                        }
410
-                        self.pendingop = null;
411
-                    }
412
-
413
-                    // FIXME: pushing down an answer while ice connection state
414
-                    // is still checking is bad...
415
-                    //console.log(self.peerconnection.iceConnectionState);
416
-
417
-                    // trying to work around another chrome bug
418
-                    //modifiedAnswer.sdp = modifiedAnswer.sdp.replace(/a=setup:active/g, 'a=setup:actpass');
419
-                    self.setLocalDescription(modifiedAnswer,
420
-                        function() {
421
-                            //console.log('modified setLocalDescription ok');
422
-                            if(successCallback){
423
-                                successCallback();
424
-                            }
425
-                        },
426
-                        function(error) {
427
-                            console.error('modified setLocalDescription failed', error);
428
-                        }
429
-                    );
430
-                },
431
-                function(error) {
432
-                    console.error('modified answer failed', error);
433
-                }
434
-            );
435
-        },
436
-        function(error) {
437
-            console.error('modify failed', error);
438
-        }
439
-    );
440
-};
441
-
442 192
 TraceablePeerConnection.prototype.close = function () {
443 193
     this.trace('stop');
444 194
     if (this.statsinterval !== null) {

+ 211
- 14
libs/strophe/strophe.jingle.session.js Просмотреть файл

@@ -33,6 +33,11 @@ function JingleSession(me, sid, connection) {
33 33
 
34 34
     this.reason = null;
35 35
 
36
+    this.addssrc = [];
37
+    this.removessrc = [];
38
+    this.pendingop = null;
39
+    this.switchstreams = false;
40
+
36 41
     this.wait = true;
37 42
     this.localStreamsSSRC = null;
38 43
 
@@ -680,8 +685,52 @@ JingleSession.prototype.addSource = function (elem, fromJid) {
680 685
         return;
681 686
     }
682 687
 
683
-    this.peerconnection.addSource(elem);
684
-
688
+    console.log('addssrc', new Date().getTime());
689
+    console.log('ice', this.peerconnection.iceConnectionState);
690
+    var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
691
+    var mySdp = new SDP(this.peerconnection.localDescription.sdp);
692
+
693
+    $(elem).each(function (idx, content) {
694
+        var name = $(content).attr('name');
695
+        var lines = '';
696
+        tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
697
+            var semantics = this.getAttribute('semantics');
698
+            var ssrcs = $(this).find('>source').map(function () {
699
+                return this.getAttribute('ssrc');
700
+            }).get();
701
+
702
+            if (ssrcs.length != 0) {
703
+                lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
704
+            }
705
+        });
706
+        tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
707
+        tmp.each(function () {
708
+            var ssrc = $(this).attr('ssrc');
709
+            if(mySdp.containsSSRC(ssrc)){
710
+                /**
711
+                 * This happens when multiple participants change their streams at the same time and
712
+                 * ColibriFocus.modifySources have to wait for stable state. In the meantime multiple
713
+                 * addssrc are scheduled for update IQ. See
714
+                 */
715
+                console.warn("Got add stream request for my own ssrc: "+ssrc);
716
+                return;
717
+            }
718
+            $(this).find('>parameter').each(function () {
719
+                lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
720
+                if ($(this).attr('value') && $(this).attr('value').length)
721
+                    lines += ':' + $(this).attr('value');
722
+                lines += '\r\n';
723
+            });
724
+        });
725
+        sdp.media.forEach(function(media, idx) {
726
+            if (!SDPUtil.find_line(media, 'a=mid:' + name))
727
+                return;
728
+            sdp.media[idx] += lines;
729
+            if (!self.addssrc[idx]) self.addssrc[idx] = '';
730
+            self.addssrc[idx] += lines;
731
+        });
732
+        sdp.raw = sdp.session + sdp.media.join('');
733
+    });
685 734
     this.modifySources();
686 735
 };
687 736
 
@@ -701,20 +750,165 @@ JingleSession.prototype.removeSource = function (elem, fromJid) {
701 750
         return;
702 751
     }
703 752
 
704
-    this.peerconnection.removeSource(elem);
705
-
753
+    console.log('removessrc', new Date().getTime());
754
+    console.log('ice', this.peerconnection.iceConnectionState);
755
+    var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
756
+    var mySdp = new SDP(this.peerconnection.localDescription.sdp);
757
+
758
+    $(elem).each(function (idx, content) {
759
+        var name = $(content).attr('name');
760
+        var lines = '';
761
+        tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
762
+            var semantics = this.getAttribute('semantics');
763
+            var ssrcs = $(this).find('>source').map(function () {
764
+                return this.getAttribute('ssrc');
765
+            }).get();
766
+
767
+            if (ssrcs.length != 0) {
768
+                lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
769
+            }
770
+        });
771
+        tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
772
+        tmp.each(function () {
773
+            var ssrc = $(this).attr('ssrc');
774
+            // This should never happen, but can be useful for bug detection
775
+            if(mySdp.containsSSRC(ssrc)){
776
+                console.error("Got remove stream request for my own ssrc: "+ssrc);
777
+                return;
778
+            }
779
+            $(this).find('>parameter').each(function () {
780
+                lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
781
+                if ($(this).attr('value') && $(this).attr('value').length)
782
+                    lines += ':' + $(this).attr('value');
783
+                lines += '\r\n';
784
+            });
785
+        });
786
+        sdp.media.forEach(function(media, idx) {
787
+            if (!SDPUtil.find_line(media, 'a=mid:' + name))
788
+                return;
789
+            sdp.media[idx] += lines;
790
+            if (!self.removessrc[idx]) self.removessrc[idx] = '';
791
+            self.removessrc[idx] += lines;
792
+        });
793
+        sdp.raw = sdp.session + sdp.media.join('');
794
+    });
706 795
     this.modifySources();
707 796
 };
708 797
 
709 798
 JingleSession.prototype.modifySources = function (successCallback) {
710 799
     var self = this;
711
-    if(this.peerconnection)
712
-        this.peerconnection.modifySources(function(){
713
-            $(document).trigger('setLocalDescription.jingle', [self.sid]);
714
-            if(successCallback) {
715
-                successCallback();
716
-            }
800
+    if (this.peerconnection.signalingState == 'closed') return;
801
+    if (!(this.addssrc.length || this.removessrc.length || this.pendingop !== null || this.switchstreams)){
802
+        // There is nothing to do since scheduled job might have been executed by another succeeding call
803
+        $(document).trigger('setLocalDescription.jingle', [self.sid]);
804
+        if(successCallback){
805
+            successCallback();
806
+        }
807
+        return;
808
+    }
809
+
810
+    // FIXME: this is a big hack
811
+    // https://code.google.com/p/webrtc/issues/detail?id=2688
812
+    // ^ has been fixed.
813
+    if (!(this.peerconnection.signalingState == 'stable' && this.peerconnection.iceConnectionState == 'connected')) {
814
+        console.warn('modifySources not yet', this.peerconnection.signalingState, this.peerconnection.iceConnectionState);
815
+        this.wait = true;
816
+        window.setTimeout(function() { self.modifySources(successCallback); }, 250);
817
+        return;
818
+    }
819
+    if (this.wait) {
820
+        window.setTimeout(function() { self.modifySources(successCallback); }, 2500);
821
+        this.wait = false;
822
+        return;
823
+    }
824
+
825
+    // Reset switch streams flag
826
+    this.switchstreams = false;
827
+
828
+    var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
829
+
830
+    // add sources
831
+    this.addssrc.forEach(function(lines, idx) {
832
+        sdp.media[idx] += lines;
833
+    });
834
+    this.addssrc = [];
835
+
836
+    // remove sources
837
+    this.removessrc.forEach(function(lines, idx) {
838
+        lines = lines.split('\r\n');
839
+        lines.pop(); // remove empty last element;
840
+        lines.forEach(function(line) {
841
+            sdp.media[idx] = sdp.media[idx].replace(line + '\r\n', '');
717 842
         });
843
+    });
844
+    this.removessrc = [];
845
+
846
+    // FIXME:
847
+    // this was a hack for the situation when only one peer exists
848
+    // in the conference.
849
+    // check if still required and remove
850
+    if (sdp.media[0])
851
+        sdp.media[0] = sdp.media[0].replace('a=recvonly', 'a=sendrecv');
852
+    if (sdp.media[1])
853
+        sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
854
+
855
+    sdp.raw = sdp.session + sdp.media.join('');
856
+    this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}),
857
+        function() {
858
+
859
+            if(self.signalingState == 'closed') {
860
+                console.error("createAnswer attempt on closed state");
861
+                return;
862
+            }
863
+
864
+            self.peerconnection.createAnswer(
865
+                function(modifiedAnswer) {
866
+                    // change video direction, see https://github.com/jitsi/jitmeet/issues/41
867
+                    if (self.pendingop !== null) {
868
+                        var sdp = new SDP(modifiedAnswer.sdp);
869
+                        if (sdp.media.length > 1) {
870
+                            switch(self.pendingop) {
871
+                                case 'mute':
872
+                                    sdp.media[1] = sdp.media[1].replace('a=sendrecv', 'a=recvonly');
873
+                                    break;
874
+                                case 'unmute':
875
+                                    sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
876
+                                    break;
877
+                            }
878
+                            sdp.raw = sdp.session + sdp.media.join('');
879
+                            modifiedAnswer.sdp = sdp.raw;
880
+                        }
881
+                        self.pendingop = null;
882
+                    }
883
+
884
+                    // FIXME: pushing down an answer while ice connection state
885
+                    // is still checking is bad...
886
+                    //console.log(self.peerconnection.iceConnectionState);
887
+
888
+                    // trying to work around another chrome bug
889
+                    //modifiedAnswer.sdp = modifiedAnswer.sdp.replace(/a=setup:active/g, 'a=setup:actpass');
890
+                    self.peerconnection.setLocalDescription(modifiedAnswer,
891
+                        function() {
892
+                            //console.log('modified setLocalDescription ok');
893
+                            $(document).trigger('setLocalDescription.jingle', [self.sid]);
894
+                            if(successCallback){
895
+                                successCallback();
896
+                            }
897
+                        },
898
+                        function(error) {
899
+                            console.error('modified setLocalDescription failed', error);
900
+                        }
901
+                    );
902
+                },
903
+                function(error) {
904
+                    console.error('modified answer failed', error);
905
+                }
906
+            );
907
+        },
908
+        function(error) {
909
+            console.error('modify failed', error);
910
+        }
911
+    );
718 912
 };
719 913
 
720 914
 /**
@@ -755,7 +949,7 @@ JingleSession.prototype.switchStreams = function (new_stream, oldStream, success
755 949
         return;
756 950
     }
757 951
 
758
-    self.peerconnection.switchstreams = true;
952
+    self.switchstreams = true;
759 953
     self.modifySources(function() {
760 954
         console.log('modify sources done');
761 955
 
@@ -961,9 +1155,7 @@ JingleSession.prototype.setVideoMute = function (mute, callback, options) {
961 1155
             tracks[i].enabled = !mute;
962 1156
         }
963 1157
 
964
-        if (this.peerconnection) {
965
-            this.peerconnection.hardMuteVideo(mute);
966
-        }
1158
+        this.hardMuteVideo(mute);
967 1159
 
968 1160
         this.modifySources(callback(mute));
969 1161
     }
@@ -975,6 +1167,10 @@ JingleSession.prototype.toggleVideoMute = function (callback) {
975 1167
     setVideoMute(isVideoMute(), callback);
976 1168
 };
977 1169
 
1170
+JingleSession.prototype.hardMuteVideo = function (muted) {
1171
+    this.pendingop = muted ? 'mute' : 'unmute';
1172
+};
1173
+
978 1174
 JingleSession.prototype.sendMute = function (muted, content) {
979 1175
     var info = $iq({to: this.peerjid,
980 1176
         type: 'set'})
@@ -1046,3 +1242,4 @@ JingleSession.prototype.getStats = function (interval) {
1046 1242
     }, interval || 3000);
1047 1243
     return this.statsinterval;
1048 1244
 };
1245
+

Загрузка…
Отмена
Сохранить