|
@@ -3,7 +3,10 @@ var VideoLayout = (function (my) {
|
3
|
3
|
var currentDominantSpeaker = null;
|
4
|
4
|
var lastNCount = config.channelLastN;
|
5
|
5
|
var lastNEndpointsCache = [];
|
6
|
|
- var largeVideoNewSrc = '';
|
|
6
|
+ var largeVideoState = {
|
|
7
|
+ updateInProgress: false,
|
|
8
|
+ newSrc: ''
|
|
9
|
+ };
|
7
|
10
|
|
8
|
11
|
my.changeLocalAudio = function(stream) {
|
9
|
12
|
connection.jingle.localAudio = stream;
|
|
@@ -66,7 +69,9 @@ var VideoLayout = (function (my) {
|
66
|
69
|
localVideoSelector.addClass("flipVideoX");
|
67
|
70
|
}
|
68
|
71
|
// Attach WebRTC stream
|
69
|
|
- RTC.attachMediaStream(localVideoSelector, stream);
|
|
72
|
+ var simulcast = new Simulcast();
|
|
73
|
+ var videoStream = simulcast.getLocalVideoStream();
|
|
74
|
+ RTC.attachMediaStream(localVideoSelector, videoStream);
|
70
|
75
|
|
71
|
76
|
localVideoSrc = localVideo.src;
|
72
|
77
|
|
|
@@ -114,68 +119,91 @@ var VideoLayout = (function (my) {
|
114
|
119
|
console.log('hover in', newSrc);
|
115
|
120
|
|
116
|
121
|
if ($('#largeVideo').attr('src') != newSrc) {
|
117
|
|
- largeVideoNewSrc = newSrc;
|
118
|
|
-
|
119
|
|
- var isVisible = $('#largeVideo').is(':visible');
|
120
|
122
|
|
121
|
|
- // we need this here because after the fade the videoSrc may have
|
122
|
|
- // changed.
|
123
|
|
- var isDesktop = isVideoSrcDesktop(newSrc);
|
|
123
|
+ // Due to the simulcast the localVideoSrc may have changed when the
|
|
124
|
+ // fadeOut event triggers. In that case the getJidFromVideoSrc and
|
|
125
|
+ // isVideoSrcDesktop methods will not function correctly.
|
|
126
|
+ //
|
|
127
|
+ // Also, again due to the simulcast, the updateLargeVideo method can
|
|
128
|
+ // be called multiple times almost simultaneously. Therefore, we
|
|
129
|
+ // store the state here and update only once.
|
|
130
|
+
|
|
131
|
+ largeVideoState.newSrc = newSrc;
|
|
132
|
+ largeVideoState.isVisible = $('#largeVideo').is(':visible');
|
|
133
|
+ largeVideoState.isDesktop = isVideoSrcDesktop(newSrc);
|
|
134
|
+ largeVideoState.userJid = getJidFromVideoSrc(newSrc);
|
|
135
|
+
|
|
136
|
+ // Screen stream is already rotated
|
|
137
|
+ largeVideoState.flipX = (newSrc === localVideoSrc) && flipXLocalVideo;
|
|
138
|
+
|
|
139
|
+ var oldSrc = $('#largeVideo').attr('src');
|
|
140
|
+ largeVideoState.oldJid = getJidFromVideoSrc(oldSrc);
|
|
141
|
+
|
|
142
|
+ var fade = false;
|
|
143
|
+ if (largeVideoState.oldJid != largeVideoState.userJid) {
|
|
144
|
+ fade = true;
|
|
145
|
+ // we want the notification to trigger even if userJid is undefined,
|
|
146
|
+ // or null.
|
|
147
|
+ $(document).trigger("selectedendpointchanged", [largeVideoState.userJid]);
|
|
148
|
+ }
|
124
|
149
|
|
125
|
|
- var userJid = getJidFromVideoSrc(newSrc);
|
126
|
|
- // we want the notification to trigger even if userJid is undefined,
|
127
|
|
- // or null.
|
128
|
|
- $(document).trigger("selectedendpointchanged", [userJid]);
|
|
150
|
+ if (!largeVideoState.updateInProgress) {
|
|
151
|
+ largeVideoState.updateInProgress = true;
|
129
|
152
|
|
130
|
|
- $('#largeVideo').fadeOut(300, function () {
|
131
|
|
- var oldSrc = $(this).attr('src');
|
|
153
|
+ var doUpdate = function () {
|
132
|
154
|
|
133
|
|
- $(this).attr('src', newSrc);
|
|
155
|
+ $('#largeVideo').attr('src', largeVideoState.newSrc);
|
134
|
156
|
|
135
|
|
- // Screen stream is already rotated
|
136
|
|
- var flipX = (newSrc === localVideoSrc) && flipXLocalVideo;
|
|
157
|
+ var videoTransform = document.getElementById('largeVideo')
|
|
158
|
+ .style.webkitTransform;
|
137
|
159
|
|
138
|
|
- var videoTransform = document.getElementById('largeVideo')
|
139
|
|
- .style.webkitTransform;
|
|
160
|
+ if (largeVideoState.flipX && videoTransform !== 'scaleX(-1)') {
|
|
161
|
+ document.getElementById('largeVideo').style.webkitTransform
|
|
162
|
+ = "scaleX(-1)";
|
|
163
|
+ }
|
|
164
|
+ else if (!largeVideoState.flipX && videoTransform === 'scaleX(-1)') {
|
|
165
|
+ document.getElementById('largeVideo').style.webkitTransform
|
|
166
|
+ = "none";
|
|
167
|
+ }
|
140
|
168
|
|
141
|
|
- if (flipX && videoTransform !== 'scaleX(-1)') {
|
142
|
|
- document.getElementById('largeVideo').style.webkitTransform
|
143
|
|
- = "scaleX(-1)";
|
144
|
|
- }
|
145
|
|
- else if (!flipX && videoTransform === 'scaleX(-1)') {
|
146
|
|
- document.getElementById('largeVideo').style.webkitTransform
|
147
|
|
- = "none";
|
148
|
|
- }
|
|
169
|
+ // Change the way we'll be measuring and positioning large video
|
|
170
|
+
|
|
171
|
+ getVideoSize = largeVideoState.isDesktop
|
|
172
|
+ ? getDesktopVideoSize
|
|
173
|
+ : getCameraVideoSize;
|
|
174
|
+ getVideoPosition = largeVideoState.isDesktop
|
|
175
|
+ ? getDesktopVideoPosition
|
|
176
|
+ : getCameraVideoPosition;
|
|
177
|
+
|
|
178
|
+ if (largeVideoState.isVisible) {
|
|
179
|
+ // Only if the large video is currently visible.
|
|
180
|
+ // Disable previous dominant speaker video.
|
|
181
|
+ if (largeVideoState.oldJid) {
|
|
182
|
+ var oldResourceJid = Strophe.getResourceFromJid(largeVideoState.oldJid);
|
|
183
|
+ VideoLayout.enableDominantSpeaker(oldResourceJid, false);
|
|
184
|
+ }
|
149
|
185
|
|
150
|
|
- // Change the way we'll be measuring and positioning large video
|
151
|
|
-
|
152
|
|
- getVideoSize = isDesktop
|
153
|
|
- ? getDesktopVideoSize
|
154
|
|
- : getCameraVideoSize;
|
155
|
|
- getVideoPosition = isDesktop
|
156
|
|
- ? getDesktopVideoPosition
|
157
|
|
- : getCameraVideoPosition;
|
158
|
|
-
|
159
|
|
- if (isVisible) {
|
160
|
|
- // Only if the large video is currently visible.
|
161
|
|
- // Disable previous dominant speaker video.
|
162
|
|
- var oldJid = getJidFromVideoSrc(oldSrc);
|
163
|
|
- if (oldJid) {
|
164
|
|
- var oldResourceJid = Strophe.getResourceFromJid(oldJid);
|
165
|
|
- VideoLayout.enableDominantSpeaker(oldResourceJid, false);
|
166
|
|
- }
|
|
186
|
+ // Enable new dominant speaker in the remote videos section.
|
|
187
|
+ if (largeVideoState.userJid) {
|
|
188
|
+ var resourceJid = Strophe.getResourceFromJid(largeVideoState.userJid);
|
|
189
|
+ VideoLayout.enableDominantSpeaker(resourceJid, true);
|
|
190
|
+ }
|
167
|
191
|
|
168
|
|
- // Enable new dominant speaker in the remote videos section.
|
169
|
|
- var userJid = getJidFromVideoSrc(newSrc);
|
170
|
|
- if (userJid)
|
171
|
|
- {
|
172
|
|
- var resourceJid = Strophe.getResourceFromJid(userJid);
|
173
|
|
- VideoLayout.enableDominantSpeaker(resourceJid, true);
|
|
192
|
+ largeVideoState.updateInProgress = false;
|
|
193
|
+ if (fade) {
|
|
194
|
+ // using "this" should be ok because we're called
|
|
195
|
+ // from within the fadeOut event.
|
|
196
|
+ $(this).fadeIn(300);
|
|
197
|
+ }
|
174
|
198
|
}
|
|
199
|
+ };
|
175
|
200
|
|
176
|
|
- $(this).fadeIn(300);
|
|
201
|
+ if (fade) {
|
|
202
|
+ $('#largeVideo').fadeOut(300, doUpdate);
|
|
203
|
+ } else {
|
|
204
|
+ doUpdate();
|
177
|
205
|
}
|
178
|
|
- });
|
|
206
|
+ }
|
179
|
207
|
}
|
180
|
208
|
};
|
181
|
209
|
|
|
@@ -814,15 +842,6 @@ var VideoLayout = (function (my) {
|
814
|
842
|
* disabled
|
815
|
843
|
*/
|
816
|
844
|
my.enableDominantSpeaker = function(resourceJid, isEnable) {
|
817
|
|
- var displayName = resourceJid;
|
818
|
|
- var nameSpan = $('#participant_' + resourceJid + '>span.displayname');
|
819
|
|
- if (nameSpan.length > 0)
|
820
|
|
- displayName = nameSpan.text();
|
821
|
|
-
|
822
|
|
- console.log("UI enable dominant speaker",
|
823
|
|
- displayName,
|
824
|
|
- resourceJid,
|
825
|
|
- isEnable);
|
826
|
845
|
|
827
|
846
|
var videoSpanId = null;
|
828
|
847
|
var videoContainerId = null;
|
|
@@ -836,6 +855,16 @@ var VideoLayout = (function (my) {
|
836
|
855
|
videoContainerId = videoSpanId;
|
837
|
856
|
}
|
838
|
857
|
|
|
858
|
+ var displayName = resourceJid;
|
|
859
|
+ var nameSpan = $('#' + videoContainerId + '>span.displayname');
|
|
860
|
+ if (nameSpan.length > 0)
|
|
861
|
+ displayName = nameSpan.text();
|
|
862
|
+
|
|
863
|
+ console.log("UI enable dominant speaker",
|
|
864
|
+ displayName,
|
|
865
|
+ resourceJid,
|
|
866
|
+ isEnable);
|
|
867
|
+
|
839
|
868
|
videoSpan = document.getElementById(videoContainerId);
|
840
|
869
|
|
841
|
870
|
if (!videoSpan) {
|
|
@@ -1322,29 +1351,6 @@ var VideoLayout = (function (my) {
|
1322
|
1351
|
}
|
1323
|
1352
|
});
|
1324
|
1353
|
|
1325
|
|
- $(document).bind('simulcastlayerstarted simulcastlayerstopped', function(event) {
|
1326
|
|
- var localVideoSelector = $('#' + 'localVideo_' + connection.jingle.localVideo.id);
|
1327
|
|
- var simulcast = new Simulcast();
|
1328
|
|
- var stream = simulcast.getLocalVideoStream();
|
1329
|
|
-
|
1330
|
|
- var updateLargeVideo = (connection.emuc.myroomjid
|
1331
|
|
- == getJidFromVideoSrc(largeVideoNewSrc));
|
1332
|
|
- var updateFocusedVideoSrc = (localVideoSrc == focusedVideoSrc);
|
1333
|
|
-
|
1334
|
|
- // Attach WebRTC stream
|
1335
|
|
- RTC.attachMediaStream(localVideoSelector, stream);
|
1336
|
|
-
|
1337
|
|
- localVideoSrc = $(localVideoSelector).attr('src');
|
1338
|
|
-
|
1339
|
|
- if (updateLargeVideo) {
|
1340
|
|
- VideoLayout.updateLargeVideo(localVideoSrc);
|
1341
|
|
- }
|
1342
|
|
-
|
1343
|
|
- if (updateFocusedVideoSrc) {
|
1344
|
|
- focusedVideoSrc = localVideoSrc;
|
1345
|
|
- }
|
1346
|
|
- });
|
1347
|
|
-
|
1348
|
1354
|
/**
|
1349
|
1355
|
* On simulcast layers changed event.
|
1350
|
1356
|
*/
|
|
@@ -1402,7 +1408,7 @@ var VideoLayout = (function (my) {
|
1402
|
1408
|
var selRemoteVideo = $(['#', 'remoteVideo_', session.sid, '_', msidParts[0]].join(''));
|
1403
|
1409
|
|
1404
|
1410
|
var updateLargeVideo = (ssrc2jid[videoSrcToSsrc[selRemoteVideo.attr('src')]]
|
1405
|
|
- == ssrc2jid[videoSrcToSsrc[largeVideoNewSrc]]);
|
|
1411
|
+ == ssrc2jid[videoSrcToSsrc[largeVideoState.newSrc]]);
|
1406
|
1412
|
var updateFocusedVideoSrc = (selRemoteVideo.attr('src') == focusedVideoSrc);
|
1407
|
1413
|
|
1408
|
1414
|
var electedStreamUrl = webkitURL.createObjectURL(electedStream);
|