video: Don't panic when passing an invalid video info to VideoMeta::add()

Instead return an error that can be handled by the caller.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/259
This commit is contained in:
Sebastian Dröge 2020-06-07 18:15:40 +03:00
parent 926ed2f53d
commit 30d51f0ca6
2 changed files with 51 additions and 12 deletions

View file

@ -169,7 +169,7 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
gst_video::VideoFormat::Bgra, gst_video::VideoFormat::Bgra,
frame_width as u32, frame_width as u32,
frame_height as u32, frame_height as u32,
); ).unwrap();
let buffer = buffer.into_mapped_buffer_writable().unwrap(); let buffer = buffer.into_mapped_buffer_writable().unwrap();
let buffer = { let buffer = {

View file

@ -29,11 +29,26 @@ impl VideoMeta {
format: ::VideoFormat, format: ::VideoFormat,
width: u32, width: u32,
height: u32, height: u32,
) -> gst::MetaRefMut<Self, gst::meta::Standalone> { ) -> Result<gst::MetaRefMut<Self, gst::meta::Standalone>, glib::BoolError> {
skip_assert_initialized!(); skip_assert_initialized!();
let info = ::VideoInfo::new(format, width, height).build().unwrap(); if format == ::VideoFormat::Unknown || format == ::VideoFormat::Encoded {
assert!(buffer.get_size() >= info.size()); return Err(glib_bool_error!("Unsupported video format {}", format));
}
let info = ::VideoInfo::new(format, width, height).build()?;
if !info.is_valid() {
return Err(glib_bool_error!("Invalid video info"));
}
if buffer.get_size() < info.size() {
return Err(glib_bool_error!(
"Buffer smaller than required frame size ({} < {})",
buffer.get_size(),
info.size()
));
}
unsafe { unsafe {
let meta = gst_video_sys::gst_buffer_add_video_meta( let meta = gst_video_sys::gst_buffer_add_video_meta(
@ -44,7 +59,11 @@ impl VideoMeta {
height, height,
); );
Self::from_mut_ptr(buffer, meta) if meta.is_null() {
return Err(glib_bool_error!("Failed to add video meta"));
}
Ok(Self::from_mut_ptr(buffer, meta))
} }
} }
@ -56,16 +75,30 @@ impl VideoMeta {
height: u32, height: u32,
offset: &[usize], offset: &[usize],
stride: &[i32], stride: &[i32],
) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> { ) -> Result<gst::MetaRefMut<'a, Self, gst::meta::Standalone>, glib::BoolError> {
skip_assert_initialized!(); skip_assert_initialized!();
if format == ::VideoFormat::Unknown || format == ::VideoFormat::Encoded {
return Err(glib_bool_error!("Unsupported video format {}", format));
}
let n_planes = offset.len() as u32; let n_planes = offset.len() as u32;
let info = ::VideoInfo::new(format, width, height) let info = ::VideoInfo::new(format, width, height)
.offset(offset) .offset(offset)
.stride(stride) .stride(stride)
.build() .build()?;
.expect("Unable to build VideoInfo for given format, offsets and strides");
assert!(buffer.get_size() >= info.size()); if !info.is_valid() {
return Err(glib_bool_error!("Invalid video info"));
}
if buffer.get_size() < info.size() {
return Err(glib_bool_error!(
"Buffer smaller than required frame size ({} < {})",
buffer.get_size(),
info.size()
));
}
unsafe { unsafe {
let meta = gst_video_sys::gst_buffer_add_video_meta_full( let meta = gst_video_sys::gst_buffer_add_video_meta_full(
@ -79,7 +112,11 @@ impl VideoMeta {
stride.as_ptr() as *mut _, stride.as_ptr() as *mut _,
); );
Self::from_mut_ptr(buffer, meta) if meta.is_null() {
return Err(glib_bool_error!("Failed to add video meta"));
}
Ok(Self::from_mut_ptr(buffer, meta))
} }
} }
@ -657,7 +694,8 @@ mod tests {
::VideoFormat::Argb, ::VideoFormat::Argb,
320, 320,
240, 240,
); )
.unwrap();
assert_eq!(meta.get_id(), 0); assert_eq!(meta.get_id(), 0);
assert_eq!(meta.get_flags(), ::VideoFrameFlags::NONE); assert_eq!(meta.get_flags(), ::VideoFrameFlags::NONE);
assert_eq!(meta.get_format(), ::VideoFormat::Argb); assert_eq!(meta.get_format(), ::VideoFormat::Argb);
@ -695,7 +733,8 @@ mod tests {
240, 240,
&[0], &[0],
&[320 * 4], &[320 * 4],
); )
.unwrap();
assert_eq!(meta.get_id(), 0); assert_eq!(meta.get_id(), 0);
assert_eq!(meta.get_flags(), ::VideoFrameFlags::NONE); assert_eq!(meta.get_flags(), ::VideoFrameFlags::NONE);
assert_eq!(meta.get_format(), ::VideoFormat::Argb); assert_eq!(meta.get_format(), ::VideoFormat::Argb);