diff --git a/gstreamer-video/src/video_meta.rs b/gstreamer-video/src/video_meta.rs index e90959726..f0258eaba 100644 --- a/gstreamer-video/src/video_meta.rs +++ b/gstreamer-video/src/video_meta.rs @@ -1201,20 +1201,32 @@ pub mod tags { gst::impl_meta_tag!(Colorspace, crate::ffi::GST_META_TAG_VIDEO_COLORSPACE_STR); } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct VideoMetaTransformScale<'a> { - in_info: &'a crate::VideoInfo, - out_info: &'a crate::VideoInfo, -} +#[repr(transparent)] +#[doc(alias = "GstVideoMetaTransform")] +pub struct VideoMetaTransformScale(ffi::GstVideoMetaTransform); -impl<'a> VideoMetaTransformScale<'a> { - pub fn new(in_info: &'a crate::VideoInfo, out_info: &'a crate::VideoInfo) -> Self { +unsafe impl Sync for VideoMetaTransformScale {} +unsafe impl Send for VideoMetaTransformScale {} + +impl VideoMetaTransformScale { + pub fn new(in_info: &crate::VideoInfo, out_info: &crate::VideoInfo) -> Self { skip_assert_initialized!(); - VideoMetaTransformScale { in_info, out_info } + Self(ffi::GstVideoMetaTransform { + in_info: mut_override(in_info.to_glib_none().0), + out_info: mut_override(out_info.to_glib_none().0), + }) + } + + pub fn in_info(&self) -> &crate::VideoInfo { + unsafe { &*(self.0.in_info as *const crate::VideoInfo) } + } + + pub fn out_info(&self) -> &crate::VideoInfo { + unsafe { &*(self.0.out_info as *const crate::VideoInfo) } } } -unsafe impl<'a> gst::meta::MetaTransform<'a> for VideoMetaTransformScale<'a> { +unsafe impl gst::meta::MetaTransform for VideoMetaTransformScale { type GLibType = ffi::GstVideoMetaTransform; #[doc(alias = "gst_video_meta_transform_scale_get_quark")] @@ -1222,14 +1234,8 @@ unsafe impl<'a> gst::meta::MetaTransform<'a> for VideoMetaTransformScale<'a> { unsafe { from_glib(ffi::gst_video_meta_transform_scale_get_quark()) } } - fn to_raw( - &self, - _meta: &gst::MetaRef, - ) -> Result { - Ok(ffi::GstVideoMetaTransform { - in_info: mut_override(self.in_info.to_glib_none().0), - out_info: mut_override(self.out_info.to_glib_none().0), - }) + fn as_ptr(&self) -> *const ffi::GstVideoMetaTransform { + &self.0 } } diff --git a/gstreamer/src/meta.rs b/gstreamer/src/meta.rs index 6a3857594..6459c7d38 100644 --- a/gstreamer/src/meta.rs +++ b/gstreamer/src/meta.rs @@ -235,7 +235,7 @@ impl<'a, T> MetaRef<'a, T> { pub fn transform(&self, buffer: &mut BufferRef, data: &'a MT) -> Result<(), glib::BoolError> where T: MetaAPI, - MT: MetaTransform<'a>, + MT: MetaTransform, { unsafe { let info = *(*self.upcast_ref().as_ptr()).info; @@ -245,15 +245,13 @@ impl<'a, T> MetaRef<'a, T> { )); }; - let data = data.to_raw(self)?; - glib::result_from_gboolean!( transform_func( buffer.as_mut_ptr(), mut_override(self.upcast_ref().as_ptr()), mut_override(self.buffer.as_ptr()), MT::quark().into_glib(), - mut_override(&data) as *mut _, + mut_override(data.as_ptr() as *mut _), ), "Failed to transform meta" ) @@ -493,7 +491,7 @@ impl<'a, T, U> MetaRefMut<'a, T, U> { ) -> Result<(), glib::BoolError> where T: MetaAPI, - MT: MetaTransform<'a>, + MT: MetaTransform, { self.as_meta_ref().transform(buffer, data) } @@ -1103,46 +1101,71 @@ pub mod tags { ); } -pub unsafe trait MetaTransform<'a> { +pub unsafe trait MetaTransform { type GLibType; fn quark() -> glib::Quark; - fn to_raw(&self, meta: &MetaRef) -> Result; + fn as_ptr(&self) -> *const Self::GLibType; } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct MetaTransformCopy { - range: (Bound, Bound), - region: bool, -} +#[repr(transparent)] +#[doc(alias = "GstMetaTransformCopy")] +pub struct MetaTransformCopy(ffi::GstMetaTransformCopy); impl MetaTransformCopy { - pub fn new(region: bool, range: impl RangeBounds) -> Self { + pub fn new(range: impl RangeBounds) -> Self { skip_assert_initialized!(); - MetaTransformCopy { - range: (range.start_bound().cloned(), range.end_bound().cloned()), - region, + + let region = !(matches!(range.start_bound(), Bound::Unbounded | Bound::Included(0)) + && range.end_bound() == Bound::Unbounded); + + let (offset, size) = if region { + ( + match range.start_bound() { + Bound::Included(idx) => *idx, + Bound::Excluded(idx) => *idx + 1, + Bound::Unbounded => 0, + }, + match range.end_bound() { + Bound::Included(idx) => *idx + 1, + Bound::Excluded(idx) => *idx, + Bound::Unbounded => usize::MAX, + }, + ) + } else { + (0, usize::MAX) + }; + + Self(ffi::GstMetaTransformCopy { + region: region.into_glib(), + offset, + size, + }) + } + + pub fn range(&self) -> Option<(Bound, Bound)> { + if self.0.region == glib::ffi::GFALSE { + None + } else { + let end = if self.0.size == usize::MAX { + Bound::Unbounded + } else { + Bound::Excluded(self.0.size) + }; + + Some((Bound::Included(self.0.offset), end)) } } } -unsafe impl MetaTransform<'_> for MetaTransformCopy { +unsafe impl MetaTransform for MetaTransformCopy { type GLibType = ffi::GstMetaTransformCopy; fn quark() -> glib::Quark { static QUARK: std::sync::OnceLock = std::sync::OnceLock::new(); *QUARK.get_or_init(|| glib::Quark::from_static_str(glib::gstr!("gst-copy"))) } - fn to_raw( - &self, - meta: &MetaRef, - ) -> Result { - let (offset, size) = meta.buffer.byte_range_into_offset_len(self.range)?; - - Ok(ffi::GstMetaTransformCopy { - region: self.region.into_glib(), - offset, - size, - }) + fn as_ptr(&self) -> *const ffi::GstMetaTransformCopy { + &self.0 } } @@ -1304,7 +1327,7 @@ mod tests { { let meta = buffer.meta::().unwrap(); let buffer_dest = buffer_dest.get_mut().unwrap(); - meta.transform(buffer_dest, &MetaTransformCopy::new(false, ..)) + meta.transform(buffer_dest, &MetaTransformCopy::new(..)) .unwrap(); }