Skip to content

Commit b19c9d6

Browse files
committed
Handle zero-frame input callbacks and output buffer size mismatches
CoreAudio can call the input callback with 0 frames during device transitions. The output callback already handles this case (added for the same reason), but the input callback had an assert that crashed the process (~21 crash pings per 30 days on macOS). Add the same early-return pattern. Similarly, during device format changes there can be a transient mismatch between the output buffer size provided by CoreAudio and the format described by output_dev_desc. The mixer assert would crash if the buffer was too small (~19 crash pings per 30 days). Replace with a check that outputs silence and returns early, avoiding an out-of-bounds write in the mixer.
1 parent 6767a85 commit b19c9d6

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

src/backend/mod.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,12 +515,19 @@ extern "C" fn audiounit_input_callback(
515515
Reinit,
516516
}
517517

518-
assert!(input_frames > 0);
519518
assert_eq!(bus, AU_IN_BUS);
520519

521520
assert!(!user_ptr.is_null());
522521
let stm = unsafe { &mut *(user_ptr as *mut AudioUnitStream) };
523522

523+
if input_frames == 0 {
524+
cubeb_alog!(
525+
"({:p}) input callback empty.",
526+
stm as *const AudioUnitStream
527+
);
528+
return NO_ERR;
529+
}
530+
524531
if unsafe { *flags | kAudioTimeStampHostTimeValid } != 0 {
525532
let now = unsafe { mach_absolute_time() };
526533
let input_latency_frames = compute_input_latency(stm, unsafe { (*tstamp).mHostTime }, now);
@@ -980,10 +987,17 @@ extern "C" fn audiounit_output_callback(
980987

981988
// Mixing
982989
if let Some(mixer) = stm.core_stream_data.mixer.as_mut() {
983-
assert!(
984-
buffers[0].mDataByteSize
985-
>= stm.core_stream_data.output_dev_desc.mBytesPerFrame * output_frames
986-
);
990+
let needed = stm.core_stream_data.output_dev_desc.mBytesPerFrame * output_frames;
991+
if buffers[0].mDataByteSize < needed {
992+
cubeb_log!(
993+
"({:p}) output buffer too small for mixer: have {} bytes, need {} bytes",
994+
stm as *const AudioUnitStream,
995+
buffers[0].mDataByteSize,
996+
needed
997+
);
998+
audiounit_make_silent(&buffers[0]);
999+
return NO_ERR;
1000+
}
9871001
mixer.mix(
9881002
output_frames as usize,
9891003
buffers[0].mData,

0 commit comments

Comments
 (0)