Moves SSRC owner signaling from MUC presence to Jingle.

This commit is contained in:
paweldomas 2015-07-14 15:35:13 +02:00
parent d74a356a40
commit a1b0677442
12 changed files with 19009 additions and 19149 deletions

View File

@ -22,7 +22,7 @@
<script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
<script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
<script src="interface_config.js?v=5"></script>
<script src="libs/app.bundle.js?v=99"></script>
<script src="libs/app.bundle.js?v=100"></script>
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
<link rel="stylesheet" href="css/font.css?v=7"/>
<link rel="stylesheet" href="css/toastr.css?v=1">

File diff suppressed because it is too large Load Diff

View File

@ -28,10 +28,10 @@ function MediaStream(data, sid, ssrc, browser, eventEmitter) {
this.sid = sid;
this.stream = data.stream;
this.peerjid = data.peerjid;
this.videoType = data.videoType;
this.ssrc = ssrc;
this.type = (this.stream.getVideoTracks().length > 0)?
MediaStreamType.VIDEO_TYPE : MediaStreamType.AUDIO_TYPE;
this.videoType = null;
this.muted = false;
this.eventEmitter = eventEmitter;
}
@ -48,13 +48,4 @@ MediaStream.prototype.setMute = function (value)
this.muted = value;
};
MediaStream.prototype.setVideoType = function (value) {
if(this.videoType === value)
return;
this.videoType = value;
this.eventEmitter.emit(StreamEventType.EVENT_TYPE_REMOTE_CHANGED,
this.peerjid);
};
module.exports = MediaStream;

View File

@ -148,20 +148,6 @@ var RTC = {
function (stream, isUsingScreenStream, callback) {
self.changeLocalVideo(stream, isUsingScreenStream, callback);
}, DesktopSharingEventTypes.NEW_STREAM_CREATED);
APP.xmpp.addListener(XMPPEvents.STREAMS_CHANGED, function (jid, changedStreams) {
for(var i = 0; i < changedStreams.length; i++) {
var type = changedStreams[i].type;
if (type != "audio") {
var peerStreams = self.remoteStreams[jid];
if(!peerStreams)
continue;
var videoStream = peerStreams[MediaStreamType.VIDEO_TYPE];
if(!videoStream)
continue;
videoStream.setVideoType(changedStreams[i].type);
}
}
});
APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function(event) {
DataChannels.init(event.peerconnection, eventEmitter);
});

View File

@ -249,24 +249,6 @@ function registerListeners() {
APP.xmpp.addListener(XMPPEvents.USER_ID_CHANGED, function (from, id) {
Avatar.setUserAvatar(from, id);
});
APP.xmpp.addListener(XMPPEvents.STREAMS_CHANGED, function (jid, changedStreams) {
for(stream in changedStreams)
{
// might need to update the direction if participant just went from sendrecv to recvonly
if (stream.type === 'video' || stream.type === 'screen') {
var el = $('#participant_' + Strophe.getResourceFromJid(jid) + '>' + APP.RTC.getVideoElementName());
switch (stream.direction) {
case 'sendrecv':
el.show();
break;
case 'recvonly':
el.hide();
break;
}
}
}
});
APP.xmpp.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, onDisplayNameChanged);
APP.xmpp.addListener(XMPPEvents.MUC_JOINED, onMucJoined);
APP.xmpp.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, onLocalRoleChanged);

View File

@ -532,6 +532,13 @@ var VideoLayout = (function (my) {
} else {
VideoLayout.ensurePeerContainerExists(jid);
remoteVideos[Strophe.getResourceFromJid(jid)].showVideoIndicator(value);
var el = $('#participant_' + Strophe.getResourceFromJid(jid)
+ '>' + APP.RTC.getVideoElementName());
if (!value)
el.show();
else
el.hide();
}
};

View File

