Parcourir la source

Fixes desktop sharing when used with simulcast.

j8
George Politis il y a 10 ans
Parent
révision
a0092b78ca
5 fichiers modifiés avec 279 ajouts et 156 suppressions
  1. 3
    3
      index.html
  2. 219
    117
      libs/colibri/colibri.focus.js
  3. 4
    2
      libs/strophe/strophe.jingle.adapter.js
  4. 8
    6
      libs/strophe/strophe.jingle.sdp.js
  5. 45
    28
      simulcast.js

+ 3
- 3
index.html Voir le fichier

@@ -11,8 +11,8 @@
11 11
     <meta itemprop="image" content="/images/jitsilogo.png"/>
12 12
     <script src="libs/jquery-2.1.1.min.js"></script>
13 13
     <script src="config.js?v=5"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
14
-    <script src="simulcast.js?v=6"></script><!-- simulcast handling -->
15
-    <script src="libs/strophe/strophe.jingle.adapter.js?v=2"></script><!-- strophe.jingle bundles -->
14
+    <script src="simulcast.js?v=7"></script><!-- simulcast handling -->
15
+    <script src="libs/strophe/strophe.jingle.adapter.js?v=3"></script><!-- strophe.jingle bundles -->
16 16
     <script src="libs/strophe/strophe.min.js?v=1"></script>
17 17
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
18 18
     <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
@@ -22,7 +22,7 @@
22 22
     <script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script>
23 23
     <script src="libs/strophe/strophe.jingle.session.js?v=2"></script>
24 24
     <script src="libs/strophe/strophe.util.js"></script>
25
-    <script src="libs/colibri/colibri.focus.js?v=11"></script><!-- colibri focus implementation -->
25
+    <script src="libs/colibri/colibri.focus.js?v=12"></script><!-- colibri focus implementation -->
26 26
     <script src="libs/colibri/colibri.session.js?v=1"></script>
27 27
     <script src="libs/jquery-ui.js"></script>
28 28
     <script src="libs/rayo.js?v=1"></script>

+ 219
- 117
libs/colibri/colibri.focus.js Voir le fichier

