Selaa lähdekoodia

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

j8
George Politis 10 vuotta sitten
vanhempi
commit
fad08fdef0
2 muutettua tiedostoa jossa 129 lisäystä ja 6 poistoa
  1. 5
    0
      data_channels.js
  2. 124
    6
      videolayout.js

+ 5
- 0
data_channels.js Näytä tiedosto

@@ -97,6 +97,11 @@ function onDataChannel(event)
97 97
                 var endpointSimulcastLayers = obj.endpointSimulcastLayers;
98 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 105
             else if ("StartSimulcastLayerEvent" === colibriClass)
101 106
             {
102 107
                 var simulcastLayer = obj.simulcastLayer;

+ 124
- 6
videolayout.js Näytä tiedosto

@@ -141,9 +141,9 @@ var VideoLayout = (function (my) {
141 141
             var oldSrc = $('#largeVideo').attr('src');
142 142
             largeVideoState.oldJid = getJidFromVideoSrc(oldSrc);
143 143
 
144
-            var fade = false;
144
+            var userChanged = false;
145 145
             if (largeVideoState.oldJid != largeVideoState.userJid) {
146
-                fade = true;
146
+                userChanged = true;
147 147
                 // we want the notification to trigger even if userJid is undefined,
148 148
                 // or null.
149 149
                 $(document).trigger("selectedendpointchanged", [largeVideoState.userJid]);
@@ -154,7 +154,41 @@ var VideoLayout = (function (my) {
154 154
 
155 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 193
                     var videoTransform = document.getElementById('largeVideo')
160 194
                         .style.webkitTransform;
@@ -191,7 +225,7 @@ var VideoLayout = (function (my) {
191 225
                         VideoLayout.enableDominantSpeaker(resourceJid, true);
192 226
                     }
193 227
 
194
-                    if (fade && largeVideoState.isVisible) {
228
+                    if (userChanged && largeVideoState.isVisible) {
195 229
                         // using "this" should be ok because we're called
196 230
                         // from within the fadeOut event.
197 231
                         $(this).fadeIn(300);
@@ -200,7 +234,7 @@ var VideoLayout = (function (my) {
200 234
                     largeVideoState.updateInProgress = false;
201 235
                 };
202 236
 
203
-                if (fade) {
237
+                if (userChanged) {
204 238
                     $('#largeVideo').fadeOut(300, doUpdate);
205 239
                 } else {
206 240
                     doUpdate();
@@ -1388,6 +1422,81 @@ var VideoLayout = (function (my) {
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 1501
      * On simulcast layers changed event.
1393 1502
      */
@@ -1447,7 +1556,16 @@ var VideoLayout = (function (my) {
1447 1556
                     == ssrc2jid[videoSrcToSsrc[largeVideoState.newSrc]]);
1448 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 1569
                 selRemoteVideo.attr('src', electedStreamUrl);
1452 1570
                 videoSrcToSsrc[selRemoteVideo.attr('src')] = primarySSRC;
1453 1571
 

Loading…
Peruuta
Tallenna