gstreamer-video: Implement VideoTimeCode via glib::wrapper!

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1180>
This commit is contained in:
Sebastian Dröge 2023-01-03 11:41:18 +02:00 committed by GStreamer Marge Bot
parent 30838b6549
commit 81bcf5c8dd

View file

@ -4,20 +4,56 @@ use glib::translate::*;
use gst::prelude::*; use gst::prelude::*;
use std::cmp; use std::cmp;
use std::fmt; use std::fmt;
use std::marker::PhantomData;
use std::mem; use std::mem;
use std::ptr;
use std::str; use std::str;
use crate::VideoTimeCodeFlags; use crate::VideoTimeCodeFlags;
use crate::VideoTimeCodeInterval; use crate::VideoTimeCodeInterval;
#[doc(alias = "GstVideoTimeCode")] glib::wrapper! {
#[repr(transparent)] #[doc(alias = "GstVideoTimeCode")]
pub struct VideoTimeCode(ffi::GstVideoTimeCode); pub struct VideoTimeCode(BoxedInline<ffi::GstVideoTimeCode>);
#[doc(alias = "GstVideoTimeCode")]
#[repr(transparent)] match fn {
pub struct ValidVideoTimeCode(ffi::GstVideoTimeCode); copy => |ptr| ffi::gst_video_time_code_copy(ptr),
free => |ptr| ffi::gst_video_time_code_free(ptr),
init => |_ptr| (),
copy_into => |dest, src| {
*dest = *src;
if !(*dest).config.latest_daily_jam.is_null() {
glib::ffi::g_date_time_ref((*dest).config.latest_daily_jam);
}
},
clear => |ptr| {
if !(*ptr).config.latest_daily_jam.is_null() {
glib::ffi::g_date_time_unref((*ptr).config.latest_daily_jam);
}
},
type_ => || ffi::gst_video_time_code_get_type(),
}
}
glib::wrapper! {
#[doc(alias = "GstVideoTimeCode")]
pub struct ValidVideoTimeCode(BoxedInline<ffi::GstVideoTimeCode>);
match fn {
copy => |ptr| ffi::gst_video_time_code_copy(ptr),
free => |ptr| ffi::gst_video_time_code_free(ptr),
init => |_ptr| (),
copy_into => |dest, src| {
*dest = *src;
if !(*dest).config.latest_daily_jam.is_null() {
glib::ffi::g_date_time_ref((*dest).config.latest_daily_jam);
}
},
clear => |ptr| {
if !(*ptr).config.latest_daily_jam.is_null() {
glib::ffi::g_date_time_unref((*ptr).config.latest_daily_jam);
}
},
}
}
impl VideoTimeCode { impl VideoTimeCode {
pub fn new_empty() -> Self { pub fn new_empty() -> Self {
@ -25,7 +61,9 @@ impl VideoTimeCode {
unsafe { unsafe {
let mut v = mem::MaybeUninit::zeroed(); let mut v = mem::MaybeUninit::zeroed();
ffi::gst_video_time_code_clear(v.as_mut_ptr()); ffi::gst_video_time_code_clear(v.as_mut_ptr());
Self(v.assume_init()) Self {
inner: v.assume_init(),
}
} }
} }
@ -56,7 +94,9 @@ impl VideoTimeCode {
field_count, field_count,
); );
Self(v.assume_init()) Self {
inner: v.assume_init(),
}
} }
} }
@ -85,7 +125,9 @@ impl VideoTimeCode {
if res == glib::ffi::GFALSE { if res == glib::ffi::GFALSE {
Err(glib::bool_error!("Failed to init video time code")) Err(glib::bool_error!("Failed to init video time code"))
} else { } else {
Ok(Self(v.assume_init())) Ok(Self {
inner: v.assume_init(),
})
} }
} }
} }
@ -96,35 +138,35 @@ impl VideoTimeCode {
} }
pub fn set_fps(&mut self, fps: gst::Fraction) { pub fn set_fps(&mut self, fps: gst::Fraction) {
self.0.config.fps_n = fps.numer() as u32; self.inner.config.fps_n = fps.numer() as u32;
self.0.config.fps_d = fps.denom() as u32; self.inner.config.fps_d = fps.denom() as u32;
} }
pub fn set_flags(&mut self, flags: VideoTimeCodeFlags) { pub fn set_flags(&mut self, flags: VideoTimeCodeFlags) {
self.0.config.flags = flags.into_glib() self.inner.config.flags = flags.into_glib()
} }
pub fn set_hours(&mut self, hours: u32) { pub fn set_hours(&mut self, hours: u32) {
self.0.hours = hours self.inner.hours = hours
} }
pub fn set_minutes(&mut self, minutes: u32) { pub fn set_minutes(&mut self, minutes: u32) {
assert!(minutes < 60); assert!(minutes < 60);
self.0.minutes = minutes self.inner.minutes = minutes
} }
pub fn set_seconds(&mut self, seconds: u32) { pub fn set_seconds(&mut self, seconds: u32) {
assert!(seconds < 60); assert!(seconds < 60);
self.0.seconds = seconds self.inner.seconds = seconds
} }
pub fn set_frames(&mut self, frames: u32) { pub fn set_frames(&mut self, frames: u32) {
self.0.frames = frames self.inner.frames = frames
} }
pub fn set_field_count(&mut self, field_count: u32) { pub fn set_field_count(&mut self, field_count: u32) {
assert!(field_count <= 2); assert!(field_count <= 2);
self.0.field_count = field_count self.inner.field_count = field_count
} }
} }
@ -138,7 +180,7 @@ impl TryFrom<VideoTimeCode> for ValidVideoTimeCode {
// from running as we don't move v.0 out here but copy it. // from running as we don't move v.0 out here but copy it.
// GstVideoTimeCode implements Copy. // GstVideoTimeCode implements Copy.
let v = mem::ManuallyDrop::new(v); let v = mem::ManuallyDrop::new(v);
Ok(Self(v.0)) Ok(Self { inner: v.inner })
} else { } else {
Err(v) Err(v)
} }
@ -251,67 +293,48 @@ macro_rules! generic_impl {
($name:ident) => { ($name:ident) => {
impl $name { impl $name {
pub fn hours(&self) -> u32 { pub fn hours(&self) -> u32 {
self.0.hours self.inner.hours
} }
pub fn minutes(&self) -> u32 { pub fn minutes(&self) -> u32 {
self.0.minutes self.inner.minutes
} }
pub fn seconds(&self) -> u32 { pub fn seconds(&self) -> u32 {
self.0.seconds self.inner.seconds
} }
pub fn frames(&self) -> u32 { pub fn frames(&self) -> u32 {
self.0.frames self.inner.frames
} }
pub fn field_count(&self) -> u32 { pub fn field_count(&self) -> u32 {
self.0.field_count self.inner.field_count
} }
pub fn fps(&self) -> gst::Fraction { pub fn fps(&self) -> gst::Fraction {
(self.0.config.fps_n as i32, self.0.config.fps_d as i32).into() (
self.inner.config.fps_n as i32,
self.inner.config.fps_d as i32,
)
.into()
} }
pub fn flags(&self) -> VideoTimeCodeFlags { pub fn flags(&self) -> VideoTimeCodeFlags {
unsafe { from_glib(self.0.config.flags) } unsafe { from_glib(self.inner.config.flags) }
} }
pub fn latest_daily_jam(&self) -> Option<glib::DateTime> { pub fn latest_daily_jam(&self) -> Option<glib::DateTime> {
unsafe { from_glib_none(self.0.config.latest_daily_jam) } unsafe { from_glib_none(self.inner.config.latest_daily_jam) }
} }
pub fn set_latest_daily_jam(&mut self, latest_daily_jam: Option<&glib::DateTime>) { pub fn set_latest_daily_jam(&mut self, latest_daily_jam: Option<&glib::DateTime>) {
unsafe { unsafe {
if !self.0.config.latest_daily_jam.is_null() { if !self.inner.config.latest_daily_jam.is_null() {
glib::ffi::g_date_time_unref(self.0.config.latest_daily_jam); glib::ffi::g_date_time_unref(self.inner.config.latest_daily_jam);
} }
self.0.config.latest_daily_jam = latest_daily_jam.to_glib_full() self.inner.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);
}
} }
} }
} }
@ -345,124 +368,22 @@ macro_rules! generic_impl {
unsafe impl Send for $name {} unsafe impl Send for $name {}
unsafe impl Sync for $name {} unsafe impl Sync for $name {}
};
}
#[doc(hidden)] generic_impl!(VideoTimeCode);
impl GlibPtrDefault for $name { generic_impl!(ValidVideoTimeCode);
type GlibType = *mut ffi::GstVideoTimeCode;
}
#[doc(hidden)] impl StaticType for ValidVideoTimeCode {
unsafe impl TransparentType for $name {
type GlibType = ffi::GstVideoTimeCode;
}
#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const ffi::GstVideoTimeCode> for $name {
type Storage = PhantomData<&'a Self>;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstVideoTimeCode, Self> {
Stash(&self.0 as *const _, PhantomData)
}
#[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 = PhantomData<&'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, PhantomData)
}
}
#[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) -> Borrowed<Self> {
assert!(!ptr.is_null());
let v = ptr::read(ptr);
Borrowed::new($name(v))
}
}
impl StaticType for $name {
fn static_type() -> glib::Type { fn static_type() -> glib::Type {
unsafe { from_glib(ffi::gst_video_time_code_get_type()) } unsafe { from_glib(ffi::gst_video_time_code_get_type()) }
} }
} }
impl glib::value::ValueType for $name { #[doc(hidden)]
type Type = Self; impl glib::value::ToValue for ValidVideoTimeCode {
}
impl glib::value::ValueTypeOptional for $name {}
#[doc(hidden)]
unsafe impl<'a> glib::value::FromValue<'a> for $name {
type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
as *mut ffi::GstVideoTimeCode)
}
}
#[doc(hidden)]
impl glib::value::ToValue for $name {
fn to_value(&self) -> glib::Value { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Self>(); let mut value = glib::Value::for_value_type::<VideoTimeCode>();
unsafe { unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
@ -475,13 +396,13 @@ macro_rules! generic_impl {
fn value_type(&self) -> glib::Type { fn value_type(&self) -> glib::Type {
Self::static_type() Self::static_type()
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::ToValueOptional for $name { impl glib::value::ToValueOptional for ValidVideoTimeCode {
fn to_value_optional(s: Option<&Self>) -> glib::Value { fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!(); skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<Self>(); let mut value = glib::Value::for_value_type::<VideoTimeCode>();
unsafe { unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
@ -490,21 +411,16 @@ macro_rules! generic_impl {
} }
value value
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl From<$name> for glib::Value { impl From<ValidVideoTimeCode> for glib::Value {
fn from(v: $name) -> glib::Value { fn from(v: ValidVideoTimeCode) -> glib::Value {
skip_assert_initialized!(); skip_assert_initialized!();
glib::value::ToValue::to_value(&v) glib::value::ToValue::to_value(&v)
} }
}
};
} }
generic_impl!(VideoTimeCode);
generic_impl!(ValidVideoTimeCode);
impl str::FromStr for VideoTimeCode { impl str::FromStr for VideoTimeCode {
type Err = glib::error::BoolError; type Err = glib::error::BoolError;
@ -550,7 +466,7 @@ impl From<ValidVideoTimeCode> for VideoTimeCode {
// from running as we don't move v.0 out here but copy it. // from running as we don't move v.0 out here but copy it.
// GstVideoTimeCode implements Copy. // GstVideoTimeCode implements Copy.
let v = mem::ManuallyDrop::new(v); let v = mem::ManuallyDrop::new(v);
Self(v.0) Self { inner: v.inner }
} }
} }
@ -591,7 +507,7 @@ impl VideoTimeCodeMeta {
// from running as we don't move tc.0 out here but copy it. // from running as we don't move tc.0 out here but copy it.
// GstVideoTimeCode implements Copy. // GstVideoTimeCode implements Copy.
let tc = mem::ManuallyDrop::new(tc); let tc = mem::ManuallyDrop::new(tc);
self.0.tc = tc.0; self.0.tc = tc.inner;
} }
} }
} }