浏览代码

feat(HDAudio): Initial implementation.

dev1
Mihai-Andrei Uscat 4 年前
父节点
当前提交
99983c757d

+ 16
- 20
modules/RTC/RTCUtils.js 查看文件

@@ -93,6 +93,9 @@ let disableAGC = false;
93 93
 // Disables Highpass Filter
94 94
 let disableHPF = false;
95 95
 
96
+// Channel count used to enable stereo.
97
+let channelCount = null;
98
+
96 99
 const featureDetectionAudioEl = document.createElement('audio');
97 100
 const isAudioOutputDeviceChangeAvailable
98 101
     = typeof featureDetectionAudioEl.setSinkId !== 'undefined';
@@ -420,26 +423,14 @@ function newGetConstraints(um = [], options = {}) {
420 423
                 noiseSuppression: !disableNS && !disableAP
421 424
             };
422 425
         } else {
423
-            // NOTE(brian): the new-style ('advanced' instead of 'optional')
424
-            // doesn't seem to carry through the googXXX constraints
425
-            // Changing back to 'optional' here (even with video using
426
-            // the 'advanced' style) allows them to be passed through
427
-            // but also requires the device id to capture to be set in optional
428
-            // as sourceId otherwise the constraints are considered malformed.
429
-            if (!constraints.audio.optional) {
430
-                constraints.audio.optional = [];
431
-            }
432
-            constraints.audio.optional.push(
433
-                { sourceId: options.micDeviceId },
434
-                { echoCancellation: !disableAEC && !disableAP },
435
-                { googEchoCancellation: !disableAEC && !disableAP },
436
-                { googAutoGainControl: !disableAGC && !disableAP },
437
-                { googNoiseSuppression: !disableNS && !disableAP },
438
-                { googHighpassFilter: !disableHPF && !disableAP },
439
-                { googNoiseSuppression2: !disableNS && !disableAP },
440
-                { googEchoCancellation2: !disableAEC && !disableAP },
441
-                { googAutoGainControl2: !disableAGC && !disableAP }
442
-            );
426
+            constraints.audio = {
427
+                autoGainControl: { exact: !disableAGC && !disableAP },
428
+                channelCount,
429
+                deviceId: options.micDeviceId,
430
+                echoCancellation: { exact: !disableAEC && !disableAP },
431
+                noiseSuppression: { exact: !disableNS && !disableAP },
432
+                sampleRate: 48000
433
+            };
443 434
         }
