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: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1312>
This commit is contained in:
Anders Hellerup Madsen 2023-09-27 15:59:03 +02:00
parent 8e3994f641
commit 2a00236a1f
5 changed files with 141 additions and 245 deletions

View file

@ -13,6 +13,7 @@
use anyhow::Error; use anyhow::Error;
use derive_more::{Display, Error}; use derive_more::{Display, Error};
use gst::prelude::*; use gst::prelude::*;
use gst_video::prelude::*;
#[path = "../examples-common.rs"] #[path = "../examples-common.rs"]
mod examples_common; mod examples_common;

View file

@ -364,7 +364,7 @@ mod video_filter {
use glib::once_cell::sync::Lazy; use glib::once_cell::sync::Lazy;
use gst::{subclass::prelude::*, PadDirection, PadPresence, PadTemplate}; use gst::{subclass::prelude::*, PadDirection, PadPresence, PadTemplate};
use gst_app::gst_base::subclass::BaseTransformMode; use gst_app::gst_base::subclass::BaseTransformMode;
use gst_video::{subclass::prelude::*, VideoFrameRef}; use gst_video::{prelude::*, subclass::prelude::*, VideoFrameRef};
use memmap2::MmapMut; use memmap2::MmapMut;
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| { static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {

View file

@ -10,6 +10,7 @@
use anyhow::Error; use anyhow::Error;
use derive_more::{Display, Error}; use derive_more::{Display, Error};
use gst::{element_error, prelude::*}; use gst::{element_error, prelude::*};
use gst_video::prelude::*;
#[path = "../examples-common.rs"] #[path = "../examples-common.rs"]
mod examples_common; mod examples_common;

View file

@ -60,7 +60,7 @@ mod video_info_dma_drm;
#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))] #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
pub use crate::video_info_dma_drm::*; pub use crate::video_info_dma_drm::*;
pub mod video_frame; pub mod video_frame;
pub use crate::video_frame::{VideoFrame, VideoFrameRef}; pub use crate::video_frame::{VideoFrame, VideoFrameExt, VideoFrameRef};
mod video_overlay; mod video_overlay;
pub use crate::video_overlay::is_video_overlay_prepare_window_handle_message; pub use crate::video_overlay::is_video_overlay_prepare_window_handle_message;
@ -151,6 +151,7 @@ pub mod prelude {
#[cfg(feature = "v1_16")] #[cfg(feature = "v1_16")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))] #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
pub use crate::video_aggregator_pad::VideoAggregatorPadExtManual; pub use crate::video_aggregator_pad::VideoAggregatorPadExtManual;
pub use crate::VideoFrameExt;
pub use crate::{ pub use crate::{
auto::traits::*, video_buffer_pool::VideoBufferPoolConfig, auto::traits::*, video_buffer_pool::VideoBufferPoolConfig,
video_decoder::VideoDecoderExtManual, video_encoder::VideoEncoderExtManual, video_decoder::VideoDecoderExtManual, video_encoder::VideoEncoderExtManual,

View file

@ -27,22 +27,147 @@ impl<T> fmt::Debug for VideoFrame<T> {
} }
} }
impl<T> VideoFrame<T> { pub trait VideoFrameExt {
fn id(&self) -> i32;
fn info(&self) -> &crate::VideoInfo;
fn flags(&self) -> crate::VideoFrameFlags;
#[inline] #[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<T> VideoFrameExt for VideoFrame<T> {
#[inline]
fn info(&self) -> &crate::VideoInfo {
unsafe { &*(&self.frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo) } unsafe { &*(&self.frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo) }
} }
#[inline] #[inline]
pub fn flags(&self) -> crate::VideoFrameFlags { fn flags(&self) -> crate::VideoFrameFlags {
unsafe { from_glib(self.frame.flags) } unsafe { from_glib(self.frame.flags) }
} }
#[inline] #[inline]
pub fn id(&self) -> i32 { fn id(&self) -> i32 {
self.frame.id self.frame.id
} }
}
impl<T> VideoFrame<T> {
#[inline] #[inline]
pub fn into_buffer(self) -> gst::Buffer { pub fn into_buffer(self) -> gst::Buffer {
unsafe { unsafe {
@ -87,83 +212,6 @@ impl<T> VideoFrame<T> {
} }
} }
#[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] #[inline]
pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> { pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> {
let poffset = self.info().comp_poffset(component as u8) as usize; let poffset = self.info().comp_poffset(component as u8) as usize;
@ -171,47 +219,7 @@ impl<T> VideoFrame<T> {
} }
#[inline] #[inline]
pub fn comp_depth(&self, component: u32) -> u32 { fn buffer(&self) -> &gst::BufferRef {
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 {
unsafe { gst::BufferRef::from_ptr(self.frame.buffer) } unsafe { gst::BufferRef::from_ptr(self.frame.buffer) }
} }
@ -516,22 +524,24 @@ impl<T> fmt::Debug for VideoFrameRef<T> {
} }
} }
impl<T> VideoFrameRef<T> { impl<T> VideoFrameExt for VideoFrameRef<T> {
#[inline] #[inline]
pub fn info(&self) -> &crate::VideoInfo { fn info(&self) -> &crate::VideoInfo {
unsafe { &*(&self.frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo) } unsafe { &*(&self.frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo) }
} }
#[inline] #[inline]
pub fn flags(&self) -> crate::VideoFrameFlags { fn flags(&self) -> crate::VideoFrameFlags {
unsafe { from_glib(self.frame.flags) } unsafe { from_glib(self.frame.flags) }
} }
#[inline] #[inline]
pub fn id(&self) -> i32 { fn id(&self) -> i32 {
self.frame.id self.frame.id
} }
}
impl<T> VideoFrameRef<T> {
#[doc(alias = "gst_video_frame_copy")] #[doc(alias = "gst_video_frame_copy")]
pub fn copy( pub fn copy(
&self, &self,
@ -569,128 +579,11 @@ impl<T> VideoFrameRef<T> {
} }
} }
#[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> { pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> {
let poffset = self.info().comp_poffset(component as u8) as usize; let poffset = self.info().comp_poffset(component as u8) as usize;
Ok(&self.plane_data(self.format_info().plane()[component as usize])?[poffset..]) 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> { pub fn plane_data(&self, plane: u32) -> Result<&[u8], glib::BoolError> {
if plane >= self.n_planes() { if plane >= self.n_planes() {
return Err(glib::bool_error!( return Err(glib::bool_error!(