소스 검색

Takes advantage of the smart simulcast layer escalation of the bridge to prevent blackness when we switch to a higher order layer.

master
George Politis 10 년 전
부모
커밋
fad08fdef0
2개의 변경된 파일129개의 추가작업 그리고 6개의 파일을 삭제
  1. 5
    0
      data_channels.js
  2. 124
    6
      videolayout.js

+ 5
- 0
data_channels.js 파일 보기

97
                 var endpointSimulcastLayers = obj.endpointSimulcastLayers;
97
                 var endpointSimulcastLayers = obj.endpointSimulcastLayers;
98
                 $(document).trigger('simulcastlayerschanged', [endpointSimulcastLayers]);
98
                 $(document).trigger('simulcastlayerschanged', [endpointSimulcastLayers]);
99
             }
99
             }
100
+            else if ("SimulcastLayersChangingEvent" === colibriClass)
101
+            {
102
+                var endpointSimulcastLayers = obj.endpointSimulcastLayers;
103
+                $(document).trigger('simulcastlayerschanging', [endpointSimulcastLayers]);
104
+            }
100
             else if ("StartSimulcastLayerEvent" === colibriClass)
105
             else if ("StartSimulcastLayerEvent" === colibriClass)
101
             {
106
             {
102
                 var simulcastLayer = obj.simulcastLayer;
107
                 var simulcastLayer = obj.simulcastLayer;

+ 124
- 6
videolayout.js 파일 보기

141
             var oldSrc = $('#largeVideo').attr('src');
141
             var oldSrc = $('#largeVideo').attr('src');
142
             largeVideoState.oldJid = getJidFromVideoSrc(oldSrc);
142
             largeVideoState.oldJid = getJidFromVideoSrc(oldSrc);
143
 
143
 
144
-            var fade = false;
144
+            var userChanged = false;
145
             if (largeVideoState.oldJid != largeVideoState.userJid) {
145
             if (largeVideoState.oldJid != largeVideoState.userJid) {
146
-                fade = true;
146
+                userChanged = true;
147
                 // we want the notification to trigger even if userJid is undefined,
147
                 // we want the notification to trigger even if userJid is undefined,
148
                 // or null.
148
                 // or null.
149
                 $(document).trigger("selectedendpointchanged", [largeVideoState.userJid]);
149
                 $(document).trigger("selectedendpointchanged", [largeVideoState.userJid]);
154
 
154
 
155
                 var doUpdate = function () {
155
                 var doUpdate = function () {
156
 
156
 
157
-                    $('#largeVideo').attr('src', largeVideoState.newSrc);
157
+                    if (!userChanged && largeVideoState.preload
158
+                        && largeVideoState.preload != null
159
+                        && $(largeVideoState.preload).attr('src') == newSrc) {
160
+
161
+                        console.info('Switching to preloaded video');
162
+                        var attributes = $('#largeVideo').prop("attributes");
163
+
164
+                        // loop through largeVideo attributes and apply them on
165
+                        // preload.
166
+                        $.each(attributes, function () {
167
+                            if (this.name != 'id' && this.name != 'src') {
168
+                                largeVideoState.preload.attr(this.name, this.value);
169
+                            }
170
+                        });
171
+
172
+                        largeVideoState.preload.appendTo($('#largeVideoContainer'));
173
+                        $('#largeVideo').attr('id', 'previousLargeVideo');
174
+                        largeVideoState.preload.attr('id', 'largeVideo');
175
+                        $('#previousLargeVideo').remove();
176
+
177
+                        largeVideoState.preload.on('loadedmetadata', function (e) {
178
+                            currentVideoWidth = this.videoWidth;
179
+                            currentVideoHeight = this.videoHeight;
180
+                            VideoLayout.positionLarge(currentVideoWidth, currentVideoHeight);
181
+                        });
182
+                        largeVideoState.preload = null;
183
+                        largeVideoState.preload_ssrc = 0;
184
+                    } else {
185
+                        if (largeVideoState.preload
186
+                            && largeVideoState.preload != null) {
187
+                            $(largeVideoState.preload).remove();
188
+                            largeVideoState.preload_ssrc = 0;
189
+                        }
190
+                        $('#largeVideo').attr('src', largeVideoState.newSrc);
191
+                    }
158
 
192
 
159
                     var videoTransform = document.getElementById('largeVideo')
193
                     var videoTransform = document.getElementById('largeVideo')
160
                         .style.webkitTransform;
194
                         .style.webkitTransform;
191
                         VideoLayout.enableDominantSpeaker(resourceJid, true);
225
                         VideoLayout.enableDominantSpeaker(resourceJid, true);
192
                     }
226
                     }
193
 
227
 
194
-                    if (fade && largeVideoState.isVisible) {
228
+                    if (userChanged && largeVideoState.isVisible) {
195
                         // using "this" should be ok because we're called
229
                         // using "this" should be ok because we're called
196
                         // from within the fadeOut event.
230
                         // from within the fadeOut event.
197
                         $(this).fadeIn(300);
231
                         $(this).fadeIn(300);
200
                     largeVideoState.updateInProgress = false;
234
                     largeVideoState.updateInProgress = false;
201
                 };
235
                 };
202
 
236
 
203
-                if (fade) {
237
+                if (userChanged) {
204
                     $('#largeVideo').fadeOut(300, doUpdate);
238
                     $('#largeVideo').fadeOut(300, doUpdate);
205
                 } else {
239
                 } else {
206
                     doUpdate();
240
                     doUpdate();
1388
         }
1422
         }
1389
     });
1423
     });
