Skip to content

Commit 76fe402

Browse files
committed
WIP SharedVoiceProcessingUnit
1 parent 71695a7 commit 76fe402

File tree

2 files changed

+62
-45
lines changed

2 files changed

+62
-45
lines changed

src/backend/mod.rs

+61-43
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use self::utils::*;
3535
use backend::ringbuf::RingBuffer;
3636
use cubeb_backend::{
3737
ffi, ChannelLayout, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType,
38-
Error, InputProcessingParams, Ops, Result, SampleFormat, State, Stream, StreamOps,
38+
Error, ErrorCode, InputProcessingParams, Ops, Result, SampleFormat, State, Stream, StreamOps,
3939
StreamParams, StreamParamsRef, StreamPrefs,
4040
};
4141
use mach::mach_time::{mach_absolute_time, mach_timebase_info};
@@ -1162,6 +1162,7 @@ fn create_voiceprocessing_audiounit(
11621162
in_device: &device_info,
11631163
out_device: &device_info,
11641164
) -> Result<OwningHandle<AudioUnit>> {
1165+
debug_assert_running_serially();
11651166
assert!(in_device.flags.contains(device_flags::DEV_INPUT));
11661167
assert!(!in_device.flags.contains(device_flags::DEV_OUTPUT));
11671168
assert!(!out_device.flags.contains(device_flags::DEV_INPUT));
@@ -2134,44 +2135,29 @@ struct SharedVoiceProcessingUnitStorage {
21342135
#[derive(Debug)]
21352136
struct SharedVoiceProcessingUnit {
21362137
sync_storage: Mutex<SharedVoiceProcessingUnitStorage>,
2137-
condvar: Condvar,
21382138
queue: Queue,
21392139
}
21402140

21412141
impl SharedVoiceProcessingUnit {
21422142
fn new(queue: Queue) -> Self {
21432143
Self {
21442144
sync_storage: Mutex::new(SharedVoiceProcessingUnitStorage::default()),
2145-
condvar: Condvar::new(),
21462145
queue,
21472146
}
21482147
}
21492148

2150-
fn prime(&mut self) {
2149+
fn ensure_unit(&mut self) -> Result<()> {
21512150
debug_assert_running_serially();
2152-
{
2153-
let mut guard = self.sync_storage.lock().unwrap();
2154-
if guard.priming {
2155-
return;
2156-
}
2157-
if guard.storage.is_some() {
2158-
return;
2159-
}
2160-
cubeb_log!("Priming the shared voiceprocessing unit");
2161-
guard.priming = true;
2162-
}
2163-
let unit = create_typed_audiounit(kAudioUnitSubType_VoiceProcessingIO);
21642151
let mut guard = self.sync_storage.lock().unwrap();
2152+
if guard.storage.is_some() {
2153+
// No need to create vpio unit as one already exists.
2154+
return Err(Error::not_supported());
2155+
}
21652156
guard.priming = false;
2166-
self.condvar.notify_all();
2167-
if let Err(e) = unit {
2168-
cubeb_log!(
2169-
"Failed creating voiceprocessing unit while priming async. r={}",
2170-
e
2171-
);
2172-
return;
2157+
let unit = create_typed_audiounit(kAudioUnitSubType_VoiceProcessingIO);
2158+
if unit.is_err() {
2159+
return Err(Error::error());
21732160
}
2174-
cubeb_log!("Shared voiceprocessing unit primed and ready");
21752161

21762162
match get_default_device(DeviceType::OUTPUT) {
21772163
None => {
@@ -2191,31 +2177,54 @@ impl SharedVoiceProcessingUnit {
21912177

21922178
let old_storage = guard.storage.replace(Arc::from(Mutex::new(unit.ok())));
21932179
assert!(old_storage.is_none());
2180+
Ok(())
2181+
}
2182+
2183+
fn prime(&mut self) {
2184+
{
2185+
let mut guard = self.sync_storage.lock().unwrap();
2186+
if guard.storage.is_some() {
2187+
// No need to prime as unit already exists.
2188+
return;
2189+
}
2190+
if guard.priming {
2191+
// No need to prime async as another call is already doing it.
2192+
return;
2193+
}
2194+
cubeb_log!("Priming the shared voiceprocessing unit");
2195+
guard.priming = true;
2196+
}
2197+
self.queue
2198+
.clone()
2199+
.run_async(move || match self.ensure_unit() {
2200+
Ok(()) => {
2201+
cubeb_log!("Shared voiceprocessing unit primed and ready");
2202+
}
2203+
Err(e) => match e.code() {
2204+
ErrorCode::Error => {
2205+
cubeb_log!("Error creating shared voiceprocessing unit for priming");
2206+
}
2207+
ErrorCode::NotSupported => {
2208+
cubeb_log!("Shared voiceprocessing unit was created before async priming");
2209+
}
2210+
_ => unreachable!("Unexpected error"),
2211+
},
2212+
});
21942213
}
21952214

21962215
fn take(&mut self) -> Result<OwningHandle<AudioUnit>> {
21972216
debug_assert_running_serially();
2198-
let guard = self.sync_storage.lock().unwrap();
2199-
let mut guard = self
2200-
.condvar
2201-
.wait_while(guard, |storage| storage.priming)
2202-
.unwrap();
2203-
if guard.storage.is_none() {
2204-
cubeb_log!("Creating synchronously the shared voiceprocessing unit");
2205-
let unit = create_typed_audiounit(kAudioUnitSubType_VoiceProcessingIO)?;
2206-
guard.storage.replace(Arc::from(Mutex::new(Some(unit))));
2217+
if let Err(e) = self.ensure_unit() {
2218+
if e.code() == ErrorCode::Error {
2219+
return Err(e);
2220+
}
22072221
}
2222+
let mut guard = self.sync_storage.lock().unwrap();
22082223
let storage: Arc<SharedStorage<AudioUnit>> = guard.storage.as_mut().unwrap().clone();
22092224
let mut guard = (*storage).lock().unwrap();
22102225
match guard.take() {
2211-
Some(unit) => {
2212-
cubeb_log!("voiceprocessing audiounit now taken");
2213-
Ok(OwningHandle::new(Arc::downgrade(&storage), unit))
2214-
}
2215-
None => {
2216-
cubeb_log!("voiceprocessing audiounit was requested but already taken");
2217-
Err(Error::device_unavailable())
2218-
}
2226+
Some(unit) => Ok(OwningHandle::new(Arc::downgrade(&storage), unit)),
2227+
None => Err(Error::device_unavailable()),
22192228
}
22202229
}
22212230
}
@@ -2225,6 +2234,7 @@ unsafe impl Sync for SharedVoiceProcessingUnit {}
22252234

22262235
impl Drop for SharedVoiceProcessingUnit {
22272236
fn drop(&mut self) {
2237+
debug_assert_not_running_serially();
22282238
self.queue.run_final(|| {
22292239
let mut guard = self.sync_storage.lock().unwrap();
22302240
assert!(!guard.priming);
@@ -2418,6 +2428,11 @@ impl ContextOps for AudioUnitContext {
24182428
let queue_label = format!("{}.context.{:p}", DISPATCH_QUEUE_LABEL, ctx.as_ref());
24192429
ctx.serial_queue =
24202430
Queue::new_with_target(queue_label.as_str(), get_serial_queue_singleton());
2431+
let shared_vp_queue = Queue::new_with_target(
2432+
format!("{}.shared_vpio", queue_label).as_str(),
2433+
&ctx.serial_queue,
2434+
);
2435+
ctx.shared_voice_processing_unit = SharedVoiceProcessingUnit::new(shared_vp_queue);
24212436
Ok(unsafe { Context::from_ptr(Box::into_raw(ctx) as *mut _) })
24222437
}
24232438

@@ -3071,14 +3086,17 @@ impl<'ctx> CoreStreamData<'ctx> {
30713086
&self.input_device,
30723087
&self.output_device,
30733088
) {
3074-
cubeb_log!("({:p}) Using VoiceProcessingIO AudioUnit", self.stm_ptr);
3089+
cubeb_log!(
3090+
"({:p}) Took shared VoiceProcessingIO AudioUnit",
3091+
self.stm_ptr
3092+
);
30753093
self.input_unit = *au_handle.as_mut();
30763094
self.output_unit = *au_handle.as_mut();
30773095
self.voiceprocessing_unit_handle = Some(au_handle);
30783096
return Ok((self.input_device.clone(), self.output_device.clone()));
30793097
}
30803098
cubeb_log!(
3081-
"({:p}) Failed to create VoiceProcessingIO AudioUnit. Trying a regular one.",
3099+
"({:p}) Failed to take VoiceProcessingIO AudioUnit. Trying a regular one.",
30823100
self.stm_ptr
30833101
);
30843102
}

src/backend/tests/api.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1776,8 +1776,7 @@ fn test_shared_voice_processing_unit_after_priming() {
17761776
get_serial_queue_singleton(),
17771777
);
17781778
let mut shared = SharedVoiceProcessingUnit::new(queue.clone());
1779-
let queue = shared.queue.clone();
1780-
queue.run_async(|| shared.prime());
1779+
shared.prime();
17811780
assert!(queue.run_sync(|| shared.take()).unwrap().is_ok());
17821781
}
17831782

0 commit comments

Comments
 (0)