video: Add various VideoFormatInfo/VideoInfo/VideoFrame helper API

This commit is contained in:
Sebastian Dröge 2022-04-04 15:50:09 +03:00
parent 4d002786ec
commit eed648831d
4 changed files with 160 additions and 2 deletions

View file

@ -12,6 +12,7 @@ pub use gst_base;
macro_rules! assert_initialized_main_thread {
() => {
#[allow(unused_unsafe)]
if unsafe { gst::ffi::gst_is_initialized() } != glib::ffi::GTRUE {
panic!("GStreamer has not been initialized. Call `gst::init` first.");
}

View file

@ -12,6 +12,12 @@ use glib::translate::{from_glib, IntoGlib, ToGlibPtr};
pub struct VideoFormatInfo(&'static ffi::GstVideoFormatInfo);
impl VideoFormatInfo {
pub unsafe fn from_ptr(format_info: *const ffi::GstVideoFormatInfo) -> Self {
assert_initialized_main_thread!();
assert!(!format_info.is_null());
Self(&*format_info)
}
pub fn from_format(format: crate::VideoFormat) -> Self {
assert_initialized_main_thread!();

View file

@ -120,6 +120,16 @@ impl<T> VideoFrame<T> {
self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
}
pub fn is_bottom_field(&self) -> bool {
self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
&& !self.flags().contains(crate::VideoFrameFlags::TFF)
}
pub fn is_top_field(&self) -> bool {
self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
&& self.flags().contains(crate::VideoFrameFlags::TFF)
}
pub fn n_planes(&self) -> u32 {
self.info().n_planes()
}
@ -136,6 +146,43 @@ impl<T> VideoFrame<T> {
self.info().offset()
}
pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> {
let poffset = self.info().comp_poffset(component as u8) as usize;
Ok(&self.plane_data(self.format_info().plane()[component as usize])?[poffset..])
}
pub fn comp_depth(&self, component: u32) -> u32 {
self.info().comp_depth(component as u8)
}
pub fn comp_height(&self, component: u32) -> u32 {
self.info().comp_height(component as u8)
}
pub fn comp_width(&self, component: u32) -> u32 {
self.info().comp_width(component as u8)
}
pub fn comp_offset(&self, component: u32) -> usize {
self.info().comp_offset(component as u8)
}
pub fn comp_poffset(&self, component: u32) -> u32 {
self.info().comp_poffset(component as u8)
}
pub fn comp_pstride(&self, component: u32) -> i32 {
self.info().comp_pstride(component as u8)
}
pub fn comp_stride(&self, component: u32) -> i32 {
self.info().comp_stride(component as u8)
}
pub fn comp_plane(&self, component: u32) -> u32 {
self.info().comp_plane(component as u8)
}
pub fn buffer(&self) -> &gst::BufferRef {
unsafe { gst::BufferRef::from_ptr(self.frame.buffer) }
}
@ -364,6 +411,11 @@ impl VideoFrame<Writable> {
unsafe { gst::BufferRef::from_mut_ptr(self.frame.buffer) }
}
pub fn comp_data_mut(&mut self, component: u32) -> Result<&mut [u8], glib::BoolError> {
let poffset = self.info().comp_poffset(component as u8) as usize;
Ok(&mut self.plane_data_mut(self.format_info().plane()[component as usize])?[poffset..])
}
pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
if plane >= self.n_planes() {
return Err(glib::bool_error!(
@ -510,6 +562,16 @@ impl<T> VideoFrameRef<T> {
self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
}
pub fn is_bottom_field(&self) -> bool {
self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
&& !self.flags().contains(crate::VideoFrameFlags::TFF)
}
pub fn is_top_field(&self) -> bool {
self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
&& self.flags().contains(crate::VideoFrameFlags::TFF)
}
pub fn n_planes(&self) -> u32 {
self.info().n_planes()
}
@ -526,6 +588,43 @@ impl<T> VideoFrameRef<T> {
self.info().offset()
}
pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> {
let poffset = self.info().comp_poffset(component as u8) as usize;
Ok(&self.plane_data(self.format_info().plane()[component as usize])?[poffset..])
}
pub fn comp_depth(&self, component: u32) -> u32 {
self.info().comp_depth(component as u8)
}
pub fn comp_height(&self, component: u32) -> u32 {
self.info().comp_height(component as u8)
}
pub fn comp_width(&self, component: u32) -> u32 {
self.info().comp_width(component as u8)
}
pub fn comp_offset(&self, component: u32) -> usize {
self.info().comp_offset(component as u8)
}
pub fn comp_poffset(&self, component: u32) -> u32 {
self.info().comp_poffset(component as u8)
}
pub fn comp_pstride(&self, component: u32) -> i32 {
self.info().comp_pstride(component as u8)
}
pub fn comp_stride(&self, component: u32) -> i32 {
self.info().comp_stride(component as u8)
}
pub fn comp_plane(&self, component: u32) -> u32 {
self.info().comp_plane(component as u8)
}
pub fn plane_data(&self, plane: u32) -> Result<&[u8], glib::BoolError> {
if plane >= self.n_planes() {
return Err(glib::bool_error!(
@ -764,6 +863,11 @@ impl<'a> VideoFrameRef<&'a mut gst::BufferRef> {
self.buffer.as_mut().unwrap()
}
pub fn comp_data_mut(&mut self, component: u32) -> Result<&mut [u8], glib::BoolError> {
let poffset = self.info().comp_poffset(component as u8) as usize;
Ok(&mut self.plane_data_mut(self.format_info().plane()[component as usize])?[poffset..])
}
pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
if plane >= self.n_planes() {
return Err(glib::bool_error!(

View file

@ -630,11 +630,15 @@ impl VideoInfo {
return crate::VideoFormat::Unknown;
}
unsafe { from_glib((*self.0.finfo).format) }
self.format_info().format()
}
pub fn format_info(&self) -> crate::VideoFormatInfo {
crate::VideoFormatInfo::from_format(self.format())
unsafe { crate::VideoFormatInfo::from_ptr(self.0.finfo) }
}
pub fn name<'a>(&self) -> &'a str {
self.format_info().name()
}
pub fn width(&self) -> u32 {
@ -679,6 +683,39 @@ impl VideoInfo {
unsafe { VideoColorimetry(ptr::read(&self.0.colorimetry)) }
}
pub fn comp_depth(&self, component: u8) -> u32 {
self.format_info().depth()[component as usize]
}
pub fn comp_height(&self, component: u8) -> u32 {
self.format_info().scale_height(component, self.height())
}
pub fn comp_width(&self, component: u8) -> u32 {
self.format_info().scale_width(component, self.width())
}
pub fn comp_offset(&self, component: u8) -> usize {
self.offset()[self.format_info().plane()[component as usize] as usize]
+ self.format_info().poffset()[component as usize] as usize
}
pub fn comp_plane(&self, component: u8) -> u32 {
self.format_info().plane()[component as usize]
}
pub fn comp_poffset(&self, component: u8) -> u32 {
self.format_info().poffset()[component as usize]
}
pub fn comp_pstride(&self, component: u8) -> i32 {
self.format_info().pixel_stride()[component as usize]
}
pub fn comp_stride(&self, component: u8) -> i32 {
self.stride()[self.format_info().plane()[component as usize] as usize]
}
pub fn par(&self) -> gst::Fraction {
gst::Fraction::new(self.0.par_n, self.0.par_d)
}
@ -687,6 +724,16 @@ impl VideoInfo {
gst::Fraction::new(self.0.fps_n, self.0.fps_d)
}
#[cfg(any(feature = "v1_16", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
pub fn field_rate(&self) -> gst::Fraction {
if self.interlace_mode() == crate::VideoInterlaceMode::Alternate {
2 * self.fps()
} else {
self.fps()
}
}
pub fn offset(&self) -> &[usize] {
&self.0.offset[0..(self.format_info().n_planes() as usize)]
}