diff --git a/Gir_GstVideo.toml b/Gir_GstVideo.toml index 56a6a52c9..555950c7e 100644 --- a/Gir_GstVideo.toml +++ b/Gir_GstVideo.toml @@ -34,9 +34,11 @@ generate = [ "GstVideo.VideoMultiviewFramePacking", "GstVideo.VideoFilter", "GstVideo.VideoOverlayFormatFlags", + "GstVideo.VideoTimeCodeFlags", ] manual = [ + "GLib.DateTime", "GObject.Object", "Gst.Object", "Gst.Element", @@ -46,6 +48,8 @@ manual = [ "GstVideo.VideoColorimetry", "GstVideo.VideoColorRange", "GstVideo.VideoFrame", + "GstVideo.VideoTimeCode", + "GstVideo.VideoTimeCodeInterval", ] [[object]] diff --git a/gstreamer-video/src/auto/flags.rs b/gstreamer-video/src/auto/flags.rs index d5b131f02..31dd9f5ca 100644 --- a/gstreamer-video/src/auto/flags.rs +++ b/gstreamer-video/src/auto/flags.rs @@ -303,3 +303,31 @@ impl FromGlib for VideoOverlayFormatFlags { } } +#[cfg(any(feature = "v1_10", feature = "dox"))] +bitflags! { + pub struct VideoTimeCodeFlags: u32 { + const NONE = 0; + const DROP_FRAME = 1; + const INTERLACED = 2; + } +} + +#[cfg(any(feature = "v1_10", feature = "dox"))] +#[doc(hidden)] +impl ToGlib for VideoTimeCodeFlags { + type GlibType = ffi::GstVideoTimeCodeFlags; + + fn to_glib(&self) -> ffi::GstVideoTimeCodeFlags { + self.bits() + } +} + +#[cfg(any(feature = "v1_10", feature = "dox"))] +#[doc(hidden)] +impl FromGlib for VideoTimeCodeFlags { + fn from_glib(value: ffi::GstVideoTimeCodeFlags) -> VideoTimeCodeFlags { + skip_assert_initialized!(); + VideoTimeCodeFlags::from_bits_truncate(value) + } +} + diff --git a/gstreamer-video/src/auto/mod.rs b/gstreamer-video/src/auto/mod.rs index 9d5c3fbc9..8329cdeae 100644 --- a/gstreamer-video/src/auto/mod.rs +++ b/gstreamer-video/src/auto/mod.rs @@ -28,6 +28,8 @@ pub use self::flags::VideoFormatFlags; pub use self::flags::VideoFrameFlags; pub use self::flags::VideoMultiviewFlags; pub use self::flags::VideoOverlayFormatFlags; +#[cfg(any(feature = "v1_10", feature = "dox"))] +pub use self::flags::VideoTimeCodeFlags; #[doc(hidden)] pub mod traits { diff --git a/gstreamer-video/src/lib.rs b/gstreamer-video/src/lib.rs index 48368ac4e..01fed64c4 100644 --- a/gstreamer-video/src/lib.rs +++ b/gstreamer-video/src/lib.rs @@ -62,6 +62,14 @@ mod video_overlay_composition; pub use video_overlay_composition::*; mod video_meta; pub use video_meta::*; +#[cfg(any(feature = "v1_10", feature = "dox"))] +mod video_time_code; +#[cfg(any(feature = "v1_10", feature = "dox"))] +pub use video_time_code::{ValidVideoTimeCode, VideoTimeCode}; +#[cfg(any(feature = "v1_12", feature = "dox"))] +mod video_time_code_interval; +#[cfg(any(feature = "v1_12", feature = "dox"))] +pub use video_time_code_interval::VideoTimeCodeInterval; // Re-export all the traits in a prelude module, so that applications // can always "use gst::prelude::*" without getting conflicts diff --git a/gstreamer-video/src/video_time_code.rs b/gstreamer-video/src/video_time_code.rs new file mode 100644 index 000000000..f059e3973 --- /dev/null +++ b/gstreamer-video/src/video_time_code.rs @@ -0,0 +1,492 @@ +// Copyright (C) 2018 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi; +use glib; +use glib::prelude::*; +use glib::translate::*; +use glib::value; +use glib_ffi; +use gobject_ffi; +use gst; +use gst::prelude::*; +use std::cmp; +use std::fmt; +use std::mem; +use std::ptr; +use std::str; + +use VideoTimeCodeFlags; +#[cfg(any(feature = "v1_12", feature = "dox"))] +use VideoTimeCodeInterval; + +pub struct VideoTimeCode(ffi::GstVideoTimeCode); +pub struct ValidVideoTimeCode(ffi::GstVideoTimeCode); + +impl VideoTimeCode { + pub fn new_empty() -> VideoTimeCode { + assert_initialized_main_thread!(); + unsafe { + let mut v = mem::zeroed(); + ffi::gst_video_time_code_clear(&mut v); + VideoTimeCode(v) + } + } + + pub fn new( + fps: gst::Fraction, + latest_daily_jam: Option<&glib::DateTime>, + flags: VideoTimeCodeFlags, + hours: u32, + minutes: u32, + seconds: u32, + frames: u32, + field_count: u32, + ) -> Self { + assert_initialized_main_thread!(); + unsafe { + let mut v = mem::zeroed(); + ffi::gst_video_time_code_init( + &mut v, + *fps.numer() as u32, + *fps.denom() as u32, + latest_daily_jam.to_glib_none().0, + flags.to_glib(), + hours, + minutes, + seconds, + frames, + field_count, + ); + + VideoTimeCode(v) + } + } + + // #[cfg(any(feature = "v1_16", feature = "dox"))] + // pub fn new_from_date_time( + // fps: gst::Fraction, + // dt: &glib::DateTime, + // flags: VideoTimeCodeFlags, + // field_count: u32, + // ) -> Option { + // assert_initialized_main_thread!(); + // assert!(fps_d > 0); + // unsafe { + // let mut v = mem::zeroed(); + // let res = ffi::gst_video_time_code_init_from_date_time_full( + // &mut v, + // *fps.numer() as u32, + // *fps.denom() as u32, + // dt.to_glib_none().0, + // flags.to_glib(), + // field_count, + // ); + // + // if res == glib_ffi::GFALSE { + // None + // } else { + // Some(VideoTimeCode(v)) + // } + // } + // } + + #[cfg(any(feature = "v1_12", feature = "dox"))] + pub fn from_string(tc_str: &str) -> Option { + assert_initialized_main_thread!(); + unsafe { + from_glib_full(ffi::gst_video_time_code_new_from_string( + tc_str.to_glib_none().0, + )) + } + } + + pub fn is_valid(&self) -> bool { + unsafe { from_glib(ffi::gst_video_time_code_is_valid(self.to_glib_none().0)) } + } + + pub fn set_fps(&mut self, fps: gst::Fraction) { + self.0.config.fps_n = *fps.numer() as u32; + self.0.config.fps_d = *fps.denom() as u32; + } + + pub fn set_flags(&mut self, flags: VideoTimeCodeFlags) { + self.0.config.flags = flags.to_glib() + } + + pub fn set_hours(&mut self, hours: u32) { + self.0.hours = hours + } + + pub fn set_minutes(&mut self, minutes: u32) { + assert!(minutes < 60); + self.0.minutes = minutes + } + + pub fn set_seconds(&mut self, seconds: u32) { + assert!(seconds < 60); + self.0.seconds = seconds + } + + pub fn set_frames(&mut self, frames: u32) { + self.0.frames = frames + } + + pub fn set_field_count(&mut self, field_count: u32) { + assert!(field_count <= 2); + self.0.field_count = field_count + } + + pub fn try_into(self) -> Result { + if self.is_valid() { + Ok(ValidVideoTimeCode(self.0)) + } else { + Err(self) + } + } +} + +impl ValidVideoTimeCode { + pub fn new( + fps: gst::Fraction, + latest_daily_jam: Option<&glib::DateTime>, + flags: VideoTimeCodeFlags, + hours: u32, + minutes: u32, + seconds: u32, + frames: u32, + field_count: u32, + ) -> Option { + let tc = VideoTimeCode::new( + fps, + latest_daily_jam, + flags, + hours, + minutes, + seconds, + frames, + field_count, + ); + tc.try_into().ok() + } + + // #[cfg(any(feature = "v1_16", feature = "dox"))] + // pub fn new_from_date_time( + // fps: gst::Fraction, + // dt: &glib::DateTime, + // flags: VideoTimeCodeFlags, + // field_count: u32, + // ) -> Option { + // let tc = VideoTimeCode::new_from_date_time(fps, dt, flags, field_count); + // tc.and_then(|tc| tc.try_into().ok()) + // } + + pub fn add_frames(&mut self, frames: i64) { + unsafe { + ffi::gst_video_time_code_add_frames(self.to_glib_none_mut().0, frames); + } + } + + #[cfg(any(feature = "v1_12", feature = "dox"))] + pub fn add_interval(&self, tc_inter: &VideoTimeCodeInterval) -> Option { + unsafe { + from_glib_full(ffi::gst_video_time_code_add_interval( + self.to_glib_none().0, + tc_inter.to_glib_none().0, + )) + } + } + + fn compare(&self, tc2: &ValidVideoTimeCode) -> i32 { + unsafe { ffi::gst_video_time_code_compare(self.to_glib_none().0, tc2.to_glib_none().0) } + } + + pub fn frames_since_daily_jam(&self) -> u64 { + unsafe { ffi::gst_video_time_code_frames_since_daily_jam(self.to_glib_none().0) } + } + + pub fn increment_frame(&mut self) { + unsafe { + ffi::gst_video_time_code_increment_frame(self.to_glib_none_mut().0); + } + } + + pub fn nsec_since_daily_jam(&self) -> u64 { + unsafe { ffi::gst_video_time_code_nsec_since_daily_jam(self.to_glib_none().0) } + } + + pub fn to_date_time(&self) -> Option { + unsafe { from_glib_full(ffi::gst_video_time_code_to_date_time(self.to_glib_none().0)) } + } +} + +macro_rules! generic_impl { + ($name:ident) => { + impl $name { + pub fn to_string(&self) -> String { + unsafe { from_glib_full(ffi::gst_video_time_code_to_string(self.to_glib_none().0)) } + } + + pub fn get_hours(&self) -> u32 { + self.0.hours + } + + pub fn get_minutes(&self) -> u32 { + self.0.minutes + } + + pub fn get_seconds(&self) -> u32 { + self.0.seconds + } + + pub fn get_frames(&self) -> u32 { + self.0.frames + } + + pub fn get_field_count(&self) -> u32 { + self.0.field_count + } + + pub fn get_fps(&self) -> gst::Fraction { + (self.0.config.fps_n as i32, self.0.config.fps_d as i32).into() + } + + pub fn get_flags(&self) -> VideoTimeCodeFlags { + from_glib(self.0.config.flags) + } + + pub fn get_latest_daily_jam(&self) -> Option { + unsafe { from_glib_none(self.0.config.latest_daily_jam) } + } + + pub fn set_latest_daily_jam(&mut self, latest_daily_jam: Option<&glib::DateTime>) { + unsafe { + if !self.0.config.latest_daily_jam.is_null() { + glib_ffi::g_date_time_unref(self.0.config.latest_daily_jam); + } + + self.0.config.latest_daily_jam = latest_daily_jam.to_glib_full() + } + } + } + + impl Clone for $name { + fn clone(&self) -> Self { + unsafe { + let v = self.0; + if !v.config.latest_daily_jam.is_null() { + glib_ffi::g_date_time_ref(v.config.latest_daily_jam); + } + + $name(v) + } + } + } + + impl Drop for $name { + fn drop(&mut self) { + unsafe { + if !self.0.config.latest_daily_jam.is_null() { + glib_ffi::g_date_time_unref(self.0.config.latest_daily_jam); + } + } + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.debug_struct("$name") + .field("fps", &self.get_fps()) + .field("flags", &self.get_flags()) + .field("latest_daily_jam", &self.get_latest_daily_jam()) + .field("hours", &self.get_hours()) + .field("minutes", &self.get_minutes()) + .field("seconds", &self.get_seconds()) + .field("frames", &self.get_frames()) + .field("field_count", &self.get_field_count()) + .finish() + } + } + + impl fmt::Display for $name { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_string()) + } + } + + unsafe impl Send for $name {} + unsafe impl Sync for $name {} + + #[doc(hidden)] + impl GlibPtrDefault for $name { + type GlibType = *mut ffi::GstVideoTimeCode; + } + + #[doc(hidden)] + impl<'a> ToGlibPtr<'a, *const ffi::GstVideoTimeCode> for $name { + type Storage = &'a Self; + + #[inline] + fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstVideoTimeCode, Self> { + Stash(&self.0 as *const _, self) + } + + #[inline] + fn to_glib_full(&self) -> *const ffi::GstVideoTimeCode { + unsafe { ffi::gst_video_time_code_copy(&self.0 as *const _) } + } + } + + #[doc(hidden)] + impl<'a> ToGlibPtrMut<'a, *mut ffi::GstVideoTimeCode> for $name { + type Storage = &'a mut Self; + + #[inline] + fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GstVideoTimeCode, Self> { + let ptr = &mut self.0 as *mut _; + StashMut(ptr, self) + } + } + + #[doc(hidden)] + impl FromGlibPtrNone<*mut ffi::GstVideoTimeCode> for $name { + #[inline] + unsafe fn from_glib_none(ptr: *mut ffi::GstVideoTimeCode) -> Self { + assert!(!ptr.is_null()); + let v = ptr::read(ptr); + if !v.config.latest_daily_jam.is_null() { + glib_ffi::g_date_time_ref(v.config.latest_daily_jam); + } + + $name(v) + } + } + + #[doc(hidden)] + impl FromGlibPtrNone<*const ffi::GstVideoTimeCode> for $name { + #[inline] + unsafe fn from_glib_none(ptr: *const ffi::GstVideoTimeCode) -> Self { + assert!(!ptr.is_null()); + let v = ptr::read(ptr); + if !v.config.latest_daily_jam.is_null() { + glib_ffi::g_date_time_ref(v.config.latest_daily_jam); + } + + $name(v) + } + } + + #[doc(hidden)] + impl FromGlibPtrFull<*mut ffi::GstVideoTimeCode> for $name { + #[inline] + unsafe fn from_glib_full(ptr: *mut ffi::GstVideoTimeCode) -> Self { + assert!(!ptr.is_null()); + let v = ptr::read(ptr); + if !v.config.latest_daily_jam.is_null() { + glib_ffi::g_date_time_ref(v.config.latest_daily_jam); + } + ffi::gst_video_time_code_free(ptr); + + $name(v) + } + } + + #[doc(hidden)] + impl FromGlibPtrBorrow<*mut ffi::GstVideoTimeCode> for $name { + #[inline] + unsafe fn from_glib_borrow(ptr: *mut ffi::GstVideoTimeCode) -> Self { + assert!(!ptr.is_null()); + let v = ptr::read(ptr); + if !v.config.latest_daily_jam.is_null() { + glib_ffi::g_date_time_ref(v.config.latest_daily_jam); + } + + $name(v) + } + } + + impl StaticType for $name { + fn static_type() -> glib::Type { + unsafe { from_glib(ffi::gst_video_time_code_get_type()) } + } + } + + #[doc(hidden)] + impl<'a> value::FromValueOptional<'a> for $name { + unsafe fn from_value_optional(value: &glib::Value) -> Option { + Option::<$name>::from_glib_none(gobject_ffi::g_value_get_boxed( + value.to_glib_none().0, + ) as *mut ffi::GstVideoTimeCode) + } + } + + #[doc(hidden)] + impl value::SetValue for $name { + unsafe fn set_value(value: &mut glib::Value, this: &Self) { + gobject_ffi::g_value_set_boxed( + value.to_glib_none_mut().0, + ToGlibPtr::<*const ffi::GstVideoTimeCode>::to_glib_none(this).0 + as glib_ffi::gpointer, + ) + } + } + + #[doc(hidden)] + impl value::SetValueOptional for $name { + unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { + gobject_ffi::g_value_set_boxed( + value.to_glib_none_mut().0, + ToGlibPtr::<*const ffi::GstVideoTimeCode>::to_glib_none(&this).0 + as glib_ffi::gpointer, + ) + } + } + }; +} + +generic_impl!(VideoTimeCode); +generic_impl!(ValidVideoTimeCode); + +impl str::FromStr for VideoTimeCode { + type Err = (); + + fn from_str(s: &str) -> Result { + skip_assert_initialized!(); + Self::from_string(s).ok_or(()) + } +} + +impl PartialEq for ValidVideoTimeCode { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.compare(other) == 0 + } +} + +impl Eq for ValidVideoTimeCode {} + +impl PartialOrd for ValidVideoTimeCode { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.compare(other).partial_cmp(&0) + } +} + +impl Ord for ValidVideoTimeCode { + #[inline] + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.compare(other).cmp(&0) + } +} + +impl From for VideoTimeCode { + fn from(v: ValidVideoTimeCode) -> VideoTimeCode { + VideoTimeCode(v.0) + } +} diff --git a/gstreamer-video/src/video_time_code_interval.rs b/gstreamer-video/src/video_time_code_interval.rs new file mode 100644 index 000000000..a84b08927 --- /dev/null +++ b/gstreamer-video/src/video_time_code_interval.rs @@ -0,0 +1,239 @@ +// Copyright (C) 2018 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi; +use glib; +use glib::prelude::*; +use glib::translate::*; +use glib::value; +use glib_ffi; +use gobject_ffi; +use gst; +use std::cmp; +use std::fmt; +use std::mem; +use std::ptr; + +#[derive(Clone)] +pub struct VideoTimeCodeInterval(ffi::GstVideoTimeCodeInterval); + +impl VideoTimeCodeInterval { + pub fn from_string(tc_inter_str: &str) -> Option { + assert_initialized_main_thread!(); + unsafe { + from_glib_full(ffi::gst_video_time_code_interval_new_from_string( + tc_inter_str.to_glib_none().0, + )) + } + } + + pub fn new(&mut self, hours: u32, minutes: u32, seconds: u32, frames: u32) -> Self { + assert_initialized_main_thread!(); + unsafe { + let mut v = mem::zeroed(); + ffi::gst_video_time_code_interval_init(&mut v, hours, minutes, seconds, frames); + VideoTimeCodeInterval(v) + } + } + + pub fn get_hours(&self) -> u32 { + self.0.hours + } + + pub fn set_hours(&mut self, hours: u32) { + self.0.hours = hours + } + + pub fn get_minutes(&self) -> u32 { + self.0.minutes + } + + pub fn set_minutes(&mut self, minutes: u32) { + assert!(minutes < 60); + self.0.minutes = minutes + } + + pub fn get_seconds(&self) -> u32 { + self.0.seconds + } + + pub fn set_seconds(&mut self, seconds: u32) { + assert!(seconds < 60); + self.0.seconds = seconds + } + + pub fn get_frames(&self) -> u32 { + self.0.frames + } + + pub fn set_frames(&mut self, hours: u32) { + self.0.frames = hours + } +} + +unsafe impl Send for VideoTimeCodeInterval {} +unsafe impl Sync for VideoTimeCodeInterval {} + +impl PartialEq for VideoTimeCodeInterval { + fn eq(&self, other: &Self) -> bool { + self.0.hours == other.0.hours + && self.0.minutes == other.0.hours + && self.0.seconds == other.0.seconds + && self.0.frames == other.0.frames + } +} + +impl Eq for VideoTimeCodeInterval {} + +impl PartialOrd for VideoTimeCodeInterval { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for VideoTimeCodeInterval { + #[inline] + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.0 + .hours + .cmp(&other.0.hours) + .then_with(|| self.0.minutes.cmp(&other.0.hours)) + .then_with(|| self.0.seconds.cmp(&other.0.seconds)) + .then_with(|| self.0.frames.cmp(&other.0.frames)) + } +} + +impl fmt::Debug for VideoTimeCodeInterval { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.debug_struct("VideoTimeCodeInterval") + .field("hours", &self.0.hours) + .field("minutes", &self.0.minutes) + .field("seconds", &self.0.seconds) + .field("frames", &self.0.frames) + .finish() + } +} + +impl fmt::Display for VideoTimeCodeInterval { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "{:02}:{:02}:{:02}:{:02}", + self.0.hours, self.0.minutes, self.0.seconds, self.0.frames + ) + } +} + +#[doc(hidden)] +impl GlibPtrDefault for VideoTimeCodeInterval { + type GlibType = *mut ffi::GstVideoTimeCodeInterval; +} + +#[doc(hidden)] +impl<'a> ToGlibPtr<'a, *const ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval { + type Storage = &'a Self; + + #[inline] + fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstVideoTimeCodeInterval, Self> { + Stash(&self.0 as *const _, self) + } + + #[inline] + fn to_glib_full(&self) -> *const ffi::GstVideoTimeCodeInterval { + unsafe { ffi::gst_video_time_code_interval_copy(&self.0 as *const _) } + } +} + +#[doc(hidden)] +impl<'a> ToGlibPtrMut<'a, *mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval { + type Storage = &'a mut Self; + + #[inline] + fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GstVideoTimeCodeInterval, Self> { + let ptr = &mut self.0 as *mut _; + StashMut(ptr, self) + } +} + +#[doc(hidden)] +impl FromGlibPtrNone<*mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval { + #[inline] + unsafe fn from_glib_none(ptr: *mut ffi::GstVideoTimeCodeInterval) -> Self { + assert!(!ptr.is_null()); + VideoTimeCodeInterval(ptr::read(ptr)) + } +} + +#[doc(hidden)] +impl FromGlibPtrNone<*const ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval { + #[inline] + unsafe fn from_glib_none(ptr: *const ffi::GstVideoTimeCodeInterval) -> Self { + assert!(!ptr.is_null()); + VideoTimeCodeInterval(ptr::read(ptr)) + } +} + +#[doc(hidden)] +impl FromGlibPtrFull<*mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval { + #[inline] + unsafe fn from_glib_full(ptr: *mut ffi::GstVideoTimeCodeInterval) -> Self { + assert!(!ptr.is_null()); + let res = VideoTimeCodeInterval(ptr::read(ptr)); + ffi::gst_video_time_code_interval_free(ptr); + + res + } +} + +#[doc(hidden)] +impl FromGlibPtrBorrow<*mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval { + #[inline] + unsafe fn from_glib_borrow(ptr: *mut ffi::GstVideoTimeCodeInterval) -> Self { + assert!(!ptr.is_null()); + VideoTimeCodeInterval(ptr::read(ptr)) + } +} + +impl StaticType for VideoTimeCodeInterval { + fn static_type() -> glib::Type { + unsafe { from_glib(ffi::gst_video_time_code_interval_get_type()) } + } +} + +#[doc(hidden)] +impl<'a> value::FromValueOptional<'a> for VideoTimeCodeInterval { + unsafe fn from_value_optional(value: &glib::Value) -> Option { + Option::::from_glib_full(gobject_ffi::g_value_dup_boxed( + value.to_glib_none().0, + ) + as *mut ffi::GstVideoTimeCodeInterval) + } +} + +#[doc(hidden)] +impl value::SetValue for VideoTimeCodeInterval { + unsafe fn set_value(value: &mut glib::Value, this: &Self) { + gobject_ffi::g_value_set_boxed( + value.to_glib_none_mut().0, + ToGlibPtr::<*const ffi::GstVideoTimeCodeInterval>::to_glib_none(this).0 + as glib_ffi::gpointer, + ) + } +} + +#[doc(hidden)] +impl value::SetValueOptional for VideoTimeCodeInterval { + unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { + gobject_ffi::g_value_set_boxed( + value.to_glib_none_mut().0, + ToGlibPtr::<*const ffi::GstVideoTimeCodeInterval>::to_glib_none(&this).0 + as glib_ffi::gpointer, + ) + } +}