gstreamer: Add support for subclassing gst::Clock

This commit is contained in:
Sebastian Dröge 2019-09-25 16:41:23 +03:00
parent 74b05f0272
commit 1c8b2c671b
2 changed files with 308 additions and 0 deletions

View file

@ -0,0 +1,305 @@
// Copyright (C) 2019 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use gst_sys;
use glib;
use glib::translate::*;
use glib::subclass::prelude::*;
use Clock;
use ClockClass;
use ClockError;
use ClockId;
use ClockReturn;
use ClockSuccess;
use ClockTime;
use ClockTimeDiff;
pub trait ClockImpl: ClockImplExt + ObjectImpl + Send + Sync + 'static {
fn change_resolution(
&self,
clock: &Clock,
old_resolution: ClockTime,
new_resolution: ClockTime,
) -> ClockTime {
self.parent_change_resolution(clock, old_resolution, new_resolution)
}
fn get_resolution(&self, clock: &Clock) -> ClockTime {
self.parent_get_resolution(clock)
}
fn get_internal_time(&self, clock: &Clock) -> ClockTime {
self.parent_get_internal_time(clock)
}
fn wait(
&self,
clock: &Clock,
id: &ClockId,
) -> (Result<ClockSuccess, ClockError>, ClockTimeDiff) {
self.parent_wait(clock, id)
}
fn wait_async(&self, clock: &Clock, id: &ClockId) -> Result<ClockSuccess, ClockError> {
self.parent_wait_async(clock, id)
}
fn unschedule(&self, clock: &Clock, id: &ClockId) {
self.parent_unschedule(clock, id)
}
}
pub trait ClockImplExt {
fn parent_change_resolution(
&self,
clock: &Clock,
old_resolution: ClockTime,
new_resolution: ClockTime,
) -> ClockTime;
fn parent_get_resolution(&self, clock: &Clock) -> ClockTime;
fn parent_get_internal_time(&self, clock: &Clock) -> ClockTime;
fn parent_wait(
&self,
clock: &Clock,
id: &ClockId,
) -> (Result<ClockSuccess, ClockError>, ClockTimeDiff);
fn parent_wait_async(&self, clock: &Clock, id: &ClockId) -> Result<ClockSuccess, ClockError>;
fn parent_unschedule(&self, clock: &Clock, id: &ClockId);
}
impl<T: ClockImpl + ObjectImpl> ClockImplExt for T {
fn parent_change_resolution(
&self,
clock: &Clock,
old_resolution: ClockTime,
new_resolution: ClockTime,
) -> ClockTime {
unsafe {
let data = self.get_type_data();
let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass;
if let Some(func) = (*parent_class).change_resolution {
from_glib(func(
clock.to_glib_none().0,
old_resolution.to_glib(),
new_resolution.to_glib(),
))
} else {
self.get_resolution(clock)
}
}
}
fn parent_get_resolution(&self, clock: &Clock) -> ClockTime {
unsafe {
let data = self.get_type_data();
let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass;
from_glib(
(*parent_class)
.get_resolution
.map(|f| f(clock.to_glib_none().0))
.unwrap_or(1),
)
}
}
fn parent_get_internal_time(&self, clock: &Clock) -> ClockTime {
unsafe {
let data = self.get_type_data();
let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass;
from_glib(
(*parent_class)
.get_internal_time
.map(|f| f(clock.to_glib_none().0))
.unwrap_or(0),
)
}
}
fn parent_wait(
&self,
clock: &Clock,
id: &ClockId,
) -> (Result<ClockSuccess, ClockError>, ClockTimeDiff) {
unsafe {
let data = self.get_type_data();
let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass;
let mut jitter = 0;
(
ClockReturn::from_glib(
(*parent_class)
.wait
.map(|f| {
f(
clock.to_glib_none().0,
id.to_glib_none().0 as *mut gst_sys::GstClockEntry,
&mut jitter,
)
})
.unwrap_or(gst_sys::GST_CLOCK_UNSUPPORTED),
)
.into_result(),
jitter,
)
}
}
fn parent_wait_async(&self, clock: &Clock, id: &ClockId) -> Result<ClockSuccess, ClockError> {
unsafe {
let data = self.get_type_data();
let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass;
ClockReturn::from_glib(
(*parent_class)
.wait_async
.map(|f| {
f(
clock.to_glib_none().0,
id.to_glib_none().0 as *mut gst_sys::GstClockEntry,
)
})
.unwrap_or(gst_sys::GST_CLOCK_UNSUPPORTED),
)
.into_result()
}
}
fn parent_unschedule(&self, clock: &Clock, id: &ClockId) {
unsafe {
let data = self.get_type_data();
let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass;
if let Some(func) = (*parent_class).unschedule {
func(
clock.to_glib_none().0,
id.to_glib_none().0 as *mut gst_sys::GstClockEntry,
);
}
}
}
}
unsafe impl<T: ObjectSubclass + ClockImpl> IsSubclassable<T> for ClockClass {
fn override_vfuncs(&mut self) {
<glib::ObjectClass as IsSubclassable<T>>::override_vfuncs(self);
unsafe {
let klass = &mut *(self as *mut Self as *mut gst_sys::GstClockClass);
klass.change_resolution = Some(clock_change_resolution::<T>);
klass.get_resolution = Some(clock_get_resolution::<T>);
klass.get_internal_time = Some(clock_get_internal_time::<T>);
klass.wait = Some(clock_wait::<T>);
klass.wait_async = Some(clock_wait_async::<T>);
klass.unschedule = Some(clock_unschedule::<T>);
}
}
}
unsafe extern "C" fn clock_change_resolution<T: ObjectSubclass>(
ptr: *mut gst_sys::GstClock,
old_resolution: gst_sys::GstClockTime,
new_resolution: gst_sys::GstClockTime,
) -> gst_sys::GstClockTime
where
T: ClockImpl,
{
glib_floating_reference_guard!(ptr);
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Clock = from_glib_borrow(ptr);
imp.change_resolution(&wrap, from_glib(old_resolution), from_glib(new_resolution))
.to_glib()
}
unsafe extern "C" fn clock_get_resolution<T: ObjectSubclass>(
ptr: *mut gst_sys::GstClock,
) -> gst_sys::GstClockTime
where
T: ClockImpl,
{
glib_floating_reference_guard!(ptr);
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Clock = from_glib_borrow(ptr);
imp.get_resolution(&wrap).to_glib()
}
unsafe extern "C" fn clock_get_internal_time<T: ObjectSubclass>(
ptr: *mut gst_sys::GstClock,
) -> gst_sys::GstClockTime
where
T: ClockImpl,
{
glib_floating_reference_guard!(ptr);
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Clock = from_glib_borrow(ptr);
imp.get_internal_time(&wrap).to_glib()
}
unsafe extern "C" fn clock_wait<T: ObjectSubclass>(
ptr: *mut gst_sys::GstClock,
id: *mut gst_sys::GstClockEntry,
jitter: *mut gst_sys::GstClockTimeDiff,
) -> gst_sys::GstClockReturn
where
T: ClockImpl,
{
glib_floating_reference_guard!(ptr);
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Clock = from_glib_borrow(ptr);
let (res, j) = imp.wait(&wrap, &from_glib_borrow(id as gst_sys::GstClockID));
if !jitter.is_null() {
*jitter = j;
}
ClockReturn::from(res).to_glib()
}
unsafe extern "C" fn clock_wait_async<T: ObjectSubclass>(
ptr: *mut gst_sys::GstClock,
id: *mut gst_sys::GstClockEntry,
) -> gst_sys::GstClockReturn
where
T: ClockImpl,
{
glib_floating_reference_guard!(ptr);
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Clock = from_glib_borrow(ptr);
ClockReturn::from(imp.wait_async(&wrap, &from_glib_borrow(id as gst_sys::GstClockID))).to_glib()
}
unsafe extern "C" fn clock_unschedule<T: ObjectSubclass>(
ptr: *mut gst_sys::GstClock,
id: *mut gst_sys::GstClockEntry,
) where
T: ClockImpl,
{
glib_floating_reference_guard!(ptr);
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Clock = from_glib_borrow(ptr);
imp.unschedule(&wrap, &from_glib_borrow(id as gst_sys::GstClockID));
}

View file

@ -31,6 +31,8 @@ pub mod pipeline;
pub mod device;
pub mod device_provider;
pub mod clock;
pub mod preset;
pub mod tag_setter;
pub mod uri_handler;
@ -38,6 +40,7 @@ pub mod uri_handler;
pub mod prelude {
pub use super::bin::{BinImpl, BinImplExt};
pub use super::child_proxy::ChildProxyImpl;
pub use super::clock::{ClockImpl, ClockImplExt};
pub use super::device::{DeviceImpl, DeviceImplExt};
pub use super::device_provider::{
DeviceProviderClassSubclassExt, DeviceProviderImpl, DeviceProviderImplExt,