Merge pull request #591 in FS/freeswitch from feature/FS-8293 to master
* commit '1ee2f0abc224fd6830fb8a2ddf120abfd8f641f0': add colors to good and bad update new pass FS-8293 [verto_communicator] - Showing speed in the menu bar if autoBand is true, adding option to test speed before making a call, enabling dedEnc if inboundBandwidth is below dedEncWatermark (3072 by default). FS-8293 [verto_communicator] - Changed info in the top menu bar for a icon+popover, changed autoBand's code in testSpeed method, moved 'Bandwidth settings' to 'Video settings' in settings modal and now hidding video quality selection when autoBand is checked. FS-8293 [verto_communicator] - Better bandwidth info ui. FS-8293 [verto_communicator] - Fixed speed test breaking at splash screen if user isn't logged in. Removed unused function. FS-8293 [verto_communicator] Implemented speed test in verto communicator. always change bw tweaks WIP not shabby auto vid settings first pass, add some funcs to conference and speed test features and fix bugs in ws.c for big payloads
This commit is contained in:
commit
785727e6fa
|
@ -91,6 +91,32 @@
|
|||
/// The next JSON-RPC request id.
|
||||
$.JsonRpcClient.prototype._current_id = 1;
|
||||
|
||||
|
||||
$.JsonRpcClient.prototype.speedTest = function (bytes, cb) {
|
||||
var socket = this.options.getSocket(this.wsOnMessage);
|
||||
if (socket !== null) {
|
||||
this.speedCB = cb;
|
||||
this.speedBytes = bytes;
|
||||
socket.send("#SPU " + bytes);
|
||||
|
||||
var loops = bytes / 1024;
|
||||
var rem = bytes % 1024;
|
||||
var i;
|
||||
var data = new Array(1024).join(".");
|
||||
for (i = 0; i < loops; i++) {
|
||||
socket.send("#SPB " + data);
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
socket.send("#SPB " + data);
|
||||
}
|
||||
|
||||
socket.send("#SPE");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @fn call
|
||||
* @memberof $.JsonRpcClient
|
||||
|
@ -382,6 +408,26 @@
|
|||
$.JsonRpcClient.prototype._wsOnMessage = function(event) {
|
||||
// Check if this could be a JSON RPC message.
|
||||
var response;
|
||||
|
||||
// Special sub proto
|
||||
if (event.data[0] == "#" && event.data[1] == "S" && event.data[2] == "P") {
|
||||
if (event.data[3] == "U") {
|
||||
this.up_dur = parseInt(event.data.substring(4));
|
||||
} else if (this.speedCB && event.data[3] == "D") {
|
||||
this.down_dur = parseInt(event.data.substring(4));
|
||||
|
||||
var up_kps = (((this.speedBytes * 8) / (this.up_dur / 1000)) / 1024).toFixed(0);
|
||||
var down_kps = (((this.speedBytes * 8) / (this.down_dur / 1000)) / 1024).toFixed(0);
|
||||
|
||||
console.info("Speed Test: Up: " + up_kps + " Down: " + down_kps);
|
||||
this.speedCB(event, { upDur: this.up_dur, downDur: this.down_dur, upKPS: up_kps, downKPS: down_kps });
|
||||
this.speedCB = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
response = $.parseJSON(event.data);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"grunt-contrib-copy": "^0.7.0",
|
||||
"grunt-contrib-cssmin": "^0.12.0",
|
||||
"grunt-contrib-htmlmin": "^0.4.0",
|
||||
"grunt-contrib-imagemin": "^0.9.2",
|
||||
"grunt-contrib-imagemin": "^1.0.0",
|
||||
"grunt-contrib-jshint": "^0.11.0",
|
||||
"grunt-contrib-uglify": "^0.7.0",
|
||||
"grunt-contrib-watch": "latest",
|
||||
|
|
|
@ -1481,6 +1481,43 @@ body:-webkit-full-screen #incall .video-footer {
|
|||
.preview-wrapper video {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.drop-net-info {
|
||||
padding-top: 0px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.drop-net-info .title {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 8px 14px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
}
|
||||
|
||||
.drop-net-info .title:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.drop-net-info a:hover {
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.net-info .yellow {
|
||||
color: #e3d95b;
|
||||
}
|
||||
|
||||
.net-info .green {
|
||||
color: #00ae00;
|
||||
}
|
||||
|
||||
.net-info .red {
|
||||
color: #ae0000;
|
||||
}
|
||||
|
||||
#mic-meter {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
<div class="centered-block-frame" id="dialpad">
|
||||
<div ng-show="loading">
|
||||
<h3 style="margin-top: 4%;" class="text-center">Calling to {{ dialpadNumber }}...</h3>
|
||||
<svg class="spinner" width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="centered-block-frame" id="dialpad" ng-show="!loading">
|
||||
<div id="call-history-wrapper">
|
||||
<div id="call_history" class="shadow-z-2 panel">
|
||||
<div class="panel-heading">
|
||||
|
|
|
@ -19,9 +19,21 @@
|
|||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="navbar-item-icon net-info" ng-show="(bandUp || bandDown) && storage.data.autoBand">
|
||||
<a href="" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
||||
<i ng-class="iconClass"></i>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu drop-net-info" role="menu" ng-click="$event.stopPropagation()">
|
||||
<li><a class="title">Bandwidth Info</a></li>
|
||||
<li><a>Outgoing: {{bandUp}} Kbps</a></li>
|
||||
<li><a>Incoming: {{bandDown}} Kbps</a></li>
|
||||
<li><a>Video Resolution: {{vidRes}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="">
|
||||
<i class="mdi-toggle-radio-button-on" user-status condition="storage.data.userStatus"></i>
|
||||
<i class="mdi-toggle-radio-button-on" user-status condition="storage.data.userStatus"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -29,7 +41,6 @@
|
|||
{{ storage.data.called_number && storage.data.userStatus == 'connecting' ? 'Last Call: ' : 'In Call: ' }} {{ storage.data.called_number }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="navbar-item-icon" ng-show="verto.data.connected">
|
||||
<a href="" ng-click="openModal('partials/modal_settings.html', 'ModalSettingsController')">
|
||||
<i class="mdi-action-settings"></i>
|
||||
|
|
|
@ -84,35 +84,53 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="video-quality">Video quality:</label>
|
||||
<select name="video_quality" id="video-quality" class="form-control"
|
||||
ng-model="mydata.vidQual"
|
||||
ng-options="item.id as item.label for item in verto.videoQuality"></select>
|
||||
</div>
|
||||
<label>Video settings:</label> <br><br>
|
||||
<a class="btn btn-primary" href="" ng-click="testSpeed()">Check Speed</a>
|
||||
<span ng-bind="speedMsg"></span>
|
||||
|
||||
<input type="hidden" name="use_dedenc" ng-value="mydata.useDedenc" ng-model="mydata.useDedenc">
|
||||
<input type="hidden" name="use_dedenc" ng-value="mydata.useDedenc" ng-model="mydata.useDedenc">
|
||||
|
||||
<h4>Dedicated Remote Encoder</h4>
|
||||
<h5>Select a non default bandwidth to use a dedicated remote encoder.</h5>
|
||||
|
||||
<div ng-show="mydata.useDedenc" class="dedicated_encoder">
|
||||
<p>Dedicated Remote Encoder enabled.</b>
|
||||
</div>
|
||||
<div ng-show="mydata.useDedenc" class="dedicated_encoder">
|
||||
<p>Dedicated Remote Encoder enabled.</b>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="outgoing-bandwidth">Max outgoing bandwidth:</label>
|
||||
<select name="outgoing_bandwidth" id="outgoing-bandwidth" class="form-control"
|
||||
ng-model="mydata.outgoingBandwidth"
|
||||
ng-change="checkUseDedRemoteEncoder(mydata.outgoingBandwidth)"
|
||||
ng-options="item.id as item.label for item in verto.bandwidth"></select>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="mydata.autoBand" ng-change="checkAutoBand(mydata.autoBand)">
|
||||
Auto
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="incoming-bandwidth">Max incoming bandwidth:</label>
|
||||
<select name="incoming_bandwidth" id="incoming-bandwidth" class="form-control"
|
||||
ng-model="mydata.incomingBandwidth"
|
||||
ng-change="checkUseDedRemoteEncoder(mydata.incomingBandwidth)"
|
||||
ng-options="item.id as item.label for item in verto.bandwidth"></select>
|
||||
<div class="checkbox" ng-show="mydata.autoBand">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="mydata.testSpeedJoin">
|
||||
Check bandwidth before joining call
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div ng-show="!mydata.autoBand">
|
||||
<label for="video-quality">Video quality:</label>
|
||||
<select name="video_quality" id="video-quality" class="form-control"
|
||||
ng-disabled="mydata.autoBand"
|
||||
ng-model="mydata.vidQual"
|
||||
ng-options="item.id as item.label for item in verto.videoQuality"></select>
|
||||
</div>
|
||||
|
||||
<div ng-show="!mydata.autoBand">
|
||||
<label for="incoming-bandwidth">Max incoming bandwidth:</label>
|
||||
<select name="incoming_bandwidth" id="incoming-bandwidth" class="form-control"
|
||||
ng-model="mydata.incomingBandwidth"
|
||||
ng-change="checkUseDedRemoteEncoder(mydata.incomingBandwidth)"
|
||||
ng-options="item.id as item.label for item in verto.bandwidth"></select>
|
||||
</div>
|
||||
|
||||
<div ng-show="!mydata.autoBand">
|
||||
<label for="outgoing-bandwidth">Max outgoing bandwidth:</label>
|
||||
<select name="outgoing_bandwidth" id="outgoing-bandwidth" class="form-control"
|
||||
ng-model="mydata.outgoingBandwidth"
|
||||
ng-options="item.id as item.label for item in verto.bandwidth"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
.module('storageService')
|
||||
.service('splashscreen', ['$rootScope', '$q', 'storage', 'config', 'verto',
|
||||
function($rootScope, $q, storage, config, verto) {
|
||||
|
||||
|
||||
var checkBrowser = function() {
|
||||
return $q(function(resolve, reject) {
|
||||
var activity = 'browser-upgrade';
|
||||
|
@ -22,10 +22,10 @@
|
|||
if (!navigator.getUserMedia) {
|
||||
result['status'] = 'error';
|
||||
result['message'] = 'Error: browser doesn\'t support WebRTC.';
|
||||
reject(result);
|
||||
reject(result);
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
resolve(result);
|
||||
|
||||
});
|
||||
};
|
||||
|
@ -48,7 +48,7 @@
|
|||
reject(result);
|
||||
}
|
||||
verto.data.mediaPerm = true;
|
||||
resolve(result);
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -62,7 +62,7 @@
|
|||
'activity': activity,
|
||||
'message': 'Refresh Media Devices.'
|
||||
};
|
||||
|
||||
|
||||
verto.refreshDevices(function(status) {
|
||||
verto.refreshDevicesCallback(function() {
|
||||
resolve(result);
|
||||
|
@ -72,6 +72,28 @@
|
|||
});
|
||||
};
|
||||
|
||||
var checkConnectionSpeed = function() {
|
||||
return $q(function(resolve, reject) {
|
||||
var activity = 'check-connection-speed';
|
||||
var result = {
|
||||
'status': 'success',
|
||||
'soft': true,
|
||||
'activity': activity,
|
||||
'message': 'Check Connection Speed.'
|
||||
};
|
||||
|
||||
if (storage.data.autoBand && verto.data.instance) {
|
||||
verto.testSpeed(cb);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
function cb(data) {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var provisionConfig = function() {
|
||||
return $q(function(resolve, reject) {
|
||||
var activity = 'provision-config';
|
||||
|
@ -100,7 +122,7 @@
|
|||
});
|
||||
|
||||
result['promise'] = configPromise;
|
||||
|
||||
|
||||
resolve(result);
|
||||
});
|
||||
};
|
||||
|
@ -136,13 +158,13 @@
|
|||
verto.data.connecting = false;
|
||||
resolve(result);
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if(storage.data.ui_connected && storage.data.ws_connected) {
|
||||
checkUserStored();
|
||||
checkUserStored();
|
||||
} else {
|
||||
resolve(result);
|
||||
resolve(result);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -152,7 +174,8 @@
|
|||
checkMediaPerm,
|
||||
refreshMediaDevices,
|
||||
provisionConfig,
|
||||
checkLogin
|
||||
checkLogin,
|
||||
checkConnectionSpeed
|
||||
];
|
||||
|
||||
var progress_message = [
|
||||
|
@ -160,12 +183,13 @@
|
|||
'Checking media permissions',
|
||||
'Refresh Media Devices.',
|
||||
'Provisioning configuration.',
|
||||
'Checking login.'
|
||||
'Checking login.',
|
||||
'Check Connection Speed.'
|
||||
];
|
||||
|
||||
|
||||
var getProgressMessage = function(current_progress) {
|
||||
if(progress_message[current_progress] != undefined) {
|
||||
return progress_message[current_progress];
|
||||
return progress_message[current_progress];
|
||||
} else {
|
||||
return 'Please wait...';
|
||||
}
|
||||
|
@ -176,7 +200,7 @@
|
|||
|
||||
var calculateProgress = function(index) {
|
||||
var _progress;
|
||||
|
||||
|
||||
_progress = index + 1;
|
||||
progress_percentage = (_progress / progress.length) * 100;
|
||||
return progress_percentage;
|
||||
|
@ -186,12 +210,12 @@
|
|||
var fn, fn_return, status, interrupt, activity, soft, message, promise;
|
||||
interrupt = false;
|
||||
current_progress++;
|
||||
|
||||
|
||||
if(current_progress >= progress.length) {
|
||||
$rootScope.$emit('progress.complete', current_progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fn = progress[current_progress];
|
||||
fn_return = fn();
|
||||
|
||||
|
@ -221,7 +245,7 @@
|
|||
emitNextProgress(fn_return);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -232,4 +256,3 @@
|
|||
};
|
||||
|
||||
}]);
|
||||
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
askRecoverCall: false,
|
||||
googNoiseSuppression: true,
|
||||
googHighpassFilter: true,
|
||||
googEchoCancellation: true
|
||||
googEchoCancellation: true,
|
||||
autoBand: true,
|
||||
testSpeedJoin: true
|
||||
};
|
||||
|
||||
data.$default(defaultSettings);
|
||||
|
|
|
@ -97,8 +97,17 @@
|
|||
/**
|
||||
* Call to the number in the $rootScope.dialpadNumber.
|
||||
*/
|
||||
$scope.loading = false;
|
||||
$rootScope.call = function(extension) {
|
||||
return call(extension);
|
||||
if (!storage.data.testSpeedJoin || !$rootScope.dialpadNumber) {
|
||||
return call(extension);
|
||||
}
|
||||
$scope.loading = true;
|
||||
|
||||
verto.testSpeed(function() {
|
||||
$scope.loading = false;
|
||||
call(extension);
|
||||
});
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
|
|
@ -52,10 +52,13 @@
|
|||
storage.data.email = verto.data.email;
|
||||
storage.data.login = verto.data.login;
|
||||
storage.data.password = verto.data.password;
|
||||
if (storage.data.autoBand) {
|
||||
verto.testSpeed();
|
||||
}
|
||||
|
||||
if (redirect && storage.data.preview) {
|
||||
$location.path('/preview');
|
||||
}
|
||||
else if (redirect) {
|
||||
} else if (redirect) {
|
||||
$location.path('/dialpad');
|
||||
}
|
||||
}
|
||||
|
@ -180,6 +183,9 @@
|
|||
};
|
||||
|
||||
function onWSLogin(ev, data) {
|
||||
if(storage.data.autoBand) {
|
||||
verto.testSpeed();
|
||||
}
|
||||
if(!ws_modalInstance) {
|
||||
return;
|
||||
};
|
||||
|
|
|
@ -4,10 +4,43 @@
|
|||
angular
|
||||
.module('vertoControllers')
|
||||
.controller('MenuController', ['$scope', '$http', '$location',
|
||||
'verto', 'storage',
|
||||
function($scope, $http, $location, verto, storage) {
|
||||
'verto', 'storage', '$rootScope',
|
||||
function($scope, $http, $location, verto, storage, $rootScope) {
|
||||
console.debug('Executing MenuController.');
|
||||
}
|
||||
$scope.storage = storage;
|
||||
|
||||
$rootScope.$on('testSpeed', function(e, data) {
|
||||
var vidQual = storage.data.vidQual;
|
||||
var bwp = 4;
|
||||
|
||||
$scope.bandDown = data.downKPS;
|
||||
$scope.bandUp = data.upKPS;
|
||||
|
||||
if (data.downKPS < 2000) {
|
||||
bwp--;
|
||||
}
|
||||
|
||||
if (data.upKPS < 2000) {
|
||||
bwp--;
|
||||
}
|
||||
|
||||
$scope.iconClass = 'mdi-device-signal-wifi-4-bar green';
|
||||
|
||||
if (bwp < 4) {
|
||||
$scope.iconClass = 'mdi-device-signal-wifi-3-bar yellow';
|
||||
} else if (bwp < 2) {
|
||||
$scope.iconClass = 'mdi-device-signal-wifi-1-bar red';
|
||||
}
|
||||
|
||||
verto.videoQuality.forEach(function(vid) {
|
||||
if (vid.id == vidQual){
|
||||
$scope.vidRes = vid.label;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
$scope.ok = function() {
|
||||
storage.changeData($scope.mydata);
|
||||
verto.data.instance.iceServers(storage.data.useSTUN);
|
||||
if (storage.data.autoBand) {
|
||||
$scope.testSpeed();
|
||||
}
|
||||
$modalInstance.close('Ok.');
|
||||
};
|
||||
|
||||
|
@ -26,6 +29,16 @@
|
|||
return verto.refreshDevices();
|
||||
};
|
||||
|
||||
$scope.testSpeed = function() {
|
||||
return verto.testSpeed(cb);
|
||||
|
||||
function cb(data) {
|
||||
$scope.mydata.vidQual = storage.data.vidQual;
|
||||
$scope.speedMsg = 'Up: ' + data.upKPS + ' Down: ' + data.downKPS;
|
||||
$scope.$apply();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.resetSettings = function() {
|
||||
if (confirm('Factory Reset Settings?')) {
|
||||
storage.factoryReset();
|
||||
|
@ -35,11 +48,22 @@
|
|||
};
|
||||
};
|
||||
|
||||
$scope.checkUseDedRemoteEncoder = function(option) {
|
||||
if ($scope.mydata.incomingBandwidth != 'default' || $scope.mydata.outgoingBandwidth != 'default') {
|
||||
$scope.mydata.useDedenc = true;
|
||||
$scope.checkAutoBand = function(option) {
|
||||
$scope.mydata.useDedenc = false;
|
||||
if (!option) {
|
||||
$scope.mydata.outgoingBandwidth = 'default';
|
||||
$scope.mydata.incomingBandwidth = 'default';
|
||||
$scope.mydata.vidQual = 'hd';
|
||||
} else {
|
||||
$scope.mydata.testSpeedJoin = true;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.checkUseDedRemoteEncoder = function(option) {
|
||||
if (['0', 'default', '5120'].indexOf(option) != -1) {
|
||||
$scope.mydata.useDedenc = false;
|
||||
} else {
|
||||
$scope.mydata.useDedenc = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ vertoService.service('config', ['$rootScope', '$http', '$location', 'storage', '
|
|||
verto.data.googlelogin = data.googlelogin;
|
||||
verto.data.googleclientid = data.googleclientid;
|
||||
}
|
||||
|
||||
|
||||
angular.extend(verto.data, data);
|
||||
|
||||
/**
|
||||
|
@ -62,13 +62,13 @@ vertoService.service('config', ['$rootScope', '$http', '$location', 'storage', '
|
|||
console.debug("auto login per config.json");
|
||||
verto.data.autologin_done = true;
|
||||
}
|
||||
|
||||
|
||||
if(verto.data.autologin && storage.data.name.length && storage.data.email.length && storage.data.login.length && storage.data.password.length) {
|
||||
$rootScope.$emit('config.http.success', data);
|
||||
$rootScope.$emit('config.http.success', data);
|
||||
};
|
||||
return response;
|
||||
}, function(response) {
|
||||
$rootScope.$emit('config.http.error', response);
|
||||
$rootScope.$emit('config.http.error', response);
|
||||
return response;
|
||||
});
|
||||
|
||||
|
@ -79,4 +79,3 @@ vertoService.service('config', ['$rootScope', '$http', '$location', 'storage', '
|
|||
'configure': configure
|
||||
};
|
||||
}]);
|
||||
|
||||
|
|
|
@ -76,6 +76,12 @@ var bandwidth = [{
|
|||
}, {
|
||||
id: '2048',
|
||||
label: '2mb'
|
||||
}, {
|
||||
id: '3196',
|
||||
label: '3mb'
|
||||
}, {
|
||||
id: '4192',
|
||||
label: '4mb'
|
||||
}, {
|
||||
id: '5120',
|
||||
label: '5mb'
|
||||
|
@ -797,6 +803,39 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Do speed test.
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
testSpeed: function(cb) {
|
||||
|
||||
data.instance.rpcClient.speedTest(1024 * 256, function(e, data) {
|
||||
var upBand = Math.ceil(data.upKPS * .75),
|
||||
downBand = Math.ceil(data.downKPS * .75);
|
||||
|
||||
|
||||
if (storage.data.autoBand) {
|
||||
storage.data.incomingBandwidth = downBand;
|
||||
storage.data.outgoingBandwidth = upBand;
|
||||
storage.data.useDedenc = false;
|
||||
storage.data.vidQual = 'hd';
|
||||
|
||||
if (upBand < 512) {
|
||||
storage.data.vidQual = 'qvga';
|
||||
}
|
||||
else if (upBand < 1024) {
|
||||
storage.data.vidQual = 'vga';
|
||||
}
|
||||
}
|
||||
|
||||
if(cb) {
|
||||
cb(data);
|
||||
}
|
||||
|
||||
$rootScope.$emit('testSpeed', data);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Mute the microphone for the current call.
|
||||
*
|
||||
|
|
|
@ -91,7 +91,7 @@ div#preload { display: none; }
|
|||
<body>
|
||||
<div data-role="page" id="page-login" align="center">
|
||||
<div data-role="header" class="page-header">
|
||||
FreeSWITCH Verto™ Video Transcoding Demo
|
||||
FreeSWITCH Verto™ Video Transcoding Demo
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -108,6 +108,18 @@ div#preload { display: none; }
|
|||
</div>
|
||||
|
||||
|
||||
<div data-role="page" id="page-bwtest" align="center">
|
||||
<div data-role="header" class="page-header">
|
||||
FreeSWITCH Verto™ Testing Network Connection
|
||||
</div>
|
||||
|
||||
<h1>Testing Network Connection</h1>
|
||||
<img src="images/speed.gif"/>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div data-role="page" id="page-incall" align="center">
|
||||
<div data-role="header" id="calltitle" class="pageheader">
|
||||
Verto™ IN CALL
|
||||
|
@ -248,7 +260,7 @@ div#preload { display: none; }
|
|||
|
||||
<div data-role="page" id="page-main" align="center">
|
||||
<div data-role="header" class="pageheader">
|
||||
FreeSWITCH Verto™ Video Transcoding Demo
|
||||
FreeSWITCH Verto™ Video Transcoding Demo (<span id="bwinfo">*checking*</span>)
|
||||
</div>
|
||||
<br>
|
||||
<center> <table width="1024" border="0">
|
||||
|
@ -347,9 +359,9 @@ if ($('#devices').is(':visible')) {
|
|||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!--<button data-inline="true" id="showdemo" onclick="toggle_demo();">View Demo Extensions</button>-->
|
||||
<button data-inline="true" id="showdevices" onclick="toggle_device();">View Device Settings</button>
|
||||
<button data-inline="true"id="speedbtn">Check Speed</button>
|
||||
<button data-inline="true"id="logoutbtn">Log Out</button>
|
||||
|
||||
<div id="devices" style="border-style:outset;border-width:2px">
|
||||
|
|
|
@ -95,7 +95,9 @@ $.FSRTC.getValidRes=function(cam,func){var used=[];var cached=localStorage.getIt
|
|||
return func?func(cache):null;}
|
||||
$.FSRTC.validRes=[];resI=0;checkRes(cam,func);}
|
||||
$.FSRTC.checkPerms=function(runtime,check_audio,check_video){getUserMedia({constraints:{audio:check_audio,video:check_video,},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info("media perm init complete");if(runtime){setTimeout(runtime,100,true);}},onerror:function(e){if(check_video&&check_audio){console.error("error, retesting with audio params only");return $.FSRTC.checkPerms(runtime,check_audio,false);}
|
||||
console.error("media perm init error");if(runtime){runtime(false)}}});}})(jQuery);(function($){$.JsonRpcClient=function(options){var self=this;this.options=$.extend({ajaxUrl:null,socketUrl:null,onmessage:null,login:null,passwd:null,sessid:null,loginParams:null,userVariables:null,getSocket:function(onmessage_cb){return self._getSocket(onmessage_cb);}},options);self.ws_cnt=0;this.wsOnMessage=function(event){self._wsOnMessage(event);};};$.JsonRpcClient.prototype._ws_socket=null;$.JsonRpcClient.prototype._ws_callbacks={};$.JsonRpcClient.prototype._current_id=1;$.JsonRpcClient.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
|
||||
console.error("media perm init error");if(runtime){runtime(false)}}});}})(jQuery);(function($){$.JsonRpcClient=function(options){var self=this;this.options=$.extend({ajaxUrl:null,socketUrl:null,onmessage:null,login:null,passwd:null,sessid:null,loginParams:null,userVariables:null,getSocket:function(onmessage_cb){return self._getSocket(onmessage_cb);}},options);self.ws_cnt=0;this.wsOnMessage=function(event){self._wsOnMessage(event);};};$.JsonRpcClient.prototype._ws_socket=null;$.JsonRpcClient.prototype._ws_callbacks={};$.JsonRpcClient.prototype._current_id=1;$.JsonRpcClient.prototype.speedTest=function(bytes,cb){var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this.speedCB=cb;this.speedBytes=bytes;socket.send("#SPU "+bytes);var loops=bytes/512;var rem=bytes%512;var i;var data=new Array(512).join(".");for(i=0;i<loops;i++){socket.send("#SPB "+data);}
|
||||
if(rem){socket.send("#SPB "+data);}
|
||||
socket.send("#SPE");}};$.JsonRpcClient.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
|
||||
if(this.options.sessid){params.sessid=this.options.sessid;}
|
||||
var request={jsonrpc:'2.0',method:method,params:params,id:this._current_id++};if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
|
||||
if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
|
||||
|
@ -113,7 +115,9 @@ console.error("Websocket Lost "+self.ws_cnt+" sleep: "+self.ws_sleep+"msec");sel
|
|||
self.ws_sleep=1000;self.ws_cnt=0;if(self.options.onWSConnect){self.options.onWSConnect(self);}
|
||||
var req;while((req=$.JsonRpcClient.q.pop())){self._ws_socket.send(req);}};}}
|
||||
return self._ws_socket?true:false;};$.JsonRpcClient.prototype._getSocket=function(onmessage_cb){if(this.options.socketUrl===null||!("WebSocket"in window))return null;this.connectSocket(onmessage_cb);return this._ws_socket;};$.JsonRpcClient.q=[];$.JsonRpcClient.prototype._wsCall=function(socket,request,success_cb,error_cb){var request_json=$.toJSON(request);if(socket.readyState<1){self=this;$.JsonRpcClient.q.push(request_json);}else{socket.send(request_json);}
|
||||
if('id'in request&&typeof success_cb!=='undefined'){this._ws_callbacks[request.id]={request:request_json,request_obj:request,success_cb:success_cb,error_cb:error_cb};}};$.JsonRpcClient.prototype._wsOnMessage=function(event){var response;try{response=$.parseJSON(event.data);if(typeof response==='object'&&'jsonrpc'in response&&response.jsonrpc==='2.0'){if('result'in response&&this._ws_callbacks[response.id]){var success_cb=this._ws_callbacks[response.id].success_cb;delete this._ws_callbacks[response.id];success_cb(response.result,this);return;}else if('error'in response&&this._ws_callbacks[response.id]){var error_cb=this._ws_callbacks[response.id].error_cb;var orig_req=this._ws_callbacks[response.id].request;if(!self.authing&&response.error.code==-32000&&self.options.login&&self.options.passwd){self.authing=true;this.call("login",{login:self.options.login,passwd:self.options.passwd,loginParams:self.options.loginParams,userVariables:self.options.userVariables},this._ws_callbacks[response.id].request_obj.method=="login"?function(e){self.authing=false;console.log("logged in");delete self._ws_callbacks[response.id];if(self.options.onWSLogin){self.options.onWSLogin(true,self);}}:function(e){self.authing=false;console.log("logged in, resending request id: "+response.id);var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send(orig_req);}
|
||||
if('id'in request&&typeof success_cb!=='undefined'){this._ws_callbacks[request.id]={request:request_json,request_obj:request,success_cb:success_cb,error_cb:error_cb};}};$.JsonRpcClient.prototype._wsOnMessage=function(event){var response;if(event.data[0]=="#"&&event.data[1]=="S"&&event.data[2]=="P"){if(event.data[3]=="U"){this.up_dur=parseInt(event.data.substring(4));}else if(this.speedCB&&event.data[3]=="D"){this.down_dur=parseInt(event.data.substring(4));var up_kps=(((this.speedBytes*8)/(this.up_dur/1000))/1024).toFixed(0);var down_kps=(((this.speedBytes*8)/(this.down_dur/1000))/1024).toFixed(0);console.info("Speed Test: Up: "+up_kps+" Down: "+down_kps);this.speedCB(event,{upDur:this.up_dur,downDur:this.down_dur,upKPS:up_kps,downKPS:down_kps});this.speedCB=null;}
|
||||
return;}
|
||||
try{response=$.parseJSON(event.data);if(typeof response==='object'&&'jsonrpc'in response&&response.jsonrpc==='2.0'){if('result'in response&&this._ws_callbacks[response.id]){var success_cb=this._ws_callbacks[response.id].success_cb;delete this._ws_callbacks[response.id];success_cb(response.result,this);return;}else if('error'in response&&this._ws_callbacks[response.id]){var error_cb=this._ws_callbacks[response.id].error_cb;var orig_req=this._ws_callbacks[response.id].request;if(!self.authing&&response.error.code==-32000&&self.options.login&&self.options.passwd){self.authing=true;this.call("login",{login:self.options.login,passwd:self.options.passwd,loginParams:self.options.loginParams,userVariables:self.options.userVariables},this._ws_callbacks[response.id].request_obj.method=="login"?function(e){self.authing=false;console.log("logged in");delete self._ws_callbacks[response.id];if(self.options.onWSLogin){self.options.onWSLogin(true,self);}}:function(e){self.authing=false;console.log("logged in, resending request id: "+response.id);var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send(orig_req);}
|
||||
if(self.options.onWSLogin){self.options.onWSLogin(true,self);}},function(e){console.log("error logging in, request id:",response.id);delete self._ws_callbacks[response.id];error_cb(response.error,this);if(self.options.onWSLogin){self.options.onWSLogin(false,self);}});return;}
|
||||
delete this._ws_callbacks[response.id];error_cb(response.error,this);return;}}}catch(err){console.log("ERROR: "+err);return;}
|
||||
if(typeof this.options.onmessage==='function'){event.eventData=response;if(!event.eventData){event.eventData={};}
|
||||
|
|
|
@ -197,7 +197,46 @@ function check_vid() {
|
|||
return use_vid;
|
||||
}
|
||||
|
||||
// Attach audio output device to video element using device/sink ID.
|
||||
function do_speed_test(fn)
|
||||
{
|
||||
goto_page("bwtest");
|
||||
|
||||
vertoHandle.rpcClient.speedTest(1024 * 256, function(e, obj) {
|
||||
//console.error("Up: " + obj.upKPS, "Down: ", obj.downKPS);
|
||||
var vid = "default";
|
||||
//if (outgoingBandwidth === "default") {
|
||||
outgoingBandwidth = Math.ceil(obj.upKPS * .75).toString();
|
||||
|
||||
$("#vqual_hd").prop("checked", true);
|
||||
vid = "1280x720";
|
||||
|
||||
if (outgoingBandwidth < 1024) {
|
||||
$("#vqual_vga").prop("checked", true);
|
||||
vid = "640x480";
|
||||
}
|
||||
if (outgoingBandwidth < 512) {
|
||||
$("#vqual_qvga").prop("checked", true);
|
||||
vid = "320x240";
|
||||
}
|
||||
//}
|
||||
|
||||
if (incomingBandwidth === "default") {
|
||||
incomingBandwidth = Math.ceil(obj.downKPS * .75).toString();
|
||||
}
|
||||
|
||||
console.info(outgoingBandwidth, incomingBandwidth);
|
||||
|
||||
$("#bwinfo").html("<b>Bandwidth: " + "Up: " + obj.upKPS + " Down: " + obj.downKPS + " Vid: " + vid + "</b>");
|
||||
|
||||
if (fn) {
|
||||
fn();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Attach audio output device to video element using device/sink ID.
|
||||
|
||||
function attachSinkId(element, sinkId) {
|
||||
if (typeof element.sinkId !== 'undefined') {
|
||||
element.setSinkId(sinkId)
|
||||
|
@ -559,24 +598,34 @@ var callbacks = {
|
|||
ringing = false;
|
||||
|
||||
if (success) {
|
||||
online(true);
|
||||
|
||||
/*
|
||||
verto.subscribe("presence", {
|
||||
handler: function(v, e) {
|
||||
console.error("PRESENCE:", e);
|
||||
}
|
||||
});
|
||||
*/
|
||||
do_speed_test(function() {
|
||||
|
||||
online(true);
|
||||
goto_page("main");
|
||||
|
||||
if (!window.location.hash) {
|
||||
goto_page("main");
|
||||
}
|
||||
$("input[type='radio']").checkboxradio("refresh");
|
||||
$("input[type='checkbox']").checkboxradio("refresh");
|
||||
|
||||
|
||||
/*
|
||||
verto.subscribe("presence", {
|
||||
handler: function(v, e) {
|
||||
console.error("PRESENCE:", e);
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
if (!window.location.hash) {
|
||||
goto_page("main");
|
||||
}
|
||||
|
||||
if (autocall) {
|
||||
autocall = false;
|
||||
docall();
|
||||
}
|
||||
});
|
||||
|
||||
if (autocall) {
|
||||
autocall = false;
|
||||
docall();
|
||||
}
|
||||
} else {
|
||||
goto_page("main");
|
||||
goto_dialog("login-error");
|
||||
|
@ -765,7 +814,7 @@ function docall() {
|
|||
$("#main_info").html("Trying");
|
||||
|
||||
check_vid_res();
|
||||
|
||||
console.error(outgoingBandwidth, incomingBandwidth);
|
||||
cur_call = vertoHandle.newCall({
|
||||
destination_number: $("#ext").val(),
|
||||
caller_id_name: $("#cidname").val(),
|
||||
|
@ -993,8 +1042,10 @@ function refresh_devices()
|
|||
$("#useshare").selectmenu('refresh', true);
|
||||
|
||||
//$("input[type='radio']).checkboxradio({});
|
||||
$("input[type='radio']").checkboxradio("refresh");
|
||||
$("input[type='checkbox']").checkboxradio("refresh");
|
||||
|
||||
|
||||
//$("input[type='radio']").checkboxradio("refresh");
|
||||
//$("input[type='checkbox']").checkboxradio("refresh");
|
||||
|
||||
//console.error($("#usecamera").find(":selected").val());
|
||||
//$.FSRTC.getValidRes($("#usecamera").find(":selected").val(), undefined);
|
||||
|
@ -1021,7 +1072,7 @@ function refresh_devices()
|
|||
|
||||
function init() {
|
||||
cur_call = null;
|
||||
goto_page("main");
|
||||
goto_page("bwtest");
|
||||
|
||||
$("#usecamera").selectmenu({});
|
||||
$("#usemic").selectmenu({});
|
||||
|
@ -1480,6 +1531,13 @@ function init() {
|
|||
$("#errordisplay").html("");
|
||||
});
|
||||
|
||||
$("#speedbtn").click(function() {
|
||||
do_speed_test(function() {
|
||||
goto_page("main");
|
||||
});
|
||||
$("#errordisplay").html("");
|
||||
});
|
||||
|
||||
$("#loginbtn").click(function() {
|
||||
online(false);
|
||||
vertoHandle.loginData({
|
||||
|
|
|
@ -341,6 +341,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_ses
|
|||
SWITCH_DECLARE(switch_file_handle_t *) switch_core_media_get_video_file(switch_core_session_t *session, switch_rw_t rw);
|
||||
SWITCH_DECLARE(switch_bool_t) switch_core_session_in_video_thread(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(switch_bool_t) switch_core_media_check_dtls(switch_core_session_t *session, switch_media_type_t type);
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_set_outgoing_bitrate(switch_core_session_t *session, switch_media_type_t type, uint32_t bitrate);
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
|
|
|
@ -767,6 +767,19 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
|
|||
conference_utils_member_set_flag_locked(member, MFLAG_NO_MINIMIZE_ENCODING);
|
||||
}
|
||||
|
||||
if ((var = switch_channel_get_variable(member->channel, "rtp_video_max_bandwidth_in"))) {
|
||||
member->max_bw_in = switch_parse_bandwidth_string(var);
|
||||
}
|
||||
|
||||
if ((var = switch_channel_get_variable(member->channel, "rtp_video_max_bandwidth_out"))) {
|
||||
member->max_bw_out = switch_parse_bandwidth_string(var);;
|
||||
|
||||
if (member->max_bw_out < conference->video_codec_settings.video.bandwidth) {
|
||||
conference_utils_member_set_flag_locked(member, MFLAG_NO_MINIMIZE_ENCODING);
|
||||
switch_core_media_set_outgoing_bitrate(member->session, SWITCH_MEDIA_TYPE_VIDEO, member->max_bw_out);
|
||||
}
|
||||
}
|
||||
|
||||
switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
|
||||
switch_channel_set_variable_printf(channel, "conference_moderator", "%s", conference_utils_member_test_flag(member, MFLAG_MOD) ? "true" : "false");
|
||||
switch_channel_set_variable_printf(channel, "conference_ghost", "%s", conference_utils_member_test_flag(member, MFLAG_GHOST) ? "true" : "false");
|
||||
|
|
|
@ -1828,13 +1828,66 @@ void conference_video_pop_next_image(conference_member_t *member, switch_image_t
|
|||
*imgP = img;
|
||||
}
|
||||
|
||||
void conference_video_set_incoming_bitrate(conference_member_t *member, int kps)
|
||||
{
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_BITRATE_REQ;
|
||||
msg.numeric_arg = kps * 1024;
|
||||
msg.from = __FILE__;
|
||||
|
||||
switch_core_session_receive_message(member->session, &msg);
|
||||
member->managed_kps = kps;
|
||||
}
|
||||
|
||||
void conference_video_set_max_incoming_bitrate_member(conference_member_t *member, int kps)
|
||||
{
|
||||
member->max_bw_in = kps;
|
||||
member->managed_kps = 0;
|
||||
}
|
||||
|
||||
void conference_video_set_absolute_incoming_bitrate_member(conference_member_t *member, int kps)
|
||||
{
|
||||
member->max_bw_in = 0;
|
||||
member->force_bw_in = kps;
|
||||
member->managed_kps = 0;
|
||||
if (!conference_utils_test_flag(member->conference, CFLAG_MANAGE_INBOUND_VIDEO_BITRATE) && switch_channel_test_flag(member->channel, CF_VIDEO)) {
|
||||
conference_video_set_incoming_bitrate(member, kps);
|
||||
}
|
||||
}
|
||||
|
||||
void conference_video_set_max_incoming_bitrate(conference_obj_t *conference, int kps)
|
||||
{
|
||||
conference_member_t *imember;
|
||||
|
||||
switch_mutex_lock(conference->member_mutex);
|
||||
for (imember = conference->members; imember; imember = imember->next) {
|
||||
if (imember->channel && switch_channel_ready(imember->channel) && conference_utils_member_test_flag(imember, MFLAG_RUNNING)) {
|
||||
conference_video_set_max_incoming_bitrate_member(imember, kps);
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(conference->member_mutex);
|
||||
}
|
||||
|
||||
void conference_video_set_absolute_incoming_bitrate(conference_obj_t *conference, int kps)
|
||||
{
|
||||
conference_member_t *imember;
|
||||
|
||||
switch_mutex_lock(conference->member_mutex);
|
||||
for (imember = conference->members; imember; imember = imember->next) {
|
||||
if (imember->channel && switch_channel_ready(imember->channel) && conference_utils_member_test_flag(imember, MFLAG_RUNNING)) {
|
||||
conference_video_set_absolute_incoming_bitrate_member(imember, kps);
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(conference->member_mutex);
|
||||
}
|
||||
|
||||
void conference_video_check_auto_bitrate(conference_member_t *member, mcu_layer_t *layer)
|
||||
{
|
||||
|
||||
if (switch_channel_test_flag(member->channel, CF_VIDEO_BITRATE_UNMANAGABLE)) {
|
||||
member->managed_kps = 0;
|
||||
} else if (conference_utils_test_flag(member->conference, CFLAG_MANAGE_INBOUND_VIDEO_BITRATE) && !member->managed_kps) {
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
int kps;
|
||||
int w = 320;
|
||||
int h = 240;
|
||||
|
@ -1845,23 +1898,40 @@ void conference_video_check_auto_bitrate(conference_member_t *member, mcu_layer_
|
|||
h = layer->screen_h;
|
||||
}
|
||||
}
|
||||
|
||||
if (!layer || !conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) || member->avatar_png_img) {
|
||||
kps = 200;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps because user's image is not visible\n",
|
||||
|
||||
if (member->conference->force_bw_in || member->force_bw_in) {
|
||||
if (!(kps = member->conference->force_bw_in)) {
|
||||
kps = member->force_bw_in;
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s setting bitrate to %dkps because it was forced.\n",
|
||||
switch_channel_get_name(member->channel), kps);
|
||||
} else {
|
||||
kps = switch_calc_bitrate(w, h, 2, (int)(member->conference->video_fps.fps));
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps to accomodate %dx%d resolution\n",
|
||||
switch_channel_get_name(member->channel), kps, layer->screen_w, layer->screen_h);
|
||||
int max = 0;
|
||||
|
||||
if (!layer || !conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) || member->avatar_png_img) {
|
||||
kps = 256;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps because user's image is not visible\n",
|
||||
switch_channel_get_name(member->channel), kps);
|
||||
} else {
|
||||
kps = switch_calc_bitrate(w, h, 1, (int)(member->conference->video_fps.fps));
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps to accomodate %dx%d resolution\n",
|
||||
switch_channel_get_name(member->channel), kps, layer->screen_w, layer->screen_h);
|
||||
}
|
||||
|
||||
if (member->conference->max_bw_in) {
|
||||
max = member->conference->max_bw_in;
|
||||
} else {
|
||||
max = member->max_bw_in;
|
||||
}
|
||||
|
||||
if (max && kps > max) {
|
||||
kps = max;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s overriding bitrate setting to %dkps because it was the max allowed.\n",
|
||||
switch_channel_get_name(member->channel), kps);
|
||||
}
|
||||
}
|
||||
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_BITRATE_REQ;
|
||||
msg.numeric_arg = kps * 1024;
|
||||
msg.from = __FILE__;
|
||||
|
||||
switch_core_session_receive_message(member->session, &msg);
|
||||
member->managed_kps = kps;
|
||||
conference_video_set_incoming_bitrate(member, kps);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2862,7 +2862,7 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
|
|||
|
||||
if (video_codec_bandwidth) {
|
||||
if (!strcasecmp(video_codec_bandwidth, "auto")) {
|
||||
conference->video_codec_settings.video.bandwidth = switch_calc_bitrate(canvas_w, canvas_h, 2, (int)conference->video_fps.fps);
|
||||
conference->video_codec_settings.video.bandwidth = switch_calc_bitrate(canvas_w, canvas_h, 1, (int)conference->video_fps.fps);
|
||||
} else {
|
||||
conference->video_codec_settings.video.bandwidth = switch_parse_bandwidth_string(video_codec_bandwidth);
|
||||
}
|
||||
|
|
|
@ -657,6 +657,8 @@ typedef struct conference_obj {
|
|||
int recording_members;
|
||||
uint32_t video_floor_packets;
|
||||
video_layout_t *new_personal_vlayout;
|
||||
int max_bw_in;
|
||||
int force_bw_in;
|
||||
} conference_obj_t;
|
||||
|
||||
/* Relationship with another member */
|
||||
|
@ -757,6 +759,9 @@ struct conference_member {
|
|||
switch_media_flow_t video_media_flow;
|
||||
mcu_canvas_t *canvas;
|
||||
switch_image_t *pcanvas_img;
|
||||
int max_bw_in;
|
||||
int force_bw_in;
|
||||
int max_bw_out;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -1844,15 +1844,79 @@ static void client_run(jsock_t *jsock)
|
|||
switch_ssize_t bytes;
|
||||
ws_opcode_t oc;
|
||||
uint8_t *data;
|
||||
|
||||
|
||||
bytes = ws_read_frame(&jsock->ws, &oc, &data);
|
||||
|
||||
|
||||
if (bytes < 0) {
|
||||
die("BAD READ %" SWITCH_SSIZE_T_FMT "\n", bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes) {
|
||||
char *s = (char *) data;
|
||||
|
||||
if (*s == '#') {
|
||||
char repl[2048] = "";
|
||||
switch_time_t a, b;
|
||||
|
||||
if (s[1] == 'S' && s[2] == 'P') {
|
||||
|
||||
if (s[3] == 'U') {
|
||||
int i, size = 0;
|
||||
char *p = s+4;
|
||||
int loops = 0;
|
||||
int rem = 0;
|
||||
int dur = 0, j = 0;
|
||||
|
||||
if (!(size = atoi(p))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
a = switch_time_now();
|
||||
do {
|
||||
bytes = ws_read_frame(&jsock->ws, &oc, &data);
|
||||
s = (char *) data;
|
||||
} while (bytes && data && s[0] == '#' && s[3] == 'B');
|
||||
b = switch_time_now();
|
||||
|
||||
if (!bytes || !data) continue;
|
||||
|
||||
if (s[0] != '#') goto nm;
|
||||
|
||||
switch_snprintf(repl, sizeof(repl), "#SPU %ld", (b - a) / 1000);
|
||||
ws_write_frame(&jsock->ws, WSOC_TEXT, repl, strlen(repl));
|
||||
loops = size / 1024;
|
||||
rem = size % 1024;
|
||||
switch_snprintf(repl, sizeof(repl), "#SPB ");
|
||||
memset(repl+4, '.', 1024);
|
||||
|
||||
for (j = 0; j < 10 ; j++) {
|
||||
int ddur = 0;
|
||||
a = switch_time_now();
|
||||
for (i = 0; i < loops; i++) {
|
||||
ws_write_frame(&jsock->ws, WSOC_TEXT, repl, 1024);
|
||||
}
|
||||
if (rem) {
|
||||
ws_write_frame(&jsock->ws, WSOC_TEXT, repl, rem);
|
||||
}
|
||||
b = switch_time_now();
|
||||
ddur += ((b - a) / 1000);
|
||||
dur += ddur;
|
||||
|
||||
}
|
||||
|
||||
dur /= j+1;
|
||||
|
||||
switch_snprintf(repl, sizeof(repl), "#SPD %d", dur);
|
||||
ws_write_frame(&jsock->ws, WSOC_TEXT, repl, strlen(repl));
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
nm:
|
||||
|
||||
if (process_input(jsock, data, bytes) != SWITCH_STATUS_SUCCESS) {
|
||||
die("Input Error\n");
|
||||
}
|
||||
|
@ -3271,7 +3335,7 @@ static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t
|
|||
|
||||
static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
|
||||
{
|
||||
cJSON *obj = cJSON_CreateObject(), *screenShare = NULL, *dedEnc = NULL, *mirrorInput, *json_ptr = NULL;
|
||||
cJSON *obj = cJSON_CreateObject(), *screenShare = NULL, *dedEnc = NULL, *mirrorInput, *json_ptr = NULL, *bandwidth = NULL;
|
||||
switch_core_session_t *session = NULL;
|
||||
switch_channel_t *channel;
|
||||
switch_event_t *var_event;
|
||||
|
@ -3281,7 +3345,7 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
|
|||
cJSON *dialog;
|
||||
verto_pvt_t *tech_pvt;
|
||||
char name[512];
|
||||
const char *var, *destination_number, *call_id = NULL, *sdp = NULL, *bandwidth = NULL,
|
||||
const char *var, *destination_number, *call_id = NULL, *sdp = NULL,
|
||||
*caller_id_name = NULL, *caller_id_number = NULL, *remote_caller_id_name = NULL, *remote_caller_id_number = NULL,*context = NULL;
|
||||
switch_event_header_t *hp;
|
||||
|
||||
|
@ -3353,15 +3417,19 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
|
|||
switch_channel_set_flag(channel, CF_VIDEO_MIRROR_INPUT);
|
||||
}
|
||||
|
||||
if ((bandwidth = cJSON_GetObjectCstr(dialog, "outgoingBandwidth"))) {
|
||||
if (strcasecmp(bandwidth, "default")) {
|
||||
switch_channel_set_variable(channel, "rtp_video_max_bandwidth_in", bandwidth);
|
||||
if ((bandwidth = cJSON_GetObjectItem(dialog, "outgoingBandwidth"))) {
|
||||
if (!zstr(bandwidth->valuestring) && strcasecmp(bandwidth->valuestring, "default")) {
|
||||
switch_channel_set_variable(channel, "rtp_video_max_bandwidth_in", bandwidth->valuestring);
|
||||
} else if (bandwidth->valueint) {
|
||||
switch_channel_set_variable_printf(channel, "rtp_video_max_bandwidth_in", "%d", bandwidth->valueint);
|
||||
}
|
||||
}
|
||||
|
||||
if ((bandwidth = cJSON_GetObjectCstr(dialog, "incomingBandwidth"))) {
|
||||
if (strcasecmp(bandwidth, "default")) {
|
||||
switch_channel_set_variable(channel, "rtp_video_max_bandwidth_out", bandwidth);
|
||||
if ((bandwidth = cJSON_GetObjectItem(dialog, "incomingBandwidth"))) {
|
||||
if (!zstr(bandwidth->valuestring) && strcasecmp(bandwidth->valuestring, "default")) {
|
||||
switch_channel_set_variable(channel, "rtp_video_max_bandwidth_out", bandwidth->valuestring);
|
||||
} else if (bandwidth->valueint) {
|
||||
switch_channel_set_variable_printf(channel, "rtp_video_max_bandwidth_out", "%d", bandwidth->valueint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ int ws_handshake(wsh_t *wsh)
|
|||
}
|
||||
}
|
||||
|
||||
if (bytes > sizeof(wsh->buffer) -1) {
|
||||
if (bytes > wsh->buflen -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
|
|||
}
|
||||
}
|
||||
|
||||
} while (r == -1 && err == SSL_ERROR_WANT_READ && wsh->x < 100);
|
||||
} while (r == -1 && err == SSL_ERROR_WANT_READ && wsh->x < 1000);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
|
|||
ms_sleep(10);
|
||||
}
|
||||
}
|
||||
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 100);
|
||||
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 1000);
|
||||
|
||||
if (wsh->x >= 1000 || (block && wsh->x >= 100)) {
|
||||
r = -1;
|
||||
|
@ -596,7 +596,15 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int
|
|||
wsh->close_sock = 1;
|
||||
}
|
||||
|
||||
wsh->buflen = sizeof(wsh->buffer);
|
||||
wsh->buflen = 1024 * 64;
|
||||
wsh->bbuflen = wsh->buflen;
|
||||
|
||||
wsh->buffer = malloc(wsh->buflen);
|
||||
wsh->bbuffer = malloc(wsh->bbuflen);
|
||||
//printf("init %p %ld\n", (void *) wsh->bbuffer, wsh->bbuflen);
|
||||
//memset(wsh->buffer, 0, wsh->buflen);
|
||||
//memset(wsh->bbuffer, 0, wsh->bbuflen);
|
||||
|
||||
wsh->secure = ssl_ctx ? 1 : 0;
|
||||
|
||||
setup_socket(sock);
|
||||
|
@ -644,6 +652,12 @@ void ws_destroy(wsh_t *wsh)
|
|||
SSL_free(wsh->ssl);
|
||||
wsh->ssl = NULL;
|
||||
}
|
||||
|
||||
if (wsh->buffer) free(wsh->buffer);
|
||||
if (wsh->bbuffer) free(wsh->bbuffer);
|
||||
|
||||
wsh->buffer = wsh->bbuffer = NULL;
|
||||
|
||||
}
|
||||
|
||||
ssize_t ws_close(wsh_t *wsh, int16_t reason)
|
||||
|
@ -685,6 +699,20 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)
|
|||
|
||||
}
|
||||
|
||||
|
||||
uint64_t hton64(uint64_t val)
|
||||
{
|
||||
if (__BYTE_ORDER == __BIG_ENDIAN) return (val);
|
||||
else return __bswap_64(val);
|
||||
}
|
||||
|
||||
uint64_t ntoh64(uint64_t val)
|
||||
{
|
||||
if (__BYTE_ORDER == __BIG_ENDIAN) return (val);
|
||||
else return __bswap_64(val);
|
||||
}
|
||||
|
||||
|
||||
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
||||
{
|
||||
|
||||
|
@ -692,6 +720,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
char *maskp;
|
||||
int ll = 0;
|
||||
int frag = 0;
|
||||
int blen;
|
||||
|
||||
wsh->body = wsh->bbuffer;
|
||||
wsh->packetlen = 0;
|
||||
|
||||
again:
|
||||
need = 2;
|
||||
|
@ -745,12 +777,11 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
int fin = (wsh->buffer[0] >> 7) & 1;
|
||||
int mask = (wsh->buffer[1] >> 7) & 1;
|
||||
|
||||
if (fin) {
|
||||
if (*oc == WSOC_CONTINUATION) {
|
||||
frag = 1;
|
||||
} else {
|
||||
frag = 0;
|
||||
}
|
||||
|
||||
if (!fin && *oc != WSOC_CONTINUATION) {
|
||||
frag = 1;
|
||||
} else if (fin && *oc == WSOC_CONTINUATION) {
|
||||
frag = 0;
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
|
@ -765,23 +796,33 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
|
||||
wsh->plen = wsh->buffer[1] & 0x7f;
|
||||
wsh->payload = &wsh->buffer[2];
|
||||
|
||||
|
||||
if (wsh->plen == 127) {
|
||||
uint64_t *u64;
|
||||
int more = 0;
|
||||
|
||||
need += 8;
|
||||
|
||||
if (need > wsh->datalen) {
|
||||
/* too small - protocol err */
|
||||
*oc = WSOC_CLOSE;
|
||||
return ws_close(wsh, WS_PROTO_ERR);
|
||||
}
|
||||
//*oc = WSOC_CLOSE;
|
||||
//return ws_close(wsh, WS_PROTO_ERR);
|
||||
|
||||
more = ws_raw_read(wsh, wsh->buffer + wsh->datalen, need - wsh->datalen, WS_BLOCK);
|
||||
|
||||
if (more < need - wsh->datalen) {
|
||||
*oc = WSOC_CLOSE;
|
||||
return ws_close(wsh, WS_PROTO_ERR);
|
||||
} else {
|
||||
wsh->datalen += more;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
u64 = (uint64_t *) wsh->payload;
|
||||
wsh->payload += 8;
|
||||
|
||||
wsh->plen = ntohl((u_long)*u64);
|
||||
|
||||
wsh->plen = ntoh64(*u64);
|
||||
} else if (wsh->plen == 126) {
|
||||
uint16_t *u16;
|
||||
|
||||
|
@ -811,16 +852,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
return ws_close(wsh, WS_PROTO_ERR);
|
||||
}
|
||||
|
||||
if ((need + wsh->datalen) > (ssize_t)wsh->buflen) {
|
||||
/* too big - Ain't nobody got time fo' dat */
|
||||
*oc = WSOC_CLOSE;
|
||||
return ws_close(wsh, WS_DATA_TOO_BIG);
|
||||
blen = wsh->body - wsh->bbuffer;
|
||||
|
||||
if (need + blen > (ssize_t)wsh->bbuflen) {
|
||||
void *tmp;
|
||||
|
||||
wsh->bbuflen = need + blen + wsh->rplen;
|
||||
|
||||
if ((tmp = realloc(wsh->bbuffer, wsh->bbuflen))) {
|
||||
wsh->bbuffer = tmp;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
||||
wsh->body = wsh->bbuffer + blen;
|
||||
}
|
||||
|
||||
wsh->rplen = wsh->plen - need;
|
||||
|
||||
|
||||
if (wsh->rplen) {
|
||||
memcpy(wsh->body, wsh->payload, wsh->rplen);
|
||||
}
|
||||
|
||||
while(need) {
|
||||
ssize_t r = ws_raw_read(wsh, wsh->payload + wsh->rplen, need, WS_BLOCK);
|
||||
ssize_t r = ws_raw_read(wsh, wsh->body + wsh->rplen, need, WS_BLOCK);
|
||||
|
||||
if (r < 1) {
|
||||
/* invalid read - protocol err .. */
|
||||
|
@ -837,28 +892,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
ssize_t i;
|
||||
|
||||
for (i = 0; i < wsh->datalen; i++) {
|
||||
wsh->payload[i] ^= maskp[i % 4];
|
||||
wsh->body[i] ^= maskp[i % 4];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (*oc == WSOC_PING) {
|
||||
ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen);
|
||||
ws_write_frame(wsh, WSOC_PONG, wsh->body, wsh->rplen);
|
||||
goto again;
|
||||
}
|
||||
|
||||
*(wsh->body+wsh->rplen) = '\0';
|
||||
wsh->packetlen += wsh->rplen;
|
||||
wsh->body += wsh->rplen;
|
||||
|
||||
if (frag) {
|
||||
goto again;
|
||||
}
|
||||
|
||||
*data = (uint8_t *)wsh->bbuffer;
|
||||
|
||||
|
||||
*(wsh->payload+wsh->rplen) = '\0';
|
||||
*data = (uint8_t *)wsh->payload;
|
||||
|
||||
//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->rplen, *oc, (char *)*data);
|
||||
//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->packetlen, *oc, (char *)*data);
|
||||
|
||||
|
||||
return wsh->rplen;
|
||||
return wsh->packetlen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -871,6 +928,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes)
|
||||
{
|
||||
|
||||
|
@ -885,6 +943,7 @@ ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes)
|
|||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc)
|
||||
{
|
||||
ssize_t r = 0;
|
||||
|
@ -899,7 +958,7 @@ ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc)
|
|||
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
|
||||
{
|
||||
|
@ -934,7 +993,7 @@ ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
|
|||
hlen += 8;
|
||||
|
||||
u64 = (uint64_t *) &hdr[2];
|
||||
*u64 = htonl(bytes);
|
||||
*u64 = hton64(bytes);
|
||||
}
|
||||
|
||||
if (wsh->write_buffer_len < (hlen + bytes + 1)) {
|
||||
|
|
|
@ -78,15 +78,18 @@ typedef enum {
|
|||
|
||||
typedef struct wsh_s {
|
||||
ws_socket_t sock;
|
||||
char buffer[65536];
|
||||
char wbuffer[65536];
|
||||
char *buffer;
|
||||
char *bbuffer;
|
||||
char *body;
|
||||
char *uri;
|
||||
size_t buflen;
|
||||
size_t bbuflen;
|
||||
ssize_t datalen;
|
||||
ssize_t wdatalen;
|
||||
char *payload;
|
||||
ssize_t plen;
|
||||
ssize_t rplen;
|
||||
ssize_t packetlen;
|
||||
SSL *ssl;
|
||||
int handshake;
|
||||
uint8_t down;
|
||||
|
|
|
@ -8890,6 +8890,30 @@ SWITCH_DECLARE(switch_bool_t) switch_core_media_check_dtls(switch_core_session_t
|
|||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_set_outgoing_bitrate(switch_core_session_t *session, switch_media_type_t type, uint32_t bitrate)
|
||||
{
|
||||
switch_media_handle_t *smh;
|
||||
switch_rtp_engine_t *engine;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (!(smh = session->media_handle)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (switch_channel_down(session->channel)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
engine = &smh->engines[type];
|
||||
|
||||
if (switch_core_codec_ready(&engine->write_codec)) {
|
||||
status = switch_core_codec_control(&engine->write_codec, SCC_VIDEO_BANDWIDTH,
|
||||
SCCT_INT, &bitrate, SCCT_NONE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//?
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue