Skip to content

Commit

Permalink
Fix crash when using formats with bits per pixel size not divisible b…
Browse files Browse the repository at this point in the history
…y 8 (#61)

* don't fail get_bytes_per_frame for byte aligned frame buffers
* handle failing to retrieve bytes more gracefully
  • Loading branch information
Wumpf authored Nov 6, 2024
1 parent f80b3a2 commit b8e50ab
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 6 deletions.
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,
}
}

0 comments on commit b8e50ab

Please sign in to comment.