Browse Source

Implemented constraints service and moved all contraints releated code there.

Refactored settings to use the new constraints refresh event to inject the constraints controlled by settings.
pull/152/head
Simon Eisenmann 11 years ago
parent
commit
8901b5c9ff
  1. 162
      static/js/controllers/mediastreamcontroller.js
  2. 104
      static/js/directives/settings.js
  3. 134
      static/js/services/constraints.js
  4. 9
      static/js/services/services.js

162
static/js/controllers/mediastreamcontroller.js

@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
*/
define(['jquery', 'underscore', 'angular', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapter'], function($, _, angular, BigScreen, moment, sjcl, Modernizr) {
return ["$scope", "$rootScope", "$element", "$window", "$timeout", "safeDisplayName", "safeApply", "mediaStream", "appData", "playSound", "desktopNotify", "alertify", "toastr", "translation", "fileDownload", "localStorage", "screensharing", "userSettingsData", "localStatus", "dialogs", "rooms", function($scope, $rootScope, $element, $window, $timeout, safeDisplayName, safeApply, mediaStream, appData, playSound, desktopNotify, alertify, toastr, translation, fileDownload, localStorage, screensharing, userSettingsData, localStatus, dialogs, rooms) {
return ["$scope", "$rootScope", "$element", "$window", "$timeout", "safeDisplayName", "safeApply", "mediaStream", "appData", "playSound", "desktopNotify", "alertify", "toastr", "translation", "fileDownload", "localStorage", "screensharing", "userSettingsData", "localStatus", "dialogs", "rooms", "constraints", function($scope, $rootScope, $element, $window, $timeout, safeDisplayName, safeApply, mediaStream, appData, playSound, desktopNotify, alertify, toastr, translation, fileDownload, localStorage, screensharing, userSettingsData, localStatus, dialogs, rooms, constraints) {
/*console.log("route", $route, $routeParams, $location);*/
@ -86,29 +86,6 @@ define(['jquery', 'underscore', 'angular', 'bigscreen', 'moment', 'sjcl', 'moder @@ -86,29 +86,6 @@ define(['jquery', 'underscore', 'angular', 'bigscreen', 'moment', 'sjcl', 'moder
appData.set($scope);
var videoQualityMap = {
tiny: {
maxWidth: 80,
maxHeight: 45
},
low: {
maxWidth: 320,
maxHeight: 180
},
high: {
maxWidth: 640,
maxHeight: 360
},
hd: {
minWidth: 1280,
minHeight: 720
},
fullhd: {
minWidth: 1920,
minHeight: 1080
}
}
var displayName = safeDisplayName;
// Init STUN and TURN servers.
@ -219,9 +196,10 @@ define(['jquery', 'underscore', 'angular', 'bigscreen', 'moment', 'sjcl', 'moder @@ -219,9 +196,10 @@ define(['jquery', 'underscore', 'angular', 'bigscreen', 'moment', 'sjcl', 'moder
console.warn("This is not a WebRTC capable browser.");
return;
}
var settings = $scope.master.settings;
// Create iceServers from scope settings.
// Create iceServers from scope.
var iceServers = [];
var iceServer;
if ($scope.stun.length) {
@ -236,139 +214,13 @@ define(['jquery', 'underscore', 'angular', 'bigscreen', 'moment', 'sjcl', 'moder @@ -236,139 +214,13 @@ define(['jquery', 'underscore', 'angular', 'bigscreen', 'moment', 'sjcl', 'moder
iceServers.push.apply(iceServers, iceServer);
}
}
mediaStream.webrtc.settings.pcConfig.iceServers = iceServers;
var audioConstraints = [];
var videoConstraints = [];
var videoConstraintsMandatory = {};
var screensharingConstraints = [];
var pushmulti = function(arrays, data) {
_.each(arrays, function(a) {
a.push(data);
});
};
// Chrome only constraints.
if ($scope.isChrome) {
// Audio settings.
// For defaults in Chromium see https://code.google.com/p/webrtc/source/browse/trunk/talk/media/webrtc/webrtcvoiceengine.cc#225
// Experimental audio settings.
if (settings.experimental.enabled) {
audioConstraints.push({
googEchoCancellation: true // defaults to true
});
audioConstraints.push({
googEchoCancellation2: settings.experimental.audioEchoCancellation2 && true // defaults to false in Chrome
});
audioConstraints.push({
googAutoGainControl: true // defaults to true
});
audioConstraints.push({
googAutoGainControl2: settings.experimental.audioAutoGainControl2 && true // defaults to false in Chrome
});
audioConstraints.push({
googNoiseSuppression: true // defaults to true
});
audioConstraints.push({
googgNoiseSuppression2: settings.experimental.audioNoiseSuppression2 && true // defaults to false in Chrome
});
audioConstraints.push({
googHighpassFilter: true // defaults to true
});
audioConstraints.push({
googTypingNoiseDetection: settings.experimental.audioTypingNoiseDetection && true // defaults to true in Chrome
});
}
if ($scope.supported.renderToAssociatedSink) {
audioConstraints.push({
// When true uses the default communications device on Windows.
// https://codereview.chromium.org/155863003
googDucking: true // defaults to true on Windows.
});
audioConstraints.push({
// Chrome will start rendering mediastream output to an output device that's associated with
// the input stream that was opened via getUserMedia.
// https://chromiumcodereview.appspot.com/23558010
chromeRenderToAssociatedSink: settings.audioRenderToAssociatedSkin && true // defaults to false in Chrome
});
}
// Select microphone device by id.
if (settings.microphoneId) {
audioConstraints.push({
sourceId: settings.microphoneId
});
}
// Select camera by device id.
if (settings.cameraId) {
videoConstraints.push({
sourceId: settings.cameraId
});
}
// Video settings.
if (settings.experimental.enabled) {
// Experimental video settings.
pushmulti([videoConstraints, screensharingConstraints], {
// Changes the way the video encoding adapts to the available bandwidth.
// https://code.google.com/p/webrtc/issues/detail?id=3351
googLeakyBucket: settings.experimental.videoLeakyBucket && true // defaults to false in Chrome
});
pushmulti([videoConstraints, screensharingConstraints], {
// Removes the noise in the captured video stream at the expense of CPU.
googNoiseReduction: settings.experimental.videoNoiseReduction && true // defaults to false in Chrome
});
pushmulti([videoConstraints, screensharingConstraints], {
googCpuOveruseDetection: settings.experimental.videoCpuOveruseDetection && true // defaults to true in Chrome
});
}
// Video.
videoConstraintsMandatory = $.extend(videoConstraintsMandatory, videoQualityMap[settings.videoQuality]);
// Not supported as of Firefox 27.
if (settings.maxFrameRate && settings.maxFrameRate != "auto") {
videoConstraintsMandatory.maxFrameRate = parseInt(settings.maxFrameRate, 10);
}
}
// Apply the shit.
// Stereo.
mediaStream.webrtc.settings.stereo = settings.stereo;
mediaStream.webrtc.settings.mediaConstraints.video.mandatory = videoConstraintsMandatory;
mediaStream.webrtc.settings.mediaConstraints.video.optional = videoConstraints;
mediaStream.webrtc.settings.mediaConstraints.audio = {
optional: audioConstraints
};
mediaStream.webrtc.settings.pcConfig.iceServers = iceServers;
mediaStream.webrtc.settings.screensharing.mediaConstraints.video.optional = screensharingConstraints;
// Inject optional stuff.
var optionalPcConstraints = mediaStream.webrtc.settings.pcConstraints.optional = [];
if ($window.webrtcDetectedBrowser === "chrome") {
// NOTE(longsleep): We can always enable SCTP data channels, as we have a workaround
// using the "active" event for Firefox < 27.
// SCTP does not work correctly with Chrome 31. Require M32.
if ($window.webrtcDetectedVersion >= 32) {
// SCTP is supported from Chrome M31.
// No need to pass DTLS constraint as it is on by default in Chrome M31.
// For SCTP, reliable and ordered is true by default.
} else {
// Chrome < M32 does not yet do DTLS-SRTP by default whereas Firefox only
// does DTLS-SRTP. In order to get interop, you must supply Chrome
// with a PC constructor constraint to enable DTLS.
console.warn("Turning on SCTP combatibility - please update your Chrome.");
optionalPcConstraints.push({
DtlsSrtpKeyAgreement: true
});
}
}
//console.log("WebRTC settings", mediaStream.webrtc.settings);
// Refresh constraints.
constraints.refresh($scope.master.settings);
};
$scope.refreshWebrtcSettings(); // Call once for bootstrap.

104
static/js/directives/settings.js

@ -20,9 +20,32 @@ @@ -20,9 +20,32 @@
*/
define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, template) {
var videoQualityMap = {
tiny: {
maxWidth: 80,
maxHeight: 45
},
low: {
maxWidth: 320,
maxHeight: 180
},
high: {
maxWidth: 640,
maxHeight: 360
},
hd: {
minWidth: 1280,
minHeight: 720
},
fullhd: {
minWidth: 1920,
minHeight: 1080
}
};
return ["$compile", "mediaStream", function($compile, mediaStream) {
var controller = ['$scope', 'desktopNotify', 'mediaSources', 'safeApply', 'availableLanguages', 'translation', 'localStorage', 'userSettingsData', function($scope, desktopNotify, mediaSources, safeApply, availableLanguages, translation, localStorage, userSettingsData) {
var controller = ['$scope', 'desktopNotify', 'mediaSources', 'safeApply', 'availableLanguages', 'translation', 'localStorage', 'userSettingsData', 'constraints', function($scope, desktopNotify, mediaSources, safeApply, availableLanguages, translation, localStorage, userSettingsData, constraints) {
$scope.layout.settings = false;
$scope.showAdvancedSettings = true;
@ -131,17 +154,88 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t @@ -131,17 +154,88 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t
}
});
}];
constraints.e.on("refresh", function(event, constraints) {
var settings = $scope.master.settings;
// Chrome only constraints.
if ($scope.isChrome) {
// For defaults in Chromium see https://code.google.com/p/webrtc/source/browse/trunk/talk/media/webrtc/webrtcvoiceengine.cc#225
// Experimental audio settings.
if (settings.experimental.enabled) {
constraints.add("audio", "googEchoCancellation", true); // defaults to true
constraints.add("audio", "googEchoCancellation2", settings.experimental.audioEchoCancellation2 && true); // defaults to false in Chrome
constraints.add("audio", "googAutoGainControl", true); // defaults to true
constraints.add("audio", "googAutoGainControl2", settings.experimental.audioAutoGainControl2 && true); // defaults to false in Chrome
constraints.add("audio", "googNoiseSuppression", true); // defaults to true
constraints.add("audio", "googgNoiseSuppression2", settings.experimental.audioNoiseSuppression2 && true); // defaults to false in Chrome
constraints.add("audio", "googHighpassFilter", true); // defaults to true
constraints.add("audio", "googTypingNoiseDetection", settings.experimental.audioTypingNoiseDetection && true); // defaults to true in Chrome
}
if ($scope.supported.renderToAssociatedSink) {
// When true uses the default communications device on Windows.
// https://codereview.chromium.org/155863003
constraints.add("audio", "googDucking", true); // defaults to true on Windows.
// Chrome will start rendering mediastream output to an output device that's associated with
// the input stream that was opened via getUserMedia.
// https://chromiumcodereview.appspot.com/23558010
constraints.add("audio", "chromeRenderToAssociatedSink", settings.audioRenderToAssociatedSkin && true); // defaults to false in Chrome
}
// Select microphone device by id.
if (settings.microphoneId) {
constraints.add("audio", "sourceId", settings.microphoneId);
}
// Select camera by device id.
if (settings.cameraId) {
constraints.add("video", "sourceId", settings.cameraId);
}
// Experimental video settings.
if (settings.experimental.enabled) {
// Changes the way the video encoding adapts to the available bandwidth.
// https://code.google.com/p/webrtc/issues/detail?id=3351
constraints.add(["video", "screensharing"], "googLeakyBucket", settings.experimental.videoLeakyBucket && true); // defaults to false in Chrome
// Removes the noise in the captured video stream at the expense of CPU.
constraints.add(["video", "screensharing"], "googNoiseReduction", settings.experimental.videoNoiseReduction && true); // defaults to false in Chrome
constraints.add(["video", "screensharing"], "googCpuOveruseDetection", settings.experimental.videoCpuOveruseDetection && true) // defaults to true in Chrome
var link = function($scope, $element) {};
}
// Set video quality.
var videoQuality = videoQualityMap[settings.videoQuality];
if (videoQuality) {
_.forEach(videoQuality, function(v, k) {
constraints.add("video", k, v, true);
});
}
// Set max frame rate if any was selected.
if (settings.maxFrameRate && settings.maxFrameRate != "auto") {
constraints.add("video", "maxFrameRate", parseInt(settings.maxFrameRate, 10), true);
}
} else {
// Other browsers constraints (there are none as of now.);
}
});
}];
return {
scope: true,
restrict: 'E',
replace: true,
template: template,
controller: controller,
link: link
controller: controller
};
}];

134
static/js/services/constraints.js

@ -0,0 +1,134 @@ @@ -0,0 +1,134 @@
/*
* Spreed WebRTC.
* Copyright (C) 2013-2014 struktur AG
*
* This file is part of Spreed WebRTC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
define(["jquery", "underscore"], function($, _) {
// constraints
return ["webrtc", "$window", function(webrtc, $window) {
var service = this;
var Constraints = function(settings) {
this.settings = _.clone(settings, true);
this.pc = [];
this.audio = [];
this.video = [];
this.videoMandatory = {};
this.screensharing =[];
};
Constraints.prototype.add = function(t, k, v, mandatory) {
if (_.isArray(t)) {
_.forEach(t, function(x) {
this.add(x, k, v, mandatory);
}, this);
return;
}
var obj;
if (mandatory) {
t = t + "Mandatory";
}
obj = this[t];
if (!obj) {
console.warn("Pushed to unknown constraint", t, k, v, mandatory);
} else {
if (mandatory) {
// Mandatory constraints are key/values.
obj[k] = v;
} else {
// Optional constraints are arrays.
var d = {};
d[k] = v;
obj.push(d)
}
}
};
Constraints.prototype.set = function(t, data, mandatory) {
if (mandatory) {
t = t + "Mandatory";
}
if (!this[t]) {
console.warn("Set to unknown constraint", t, data, mandatory);
} else {
this[t] = data;
}
};
service.e = $({}); // events
service.mediaConstraints = function(constraints) {
webrtc.settings.mediaConstraints.audio = {
optional: constraints.audio
};
webrtc.settings.mediaConstraints.video = {
optional: constraints.video,
mandatory: constraints.videoMandatory
};
webrtc.settings.screensharing.mediaConstraints.video.optional = constraints.screensharing;
};
service.pcConstraints = function(constraints) {
webrtc.settings.pcConstraints.optional = constraints.pc;
};
// Some default constraints.
service.e.on("refresh", function(event, constraints) {
if ($window.webrtcDetectedBrowser === "chrome") {
// NOTE(longsleep): We can always enable SCTP data channels, as we have a workaround
// using the "active" event for Firefox < 27.
// SCTP does not work correctly with Chrome 31. Require M32.
if ($window.webrtcDetectedVersion >= 32) {
// SCTP is supported from Chrome M31.
// No need to pass DTLS constraint as it is on by default in Chrome M31.
// For SCTP, reliable and ordered is true by default.
} else {
// Chrome < M32 does not yet do DTLS-SRTP by default whereas Firefox only
// does DTLS-SRTP. In order to get interop, you must supply Chrome
// with a PC constructor constraint to enable DTLS.
console.warn("Turning on SCTP combatibility - please update your Chrome.");
constraints.add("pc", "DtlsSrtpKeyAgreement", true);
}
}
});
// Public API.
return {
e: service.e,
refresh: function(settings) {
var constraints = new Constraints(settings);
service.e.triggerHandler("refresh", [constraints]);
service.mediaConstraints(constraints);
service.pcConstraints(constraints);
},
turn: function(turnData) {
// Set TURN server details.
service.turn = turnData;
},
stun: function(stunData) {
service.stun = stunData;
}
};
}];
});

9
static/js/services/services.js

@ -62,7 +62,8 @@ define([ @@ -62,7 +62,8 @@ define([
'services/localstatus',
'services/rooms',
'services/resturl',
'services/roompin'], function(_,
'services/roompin',
'services/constraints'], function(_,
desktopNotify,
playSound,
safeApply,
@ -104,7 +105,8 @@ userSettingsData, @@ -104,7 +105,8 @@ userSettingsData,
localStatus,
rooms,
restURL,
roompin) {
roompin,
constraints) {
var services = {
desktopNotify: desktopNotify,
@ -148,7 +150,8 @@ roompin) { @@ -148,7 +150,8 @@ roompin) {
localStatus: localStatus,
rooms: rooms,
restURL: restURL,
roompin: roompin
roompin: roompin,
constraints: constraints
};
var initialize = function(angModule) {

Loading…
Cancel
Save