From 0feadec9fee5eca5d0d40865a49b28eb23d9ce97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 2 Jun 2020 11:18:42 +0300 Subject: [PATCH] video: Add VideoAffineTransformationMeta, CropMeta and RegionOfInterestMeta Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/218 --- gstreamer-video/src/lib.rs | 9 +- gstreamer-video/src/video_meta.rs | 253 +++++++++++++++++++++++++++++- 2 files changed, 259 insertions(+), 3 deletions(-) diff --git a/gstreamer-video/src/lib.rs b/gstreamer-video/src/lib.rs index b1aad5e0c..b4629fd01 100644 --- a/gstreamer-video/src/lib.rs +++ b/gstreamer-video/src/lib.rs @@ -70,8 +70,13 @@ mod video_rectangle; pub use video_rectangle::*; mod video_overlay_composition; pub use video_overlay_composition::*; -mod video_meta; -pub use video_meta::*; +pub mod video_meta; +#[cfg(any(feature = "v1_16", feature = "dox"))] +pub use video_meta::VideoCaptionMeta; +pub use video_meta::{ + VideoAffineTransformationMeta, VideoCropMeta, VideoMeta, VideoOverlayCompositionMeta, + VideoRegionOfInterestMeta, +}; #[cfg(any(feature = "v1_10", feature = "dox"))] mod video_time_code; #[cfg(any(feature = "v1_10", feature = "dox"))] diff --git a/gstreamer-video/src/video_meta.rs b/gstreamer-video/src/video_meta.rs index 70984af1f..3650722ba 100644 --- a/gstreamer-video/src/video_meta.rs +++ b/gstreamer-video/src/video_meta.rs @@ -7,9 +7,10 @@ // except according to those terms. use std::fmt; +use std::ptr; use glib; -use glib::translate::{from_glib, from_glib_none, ToGlib}; +use glib::translate::{from_glib, from_glib_none, FromGlib, ToGlib, ToGlibPtr}; use gst; use gst::prelude::*; use gst_sys; @@ -134,6 +135,256 @@ impl fmt::Debug for VideoMeta { } } +#[repr(C)] +pub struct VideoCropMeta(gst_video_sys::GstVideoCropMeta); + +unsafe impl Send for VideoCropMeta {} +unsafe impl Sync for VideoCropMeta {} + +impl VideoCropMeta { + pub fn add( + buffer: &mut gst::BufferRef, + rect: (u32, u32, u32, u32), + ) -> gst::MetaRefMut { + skip_assert_initialized!(); + unsafe { + let meta = gst_sys::gst_buffer_add_meta( + buffer.as_mut_ptr(), + gst_video_sys::gst_video_crop_meta_get_info(), + ptr::null_mut(), + ) as *mut gst_video_sys::GstVideoCropMeta; + + { + let meta = &mut *meta; + meta.x = rect.0; + meta.y = rect.1; + meta.width = rect.2; + meta.height = rect.3; + } + + Self::from_mut_ptr(buffer, meta) + } + } + + pub fn get_rect(&self) -> (u32, u32, u32, u32) { + (self.0.x, self.0.y, self.0.width, self.0.height) + } + + pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) { + self.0.x = rect.0; + self.0.y = rect.1; + self.0.width = rect.2; + self.0.height = rect.3; + } +} + +unsafe impl MetaAPI for VideoCropMeta { + type GstType = gst_video_sys::GstVideoCropMeta; + + fn get_meta_api() -> glib::Type { + unsafe { from_glib(gst_video_sys::gst_video_crop_meta_api_get_type()) } + } +} + +impl fmt::Debug for VideoCropMeta { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("VideoCropMeta") + .field("rect", &self.get_rect()) + .finish() + } +} + +#[repr(C)] +pub struct VideoRegionOfInterestMeta(gst_video_sys::GstVideoRegionOfInterestMeta); + +unsafe impl Send for VideoRegionOfInterestMeta {} +unsafe impl Sync for VideoRegionOfInterestMeta {} + +impl VideoRegionOfInterestMeta { + pub fn add<'a>( + buffer: &'a mut gst::BufferRef, + roi_type: &str, + rect: (u32, u32, u32, u32), + ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> { + skip_assert_initialized!(); + unsafe { + let meta = gst_video_sys::gst_buffer_add_video_region_of_interest_meta( + buffer.as_mut_ptr(), + roi_type.to_glib_none().0, + rect.0, + rect.1, + rect.2, + rect.3, + ); + + Self::from_mut_ptr(buffer, meta) + } + } + + pub fn get_rect(&self) -> (u32, u32, u32, u32) { + (self.0.x, self.0.y, self.0.w, self.0.h) + } + + pub fn get_id(&self) -> i32 { + self.0.id + } + + pub fn get_parent_id(&self) -> i32 { + self.0.parent_id + } + + pub fn get_roi_type<'a>(&self) -> &'a str { + glib::Quark::from_glib(self.0.roi_type).to_string() + } + + #[cfg(feature = "v1_14")] + pub fn get_params(&self) -> ParamsIter { + ParamsIter { + _meta: self, + list: self.0.params, + } + } + + #[cfg(feature = "v1_14")] + pub fn get_param<'b>(&self, name: &'b str) -> Option<&gst::StructureRef> { + self.get_params().find(|s| s.get_name() == name) + } + + pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) { + self.0.x = rect.0; + self.0.y = rect.1; + self.0.w = rect.2; + self.0.h = rect.3; + } + + pub fn set_id(&mut self, id: i32) { + self.0.id = id + } + + pub fn set_parent_id(&mut self, id: i32) { + self.0.parent_id = id + } + + #[cfg(feature = "v1_14")] + pub fn add_param(&mut self, s: gst::Structure) { + unsafe { + gst_video_sys::gst_video_region_of_interest_meta_add_param(&mut self.0, s.into_ptr()); + } + } +} + +#[cfg(feature = "v1_14")] +pub struct ParamsIter<'a> { + _meta: &'a VideoRegionOfInterestMeta, + list: *const glib_sys::GList, +} + +#[cfg(feature = "v1_14")] +impl<'a> Iterator for ParamsIter<'a> { + type Item = &'a gst::StructureRef; + + fn next(&mut self) -> Option<&'a gst::StructureRef> { + if self.list.is_null() { + return None; + } + + unsafe { + let data = (*self.list).data; + assert!(!data.is_null()); + self.list = (*self.list).next; + + let s = gst::StructureRef::from_glib_borrow(data as *const gst_sys::GstStructure); + + Some(s) + } + } +} + +unsafe impl MetaAPI for VideoRegionOfInterestMeta { + type GstType = gst_video_sys::GstVideoRegionOfInterestMeta; + + fn get_meta_api() -> glib::Type { + unsafe { from_glib(gst_video_sys::gst_video_region_of_interest_meta_api_get_type()) } + } +} + +impl fmt::Debug for VideoRegionOfInterestMeta { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut f = f.debug_struct("VideoRegionOfInterestMeta"); + + f.field("roi_type", &self.get_roi_type()) + .field("rect", &self.get_rect()) + .field("id", &self.get_id()) + .field("parent_id", &self.get_parent_id()); + + #[cfg(feature = "v1_14")] + { + f.field("params", &self.get_params().collect::>()); + } + + f.finish() + } +} + +#[repr(C)] +pub struct VideoAffineTransformationMeta(gst_video_sys::GstVideoAffineTransformationMeta); + +unsafe impl Send for VideoAffineTransformationMeta {} +unsafe impl Sync for VideoAffineTransformationMeta {} + +impl VideoAffineTransformationMeta { + pub fn add<'a>( + buffer: &'a mut gst::BufferRef, + matrix: Option<&[f32; 16]>, + ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> { + skip_assert_initialized!(); + unsafe { + let meta = gst_sys::gst_buffer_add_meta( + buffer.as_mut_ptr(), + gst_video_sys::gst_video_affine_transformation_meta_get_info(), + ptr::null_mut(), + ) as *mut gst_video_sys::GstVideoAffineTransformationMeta; + + if let Some(matrix) = matrix { + let meta = &mut *meta; + meta.matrix.copy_from_slice(matrix); + } + + Self::from_mut_ptr(buffer, meta) + } + } + + pub fn get_matrix(&self) -> &[f32; 16] { + &self.0.matrix + } + + pub fn set_matrix(&mut self, matrix: &[f32; 16]) { + self.0.matrix.copy_from_slice(matrix); + } + + pub fn apply_matrix(&mut self, matrix: &[f32; 16]) { + unsafe { + gst_video_sys::gst_video_affine_transformation_meta_apply_matrix(&mut self.0, matrix); + } + } +} + +unsafe impl MetaAPI for VideoAffineTransformationMeta { + type GstType = gst_video_sys::GstVideoAffineTransformationMeta; + + fn get_meta_api() -> glib::Type { + unsafe { from_glib(gst_video_sys::gst_video_affine_transformation_meta_api_get_type()) } + } +} + +impl fmt::Debug for VideoAffineTransformationMeta { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("VideoAffineTransformationMeta") + .field("matrix", &self.get_matrix()) + .finish() + } +} + #[repr(C)] pub struct VideoOverlayCompositionMeta(gst_video_sys::GstVideoOverlayCompositionMeta);