@ -48,6 +48,8 @@ function JingleSession(me, sid, connection, service, eventEmitter) {
this.wait = true;
this.localStreamsSSRC = null;
this.ssrcOwners = {};
this.ssrcVideoTypes = {};
this.eventEmitter = eventEmitter;
/**
@ -189,6 +191,10 @@ function onIceConnectionStateChange(sid, session) {
}
}
JingleSession.prototype.getVideoType = function () {
return APP.desktopsharing.isUsingScreenStream() ? 'screen' : 'camera';
};
JingleSession.prototype.accept = function () {
this.state = 'active';
@ -216,7 +222,12 @@ JingleSession.prototype.accept = function () {
initiator: this.initiator,
responder: this.responder,
sid: this.sid });
prsdp.toJingle(accept, this.initiator == this.me ? 'initiator' : 'responder', this.localStreamsSSRC);
// FIXME why do we generate session-accept in 3 different places ?
prsdp.toJingle(
accept,
this.initiator == this.me ? 'initiator' : 'responder',
this.localStreamsSSRC,
self.getVideoType());
var sdp = this.peerconnection.localDescription.sdp;
while (SDPUtil.find_line(sdp, 'a=inactive')) {
// FIXME: change any inactive to sendrecv or whatever they were originally
@ -303,6 +314,7 @@ JingleSession.prototype.sendIceCandidate = function (candidate) {
//console.log('sendIceCandidate: last candidate.');
if (!this.usetrickle) {
//console.log('should send full offer now...');
//FIXME why do we generate session-accept in 3 different places ?
var init = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
@ -314,7 +326,11 @@ JingleSession.prototype.sendIceCandidate = function (candidate) {
var sendJingle = function (ssrc) {
if(!ssrc)
ssrc = {};
self.localSDP.toJingle(init, self.initiator == self.me ? 'initiator' : 'responder', ssrc);
self.localSDP.toJingle(
init,
self.initiator == self.me ? 'initiator' : 'responder',
ssrc,
self.getVideoType());
self.connection.sendIQ(init,
function () {
//console.log('session initiate ack');
@ -414,6 +430,7 @@ JingleSession.prototype.sendOffer = function () {
);
};
// FIXME createdOffer is never used in jitsi-meet
JingleSession.prototype.createdOffer = function (sdp) {
//console.log('createdOffer', sdp);
var self = this;
@ -426,7 +443,11 @@ JingleSession.prototype.createdOffer = function (sdp) {
action: 'session-initiate',
initiator: this.initiator,
sid: this.sid});
self.localSDP.toJingle(init, this.initiator == this.me ? 'initiator' : 'responder', this.localStreamsSSRC);
self.localSDP.toJingle(
init,
this.initiator == this.me ? 'initiator' : 'responder',
this.localStreamsSSRC,
self.getVideoType());
self.connection.sendIQ(init,
function () {
var ack = {};
@ -471,10 +492,35 @@ JingleSession.prototype.createdOffer = function (sdp) {
}
};
JingleSession.prototype.readSsrcInfo = function (contents) {
var self = this;
$(contents).each(function (idx, content) {
var name = $(content).attr('name');
var mediaType = this.getAttribute('name');
var ssrcs = $(content).find('description>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
ssrcs.each(function () {
var ssrc = this.getAttribute('ssrc');
$(this).find('>ssrc-info[xmlns="http://jitsi.org/jitmeet"]').each(
function () {
var owner = this.getAttribute('owner');
var videoType = this.getAttribute('video-type');
self.ssrcOwners[ssrc] = owner;
self.ssrcVideoTypes[ssrc] = videoType;
}
);
});
});
};
JingleSession.prototype.getSsrcOwner = function (ssrc) {
return this.ssrcOwners[ssrc];
};
JingleSession.prototype.setRemoteDescription = function (elem, desctype) {
//console.log('setting remote description... ', desctype);
this.remoteSDP = new SDP('');
this.remoteSDP.fromJingle(elem);
this.readSsrcInfo($(elem).find(">content"));
if (this.peerconnection.remoteDescription !== null) {
console.log('setRemoteDescription when remote description is not null, should be pranswer', this.peerconnection.remoteDescription);
if (this.peerconnection.remoteDescription.type == 'pranswer') {
@ -655,7 +701,7 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) {
}
var self = this;
var sendJingle = function (ssrcs) {
// FIXME why do we generate session-accept in 3 different places ?
var accept = $iq({to: self.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
@ -663,7 +709,11 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) {
initiator: self.initiator,
responder: self.responder,
sid: self.sid });
self.localSDP.toJingle(accept, self.initiator == self.me ? 'initiator' : 'responder', ssrcs);
self.localSDP.toJingle(
accept,
self.initiator == self.me ? 'initiator' : 'responder',
ssrcs,
self.getVideoType());
self.connection.sendIQ(accept,
function () {
var ack = {};
@ -762,6 +812,9 @@ JingleSession.prototype.addSource = function (elem, fromJid) {
console.log('addssrc', new Date().getTime());
console.log('ice', this.peerconnection.iceConnectionState);
this.readSsrcInfo(elem);
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
var mySdp = new SDP(this.peerconnection.localDescription.sdp);
@ -1085,7 +1138,7 @@ JingleSession.prototype.notifyMySSRCUpdate = function (old_sdp, new_sdp) {
sid: this.sid
}
);
var added = sdpDiffer.toJingle(add);
var added = sdpDiffer.toJingle(add, this.getVideoType());
if (added) {
this.connection.sendIQ(add,
function (res) {
@ -1245,7 +1298,7 @@ JingleSession.onJingleFatalError = function (session, error)
}
JingleSession.prototype.setLocalDescription = function () {
// put our ssrcs into presence so other clients can identify our stream
var self = this;
var newssrcs = [];
var session = transform.parse(this.peerconnection.localDescription.sdp);
session.media.forEach(function (media) {
@ -1258,17 +1311,15 @@ JingleSession.prototype.setLocalDescription = function () {
}
newssrcs.push({
'ssrc': ssrc.id,
'type': media.type,
'direction': media.direction
'type': media.type
});
});
}
else if(this.localStreamsSSRC && this.localStreamsSSRC[media.type])
else if(self.localStreamsSSRC && self.localStreamsSSRC[media.type])
{
newssrcs.push({
'ssrc': this.localStreamsSSRC[media.type],
'type': media.type,
'direction': media.direction
'ssrc': self.localStreamsSSRC[media.type],
'type': media.type
});
}
@ -1276,20 +1327,16 @@ JingleSession.prototype.setLocalDescription = function () {
console.log('new ssrcs', newssrcs);
// Have to clear presence map to get rid of removed streams
this.connection.emuc.clearPresenceMedia();
// Bind us as local SSRCs owner
if (newssrcs.length > 0) {
for (var i = 1; i <= newssrcs.length; i ++) {
// Change video type to screen
if (newssrcs[i-1].type === 'video' && APP.desktopsharing.isUsingScreenStream()) {
newssrcs[i-1].type = 'screen';
var ssrc = newssrcs[i-1].ssrc;
var myJid = self.connection.emuc.myroomjid;
self.ssrcOwners[ssrc] = myJid;
if (newssrcs[i-1].type === 'video'){
self.ssrcVideoTypes[ssrc] = self.getVideoType();
}
this.connection.emuc.addMediaToPresence(i,
newssrcs[i-1].type, newssrcs[i-1].ssrc, newssrcs[i-1].direction);
}
this.connection.emuc.sendPresence();
}
}
@ -1331,7 +1378,6 @@ function sendKeyframe(pc) {
JingleSession.prototype.remoteStreamAdded = function (data, times) {
var self = this;
var thessrc;
var ssrc2jid = this.connection.emuc.ssrc2jid;
var streamId = APP.RTC.getStreamID(data.stream);
// look up an associated JID for a stream id
@ -1354,40 +1400,14 @@ JingleSession.prototype.remoteStreamAdded = function (data, times) {
if (ssrclines.length) {
thessrc = ssrclines[0].substring(7).split(' ')[0];
// We signal our streams (through Jingle to the focus) before we set
// our presence (through which peers associate remote streams to
// jids). So, it might arrive that a remote stream is added but
// ssrc2jid is not yet updated and thus data.peerjid cannot be
// successfully set. Here we wait for up to a second for the
// presence to arrive.
if (!ssrc2jid[thessrc]) {
if (typeof times === 'undefined')
{
times = 0;
}
if (times > 10)
{
console.warning('Waiting for jid timed out', thessrc);
}
else
{
setTimeout(function(d) {
return function() {
self.remoteStreamAdded(d, times++);
}
}(data), 250);
}
if (!self.ssrcOwners[thessrc]) {
console.error("No SSRC owner known for: " + thessrc);
return;
}
// ok to overwrite the one from focus? might save work in colibri.js
console.log('associated jid', ssrc2jid[thessrc], thessrc);
if (ssrc2jid[thessrc]) {
data.peerjid = ssrc2jid[thessrc];
}
data.peerjid = self.ssrcOwners[thessrc];
data.videoType = self.ssrcVideoTypes[thessrc]
console.log('associated jid', self.ssrcOwners[thessrc],
thessrc, data.videoType);
}
}

View File

@ -125,7 +125,7 @@ SDP.prototype.removeMediaLines = function(mediaindex, prefix) {
}
// add content's to a jingle element
SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
SDP.prototype.toJingle = function (elem, thecreator, ssrcs, videoType) {
// console.log("SSRC" + ssrcs["audio"] + " - " + ssrcs["video"]);
var i, j, k, mline, ssrc, rtpmap, tmp, line, lines;
var self = this;
@ -227,7 +227,6 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
}
elem.up();
});
elem.up();
}
else
{
@ -257,11 +256,17 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
elem.c('parameter');
elem.attrs({name: "label", value:msid});
elem.up();
elem.up();
}
}
// Video type
if (videoType && mline.media == "video") {
elem.c('ssrc-info',
{
xmlns: 'http://jitsi.org/jitmeet',
'video-type': videoType
}).up();
}
elem.up();
// XEP-0339 handle ssrc-group attributes
var ssrc_group_lines = SDPUtil.find_lines(this.media[i], 'a=ssrc-group:');

View File

@ -106,7 +106,7 @@ SDPDiffer.prototype.getNewMedia = function() {
* @param toJid destination Jid
* @param isAdd indicates if this is remove or add operation.
*/
SDPDiffer.prototype.toJingle = function(modify) {
SDPDiffer.prototype.toJingle = function(modify, videoType) {
var sdpMediaSsrcs = this.getNewMedia();
var self = this;
@ -141,6 +141,15 @@ SDPDiffer.prototype.toJingle = function(modify) {
}
modify.up(); // end of parameter
});
// indicate video type
if (videoType && media.mid == 'video') {
modify.c('ssrc-info',
{
xmlns: 'http://jitsi.org/jitmeet',
'video-type': videoType
})
.up();
}
modify.up(); // end of source
});