1390
 
1424
 
1425
+    $(document).bind('simulcastlayerschanging', function (event, endpointSimulcastLayers) {
1426
+        endpointSimulcastLayers.forEach(function (esl) {
1427
+            var primarySSRC = esl.simulcastLayer.primarySSRC;
1428
+            var msid = simulcast.getRemoteVideoStreamIdBySSRC(primarySSRC);
1429
+
1430
+            // Get session and stream from msid.
1431
+            var session, electedStream;
1432
+            var i, j, k;
1433
+            if (connection.jingle) {
1434
+                var keys = Object.keys(connection.jingle.sessions);
1435
+                for (i = 0; i < keys.length; i++) {
1436
+                    var sid = keys[i];
1437
+
1438
+                    if (electedStream) {
1439
+                        // stream found, stop.
1440
+                        break;
1441
+                    }
1442
+
1443
+                    session = connection.jingle.sessions[sid];
1444
+                    if (session.remoteStreams) {
1445
+                        for (j = 0; j < session.remoteStreams.length; j++) {
1446
+                            var remoteStream = session.remoteStreams[j];
1447
+
1448
+                            if (electedStream) {
1449
+                                // stream found, stop.
1450
+                                break;
1451
+                            }
1452
+                            var tracks = remoteStream.getVideoTracks();
1453
+                            if (tracks) {
1454
+                                for (k = 0; k < tracks.length; k++) {
1455
+                                    var track = tracks[k];
1456
+
1457
+                                    if (msid === [remoteStream.id, track.id].join(' ')) {
1458
+                                        electedStream = new webkitMediaStream([track]);
1459
+                                        // stream found, stop.
1460
+                                        break;
1461
+                                    }
1462
+                                }
1463
+                            }
1464
+                        }
1465
+                    }
1466
+                }
1467
+            }
1468
+
1469
+            if (session && electedStream) {
1470
+                console.info('Switching simulcast substream.');
1471
+                console.info([esl, primarySSRC, msid, session, electedStream]);
1472
+
1473
+                var msidParts = msid.split(' ');
1474
+                var selRemoteVideo = $(['#', 'remoteVideo_', session.sid, '_', msidParts[0]].join(''));
1475
+
1476
+                var preload = (ssrc2jid[videoSrcToSsrc[selRemoteVideo.attr('src')]]
1477
+                    == ssrc2jid[videoSrcToSsrc[largeVideoState.newSrc]]);
1478
+
1479
+                if (preload) {
1480
+                    if (largeVideoState.preload)
1481
+                    {
1482
+                        $(largeVideoState.preload).remove();
1483
+                    }
1484
+                    console.info('Preloading remote video');
1485
+                    largeVideoState.preload = $('<video autoplay></video>');
1486
+                    // ssrcs are unique in an rtp session
1487
+                    largeVideoState.preload_ssrc = primarySSRC;
1488
+
1489
+                    var electedStreamUrl = webkitURL.createObjectURL(electedStream);
1490
+                    largeVideoState.preload
1491
+                        .attr('src', electedStreamUrl);
1492
+                }
1493
+
1494
+            } else {
1495
+                console.error('Could not find a stream or a session.', session, electedStream);
1496
+            }
1497
+        });
1498
+    });
1499
+
1391
     /**
1500
     /**
1392
      * On simulcast layers changed event.
1501
      * On simulcast layers changed event.
1393
      */
1502
      */
1447
                     == ssrc2jid[videoSrcToSsrc[largeVideoState.newSrc]]);
1556
                     == ssrc2jid[videoSrcToSsrc[largeVideoState.newSrc]]);
1448
                 var updateFocusedVideoSrc = (selRemoteVideo.attr('src') == focusedVideoSrc);
1557
                 var updateFocusedVideoSrc = (selRemoteVideo.attr('src') == focusedVideoSrc);
1449
 
1558
 
1450
-                var electedStreamUrl = webkitURL.createObjectURL(electedStream);
1559
+                var electedStreamUrl;
1560
+                if (largeVideoState.preload_ssrc == primarySSRC)
1561
+                {
1562
+                    electedStreamUrl = $(largeVideoState.preload).attr('src');
1563
+                }
1564
+                else
1565
+                {
1566
+                    electedStreamUrl = webkitURL.createObjectURL(electedStream);
1567
+                }
1568
+
1451
                 selRemoteVideo.attr('src', electedStreamUrl);
1569
                 selRemoteVideo.attr('src', electedStreamUrl);
1452
                 videoSrcToSsrc[selRemoteVideo.attr('src')] = primarySSRC;
1570
                 videoSrcToSsrc[selRemoteVideo.attr('src')] = primarySSRC;
1453
 
1571
 

Loading…
취소
저장