瀏覽代碼

Fixes audio level performance issue on avatar.

master
hristoterezov 10 年之前
父節點
當前提交
f2a7a43ba7
共有 6 個檔案被更改,包括 121 行新增77 行删除
  1. 1
    1
      index.html
  2. 60
    38
      libs/app.bundle.js
  3. 1
    1
      modules/UI/UI.js
  4. 29
    28
      modules/UI/audio_levels/AudioLevels.js
  5. 29
    8
      modules/statistics/RTPStatsCollector.js
  6. 1
    1
      modules/statistics/statistics.js

+ 1
- 1
index.html 查看文件

@@ -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=8"></script>
22
+    <script src="libs/app.bundle.js?v=9"></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"/>

+ 60
- 38
libs/app.bundle.js 查看文件

@@ -1315,7 +1315,7 @@ function registerListeners() {
1315 1315
             VideoLayout.onSimulcastLayersChanging(endpointSimulcastLayers);
1316 1316
         });
1317 1317
     VideoLayout.init(eventEmitter);
1318
-
1318
+    AudioLevels.init();
1319 1319
     APP.statistics.addAudioLevelListener(function(jid, audioLevel)
1320 1320
     {
1321 1321
         var resourceJid;
@@ -1933,6 +1933,21 @@ module.exports = UI;
1933 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){
1934 1934
 var CanvasUtil = require("./CanvasUtils");
1935 1935
 
1936
+var ASDrawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d');
1937
+
1938
+function initActiveSpeakerAudioLevels() {
1939
+    var ASRadius = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE / 2;
1940
+    var ASCenter = (interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE + ASRadius) / 2;
1941
+
1942
+// Draw a circle.
1943
+    ASDrawContext.arc(ASCenter, ASCenter, ASRadius, 0, 2 * Math.PI);
1944
+
1945
+// Add a shadow around the circle
1946
+    ASDrawContext.shadowColor = interfaceConfig.SHADOW_COLOR;
1947
+    ASDrawContext.shadowOffsetX = 0;
1948
+    ASDrawContext.shadowOffsetY = 0;
1949
+}
1950
+
1936 1951
 /**
1937 1952
  * The audio Levels plugin.
1938 1953
  */
@@ -1941,6 +1956,10 @@ var AudioLevels = (function(my) {
1941 1956
 
1942 1957
     my.LOCAL_LEVEL = 'local';
1943 1958
 
1959
+    my.init = function () {
1960
+        initActiveSpeakerAudioLevels();
1961
+    }
1962
+
1944 1963
     /**
1945 1964
      * Updates the audio level canvas for the given peerJid. If the canvas
1946 1965
      * didn't exist we create it.
@@ -2027,44 +2046,26 @@ var AudioLevels = (function(my) {
2027 2046
         }
2028 2047
 
2029 2048
         if(resourceJid  === largeVideoResourceJid) {
2030
-            AudioLevels.updateActiveSpeakerAudioLevel(audioLevel);
2049
+            window.requestAnimationFrame(function () {
2050
+                AudioLevels.updateActiveSpeakerAudioLevel(audioLevel);
2051
+            });
2031 2052
         }
2032 2053
     };
2033 2054
 
2034 2055
     my.updateActiveSpeakerAudioLevel = function(audioLevel) {
2035
-        var drawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d');
2036
-        var r = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE / 2;
2037
-        var center = (interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE + r) / 2;
2056
+        if($("#activeSpeaker").css("visibility") == "hidden")
2057
+            return;
2038 2058
 
2039
-        // Save the previous state of the context.
2040
-        drawContext.save();
2041 2059
 
2042
-        drawContext.clearRect(0, 0, 300, 300);
2060
+        ASDrawContext.clearRect(0, 0, 300, 300);
2061
+        if(audioLevel == 0)
2062
+            return;
2043 2063
 
2044
-        // Draw a circle.
2045
-        drawContext.arc(center, center, r, 0, 2 * Math.PI);
2064
+        ASDrawContext.shadowBlur = getShadowLevel(audioLevel);
2046 2065
 
2047
-        // Add a shadow around the circle
2048
-        drawContext.shadowColor = interfaceConfig.SHADOW_COLOR;
2049
-        drawContext.shadowBlur = getShadowLevel(audioLevel);
2050
-        drawContext.shadowOffsetX = 0;
2051
-        drawContext.shadowOffsetY = 0;
2052 2066
 
2053 2067
         // Fill the shape.
2054
-        drawContext.fill();
2055
-
2056
-        drawContext.save();
2057
-
2058
-        drawContext.restore();
2059
-
2060
-
2061
-        drawContext.arc(center, center, r, 0, 2 * Math.PI);
2062
-
2063
-        drawContext.clip();
2064
-        drawContext.clearRect(0, 0, 277, 200);
2065
-
2066
-        // Restore the previous context state.
2067
-        drawContext.restore();
2068
+        ASDrawContext.fill();
2068 2069
     };
2069 2070
 
2070 2071
     /**
@@ -10604,9 +10605,13 @@ PeerStats.prototype.setSsrcBitrate = function (ssrc, bitrate)
10604 10605
 PeerStats.prototype.setSsrcAudioLevel = function (ssrc, audioLevel)
10605 10606
 {
10606 10607
     // Range limit 0 - 1
10607
-    this.ssrc2AudioLevel[ssrc] = Math.min(Math.max(audioLevel, 0), 1);
10608
+    this.ssrc2AudioLevel[ssrc] = formatAudioLevel(audioLevel);
10608 10609
 };
10609 10610
 
10611
+function formatAudioLevel(audioLevel) {
10612
+    return Math.min(Math.max(audioLevel, 0), 1);
10613
+}
10614
+
10610 10615
 /**
10611 10616
  * Array with the transport information.
10612 10617
  * @type {Array}
@@ -10681,16 +10686,26 @@ module.exports = StatsCollector;
10681 10686
 /**
10682 10687
  * Stops stats updates.
10683 10688
  */
10684
-StatsCollector.prototype.stop = function ()
10685
-{
10686
-    if (this.audioLevelsIntervalId)
10687
-    {
10689
+StatsCollector.prototype.stop = function () {
10690
+    if (this.audioLevelsIntervalId) {
10688 10691
         clearInterval(this.audioLevelsIntervalId);
10689 10692
         this.audioLevelsIntervalId = null;
10693
+    }
10694
+
10695
+    if (this.statsIntervalId)
10696
+    {
10690 10697
         clearInterval(this.statsIntervalId);
10691 10698
         this.statsIntervalId = null;
10699
+    }
10700
+
10701
+    if(this.logStatsIntervalId)
10702
+    {
10692 10703
         clearInterval(this.logStatsIntervalId);
10693 10704
         this.logStatsIntervalId = null;
10705
+    }
10706
+
10707
+    if(this.gatherStatsIntervalId)
10708
+    {
10694 10709
         clearInterval(this.gatherStatsIntervalId);
10695 10710
         this.gatherStatsIntervalId = null;
10696 10711
     }
@@ -10713,6 +10728,7 @@ StatsCollector.prototype.start = function ()
10713 10728
 {
10714 10729
     var self = this;
10715 10730
     if(!config.disableAudioLevels) {
10731
+        console.debug("set audio levels interval");
10716 10732
         this.audioLevelsIntervalId = setInterval(
10717 10733
             function () {
10718 10734
                 // Interval updates
@@ -10740,6 +10756,7 @@ StatsCollector.prototype.start = function ()
10740 10756
     }
10741 10757
 
10742 10758
     if(!config.disableStats) {
10759
+        console.debug("set stats interval");
10743 10760
         this.statsIntervalId = setInterval(
10744 10761
             function () {
10745 10762
                 // Interval updates
@@ -11170,10 +11187,15 @@ StatsCollector.prototype.processAudioLevelReport = function ()
11170 11187
         {
11171 11188
             // TODO: can't find specs about what this value really is,
11172 11189
             // but it seems to vary between 0 and around 32k.
11173
-            audioLevel = audioLevel / 32767;
11174
-            jidStats.setSsrcAudioLevel(ssrc, audioLevel);
11175
-            if(jid != APP.xmpp.myJid())
11190
+            audioLevel = formatAudioLevel(audioLevel / 32767);
11191
+            var oldLevel = jidStats.ssrc2AudioLevel[ssrc];
11192
+            if(jid != APP.xmpp.myJid() && (!oldLevel || oldLevel != audioLevel))
11193
+            {
11194
+
11195
+                jidStats.ssrc2AudioLevel[ssrc] = audioLevel;
11196
+
11176 11197
                 this.eventEmitter.emit("statistics.audioLevel", jid, audioLevel);
11198
+            }
11177 11199
         }
11178 11200
 
11179 11201
     }
@@ -11231,7 +11253,7 @@ function onStreamCreated(stream)
11231 11253
     if(stream.getOriginalStream().getAudioTracks().length === 0)
11232 11254
         return;
11233 11255
 
11234
-    localStats = new LocalStats(stream.getOriginalStream(), 100, statistics,
11256
+    localStats = new LocalStats(stream.getOriginalStream(), 200, statistics,
11235 11257
         eventEmitter);
11236 11258
     localStats.start();
11237 11259
 }

+ 1
- 1
modules/UI/UI.js 查看文件

@@ -103,7 +103,7 @@ function registerListeners() {
103 103
             VideoLayout.onSimulcastLayersChanging(endpointSimulcastLayers);
104 104
         });
105 105
     VideoLayout.init(eventEmitter);
106
-
106
+    AudioLevels.init();
107 107
     APP.statistics.addAudioLevelListener(function(jid, audioLevel)
108 108
     {
109 109
         var resourceJid;

+ 29
- 28
modules/UI/audio_levels/AudioLevels.js 查看文件

@@ -1,5 +1,20 @@
1 1
 var CanvasUtil = require("./CanvasUtils");
2 2
 
3
+var ASDrawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d');
4
+
5
+function initActiveSpeakerAudioLevels() {
6
+    var ASRadius = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE / 2;
7
+    var ASCenter = (interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE + ASRadius) / 2;
8
+
9
+// Draw a circle.
10
+    ASDrawContext.arc(ASCenter, ASCenter, ASRadius, 0, 2 * Math.PI);
11
+
12
+// Add a shadow around the circle
13
+    ASDrawContext.shadowColor = interfaceConfig.SHADOW_COLOR;
14
+    ASDrawContext.shadowOffsetX = 0;
15
+    ASDrawContext.shadowOffsetY = 0;
16
+}
17
+
3 18
 /**
4 19
  * The audio Levels plugin.
5 20
  */
@@ -8,6 +23,10 @@ var AudioLevels = (function(my) {
8 23
 
9 24
     my.LOCAL_LEVEL = 'local';
10 25
 
26
+    my.init = function () {
27
+        initActiveSpeakerAudioLevels();
28
+    }
29
+
11 30
     /**
12 31
      * Updates the audio level canvas for the given peerJid. If the canvas
13 32
      * didn't exist we create it.
@@ -94,44 +113,26 @@ var AudioLevels = (function(my) {
94 113
         }
95 114
 
96 115
         if(resourceJid  === largeVideoResourceJid) {
97
-            AudioLevels.updateActiveSpeakerAudioLevel(audioLevel);
116
+            window.requestAnimationFrame(function () {
117
+                AudioLevels.updateActiveSpeakerAudioLevel(audioLevel);
118
+            });
98 119
         }
99 120
     };
100 121
 
101 122
     my.updateActiveSpeakerAudioLevel = function(audioLevel) {
102
-        var drawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d');
103
-        var r = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE / 2;
104
-        var center = (interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE + r) / 2;
123
+        if($("#activeSpeaker").css("visibility") == "hidden")
124
+            return;
105 125
 
106
-        // Save the previous state of the context.
107
-        drawContext.save();
108 126
 
109
-        drawContext.clearRect(0, 0, 300, 300);
127
+        ASDrawContext.clearRect(0, 0, 300, 300);
128
+        if(audioLevel == 0)
129
+            return;
110 130
 
111
-        // Draw a circle.
112
-        drawContext.arc(center, center, r, 0, 2 * Math.PI);
131
+        ASDrawContext.shadowBlur = getShadowLevel(audioLevel);
113 132
 
114
-        // Add a shadow around the circle
115
-        drawContext.shadowColor = interfaceConfig.SHADOW_COLOR;
116
-        drawContext.shadowBlur = getShadowLevel(audioLevel);
117
-        drawContext.shadowOffsetX = 0;
118
-        drawContext.shadowOffsetY = 0;
119 133
 
120 134
         // Fill the shape.
121
-        drawContext.fill();
122
-
123
-        drawContext.save();
124
-
125
-        drawContext.restore();
126
-
127
-
128
-        drawContext.arc(center, center, r, 0, 2 * Math.PI);
129
-
130
-        drawContext.clip();
131
-        drawContext.clearRect(0, 0, 277, 200);
132
-
133
-        // Restore the previous context state.
134
-        drawContext.restore();
135
+        ASDrawContext.fill();
135 136
     };
136 137
 
137 138
     /**

+ 29
- 8
modules/statistics/RTPStatsCollector.js 查看文件

@@ -111,9 +111,13 @@ PeerStats.prototype.setSsrcBitrate = function (ssrc, bitrate)
111 111
 PeerStats.prototype.setSsrcAudioLevel = function (ssrc, audioLevel)
112 112
 {
113 113
     // Range limit 0 - 1
114
-    this.ssrc2AudioLevel[ssrc] = Math.min(Math.max(audioLevel, 0), 1);
114
+    this.ssrc2AudioLevel[ssrc] = formatAudioLevel(audioLevel);
115 115
 };
116 116
 
117
+function formatAudioLevel(audioLevel) {
118
+    return Math.min(Math.max(audioLevel, 0), 1);
119
+}
120
+
117 121
 /**
118 122
  * Array with the transport information.
119 123
  * @type {Array}
@@ -188,16 +192,26 @@ module.exports = StatsCollector;
188 192
 /**
189 193
  * Stops stats updates.
190 194
  */
191
-StatsCollector.prototype.stop = function ()
192
-{
193
-    if (this.audioLevelsIntervalId)
194
-    {
195
+StatsCollector.prototype.stop = function () {
196
+    if (this.audioLevelsIntervalId) {
195 197
         clearInterval(this.audioLevelsIntervalId);
196 198
         this.audioLevelsIntervalId = null;
199
+    }
200
+
201
+    if (this.statsIntervalId)
202
+    {
197 203
         clearInterval(this.statsIntervalId);
198 204
         this.statsIntervalId = null;
205
+    }
206
+
207
+    if(this.logStatsIntervalId)
208
+    {
199 209
         clearInterval(this.logStatsIntervalId);
200 210
         this.logStatsIntervalId = null;
211
+    }
212
+
213
+    if(this.gatherStatsIntervalId)
214
+    {
201 215
         clearInterval(this.gatherStatsIntervalId);
202 216
         this.gatherStatsIntervalId = null;
203 217
     }
@@ -220,6 +234,7 @@ StatsCollector.prototype.start = function ()
220 234
 {
221 235
     var self = this;
222 236
     if(!config.disableAudioLevels) {
237
+        console.debug("set audio levels interval");
223 238
         this.audioLevelsIntervalId = setInterval(
224 239
             function () {
225 240
                 // Interval updates
@@ -247,6 +262,7 @@ StatsCollector.prototype.start = function ()
247 262
     }
248 263
 
249 264
     if(!config.disableStats) {
265
+        console.debug("set stats interval");
250 266
         this.statsIntervalId = setInterval(
251 267
             function () {
252 268
                 // Interval updates
@@ -677,10 +693,15 @@ StatsCollector.prototype.processAudioLevelReport = function ()
677 693
         {
678 694
             // TODO: can't find specs about what this value really is,
679 695
             // but it seems to vary between 0 and around 32k.
680
-            audioLevel = audioLevel / 32767;
681
-            jidStats.setSsrcAudioLevel(ssrc, audioLevel);
682
-            if(jid != APP.xmpp.myJid())
696
+            audioLevel = formatAudioLevel(audioLevel / 32767);
697
+            var oldLevel = jidStats.ssrc2AudioLevel[ssrc];
698
+            if(jid != APP.xmpp.myJid() && (!oldLevel || oldLevel != audioLevel))
699
+            {
700
+
701
+                jidStats.ssrc2AudioLevel[ssrc] = audioLevel;
702
+
683 703
                 this.eventEmitter.emit("statistics.audioLevel", jid, audioLevel);
704
+            }
684 705
         }
685 706
 
686 707
     }

+ 1
- 1
modules/statistics/statistics.js 查看文件

@@ -48,7 +48,7 @@ function onStreamCreated(stream)
48 48
     if(stream.getOriginalStream().getAudioTracks().length === 0)
49 49
         return;
50 50
 
51
-    localStats = new LocalStats(stream.getOriginalStream(), 100, statistics,
51
+    localStats = new LocalStats(stream.getOriginalStream(), 200, statistics,
52 52
         eventEmitter);
53 53
     localStats.start();
54 54
 }

Loading…
取消
儲存