Преглед изворни кода

Fixes desktop sharing when used with simulcast.

master
George Politis пре 10 година
родитељ
комит
a0092b78ca
5 измењених фајлова са 279 додато и 156 уклоњено
  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 Прегледај датотеку

11
     <meta itemprop="image" content="/images/jitsilogo.png"/>
11
     <meta itemprop="image" content="/images/jitsilogo.png"/>
12
     <script src="libs/jquery-2.1.1.min.js"></script>
12
     <script src="libs/jquery-2.1.1.min.js"></script>
13
     <script src="config.js?v=5"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
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
     <script src="libs/strophe/strophe.min.js?v=1"></script>
16
     <script src="libs/strophe/strophe.min.js?v=1"></script>
17
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
17
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
18
     <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
18
     <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
22
     <script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script>
22
     <script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script>
23
     <script src="libs/strophe/strophe.jingle.session.js?v=2"></script>
23
     <script src="libs/strophe/strophe.jingle.session.js?v=2"></script>
24
     <script src="libs/strophe/strophe.util.js"></script>
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
     <script src="libs/colibri/colibri.session.js?v=1"></script>
26
     <script src="libs/colibri/colibri.session.js?v=1"></script>
27
     <script src="libs/jquery-ui.js"></script>
27
     <script src="libs/jquery-ui.js"></script>
28
     <script src="libs/rayo.js?v=1"></script>
28
     <script src="libs/rayo.js?v=1"></script>

+ 219
- 117
libs/colibri/colibri.focus.js Прегледај датотеку

551
                             console.log('setLocalDescription succeeded.');
551
                             console.log('setLocalDescription succeeded.');
552
                             // make sure our presence is updated
552
                             // make sure our presence is updated
553
                             $(document).trigger('setLocalDescription.jingle', [self.sid]);
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
                             var localSDP = new SDP(self.peerconnection.localDescription.sdp);
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
                             // now initiate sessions
557
                             // now initiate sessions
