Browse Source

Added client side configuration support for WebRTC renegotiation of user media streams.

pull/206/head
Simon Eisenmann 10 years ago committed by Simon Eisenmann
parent
commit
fba521352a
  1. 19
      static/js/directives/audiolevel.js
  2. 4
      static/js/directives/audiovideo.js
  3. 14
      static/js/mediastream/peerconference.js
  4. 49
      static/js/mediastream/usermedia.js
  5. 70
      static/js/mediastream/webrtc.js
  6. 4
      static/js/services/mediastream.js

19
static/js/directives/audiolevel.js

@ -22,9 +22,7 @@ @@ -22,9 +22,7 @@
"use strict";
define(['jquery', 'underscore'], function($, _) {
return ["$window", "mediaStream", "safeApply", "animationFrame", function($window, mediaStream, safeApply, animationFrame) {
var webrtc = mediaStream.webrtc;
return ["$window", "webrtc", "safeApply", "animationFrame", function($window, webrtc, safeApply, animationFrame) {
// Consider anyting lower than this % as no audio.
var threshhold = 5;
@ -37,6 +35,13 @@ define(['jquery', 'underscore'], function($, _) { @@ -37,6 +35,13 @@ define(['jquery', 'underscore'], function($, _) {
// Talking status history map.
var talkingStatus = {};
// Usermedia reference.
var usermedia = null;
webrtc.e.on("usermedia", function(event, um) {
console.log("Audio level user media changed", um);
usermedia = um;
});
var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
$scope.talking = false;
@ -47,8 +52,8 @@ define(['jquery', 'underscore'], function($, _) { @@ -47,8 +52,8 @@ define(['jquery', 'underscore'], function($, _) {
var width = 0;
this.update = _.bind(function() {
if (this.active || width > 0) {
if (webrtc.usermedia.audioLevel) {
width = Math.round(100 * webrtc.usermedia.audioLevel);
if (usermedia && usermedia.audioLevel) {
width = Math.round(100 * usermedia.audioLevel);
// Hide low volumes.
if (width < threshhold) {
width = 0;
@ -68,8 +73,8 @@ define(['jquery', 'underscore'], function($, _) { @@ -68,8 +73,8 @@ define(['jquery', 'underscore'], function($, _) {
this.meter = _.bind(function() {
var talking;
if (this.active) {
var level = Math.round(100 * webrtc.usermedia.audioLevel);
if (this.active && usermedia) {
var level = Math.round(100 * usermedia.audioLevel);
if (level < threshhold) {
level = 0;
} else {

4
static/js/directives/audiovideo.js

@ -243,6 +243,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -243,6 +243,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
mediaStream.webrtc.e.on("usermedia", function(event, usermedia) {
if (!usermedia || !usermedia.started) {
return;
}
//console.log("XXXX XXXXXXXXXXXXXXXXXXXXX usermedia event", usermedia);
if ($scope.haveStreams) {

14
static/js/mediastream/peerconference.js

@ -40,6 +40,12 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall @@ -40,6 +40,12 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
this.id = id;
}
this.usermedia = null;
webrtc.e.on("usermedia", _.bind(function(event, um) {
console.log("Conference user media changed", um);
this.usermedia = um;
}, this));
console.log("Created conference", this.id);
};
@ -97,8 +103,8 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall @@ -97,8 +103,8 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
call.e.on("negotiationNeeded", _.bind(function(event, extracall) {
this.webrtc.sendOfferWhenNegotiationNeeded(extracall);
}, this));
if (this.webrtc.usermedia) {
this.webrtc.usermedia.addToPeerConnection(peerconnection);
if (this.usermedia) {
this.usermedia.addToPeerConnection(peerconnection);
}
/*call.createOffer(_.bind(function(sessionDescription, extracall) {
console.log("Sending offer with sessionDescription", sessionDescription, extracall.id);
@ -143,8 +149,8 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall @@ -143,8 +149,8 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
call.createPeerConnection(_.bind(function(peerconnection) {
// Success call.
call.setRemoteDescription(rtcsdp, _.bind(function() {
if (this.webrtc.usermedia) {
this.webrtc.usermedia.addToPeerConnection(peerconnection);
if (this.usermedia) {
this.usermedia.addToPeerConnection(peerconnection);
}
call.createAnswer(_.bind(function(sessionDescription, extracall) {
console.log("Sending answer", sessionDescription, extracall.id);

49
static/js/mediastream/usermedia.js

@ -24,11 +24,6 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -24,11 +24,6 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
// Create AudioContext singleton, if supported.
var context = AudioContext ? new AudioContext() : null;
var peerconnections = {};
// Disabled for now until browser support matures. If enabled this totally breaks
// Firefox and Chrome with Firefox interop.
var enableRenegotiationSupport = false;
// Converter helpers to convert media constraints to new API.
var mergeConstraints = function(constraints, k, v, mandatory) {
@ -131,15 +126,21 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -131,15 +126,21 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
this.localStream = null;
this.started = false;
this.delay = 0;
//this.delay = 0;
this.audioMute = false;
this.videoMute = false;
this.peerconnections = {};
// If true, mute/unmute of audio/video creates a new stream which
// will trigger renegotiation on the peer connection.
this.renegotiation = options.renegotiation && true;
this.audioMute = options.audioMute && true;
this.videoMute = options.videoMute && true;
this.mediaConstraints = null;
// Audio level.
this.audioLevel = 0;
if (!this.options.noaudio && context && context.createScriptProcessor) {
if (!this.options.noAudio && context && context.createScriptProcessor) {
this.audioSource = null;
this.audioProcessor = context.createScriptProcessor(2048, 1, 1);
@ -185,7 +186,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -185,7 +186,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
this.e.on("localstream", _.bind(function(event, stream, oldstream) {
// Update stream support.
if (oldstream) {
_.each(peerconnections, function(pc) {
_.each(this.peerconnections, function(pc) {
pc.removeStream(oldstream);
pc.addStream(stream);
console.log("Updated usermedia stream at peer connection", pc, stream);
@ -319,7 +320,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -319,7 +320,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
// Let webrtc handle the rest.
setTimeout(_.bind(function() {
this.e.triggerHandler("mediasuccess", [this]);
}, this), this.delay);
}, this), 0);
}
// Get notified of end events.
@ -357,11 +358,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -357,11 +358,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
this.mediaConstraints = null;
console.log("Stopped user media.");
this.e.triggerHandler("stopped", [this]);
this.delay = 1500;
setTimeout(_.bind(function() {
this.delay = 0;
}, this), 2000);
this.e.off();
};
@ -369,7 +366,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -369,7 +366,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
var m = !!mute;
if (!enableRenegotiationSupport) {
if (!this.renegotiation) {
// Disable streams only - does not require renegotiation but keeps mic
// active and the stream will transmit silence.
@ -418,7 +415,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -418,7 +415,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
var m = !!mute;
if (!enableRenegotiationSupport) {
if (!this.renegotiation) {
// Disable streams only - does not require renegotiation but keeps camera
// active and the stream will transmit black.
@ -443,7 +440,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -443,7 +440,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
}
} else {
// Removevideo stream, by creating a new stream and doing renegotiation. This
// Remove video stream, by creating a new stream and doing renegotiation. This
// is the way to go to disable the camera when video is muted.
if (this.localStream) {
@ -467,11 +464,11 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -467,11 +464,11 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
if (this.localStream) {
pc.addStream(this.localStream);
var id = pc.id;
if (!peerconnections.hasOwnProperty(id)) {
peerconnections[id] = pc;
pc.currentcall.e.one("closed", function() {
delete peerconnections[id];
});
if (!this.peerconnections.hasOwnProperty(id)) {
this.peerconnections[id] = pc;
pc.currentcall.e.one("closed", _.bind(function() {
delete this.peerconnections[id];
}, this));
}
}
@ -482,8 +479,8 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _ @@ -482,8 +479,8 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
console.log("Remove usermedia stream from peer connection", pc, this.localStream);
if (this.localStream) {
pc.removeStream(this.localStream);
if (peerconnections.hasOwnProperty(pc.id)) {
delete peerconnections[pc.id];
if (this.peerconnections.hasOwnProperty(pc.id)) {
delete this.peerconnections[pc.id];
}
}

70
static/js/mediastream/webrtc.js

@ -54,6 +54,8 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -54,6 +54,8 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
this.started = false;
this.initiator = null;
this.usermedia = null;
this.audioMute = false;
this.videoMute = false;
@ -112,7 +114,8 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -112,7 +114,8 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
videoSendCodec: "VP8/90000"
//videoRecvBitrate: ,
//videoRecvCodec
}
},
renegotiation: true
};
this.screensharingSettings = {
@ -121,17 +124,6 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -121,17 +124,6 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
this.api.e.bind("received.offer received.candidate received.answer received.bye received.conference", _.bind(this.processReceived, this));
// Create default media (audio/video).
this.usermedia = new UserMedia();
this.usermedia.e.on("mediasuccess mediaerror", _.bind(function() {
// Start always, no matter what.
this.maybeStart();
}, this));
this.usermedia.e.on("mediachanged", _.bind(function() {
// Propagate media change events.
this.e.triggerHandler("usermedia", [this.usermedia]);
}, this));
};
WebRTC.prototype.processReceived = function(event, to, data, type, to2, from) {
@ -396,6 +388,39 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -396,6 +388,39 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
};
WebRTC.prototype.doUserMedia = function(currentcall) {
// Create default media (audio/video).
var usermedia = new UserMedia({
renegotiation: this.settings.renegotiation,
audioMute: this.audioMute,
videoMute: this.videoMute
});
usermedia.e.on("mediasuccess mediaerror", _.bind(function(event, um) {
this.e.triggerHandler("usermedia", [usermedia]);
// Start always, no matter what.
this.maybeStart(um);
}, this));
usermedia.e.on("mediachanged", _.bind(function(event, um) {
// Propagate media change events.
this.e.triggerHandler("usermedia", [um]);
}, this));
usermedia.e.on("stopped", _.bind(function(event, um) {
if (um === this.usermedia) {
this.e.triggerHandler("usermedia", [null]);
this.usermedia = null;
}
}, this));
this.e.one("stop", function() {
usermedia.stop();
});
this.usermedia = usermedia;
this.e.triggerHandler("usermedia", [usermedia]);
return usermedia.doGetUserMedia(currentcall);
};
WebRTC.prototype.doCall = function(id) {
if (this.currentcall) {
@ -413,7 +438,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -413,7 +438,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
} else {
var currentcall = this.currentcall = this.createCall(id, null, id);
this.e.triggerHandler("peercall", [currentcall]);
var ok = this.usermedia.doGetUserMedia(currentcall);
var ok = this.doUserMedia(currentcall);
if (ok) {
this.e.triggerHandler("waitforusermedia", [currentcall]);
} else {
@ -432,7 +457,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -432,7 +457,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
console.warn("Trying to accept without a call.", currentcall);
return;
}
var ok = this.usermedia.doGetUserMedia(currentcall);
var ok = this.doUserMedia(currentcall);
if (ok) {
this.e.triggerHandler("waitforusermedia", [currentcall]);
} else {
@ -501,7 +526,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -501,7 +526,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
WebRTC.prototype.doScreenshare = function(options) {
var usermedia = new UserMedia({
noaudio: true
noAudio: true
});
var ok = usermedia.doGetUserMedia(null, PeerScreenshare.getCaptureMediaConstraints(this, options));
if (ok) {
@ -579,11 +604,9 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -579,11 +604,9 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
this.currentcall.close();
this.currentcall = null;
}
if (this.usermedia) {
this.usermedia.stop();
}
this.e.triggerHandler("peerconference", [null]);
this.e.triggerHandler("peercall", [null]);
this.e.triggerHandler("stop");
this.msgQueue.length = 0;
this.initiator = null;
this.started = false;
@ -629,7 +652,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -629,7 +652,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
}
WebRTC.prototype.maybeStart = function() {
WebRTC.prototype.maybeStart = function(usermedia) {
//console.log("maybeStart", this.started);
if (!this.started) {
@ -640,14 +663,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -640,14 +663,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
console.log('Creating PeerConnection.', currentcall);
currentcall.createPeerConnection(_.bind(function(peerconnection) {
// Success call.
if (this.usermedia) {
this.usermedia.applyVideoMute(this.videoMute);
this.usermedia.applyAudioMute(this.audioMute);
this.e.triggerHandler("usermedia", [this.usermedia]);
this.usermedia.addToPeerConnection(peerconnection);
} else {
_.defer(peerconnection.negotiationNeeded);
}
usermedia.addToPeerConnection(peerconnection);
this.started = true;
if (!this.initiator) {
this.calleeStart();

4
static/js/services/mediastream.js

@ -43,6 +43,10 @@ define([ @@ -43,6 +43,10 @@ define([
// Create encryption key from server token and browser name.
var secureKey = sjcl.codec.base64.fromBits(sjcl.hash.sha256.hash(context.Cfg.Token + uaparser().browser.name));
// Apply configuration details.
webrtc.settings.renegotiation = context.Cfg.WebRTC ? context.Cfg.WebRTC.Renegotiation : false;
// mediaStream service API.
var mediaStream = {
version: version,
ws: url,

Loading…
Cancel
Save