Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash when using formats with bits per pixel size not divisible by 8 #61

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,26 @@ pub fn spawn_stdout_thread(
let mut buffers = stdout_output_video_streams
.map(|video_stream| {
// Since we filtered for video_streams above, we can unwrap unconditionally.
let video_data = video_stream.video_data().unwrap();
let bytes_per_frame = get_bytes_per_frame(video_data);
let buf_size = match video_stream.format.as_str() {
"rawvideo" => bytes_per_frame.expect("Should use a known pix_fmt") as usize,
"rawvideo" => {
let Some(video_data) = video_stream.video_data() else {
tx.send(FfmpegEvent::Error(
"Video stream doesn't have any video data".to_owned(),
))
.ok();
return Vec::new();
};

let Some(bytes_per_frame) = get_bytes_per_frame(video_data) else {
tx.send(FfmpegEvent::Error(
format!("Can't bytes per fraame for video data {video_data:?}").to_owned(),
))
.ok();
return Vec::new();
};

bytes_per_frame as usize
}

// Arbitrary default buffer size for receiving indeterminate chunks
// of any encoder or container output, when frame boundaries are unknown
Expand All @@ -234,7 +250,8 @@ pub fn spawn_stdout_thread(
})
.collect::<Vec<Vec<u8>>>();

// No buffers probably indicates that output is being sent to file
// No buffers probably indicates that output is being sent to file or
// that an error occured.
if buffers.is_empty() {
return;
}
Expand Down
7 changes: 5 additions & 2 deletions src/pix_fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,11 @@ pub fn get_bytes_per_frame(video_data: &VideoStream) -> Option<u32> {
let bits_per_pixel = get_bits_per_pixel(&video_data.pix_fmt)?;
// Enforce byte-alignment, since we don't currently have buffer reads in
// sub-byte increments.
match bits_per_pixel % 8 {
0 => Some(video_data.width * video_data.height * bits_per_pixel / 8),
// Use the full frame buffer size for this, since formats like `yuvj420p` typically restrict a frame's size
// such that the buffer size has full bytes.
let num_bits = video_data.width * video_data.height * bits_per_pixel;
match num_bits % 8 {
0 => Some(num_bits / 8),
_ => None,
}
}
Loading