gstreamer-rs/gstreamer-app/src/app_src.rs
Sebastian Dröge d1e562b9f6 Explicitly add dyn keyword to trait objects
Trait objects without are deprecated with the latest nightly and this
makes it more clear that we're doing dynamic dispatch anyway.
2019-06-06 09:09:34 +03:00

227 lines
6.7 KiB
Rust

// Copyright (C) 2017 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 glib::translate::*;
use glib_sys::{gboolean, gpointer};
use gst;
use gst_app_sys;
use std::cell::RefCell;
use std::mem;
use std::ptr;
use AppSrc;
#[allow(clippy::type_complexity)]
pub struct AppSrcCallbacks {
need_data: Option<RefCell<Box<dyn FnMut(&AppSrc, u32) + Send + 'static>>>,
enough_data: Option<Box<dyn Fn(&AppSrc) + Send + Sync + 'static>>,
seek_data: Option<Box<dyn Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>>,
callbacks: gst_app_sys::GstAppSrcCallbacks,
}
unsafe impl Send for AppSrcCallbacks {}
unsafe impl Sync for AppSrcCallbacks {}
impl AppSrcCallbacks {
#[allow(clippy::new_ret_no_self)]
pub fn new() -> AppSrcCallbacksBuilder {
skip_assert_initialized!();
AppSrcCallbacksBuilder {
need_data: None,
enough_data: None,
seek_data: None,
}
}
}
#[allow(clippy::type_complexity)]
pub struct AppSrcCallbacksBuilder {
need_data: Option<RefCell<Box<dyn FnMut(&AppSrc, u32) + Send + 'static>>>,
enough_data: Option<Box<dyn Fn(&AppSrc) + Send + Sync + 'static>>,
seek_data: Option<Box<dyn Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>>,
}
impl AppSrcCallbacksBuilder {
pub fn need_data<F: FnMut(&AppSrc, u32) + Send + 'static>(self, need_data: F) -> Self {
Self {
need_data: Some(RefCell::new(Box::new(need_data))),
..self
}
}
pub fn enough_data<F: Fn(&AppSrc) + Send + Sync + 'static>(self, enough_data: F) -> Self {
Self {
enough_data: Some(Box::new(enough_data)),
..self
}
}
pub fn seek_data<F: Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>(
self,
seek_data: F,
) -> Self {
Self {
seek_data: Some(Box::new(seek_data)),
..self
}
}
pub fn build(self) -> AppSrcCallbacks {
let have_need_data = self.need_data.is_some();
let have_enough_data = self.enough_data.is_some();
let have_seek_data = self.seek_data.is_some();
AppSrcCallbacks {
need_data: self.need_data,
enough_data: self.enough_data,
seek_data: self.seek_data,
callbacks: gst_app_sys::GstAppSrcCallbacks {
need_data: if have_need_data {
Some(trampoline_need_data)
} else {
None
},
enough_data: if have_enough_data {
Some(trampoline_enough_data)
} else {
None
},
seek_data: if have_seek_data {
Some(trampoline_seek_data)
} else {
None
},
_gst_reserved: [
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
],
},
}
}
}
unsafe extern "C" fn trampoline_need_data(
appsrc: *mut gst_app_sys::GstAppSrc,
length: u32,
callbacks: gpointer,
) {
let callbacks = &*(callbacks as *const AppSrcCallbacks);
if let Some(ref need_data) = callbacks.need_data {
(&mut *need_data.borrow_mut())(&from_glib_borrow(appsrc), length);
}
}
unsafe extern "C" fn trampoline_enough_data(
appsrc: *mut gst_app_sys::GstAppSrc,
callbacks: gpointer,
) {
let callbacks = &*(callbacks as *const AppSrcCallbacks);
if let Some(ref enough_data) = callbacks.enough_data {
(*enough_data)(&from_glib_borrow(appsrc));
}
}
unsafe extern "C" fn trampoline_seek_data(
appsrc: *mut gst_app_sys::GstAppSrc,
offset: u64,
callbacks: gpointer,
) -> gboolean {
let callbacks = &*(callbacks as *const AppSrcCallbacks);
let ret = if let Some(ref seek_data) = callbacks.seek_data {
(*seek_data)(&from_glib_borrow(appsrc), offset)
} else {
false
};
ret.to_glib()
}
unsafe extern "C" fn destroy_callbacks(ptr: gpointer) {
Box::<AppSrcCallbacks>::from_raw(ptr as *mut _);
}
impl AppSrc {
pub fn end_of_stream(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
let ret: gst::FlowReturn = unsafe {
from_glib(gst_app_sys::gst_app_src_end_of_stream(
self.to_glib_none().0,
))
};
ret.into_result()
}
pub fn push_buffer(&self, buffer: gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
let ret: gst::FlowReturn = unsafe {
from_glib(gst_app_sys::gst_app_src_push_buffer(
self.to_glib_none().0,
buffer.into_ptr(),
))
};
ret.into_result()
}
#[cfg(any(feature = "v1_14", feature = "dox"))]
pub fn push_buffer_list(
&self,
list: gst::BufferList,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let ret: gst::FlowReturn = unsafe {
from_glib(gst_app_sys::gst_app_src_push_buffer_list(
self.to_glib_none().0,
list.into_ptr(),
))
};
ret.into_result()
}
pub fn push_sample(&self, sample: &gst::Sample) -> Result<gst::FlowSuccess, gst::FlowError> {
let ret: gst::FlowReturn = unsafe {
from_glib(gst_app_sys::gst_app_src_push_sample(
self.to_glib_none().0,
sample.to_glib_none().0,
))
};
ret.into_result()
}
pub fn set_callbacks(&self, callbacks: AppSrcCallbacks) {
unsafe {
gst_app_sys::gst_app_src_set_callbacks(
self.to_glib_none().0,
mut_override(&callbacks.callbacks),
Box::into_raw(Box::new(callbacks)) as *mut _,
Some(destroy_callbacks),
);
}
}
pub fn set_latency(&self, min: gst::ClockTime, max: gst::ClockTime) {
unsafe {
gst_app_sys::gst_app_src_set_latency(
self.to_glib_none().0,
min.to_glib(),
max.to_glib(),
);
}
}
pub fn get_latency(&self) -> (gst::ClockTime, gst::ClockTime) {
unsafe {
let mut min = mem::uninitialized();
let mut max = mem::uninitialized();
gst_app_sys::gst_app_src_get_latency(self.to_glib_none().0, &mut min, &mut max);
(from_glib(min), from_glib(max))
}
}
}