// Take a look at the license at the top of the repository in the LICENSE file. use std::{fmt, mem}; use crate::ffi; use glib::translate::*; gst::mini_object_wrapper!( VideoOverlayRectangle, VideoOverlayRectangleRef, ffi::GstVideoOverlayRectangle, || ffi::gst_video_overlay_rectangle_get_type() ); impl fmt::Debug for VideoOverlayRectangle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { VideoOverlayRectangleRef::fmt(self, f) } } impl fmt::Debug for VideoOverlayRectangleRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("VideoOverlayRectangle") .field("flags", &self.flags()) .field("global_alpha", &self.global_alpha()) .field("render_rectangle", &self.render_rectangle()) .finish() } } impl VideoOverlayRectangle { #[doc(alias = "gst_video_overlay_rectangle_new_raw")] pub fn new_raw( buffer: &gst::Buffer, render_x: i32, render_y: i32, render_width: u32, render_height: u32, flags: crate::VideoOverlayFormatFlags, ) -> Self { skip_assert_initialized!(); assert!(buffer.meta::().is_some()); unsafe { from_glib_full(ffi::gst_video_overlay_rectangle_new_raw( buffer.to_glib_none().0, render_x, render_y, render_width, render_height, flags.into_glib(), )) } } } impl VideoOverlayRectangleRef { #[doc(alias = "get_flags")] #[doc(alias = "gst_video_overlay_rectangle_get_flags")] pub fn flags(&self) -> crate::VideoOverlayFormatFlags { unsafe { from_glib(ffi::gst_video_overlay_rectangle_get_flags( self.as_mut_ptr(), )) } } #[doc(alias = "get_global_alpha")] #[doc(alias = "gst_video_overlay_rectangle_get_global_alpha")] pub fn global_alpha(&self) -> f32 { unsafe { ffi::gst_video_overlay_rectangle_get_global_alpha(self.as_mut_ptr()) } } #[doc(alias = "gst_video_overlay_rectangle_set_global_alpha")] pub fn set_global_alpha(&mut self, alpha: f32) { unsafe { ffi::gst_video_overlay_rectangle_set_global_alpha(self.as_mut_ptr(), alpha) } } #[doc(alias = "get_seqnum")] #[doc(alias = "gst_video_overlay_rectangle_get_seqnum")] pub fn seqnum(&self) -> u32 { unsafe { ffi::gst_video_overlay_rectangle_get_seqnum(self.as_mut_ptr()) } } #[doc(alias = "get_render_rectangle")] #[doc(alias = "gst_video_overlay_rectangle_get_render_rectangle")] pub fn render_rectangle(&self) -> (i32, i32, u32, u32) { unsafe { let mut render_x = mem::MaybeUninit::uninit(); let mut render_y = mem::MaybeUninit::uninit(); let mut render_width = mem::MaybeUninit::uninit(); let mut render_height = mem::MaybeUninit::uninit(); ffi::gst_video_overlay_rectangle_get_render_rectangle( self.as_mut_ptr(), render_x.as_mut_ptr(), render_y.as_mut_ptr(), render_width.as_mut_ptr(), render_height.as_mut_ptr(), ); ( render_x.assume_init(), render_y.assume_init(), render_width.assume_init(), render_height.assume_init(), ) } } #[doc(alias = "gst_video_overlay_rectangle_set_render_rectangle")] pub fn set_render_rectangle( &mut self, render_x: i32, render_y: i32, render_width: u32, render_height: u32, ) { unsafe { ffi::gst_video_overlay_rectangle_set_render_rectangle( self.as_mut_ptr(), render_x, render_y, render_width, render_height, ) } } #[doc(alias = "get_pixels_unscaled_raw")] #[doc(alias = "gst_video_overlay_rectangle_get_pixels_unscaled_raw")] pub fn pixels_unscaled_raw(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer { unsafe { from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_unscaled_raw( self.as_mut_ptr(), flags.into_glib(), )) } } #[doc(alias = "get_pixels_unscaled_ayuv")] #[doc(alias = "gst_video_overlay_rectangle_get_pixels_unscaled_ayuv")] pub fn pixels_unscaled_ayuv(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer { unsafe { from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_unscaled_ayuv( self.as_mut_ptr(), flags.into_glib(), )) } } #[doc(alias = "get_pixels_unscaled_argb")] #[doc(alias = "gst_video_overlay_rectangle_get_pixels_unscaled_argb")] pub fn pixels_unscaled_argb(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer { unsafe { from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_unscaled_argb( self.as_mut_ptr(), flags.into_glib(), )) } } #[doc(alias = "get_pixels_raw")] #[doc(alias = "gst_video_overlay_rectangle_get_pixels_raw")] pub fn pixels_raw(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer { unsafe { from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_raw( self.as_mut_ptr(), flags.into_glib(), )) } } #[doc(alias = "get_pixels_ayuv")] #[doc(alias = "gst_video_overlay_rectangle_get_pixels_ayuv")] pub fn pixels_ayuv(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer { unsafe { from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_ayuv( self.as_mut_ptr(), flags.into_glib(), )) } } #[doc(alias = "get_pixels_argb")] #[doc(alias = "gst_video_overlay_rectangle_get_pixels_argb")] pub fn pixels_argb(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer { unsafe { from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_argb( self.as_mut_ptr(), flags.into_glib(), )) } } } gst::mini_object_wrapper!( VideoOverlayComposition, VideoOverlayCompositionRef, ffi::GstVideoOverlayComposition, || ffi::gst_video_overlay_composition_get_type() ); impl fmt::Debug for VideoOverlayComposition { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { VideoOverlayCompositionRef::fmt(self, f) } } impl fmt::Debug for VideoOverlayCompositionRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("VideoOverlayComposition").finish() } } impl VideoOverlayComposition { #[doc(alias = "gst_video_overlay_composition_new")] pub fn new<'a>( rects: impl IntoIterator, ) -> Result { assert_initialized_main_thread!(); #[cfg(feature = "v1_20")] unsafe { use std::ptr; let composition = Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut())); rects.into_iter().for_each(|rect| { ffi::gst_video_overlay_composition_add_rectangle( composition.as_mut_ptr(), rect.as_mut_ptr(), ); }); Ok(composition) } #[cfg(not(feature = "v1_20"))] unsafe { let mut iter = rects.into_iter(); let first = match iter.next() { None => { return Err(glib::bool_error!( "Failed to create VideoOverlayComposition" )) } Some(first) => first, }; let composition = Self::from_glib_full(ffi::gst_video_overlay_composition_new(first.as_mut_ptr())); for rect in iter { ffi::gst_video_overlay_composition_add_rectangle( composition.as_mut_ptr(), rect.as_mut_ptr(), ); } Ok(composition) } } } #[cfg(feature = "v1_20")] impl Default for VideoOverlayComposition { fn default() -> Self { assert_initialized_main_thread!(); use std::ptr; unsafe { from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut())) } } } impl VideoOverlayCompositionRef { #[doc(alias = "gst_video_overlay_composition_n_rectangles")] pub fn n_rectangles(&self) -> u32 { unsafe { ffi::gst_video_overlay_composition_n_rectangles(self.as_mut_ptr()) } } #[doc(alias = "get_rectangle")] #[doc(alias = "gst_video_overlay_composition_get_rectangle")] pub fn rectangle(&self, idx: u32) -> Result { if idx >= self.n_rectangles() { return Err(glib::bool_error!("Invalid index")); } unsafe { match from_glib_none(ffi::gst_video_overlay_composition_get_rectangle( self.as_mut_ptr(), idx, )) { Some(r) => Ok(r), None => Err(glib::bool_error!("Failed to get rectangle")), } } } #[doc(alias = "gst_video_overlay_composition_add_rectangle")] pub fn add_rectangle(&mut self, rect: &VideoOverlayRectangleRef) { unsafe { ffi::gst_video_overlay_composition_add_rectangle(self.as_mut_ptr(), rect.as_mut_ptr()); } } #[doc(alias = "get_seqnum")] #[doc(alias = "gst_video_overlay_composition_get_seqnum")] pub fn seqnum(&self) -> u32 { unsafe { ffi::gst_video_overlay_composition_get_seqnum(self.as_mut_ptr()) } } #[doc(alias = "gst_video_overlay_composition_blend")] pub fn blend( &self, frame: &mut crate::VideoFrameRef<&mut gst::BufferRef>, ) -> Result<(), glib::BoolError> { unsafe { glib::result_from_gboolean!( ffi::gst_video_overlay_composition_blend(self.as_mut_ptr(), frame.as_mut_ptr()), "Failed to blend overlay composition", ) } } pub fn iter(&self) -> Iter { Iter { composition: self, idx: 0, len: self.n_rectangles() as usize, } } } impl<'a> IntoIterator for &'a VideoOverlayComposition { type IntoIter = Iter<'a>; type Item = VideoOverlayRectangle; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl From for VideoOverlayComposition { fn from(value: VideoOverlayRectangle) -> Self { skip_assert_initialized!(); unsafe { Self::from_glib_full(ffi::gst_video_overlay_composition_new( value.into_glib_ptr(), )) } } } impl<'a> From<&'a VideoOverlayRectangle> for VideoOverlayComposition { fn from(value: &'a VideoOverlayRectangle) -> Self { skip_assert_initialized!(); unsafe { Self::from_glib_full(ffi::gst_video_overlay_composition_new(value.as_mut_ptr())) } } } #[cfg(feature = "v1_20")] impl From<[VideoOverlayRectangle; N]> for VideoOverlayComposition { fn from(value: [VideoOverlayRectangle; N]) -> Self { assert_initialized_main_thread!(); unsafe { use std::ptr; let composition = Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut())); value.into_iter().for_each(|rect| { ffi::gst_video_overlay_composition_add_rectangle( composition.as_mut_ptr(), rect.into_glib_ptr(), ); }); composition } } } #[cfg(feature = "v1_20")] impl<'a, const N: usize> From<[&'a VideoOverlayRectangle; N]> for VideoOverlayComposition { fn from(value: [&'a VideoOverlayRectangle; N]) -> Self { assert_initialized_main_thread!(); unsafe { use std::ptr; let composition = Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut())); value.into_iter().for_each(|rect| { ffi::gst_video_overlay_composition_add_rectangle( composition.as_mut_ptr(), rect.as_mut_ptr(), ); }); composition } } } #[cfg(feature = "v1_20")] impl std::iter::FromIterator for VideoOverlayComposition { fn from_iter>(iter: T) -> Self { assert_initialized_main_thread!(); unsafe { use std::ptr; let composition = Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut())); iter.into_iter().for_each(|rect| { ffi::gst_video_overlay_composition_add_rectangle( composition.as_mut_ptr(), rect.into_glib_ptr(), ); }); composition } } } #[cfg(feature = "v1_20")] impl<'a> std::iter::FromIterator<&'a VideoOverlayRectangle> for VideoOverlayComposition { fn from_iter>(iter: T) -> Self { assert_initialized_main_thread!(); unsafe { use std::ptr; let composition = Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut())); iter.into_iter().for_each(|rect| { ffi::gst_video_overlay_composition_add_rectangle( composition.as_mut_ptr(), rect.as_mut_ptr(), ); }); composition } } } pub struct Iter<'a> { composition: &'a VideoOverlayCompositionRef, idx: usize, len: usize, } impl<'a> Iterator for Iter<'a> { type Item = VideoOverlayRectangle; fn next(&mut self) -> Option { if self.idx >= self.len { return None; } let rect = self.composition.rectangle(self.idx as u32).unwrap(); self.idx += 1; Some(rect) } fn size_hint(&self) -> (usize, Option) { let remaining = self.len - self.idx; (remaining, Some(remaining)) } fn count(self) -> usize { self.len - self.idx } fn nth(&mut self, n: usize) -> Option { let (end, overflow) = self.idx.overflowing_add(n); if end >= self.len || overflow { self.idx = self.len; None } else { self.idx = end + 1; Some(self.composition.rectangle(end as u32).unwrap()) } } fn last(self) -> Option { if self.idx == self.len { None } else { Some(self.composition.rectangle(self.len as u32 - 1).unwrap()) } } } impl<'a> DoubleEndedIterator for Iter<'a> { fn next_back(&mut self) -> Option { if self.idx == self.len { return None; } self.len -= 1; Some(self.composition.rectangle(self.len as u32).unwrap()) } fn nth_back(&mut self, n: usize) -> Option { let (end, overflow) = self.len.overflowing_sub(n); if end <= self.idx || overflow { self.idx = self.len; None } else { self.len = end - 1; Some(self.composition.rectangle(self.len as u32).unwrap()) } } } impl<'a> ExactSizeIterator for Iter<'a> {} impl<'a> std::iter::FusedIterator for Iter<'a> {}