632
                             for (var i = 0; i < numparticipants; i++) {
558
                             for (var i = 0; i < numparticipants; i++) {
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
 // send a session-initiate to a new participant
678
 // send a session-initiate to a new participant
663
 ColibriFocus.prototype.initiate = function (peer, isInitiator) {
679
 ColibriFocus.prototype.initiate = function (peer, isInitiator) {
664
     var participant = this.peers.indexOf(peer);
680
     var participant = this.peers.indexOf(peer);
894
 };
910
 };
895
 
911
 
896
 // update the channel description (payload-types + dtls fp) for a participant
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
     console.log('change allocation for', this.confid);
914
     console.log('change allocation for', this.confid);
899
     var self = this;
915
     var self = this;
900
     var change = $iq({to: this.bridgejid, type: 'set'});
916
     var change = $iq({to: this.bridgejid, type: 'set'});
901
     change.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri', id: this.confid});
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
         if (!remoteSDP.media[channel])
919
         if (!remoteSDP.media[channel])
905
             continue;
920
             continue;
906
 
921
 
907
         var name = SDPUtil.parse_mid(SDPUtil.find_line(remoteSDP.media[channel], 'a=mid:'));
922
         var name = SDPUtil.parse_mid(SDPUtil.find_line(remoteSDP.media[channel], 'a=mid:'));
908
         change.c('content', {name: name});
923
         change.c('content', {name: name});
909
-        if (name !== 'data')
910
-        {
924
+        if (name !== 'data') {
911
             change.c('channel', {
925
             change.c('channel', {
912
                 id: $(this.channels[participant][channel]).attr('id'),
926
                 id: $(this.channels[participant][channel]).attr('id'),
913
                 endpoint: $(this.channels[participant][channel]).attr('endpoint'),
927
                 endpoint: $(this.channels[participant][channel]).attr('endpoint'),
914
                 expire: self.channelExpire
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
                     change.up();
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
         else
981
         else
954
         {
982
         {
960
                 port: SDPUtil.parse_sctpmap(sctpmap)[0]
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
         change.up(); // end of channel/sctpconnection
997
         change.up(); // end of channel/sctpconnection
967
         change.up(); // end of content
998
         change.up(); // end of content
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
 // tell everyone about a new participants a=ssrc lines (isadd is true)
1061
 // tell everyone about a new participants a=ssrc lines (isadd is true)
980
 // or a leaving participants a=ssrc lines
1062
 // or a leaving participants a=ssrc lines
981
 ColibriFocus.prototype.sendSSRCUpdate = function (sdpMediaSsrcs, fromJid, isadd) {
1063
 ColibriFocus.prototype.sendSSRCUpdate = function (sdpMediaSsrcs, fromJid, isadd) {
1010
     // FIXME: dirty waiting
1092
     // FIXME: dirty waiting
1011
     if (!this.peerconnection.localDescription)
1093
     if (!this.peerconnection.localDescription)
1012
     {
1094
     {
1013
-        console.warn("addSource - localDescription not ready yet")
1095
+        console.warn("addSource - localDescription not ready yet");
1014
         setTimeout(function() { self.addSource(elem, fromJid); }, 200);
1096
         setTimeout(function() { self.addSource(elem, fromJid); }, 200);
1015
         return;
1097
         return;
1016
     }
1098
     }
1031
     });
1113
     });
1032
 
1114
 
1033
     var oldRemoteSdp = new SDP(this.peerconnection.remoteDescription.sdp);
1115
     var oldRemoteSdp = new SDP(this.peerconnection.remoteDescription.sdp);
1034
-    this.modifySources(function(){
1116
+    this.modifySources(function() {
1035
         // Notify other participants about added ssrc
1117
         // Notify other participants about added ssrc
1036
         var remoteSDP = new SDP(self.peerconnection.remoteDescription.sdp);
1118
         var remoteSDP = new SDP(self.peerconnection.remoteDescription.sdp);
1037
         var newSSRCs = oldRemoteSdp.getNewMedia(remoteSDP);
1119
         var newSSRCs = oldRemoteSdp.getNewMedia(remoteSDP);
1038
         self.sendSSRCUpdate(newSSRCs, fromJid, true);
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
         var remoteSDP = new SDP(self.peerconnection.remoteDescription.sdp);
1165
         var remoteSDP = new SDP(self.peerconnection.remoteDescription.sdp);
1074
         var removedSSRCs = remoteSDP.getNewMedia(oldSDP);
1166
         var removedSSRCs = remoteSDP.getNewMedia(oldSDP);
1075
         self.sendSSRCUpdate(removedSSRCs, fromJid, false);
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
     remoteSDP.fromJingle(elem);
1186
     remoteSDP.fromJingle(elem);
1085
 
1187
 
1086
     // ACT 1: change allocation on bridge
1188
     // ACT 1: change allocation on bridge
1087
-    this.updateChannel(remoteSDP, participant);
1189
+    this.updateRemoteChannel(remoteSDP, participant);
1088
 
1190
 
1089
     // ACT 2: tell anyone else about the new SSRCs
1191
     // ACT 2: tell anyone else about the new SSRCs
1090
     this.sendSSRCUpdate(remoteSDP.getMediaSsrcMap(), session.peerjid, true);
1192
     this.sendSSRCUpdate(remoteSDP.getMediaSsrcMap(), session.peerjid, true);

+ 4
- 2
libs/strophe/strophe.jingle.adapter.js Прегледај датотеку

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

+ 8
- 6
libs/strophe/strophe.jingle.sdp.js Прегледај датотеку

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

+ 45
- 28
simulcast.js Прегледај датотеку

490
     this.logger = new SimulcastLogger('SimulcastSender', 1);
490
     this.logger = new SimulcastLogger('SimulcastSender', 1);
491
 }
491
 }
492
 
492
 
493
-SimulcastSender.prototype._localVideoSourceCache = '';
494
 SimulcastSender.prototype.displayedLocalVideoStream = null;
493
 SimulcastSender.prototype.displayedLocalVideoStream = null;
495
 
494
 
496
 SimulcastSender.prototype._generateGuid = (function () {
495
 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
 // Returns a random integer between min (included) and max (excluded)
508
 // Returns a random integer between min (included) and max (excluded)
518
 // Using Math.round() gives a non-uniform distribution!
509
 // Using Math.round() gives a non-uniform distribution!
519
 SimulcastSender.prototype._generateRandomSSRC = function () {
510
 SimulcastSender.prototype._generateRandomSSRC = function () {
521
     return Math.floor(Math.random() * (max - min)) + min;
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
     var videoSources, ssrcGroup, simSSRC, numOfSubs = 2, i, sb, msid;
546
     var videoSources, ssrcGroup, simSSRC, numOfSubs = 2, i, sb, msid;
526
 
547
 
527
     this.logger.info('Appending simulcast group...');
548
     this.logger.info('Appending simulcast group...');
557
 };
578
 };
558
 
579
 
559
 // Does the actual patching.
580
 // Does the actual patching.
560
-SimulcastSender.prototype._ensureSimulcastGroup = function (lines) {
581
+NativeSimulcastSender.prototype._ensureSimulcastGroup = function (lines) {
561
 
582
 
562
     this.logger.info('Ensuring simulcast group...');
583
     this.logger.info('Ensuring simulcast group...');
563
 
584
 
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
  * Produces a single stream with multiple tracks for local video sources.
596
  * Produces a single stream with multiple tracks for local video sources.
591
  *
597
  *
658
 NativeSimulcastSender.prototype.reverseTransformLocalDescription = function (desc) {
664
 NativeSimulcastSender.prototype.reverseTransformLocalDescription = function (desc) {
659
     var sb;
665
     var sb;
660
 
666
 
661
-    if (!desc || desc == null) {
667
+    if (!desc || desc == null || this._isUsingScreenStream) {
662
         return desc;
668
         return desc;
663
     }
669
     }
664
 
670
 
686
  */
692
  */
687
 NativeSimulcastSender.prototype.transformAnswer = function (desc) {
693
 NativeSimulcastSender.prototype.transformAnswer = function (desc) {
688
 
694
 
695
+    if (!desc || desc == null || this._isUsingScreenStream) {
696
+        return desc;
697
+    }
698
+
689
     var sb = desc.sdp.split('\r\n');
699
     var sb = desc.sdp.split('\r\n');
690
 
700
 
691
     // Even if we have enabled native simulcasting previously
701
     // Even if we have enabled native simulcasting previously
734
         this._updateRemoteMaps(sb);
744
         this._updateRemoteMaps(sb);
735
         this._cacheRemoteVideoSources(sb);
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
         this.simulcastUtils._removeSimulcastGroup(sb);
749
         this.simulcastUtils._removeSimulcastGroup(sb);
739
 
750
 
740
         if (desc.sdp.indexOf('a=ssrc-group:SIM') !== -1) {
751
         if (desc.sdp.indexOf('a=ssrc-group:SIM') !== -1) {
1189
     this.simulcastSender._setLocalVideoStreamEnabled(ssrc, enabled);
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
  * @constructor
1211
  * @constructor

Loading…
Откажи
Сачувај