зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1874789) for causing assertion failures at media.getusermedia.microphone.prefer_voice_stream_with_processing.enabled CLOSED TREE
Backed out changeset 80e08d441c6c (bug 1874789) Backed out changeset f0ab0afca52f (bug 1874789)
This commit is contained in:
Родитель
876d3096fd
Коммит
35824cf6dd
|
@ -65,9 +65,9 @@ git = "https://github.com/mozilla/audioipc"
|
|||
rev = "596bdb7fbb5745ea415726e16bd497e6c850a540"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=d23ab55eab684b46f46e1da177c8814f6103a009"]
|
||||
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ba39ca14bbb5bb0274843701cd958717a0fe293"]
|
||||
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
|
||||
rev = "d23ab55eab684b46f46e1da177c8814f6103a009"
|
||||
rev = "4ba39ca14bbb5bb0274843701cd958717a0fe293"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/cubeb-pulse-rs?rev=8ff972c8e2ec1782ff262ac4071c0415e69b1367"]
|
||||
|
|
|
@ -899,7 +899,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "coreaudio-sys-utils"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=d23ab55eab684b46f46e1da177c8814f6103a009#d23ab55eab684b46f46e1da177c8814f6103a009"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ba39ca14bbb5bb0274843701cd958717a0fe293#4ba39ca14bbb5bb0274843701cd958717a0fe293"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"coreaudio-sys",
|
||||
|
@ -1110,7 +1110,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cubeb-coreaudio"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=d23ab55eab684b46f46e1da177c8814f6103a009#d23ab55eab684b46f46e1da177c8814f6103a009"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ba39ca14bbb5bb0274843701cd958717a0fe293#4ba39ca14bbb5bb0274843701cd958717a0fe293"
|
||||
dependencies = [
|
||||
"atomic",
|
||||
"audio-mixer",
|
||||
|
|
|
@ -482,12 +482,11 @@ AudioCallbackDriver::AudioCallbackDriver(
|
|||
"Invalid output channel count");
|
||||
MOZ_ASSERT(mOutputChannelCount <= 8);
|
||||
|
||||
bool allowVoice = StaticPrefs::
|
||||
media_getusermedia_microphone_prefer_voice_stream_with_processing_enabled();
|
||||
bool allowVoice = true;
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
// Using the VoiceProcessingIO audio unit on MacOS 12 causes crashes in
|
||||
// OS code.
|
||||
allowVoice = allowVoice && nsCocoaFeatures::macOSVersionMajor() != 12;
|
||||
// platform code.
|
||||
allowVoice = nsCocoaFeatures::macOSVersionMajor() != 12;
|
||||
#endif
|
||||
|
||||
if (aAudioInputType == AudioInputType::Voice && allowVoice) {
|
||||
|
|
|
@ -10682,14 +10682,6 @@
|
|||
value: true
|
||||
mirror: once
|
||||
|
||||
# Tell the audio backend to prefer a stream adapted for voice when processing is
|
||||
# enabled through constraints (possibly defaults). Whether it has any effect
|
||||
# depends on the backend.
|
||||
- name: media.getusermedia.microphone.prefer_voice_stream_with_processing.enabled
|
||||
type: bool
|
||||
value: True
|
||||
mirror: always
|
||||
|
||||
# This pref turns on legacy (non-spec) exposure of camera and microphone
|
||||
# information from enumerateDevices and devicechange ahead of successful
|
||||
# getUserMedia calls. Should only be turned on to resolve web compat issues,
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"aa1998a3b104ad131805ca3513832cef3f65300192824f8b1efc9a5a0cc108f6",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"d7e757e664c23fae52028f1dfc5917f92523c08702e3a1f95e1fd38ed714416c","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"d717e598c96e4911d9494b18382d6bd3a8d5038b7d68d3166ad4336e237a97d8","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"43511107ba2a75a19340ac663c981362ca1b75b679b6c295d88b5035bd7e3619","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"a7622feaa41db1cd76fd35a85a022e44f4894e396a104a59008d5b8757d2ab4e","src/backend/mixer.rs":"ed299d3954e2a823060c870a8244673a7d4bca530830cb66b964d047a80ee3af","src/backend/mod.rs":"1591669c30a3d07754bfb39c9cb042cdd101f0ab89be13f6cdf74d376e441cf8","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"e3f94e118e1dd47941fbba4417de40bddc4254d9f06b1e938f58d8f1aa566a5c","src/backend/tests/api.rs":"cd7e7551e2e82b19da883621a494d2a6779c373f3ff2d12ee52fae8efec1e7b8","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"f68c2eaa55c3ec2a58894832fbca1e2a2e79e740b145f76a0f45452af465a934","src/backend/tests/device_property.rs":"ea0be5f8834be494cb33f854ce9d334b5763dc5287f949bcb4bd025d8a8b2d3b","src/backend/tests/interfaces.rs":"af8e3fdeb58226621699b29f1a90621b2260e3f17292dac54860cd05fe4eec71","src/backend/tests/manual.rs":"4a1634e86beb145d2703722a8be057a762953241329c82ee09acf7dc0f0d9d0c","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"59632744e70616ab7037facb0787db339b96800c8cc397d203241548c5cfb7f5","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"efb8b3709aff7ed5e2923566084de3e0709f3bd9c18a04f3310d7a3b86fa4b71","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}
|
||||
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"aa1998a3b104ad131805ca3513832cef3f65300192824f8b1efc9a5a0cc108f6",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"d7e757e664c23fae52028f1dfc5917f92523c08702e3a1f95e1fd38ed714416c","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"d717e598c96e4911d9494b18382d6bd3a8d5038b7d68d3166ad4336e237a97d8","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"43511107ba2a75a19340ac663c981362ca1b75b679b6c295d88b5035bd7e3619","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"a7622feaa41db1cd76fd35a85a022e44f4894e396a104a59008d5b8757d2ab4e","src/backend/mixer.rs":"ed299d3954e2a823060c870a8244673a7d4bca530830cb66b964d047a80ee3af","src/backend/mod.rs":"4f07743a46a4b908c9e23b31d0bc8f3a0983b943e0bb824b9154272b2673ae90","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"e3f94e118e1dd47941fbba4417de40bddc4254d9f06b1e938f58d8f1aa566a5c","src/backend/tests/api.rs":"cd7e7551e2e82b19da883621a494d2a6779c373f3ff2d12ee52fae8efec1e7b8","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"f68c2eaa55c3ec2a58894832fbca1e2a2e79e740b145f76a0f45452af465a934","src/backend/tests/device_property.rs":"ea0be5f8834be494cb33f854ce9d334b5763dc5287f949bcb4bd025d8a8b2d3b","src/backend/tests/interfaces.rs":"2f192d08a5b2cbf678e0fea38b7061b1f0e83aa6b8f443bd92b70fee67c35516","src/backend/tests/manual.rs":"0c1bbd9b6137bbc484974c4bf7ea965872b8f52f86055f07916b85a3d715e0a6","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"59632744e70616ab7037facb0787db339b96800c8cc397d203241548c5cfb7f5","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"efb8b3709aff7ed5e2923566084de3e0709f3bd9c18a04f3310d7a3b86fa4b71","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}
|
|
@ -32,11 +32,12 @@ use self::device_property::*;
|
|||
use self::mixer::*;
|
||||
use self::resampler::*;
|
||||
use self::utils::*;
|
||||
use atomic;
|
||||
use backend::ringbuf::RingBuffer;
|
||||
use cubeb_backend::{
|
||||
ffi, ChannelLayout, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType,
|
||||
Error, InputProcessingParams, Ops, Result, SampleFormat, State, Stream, StreamOps,
|
||||
StreamParams, StreamParamsRef, StreamPrefs,
|
||||
ffi, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType, Error,
|
||||
InputProcessingParams, Ops, Result, SampleFormat, State, Stream, StreamOps, StreamParams,
|
||||
StreamParamsRef, StreamPrefs,
|
||||
};
|
||||
use mach::mach_time::{mach_absolute_time, mach_timebase_info};
|
||||
use std::cmp;
|
||||
|
@ -58,8 +59,6 @@ const DISPATCH_QUEUE_LABEL: &str = "org.mozilla.cubeb";
|
|||
const PRIVATE_AGGREGATE_DEVICE_NAME: &str = "CubebAggregateDevice";
|
||||
const VOICEPROCESSING_AGGREGATE_DEVICE_NAME: &str = "VPAUAggregateAudioDevice";
|
||||
|
||||
const APPLE_STUDIO_DISPLAY_USB_ID: &str = "05AC:1114";
|
||||
|
||||
// Testing empirically, some headsets report a minimal latency that is very low,
|
||||
// but this does not work in practice. Lie and say the minimum is 128 frames.
|
||||
const SAFE_MIN_LATENCY_FRAMES: u32 = 128;
|
||||
|
@ -287,26 +286,7 @@ fn get_volume(unit: AudioUnit) -> Result<f32> {
|
|||
|
||||
fn set_input_mute(unit: AudioUnit, mute: bool) -> Result<()> {
|
||||
assert!(!unit.is_null());
|
||||
let mute: u32 = mute.into();
|
||||
let mut old_mute: u32 = 0;
|
||||
let r = audio_unit_get_property(
|
||||
unit,
|
||||
kAUVoiceIOProperty_MuteOutput,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&mut old_mute,
|
||||
&mut mem::size_of::<u32>(),
|
||||
);
|
||||
if r != NO_ERR {
|
||||
cubeb_log!(
|
||||
"AudioUnitGetProperty/kAUVoiceIOProperty_MuteOutput rv={}",
|
||||
r
|
||||
);
|
||||
return Err(Error::error());
|
||||
}
|
||||
if old_mute == mute {
|
||||
return Ok(());
|
||||
}
|
||||
let mute: UInt32 = mute.into();
|
||||
let r = audio_unit_set_property(
|
||||
unit,
|
||||
kAUVoiceIOProperty_MuteOutput,
|
||||
|
@ -330,85 +310,52 @@ fn set_input_processing_params(unit: AudioUnit, params: InputProcessingParams) -
|
|||
assert!(!unit.is_null());
|
||||
let aec = params.contains(InputProcessingParams::ECHO_CANCELLATION);
|
||||
let ns = params.contains(InputProcessingParams::NOISE_SUPPRESSION);
|
||||
let agc = params.contains(InputProcessingParams::AUTOMATIC_GAIN_CONTROL);
|
||||
|
||||
// AEC and NS are active as soon as VPIO is not bypassed, therefore the only combinations
|
||||
// of those we can explicitly support are {} and {aec, ns}.
|
||||
// We don't use AGC, but keep it here for reference.
|
||||
// See the comment in supported_input_processing_params.
|
||||
let agc = params.contains(InputProcessingParams::AUTOMATIC_GAIN_CONTROL);
|
||||
assert!(!agc);
|
||||
|
||||
// AEC and NS are active as soon as VPIO is not bypassed.
|
||||
// Therefore the only modes we can explicitly support are {} and {aec, ns}.
|
||||
|
||||
if aec != ns {
|
||||
// No control to turn on AEC without NS or vice versa.
|
||||
return Err(Error::error());
|
||||
}
|
||||
|
||||
let mut old_agc: u32 = 0;
|
||||
let r = audio_unit_get_property(
|
||||
let agc = u32::from(agc);
|
||||
let r = audio_unit_set_property(
|
||||
unit,
|
||||
kAUVoiceIOProperty_VoiceProcessingEnableAGC,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&mut old_agc,
|
||||
&mut mem::size_of::<u32>(),
|
||||
&agc,
|
||||
mem::size_of::<u32>(),
|
||||
);
|
||||
if r != NO_ERR {
|
||||
cubeb_log!(
|
||||
"AudioUnitGetProperty/kAUVoiceIOProperty_VoiceProcessingEnableAGC rv={}",
|
||||
r
|
||||
);
|
||||
return Err(Error::error());
|
||||
}
|
||||
|
||||
if (old_agc == 1) != agc {
|
||||
let agc = u32::from(agc);
|
||||
let r = audio_unit_set_property(
|
||||
unit,
|
||||
kAUVoiceIOProperty_VoiceProcessingEnableAGC,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&agc,
|
||||
mem::size_of::<u32>(),
|
||||
);
|
||||
if r != NO_ERR {
|
||||
cubeb_log!(
|
||||
"AudioUnitSetProperty/kAUVoiceIOProperty_VoiceProcessingEnableAGC rv={}",
|
||||
r
|
||||
);
|
||||
return Err(Error::error());
|
||||
}
|
||||
}
|
||||
|
||||
let mut old_bypass: u32 = 0;
|
||||
let r = audio_unit_get_property(
|
||||
unit,
|
||||
kAUVoiceIOProperty_BypassVoiceProcessing,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&mut old_bypass,
|
||||
&mut mem::size_of::<u32>(),
|
||||
);
|
||||
if r != NO_ERR {
|
||||
cubeb_log!(
|
||||
"AudioUnitGetProperty/kAUVoiceIOProperty_BypassVoiceProcessing rv={}",
|
||||
"AudioUnitSetProperty/kAUVoiceIOProperty_VoiceProcessingEnableAGC rv={}",
|
||||
r
|
||||
);
|
||||
return Err(Error::error());
|
||||
}
|
||||
|
||||
let bypass = u32::from(!aec);
|
||||
if old_bypass != bypass {
|
||||
let r = audio_unit_set_property(
|
||||
unit,
|
||||
kAUVoiceIOProperty_BypassVoiceProcessing,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&bypass,
|
||||
mem::size_of::<u32>(),
|
||||
let r = audio_unit_set_property(
|
||||
unit,
|
||||
kAUVoiceIOProperty_BypassVoiceProcessing,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&bypass,
|
||||
mem::size_of::<u32>(),
|
||||
);
|
||||
if r != NO_ERR {
|
||||
cubeb_log!(
|
||||
"AudioUnitSetProperty/kAUVoiceIOProperty_BypassVoiceProcessing rv={}",
|
||||
r
|
||||
);
|
||||
if r != NO_ERR {
|
||||
cubeb_log!(
|
||||
"AudioUnitSetProperty/kAUVoiceIOProperty_BypassVoiceProcessing rv={}",
|
||||
r
|
||||
);
|
||||
return Err(Error::error());
|
||||
}
|
||||
return Err(Error::error());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1471,8 +1418,6 @@ fn get_channel_count(
|
|||
assert_ne!(devid, kAudioObjectUnknown);
|
||||
|
||||
let mut streams = get_device_streams(devid, devtype)?;
|
||||
let model_uid =
|
||||
get_device_model_uid(devid, devtype).map_or_else(|_| String::new(), |s| s.into_string());
|
||||
|
||||
if devtype == DeviceType::INPUT {
|
||||
// With VPIO, output devices will/may get a Tap that appears as input channels on the
|
||||
|
@ -1517,13 +1462,6 @@ fn get_channel_count(
|
|||
);
|
||||
false
|
||||
}
|
||||
// The input tap stream on the Studio Display Speakers has a terminal type that
|
||||
// is not clearly output-specific. We special-case it here.
|
||||
EXTERNAL_DIGITAL_AUDIO_INTERFACE
|
||||
if model_uid.contains(APPLE_STUDIO_DISPLAY_USB_ID) =>
|
||||
{
|
||||
false
|
||||
}
|
||||
// Note INPUT_UNDEFINED is 0x200 and INPUT_MICROPHONE is 0x201
|
||||
t if (INPUT_MICROPHONE..OUTPUT_UNDEFINED).contains(&t) => true,
|
||||
t if (OUTPUT_UNDEFINED..BIDIRECTIONAL_UNDEFINED).contains(&t) => false,
|
||||
|
@ -2299,9 +2237,11 @@ impl ContextOps for AudioUnitContext {
|
|||
Ok(rate as u32)
|
||||
}
|
||||
fn supported_input_processing_params(&mut self) -> Result<InputProcessingParams> {
|
||||
Ok(InputProcessingParams::ECHO_CANCELLATION
|
||||
| InputProcessingParams::NOISE_SUPPRESSION
|
||||
| InputProcessingParams::AUTOMATIC_GAIN_CONTROL)
|
||||
// The VoiceProcessingIO AudioUnit has the
|
||||
// kAUVoiceIOProperty_VoiceProcessingEnableAGC property to enable AGC on
|
||||
// the input signal, but some simple manual tests on MacOS 14.0 suggest
|
||||
// it doesn't have any effect.
|
||||
Ok(InputProcessingParams::ECHO_CANCELLATION | InputProcessingParams::NOISE_SUPPRESSION)
|
||||
}
|
||||
fn enumerate_devices(
|
||||
&mut self,
|
||||
|
@ -2565,8 +2505,6 @@ struct CoreStreamData<'ctx> {
|
|||
// Info of the I/O devices.
|
||||
input_device: device_info,
|
||||
output_device: device_info,
|
||||
input_processing_params: InputProcessingParams,
|
||||
input_mute: bool,
|
||||
input_buffer_manager: Option<BufferManager>,
|
||||
// Listeners indicating what system events are monitored.
|
||||
default_input_listener: Option<device_property_listener>,
|
||||
|
@ -2605,8 +2543,6 @@ impl<'ctx> Default for CoreStreamData<'ctx> {
|
|||
output_unit: ptr::null_mut(),
|
||||
input_device: device_info::default(),
|
||||
output_device: device_info::default(),
|
||||
input_processing_params: InputProcessingParams::NONE,
|
||||
input_mute: false,
|
||||
input_buffer_manager: None,
|
||||
default_input_listener: None,
|
||||
default_output_listener: None,
|
||||
|
@ -2651,8 +2587,6 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
output_unit: ptr::null_mut(),
|
||||
input_device: in_dev,
|
||||
output_device: out_dev,
|
||||
input_processing_params: InputProcessingParams::NONE,
|
||||
input_mute: false,
|
||||
input_buffer_manager: None,
|
||||
default_input_listener: None,
|
||||
default_output_listener: None,
|
||||
|
@ -2744,50 +2678,6 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
input_domain == output_domain
|
||||
}
|
||||
|
||||
fn should_block_vpio_for_device_pair(
|
||||
&self,
|
||||
in_device: &device_info,
|
||||
out_device: &device_info,
|
||||
) -> bool {
|
||||
self.debug_assert_is_on_stream_queue();
|
||||
cubeb_log!("Evaluating device pair against VPIO block list");
|
||||
let log_device = |id, devtype| -> std::result::Result<(), OSStatus> {
|
||||
cubeb_log!("{} uid=\"{}\", model_uid=\"{}\", transport_type={:?}, source={:?}, source_name=\"{}\", name=\"{}\", manufacturer=\"{}\"",
|
||||
if devtype == DeviceType::INPUT {
|
||||
"Input"
|
||||
} else {
|
||||
debug_assert_eq!(devtype, DeviceType::OUTPUT);
|
||||
"Output"
|
||||
},
|
||||
get_device_uid(id, devtype).map(|s| s.into_string()).unwrap_or_default(),
|
||||
get_device_model_uid(id, devtype).map(|s| s.into_string()).unwrap_or_default(),
|
||||
convert_uint32_into_string(get_device_transport_type(id, devtype).unwrap_or(0)),
|
||||
convert_uint32_into_string(get_device_source(id, devtype).unwrap_or(0)),
|
||||
get_device_source_name(id, devtype).map(|s| s.into_string()).unwrap_or_default(),
|
||||
get_device_name(id, devtype).map(|s| s.into_string()).unwrap_or_default(),
|
||||
get_device_manufacturer(id, devtype).map(|s| s.into_string()).unwrap_or_default());
|
||||
Ok(())
|
||||
};
|
||||
log_device(in_device.id, DeviceType::INPUT);
|
||||
log_device(out_device.id, DeviceType::OUTPUT);
|
||||
match (
|
||||
get_device_model_uid(in_device.id, DeviceType::INPUT).map(|s| s.to_string()),
|
||||
get_device_model_uid(out_device.id, DeviceType::OUTPUT).map(|s| s.to_string()),
|
||||
) {
|
||||
(Ok(in_model_uid), Ok(out_model_uid))
|
||||
if in_model_uid.contains(APPLE_STUDIO_DISPLAY_USB_ID)
|
||||
&& out_model_uid.contains(APPLE_STUDIO_DISPLAY_USB_ID) =>
|
||||
{
|
||||
cubeb_log!("Both input and output device is an Apple Studio Display. BLOCKED");
|
||||
true
|
||||
}
|
||||
_ => {
|
||||
cubeb_log!("Device pair is not blocked");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_audiounits(&mut self) -> Result<(device_info, device_info)> {
|
||||
self.debug_assert_is_on_stream_queue();
|
||||
let should_use_voice_processing_unit = self.has_input()
|
||||
|
@ -2795,8 +2685,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
&& self
|
||||
.input_stream_params
|
||||
.prefs()
|
||||
.contains(StreamPrefs::VOICE)
|
||||
&& !self.should_block_vpio_for_device_pair(&self.input_device, &self.output_device);
|
||||
.contains(StreamPrefs::VOICE);
|
||||
|
||||
let should_use_aggregate_device = {
|
||||
// It's impossible to create an aggregate device from an aggregate device, and it's
|
||||
|
@ -2826,7 +2715,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
}
|
||||
cubeb_log!(
|
||||
"Output device ID: {} (aggregate: {:?})",
|
||||
self.output_device.id,
|
||||
self.input_device.id,
|
||||
output_is_aggregate
|
||||
);
|
||||
}
|
||||
|
@ -3046,7 +2935,8 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
let params = unsafe {
|
||||
let mut p = *self.input_stream_params.as_ptr();
|
||||
p.channels = if using_voice_processing_unit {
|
||||
// VPIO is always MONO.
|
||||
// With VPIO, stereo input devices configured for stereo have been observed to
|
||||
// spit out only a single mono channel.
|
||||
1
|
||||
} else {
|
||||
input_hw_desc.mChannelsPerFrame
|
||||
|
@ -3164,6 +3054,9 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
out_dev_info
|
||||
);
|
||||
|
||||
let device_channel_count =
|
||||
get_channel_count(self.output_device.id, DeviceType::OUTPUT).unwrap_or(0);
|
||||
|
||||
cubeb_log!(
|
||||
"({:p}) Opening output side: rate {}, channels {}, format {:?}, layout {:?}, prefs {:?}, latency in frames {}, voice processing {}.",
|
||||
self.stm_ptr,
|
||||
|
@ -3200,10 +3093,9 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
output_hw_desc
|
||||
);
|
||||
|
||||
// In some cases with (other streams using) VPIO the stream format's mChannelsPerFrame
|
||||
// is higher than expected. Use get_channel_count as source of truth.
|
||||
output_hw_desc.mChannelsPerFrame =
|
||||
get_channel_count(self.output_device.id, DeviceType::OUTPUT).unwrap_or(0);
|
||||
// In some cases with VPIO the stream format's mChannelsPerFrame is higher than
|
||||
// expected. Use get_channel_count as source of truth.
|
||||
output_hw_desc.mChannelsPerFrame = device_channel_count;
|
||||
|
||||
// This has been observed in the wild.
|
||||
if output_hw_desc.mChannelsPerFrame == 0 {
|
||||
|
@ -3220,12 +3112,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
// channels will be appended at the end of the raw data given by the output callback.
|
||||
let params = unsafe {
|
||||
let mut p = *self.output_stream_params.as_ptr();
|
||||
p.channels = if using_voice_processing_unit {
|
||||
// VPIO is always MONO.
|
||||
1
|
||||
} else {
|
||||
output_hw_desc.mChannelsPerFrame
|
||||
};
|
||||
p.channels = output_hw_desc.mChannelsPerFrame;
|
||||
if using_voice_processing_unit {
|
||||
// VPIO will always use the sample rate of the input hw for both input and output,
|
||||
// as reported to us. (We can override it but we cannot improve quality this way).
|
||||
|
@ -3473,26 +3360,12 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
);
|
||||
}
|
||||
|
||||
// Always try to remember the applied input mute state. If it cannot be applied
|
||||
// to the new device pair, we notify the client of an error and it will have to
|
||||
// open a new stream.
|
||||
if let Err(r) = set_input_mute(self.input_unit, self.input_mute) {
|
||||
cubeb_log!(
|
||||
"({:p}) Failed to set mute state of voiceprocessing. Error: {}",
|
||||
self.stm_ptr,
|
||||
r
|
||||
);
|
||||
return Err(r);
|
||||
}
|
||||
|
||||
// Always try to remember the applied input processing params. If they cannot
|
||||
// be applied in the new device pair, we notify the client of an error and it
|
||||
// will have to open a new stream.
|
||||
// Always initiate to not use input processing.
|
||||
if let Err(r) =
|
||||
set_input_processing_params(self.input_unit, self.input_processing_params)
|
||||
set_input_processing_params(self.input_unit, InputProcessingParams::NONE)
|
||||
{
|
||||
cubeb_log!(
|
||||
"({:p}) Failed to set params of voiceprocessing. Error: {}",
|
||||
"({:p}) Failed to enable bypass of voiceprocessing. Error: {}",
|
||||
self.stm_ptr,
|
||||
r
|
||||
);
|
||||
|
@ -3846,10 +3719,23 @@ impl<'ctx> CoreStreamData<'ctx> {
|
|||
fn get_output_channel_layout(&self) -> Result<Vec<mixer::Channel>> {
|
||||
self.debug_assert_is_on_stream_queue();
|
||||
assert!(!self.output_unit.is_null());
|
||||
if self.using_voice_processing_unit() {
|
||||
return Ok(get_channel_order(ChannelLayout::MONO));
|
||||
if !self.using_voice_processing_unit() {
|
||||
return get_channel_layout(self.output_unit);
|
||||
}
|
||||
get_channel_layout(self.output_unit)
|
||||
|
||||
// The VoiceProcessingIO unit (as tried on MacOS 14) is known to not support
|
||||
// kAudioUnitProperty_AudioChannelLayout queries, and to lie about
|
||||
// kAudioDevicePropertyPreferredChannelLayout. If we're using
|
||||
// VoiceProcessingIO, try standing up a regular AudioUnit and query that.
|
||||
cubeb_log!(
|
||||
"({:p}) get_output_channel_layout with a VoiceProcessingIO output unit. Trying a dedicated unit.",
|
||||
self.stm_ptr
|
||||
);
|
||||
let mut dedicated_unit = create_audiounit(&self.output_device)?;
|
||||
let res = get_channel_layout(dedicated_unit);
|
||||
dispose_audio_unit(dedicated_unit);
|
||||
dedicated_unit = ptr::null_mut();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4331,7 +4217,6 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
|
|||
self as *const AudioUnitStream,
|
||||
mute
|
||||
);
|
||||
self.core_stream_data.input_mute = mute;
|
||||
Ok(())
|
||||
}
|
||||
fn set_input_processing_params(&mut self, params: InputProcessingParams) -> Result<()> {
|
||||
|
@ -4372,7 +4257,6 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
|
|||
self as *const AudioUnitStream,
|
||||
params
|
||||
);
|
||||
self.core_stream_data.input_processing_params = params;
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(target_os = "ios")]
|
||||
|
|
|
@ -90,7 +90,6 @@ fn test_ops_context_supported_input_processing_params() {
|
|||
params,
|
||||
ffi::CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -1018,54 +1017,6 @@ fn test_ops_duplex_voice_stream_set_input_mute() {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ops_duplex_voice_stream_set_input_mute_before_start() {
|
||||
test_default_duplex_voice_stream_operation(
|
||||
"duplex voice stream: mute before start",
|
||||
|stream| {
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_set_input_mute.unwrap()(stream, 1) },
|
||||
ffi::CUBEB_OK
|
||||
);
|
||||
assert_eq!(unsafe { OPS.stream_start.unwrap()(stream) }, ffi::CUBEB_OK);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ops_duplex_voice_stream_set_input_mute_before_start_with_reinit() {
|
||||
test_default_duplex_voice_stream_operation(
|
||||
"duplex voice stream: mute before start with reinit",
|
||||
|stream| {
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_set_input_mute.unwrap()(stream, 1) },
|
||||
ffi::CUBEB_OK
|
||||
);
|
||||
assert_eq!(unsafe { OPS.stream_start.unwrap()(stream) }, ffi::CUBEB_OK);
|
||||
|
||||
// Hacky cast, but testing this here was simplest for now.
|
||||
let stm = unsafe { &mut *(stream as *mut AudioUnitStream) };
|
||||
stm.reinit_async();
|
||||
let queue = stm.queue.clone();
|
||||
let mut mute_after_reinit = false;
|
||||
queue.run_sync(|| {
|
||||
let mut mute: u32 = 0;
|
||||
let r = audio_unit_get_property(
|
||||
stm.core_stream_data.input_unit,
|
||||
kAUVoiceIOProperty_MuteOutput,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&mut mute,
|
||||
&mut mem::size_of::<u32>(),
|
||||
);
|
||||
assert_eq!(r, NO_ERR);
|
||||
mute_after_reinit = mute == 1;
|
||||
});
|
||||
assert_eq!(mute_after_reinit, true);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ops_duplex_voice_stream_set_input_mute_after_start() {
|
||||
test_default_duplex_voice_stream_operation("duplex voice stream: mute after start", |stream| {
|
||||
|
@ -1082,8 +1033,7 @@ fn test_ops_duplex_voice_stream_set_input_processing_params() {
|
|||
test_default_duplex_voice_stream_operation("duplex voice stream: processing", |stream| {
|
||||
let params: ffi::cubeb_input_processing_params =
|
||||
ffi::CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL;
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION;
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_set_input_processing_params.unwrap()(stream, params) },
|
||||
ffi::CUBEB_OK
|
||||
|
@ -1098,8 +1048,7 @@ fn test_ops_duplex_voice_stream_set_input_processing_params_before_start() {
|
|||
|stream| {
|
||||
let params: ffi::cubeb_input_processing_params =
|
||||
ffi::CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL;
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION;
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_set_input_processing_params.unwrap()(stream, params) },
|
||||
ffi::CUBEB_OK
|
||||
|
@ -1109,65 +1058,6 @@ fn test_ops_duplex_voice_stream_set_input_processing_params_before_start() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ops_duplex_voice_stream_set_input_processing_params_before_start_with_reinit() {
|
||||
test_default_duplex_voice_stream_operation(
|
||||
"duplex voice stream: processing before start with reinit",
|
||||
|stream| {
|
||||
let params: ffi::cubeb_input_processing_params =
|
||||
ffi::CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL;
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_set_input_processing_params.unwrap()(stream, params) },
|
||||
ffi::CUBEB_OK
|
||||
);
|
||||
assert_eq!(unsafe { OPS.stream_start.unwrap()(stream) }, ffi::CUBEB_OK);
|
||||
|
||||
// Hacky cast, but testing this here was simplest for now.
|
||||
let stm = unsafe { &mut *(stream as *mut AudioUnitStream) };
|
||||
stm.reinit_async();
|
||||
let queue = stm.queue.clone();
|
||||
let mut params_after_reinit: ffi::cubeb_input_processing_params =
|
||||
ffi::CUBEB_INPUT_PROCESSING_PARAM_NONE;
|
||||
queue.run_sync(|| {
|
||||
let mut params: ffi::cubeb_input_processing_params =
|
||||
ffi::CUBEB_INPUT_PROCESSING_PARAM_NONE;
|
||||
let mut agc: u32 = 0;
|
||||
let r = audio_unit_get_property(
|
||||
stm.core_stream_data.input_unit,
|
||||
kAUVoiceIOProperty_VoiceProcessingEnableAGC,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&mut agc,
|
||||
&mut mem::size_of::<u32>(),
|
||||
);
|
||||
assert_eq!(r, NO_ERR);
|
||||
if agc == 1 {
|
||||
params = params | ffi::CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL;
|
||||
}
|
||||
let mut bypass: u32 = 0;
|
||||
let r = audio_unit_get_property(
|
||||
stm.core_stream_data.input_unit,
|
||||
kAUVoiceIOProperty_BypassVoiceProcessing,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&mut bypass,
|
||||
&mut mem::size_of::<u32>(),
|
||||
);
|
||||
assert_eq!(r, NO_ERR);
|
||||
if bypass == 0 {
|
||||
params = params
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION;
|
||||
}
|
||||
params_after_reinit = params;
|
||||
});
|
||||
assert_eq!(params, params_after_reinit);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ops_duplex_voice_stream_set_input_processing_params_after_start() {
|
||||
test_default_duplex_voice_stream_operation(
|
||||
|
@ -1176,8 +1066,7 @@ fn test_ops_duplex_voice_stream_set_input_processing_params_after_start() {
|
|||
assert_eq!(unsafe { OPS.stream_start.unwrap()(stream) }, ffi::CUBEB_OK);
|
||||
let params: ffi::cubeb_input_processing_params =
|
||||
ffi::CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL;
|
||||
| ffi::CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION;
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_set_input_processing_params.unwrap()(stream, params) },
|
||||
ffi::CUBEB_OK
|
||||
|
|
|
@ -338,6 +338,23 @@ fn test_stream_tester() {
|
|||
params.set(InputProcessingParams::ECHO_CANCELLATION, true);
|
||||
params.set(InputProcessingParams::NOISE_SUPPRESSION, true);
|
||||
}
|
||||
let mut agc = u32::from(false);
|
||||
let mut size: usize = mem::size_of::<u32>();
|
||||
assert_eq!(
|
||||
audio_unit_get_property(
|
||||
stm.core_stream_data.input_unit,
|
||||
kAUVoiceIOProperty_VoiceProcessingEnableAGC,
|
||||
kAudioUnitScope_Global,
|
||||
AU_IN_BUS,
|
||||
&mut agc,
|
||||
&mut size,
|
||||
),
|
||||
NO_ERR
|
||||
);
|
||||
assert_eq!(size, mem::size_of::<u32>());
|
||||
if agc == 1 {
|
||||
params.set(InputProcessingParams::AUTOMATIC_GAIN_CONTROL, true);
|
||||
}
|
||||
}
|
||||
let mut done = false;
|
||||
while !done {
|
||||
|
|
|
@ -22,7 +22,7 @@ static_prefs = { path = "../../../../modules/libpref/init/static_prefs" }
|
|||
profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
|
||||
mozurl = { path = "../../../../netwerk/base/mozurl" }
|
||||
webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
|
||||
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "d23ab55eab684b46f46e1da177c8814f6103a009", optional = true }
|
||||
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "4ba39ca14bbb5bb0274843701cd958717a0fe293", optional = true }
|
||||
cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="8ff972c8e2ec1782ff262ac4071c0415e69b1367", optional = true, features=["pulse-dlopen"] }
|
||||
cubeb-sys = { version = "0.12.0", optional = true, features=["gecko-in-tree"] }
|
||||
audioipc2-client = { git = "https://github.com/mozilla/audioipc", rev = "596bdb7fbb5745ea415726e16bd497e6c850a540", optional = true }
|
||||
|
|
Загрузка…
Ссылка в новой задаче