@@ -551,82 +551,8 @@ ColibriFocus.prototype.createdConference = function (result) {
551 551
                             console.log('setLocalDescription succeeded.');
552 552
                             // make sure our presence is updated
553 553
                             $(document).trigger('setLocalDescription.jingle', [self.sid]);
554
-                            var elem = $iq({to: self.bridgejid, type: 'get'});
555
-                            elem.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri', id: self.confid});
556 554
                             var localSDP = new SDP(self.peerconnection.localDescription.sdp);
557
-                            localSDP.media.forEach(function (media, channel) {
558
-                                var name = SDPUtil.parse_mid(SDPUtil.find_line(media, 'a=mid:'));
559
-                                elem.c('content', {name: name});
560
-                                var mline = SDPUtil.parse_mline(media.split('\r\n')[0]);
561
-                                if (name !== 'data')
562
-                                {
563
-                                    elem.c('channel', {
564
-                                        initiator: 'true',
565
-                                        expire: self.channelExpire,
566
-                                        id: self.mychannel[channel].attr('id'),
567
-                                        endpoint: self.myMucResource
568
-                                    });
569
-
570
-                                    // signal (through COLIBRI) to the bridge
571
-                                    // the SSRC groups of the participant
572
-                                    // that plays the role of the focus
573
-                                    var ssrc_group_lines = SDPUtil.find_lines(media, 'a=ssrc-group:');
574
-                                    var idx = 0;
575
-                                    ssrc_group_lines.forEach(function(line) {
576
-                                        idx = line.indexOf(' ');
577
-                                        var semantics = line.substr(0, idx).substr(13);
578
-                                        var ssrcs = line.substr(14 + semantics.length).split(' ');
579
-                                        if (ssrcs.length != 0) {
580
-                                            elem.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
581
-                                            ssrcs.forEach(function(ssrc) {
582
-                                                elem.c('source', { ssrc: ssrc })
583
-                                                    .up();
584
-                                            });
585
-                                            elem.up();
586
-                                        }
587
-                                    });
588
-                                    // FIXME: should reuse code from .toJingle
589
-                                    for (var j = 0; j < mline.fmt.length; j++)
590
-                                    {
591
-                                        var rtpmap = SDPUtil.find_line(media, 'a=rtpmap:' + mline.fmt[j]);
592
-                                        if (rtpmap)
593
-                                        {
594
-                                            elem.c('payload-type', SDPUtil.parse_rtpmap(rtpmap));
595
-                                            elem.up();
596
-                                        }
597
-                                    }
598
-                                }
599
-                                else
600
-                                {
601
-                                    var sctpmap = SDPUtil.find_line(media, 'a=sctpmap:' + mline.fmt[0]);
602
-                                    var sctpPort = SDPUtil.parse_sctpmap(sctpmap)[0];
603
-                                    elem.c("sctpconnection",
604
-                                        {
605
-                                            initiator: 'true',
606
-                                            expire: self.channelExpire,
607
-                                            id: self.mychannel[channel].attr('id'),
608
-                                            endpoint: self.myMucResource,
609
-                                            port: sctpPort
610
-                                        }
611
-                                    );
612
-                                }
613
-
614
-                                localSDP.TransportToJingle(channel, elem);
615
-
616
-                                elem.up(); // end of channel
617
-                                elem.up(); // end of content
618
-                            });
619
-
620
-                            self.connection.sendIQ(elem,
621
-                                function (result) {
622
-                                    // ...
623
-                                },
624
-                                function (error) {
625
-                                    console.error(
626
-                                        "ERROR sending colibri message",
627
-                                        error, elem);
628
-                                }
629
-                            );
555
+                            self.updateLocalChannel(localSDP);
630 556
 
631 557
                             // now initiate sessions
632 558
                             for (var i = 0; i < numparticipants; i++) {
@@ -659,6 +585,96 @@ ColibriFocus.prototype.createdConference = function (result) {
659 585
 
660 586
 };
661 587
 
588
+ColibriFocus.prototype.updateLocalChannel = function(localSDP, parts) {
589
+    var self = this;
590
+    var elem = $iq({to: self.bridgejid, type: 'get'});
591
+    elem.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri', id: self.confid});
592
+    localSDP.media.forEach(function (media, channel) {
593
+        var name = SDPUtil.parse_mid(SDPUtil.find_line(media, 'a=mid:'));
594
+        elem.c('content', {name: name});
595
+        var mline = SDPUtil.parse_mline(media.split('\r\n')[0]);
596
+        if (name !== 'data') {
597
+            elem.c('channel', {
598
+                initiator: 'true',
599
+                expire: self.channelExpire,
600
+                id: self.mychannel[channel].attr('id'),
601
+                endpoint: self.myMucResource
602
+            });
603
+
604
+            if (!parts || parts.indexOf('sources') !== -1) {
605
+                // signal (through COLIBRI) to the bridge
606
+                // the SSRC groups of the participant
607
+                // that plays the role of the focus
608
+                var ssrc_group_lines = SDPUtil.find_lines(media, 'a=ssrc-group:');
609
+                var idx = 0;
610
+                var hasSIM = false;
611
+                ssrc_group_lines.forEach(function (line) {
612
+                    idx = line.indexOf(' ');
613
+                    var semantics = line.substr(0, idx).substr(13);
614
+                    var ssrcs = line.substr(14 + semantics.length).split(' ');
615
+                    if (ssrcs.length != 0) {
616
+                        elem.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
617
+                        ssrcs.forEach(function (ssrc) {
618
+                            elem.c('source', { ssrc: ssrc })
619
+                                .up();
620
+                        });
621
+                        elem.up();
622
+                    }
623
+                });
624
+
625
+                if (!hasSIM && name == 'video') {
626
+                    // disable simulcast with an empty ssrc-group element.
627
+                    elem.c('ssrc-group', { semantics: 'SIM', xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
628
+                    elem.up();
629
+                }
630
+            }
631
+
632
+            if (!parts || parts.indexOf('payload-type') !== -1) {
633
+                // FIXME: should reuse code from .toJingle
634
+                for (var j = 0; j < mline.fmt.length; j++) {
635
+                    var rtpmap = SDPUtil.find_line(media, 'a=rtpmap:' + mline.fmt[j]);
636
+                    if (rtpmap) {
637
+                        elem.c('payload-type', SDPUtil.parse_rtpmap(rtpmap));
638
+                        elem.up();
639
+                    }
640
+                }
641
+            }
642
+        }
643
+        else
644
+        {
645
+            var sctpmap = SDPUtil.find_line(media, 'a=sctpmap:' + mline.fmt[0]);
646
+            var sctpPort = SDPUtil.parse_sctpmap(sctpmap)[0];
647
+            elem.c("sctpconnection",
648
+                {
649
+                    initiator: 'true',
650
+                    expire: self.channelExpire,
651
+                    id: self.mychannel[channel].attr('id'),
652
+                    endpoint: self.myMucResource,
653
+                    port: sctpPort
654
+                }
655
+            );
656
+        }
657
+
658
+        if (!parts || parts.indexOf('transport') !== -1) {
659
+            localSDP.TransportToJingle(channel, elem);
660
+        }
661
+
662
+        elem.up(); // end of channel
663
+        elem.up(); // end of content
664
+    });
665
+
666
+    self.connection.sendIQ(elem,
667
+        function (result) {
668
+            // ...
669
+        },
670
+        function (error) {
671
+            console.error(
672
+                "ERROR sending colibri message",
673
+                error, elem);
674
+        }
675
+    );
676
+};
677
+
662 678
 // send a session-initiate to a new participant
663 679
 ColibriFocus.prototype.initiate = function (peer, isInitiator) {
664 680
     var participant = this.peers.indexOf(peer);
@@ -894,61 +910,73 @@ ColibriFocus.prototype.addNewParticipant = function (peer) {
894 910
 };
895 911
 
896 912
 // update the channel description (payload-types + dtls fp) for a participant
897
-ColibriFocus.prototype.updateChannel = function (remoteSDP, participant) {
913
+ColibriFocus.prototype.updateRemoteChannel = function (remoteSDP, participant, parts) {
898 914
     console.log('change allocation for', this.confid);
899 915
     var self = this;
900 916
     var change = $iq({to: this.bridgejid, type: 'set'});
901 917
     change.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri', id: this.confid});
902
-    for (channel = 0; channel < this.channels[participant].length; channel++)
903
-    {
918
+    for (channel = 0; channel < this.channels[participant].length; channel++) {
904 919
         if (!remoteSDP.media[channel])
905 920
             continue;
906 921
 
907 922
         var name = SDPUtil.parse_mid(SDPUtil.find_line(remoteSDP.media[channel], 'a=mid:'));
908 923
         change.c('content', {name: name});
909
-        if (name !== 'data')
910
-        {
924
+        if (name !== 'data') {
911 925
             change.c('channel', {
912 926
                 id: $(this.channels[participant][channel]).attr('id'),
913 927
                 endpoint: $(this.channels[participant][channel]).attr('endpoint'),
914 928
                 expire: self.channelExpire
915 929
             });
916 930
 
917
-            // signal (throught COLIBRI) to the bridge the SSRC groups of this
918
-            // participant
919
-            var ssrc_group_lines = SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc-group:');
920
-            var idx = 0;
921
-            ssrc_group_lines.forEach(function(line) {
922
-                idx = line.indexOf(' ');
923
-                var semantics = line.substr(0, idx).substr(13);
924
-                var ssrcs = line.substr(14 + semantics.length).split(' ');
925
-                if (ssrcs.length != 0) {
926
-                    change.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
927
-                    ssrcs.forEach(function(ssrc) {
928
-                        change.c('source', { ssrc: ssrc })
929
-                            .up();
930
-                    });
931
+            if (!parts || parts.indexOf('sources') !== -1) {
932
+                // signal (throught COLIBRI) to the bridge the SSRC groups of this
933
+                // participant
934
+                var ssrc_group_lines = SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc-group:');
935
+                var idx = 0;
936
+                var hasSIM = false;
937
+                ssrc_group_lines.forEach(function (line) {
938
+                    idx = line.indexOf(' ');
939
+                    var semantics = line.substr(0, idx).substr(13);
940
+                    if (semantics == 'SIM') {
941
+                        hasSIM = true;
942
+                    }
943
+                    var ssrcs = line.substr(14 + semantics.length).split(' ');
944
+                    if (ssrcs.length != 0) {
945
+                        change.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
946
+                        ssrcs.forEach(function (ssrc) {
947
+                            change.c('source', { ssrc: ssrc })
948
+                                .up();
949
+                        });
950
+                        change.up();
951
+                    }
952
+                });
953
+
954
+                if (!hasSIM && name == 'video') {
955
+                    // disable simulcast with an empty ssrc-group element.
956
+                    change.c('ssrc-group', { semantics: 'SIM', xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
931 957
                     change.up();
932 958
                 }
933
-            });
959
+            }
934 960
 
935
-            var rtpmap = SDPUtil.find_lines(remoteSDP.media[channel], 'a=rtpmap:');
936
-            rtpmap.forEach(function (val) {
937
-                // TODO: too much copy-paste
938
-                var rtpmap = SDPUtil.parse_rtpmap(val);
939
-                change.c('payload-type', rtpmap);
940
-                //
941
-                // put any 'a=fmtp:' + mline.fmt[j] lines into <param name=foo value=bar/>
942
-                /*
943
-                if (SDPUtil.find_line(remoteSDP.media[channel], 'a=fmtp:' + rtpmap.id)) {
944
-                    tmp = SDPUtil.parse_fmtp(SDPUtil.find_line(remoteSDP.media[channel], 'a=fmtp:' + rtpmap.id));
945
-                    for (var k = 0; k < tmp.length; k++) {
946
-                        change.c('parameter', tmp[k]).up();
947
-                    }
948
-                }
949
-                */
950
-                change.up();
951
-            });
961
+            if (!parts || parts.indexOf('payload-type') !== -1) {
962
+                var rtpmap = SDPUtil.find_lines(remoteSDP.media[channel], 'a=rtpmap:');
963
+                rtpmap.forEach(function (val) {
964
+                    // TODO: too much copy-paste
965
+                    var rtpmap = SDPUtil.parse_rtpmap(val);
966
+                    change.c('payload-type', rtpmap);
967
+                    //
968
+                    // put any 'a=fmtp:' + mline.fmt[j] lines into <param name=foo value=bar/>
969
+                    /*
970
+                     if (SDPUtil.find_line(remoteSDP.media[channel], 'a=fmtp:' + rtpmap.id)) {
971
+                     tmp = SDPUtil.parse_fmtp(SDPUtil.find_line(remoteSDP.media[channel], 'a=fmtp:' + rtpmap.id));
972
+                     for (var k = 0; k < tmp.length; k++) {
973
+                     change.c('parameter', tmp[k]).up();
974
+                     }
975
+                     }
976
+                     */
977
+                    change.up();
978
+                });
979
+            }
952 980
         }
953 981
         else
954 982
         {
@@ -960,8 +988,11 @@ ColibriFocus.prototype.updateChannel = function (remoteSDP, participant) {
960 988
                 port: SDPUtil.parse_sctpmap(sctpmap)[0]
961 989
             });
962 990
         }
963
-        // now add transport
964
-        remoteSDP.TransportToJingle(channel, change);
991
+
992
+        if (!parts || parts.indexOf('transport') !== -1) {
993
+            // now add transport
994
+            remoteSDP.TransportToJingle(channel, change);
995
+        }
965 996
 
966 997
         change.up(); // end of channel/sctpconnection
967 998
         change.up(); // end of content
@@ -976,6 +1007,57 @@ ColibriFocus.prototype.updateChannel = function (remoteSDP, participant) {
976 1007
     );
977 1008
 };
978 1009
 
1010
+/**
1011
+ * Switches video streams.
1012
+ * @param new_stream new stream that will be used as video of this session.
1013
+ * @param oldStream old video stream of this session.
1014
+ * @param success_callback callback executed after successful stream switch.
1015
+ */
1016
+ColibriFocus.prototype.switchStreams = function (new_stream, oldStream, success_callback) {
1017
+
1018
+    var self = this;
1019
+
1020
+    // Stop the stream to trigger onended event for old stream
1021
+    oldStream.stop();
1022
+
1023
+    // Remember SDP to figure out added/removed SSRCs
1024
+    var oldSdp = null;
1025
+    if(self.peerconnection) {
1026
+        if(self.peerconnection.localDescription) {
1027
+            oldSdp = new SDP(self.peerconnection.localDescription.sdp);
1028
+        }
1029
+        self.peerconnection.removeStream(oldStream);
1030
+        self.peerconnection.addStream(new_stream);
1031
+    }
1032
+
1033
+    self.connection.jingle.localVideo = new_stream;
1034
+
1035
+    self.connection.jingle.localStreams = [];
1036
+    self.connection.jingle.localStreams.push(self.connection.jingle.localAudio);
1037
+    self.connection.jingle.localStreams.push(self.connection.jingle.localVideo);
1038
+
1039
+    // Conference is not active
1040
+    if(!oldSdp || !self.peerconnection) {
1041
+        success_callback();
1042
+        return;
1043
+    }
1044
+
1045
+    self.peerconnection.switchstreams = true;
1046
+    self.modifySources(function() {
1047
+        console.log('modify sources done');
1048
+
1049
+        var newSdp = new SDP(self.peerconnection.localDescription.sdp);
1050
+
1051
+        // change allocation on bridge
1052
+        self.updateLocalChannel(newSdp, ['sources']);
1053
+
1054
+        console.log("SDPs", oldSdp, newSdp);
1055
+        self.notifyMySSRCUpdate(oldSdp, newSdp);
1056
+
1057
+        success_callback();
1058
+    });
1059
+};
1060
+
979 1061
 // tell everyone about a new participants a=ssrc lines (isadd is true)
980 1062
 // or a leaving participants a=ssrc lines
981 1063
 ColibriFocus.prototype.sendSSRCUpdate = function (sdpMediaSsrcs, fromJid, isadd) {
@@ -1010,7 +1092,7 @@ ColibriFocus.prototype.addSource = function (elem, fromJid) {
1010 1092
     // FIXME: dirty waiting
1011 1093
     if (!this.peerconnection.localDescription)
1012 1094
     {
1013
-        console.warn("addSource - localDescription not ready yet")
1095
+        console.warn("addSource - localDescription not ready yet");
1014 1096
         setTimeout(function() { self.addSource(elem, fromJid); }, 200);
1015 1097
         return;
1016 1098
     }
@@ -1031,11 +1113,21 @@ ColibriFocus.prototype.addSource = function (elem, fromJid) {
1031 1113
     });
1032 1114
 
1033 1115
     var oldRemoteSdp = new SDP(this.peerconnection.remoteDescription.sdp);
1034
-    this.modifySources(function(){
1116
+    this.modifySources(function() {
1035 1117
         // Notify other participants about added ssrc
1036 1118
         var remoteSDP = new SDP(self.peerconnection.remoteDescription.sdp);
1037 1119
         var newSSRCs = oldRemoteSdp.getNewMedia(remoteSDP);
1038 1120
         self.sendSSRCUpdate(newSSRCs, fromJid, true);
1121
+        // change allocation on bridge
1122
+        if (peerSsrc[1] /* video */) {
1123
+            // If the remote peer has changed its video sources, then we need to
1124
+            // update the bridge with this information, in order for the
1125
+            // simulcast manager of the remote peer to update its layers, and
1126
+            // any associated receivers to adjust to the change.
1127
+            var videoSDP = new SDP(['v=0', 'm=audio', 'a=mid:audio', peerSsrc[0]].join('\r\n') + ['m=video', 'a=mid:video', peerSsrc[1]].join('\r\n'));
1128
+            var participant = self.peers.indexOf(fromJid);
1129
+            self.updateRemoteChannel(videoSDP, participant, ['sources']);
1130
+        }
1039 1131
     });
1040 1132
 };
1041 1133
 
@@ -1073,6 +1165,16 @@ ColibriFocus.prototype.removeSource = function (elem, fromJid) {
1073 1165
         var remoteSDP = new SDP(self.peerconnection.remoteDescription.sdp);
1074 1166
         var removedSSRCs = remoteSDP.getNewMedia(oldSDP);
1075 1167
         self.sendSSRCUpdate(removedSSRCs, fromJid, false);
1168
+        // change allocation on bridge
1169
+        if (peerSsrc[1] /* video */) {
1170
+            // If the remote peer has changed its video sources, then we need to
1171
+            // update the bridge with this information, in order for the
1172
+            // simulcast manager of the remote peer to update its layers, and
1173
+            // any associated receivers to adjust to the change.
1174
+            var videoSDP = new SDP(['v=0', 'm=audio', 'a=mid:audio', peerSsrc[0]].join('\r\n') + ['m=video', 'a=mid:video', peerSsrc[1]].join('\r\n'));
1175
+            var participant = self.peers.indexOf(fromJid);
1176
+            self.updateRemoteChannel(videoSDP, participant, ['sources']);
1177
+        }
1076 1178
     });
1077 1179
 };
1078 1180
 
@@ -1084,7 +1186,7 @@ ColibriFocus.prototype.setRemoteDescription = function (session, elem, desctype)
1084 1186
     remoteSDP.fromJingle(elem);
1085 1187
 
1086 1188
     // ACT 1: change allocation on bridge
1087
-    this.updateChannel(remoteSDP, participant);
1189
+    this.updateRemoteChannel(remoteSDP, participant);
1088 1190
 
1089 1191
     // ACT 2: tell anyone else about the new SSRCs
1090 1192
     this.sendSSRCUpdate(remoteSDP.getMediaSsrcMap(), session.peerjid, true);

+ 4
- 2
libs/strophe/strophe.jingle.adapter.js Voir le fichier

@@ -140,11 +140,13 @@ if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) {
140 140
 
141 141
 TraceablePeerConnection.prototype.addStream = function (stream) {
142 142
     this.trace('addStream', stream.id);
143
+    simulcast.resetSender();
143 144
     this.peerconnection.addStream(stream);
144 145
 };
145 146
 
146 147
 TraceablePeerConnection.prototype.removeStream = function (stream) {
147 148
     this.trace('removeStream', stream.id);
149
+    simulcast.resetSender();
148 150
     this.peerconnection.removeStream(stream);
149 151
 };
150 152
 
@@ -204,7 +206,7 @@ TraceablePeerConnection.prototype.enqueueAddSsrc = function(channel, ssrcLines)
204 206
         this.addssrc[channel] = '';
205 207
     }
206 208
     this.addssrc[channel] += ssrcLines;
207
-}
209
+};
208 210
 
209 211
 TraceablePeerConnection.prototype.addSource = function (elem) {
210 212
     console.log('addssrc', new Date().getTime());
@@ -260,7 +262,7 @@ TraceablePeerConnection.prototype.enqueueRemoveSsrc = function(channel, ssrcLine
260 262
         this.removessrc[channel] = '';
261 263
     }
262 264
     this.removessrc[channel] += ssrcLines;
263
-}
265
+};
264 266
 
265 267
 TraceablePeerConnection.prototype.removeSource = function (elem) {
266 268
     console.log('removessrc', new Date().getTime());

+ 8
- 6
libs/strophe/strophe.jingle.sdp.js Voir le fichier

@@ -42,7 +42,7 @@ SDP.prototype.getMediaSsrcMap = function() {
42 42
         });
43 43
     }
44 44
     return media_ssrcs;
45
-}
45
+};
46 46
 /**
47 47
  * Returns <tt>true</tt> if this SDP contains given SSRC.
48 48
  * @param ssrc the ssrc to check.
@@ -59,7 +59,8 @@ SDP.prototype.containsSSRC = function(ssrc) {
59 59
         }
60 60
     });
61 61
     return contains;
62
-}
62
+};
63
+
63 64
 /**
64 65
  * Returns map of MediaChannel that contains only media not contained in <tt>otherSdp</tt>. Mapped by channel idx.
65 66
  * @param otherSdp the other SDP to check ssrc with.
@@ -89,7 +90,7 @@ SDP.prototype.getNewMedia = function(otherSdp) {
89 90
             }
90 91
         }
91 92
         return true;
92
-    };
93
+    }
93 94
 
94 95
     var myMedia = this.getMediaSsrcMap();
95 96
     var othersMedia = otherSdp.getMediaSsrcMap();
@@ -111,7 +112,7 @@ SDP.prototype.getNewMedia = function(otherSdp) {
111 112
                 }
112 113
                 newMedia[channelNum].ssrcs[ssrc] = othersChannel.ssrcs[ssrc];
113 114
             }
114
-        })
115
+        });
115 116
 
116 117
         // Look for new ssrc groups across the channels
117 118
         othersChannel.ssrcGroups.forEach(function(otherSsrcGroup){
@@ -120,7 +121,7 @@ SDP.prototype.getNewMedia = function(otherSdp) {
120 121
             var matched = false;
121 122
             for (var i = 0; i < myChannel.ssrcGroups.length; i++) {
122 123
                 var mySsrcGroup = myChannel.ssrcGroups[i];
123
-                if (otherSsrcGroup.semantics == mySsrcGroup
124
+                if (otherSsrcGroup.semantics == mySsrcGroup.semantics
124 125
                     && arrayEquals.apply(otherSsrcGroup.ssrcs, [mySsrcGroup.ssrcs])) {
125 126
 
126 127
                     matched = true;
@@ -140,7 +141,8 @@ SDP.prototype.getNewMedia = function(otherSdp) {
140 141
         });
141 142
     });
142 143
     return newMedia;
143
-}
144
+};
145
+
144 146
 // remove iSAC and CN from SDP
145 147
 SDP.prototype.mangle = function () {
146 148
     var i, j, mline, lines, rtpmap, newdesc;

+ 45
- 28
simulcast.js Voir le fichier

@@ -490,7 +490,6 @@ function SimulcastSender() {
490 490
     this.logger = new SimulcastLogger('SimulcastSender', 1);
491 491
 }
492 492
 
493
-SimulcastSender.prototype._localVideoSourceCache = '';
494 493
 SimulcastSender.prototype.displayedLocalVideoStream = null;
495 494
 
496 495
 SimulcastSender.prototype._generateGuid = (function () {
@@ -506,14 +505,6 @@ SimulcastSender.prototype._generateGuid = (function () {
506 505
     };
507 506
 }());
508 507
 
509
-SimulcastSender.prototype._cacheLocalVideoSources = function (lines) {
510
-    this._localVideoSourceCache = this.simulcastUtils._getVideoSources(lines);
511
-};
512
-
513
-SimulcastSender.prototype._restoreLocalVideoSources = function (lines) {
514
-    this.simulcastUtils._replaceVideoSources(lines, this._localVideoSourceCache);
515
-};
516
-
517 508
 // Returns a random integer between min (included) and max (excluded)
518 509
 // Using Math.round() gives a non-uniform distribution!
519 510
 SimulcastSender.prototype._generateRandomSSRC = function () {
@@ -521,7 +512,37 @@ SimulcastSender.prototype._generateRandomSSRC = function () {
521 512
     return Math.floor(Math.random() * (max - min)) + min;
522 513
 };
523 514
 
524
-SimulcastSender.prototype._appendSimulcastGroup = function (lines) {
515
+SimulcastSender.prototype.getLocalVideoStream = function () {
516
+    return (this.displayedLocalVideoStream != null)
517
+        ? this.displayedLocalVideoStream
518
+        // in case we have no simulcast at all, i.e. we didn't perform the GUM
519
+        : connection.jingle.localVideo;
520
+};
521
+
522
+function NativeSimulcastSender() {
523
+    SimulcastSender.call(this); // call the super constructor.
524
+}
525
+
526
+NativeSimulcastSender.prototype = Object.create(SimulcastSender.prototype);
527
+
528
+NativeSimulcastSender.prototype._localExplosionMap = {};
529
+NativeSimulcastSender.prototype._isUsingScreenStream = false;
530
+NativeSimulcastSender.prototype._localVideoSourceCache = '';
531
+
532
+NativeSimulcastSender.prototype.reset = function () {
533
+    this._localExplosionMap = {};
534
+    this._isUsingScreenStream = isUsingScreenStream;
535
+};
536
+
537
+NativeSimulcastSender.prototype._cacheLocalVideoSources = function (lines) {
538
+    this._localVideoSourceCache = this.simulcastUtils._getVideoSources(lines);
539
+};
540
+
541
+NativeSimulcastSender.prototype._restoreLocalVideoSources = function (lines) {
542
+    this.simulcastUtils._replaceVideoSources(lines, this._localVideoSourceCache);
543
+};
544
+
545
+NativeSimulcastSender.prototype._appendSimulcastGroup = function (lines) {
525 546
     var videoSources, ssrcGroup, simSSRC, numOfSubs = 2, i, sb, msid;
526 547
 
527 548
     this.logger.info('Appending simulcast group...');
@@ -557,7 +578,7 @@ SimulcastSender.prototype._appendSimulcastGroup = function (lines) {
557 578
 };
558 579
 
559 580
 // Does the actual patching.
560
-SimulcastSender.prototype._ensureSimulcastGroup = function (lines) {
581
+NativeSimulcastSender.prototype._ensureSimulcastGroup = function (lines) {
561 582
 
562 583
     this.logger.info('Ensuring simulcast group...');
563 584
 
@@ -571,21 +592,6 @@ SimulcastSender.prototype._ensureSimulcastGroup = function (lines) {
571 592
     }
572 593
 };
573 594
 
574
-SimulcastSender.prototype.getLocalVideoStream = function () {
575
-    return (this.displayedLocalVideoStream != null)
576
-        ? this.displayedLocalVideoStream
577
-        // in case we have no simulcast at all, i.e. we didn't perform the GUM
578
-        : connection.jingle.localVideo;
579
-};
580
-
581
-function NativeSimulcastSender() {
582
-    SimulcastSender.call(this); // call the super constructor.
583
-}
584
-
585
-NativeSimulcastSender.prototype = Object.create(SimulcastSender.prototype);
586
-
587
-NativeSimulcastSender.prototype._localExplosionMap = {};
588
-
589 595
 /**
590 596
  * Produces a single stream with multiple tracks for local video sources.
591 597
  *
@@ -658,7 +664,7 @@ NativeSimulcastSender.prototype.getUserMedia = function (constraints, success, e
658 664
 NativeSimulcastSender.prototype.reverseTransformLocalDescription = function (desc) {
659 665
     var sb;
660 666
 
661
-    if (!desc || desc == null) {
667
+    if (!desc || desc == null || this._isUsingScreenStream) {
662 668
         return desc;
663 669
     }
664 670
 
@@ -686,6 +692,10 @@ NativeSimulcastSender.prototype.reverseTransformLocalDescription = function (des
686 692
  */
687 693
 NativeSimulcastSender.prototype.transformAnswer = function (desc) {
688 694
 
695
+    if (!desc || desc == null || this._isUsingScreenStream) {
696
+        return desc;
697
+    }
698
+
689 699
     var sb = desc.sdp.split('\r\n');
690 700
 
691 701
     // Even if we have enabled native simulcasting previously
@@ -734,7 +744,8 @@ SimulcastReceiver.prototype.transformRemoteDescription = function (desc) {
734 744
         this._updateRemoteMaps(sb);
735 745
         this._cacheRemoteVideoSources(sb);
736 746
 
737
-        // NOTE(gp) this needs to be called after updateRemoteMaps because we need the simulcast group in the _updateRemoteMaps() method.
747
+        // NOTE(gp) this needs to be called after updateRemoteMaps because we
748
+        // need the simulcast group in the _updateRemoteMaps() method.
738 749
         this.simulcastUtils._removeSimulcastGroup(sb);
739 750
 
740 751
         if (desc.sdp.indexOf('a=ssrc-group:SIM') !== -1) {
@@ -1189,6 +1200,12 @@ SimulcastManager.prototype._setLocalVideoStreamEnabled = function(ssrc, enabled)
1189 1200
     this.simulcastSender._setLocalVideoStreamEnabled(ssrc, enabled);
1190 1201
 };
1191 1202
 
1203
+SimulcastManager.prototype.resetSender = function() {
1204
+    if (typeof this.simulcastSender.reset === 'function'){
1205
+        this.simulcastSender.reset();
1206
+    }
1207
+};
1208
+
1192 1209
 /**
1193 1210
  *
1194 1211
  * @constructor

Chargement…
Annuler
Enregistrer