| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 | 
							- var SimulcastLogger = require("./SimulcastLogger");
 - var SimulcastUtils = require("./SimulcastUtils");
 - 
 - function SimulcastReceiver() {
 -     this.simulcastUtils = new SimulcastUtils();
 -     this.logger = new SimulcastLogger('SimulcastReceiver', 1);
 - }
 - 
 - SimulcastReceiver.prototype._remoteVideoSourceCache = '';
 - SimulcastReceiver.prototype._remoteMaps = {
 -     msid2Quality: {},
 -     ssrc2Msid: {},
 -     msid2ssrc: {},
 -     receivingVideoStreams: {}
 - };
 - 
 - SimulcastReceiver.prototype._cacheRemoteVideoSources = function (lines) {
 -     this._remoteVideoSourceCache = this.simulcastUtils._getVideoSources(lines);
 - };
 - 
 - SimulcastReceiver.prototype._restoreRemoteVideoSources = function (lines) {
 -     this.simulcastUtils._replaceVideoSources(lines, this._remoteVideoSourceCache);
 - };
 - 
 - SimulcastReceiver.prototype._ensureGoogConference = function (lines) {
 -     var sb;
 - 
 -     this.logger.info('Ensuring x-google-conference flag...')
 - 
 -     if (this.simulcastUtils._indexOfArray('a=x-google-flag:conference', lines) === this.simulcastUtils._emptyCompoundIndex) {
 -         // TODO(gp) do that for the audio as well as suggested by fippo.
 -         // Add the google conference flag
 -         sb = this.simulcastUtils._getVideoSources(lines);
 -         sb = ['a=x-google-flag:conference'].concat(sb);
 -         this.simulcastUtils._replaceVideoSources(lines, sb);
 -     }
 - };
 - 
 - SimulcastReceiver.prototype._restoreSimulcastGroups = function (sb) {
 -     this._restoreRemoteVideoSources(sb);
 - };
 - 
 - /**
 -  * Restores the simulcast groups of the remote description. In
 -  * transformRemoteDescription we remove those in order for the set remote
 -  * description to succeed. The focus needs the signal the groups to new
 -  * participants.
 -  *
 -  * @param desc
 -  * @returns {*}
 -  */
 - SimulcastReceiver.prototype.reverseTransformRemoteDescription = function (desc) {
 -     var sb;
 - 
 -     if (!this.simulcastUtils.isValidDescription(desc)) {
 -         return desc;
 -     }
 - 
 -     if (config.enableSimulcast) {
 -         sb = desc.sdp.split('\r\n');
 - 
 -         this._restoreSimulcastGroups(sb);
 - 
 -         desc = new RTCSessionDescription({
 -             type: desc.type,
 -             sdp: sb.join('\r\n')
 -         });
 -     }
 - 
 -     return desc;
 - };
 - 
 - SimulcastUtils.prototype._ensureOrder = function (lines) {
 -     var videoSources, sb;
 - 
 -     videoSources = this.parseMedia(lines, ['video'])[0];
 -     sb = this._compileVideoSources(videoSources);
 - 
 -     this._replaceVideoSources(lines, sb);
 - };
 - 
 - SimulcastReceiver.prototype._updateRemoteMaps = function (lines) {
 -     var remoteVideoSources = this.simulcastUtils.parseMedia(lines, ['video'])[0],
 -         videoSource, quality;
 - 
 -     // (re) initialize the remote maps.
 -     this._remoteMaps.msid2Quality = {};
 -     this._remoteMaps.ssrc2Msid = {};
 -     this._remoteMaps.msid2ssrc = {};
 - 
 -     var self = this;
 -     if (remoteVideoSources.groups && remoteVideoSources.groups.length !== 0) {
 -         remoteVideoSources.groups.forEach(function (group) {
 -             if (group.semantics === 'SIM' && group.ssrcs && group.ssrcs.length !== 0) {
 -                 quality = 0;
 -                 group.ssrcs.forEach(function (ssrc) {
 -                     videoSource = remoteVideoSources.sources[ssrc];
 -                     self._remoteMaps.msid2Quality[videoSource.msid] = quality++;
 -                     self._remoteMaps.ssrc2Msid[videoSource.ssrc] = videoSource.msid;
 -                     self._remoteMaps.msid2ssrc[videoSource.msid] = videoSource.ssrc;
 -                 });
 -             }
 -         });
 -     }
 - };
 - 
 - SimulcastReceiver.prototype._setReceivingVideoStream = function (resource, ssrc) {
 -     this._remoteMaps.receivingVideoStreams[resource] = ssrc;
 - };
 - 
 - /**
 -  * Returns a stream with single video track, the one currently being
 -  * received by this endpoint.
 -  *
 -  * @param stream the remote simulcast stream.
 -  * @returns {webkitMediaStream}
 -  */
 - SimulcastReceiver.prototype.getReceivingVideoStream = function (stream) {
 -     var tracks, i, electedTrack, msid, quality = 0, receivingTrackId;
 - 
 -     var self = this;
 -     if (config.enableSimulcast) {
 - 
 -         stream.getVideoTracks().some(function (track) {
 -             return Object.keys(self._remoteMaps.receivingVideoStreams).some(function (resource) {
 -                 var ssrc = self._remoteMaps.receivingVideoStreams[resource];
 -                 var msid = self._remoteMaps.ssrc2Msid[ssrc];
 -                 if (msid == [stream.id, track.id].join(' ')) {
 -                     electedTrack = track;
 -                     return true;
 -                 }
 -             });
 -         });
 - 
 -         if (!electedTrack) {
 -             // we don't have an elected track, choose by initial quality.
 -             tracks = stream.getVideoTracks();
 -             for (i = 0; i < tracks.length; i++) {
 -                 msid = [stream.id, tracks[i].id].join(' ');
 -                 if (this._remoteMaps.msid2Quality[msid] === quality) {
 -                     electedTrack = tracks[i];
 -                     break;
 -                 }
 -             }
 - 
 -             // TODO(gp) if the initialQuality could not be satisfied, lower
 -             // the requirement and try again.
 -         }
 -     }
 - 
 -     return (electedTrack)
 -         ? new webkitMediaStream([electedTrack])
 -         : stream;
 - };
 - 
 - SimulcastReceiver.prototype.getReceivingSSRC = function (jid) {
 -     var resource = Strophe.getResourceFromJid(jid);
 -     var ssrc = this._remoteMaps.receivingVideoStreams[resource];
 - 
 -     // If we haven't receiving a "changed" event yet, then we must be receiving
 -     // low quality (that the sender always streams).
 -     if (!ssrc && connection.jingle) {
 -         var session;
 -         var i, j, k;
 - 
 -         var keys = Object.keys(connection.jingle.sessions);
 -         for (i = 0; i < keys.length; i++) {
 -             var sid = keys[i];
 - 
 -             if (ssrc) {
 -                 // stream found, stop.
 -                 break;
 -             }
 - 
 -             session = connection.jingle.sessions[sid];
 -             if (session.remoteStreams) {
 -                 for (j = 0; j < session.remoteStreams.length; j++) {
 -                     var remoteStream = session.remoteStreams[j];
 - 
 -                     if (ssrc) {
 -                         // stream found, stop.
 -                         break;
 -                     }
 -                     var tracks = remoteStream.getVideoTracks();
 -                     if (tracks) {
 -                         for (k = 0; k < tracks.length; k++) {
 -                             var track = tracks[k];
 -                             var msid = [remoteStream.id, track.id].join(' ');
 -                             var _ssrc = this._remoteMaps.msid2ssrc[msid];
 -                             var _jid = ssrc2jid[_ssrc];
 -                             var quality = this._remoteMaps.msid2Quality[msid];
 -                             if (jid == _jid && quality == 0) {
 -                                 ssrc = _ssrc;
 -                                 // stream found, stop.
 -                                 break;
 -                             }
 -                         }
 -                     }
 -                 }
 -             }
 -         }
 -     }
 - 
 -     return ssrc;
 - };
 - 
 - SimulcastReceiver.prototype.getReceivingVideoStreamBySSRC = function (ssrc)
 - {
 -     var session, electedStream;
 -     var i, j, k;
 -     if (connection.jingle) {
 -         var keys = Object.keys(connection.jingle.sessions);
 -         for (i = 0; i < keys.length; i++) {
 -             var sid = keys[i];
 - 
 -             if (electedStream) {
 -                 // stream found, stop.
 -                 break;
 -             }
 - 
 -             session = connection.jingle.sessions[sid];
 -             if (session.remoteStreams) {
 -                 for (j = 0; j < session.remoteStreams.length; j++) {
 -                     var remoteStream = session.remoteStreams[j];
 - 
 -                     if (electedStream) {
 -                         // stream found, stop.
 -                         break;
 -                     }
 -                     var tracks = remoteStream.getVideoTracks();
 -                     if (tracks) {
 -                         for (k = 0; k < tracks.length; k++) {
 -                             var track = tracks[k];
 -                             var msid = [remoteStream.id, track.id].join(' ');
 -                             var tmp = this._remoteMaps.msid2ssrc[msid];
 -                             if (tmp == ssrc) {
 -                                 electedStream = new webkitMediaStream([track]);
 -                                 // stream found, stop.
 -                                 break;
 -                             }
 -                         }
 -                     }
 -                 }
 -             }
 -         }
 -     }
 - 
 -     return {
 -         session: session,
 -         stream: electedStream
 -     };
 - };
 - 
 - /**
 -  * Gets the fully qualified msid (stream.id + track.id) associated to the
 -  * SSRC.
 -  *
 -  * @param ssrc
 -  * @returns {*}
 -  */
 - SimulcastReceiver.prototype.getRemoteVideoStreamIdBySSRC = function (ssrc) {
 -     return this._remoteMaps.ssrc2Msid[ssrc];
 - };
 - 
 - /**
 -  * Removes the ssrc-group:SIM from the remote description bacause Chrome
 -  * either gets confused and thinks this is an FID group or, if an FID group
 -  * is already present, it fails to set the remote description.
 -  *
 -  * @param desc
 -  * @returns {*}
 -  */
 - SimulcastReceiver.prototype.transformRemoteDescription = function (desc) {
 - 
 -     if (desc && desc.sdp) {
 -         var sb = desc.sdp.split('\r\n');
 - 
 -         this._updateRemoteMaps(sb);
 -         this._cacheRemoteVideoSources(sb);
 - 
 -         // NOTE(gp) this needs to be called after updateRemoteMaps because we
 -         // need the simulcast group in the _updateRemoteMaps() method.
 -         this.simulcastUtils._removeSimulcastGroup(sb);
 - 
 -         if (desc.sdp.indexOf('a=ssrc-group:SIM') !== -1) {
 -             // We don't need the goog conference flag if we're not doing
 -             // simulcast.
 -             this._ensureGoogConference(sb);
 -         }
 - 
 -         desc = new RTCSessionDescription({
 -             type: desc.type,
 -             sdp: sb.join('\r\n')
 -         });
 - 
 -         this.logger.fine(['Transformed remote description', desc.sdp].join(' '));
 -     }
 - 
 -     return desc;
 - };
 - 
 - module.exports = SimulcastReceiver;
 
 
  |