Skip to content

Commit 58009a5

Browse files
committed
fix: handle 0-channel edge case in wrap_frame_with_max_channels
Address code review feedback: - Replace unreachable!() with proper handling by treating 0 channels as mono - Fix division by zero by using effective_channels (clamped to minimum 1) - Also clamp max_channels to minimum 1 for safety - Add test for wrap_frame with 0 channels
1 parent 0742b89 commit 58009a5

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

crates/media-info/src/lib.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,13 @@ impl AudioInfo {
146146
packed_data: &[u8],
147147
max_channels: usize,
148148
) -> frame::Audio {
149-
let out_channels = self.channels.min(max_channels);
149+
// Handle 0 channels by treating as mono to avoid division by zero
150+
// and unreachable code paths. This can happen with misconfigured audio devices.
151+
let effective_channels = self.channels.max(1);
152+
let out_channels = effective_channels.min(max_channels.max(1));
150153

151154
let sample_size = self.sample_size();
152-
let packed_sample_size = sample_size * self.channels;
155+
let packed_sample_size = sample_size * effective_channels;
153156
let samples = packed_data.len() / packed_sample_size;
154157

155158
let mut frame = frame::Audio::new(
@@ -159,12 +162,10 @@ impl AudioInfo {
159162
);
160163
frame.set_rate(self.sample_rate);
161164

162-
if self.channels == 0 {
163-
unreachable!()
164-
} else if self.channels == 1 || (frame.is_packed() && self.channels <= out_channels) {
165+
if effective_channels == 1 || (frame.is_packed() && effective_channels <= out_channels) {
165166
// frame is allocated with parameters derived from packed_data, so this is safe
166167
frame.data_mut(0)[0..packed_data.len()].copy_from_slice(packed_data);
167-
} else if frame.is_packed() && self.channels > out_channels {
168+
} else if frame.is_packed() && effective_channels > out_channels {
168169
for (chunk_index, packed_chunk) in packed_data.chunks(packed_sample_size).enumerate() {
169170
let start = chunk_index * sample_size * out_channels;
170171

@@ -430,5 +431,16 @@ mod tests {
430431
assert_eq!(layout, ChannelLayout::_7POINT1);
431432
}
432433
}
434+
435+
#[test]
436+
fn wrap_frame_handles_zero_channels() {
437+
// Zero channels should be treated as mono to avoid division by zero
438+
let info = AudioInfo::new_raw(Sample::U8(Type::Packed), 2, 0);
439+
let input = &[1, 2, 3, 4];
440+
// This should not panic
441+
let frame = info.wrap_frame(input);
442+
// With effective_channels = 1, all input should be copied as mono
443+
assert_eq!(&frame.data(0)[0..input.len()], input);
444+
}
433445
}
434446
}

0 commit comments

Comments
 (0)