444 435
     } else {
445 436
         constraints.audio = false;
@@ -777,6 +768,11 @@ class RTCUtils extends Listenable {
777 768
             logger.info(`Disable HPF: ${disableHPF}`);
778 769
         }
779 770
 
771
+        if (typeof options.channelCount === 'number') {
772
+            channelCount = options.channelCount;
773
+            logger.info(`Channel count: ${channelCount}`);
774
+        }
775
+
780 776
         window.clearInterval(availableDevicesPollTimer);
781 777
         availableDevicesPollTimer = undefined;
782 778
 

+ 11
- 1
modules/RTC/ScreenObtainer.js 查看文件

@@ -163,9 +163,19 @@ const ScreenObtainer = {
163 163
             getDisplayMedia = navigator.mediaDevices.getDisplayMedia.bind(navigator.mediaDevices);
164 164
         }
165 165
 
166
+        const { channelCount, disableAGC, disableAP, enableHdAudio } = this.options;
167
+        const audioProcessingValue = !disableAGC && !disableAP;
168
+        const audio = enableHdAudio ? {
169
+            autoGainControl: audioProcessingValue,
170
+            channelCount,
171
+            echoCancellation: audioProcessingValue,
172
+            noiseSuppression: audioProcessingValue,
173
+            sampleRate: 48000
174
+        } : true;
175
+
166 176
         getDisplayMedia({
167 177
             video: true,
168
-            audio: true,
178
+            audio,
169 179
             cursor: 'always'
170 180
         })
171 181
             .then(stream => {

+ 77
- 1
modules/RTC/TraceablePeerConnection.js 查看文件

@@ -2149,6 +2149,73 @@ TraceablePeerConnection.prototype._adjustLocalMediaDirection = function(
2149 2149
     return localDescription;
2150 2150
 };
2151 2151
 
2152
+/**
2153
+ * Converts an object to a config-like string.
2154
+ *
2155
+ * @param {Object} obj - The object to be converted into a config string.
2156
+ * @returns {String} - The config string.
2157
+ */
2158
+TraceablePeerConnection.prototype.getConfigFromObject = function(obj) {
2159
+    let config = '';
2160
+
2161
+    for (const key of Object.keys(obj)) {
2162
+        config += `${key}=${obj[key]}; `;
2163
+    }
2164
+
2165
+    return config.trim();
2166
+};
2167
+
2168
+/**
2169
+ * Munges the stereo flag as well as the opusMaxAverageBitrate in the SDP, based
2170
+ * on values set through config.js, if present.
2171
+ *
2172
+ * @param {RTCSessionDescription} description that needs to be munged.
2173
+ * @returns {RTCSessionDescription} the munged description.
2174
+ */
2175
+TraceablePeerConnection.prototype.mungeOpus = function(description) {
2176
+    const parsedSdp = transform.parse(description.sdp);
2177
+    const audio = parsedSdp.media.find(mLine => mLine.type === 'audio');
2178
+    const { payload } = audio.rtp.find(protocol => protocol.codec === 'opus');
2179
+
2180
+    if (!payload) {
2181
+        // No Opus.
2182
+        return description;
2183
+    }
2184
+
2185
+    let fmtpOpus = audio.fmtp.find(protocol => protocol.payload === payload);
2186
+
2187
+    if (!fmtpOpus) {
2188
+        fmtpOpus = {
2189
+            payload,
2190
+            config: ''
2191
+        };
2192
+    }
2193
+
2194
+    const fmtpConfig = transform.parseParams(fmtpOpus.config);
2195
+    let sdpChanged = false;
2196
+
2197
+    if (this.options.stereo) {
2198
+        fmtpConfig.stereo = 1;
2199
+        sdpChanged = true;
2200
+    }
2201
+
2202
+    if (this.options.opusMaxAverageBitrate) {
2203
+        fmtpConfig.opusMaxAverageBitrate = this.options.opusMaxAverageBitrate;
2204
+        sdpChanged = true;
2205
+    }
2206
+
2207
+    if (!sdpChanged) {
2208
+        return description;
2209
+    }
2210
+
2211
+    fmtpOpus.config = this.getConfigFromObject(fmtpConfig);
2212
+
2213
+    return new RTCSessionDescription({
2214
+        type: description.type,
2215
+        sdp: transform.write(parsedSdp)
2216
+    });
2217
+};
2218
+
2152 2219
 TraceablePeerConnection.prototype.setLocalDescription = function(description) {
2153 2220
     let localSdp = description;
2154 2221
 
@@ -2157,6 +2224,9 @@ TraceablePeerConnection.prototype.setLocalDescription = function(description) {
2157 2224
     // Munge the order of the codecs based on the preferences set through config.js
2158 2225
     localSdp = this._mungeCodecOrder(localSdp);
2159 2226
 
2227
+    // Munge stereo flag and opusMaxAverageBitrate based on config.js
2228
+    localSdp = this.mungeOpus(localSdp);
2229
+
2160 2230
     if (browser.usesPlanB()) {
2161 2231
         localSdp = this._adjustLocalMediaDirection(localSdp);
2162 2232
         localSdp = this._ensureSimulcastGroupIsLast(localSdp);
@@ -2358,10 +2428,16 @@ TraceablePeerConnection.prototype.setMaxBitRate = function() {
2358 2428
 TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
2359 2429
     this.trace('setRemoteDescription::preTransform', dumpSDP(description));
2360 2430
 
2431
+    /* eslint-disable no-param-reassign */
2432
+
2361 2433
     // Munge the order of the codecs based on the preferences set through config.js
2362
-    // eslint-disable-next-line no-param-reassign
2363 2434
     description = this._mungeCodecOrder(description);
2364 2435
 
2436
+    // Munge stereo flag and opusMaxAverageBitrate based on config.js
2437
+    description = this.mungeOpus(description);
2438
+
2439
+    /* eslint-enable no-param-reassign */
2440
+
2365 2441
     if (browser.usesPlanB()) {
2366 2442
         // TODO the focus should squeze or explode the remote simulcast
2367 2443
         if (this.isSimulcastOn()) {

+ 2
- 0
modules/xmpp/JingleSessionPC.js 查看文件

@@ -329,6 +329,8 @@ export default class JingleSessionPC extends JingleSession {
329 329
         pcOptions.enableInsertableStreams = options.enableInsertableStreams;
330 330
         pcOptions.videoQuality = options.videoQuality;
331 331
         pcOptions.forceTurnRelay = options.forceTurnRelay;
332
+        pcOptions.stereo = options.stereo;
333
+        pcOptions.opusMaxAverageBitrate = options.opusMaxAverageBitrate;
332 334
 
333 335
         if (this.isP2P) {
334 336
             // simulcast needs to be disabled for P2P (121) calls

+ 0
- 14
modules/xmpp/moderator.js 查看文件

@@ -186,13 +186,6 @@ Moderator.prototype.createConferenceIq = function() {
186 186
             }).up();
187 187
     }
188 188
 
189
-    if (config.opusMaxAverageBitrate) {
190
-        elem.c(
191
-            'property', {
192
-                name: 'opusMaxAverageBitrate',
193
-                value: config.opusMaxAverageBitrate
194
-            }).up();
195
-    }
196 189
     if (this.options.conference.startAudioMuted !== undefined) {
197 190
         elem.c(
198 191
             'property', {
@@ -207,13 +200,6 @@ Moderator.prototype.createConferenceIq = function() {
207 200
                 value: this.options.conference.startVideoMuted
208 201
             }).up();
209 202
     }
210
-    if (this.options.conference.stereo !== undefined) {
211
-        elem.c(
212
-            'property', {
213
-                name: 'stereo',
214
-                value: this.options.conference.stereo
215
-            }).up();
216
-    }
217 203
     elem.up();
218 204
 
219 205
     return elem;

正在加载...
取消
保存