View File

@ -21,7 +21,6 @@ module.exports = function(XMPP, eventEmitter) {
isOwner: false,
role: null,
focusMucJid: null,
ssrc2jid: {},
init: function (conn) {
this.connection = conn;
},
@ -280,14 +279,6 @@ module.exports = function(XMPP, eventEmitter) {
return true;
}
var self = this;
// Remove old ssrcs coming from the jid
Object.keys(this.ssrc2jid).forEach(function (ssrc) {
if (self.ssrc2jid[ssrc] == from) {
delete self.ssrc2jid[ssrc];
}
});
// Status code 110 indicates that this notification is "self-presence".
if (!$(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="110"]').length) {
delete this.members[from];
@ -514,26 +505,6 @@ module.exports = function(XMPP, eventEmitter) {
.c('current').t(this.presMap['prezicurrent']).up().up();
}
if (this.presMap['medians']) {
pres.c('media', {xmlns: this.presMap['medians']});
var sourceNumber = 0;
Object.keys(this.presMap).forEach(function (key) {
if (key.indexOf('source') >= 0) {
sourceNumber++;
}
});
if (sourceNumber > 0)
for (var i = 1; i <= sourceNumber / 3; i++) {
pres.c('source',
{type: this.presMap['source' + i + '_type'],
ssrc: this.presMap['source' + i + '_ssrc'],
direction: this.presMap['source' + i + '_direction']
|| 'sendrecv' }
).up();
}
pres.up();
}
if(this.presMap["startMuted"] !== undefined)
{
pres.c("startmuted", {audio: this.presMap["startMuted"].audio,
@ -548,25 +519,9 @@ module.exports = function(XMPP, eventEmitter) {
addDisplayNameToPresence: function (displayName) {
this.presMap['displayName'] = displayName;
},
addMediaToPresence: function (sourceNumber, mtype, ssrcs, direction) {
if (!this.presMap['medians'])
this.presMap['medians'] = 'http://estos.de/ns/mjs';
this.presMap['source' + sourceNumber + '_type'] = mtype;
this.presMap['source' + sourceNumber + '_ssrc'] = ssrcs;
this.presMap['source' + sourceNumber + '_direction'] = direction;
},
addDevicesToPresence: function (devices) {
this.presMap['devices'] = devices;
},
clearPresenceMedia: function () {
var self = this;
Object.keys(this.presMap).forEach(function (key) {
if (key.indexOf('source') != -1) {
delete self.presMap[key];
}
});
},
addPreziToPresence: function (url, currentSlide) {
this.presMap['prezins'] = 'http://jitsi.org/jitmeet/prezi';
this.presMap['preziurl'] = url;
@ -650,30 +605,6 @@ module.exports = function(XMPP, eventEmitter) {
if(memeber.isFocus)
return;
var self = this;
// Remove old ssrcs coming from the jid
Object.keys(this.ssrc2jid).forEach(function (ssrc) {
if (self.ssrc2jid[ssrc] == from) {
delete self.ssrc2jid[ssrc];
}
});
var changedStreams = [];
$(pres).find('>media[xmlns="http://estos.de/ns/mjs"]>source').each(function (idx, ssrc) {
//console.log(jid, 'assoc ssrc', ssrc.getAttribute('type'), ssrc.getAttribute('ssrc'));
var ssrcV = ssrc.getAttribute('ssrc');
self.ssrc2jid[ssrcV] = from;
var type = ssrc.getAttribute('type');
var direction = ssrc.getAttribute('direction');
changedStreams.push({type: type, direction: direction});
});
eventEmitter.emit(XMPPEvents.STREAMS_CHANGED, from, changedStreams);
var displayName = !config.displayJids
? memeber.displayName : Strophe.getResourceFromJid(from);

View File

@ -594,9 +594,9 @@ var XMPP = {
return connection.emuc.members;
},
getJidFromSSRC: function (ssrc) {
if(!connection)
if (!this.isConferenceInProgress())
return null;
return connection.emuc.ssrc2jid[ssrc];
return connection.jingle.activecall.getSsrcOwner(ssrc);
},
getMUCJoined: function () {
return connection.emuc.joined;

View File

@ -7,7 +7,6 @@ var XMPPEvents = {
KICKED: "xmpp.kicked",
BRIDGE_DOWN: "xmpp.bridge_down",
USER_ID_CHANGED: "xmpp.user_id_changed",
STREAMS_CHANGED: "xmpp.streams_changed",
// We joined the MUC
MUC_JOINED: "xmpp.muc_joined",
// A member joined the MUC