From 2a00236a1fb78dec988130c9bf38b375c760f104 Mon Sep 17 00:00:00 2001 From: Anders Hellerup Madsen Date: Wed, 27 Sep 2023 15:59:03 +0200 Subject: [PATCH] video: extract common videoframe methods to trait In preparation to make a more specialized VideoFrameGL this extracts common helper functions valid for all VideoFrames into a trait that can be implemented without too much code duplication. Note that this is a breaking change, now VideoFrame and VideoFrameRef cannot really be used without include the gst_video prelude. Part-of: --- examples/src/bin/appsrc.rs | 1 + examples/src/bin/fd_allocator.rs | 2 +- examples/src/bin/thumbnail.rs | 1 + gstreamer-video/src/lib.rs | 3 +- gstreamer-video/src/video_frame.rs | 379 +++++++++++------------------ 5 files changed, 141 insertions(+), 245 deletions(-) diff --git a/examples/src/bin/appsrc.rs b/examples/src/bin/appsrc.rs index 4901d6846..12daf5990 100644 --- a/examples/src/bin/appsrc.rs +++ b/examples/src/bin/appsrc.rs @@ -13,6 +13,7 @@ use anyhow::Error; use derive_more::{Display, Error}; use gst::prelude::*; +use gst_video::prelude::*; #[path = "../examples-common.rs"] mod examples_common; diff --git a/examples/src/bin/fd_allocator.rs b/examples/src/bin/fd_allocator.rs index 1b1ef6055..1c2573f3c 100644 --- a/examples/src/bin/fd_allocator.rs +++ b/examples/src/bin/fd_allocator.rs @@ -364,7 +364,7 @@ mod video_filter { use glib::once_cell::sync::Lazy; use gst::{subclass::prelude::*, PadDirection, PadPresence, PadTemplate}; use gst_app::gst_base::subclass::BaseTransformMode; - use gst_video::{subclass::prelude::*, VideoFrameRef}; + use gst_video::{prelude::*, subclass::prelude::*, VideoFrameRef}; use memmap2::MmapMut; static CAT: Lazy = Lazy::new(|| { diff --git a/examples/src/bin/thumbnail.rs b/examples/src/bin/thumbnail.rs index 29f204e38..3d833f506 100644 --- a/examples/src/bin/thumbnail.rs +++ b/examples/src/bin/thumbnail.rs @@ -10,6 +10,7 @@ use anyhow::Error; use derive_more::{Display, Error}; use gst::{element_error, prelude::*}; +use gst_video::prelude::*; #[path = "../examples-common.rs"] mod examples_common; diff --git a/gstreamer-video/src/lib.rs b/gstreamer-video/src/lib.rs index df61e5ffa..8b9134e9e 100644 --- a/gstreamer-video/src/lib.rs +++ b/gstreamer-video/src/lib.rs @@ -60,7 +60,7 @@ mod video_info_dma_drm; #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))] pub use crate::video_info_dma_drm::*; pub mod video_frame; -pub use crate::video_frame::{VideoFrame, VideoFrameRef}; +pub use crate::video_frame::{VideoFrame, VideoFrameExt, VideoFrameRef}; mod video_overlay; pub use crate::video_overlay::is_video_overlay_prepare_window_handle_message; @@ -151,6 +151,7 @@ pub mod prelude { #[cfg(feature = "v1_16")] #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))] pub use crate::video_aggregator_pad::VideoAggregatorPadExtManual; + pub use crate::VideoFrameExt; pub use crate::{ auto::traits::*, video_buffer_pool::VideoBufferPoolConfig, video_decoder::VideoDecoderExtManual, video_encoder::VideoEncoderExtManual, diff --git a/gstreamer-video/src/video_frame.rs b/gstreamer-video/src/video_frame.rs index 686d9dc87..56407cafa 100644 --- a/gstreamer-video/src/video_frame.rs +++ b/gstreamer-video/src/video_frame.rs @@ -27,22 +27,147 @@ impl fmt::Debug for VideoFrame { } } -impl VideoFrame { +pub trait VideoFrameExt { + fn id(&self) -> i32; + fn info(&self) -> &crate::VideoInfo; + fn flags(&self) -> crate::VideoFrameFlags; + #[inline] - pub fn info(&self) -> &crate::VideoInfo { + fn format(&self) -> crate::VideoFormat { + self.info().format() + } + + #[inline] + fn format_info(&self) -> crate::VideoFormatInfo { + self.info().format_info() + } + + #[inline] + fn width(&self) -> u32 { + self.info().width() + } + + #[inline] + fn height(&self) -> u32 { + self.info().height() + } + + #[inline] + fn size(&self) -> usize { + self.info().size() + } + + #[inline] + fn is_interlaced(&self) -> bool { + self.flags().contains(crate::VideoFrameFlags::INTERLACED) + } + + #[inline] + fn is_tff(&self) -> bool { + self.flags().contains(crate::VideoFrameFlags::TFF) + } + + #[inline] + fn is_rff(&self) -> bool { + self.flags().contains(crate::VideoFrameFlags::RFF) + } + + #[inline] + fn is_onefield(&self) -> bool { + self.flags().contains(crate::VideoFrameFlags::ONEFIELD) + } + + #[inline] + fn is_bottom_field(&self) -> bool { + self.flags().contains(crate::VideoFrameFlags::ONEFIELD) + && !self.flags().contains(crate::VideoFrameFlags::TFF) + } + + #[inline] + fn is_top_field(&self) -> bool { + self.flags().contains(crate::VideoFrameFlags::ONEFIELD) + && self.flags().contains(crate::VideoFrameFlags::TFF) + } + + #[inline] + fn n_planes(&self) -> u32 { + self.info().n_planes() + } + + #[inline] + fn n_components(&self) -> u32 { + self.info().n_components() + } + + #[inline] + fn plane_stride(&self) -> &[i32] { + self.info().stride() + } + + #[inline] + fn plane_offset(&self) -> &[usize] { + self.info().offset() + } + + #[inline] + fn comp_depth(&self, component: u32) -> u32 { + self.info().comp_depth(component as u8) + } + + #[inline] + fn comp_height(&self, component: u32) -> u32 { + self.info().comp_height(component as u8) + } + + #[inline] + fn comp_width(&self, component: u32) -> u32 { + self.info().comp_width(component as u8) + } + + #[inline] + fn comp_offset(&self, component: u32) -> usize { + self.info().comp_offset(component as u8) + } + + #[inline] + fn comp_poffset(&self, component: u32) -> u32 { + self.info().comp_poffset(component as u8) + } + + #[inline] + fn comp_pstride(&self, component: u32) -> i32 { + self.info().comp_pstride(component as u8) + } + + #[inline] + fn comp_stride(&self, component: u32) -> i32 { + self.info().comp_stride(component as u8) + } + + #[inline] + fn comp_plane(&self, component: u32) -> u32 { + self.info().comp_plane(component as u8) + } +} + +impl VideoFrameExt for VideoFrame { + #[inline] + fn info(&self) -> &crate::VideoInfo { unsafe { &*(&self.frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo) } } #[inline] - pub fn flags(&self) -> crate::VideoFrameFlags { + fn flags(&self) -> crate::VideoFrameFlags { unsafe { from_glib(self.frame.flags) } } #[inline] - pub fn id(&self) -> i32 { + fn id(&self) -> i32 { self.frame.id } +} +impl VideoFrame { #[inline] pub fn into_buffer(self) -> gst::Buffer { unsafe { @@ -87,83 +212,6 @@ impl VideoFrame { } } - #[inline] - pub fn format(&self) -> crate::VideoFormat { - self.info().format() - } - - #[inline] - pub fn format_info(&self) -> crate::VideoFormatInfo { - self.info().format_info() - } - - #[inline] - pub fn width(&self) -> u32 { - self.info().width() - } - - #[inline] - pub fn height(&self) -> u32 { - self.info().height() - } - - #[inline] - pub fn size(&self) -> usize { - self.info().size() - } - - #[inline] - pub fn is_interlaced(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::INTERLACED) - } - - #[inline] - pub fn is_tff(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::TFF) - } - - #[inline] - pub fn is_rff(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::RFF) - } - - #[inline] - pub fn is_onefield(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::ONEFIELD) - } - - #[inline] - pub fn is_bottom_field(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::ONEFIELD) - && !self.flags().contains(crate::VideoFrameFlags::TFF) - } - - #[inline] - pub fn is_top_field(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::ONEFIELD) - && self.flags().contains(crate::VideoFrameFlags::TFF) - } - - #[inline] - pub fn n_planes(&self) -> u32 { - self.info().n_planes() - } - - #[inline] - pub fn n_components(&self) -> u32 { - self.info().n_components() - } - - #[inline] - pub fn plane_stride(&self) -> &[i32] { - self.info().stride() - } - - #[inline] - pub fn plane_offset(&self) -> &[usize] { - self.info().offset() - } - #[inline] pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> { let poffset = self.info().comp_poffset(component as u8) as usize; @@ -171,47 +219,7 @@ impl VideoFrame { } #[inline] - pub fn comp_depth(&self, component: u32) -> u32 { - self.info().comp_depth(component as u8) - } - - #[inline] - pub fn comp_height(&self, component: u32) -> u32 { - self.info().comp_height(component as u8) - } - - #[inline] - pub fn comp_width(&self, component: u32) -> u32 { - self.info().comp_width(component as u8) - } - - #[inline] - pub fn comp_offset(&self, component: u32) -> usize { - self.info().comp_offset(component as u8) - } - - #[inline] - pub fn comp_poffset(&self, component: u32) -> u32 { - self.info().comp_poffset(component as u8) - } - - #[inline] - pub fn comp_pstride(&self, component: u32) -> i32 { - self.info().comp_pstride(component as u8) - } - - #[inline] - pub fn comp_stride(&self, component: u32) -> i32 { - self.info().comp_stride(component as u8) - } - - #[inline] - pub fn comp_plane(&self, component: u32) -> u32 { - self.info().comp_plane(component as u8) - } - - #[inline] - pub fn buffer(&self) -> &gst::BufferRef { + fn buffer(&self) -> &gst::BufferRef { unsafe { gst::BufferRef::from_ptr(self.frame.buffer) } } @@ -516,22 +524,24 @@ impl fmt::Debug for VideoFrameRef { } } -impl VideoFrameRef { +impl VideoFrameExt for VideoFrameRef { #[inline] - pub fn info(&self) -> &crate::VideoInfo { + fn info(&self) -> &crate::VideoInfo { unsafe { &*(&self.frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo) } } #[inline] - pub fn flags(&self) -> crate::VideoFrameFlags { + fn flags(&self) -> crate::VideoFrameFlags { unsafe { from_glib(self.frame.flags) } } #[inline] - pub fn id(&self) -> i32 { + fn id(&self) -> i32 { self.frame.id } +} +impl VideoFrameRef { #[doc(alias = "gst_video_frame_copy")] pub fn copy( &self, @@ -569,128 +579,11 @@ impl VideoFrameRef { } } - #[inline] - pub fn format(&self) -> crate::VideoFormat { - self.info().format() - } - - #[inline] - pub fn format_info(&self) -> crate::VideoFormatInfo { - self.info().format_info() - } - - #[inline] - pub fn width(&self) -> u32 { - self.info().width() - } - - #[inline] - pub fn height(&self) -> u32 { - self.info().height() - } - - #[inline] - pub fn size(&self) -> usize { - self.info().size() - } - - #[inline] - pub fn is_interlaced(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::INTERLACED) - } - - #[inline] - pub fn is_tff(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::TFF) - } - - #[inline] - pub fn is_rff(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::RFF) - } - - #[inline] - pub fn is_onefield(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::ONEFIELD) - } - - #[inline] - pub fn is_bottom_field(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::ONEFIELD) - && !self.flags().contains(crate::VideoFrameFlags::TFF) - } - - #[inline] - pub fn is_top_field(&self) -> bool { - self.flags().contains(crate::VideoFrameFlags::ONEFIELD) - && self.flags().contains(crate::VideoFrameFlags::TFF) - } - - #[inline] - pub fn n_planes(&self) -> u32 { - self.info().n_planes() - } - - #[inline] - pub fn n_components(&self) -> u32 { - self.info().n_components() - } - - #[inline] - pub fn plane_stride(&self) -> &[i32] { - self.info().stride() - } - - #[inline] - pub fn plane_offset(&self) -> &[usize] { - 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..]) } - #[inline] - pub fn comp_depth(&self, component: u32) -> u32 { - self.info().comp_depth(component as u8) - } - - #[inline] - pub fn comp_height(&self, component: u32) -> u32 { - self.info().comp_height(component as u8) - } - - #[inline] - pub fn comp_width(&self, component: u32) -> u32 { - self.info().comp_width(component as u8) - } - - #[inline] - pub fn comp_offset(&self, component: u32) -> usize { - self.info().comp_offset(component as u8) - } - - #[inline] - pub fn comp_poffset(&self, component: u32) -> u32 { - self.info().comp_poffset(component as u8) - } - - #[inline] - pub fn comp_pstride(&self, component: u32) -> i32 { - self.info().comp_pstride(component as u8) - } - - #[inline] - pub fn comp_stride(&self, component: u32) -> i32 { - self.info().comp_stride(component as u8) - } - - #[inline] - 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!(