Give most spawned threads names (#38302)

Release Notes:

- N/A
This commit is contained in:
Lukas Wirth
2025-09-17 10:11:51 +02:00
committed by GitHub
parent 64d362cbce
commit 531f9ee236
11 changed files with 331 additions and 277 deletions
@@ -188,12 +188,15 @@ impl AudioStack {
let voip_parts = audio::VoipParts::new(cx)?;
// Audio needs to run real-time and should never be paused. That is why we are using a
// normal std::thread and not a background task
thread::spawn(move || {
// microphone is non send on mac
let microphone = audio::Audio::open_microphone(voip_parts)?;
send_to_livekit(frame_tx, microphone);
Ok::<(), anyhow::Error>(())
});
thread::Builder::new()
.name("AudioCapture".to_string())
.spawn(move || {
// microphone is non send on mac
let microphone = audio::Audio::open_microphone(voip_parts)?;
send_to_livekit(frame_tx, microphone);
Ok::<(), anyhow::Error>(())
})
.unwrap();
Task::ready(Ok(()))
} else {
self.executor.spawn(async move {
@@ -229,57 +232,60 @@ impl AudioStack {
let mut resampler = audio_resampler::AudioResampler::default();
let mut buf = Vec::new();
thread::spawn(move || {
let output_stream = output_device.build_output_stream(
&output_config.config(),
{
move |mut data, _info| {
while data.len() > 0 {
if data.len() <= buf.len() {
let rest = buf.split_off(data.len());
data.copy_from_slice(&buf);
buf = rest;
return;
}
if buf.len() > 0 {
let (prefix, suffix) = data.split_at_mut(buf.len());
prefix.copy_from_slice(&buf);
data = suffix;
}
thread::Builder::new()
.name("AudioPlayback".to_owned())
.spawn(move || {
let output_stream = output_device.build_output_stream(
&output_config.config(),
{
move |mut data, _info| {
while data.len() > 0 {
if data.len() <= buf.len() {
let rest = buf.split_off(data.len());
data.copy_from_slice(&buf);
buf = rest;
return;
}
if buf.len() > 0 {
let (prefix, suffix) = data.split_at_mut(buf.len());
prefix.copy_from_slice(&buf);
data = suffix;
}
let mut mixer = mixer.lock();
let mixed = mixer.mix(output_config.channels() as usize);
let sampled = resampler.remix_and_resample(
mixed,
sample_rate / 100,
num_channels,
sample_rate,
output_config.channels() as u32,
output_config.sample_rate().0,
);
buf = sampled.to_vec();
apm.lock()
.process_reverse_stream(
&mut buf,
output_config.sample_rate().0 as i32,
output_config.channels() as i32,
)
.ok();
let mut mixer = mixer.lock();
let mixed = mixer.mix(output_config.channels() as usize);
let sampled = resampler.remix_and_resample(
mixed,
sample_rate / 100,
num_channels,
sample_rate,
output_config.channels() as u32,
output_config.sample_rate().0,
);
buf = sampled.to_vec();
apm.lock()
.process_reverse_stream(
&mut buf,
output_config.sample_rate().0 as i32,
output_config.channels() as i32,
)
.ok();
}
}
}
},
|error| log::error!("error playing audio track: {:?}", error),
Some(Duration::from_millis(100)),
);
},
|error| log::error!("error playing audio track: {:?}", error),
Some(Duration::from_millis(100)),
);
let Some(output_stream) = output_stream.log_err() else {
return;
};
let Some(output_stream) = output_stream.log_err() else {
return;
};
output_stream.play().log_err();
// Block forever to keep the output stream alive
end_on_drop_rx.recv().ok();
});
output_stream.play().log_err();
// Block forever to keep the output stream alive
end_on_drop_rx.recv().ok();
})
.unwrap();
device_change_listener.next().await;
drop(end_on_drop_tx)
@@ -300,77 +306,81 @@ impl AudioStack {
let frame_tx = frame_tx.clone();
let mut resampler = audio_resampler::AudioResampler::default();
thread::spawn(move || {
maybe!({
if let Some(name) = device.name().ok() {
log::info!("Using microphone: {}", name)
} else {
log::info!("Using microphone: <unknown>");
}
thread::Builder::new()
.name("AudioCapture".to_owned())
.spawn(move || {
maybe!({
if let Some(name) = device.name().ok() {
log::info!("Using microphone: {}", name)
} else {
log::info!("Using microphone: <unknown>");
}
let ten_ms_buffer_size =
(config.channels() as u32 * config.sample_rate().0 / 100) as usize;
let mut buf: Vec<i16> = Vec::with_capacity(ten_ms_buffer_size);
let ten_ms_buffer_size =
(config.channels() as u32 * config.sample_rate().0 / 100) as usize;
let mut buf: Vec<i16> = Vec::with_capacity(ten_ms_buffer_size);
let stream = device
.build_input_stream_raw(
&config.config(),
config.sample_format(),
move |data, _: &_| {
let data =
crate::get_sample_data(config.sample_format(), data).log_err();
let Some(data) = data else {
return;
};
let mut data = data.as_slice();
let stream = device
.build_input_stream_raw(
&config.config(),
config.sample_format(),
move |data, _: &_| {
let data = crate::get_sample_data(config.sample_format(), data)
.log_err();
let Some(data) = data else {
return;
};
let mut data = data.as_slice();
while data.len() > 0 {
let remainder = (buf.capacity() - buf.len()).min(data.len());
buf.extend_from_slice(&data[..remainder]);
data = &data[remainder..];
while data.len() > 0 {
let remainder =
(buf.capacity() - buf.len()).min(data.len());
buf.extend_from_slice(&data[..remainder]);
data = &data[remainder..];
if buf.capacity() == buf.len() {
let mut sampled = resampler
.remix_and_resample(
buf.as_slice(),
config.sample_rate().0 / 100,
config.channels() as u32,
config.sample_rate().0,
num_channels,
sample_rate,
)
.to_owned();
apm.lock()
.process_stream(
&mut sampled,
sample_rate as i32,
num_channels as i32,
)
.log_err();
buf.clear();
frame_tx
.unbounded_send(AudioFrame {
data: Cow::Owned(sampled),
sample_rate,
num_channels,
samples_per_channel: sample_rate / 100,
})
.ok();
if buf.capacity() == buf.len() {
let mut sampled = resampler
.remix_and_resample(
buf.as_slice(),
config.sample_rate().0 / 100,
config.channels() as u32,
config.sample_rate().0,
num_channels,
sample_rate,
)
.to_owned();
apm.lock()
.process_stream(
&mut sampled,
sample_rate as i32,
num_channels as i32,
)
.log_err();
buf.clear();
frame_tx
.unbounded_send(AudioFrame {
data: Cow::Owned(sampled),
sample_rate,
num_channels,
samples_per_channel: sample_rate / 100,
})
.ok();
}
}
}
},
|err| log::error!("error capturing audio track: {:?}", err),
Some(Duration::from_millis(100)),
)
.context("failed to build input stream")?;
},
|err| log::error!("error capturing audio track: {:?}", err),
Some(Duration::from_millis(100)),
)
.context("failed to build input stream")?;
stream.play()?;
// Keep the thread alive and holding onto the `stream`
end_on_drop_rx.recv().ok();
anyhow::Ok(Some(()))
stream.play()?;
// Keep the thread alive and holding onto the `stream`
end_on_drop_rx.recv().ok();
anyhow::Ok(Some(()))
})
.log_err();
})
.log_err();
});
.unwrap();
device_change_listener.next().await;
drop(end_on_drop_tx)