Browse Source

Changes getUserMedia implementation to try lower resolution if the configured one is not supported.

j8
hristoterezov 10 years ago
parent
commit
2362770cce
4 changed files with 295 additions and 142 deletions
  1. 1
    1
      index.html
  2. 159
    82
      libs/app.bundle.js
  3. 82
    59
      modules/RTC/RTCUtils.js
  4. 53
    0
      service/RTC/Resolutions.js

+ 1
- 1
index.html View File

@@ -19,7 +19,7 @@
19 19
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
20 20
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
21 21
     <script src="interface_config.js?v=5"></script>
22
-    <script src="libs/app.bundle.js?v=9"></script>
22
+    <script src="libs/app.bundle.js?v=10"></script>
23 23
 
24 24
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
25 25
     <link rel="stylesheet" href="css/font.css?v=6"/>

+ 159
- 82
libs/app.bundle.js View File

@@ -285,7 +285,7 @@ var API = {
285 285
 };
286 286
 
287 287
 module.exports = API;
288
-},{"../../service/xmpp/XMPPEvents":86}],3:[function(require,module,exports){
288
+},{"../../service/xmpp/XMPPEvents":87}],3:[function(require,module,exports){
289 289
 /* global Strophe, updateLargeVideo, focusedVideoSrc*/
290 290
 
291 291
 // cache datachannels to avoid garbage collection
@@ -607,7 +607,7 @@ LocalStream.prototype.getId = function () {
607 607
 
608 608
 module.exports = LocalStream;
609 609
 
610
-},{"../../service/RTC/StreamEventTypes.js":81}],5:[function(require,module,exports){
610
+},{"../../service/RTC/StreamEventTypes.js":82}],5:[function(require,module,exports){
611 611
 ////These lines should be uncommented when require works in app.js
612 612
 var RTCBrowserType = require("../../service/RTC/RTCBrowserType.js");
613 613
 var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
@@ -873,64 +873,56 @@ var RTC = {
873 873
 
874 874
 module.exports = RTC;
875 875
 
876
-},{"../../service/RTC/MediaStreamTypes":78,"../../service/RTC/StreamEventTypes.js":81,"../../service/UI/UIEvents":82,"../../service/desktopsharing/DesktopSharingEventTypes":84,"../../service/xmpp/XMPPEvents":86,"./DataChannels":3,"./LocalStream.js":4,"./MediaStream.js":5,"./RTCUtils.js":7,"events":87}],7:[function(require,module,exports){
876
+},{"../../service/RTC/MediaStreamTypes":78,"../../service/RTC/StreamEventTypes.js":82,"../../service/UI/UIEvents":83,"../../service/desktopsharing/DesktopSharingEventTypes":85,"../../service/xmpp/XMPPEvents":87,"./DataChannels":3,"./LocalStream.js":4,"./MediaStream.js":5,"./RTCUtils.js":7,"events":88}],7:[function(require,module,exports){
877 877
 var RTCBrowserType = require("../../service/RTC/RTCBrowserType.js");
878
+var Resolutions = require("../../service/RTC/Resolutions");
879
+
880
+var currentResolution = null;
881
+
882
+function getPreviousResolution(resolution) {
883
+    if(!Resolutions[resolution])
884
+        return null;
885
+    var order = Resolutions[resolution].order;
886
+    var res = null;
887
+    var resName = null;
888
+    for(var i in Resolutions)
889
+    {
890
+        var tmp = Resolutions[i];
891
+        if(res == null || (res.order < tmp.order && tmp.order < order))
892
+        {
893
+            resName = i;
894
+            res = tmp;
895
+        }
896
+    }
897
+    return resName;
898
+}
878 899
 
879 900
 function setResolutionConstraints(constraints, resolution, isAndroid)
880 901
 {
881 902
     if (resolution && !constraints.video || isAndroid) {
882 903
         constraints.video = { mandatory: {}, optional: [] };// same behaviour as true
883 904
     }
884
-    // see https://code.google.com/p/chromium/issues/detail?id=143631#c9 for list of supported resolutions
885
-    switch (resolution) {
886
-        // 16:9 first
887
-        case '1080':
888
-        case 'fullhd':
889
-            constraints.video.mandatory.minWidth = 1920;
890
-            constraints.video.mandatory.minHeight = 1080;
891
-            break;
892
-        case '720':
893
-        case 'hd':
894
-            constraints.video.mandatory.minWidth = 1280;
895
-            constraints.video.mandatory.minHeight = 720;
896
-            break;
897
-        case '360':
898
-            constraints.video.mandatory.minWidth = 640;
899
-            constraints.video.mandatory.minHeight = 360;
900
-            break;
901
-        case '180':
902
-            constraints.video.mandatory.minWidth = 320;
903
-            constraints.video.mandatory.minHeight = 180;
904
-            break;
905
-        // 4:3
906
-        case '960':
907
-            constraints.video.mandatory.minWidth = 960;
908
-            constraints.video.mandatory.minHeight = 720;
909
-            break;
910
-        case '640':
911
-        case 'vga':
912
-            constraints.video.mandatory.minWidth = 640;
913
-            constraints.video.mandatory.minHeight = 480;
914
-            break;
915
-        case '320':
905
+
906
+    if(Resolutions[resolution])
907
+    {
908
+        constraints.video.mandatory.minWidth = Resolutions[resolution].width;
909
+        constraints.video.mandatory.minHeight = Resolutions[resolution].height;
910
+    }
911
+    else
912
+    {
913
+        if (isAndroid) {
916 914
             constraints.video.mandatory.minWidth = 320;
917 915
             constraints.video.mandatory.minHeight = 240;
918
-            break;
919
-        default:
920
-            if (isAndroid) {
921
-                constraints.video.mandatory.minWidth = 320;
922
-                constraints.video.mandatory.minHeight = 240;
923
-                constraints.video.mandatory.maxFrameRate = 15;
924
-            }
925
-            break;
916
+            constraints.video.mandatory.maxFrameRate = 15;
917
+        }
926 918
     }
919
+
927 920
     if (constraints.video.mandatory.minWidth)
928 921
         constraints.video.mandatory.maxWidth = constraints.video.mandatory.minWidth;
929 922
     if (constraints.video.mandatory.minHeight)
930 923
         constraints.video.mandatory.maxHeight = constraints.video.mandatory.minHeight;
931 924
 }
932 925
 
933
-
934 926
 function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid)
935 927
 {
936 928
     var constraints = {audio: false, video: false};
@@ -1096,6 +1088,7 @@ RTCUtils.prototype.getUserMediaWithConstraints = function(
1096 1088
     um, success_callback, failure_callback, resolution,bandwidth, fps,
1097 1089
     desktopStream)
1098 1090
 {
1091
+    currentResolution = resolution;
1099 1092
     // Check if we are running on Android device
1100 1093
     var isAndroid = navigator.userAgent.indexOf('Android') != -1;
1101 1094
 
@@ -1154,28 +1147,58 @@ RTCUtils.prototype.getUserMediaWithConstraints = function(
1154 1147
 RTCUtils.prototype.obtainAudioAndVideoPermissions = function() {
1155 1148
     var self = this;
1156 1149
     // Get AV
1157
-    var cb = function (stream) {
1158
-        console.log('got', stream, stream.getAudioTracks().length, stream.getVideoTracks().length);
1159
-        self.handleLocalStream(stream);
1160
-    };
1161
-    var self = this;
1150
+
1162 1151
     this.getUserMediaWithConstraints(
1163 1152
         ['audio', 'video'],
1164
-        cb,
1153
+        function (stream) {
1154
+            self.successCallback(stream);
1155
+        },
1165 1156
         function (error) {
1166
-            console.error('failed to obtain audio/video stream - trying audio only', error);
1167
-            self.getUserMediaWithConstraints(
1168
-                ['audio'],
1169
-                cb,
1170
-                function (error) {
1171
-                    console.error('failed to obtain audio/video stream - stop', error);
1172
-                    APP.UI.messageHandler.showError("Error",
1173
-                            "Failed to obtain permissions to use the local microphone" +
1174
-                            "and/or camera.");
1175
-                }
1176
-            );
1157
+            self.errorCallback(error);
1177 1158
         },
1178
-            config.resolution || '360');
1159
+        config.resolution || '360');
1160
+}
1161
+
1162
+RTCUtils.prototype.successCallback = function (stream) {
1163
+    console.log('got', stream, stream.getAudioTracks().length,
1164
+        stream.getVideoTracks().length);
1165
+    this.handleLocalStream(stream);
1166
+};
1167
+
1168
+RTCUtils.prototype.errorCallback = function (error) {
1169
+    var self = this;
1170
+    console.error('failed to obtain audio/video stream - trying audio only', error);
1171
+    var resolution = getPreviousResolution(currentResolution);
1172
+    if(typeof error == "object" && error.constraintName && error.name
1173
+        && (error.name == "ConstraintNotSatisfiedError" ||
1174
+            error.name == "OverconstrainedError") &&
1175
+        (error.constraintName == "minWidth" || error.constraintName == "maxWidth" ||
1176
+            error.constraintName == "minHeight" || error.constraintName == "maxHeight")
1177
+        && resolution != null)
1178
+    {
1179
+        self.getUserMediaWithConstraints(['audio', 'video'],
1180
+            function (stream) {
1181
+                return self.successCallback(stream);
1182
+            }, function (error) {
1183
+                return self.errorCallback(error);
1184
+            }, resolution);
1185
+    }
1186
+    else
1187
+    {
1188
+        self.getUserMediaWithConstraints(
1189
+            ['audio'],
1190
+            function (stream) {
1191
+                return self.successCallback(stream);
1192
+            },
1193
+            function (error) {
1194
+                console.error('failed to obtain audio/video stream - stop', error);
1195
+                APP.UI.messageHandler.showError("Error",
1196
+                        "Failed to obtain permissions to use the local microphone" +
1197
+                        "and/or camera.");
1198
+            }
1199
+        );
1200
+    }
1201
+
1179 1202
 }
1180 1203
 
1181 1204
 RTCUtils.prototype.handleLocalStream = function(stream)
@@ -1209,7 +1232,7 @@ RTCUtils.prototype.handleLocalStream = function(stream)
1209 1232
 
1210 1233
 
1211 1234
 module.exports = RTCUtils;
1212
-},{"../../service/RTC/RTCBrowserType.js":79}],8:[function(require,module,exports){
1235
+},{"../../service/RTC/RTCBrowserType.js":79,"../../service/RTC/Resolutions":81}],8:[function(require,module,exports){
1213 1236
 var UI = {};
1214 1237
 
1215 1238
 var VideoLayout = require("./videolayout/VideoLayout.js");
@@ -1930,7 +1953,7 @@ UI.dockToolbar = function (isDock) {
1930 1953
 module.exports = UI;
1931 1954
 
1932 1955
 
1933
-},{"../../service/RTC/RTCEvents":80,"../../service/RTC/StreamEventTypes":81,"../../service/connectionquality/CQEvents":83,"../../service/desktopsharing/DesktopSharingEventTypes":84,"../../service/xmpp/XMPPEvents":86,"./audio_levels/AudioLevels.js":9,"./authentication/Authentication":11,"./avatar/Avatar":12,"./etherpad/Etherpad.js":13,"./prezi/Prezi.js":14,"./side_pannels/SidePanelToggler":16,"./side_pannels/chat/Chat.js":17,"./side_pannels/contactlist/ContactList":21,"./side_pannels/settings/Settings":22,"./side_pannels/settings/SettingsMenu":23,"./toolbars/BottomToolbar":24,"./toolbars/Toolbar":25,"./toolbars/ToolbarToggler":26,"./util/MessageHandler":28,"./util/NicknameHandler":29,"./util/UIUtil":30,"./videolayout/VideoLayout.js":32,"./welcome_page/RoomnameGenerator":33,"./welcome_page/WelcomePage":34,"events":87}],9:[function(require,module,exports){
1956
+},{"../../service/RTC/RTCEvents":80,"../../service/RTC/StreamEventTypes":82,"../../service/connectionquality/CQEvents":84,"../../service/desktopsharing/DesktopSharingEventTypes":85,"../../service/xmpp/XMPPEvents":87,"./audio_levels/AudioLevels.js":9,"./authentication/Authentication":11,"./avatar/Avatar":12,"./etherpad/Etherpad.js":13,"./prezi/Prezi.js":14,"./side_pannels/SidePanelToggler":16,"./side_pannels/chat/Chat.js":17,"./side_pannels/contactlist/ContactList":21,"./side_pannels/settings/Settings":22,"./side_pannels/settings/SettingsMenu":23,"./toolbars/BottomToolbar":24,"./toolbars/Toolbar":25,"./toolbars/ToolbarToggler":26,"./util/MessageHandler":28,"./util/NicknameHandler":29,"./util/UIUtil":30,"./videolayout/VideoLayout.js":32,"./welcome_page/RoomnameGenerator":33,"./welcome_page/WelcomePage":34,"events":88}],9:[function(require,module,exports){
1934 1957
 var CanvasUtil = require("./CanvasUtils");
1935 1958
 
1936 1959
 var ASDrawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d');
@@ -4008,7 +4031,7 @@ var Chat = (function (my) {
4008 4031
     return my;
4009 4032
 }(Chat || {}));
4010 4033
 module.exports = Chat;
4011
-},{"../../../../service/UI/UIEvents":82,"../../toolbars/ToolbarToggler":26,"../../util/NicknameHandler":29,"../../util/UIUtil":30,"../SidePanelToggler":16,"./Commands":18,"./Replacement":19,"./smileys.json":20}],18:[function(require,module,exports){
4034
+},{"../../../../service/UI/UIEvents":83,"../../toolbars/ToolbarToggler":26,"../../util/NicknameHandler":29,"../../util/UIUtil":30,"../SidePanelToggler":16,"./Commands":18,"./Replacement":19,"./smileys.json":20}],18:[function(require,module,exports){
4012 4035
 var UIUtil = require("../../util/UIUtil");
4013 4036
 
4014 4037
 /**
@@ -4542,7 +4565,7 @@ var SettingsMenu = {
4542 4565
 
4543 4566
 
4544 4567
 module.exports = SettingsMenu;
4545
-},{"../../../../service/translation/languages":85,"../../avatar/Avatar":12,"../../util/UIUtil":30,"./Settings":22}],24:[function(require,module,exports){
4568
+},{"../../../../service/translation/languages":86,"../../avatar/Avatar":12,"../../util/UIUtil":30,"./Settings":22}],24:[function(require,module,exports){
4546 4569
 var PanelToggler = require("../side_pannels/SidePanelToggler");
4547 4570
 
4548 4571
 var buttonHandlers = {
@@ -5545,7 +5568,7 @@ var NickanameHandler = {
5545 5568
 };
5546 5569
 
5547 5570
 module.exports = NickanameHandler;
5548
-},{"../../../service/UI/UIEvents":82}],30:[function(require,module,exports){
5571
+},{"../../../service/UI/UIEvents":83}],30:[function(require,module,exports){
5549 5572
 /**
5550 5573
  * Created by hristo on 12/22/14.
5551 5574
  */
@@ -8262,7 +8285,7 @@ var VideoLayout = (function (my) {
8262 8285
 }(VideoLayout || {}));
8263 8286
 
8264 8287
 module.exports = VideoLayout;
8265
-},{"../../../service/RTC/MediaStreamTypes":78,"../../../service/UI/UIEvents":82,"../audio_levels/AudioLevels":9,"../avatar/Avatar":12,"../etherpad/Etherpad":13,"../prezi/Prezi":14,"../side_pannels/chat/Chat":17,"../side_pannels/contactlist/ContactList":21,"../util/NicknameHandler":29,"../util/UIUtil":30,"./ConnectionIndicator":31}],33:[function(require,module,exports){
8288
+},{"../../../service/RTC/MediaStreamTypes":78,"../../../service/UI/UIEvents":83,"../audio_levels/AudioLevels":9,"../avatar/Avatar":12,"../etherpad/Etherpad":13,"../prezi/Prezi":14,"../side_pannels/chat/Chat":17,"../side_pannels/contactlist/ContactList":21,"../util/NicknameHandler":29,"../util/UIUtil":30,"./ConnectionIndicator":31}],33:[function(require,module,exports){
8266 8289
 //var nouns = [
8267 8290
 //];
8268 8291
 var pluralNouns = [
@@ -8680,7 +8703,7 @@ var ConnectionQuality = {
8680 8703
 };
8681 8704
 
8682 8705
 module.exports = ConnectionQuality;
8683
-},{"../../service/connectionquality/CQEvents":83,"../../service/xmpp/XMPPEvents":86,"events":87}],36:[function(require,module,exports){
8706
+},{"../../service/connectionquality/CQEvents":84,"../../service/xmpp/XMPPEvents":87,"events":88}],36:[function(require,module,exports){
8684 8707
 /* global $, alert, changeLocalVideo, chrome, config, getConferenceHandler, getUserMediaWithConstraints */
8685 8708
 /**
8686 8709
  * Indicates that desktop stream is currently in use(for toggle purpose).
@@ -9005,7 +9028,7 @@ module.exports = {
9005 9028
 };
9006 9029
 
9007 9030
 
9008
-},{"../../service/desktopsharing/DesktopSharingEventTypes":84,"events":87}],37:[function(require,module,exports){
9031
+},{"../../service/desktopsharing/DesktopSharingEventTypes":85,"events":88}],37:[function(require,module,exports){
9009 9032
 //maps keycode to character, id of popover for given function and function
9010 9033
 var shortcuts = {
9011 9034
     67: {
@@ -11335,7 +11358,7 @@ var statistics =
11335 11358
 
11336 11359
 
11337 11360
 module.exports = statistics;
11338
-},{"../../service/RTC/StreamEventTypes.js":81,"../../service/xmpp/XMPPEvents":86,"./LocalStatsCollector.js":43,"./RTPStatsCollector.js":44,"events":87}],46:[function(require,module,exports){
11361
+},{"../../service/RTC/StreamEventTypes.js":82,"../../service/xmpp/XMPPEvents":87,"./LocalStatsCollector.js":43,"./RTPStatsCollector.js":44,"events":88}],46:[function(require,module,exports){
11339 11362
 var i18n = require("i18next-client");
11340 11363
 var languages = require("../../service/translation/languages");
11341 11364
 var DEFAULT_LANG = languages.EN;
@@ -11447,7 +11470,7 @@ module.exports = {
11447 11470
     }
11448 11471
 };
11449 11472
 
11450
-},{"../../service/translation/languages":85,"i18next-client":61}],47:[function(require,module,exports){
11473
+},{"../../service/translation/languages":86,"i18next-client":61}],47:[function(require,module,exports){
11451 11474
 /* jshint -W117 */
11452 11475
 var TraceablePeerConnection = require("./TraceablePeerConnection");
11453 11476
 var SDPDiffer = require("./SDPDiffer");
@@ -14528,7 +14551,7 @@ module.exports = Moderator;
14528 14551
 
14529 14552
 
14530 14553
 
14531
-},{"../../service/xmpp/XMPPEvents":86}],53:[function(require,module,exports){
14554
+},{"../../service/xmpp/XMPPEvents":87}],53:[function(require,module,exports){
14532 14555
 /* global $, $iq, config, connection, focusMucJid, messageHandler, Moderator,
14533 14556
    Toolbar, Util */
14534 14557
 var Moderator = require("./moderator");
@@ -15300,7 +15323,7 @@ module.exports = function(XMPP, eventEmitter) {
15300 15323
 };
15301 15324
 
15302 15325
 
15303
-},{"../../service/xmpp/XMPPEvents":86,"./JingleSession":47,"./moderator":52}],55:[function(require,module,exports){
15326
+},{"../../service/xmpp/XMPPEvents":87,"./JingleSession":47,"./moderator":52}],55:[function(require,module,exports){
15304 15327
 /* jshint -W117 */
15305 15328
 
15306 15329
 var JingleSession = require("./JingleSession");
@@ -15639,7 +15662,7 @@ module.exports = function(XMPP, eventEmitter)
15639 15662
 };
15640 15663
 
15641 15664
 
15642
-},{"../../service/xmpp/XMPPEvents":86,"./JingleSession":47}],56:[function(require,module,exports){
15665
+},{"../../service/xmpp/XMPPEvents":87,"./JingleSession":47}],56:[function(require,module,exports){
15643 15666
 /* global Strophe */
15644 15667
 module.exports = function () {
15645 15668
 
@@ -16306,7 +16329,7 @@ var XMPP = {
16306 16329
 
16307 16330
 module.exports = XMPP;
16308 16331
 
16309
-},{"../../service/RTC/StreamEventTypes":81,"../../service/UI/UIEvents":82,"../../service/xmpp/XMPPEvents":86,"./SDP":48,"./moderator":52,"./recording":53,"./strophe.emuc":54,"./strophe.jingle":55,"./strophe.logger":56,"./strophe.moderate":57,"./strophe.rayo":58,"./strophe.util":59,"events":87,"pako":62}],61:[function(require,module,exports){
16332
+},{"../../service/RTC/StreamEventTypes":82,"../../service/UI/UIEvents":83,"../../service/xmpp/XMPPEvents":87,"./SDP":48,"./moderator":52,"./recording":53,"./strophe.emuc":54,"./strophe.jingle":55,"./strophe.logger":56,"./strophe.moderate":57,"./strophe.rayo":58,"./strophe.util":59,"events":88,"pako":62}],61:[function(require,module,exports){
16310 16333
 // i18next, v1.7.7
16311 16334
 // Copyright (c)2014 Jan Mühlemann (jamuhl).
16312 16335
 // Distributed under MIT license
@@ -24822,6 +24845,60 @@ var RTCEvents = {
24822 24845
 
24823 24846
 module.exports = RTCEvents;
24824 24847
 },{}],81:[function(require,module,exports){
24848
+var Resolutions = {
24849
+    "1080": {
24850
+        width: 1920,
24851
+        height: 1080,
24852
+        order: 7
24853
+    },
24854
+    "fullhd": {
24855
+        width: 1920,
24856
+        height: 1080,
24857
+        order: 7
24858
+    },
24859
+    "720": {
24860
+        width: 1280,
24861
+        height: 720,
24862
+        order: 6
24863
+    },
24864
+    "hd": {
24865
+        width: 1280,
24866
+        height: 720,
24867
+        order: 6
24868
+    },
24869
+    "960": {
24870
+        width: 960,
24871
+        height: 720,
24872
+        order: 5
24873
+    },
24874
+    "640": {
24875
+        width: 640,
24876
+        height: 480,
24877
+        order: 4
24878
+    },
24879
+    "vga": {
24880
+        width: 640,
24881
+        height: 480,
24882
+        order: 4
24883
+    },
24884
+    "360": {
24885
+        width: 640,
24886
+        height: 360,
24887
+        order: 3
24888
+    },
24889
+    "320": {
24890
+        width: 320,
24891
+        height: 240,
24892
+        order: 2
24893
+    },
24894
+    "180": {
24895
+        width: 320,
24896
+        height: 180,
24897
+        order: 1
24898
+    }
24899
+};
24900
+module.exports = Resolutions;
24901
+},{}],82:[function(require,module,exports){
24825 24902
 var StreamEventTypes = {
24826 24903
     EVENT_TYPE_LOCAL_CREATED: "stream.local_created",
24827 24904
 
@@ -24835,14 +24912,14 @@ var StreamEventTypes = {
24835 24912
 };
24836 24913
 
24837 24914
 module.exports = StreamEventTypes;
24838
-},{}],82:[function(require,module,exports){
24915
+},{}],83:[function(require,module,exports){
24839 24916
 var UIEvents = {
24840 24917
     NICKNAME_CHANGED: "UI.nickname_changed",
24841 24918
     SELECTED_ENDPOINT: "UI.selected_endpoint",
24842 24919
     PINNED_ENDPOINT: "UI.pinned_endpoint"
24843 24920
 };
24844 24921
 module.exports = UIEvents;
24845
-},{}],83:[function(require,module,exports){
24922
+},{}],84:[function(require,module,exports){
24846 24923
 var CQEvents = {
24847 24924
     LOCALSTATS_UPDATED: "cq.localstats_updated",
24848 24925
     REMOTESTATS_UPDATED: "cq.remotestats_updated",
@@ -24850,7 +24927,7 @@ var CQEvents = {
24850 24927
 };
24851 24928
 
24852 24929
 module.exports = CQEvents;
24853
-},{}],84:[function(require,module,exports){
24930
+},{}],85:[function(require,module,exports){
24854 24931
 var DesktopSharingEventTypes = {
24855 24932
     INIT: "ds.init",
24856 24933
 
@@ -24860,7 +24937,7 @@ var DesktopSharingEventTypes = {
24860 24937
 };
24861 24938
 
24862 24939
 module.exports = DesktopSharingEventTypes;
24863
-},{}],85:[function(require,module,exports){
24940
+},{}],86:[function(require,module,exports){
24864 24941
 module.exports = {
24865 24942
     getLanguages : function () {
24866 24943
         var languages = [];
@@ -24873,7 +24950,7 @@ module.exports = {
24873 24950
     },
24874 24951
     EN: "en"
24875 24952
 }
24876
-},{}],86:[function(require,module,exports){
24953
+},{}],87:[function(require,module,exports){
24877 24954
 var XMPPEvents = {
24878 24955
     CONFERENCE_CERATED: "xmpp.conferenceCreated.jingle",
24879 24956
     CALL_TERMINATED: "xmpp.callterminated.jingle",
@@ -24900,7 +24977,7 @@ var XMPPEvents = {
24900 24977
     ETHERPAD: "xmpp.etherpad"
24901 24978
 };
24902 24979
 module.exports = XMPPEvents;
24903
-},{}],87:[function(require,module,exports){
24980
+},{}],88:[function(require,module,exports){
24904 24981
 // Copyright Joyent, Inc. and other Node contributors.
24905 24982
 //
24906 24983
 // Permission is hereby granted, free of charge, to any person obtaining a

+ 82
- 59
modules/RTC/RTCUtils.js View File

@@ -1,60 +1,52 @@
1 1
 var RTCBrowserType = require("../../service/RTC/RTCBrowserType.js");
2
+var Resolutions = require("../../service/RTC/Resolutions");
3
+
4
+var currentResolution = null;
5
+
6
+function getPreviousResolution(resolution) {
7
+    if(!Resolutions[resolution])
8
+        return null;
9
+    var order = Resolutions[resolution].order;
10
+    var res = null;
11
+    var resName = null;
12
+    for(var i in Resolutions)
13
+    {
14
+        var tmp = Resolutions[i];
15
+        if(res == null || (res.order < tmp.order && tmp.order < order))
16
+        {
17
+            resName = i;
18
+            res = tmp;
19
+        }
20
+    }
21
+    return resName;
22
+}
2 23
 
3 24
 function setResolutionConstraints(constraints, resolution, isAndroid)
4 25
 {
5 26
     if (resolution && !constraints.video || isAndroid) {
6 27
         constraints.video = { mandatory: {}, optional: [] };// same behaviour as true
7 28
     }
8
-    // see https://code.google.com/p/chromium/issues/detail?id=143631#c9 for list of supported resolutions
9
-    switch (resolution) {
10
-        // 16:9 first
11
-        case '1080':
12
-        case 'fullhd':
13
-            constraints.video.mandatory.minWidth = 1920;
14
-            constraints.video.mandatory.minHeight = 1080;
15
-            break;
16
-        case '720':
17
-        case 'hd':
18
-            constraints.video.mandatory.minWidth = 1280;
19
-            constraints.video.mandatory.minHeight = 720;
20
-            break;
21
-        case '360':
22
-            constraints.video.mandatory.minWidth = 640;
23
-            constraints.video.mandatory.minHeight = 360;
24
-            break;
25
-        case '180':
26
-            constraints.video.mandatory.minWidth = 320;
27
-            constraints.video.mandatory.minHeight = 180;
28
-            break;
29
-        // 4:3
30
-        case '960':
31
-            constraints.video.mandatory.minWidth = 960;
32
-            constraints.video.mandatory.minHeight = 720;
33
-            break;
34
-        case '640':
35
-        case 'vga':
36
-            constraints.video.mandatory.minWidth = 640;
37
-            constraints.video.mandatory.minHeight = 480;
38
-            break;
39
-        case '320':
29
+
30
+    if(Resolutions[resolution])
31
+    {
32
+        constraints.video.mandatory.minWidth = Resolutions[resolution].width;
33
+        constraints.video.mandatory.minHeight = Resolutions[resolution].height;
34
+    }
35
+    else
36
+    {
37
+        if (isAndroid) {
40 38
             constraints.video.mandatory.minWidth = 320;
41 39
             constraints.video.mandatory.minHeight = 240;
42
-            break;
43
-        default:
44
-            if (isAndroid) {
45
-                constraints.video.mandatory.minWidth = 320;
46
-                constraints.video.mandatory.minHeight = 240;
47
-                constraints.video.mandatory.maxFrameRate = 15;
48
-            }
49
-            break;
40
+            constraints.video.mandatory.maxFrameRate = 15;
41
+        }
50 42
     }
43
+
51 44
     if (constraints.video.mandatory.minWidth)
52 45
         constraints.video.mandatory.maxWidth = constraints.video.mandatory.minWidth;
53 46
     if (constraints.video.mandatory.minHeight)
54 47
         constraints.video.mandatory.maxHeight = constraints.video.mandatory.minHeight;
55 48
 }
56 49
 
57
-
58 50
 function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid)
59 51
 {
60 52
     var constraints = {audio: false, video: false};
@@ -220,6 +212,7 @@ RTCUtils.prototype.getUserMediaWithConstraints = function(
220 212
     um, success_callback, failure_callback, resolution,bandwidth, fps,
221 213
     desktopStream)
222 214
 {
215
+    currentResolution = resolution;
223 216
     // Check if we are running on Android device
224 217
     var isAndroid = navigator.userAgent.indexOf('Android') != -1;
225 218
 
@@ -278,28 +271,58 @@ RTCUtils.prototype.getUserMediaWithConstraints = function(
278 271
 RTCUtils.prototype.obtainAudioAndVideoPermissions = function() {
279 272
     var self = this;
280 273
     // Get AV
281
-    var cb = function (stream) {
282
-        console.log('got', stream, stream.getAudioTracks().length, stream.getVideoTracks().length);
283
-        self.handleLocalStream(stream);
284
-    };
285
-    var self = this;
274
+
286 275
     this.getUserMediaWithConstraints(
287 276
         ['audio', 'video'],
288
-        cb,
277
+        function (stream) {
278
+            self.successCallback(stream);
279
+        },
289 280
         function (error) {
290
-            console.error('failed to obtain audio/video stream - trying audio only', error);
291
-            self.getUserMediaWithConstraints(
292
-                ['audio'],
293
-                cb,
294
-                function (error) {
295
-                    console.error('failed to obtain audio/video stream - stop', error);
296
-                    APP.UI.messageHandler.showError("Error",
297
-                            "Failed to obtain permissions to use the local microphone" +
298
-                            "and/or camera.");
299
-                }
300
-            );
281
+            self.errorCallback(error);
301 282
         },
302
-            config.resolution || '360');
283
+        config.resolution || '360');
284
+}
285
+
286
+RTCUtils.prototype.successCallback = function (stream) {
287
+    console.log('got', stream, stream.getAudioTracks().length,
288
+        stream.getVideoTracks().length);
289
+    this.handleLocalStream(stream);
290
+};
291
+
292
+RTCUtils.prototype.errorCallback = function (error) {
293
+    var self = this;
294
+    console.error('failed to obtain audio/video stream - trying audio only', error);
295
+    var resolution = getPreviousResolution(currentResolution);
296
+    if(typeof error == "object" && error.constraintName && error.name
297
+        && (error.name == "ConstraintNotSatisfiedError" ||
298
+            error.name == "OverconstrainedError") &&
299
+        (error.constraintName == "minWidth" || error.constraintName == "maxWidth" ||
300
+            error.constraintName == "minHeight" || error.constraintName == "maxHeight")
301
+        && resolution != null)
302
+    {
303
+        self.getUserMediaWithConstraints(['audio', 'video'],
304
+            function (stream) {
305
+                return self.successCallback(stream);
306
+            }, function (error) {
307
+                return self.errorCallback(error);
308
+            }, resolution);
309
+    }
310
+    else
311
+    {
312
+        self.getUserMediaWithConstraints(
313
+            ['audio'],
314
+            function (stream) {
315
+                return self.successCallback(stream);
316
+            },
317
+            function (error) {
318
+                console.error('failed to obtain audio/video stream - stop', error);
319
+                APP.UI.messageHandler.showError("Error",
320
+                        "Failed to obtain permissions to use the local microphone" +
321
+                        "and/or camera.");
322
+            }
323
+        );
324
+    }
325
+
303 326
 }
304 327
 
305 328
 RTCUtils.prototype.handleLocalStream = function(stream)

+ 53
- 0
service/RTC/Resolutions.js View File

@@ -0,0 +1,53 @@
1
+var Resolutions = {
2
+    "1080": {
3
+        width: 1920,
4
+        height: 1080,
5
+        order: 7
6
+    },
7
+    "fullhd": {
8
+        width: 1920,
9
+        height: 1080,
10
+        order: 7
11
+    },
12
+    "720": {
13
+        width: 1280,
14
+        height: 720,
15
+        order: 6
16
+    },
17
+    "hd": {
18
+        width: 1280,
19
+        height: 720,
20
+        order: 6
21
+    },
22
+    "960": {
23
+        width: 960,
24
+        height: 720,
25
+        order: 5
26
+    },
27
+    "640": {
28
+        width: 640,
29
+        height: 480,
30
+        order: 4
31
+    },
32
+    "vga": {
33
+        width: 640,
34
+        height: 480,
35
+        order: 4
36
+    },
37
+    "360": {
38
+        width: 640,
39
+        height: 360,
40
+        order: 3
41
+    },
42
+    "320": {
43
+        width: 320,
44
+        height: 240,
45
+        order: 2
46
+    },
47
+    "180": {
48
+        width: 320,
49
+        height: 180,
50
+        order: 1
51
+    }
52
+};
53
+module.exports = Resolutions;

Loading…
Cancel
Save