Remove gst-plugin and gst-plugin-simple crates

They're not used anymore.
This commit is contained in:
Sebastian Dröge 2019-01-03 23:54:04 +02:00
parent 4b4ae6d52c
commit abe87fae12
28 changed files with 0 additions and 6760 deletions

View file

@ -1,8 +1,6 @@
[workspace]
members = [
"gst-plugin",
"gst-plugin-simple",
"gst-plugin-file",
"gst-plugin-http",
"gst-plugin-flv",

View file

@ -1,18 +0,0 @@
[package]
name = "gst-plugin-simple"
version = "0.4.0"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs"
license = "MIT/Apache-2.0"
[dependencies]
url = "1.1"
glib = { git = "https://github.com/gtk-rs/glib" }
gobject-subclass = { git = "https://github.com/gtk-rs/gobject-subclass" }
gst-plugin = { path="../gst-plugin" }
gstreamer = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
gstreamer-base = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
[lib]
name = "gst_plugin_simple"
path = "src/lib.rs"

View file

@ -1,689 +0,0 @@
// Copyright (C) 2016-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 std::sync::Mutex;
use std::collections::BTreeMap;
use std::u32;
use std::u64;
use glib;
use gobject_subclass::object::*;
use gst_plugin::element::*;
use gst_plugin::error::*;
use gst;
use gst::prelude::*;
use gst_base;
pub type StreamIndex = u32;
#[derive(Debug)]
pub enum SeekResult {
TooEarly,
Ok(u64),
Eos,
}
#[derive(Debug)]
pub enum HandleBufferResult {
NeedMoreData,
Again,
// NeedDataFromOffset(u64),
StreamAdded(Stream),
HaveAllStreams,
StreamChanged(Stream),
// StreamsAdded(Vec<Stream>), // Implies HaveAllStreams
StreamsChanged(Vec<Stream>),
// TODO need something to replace/add new streams
// TODO should probably directly implement the GstStreams new world order
BufferForStream(StreamIndex, gst::Buffer),
Eos(Option<StreamIndex>),
}
pub trait DemuxerImpl: Send + 'static {
fn start(
&mut self,
demuxer: &Element,
upstream_size: Option<u64>,
random_access: bool,
) -> Result<(), gst::ErrorMessage>;
fn stop(&mut self, demuxer: &Element) -> Result<(), gst::ErrorMessage>;
fn seek(
&mut self,
demuxer: &Element,
start: gst::ClockTime,
stop: gst::ClockTime,
) -> Result<SeekResult, gst::ErrorMessage>;
fn handle_buffer(
&mut self,
demuxer: &Element,
buffer: Option<gst::Buffer>,
) -> Result<HandleBufferResult, FlowError>;
fn end_of_stream(&mut self, demuxer: &Element) -> Result<(), gst::ErrorMessage>;
fn is_seekable(&self, demuxer: &Element) -> bool;
fn get_position(&self, demuxer: &Element) -> gst::ClockTime;
fn get_duration(&self, demuxer: &Element) -> gst::ClockTime;
}
#[derive(Debug)]
pub struct Stream {
pub index: StreamIndex,
pub caps: gst::Caps,
pub stream_id: String,
}
impl Stream {
pub fn new(index: StreamIndex, caps: gst::Caps, stream_id: String) -> Stream {
Stream {
index,
caps,
stream_id,
}
}
}
pub struct DemuxerInfo {
pub name: String,
pub long_name: String,
pub description: String,
pub classification: String,
pub author: String,
pub rank: u32,
pub create_instance: fn(&Element) -> Box<DemuxerImpl>,
pub input_caps: gst::Caps,
pub output_caps: gst::Caps,
}
pub struct Demuxer {
cat: gst::DebugCategory,
sinkpad: gst::Pad,
flow_combiner: Mutex<UniqueFlowCombiner>,
group_id: Mutex<gst::GroupId>,
srcpads: Mutex<BTreeMap<u32, gst::Pad>>,
imp: Mutex<Box<DemuxerImpl>>,
}
#[derive(Default)]
pub struct UniqueFlowCombiner(gst_base::FlowCombiner);
impl UniqueFlowCombiner {
fn add_pad(&mut self, pad: &gst::Pad) {
self.0.add_pad(pad);
}
fn clear(&mut self) {
self.0.clear();
}
fn update_flow(&mut self, flow_ret: gst::FlowReturn) -> gst::FlowReturn {
self.0.update_flow(flow_ret)
}
}
unsafe impl Send for UniqueFlowCombiner {}
unsafe impl Sync for UniqueFlowCombiner {}
impl Demuxer {
fn new(element: &Element, sinkpad: gst::Pad, demuxer_info: &DemuxerInfo) -> Self {
Self {
cat: gst::DebugCategory::new(
"rsdemux",
gst::DebugColorFlags::empty(),
"Rust demuxer base class",
),
sinkpad,
flow_combiner: Mutex::new(Default::default()),
group_id: Mutex::new(gst::util_group_id_next()),
srcpads: Mutex::new(BTreeMap::new()),
imp: Mutex::new((demuxer_info.create_instance)(element)),
}
}
fn class_init(klass: &mut ElementClass, demuxer_info: &DemuxerInfo) {
klass.set_metadata(
&demuxer_info.long_name,
&demuxer_info.classification,
&demuxer_info.description,
&demuxer_info.author,
);
let pad_template = gst::PadTemplate::new(
"sink",
gst::PadDirection::Sink,
gst::PadPresence::Always,
&demuxer_info.input_caps,
);
klass.add_pad_template(pad_template);
let pad_template = gst::PadTemplate::new(
"src_%u",
gst::PadDirection::Src,
gst::PadPresence::Sometimes,
&demuxer_info.output_caps,
);
klass.add_pad_template(pad_template);
}
fn init(element: &Element, demuxer_info: &DemuxerInfo) -> Box<ElementImpl<Element>> {
let templ = element.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::new_from_template(&templ, "sink");
sinkpad.set_activate_function(Demuxer::sink_activate);
sinkpad.set_activatemode_function(Demuxer::sink_activatemode);
sinkpad.set_chain_function(Demuxer::sink_chain);
sinkpad.set_event_function(Demuxer::sink_event);
element.add_pad(&sinkpad).unwrap();
let imp = Self::new(element, sinkpad, demuxer_info);
Box::new(imp)
}
fn add_stream(&self, element: &Element, index: u32, caps: gst::Caps, stream_id: &str) {
let mut srcpads = self.srcpads.lock().unwrap();
assert!(!srcpads.contains_key(&index));
let templ = element.get_pad_template("src_%u").unwrap();
let name = format!("src_{}", index);
let pad = gst::Pad::new_from_template(&templ, Some(name.as_str()));
pad.set_query_function(Demuxer::src_query);
pad.set_event_function(Demuxer::src_event);
pad.set_active(true).unwrap();
let full_stream_id = pad.create_stream_id(element, stream_id).unwrap();
pad.push_event(
gst::Event::new_stream_start(&full_stream_id)
.group_id(*self.group_id.lock().unwrap())
.build(),
);
pad.push_event(gst::Event::new_caps(&caps).build());
let segment = gst::FormattedSegment::<gst::ClockTime>::default();
pad.push_event(gst::Event::new_segment(&segment).build());
self.flow_combiner.lock().unwrap().add_pad(&pad);
element.add_pad(&pad).unwrap();
srcpads.insert(index, pad);
}
fn added_all_streams(&self, element: &Element) {
element.no_more_pads();
*self.group_id.lock().unwrap() = gst::util_group_id_next();
}
fn stream_format_changed(&self, _element: &Element, index: u32, caps: gst::Caps) {
let srcpads = self.srcpads.lock().unwrap();
if let Some(pad) = srcpads.get(&index) {
pad.push_event(gst::Event::new_caps(&caps).build());
}
}
fn stream_eos(&self, _element: &Element, index: Option<u32>) {
let srcpads = self.srcpads.lock().unwrap();
let event = gst::Event::new_eos().build();
match index {
Some(index) => {
if let Some(pad) = srcpads.get(&index) {
pad.push_event(event);
}
}
None => {
for (_, pad) in srcpads.iter().by_ref() {
pad.push_event(event.clone());
}
}
};
}
fn stream_push_buffer(
&self,
_element: &Element,
index: u32,
buffer: gst::Buffer,
) -> gst::FlowReturn {
let srcpads = self.srcpads.lock().unwrap();
if let Some(pad) = srcpads.get(&index) {
self.flow_combiner
.lock()
.unwrap()
.update_flow(pad.push(buffer))
} else {
gst::FlowReturn::Error
}
}
fn remove_all_streams(&self, element: &Element) {
self.flow_combiner.lock().unwrap().clear();
let mut srcpads = self.srcpads.lock().unwrap();
for (_, pad) in srcpads.iter().by_ref() {
element.remove_pad(pad).unwrap();
}
srcpads.clear();
}
fn sink_activate(pad: &gst::Pad, _parent: &Option<gst::Object>) -> bool {
let mode = {
let mut query = gst::Query::new_scheduling();
if !pad.peer_query(&mut query) {
return false;
}
// TODO
//if (gst_query_has_scheduling_mode_with_flags (query, GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE)) {
// GST_DEBUG_OBJECT (demuxer, "Activating in PULL mode");
// mode = GST_PAD_MODE_PULL;
//} else {
//GST_DEBUG_OBJECT (demuxer, "Activating in PUSH mode");
//}
gst::PadMode::Push
};
match pad.activate_mode(mode, true) {
Ok(_) => true,
Err(_) => false,
}
}
fn start(&self, element: &Element, upstream_size: Option<u64>, random_access: bool) -> bool {
let demuxer_impl = &mut self.imp.lock().unwrap();
gst_debug!(
self.cat,
obj: element,
"Starting with upstream size {:?} and random access {}",
upstream_size,
random_access
);
match demuxer_impl.start(element, upstream_size, random_access) {
Ok(..) => {
gst_trace!(self.cat, obj: element, "Successfully started",);
true
}
Err(ref msg) => {
gst_error!(self.cat, obj: element, "Failed to start: {:?}", msg);
element.post_error_message(msg);
false
}
}
}
fn stop(&self, element: &Element) -> bool {
let demuxer_impl = &mut self.imp.lock().unwrap();
gst_debug!(self.cat, obj: element, "Stopping");
match demuxer_impl.stop(element) {
Ok(..) => {
gst_trace!(self.cat, obj: element, "Successfully stop");
true
}
Err(ref msg) => {
gst_error!(self.cat, obj: element, "Failed to stop: {:?}", msg);
element.post_error_message(msg);
false
}
}
}
fn sink_activatemode(
_pad: &gst::Pad,
parent: &Option<gst::Object>,
mode: gst::PadMode,
active: bool,
) -> bool {
let element = parent.as_ref().unwrap().downcast_ref::<Element>().unwrap();
let demuxer = element.get_impl().downcast_ref::<Demuxer>().unwrap();
if active {
let upstream_size = demuxer
.sinkpad
.peer_query_duration::<gst::format::Bytes>()
.and_then(|v| v.0);
if !demuxer.start(element, upstream_size, mode == gst::PadMode::Pull) {
return false;
}
if mode == gst::PadMode::Pull {
// TODO
// demuxer.sinkpad.start_task(...)
}
true
} else {
if mode == gst::PadMode::Pull {
let _ = demuxer.sinkpad.stop_task();
}
demuxer.stop(element)
}
}
fn sink_chain(
_pad: &gst::Pad,
parent: &Option<gst::Object>,
buffer: gst::Buffer,
) -> gst::FlowReturn {
let element = parent.as_ref().unwrap().downcast_ref::<Element>().unwrap();
let demuxer = element.get_impl().downcast_ref::<Demuxer>().unwrap();
let mut res = {
let demuxer_impl = &mut demuxer.imp.lock().unwrap();
gst_trace!(demuxer.cat, obj: element, "Handling buffer {:?}", buffer);
match demuxer_impl.handle_buffer(element, Some(buffer)) {
Ok(res) => res,
Err(flow_error) => {
gst_error!(
demuxer.cat,
obj: element,
"Failed handling buffer: {:?}",
flow_error
);
match flow_error {
FlowError::NotNegotiated(ref msg) | FlowError::Error(ref msg) => {
element.post_error_message(msg);
}
_ => (),
}
return flow_error.into();
}
}
};
// Loop until AllEos, NeedMoreData or error when pushing downstream
loop {
gst_trace!(demuxer.cat, obj: element, "Handled {:?}", res);
match res {
HandleBufferResult::NeedMoreData => {
return gst::FlowReturn::Ok;
}
HandleBufferResult::StreamAdded(stream) => {
demuxer.add_stream(element, stream.index, stream.caps, &stream.stream_id);
}
HandleBufferResult::HaveAllStreams => {
demuxer.added_all_streams(element);
}
HandleBufferResult::StreamChanged(stream) => {
demuxer.stream_format_changed(element, stream.index, stream.caps);
}
HandleBufferResult::StreamsChanged(streams) => {
for stream in streams {
demuxer.stream_format_changed(element, stream.index, stream.caps);
}
}
HandleBufferResult::BufferForStream(index, buffer) => {
let flow_ret = demuxer.stream_push_buffer(element, index, buffer);
if flow_ret != gst::FlowReturn::Ok {
return flow_ret;
}
}
HandleBufferResult::Eos(index) => {
demuxer.stream_eos(element, index);
return gst::FlowReturn::Eos;
}
HandleBufferResult::Again => {
// nothing, just call again
}
};
gst_trace!(demuxer.cat, obj: element, "Calling again");
res = {
let demuxer_impl = &mut demuxer.imp.lock().unwrap();
match demuxer_impl.handle_buffer(element, None) {
Ok(res) => res,
Err(flow_error) => {
gst_error!(
demuxer.cat,
obj: element,
"Failed calling again: {:?}",
flow_error
);
match flow_error {
FlowError::NotNegotiated(ref msg) | FlowError::Error(ref msg) => {
element.post_error_message(msg);
}
_ => (),
}
return flow_error.into();
}
}
}
}
}
fn sink_event(pad: &gst::Pad, parent: &Option<gst::Object>, event: gst::Event) -> bool {
use gst::EventView;
let element = parent.as_ref().unwrap().downcast_ref::<Element>().unwrap();
let demuxer = element.get_impl().downcast_ref::<Demuxer>().unwrap();
match event.view() {
EventView::Eos(..) => {
let demuxer_impl = &mut demuxer.imp.lock().unwrap();
gst_debug!(demuxer.cat, obj: element, "End of stream");
match demuxer_impl.end_of_stream(element) {
Ok(_) => (),
Err(ref msg) => {
gst_error!(demuxer.cat, obj: element, "Failed end of stream: {:?}", msg);
element.post_error_message(msg);
}
}
pad.event_default(parent.as_ref(), event)
}
EventView::Segment(..) => pad.event_default(parent.as_ref(), event),
_ => pad.event_default(parent.as_ref(), event),
}
}
fn src_query(pad: &gst::Pad, parent: &Option<gst::Object>, query: &mut gst::QueryRef) -> bool {
use gst::QueryView;
let element = parent.as_ref().unwrap().downcast_ref::<Element>().unwrap();
let demuxer = element.get_impl().downcast_ref::<Demuxer>().unwrap();
match query.view_mut() {
QueryView::Position(ref mut q) => {
let fmt = q.get_format();
if fmt == gst::Format::Time {
let demuxer_impl = &demuxer.imp.lock().unwrap();
let position = demuxer_impl.get_position(&element);
gst_trace!(
demuxer.cat,
obj: element,
"Returning position {:?}",
position
);
match *position {
None => return false,
Some(_) => {
q.set(position);
return true;
}
}
} else {
return false;
}
}
QueryView::Duration(ref mut q) => {
let fmt = q.get_format();
if fmt == gst::Format::Time {
let demuxer_impl = &demuxer.imp.lock().unwrap();
let duration = demuxer_impl.get_duration(&element);
gst_trace!(
demuxer.cat,
obj: element,
"Returning duration {:?}",
duration
);
match *duration {
None => return false,
Some(_) => {
q.set(duration);
return true;
}
}
} else {
return false;
}
}
_ => (),
}
// FIXME: Have to do it outside the match because otherwise query is already mutably
// borrowed by the query view.
pad.query_default(parent.as_ref(), query)
}
fn src_event(pad: &gst::Pad, parent: &Option<gst::Object>, event: gst::Event) -> bool {
use gst::EventView;
match event.view() {
EventView::Seek(..) => {
// TODO: Implement
false
}
_ => pad.event_default(parent.as_ref(), event),
}
}
fn seek(
&self,
element: &Element,
start: gst::ClockTime,
stop: gst::ClockTime,
offset: &mut u64,
) -> bool {
gst_debug!(self.cat, obj: element, "Seeking to {:?}-{:?}", start, stop);
let res = {
let demuxer_impl = &mut self.imp.lock().unwrap();
match demuxer_impl.seek(element, start, stop) {
Ok(res) => res,
Err(ref msg) => {
gst_error!(self.cat, obj: element, "Failed to seek: {:?}", msg);
element.post_error_message(msg);
return false;
}
}
};
match res {
SeekResult::TooEarly => {
gst_debug!(self.cat, obj: element, "Seeked too early");
false
}
SeekResult::Ok(off) => {
gst_trace!(self.cat, obj: element, "Seeked successfully");
*offset = off;
true
}
SeekResult::Eos => {
gst_debug!(self.cat, obj: element, "Seeked after EOS");
*offset = u64::MAX;
self.stream_eos(element, None);
true
}
}
}
}
impl ObjectImpl<Element> for Demuxer {}
impl ElementImpl<Element> for Demuxer {
fn change_state(
&self,
element: &Element,
transition: gst::StateChange,
) -> gst::StateChangeReturn {
let mut ret = gst::StateChangeReturn::Success;
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
// TODO
*self.group_id.lock().unwrap() = gst::util_group_id_next();
}
_ => (),
}
ret = element.parent_change_state(transition);
if ret == gst::StateChangeReturn::Failure {
return ret;
}
match transition {
gst::StateChange::PausedToReady => {
self.flow_combiner.lock().unwrap().clear();
let mut srcpads = self.srcpads.lock().unwrap();
for (_, pad) in srcpads.iter().by_ref() {
element.remove_pad(pad).unwrap();
}
srcpads.clear();
}
_ => (),
}
ret
}
}
struct DemuxerStatic {
name: String,
demuxer_info: DemuxerInfo,
}
impl ImplTypeStatic<Element> for DemuxerStatic {
fn get_name(&self) -> &str {
self.name.as_str()
}
fn new(&self, element: &Element) -> Box<ElementImpl<Element>> {
Demuxer::init(element, &self.demuxer_info)
}
fn class_init(&self, klass: &mut ElementClass) {
Demuxer::class_init(klass, &self.demuxer_info);
}
}
pub fn demuxer_register(
plugin: &gst::Plugin,
demuxer_info: DemuxerInfo,
) -> Result<(), glib::BoolError> {
let name = demuxer_info.name.clone();
let rank = demuxer_info.rank;
let demuxer_static = DemuxerStatic {
name: format!("Demuxer-{}", name),
demuxer_info,
};
let type_ = register_type(demuxer_static);
gst::Element::register(plugin, &name, rank, type_)
}

View file

@ -1,67 +0,0 @@
// Copyright (C) 2016-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 std::error::Error;
use std::fmt::Error as FmtError;
use std::fmt::{Display, Formatter};
use glib;
use gst;
#[derive(Debug, PartialEq, Eq)]
pub struct UriError {
error: gst::URIError,
message: String,
}
impl UriError {
pub fn new<T: Into<String>>(error: gst::URIError, message: T) -> UriError {
UriError {
error,
message: message.into(),
}
}
pub fn message(&self) -> &str {
&self.message
}
pub fn error(&self) -> gst::URIError {
self.error
}
}
impl Into<glib::Error> for UriError {
fn into(self) -> glib::Error {
(&self).into()
}
}
impl<'a> Into<glib::Error> for &'a UriError {
fn into(self) -> glib::Error {
glib::Error::new(self.error, &self.message)
}
}
impl Display for UriError {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
f.write_fmt(format_args!("{}: {}", self.description(), self.message))
}
}
impl Error for UriError {
fn description(&self) -> &str {
match self.error {
gst::URIError::UnsupportedProtocol => "Unsupported protocol",
gst::URIError::BadUri => "Bad URI",
gst::URIError::BadState => "Bad State",
gst::URIError::BadReference => "Bad Reference",
_ => "Unknown",
}
}
}

View file

@ -1,23 +0,0 @@
// 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.
extern crate glib;
extern crate gobject_subclass;
extern crate gst_plugin;
#[macro_use]
extern crate gstreamer as gst;
extern crate gstreamer_base as gst_base;
extern crate url;
pub mod demuxer;
pub mod error;
pub mod sink;
pub mod source;
pub type UriValidator = Fn(&url::Url) -> Result<(), error::UriError> + Send + Sync + 'static;

View file

@ -1,303 +0,0 @@
// Copyright (C) 2016-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://opensink.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::sync::Mutex;
use url::Url;
use glib;
use gst;
use gst::prelude::*;
use gst_base::prelude::*;
use gobject_subclass::object::*;
use gst_plugin::base_sink::*;
use gst_plugin::element::*;
use gst_plugin::error::*;
use gst_plugin::uri_handler::*;
pub use gst_plugin::base_sink::BaseSink;
use error::*;
use UriValidator;
pub trait SinkImpl: Send + 'static {
fn uri_validator(&self) -> Box<UriValidator>;
fn start(&mut self, sink: &BaseSink, uri: Url) -> Result<(), gst::ErrorMessage>;
fn stop(&mut self, sink: &BaseSink) -> Result<(), gst::ErrorMessage>;
fn render(&mut self, sink: &BaseSink, buffer: &gst::BufferRef) -> Result<(), FlowError>;
}
struct Sink {
cat: gst::DebugCategory,
uri: Mutex<(Option<Url>, bool)>,
uri_validator: Box<UriValidator>,
imp: Mutex<Box<SinkImpl>>,
}
static PROPERTIES: [Property; 1] = [Property::String(
"uri",
"URI",
"URI to read from",
None,
PropertyMutability::ReadWrite,
)];
impl Sink {
fn new(sink: &BaseSink, sink_info: &SinkInfo) -> Self {
let sink_impl = (sink_info.create_instance)(sink);
Self {
cat: gst::DebugCategory::new(
"rssink",
gst::DebugColorFlags::empty(),
"Rust sink base class",
),
uri: Mutex::new((None, false)),
uri_validator: sink_impl.uri_validator(),
imp: Mutex::new(sink_impl),
}
}
fn class_init(klass: &mut BaseSinkClass, sink_info: &SinkInfo) {
klass.set_metadata(
&sink_info.long_name,
&sink_info.classification,
&sink_info.description,
&sink_info.author,
);
let caps = gst::Caps::new_any();
let pad_template = gst::PadTemplate::new(
"sink",
gst::PadDirection::Sink,
gst::PadPresence::Always,
&caps,
);
klass.add_pad_template(pad_template);
klass.install_properties(&PROPERTIES);
}
fn init(element: &BaseSink, sink_info: &SinkInfo) -> Box<BaseSinkImpl<BaseSink>> {
element.set_blocksize(4096);
let imp = Self::new(element, sink_info);
Box::new(imp)
}
fn get_uri(&self, _element: &glib::Object) -> Option<String> {
let uri_storage = &self.uri.lock().unwrap();
uri_storage.0.as_ref().map(|uri| String::from(uri.as_str()))
}
fn set_uri(&self, element: &glib::Object, uri_str: Option<String>) -> Result<(), glib::Error> {
let sink = element.clone().dynamic_cast::<BaseSink>().unwrap();
let uri_storage = &mut self.uri.lock().unwrap();
gst_debug!(self.cat, obj: &sink, "Setting URI {:?}", uri_str);
if uri_storage.1 {
return Err(
UriError::new(gst::URIError::BadState, "Already started".to_string()).into(),
);
}
uri_storage.0 = None;
if let Some(uri_str) = uri_str {
match Url::parse(uri_str.as_str()) {
Ok(uri) => {
try!((self.uri_validator)(&uri).map_err(|e| e.into()));
uri_storage.0 = Some(uri);
Ok(())
}
Err(err) => Err(UriError::new(
gst::URIError::BadUri,
format!("Failed to parse URI '{}': {}", uri_str, err),
)
.into()),
}
} else {
Ok(())
}
}
}
impl ObjectImpl<BaseSink> for Sink {
fn set_property(&self, obj: &glib::Object, id: u32, value: &glib::Value) {
let prop = &PROPERTIES[id as usize];
match *prop {
Property::String("uri", ..) => {
self.set_uri(obj, value.get()).unwrap();
}
_ => unimplemented!(),
}
}
fn get_property(&self, obj: &glib::Object, id: u32) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id as usize];
match *prop {
Property::String("uri", ..) => Ok(self.get_uri(obj).to_value()),
_ => unimplemented!(),
}
}
}
impl ElementImpl<BaseSink> for Sink {}
impl BaseSinkImpl<BaseSink> for Sink {
fn start(&self, sink: &BaseSink) -> bool {
gst_debug!(self.cat, obj: sink, "Starting");
// Don't keep the URI locked while we call start later
let uri = match *self.uri.lock().unwrap() {
(Some(ref uri), ref mut started) => {
*started = true;
uri.clone()
}
(None, _) => {
gst_error!(self.cat, obj: sink, "No URI given");
gst_element_error!(sink, gst::ResourceError::OpenRead, ["No URI given"]);
return false;
}
};
let sink_impl = &mut self.imp.lock().unwrap();
match sink_impl.start(sink, uri) {
Ok(..) => {
gst_trace!(self.cat, obj: sink, "Started successfully");
true
}
Err(ref msg) => {
gst_error!(self.cat, obj: sink, "Failed to start: {:?}", msg);
self.uri.lock().unwrap().1 = false;
sink.post_error_message(msg);
false
}
}
}
fn stop(&self, sink: &BaseSink) -> bool {
let sink_impl = &mut self.imp.lock().unwrap();
gst_debug!(self.cat, obj: sink, "Stopping");
match sink_impl.stop(sink) {
Ok(..) => {
gst_trace!(self.cat, obj: sink, "Stopped successfully");
self.uri.lock().unwrap().1 = false;
true
}
Err(ref msg) => {
gst_error!(self.cat, obj: sink, "Failed to stop: {:?}", msg);
sink.post_error_message(msg);
false
}
}
}
fn render(&self, sink: &BaseSink, buffer: &gst::BufferRef) -> gst::FlowReturn {
let sink_impl = &mut self.imp.lock().unwrap();
gst_trace!(self.cat, obj: sink, "Rendering buffer {:?}", buffer,);
match sink_impl.render(sink, buffer) {
Ok(()) => gst::FlowReturn::Ok,
Err(flow_error) => {
gst_error!(self.cat, obj: sink, "Failed to render: {:?}", flow_error);
match flow_error {
FlowError::NotNegotiated(ref msg) | FlowError::Error(ref msg) => {
sink.post_error_message(msg);
}
_ => (),
}
flow_error.into()
}
}
}
}
impl URIHandlerImpl for Sink {
fn get_uri(&self, element: &gst::URIHandler) -> Option<String> {
Sink::get_uri(self, &element.clone().upcast())
}
fn set_uri(&self, element: &gst::URIHandler, uri: Option<String>) -> Result<(), glib::Error> {
Sink::set_uri(self, &element.clone().upcast(), uri)
}
}
pub struct SinkInfo {
pub name: String,
pub long_name: String,
pub description: String,
pub classification: String,
pub author: String,
pub rank: u32,
pub create_instance: fn(&BaseSink) -> Box<SinkImpl>,
pub protocols: Vec<String>,
}
struct SinkStatic {
name: String,
sink_info: SinkInfo,
}
impl ImplTypeStatic<BaseSink> for SinkStatic {
fn get_name(&self) -> &str {
self.name.as_str()
}
fn new(&self, element: &BaseSink) -> Box<BaseSinkImpl<BaseSink>> {
Sink::init(element, &self.sink_info)
}
fn class_init(&self, klass: &mut BaseSinkClass) {
Sink::class_init(klass, &self.sink_info);
}
fn type_init(&self, token: &TypeInitToken, type_: glib::Type) {
register_uri_handler(token, type_, self);
}
}
impl URIHandlerImplStatic<BaseSink> for SinkStatic {
fn get_impl<'a>(&self, imp: &'a Box<BaseSinkImpl<BaseSink>>) -> &'a URIHandlerImpl {
imp.downcast_ref::<Sink>().unwrap()
}
fn get_type(&self) -> gst::URIType {
gst::URIType::Sink
}
fn get_protocols(&self) -> Vec<String> {
self.sink_info.protocols.clone()
}
}
pub fn sink_register(plugin: &gst::Plugin, sink_info: SinkInfo) -> Result<(), glib::BoolError> {
let name = sink_info.name.clone();
let rank = sink_info.rank;
let sink_static = SinkStatic {
name: format!("Sink-{}", name),
sink_info,
};
let type_ = register_type(sink_static);
gst::Element::register(plugin, &name, rank, type_)
}

View file

@ -1,390 +0,0 @@
// Copyright (C) 2016-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 std::u64;
use std::sync::Mutex;
use url::Url;
use glib;
use gst;
use gst::prelude::*;
use gst_base::prelude::*;
use gobject_subclass::object::*;
use gst_plugin::base_src::*;
use gst_plugin::element::*;
use gst_plugin::error::*;
use gst_plugin::uri_handler::*;
pub use gst_plugin::base_src::BaseSrc;
use error::*;
use UriValidator;
pub trait SourceImpl: Send + 'static {
fn uri_validator(&self) -> Box<UriValidator>;
fn is_seekable(&self, src: &BaseSrc) -> bool;
fn get_size(&self, src: &BaseSrc) -> Option<u64>;
fn start(&mut self, src: &BaseSrc, uri: Url) -> Result<(), gst::ErrorMessage>;
fn stop(&mut self, src: &BaseSrc) -> Result<(), gst::ErrorMessage>;
fn fill(
&mut self,
src: &BaseSrc,
offset: u64,
length: u32,
buffer: &mut gst::BufferRef,
) -> Result<(), FlowError>;
fn seek(
&mut self,
src: &BaseSrc,
start: u64,
stop: Option<u64>,
) -> Result<(), gst::ErrorMessage>;
}
struct Source {
cat: gst::DebugCategory,
uri: Mutex<(Option<Url>, bool)>,
uri_validator: Box<UriValidator>,
imp: Mutex<Box<SourceImpl>>,
push_only: bool,
}
static PROPERTIES: [Property; 1] = [Property::String(
"uri",
"URI",
"URI to read from",
None,
PropertyMutability::ReadWrite,
)];
impl Source {
fn new(source: &BaseSrc, source_info: &SourceInfo) -> Self {
let source_impl = (source_info.create_instance)(source);
Self {
cat: gst::DebugCategory::new(
"rssource",
gst::DebugColorFlags::empty(),
"Rust source base class",
),
uri: Mutex::new((None, false)),
uri_validator: source_impl.uri_validator(),
imp: Mutex::new(source_impl),
push_only: source_info.push_only,
}
}
fn class_init(klass: &mut BaseSrcClass, source_info: &SourceInfo) {
klass.set_metadata(
&source_info.long_name,
&source_info.classification,
&source_info.description,
&source_info.author,
);
let caps = gst::Caps::new_any();
let pad_template = gst::PadTemplate::new(
"src",
gst::PadDirection::Src,
gst::PadPresence::Always,
&caps,
);
klass.add_pad_template(pad_template);
klass.install_properties(&PROPERTIES);
}
fn init(element: &BaseSrc, source_info: &SourceInfo) -> Box<BaseSrcImpl<BaseSrc>> {
element.set_blocksize(4096);
let imp = Self::new(element, source_info);
Box::new(imp)
}
fn get_uri(&self, _element: &glib::Object) -> Option<String> {
let uri_storage = &self.uri.lock().unwrap();
uri_storage.0.as_ref().map(|uri| String::from(uri.as_str()))
}
fn set_uri(&self, element: &glib::Object, uri_str: Option<String>) -> Result<(), glib::Error> {
let src = element.clone().dynamic_cast::<BaseSrc>().unwrap();
let uri_storage = &mut self.uri.lock().unwrap();
gst_debug!(self.cat, obj: &src, "Setting URI {:?}", uri_str);
if uri_storage.1 {
return Err(
UriError::new(gst::URIError::BadState, "Already started".to_string()).into(),
);
}
uri_storage.0 = None;
if let Some(uri_str) = uri_str {
match Url::parse(uri_str.as_str()) {
Ok(uri) => {
try!((self.uri_validator)(&uri).map_err(|e| e.into()));
uri_storage.0 = Some(uri);
Ok(())
}
Err(err) => Err(UriError::new(
gst::URIError::BadUri,
format!("Failed to parse URI '{}': {}", uri_str, err),
)
.into()),
}
} else {
Ok(())
}
}
}
impl ObjectImpl<BaseSrc> for Source {
fn set_property(&self, obj: &glib::Object, id: u32, value: &glib::Value) {
let prop = &PROPERTIES[id as usize];
match *prop {
Property::String("uri", ..) => {
self.set_uri(obj, value.get()).unwrap();
}
_ => unimplemented!(),
}
}
fn get_property(&self, obj: &glib::Object, id: u32) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id as usize];
match *prop {
Property::String("uri", ..) => Ok(self.get_uri(obj).to_value()),
_ => unimplemented!(),
}
}
}
impl ElementImpl<BaseSrc> for Source {}
impl BaseSrcImpl<BaseSrc> for Source {
fn start(&self, src: &BaseSrc) -> bool {
gst_debug!(self.cat, obj: src, "Starting");
// Don't keep the URI locked while we call start later
let uri = match *self.uri.lock().unwrap() {
(Some(ref uri), ref mut started) => {
*started = true;
uri.clone()
}
(None, _) => {
gst_error!(self.cat, obj: src, "No URI given");
gst_element_error!(src, gst::ResourceError::OpenRead, ["No URI given"]);
return false;
}
};
let source_impl = &mut self.imp.lock().unwrap();
match source_impl.start(src, uri) {
Ok(..) => {
gst_trace!(self.cat, obj: src, "Started successfully");
true
}
Err(ref msg) => {
gst_error!(self.cat, obj: src, "Failed to start: {:?}", msg);
self.uri.lock().unwrap().1 = false;
src.post_error_message(msg);
false
}
}
}
fn stop(&self, src: &BaseSrc) -> bool {
let source_impl = &mut self.imp.lock().unwrap();
gst_debug!(self.cat, obj: src, "Stopping");
match source_impl.stop(src) {
Ok(..) => {
gst_trace!(self.cat, obj: src, "Stopped successfully");
self.uri.lock().unwrap().1 = false;
true
}
Err(ref msg) => {
gst_error!(self.cat, obj: src, "Failed to stop: {:?}", msg);
src.post_error_message(msg);
false
}
}
}
fn query(&self, src: &BaseSrc, query: &mut gst::QueryRef) -> bool {
use gst::QueryView;
match query.view_mut() {
QueryView::Scheduling(ref mut q) if self.push_only => {
q.set(gst::SchedulingFlags::SEQUENTIAL, 1, -1, 0);
q.add_scheduling_modes(&[gst::PadMode::Push]);
return true;
}
_ => (),
}
BaseSrcBase::parent_query(src, query)
}
fn fill(
&self,
src: &BaseSrc,
offset: u64,
length: u32,
buffer: &mut gst::BufferRef,
) -> gst::FlowReturn {
let source_impl = &mut self.imp.lock().unwrap();
gst_trace!(
self.cat,
obj: src,
"Filling buffer {:?} with offset {} and length {}",
buffer,
offset,
length
);
match source_impl.fill(src, offset, length, buffer) {
Ok(()) => gst::FlowReturn::Ok,
Err(flow_error) => {
gst_error!(self.cat, obj: src, "Failed to fill: {:?}", flow_error);
match flow_error {
FlowError::NotNegotiated(ref msg) | FlowError::Error(ref msg) => {
src.post_error_message(msg);
}
_ => (),
}
flow_error.into()
}
}
}
fn do_seek(&self, src: &BaseSrc, segment: &mut gst::Segment) -> bool {
let source_impl = &mut self.imp.lock().unwrap();
let segment = match segment.downcast_ref::<gst::format::Bytes>() {
None => return false,
Some(segment) => segment,
};
let start = match segment.get_start().0 {
None => return false,
Some(start) => start,
};
let stop = segment.get_stop().0;
gst_debug!(self.cat, obj: src, "Seeking to {:?}-{:?}", start, stop);
match source_impl.seek(src, start, stop) {
Ok(..) => true,
Err(ref msg) => {
gst_error!(self.cat, obj: src, "Failed to seek {:?}", msg);
src.post_error_message(msg);
false
}
}
}
fn is_seekable(&self, src: &BaseSrc) -> bool {
let source_impl = &self.imp.lock().unwrap();
source_impl.is_seekable(src)
}
fn get_size(&self, src: &BaseSrc) -> Option<u64> {
let source_impl = &self.imp.lock().unwrap();
source_impl.get_size(src)
}
}
impl URIHandlerImpl for Source {
fn get_uri(&self, element: &gst::URIHandler) -> Option<String> {
Source::get_uri(self, &element.clone().upcast())
}
fn set_uri(&self, element: &gst::URIHandler, uri: Option<String>) -> Result<(), glib::Error> {
Source::set_uri(self, &element.clone().upcast(), uri)
}
}
pub struct SourceInfo {
pub name: String,
pub long_name: String,
pub description: String,
pub classification: String,
pub author: String,
pub rank: u32,
pub create_instance: fn(&BaseSrc) -> Box<SourceImpl>,
pub protocols: Vec<String>,
pub push_only: bool,
}
struct SourceStatic {
name: String,
source_info: SourceInfo,
}
impl ImplTypeStatic<BaseSrc> for SourceStatic {
fn get_name(&self) -> &str {
self.name.as_str()
}
fn new(&self, element: &BaseSrc) -> Box<BaseSrcImpl<BaseSrc>> {
Source::init(element, &self.source_info)
}
fn class_init(&self, klass: &mut BaseSrcClass) {
Source::class_init(klass, &self.source_info);
}
fn type_init(&self, token: &TypeInitToken, type_: glib::Type) {
register_uri_handler(token, type_, self);
}
}
impl URIHandlerImplStatic<BaseSrc> for SourceStatic {
fn get_impl<'a>(&self, imp: &'a Box<BaseSrcImpl<BaseSrc>>) -> &'a URIHandlerImpl {
imp.downcast_ref::<Source>().unwrap()
}
fn get_type(&self) -> gst::URIType {
gst::URIType::Src
}
fn get_protocols(&self) -> Vec<String> {
self.source_info.protocols.clone()
}
}
pub fn source_register(
plugin: &gst::Plugin,
source_info: SourceInfo,
) -> Result<(), glib::BoolError> {
let name = source_info.name.clone();
let rank = source_info.rank;
let source_static = SourceStatic {
name: format!("Source-{}", name),
source_info,
};
let type_ = register_type(source_static);
gst::Element::register(plugin, &name, rank, type_)
}

View file

@ -1,79 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.3.2] - 2018-11-26
### Changed
- Fix various links in the README.md
- Link to the correct location for the documentation
## [0.3.1] - 2018-11-19
### Fixed
- Override vfuncs of all parent classes correctly.
## [0.3.0] - 2018-09-08
### Added
- Support for subclassing pads, ghost pads, aggregator and aggregator pads
- Support for implementing child proxy interface
- Generic catch_panic_pad_function() that allows wrapping around pad functions
for catching their panics and converting them into error messages
- More Rust-like FlowError enum that can be used to simplify implementations
### Changed
- Use ptr::NonNull in various places
- Move to standalone gobject-subclass crate and refactor for its API changes
- Removed CallbackGuard as unwinding across FFI boundaries is not undefined
behaviour anymore and will cause an immediate panic instead
- Use new Object::downcast_ref() to prevent some unneeded clones
## [0.2.1] - 2018-05-09
### Fixed
- Fix memory leak in ElementClass::add_pad_template() related to floating
reference handling.
## [0.2.0] - 2018-03-20
### Changed
- Update to gstreamer-rs 0.11
- BaseTransform::transform_caps() takes caps by reference instead of value
### Added
- Send+Sync impls for all wrapper types
## [0.1.4] - 2018-02-12
### Fixed
- Fix BaseSrc::unlock_stop() and the same in BaseSink. It was calling unlock()
instead of unlock_stop() before, making it rather useless.
## [0.1.3] - 2018-01-15
### Fixed
- Only require GStreamer >= 1.8, not >= 1.10. We didn't use any 1.10 API
anymore since quite a while
- Don't call BaseTransform::transform_ip in passthrough mode with a mutable
reference, but call a new transform_ip_passthrough with an immutable
reference. The mutable reference would've failed all mutable operations.
## [0.1.2] - 2018-01-03
### Fixed
- BaseTransform::transform_caps() caps parameter is not owned when chainging
to the parent class' implementation either
## [0.1.1] - 2018-01-03
### Fixed
- BaseTransform::transform_caps() caps parameter is not owned
## [0.1.0] - 2017-12-22
- Initial release of the `gst-plugin` crate.
[Unreleased]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.3.2...HEAD
[0.3.2]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.3.1...0.3.2
[0.3.1]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.3.0...0.3.1
[0.3.0]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.2.1...0.3.0
[0.2.1]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.2.0...0.2.1
[0.2.0]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.1.4...0.2.0
[0.1.4]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.1.3...0.1.4
[0.1.3]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.1.2...0.1.3
[0.1.2]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.1.1...0.1.2
[0.1.1]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/compare/0.1.0...0.1.1

View file

@ -1,35 +0,0 @@
[package]
name = "gst-plugin"
version = "0.4.0"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
categories = ["multimedia", "api-bindings"]
description = "Infrastructure for writing GStreamer plugins in Rust"
documentation = "https://slomo.pages.freedesktop.org/rustdocs/gst-plugin/gst_plugin"
repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/tree/master/gst-plugin"
license = "MIT/Apache-2.0"
readme = "README.md"
homepage = "https://gstreamer.freedesktop.org"
keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"]
[dependencies]
libc = "0.2"
lazy_static = "1.0"
byteorder = "1.0"
gobject-subclass = { git = "https://github.com/gtk-rs/gobject-subclass" }
glib-sys = { git = "https://github.com/gtk-rs/sys" }
gobject-sys = { git = "https://github.com/gtk-rs/sys" }
gstreamer-sys = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys" }
gstreamer-base-sys = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys" }
glib = { git = "https://github.com/gtk-rs/glib" }
gstreamer = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
gstreamer-base = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
[lib]
name = "gst_plugin"
path = "src/lib.rs"
[features]
v1_10 = ["gstreamer/v1_10", "gstreamer-base/v1_10"]
v1_12 = ["gstreamer/v1_12", "gstreamer-base/v1_12", "v1_10"]
v1_14 = ["gstreamer/v1_14", "gstreamer-base/v1_14", "v1_12"]

View file

@ -1,54 +0,0 @@
# NOTE: The canonical repository for gst-plugins-rs has moved to [freedesktop.org GitLab](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs)!
# gst-plugins-rs [![crates.io](https://img.shields.io/crates/v/gst-plugin.svg)](https://crates.io/crates/gst-plugin) [![pipeline status](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/badges/master/pipeline.svg)](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/commits/master)
Infrastructure for writing [GStreamer](https://gstreamer.freedesktop.org/)
plugins and elements in the [Rust programming
language](https://www.rust-lang.org/), and a collection of various GStreamer
plugins.
Documentation for the crate containing the infrastructure for writing
GStreamer plugins in Rust, [`gst-plugin`](gst-plugin), can be found
[here](https://slomo.pages.freedesktop.org/rustdocs/gst-plugin/gst_plugin). The whole
API builds upon the [application-side GStreamer bindings](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs).
Check the README.md of that repository also for details about how to set-up
your development environment.
Various example plugins can be found in the [GIT repository](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/). A blog post series about writing GStreamer plugins/elements can be found [here](https://coaxion.net/blog/2018/01/how-to-write-gstreamer-elements-in-rust-part-1-a-video-filter-for-converting-rgb-to-grayscale/)[2](https://coaxion.net/blog/2018/02/how-to-write-gstreamer-elements-in-rust-part-2-a-raw-audio-sine-wave-source/).
For background and motivation, see the [announcement
blogpost](https://coaxion.net/blog/2016/05/writing-gstreamer-plugins-and-elements-in-rust/)
and the follow-up blogposts
[1](https://coaxion.net/blog/2016/09/writing-gstreamer-elements-in-rust-part-2-dont-panic-we-have-better-assertions-now-and-other-updates/),
[2](https://coaxion.net/blog/2016/11/writing-gstreamer-elements-in-rust-part-3-parsing-data-from-untrusted-sources-like-its-2016/),
[3](https://coaxion.net/blog/2017/03/writing-gstreamer-elements-in-rust-part-4-logging-cows-and-plugins/).
Note that the overall implementation has changed completely since those
blogposts were written.
## LICENSE
gst-plugins-rs and all crates contained in here that are not listed below are
licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
at your option.
gst-plugin-togglerecord is licensed under the Lesser General Public License
([LICENSE-LGPLv2](LICENSE-LGPLv2)) version 2.1 or (at your option) any later
version.
GStreamer itself is licensed under the Lesser General Public License version
2.1 or (at your option) any later version:
https://www.gnu.org/licenses/lgpl-2.1.html
## Contribution
Any kinds of contributions are welcome as a pull request.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in gst-plugins-rs by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

View file

@ -1,334 +0,0 @@
// Copyright (C) 2016-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 std::cmp;
use std::collections::VecDeque;
use std::error::Error;
use std::fmt;
use std::io;
use gst;
lazy_static! {
static ref CAT: gst::DebugCategory = {
gst::DebugCategory::new(
"rsadapter",
gst::DebugColorFlags::empty(),
"Rust buffer adapter",
)
};
}
#[derive(Default, Debug)]
pub struct Adapter {
deque: VecDeque<gst::MappedBuffer<gst::buffer::Readable>>,
size: usize,
skip: usize,
scratch: Vec<u8>,
}
#[derive(Debug, PartialEq, Eq)]
pub enum AdapterError {
NotEnoughData,
}
impl fmt::Display for AdapterError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Not enough data")
}
}
impl Error for AdapterError {
fn description(&self) -> &str {
"Not enough data"
}
}
impl Adapter {
pub fn new() -> Adapter {
Adapter {
deque: VecDeque::new(),
size: 0,
skip: 0,
scratch: Vec::new(),
}
}
pub fn push(&mut self, buffer: gst::Buffer) {
let size = buffer.get_size();
self.size += size;
gst_trace!(
CAT,
"Storing {:?} of size {}, now have size {}",
buffer,
size,
self.size
);
self.deque
.push_back(buffer.into_mapped_buffer_readable().unwrap());
}
pub fn clear(&mut self) {
self.deque.clear();
self.size = 0;
self.skip = 0;
self.scratch.clear();
gst_trace!(CAT, "Cleared adapter");
}
pub fn get_available(&self) -> usize {
self.size
}
fn copy_data(
deque: &VecDeque<gst::MappedBuffer<gst::buffer::Readable>>,
skip: usize,
data: &mut [u8],
size: usize,
) {
let mut skip = skip;
let mut left = size;
let mut idx = 0;
gst_trace!(CAT, "Copying {} bytes", size);
for item in deque {
let data_item = item.as_slice();
let to_copy = cmp::min(left, data_item.len() - skip);
gst_trace!(
CAT,
"Copying {} bytes from {:?}, {} more to go",
to_copy,
item.get_buffer(),
left - to_copy
);
data[idx..idx + to_copy].copy_from_slice(&data_item[skip..skip + to_copy]);
skip = 0;
idx += to_copy;
left -= to_copy;
if left == 0 {
break;
}
}
assert_eq!(left, 0);
}
pub fn peek_into(&self, data: &mut [u8]) -> Result<(), AdapterError> {
let size = data.len();
if self.size < size {
gst_debug!(
CAT,
"Peeking {} bytes into, not enough data: have {}",
size,
self.size
);
return Err(AdapterError::NotEnoughData);
}
gst_trace!(CAT, "Peeking {} bytes into", size);
if size == 0 {
return Ok(());
}
Self::copy_data(&self.deque, self.skip, data, size);
Ok(())
}
pub fn peek(&mut self, size: usize) -> Result<&[u8], AdapterError> {
if self.size < size {
gst_debug!(
CAT,
"Peeking {} bytes, not enough data: have {}",
size,
self.size
);
return Err(AdapterError::NotEnoughData);
}
if size == 0 {
return Ok(&[]);
}
if let Some(front) = self.deque.front() {
gst_trace!(CAT, "Peeking {} bytes, subbuffer of first", size);
if front.get_size() - self.skip >= size {
return Ok(&front.as_slice()[self.skip..self.skip + size]);
}
}
gst_trace!(CAT, "Peeking {} bytes, copy to scratch", size);
self.scratch.truncate(0);
self.scratch.reserve(size);
{
let data = self.scratch.as_mut_slice();
Self::copy_data(&self.deque, self.skip, data, size);
}
Ok(self.scratch.as_slice())
}
pub fn get_buffer(&mut self, size: usize) -> Result<gst::Buffer, AdapterError> {
if self.size < size {
gst_debug!(
CAT,
"Get buffer of {} bytes, not enough data: have {}",
size,
self.size
);
return Err(AdapterError::NotEnoughData);
}
if size == 0 {
return Ok(gst::Buffer::new());
}
let sub = self.deque.front().and_then(|front| {
if front.get_size() - self.skip >= size {
gst_trace!(CAT, "Get buffer of {} bytes, subbuffer of first", size);
let new = front
.get_buffer()
.copy_region(*gst::BUFFER_COPY_ALL, self.skip, Some(size))
.unwrap();
Some(new)
} else {
None
}
});
if let Some(s) = sub {
self.flush(size).unwrap();
return Ok(s);
}
gst_trace!(CAT, "Get buffer of {} bytes, copy into new buffer", size);
let mut new = gst::Buffer::with_size(size).unwrap();
{
let mut map = new.get_mut().unwrap().map_writable().unwrap();
let data = map.as_mut_slice();
Self::copy_data(&self.deque, self.skip, data, size);
}
self.flush(size).unwrap();
Ok(new)
}
pub fn flush(&mut self, size: usize) -> Result<(), AdapterError> {
if self.size < size {
gst_debug!(
CAT,
"Flush {} bytes, not enough data: have {}",
size,
self.size
);
return Err(AdapterError::NotEnoughData);
}
if size == 0 {
return Ok(());
}
gst_trace!(CAT, "Flushing {} bytes, have {}", size, self.size);
let mut left = size;
while left > 0 {
let front_size = self.deque.front().unwrap().get_size() - self.skip;
if front_size <= left {
gst_trace!(
CAT,
"Flushing whole {:?}, {} more to go",
self.deque.front().map(|b| b.get_buffer()),
left - front_size
);
self.deque.pop_front();
self.size -= front_size;
self.skip = 0;
left -= front_size;
} else {
gst_trace!(
CAT,
"Flushing partial {:?}, {} more left",
self.deque.front().map(|b| b.get_buffer()),
front_size - left
);
self.skip += left;
self.size -= left;
left = 0;
}
}
Ok(())
}
}
impl io::Read for Adapter {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
let mut len = self.size;
if len == 0 {
return Err(io::Error::new(
io::ErrorKind::WouldBlock,
format!(
"Missing data: requesting {} but only got {}.",
buf.len(),
len
),
));
}
if buf.len() < len {
len = buf.len();
}
Self::copy_data(&self.deque, self.skip, buf, len);
self.flush(len).unwrap();
Ok(len)
}
}
#[cfg(test)]
mod tests {
use super::*;
use gst;
#[test]
fn test_push_get() {
gst::init().unwrap();
let mut a = Adapter::new();
a.push(gst::Buffer::with_size(100).unwrap());
assert_eq!(a.get_available(), 100);
a.push(gst::Buffer::with_size(20).unwrap());
assert_eq!(a.get_available(), 120);
let b = a.get_buffer(20).unwrap();
assert_eq!(a.get_available(), 100);
assert_eq!(b.get_size(), 20);
let b = a.get_buffer(90).unwrap();
assert_eq!(a.get_available(), 10);
assert_eq!(b.get_size(), 90);
a.push(gst::Buffer::with_size(20).unwrap());
assert_eq!(a.get_available(), 30);
let b = a.get_buffer(20).unwrap();
assert_eq!(a.get_available(), 10);
assert_eq!(b.get_size(), 20);
let b = a.get_buffer(10).unwrap();
assert_eq!(a.get_available(), 0);
assert_eq!(b.get_size(), 10);
let b = a.get_buffer(1);
assert_eq!(b.err().unwrap(), AdapterError::NotEnoughData);
}
}

View file

@ -1,867 +0,0 @@
// 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 std::mem;
use std::ptr;
use libc;
use glib_ffi;
use gobject_ffi;
use gst_base_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gst_base;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use element::*;
use object::*;
pub trait AggregatorImpl<T: AggregatorBase>:
AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
where
T::InstanceStructType: PanicPoison,
{
fn flush(&self, aggregator: &T) -> gst::FlowReturn {
aggregator.parent_flush()
}
fn clip(
&self,
aggregator: &T,
aggregator_pad: &gst_base::AggregatorPad,
buffer: gst::Buffer,
) -> Option<gst::Buffer> {
aggregator.parent_clip(aggregator_pad, buffer)
}
fn finish_buffer(&self, aggregator: &T, buffer: gst::Buffer) -> gst::FlowReturn {
aggregator.parent_finish_buffer(buffer)
}
fn sink_event(
&self,
aggregator: &T,
aggregator_pad: &gst_base::AggregatorPad,
event: gst::Event,
) -> bool {
aggregator.parent_sink_event(aggregator_pad, event)
}
fn sink_query(
&self,
aggregator: &T,
aggregator_pad: &gst_base::AggregatorPad,
query: &mut gst::QueryRef,
) -> bool {
aggregator.parent_sink_query(aggregator_pad, query)
}
fn src_event(&self, aggregator: &T, event: gst::Event) -> bool {
aggregator.parent_src_event(event)
}
fn src_query(&self, aggregator: &T, query: &mut gst::QueryRef) -> bool {
aggregator.parent_src_query(query)
}
fn src_activate(&self, aggregator: &T, mode: gst::PadMode, active: bool) -> bool {
aggregator.parent_src_activate(mode, active)
}
fn aggregate(&self, aggregator: &T, timeout: bool) -> gst::FlowReturn;
fn start(&self, aggregator: &T) -> bool {
aggregator.parent_start()
}
fn stop(&self, aggregator: &T) -> bool {
aggregator.parent_stop()
}
fn get_next_time(&self, aggregator: &T) -> gst::ClockTime {
aggregator.parent_get_next_time()
}
fn create_new_pad(
&self,
aggregator: &T,
templ: &gst::PadTemplate,
req_name: Option<&str>,
caps: Option<&gst::CapsRef>,
) -> Option<gst_base::AggregatorPad> {
aggregator.parent_create_new_pad(templ, req_name, caps)
}
fn update_src_caps(
&self,
aggregator: &T,
caps: &gst::CapsRef,
) -> Result<gst::Caps, gst::FlowError> {
aggregator.parent_update_src_caps(caps)
}
fn fixate_src_caps(&self, aggregator: &T, caps: gst::Caps) -> gst::Caps {
aggregator.parent_fixate_src_caps(caps)
}
fn negotiated_src_caps(&self, aggregator: &T, caps: &gst::CapsRef) -> bool {
aggregator.parent_negotiated_src_caps(caps)
}
}
any_impl!(AggregatorBase, AggregatorImpl, PanicPoison);
pub unsafe trait AggregatorBase:
IsA<gst::Element> + IsA<gst_base::Aggregator> + ObjectType
{
fn parent_flush(&self) -> gst::FlowReturn {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.flush
.map(|f| from_glib(f(self.to_glib_none().0)))
.unwrap_or(gst::FlowReturn::Ok)
}
}
fn parent_clip(
&self,
aggregator_pad: &gst_base::AggregatorPad,
buffer: gst::Buffer,
) -> Option<gst::Buffer> {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
match (*parent_klass).clip {
None => Some(buffer),
Some(ref func) => from_glib_full(func(
self.to_glib_none().0,
aggregator_pad.to_glib_none().0,
buffer.into_ptr(),
)),
}
}
}
fn parent_finish_buffer(&self, buffer: gst::Buffer) -> gst::FlowReturn {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.finish_buffer
.map(|f| from_glib(f(self.to_glib_none().0, buffer.into_ptr())))
.unwrap_or(gst::FlowReturn::Ok)
}
}
fn parent_sink_event(
&self,
aggregator_pad: &gst_base::AggregatorPad,
event: gst::Event,
) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.sink_event
.map(|f| {
from_glib(f(
self.to_glib_none().0,
aggregator_pad.to_glib_none().0,
event.into_ptr(),
))
})
.unwrap_or(false)
}
}
fn parent_sink_query(
&self,
aggregator_pad: &gst_base::AggregatorPad,
query: &mut gst::QueryRef,
) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.sink_query
.map(|f| {
from_glib(f(
self.to_glib_none().0,
aggregator_pad.to_glib_none().0,
query.as_mut_ptr(),
))
})
.unwrap_or(false)
}
}
fn parent_src_event(&self, event: gst::Event) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.src_event
.map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
.unwrap_or(false)
}
}
fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.src_query
.map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
.unwrap_or(false)
}
}
fn parent_src_activate(&self, mode: gst::PadMode, active: bool) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.src_activate
.map(|f| from_glib(f(self.to_glib_none().0, mode.to_glib(), active.to_glib())))
.unwrap_or(false)
}
}
fn parent_aggregate(&self, timeout: bool) -> gst::FlowReturn {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.aggregate
.map(|f| from_glib(f(self.to_glib_none().0, timeout.to_glib())))
.unwrap_or(gst::FlowReturn::Error)
}
}
fn parent_start(&self) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.start
.map(|f| from_glib(f(self.to_glib_none().0)))
.unwrap_or(false)
}
}
fn parent_stop(&self) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.stop
.map(|f| from_glib(f(self.to_glib_none().0)))
.unwrap_or(false)
}
}
fn parent_get_next_time(&self) -> gst::ClockTime {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.get_next_time
.map(|f| from_glib(f(self.to_glib_none().0)))
.unwrap_or(gst::CLOCK_TIME_NONE)
}
}
fn parent_create_new_pad(
&self,
templ: &gst::PadTemplate,
req_name: Option<&str>,
caps: Option<&gst::CapsRef>,
) -> Option<gst_base::AggregatorPad> {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.create_new_pad
.map(|f| {
from_glib_full(f(
self.to_glib_none().0,
templ.to_glib_none().0,
req_name.to_glib_none().0,
caps.map(|c| c.as_ptr()).unwrap_or(ptr::null()),
))
})
.unwrap_or(None)
}
}
fn parent_update_src_caps(&self, caps: &gst::CapsRef) -> Result<gst::Caps, gst::FlowError> {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.update_src_caps
.map(|f| {
let mut out_caps = ptr::null_mut();
let flow_ret =
from_glib(f(self.to_glib_none().0, caps.as_mut_ptr(), &mut out_caps));
flow_ret.into_result_value(|| from_glib_full(out_caps))
})
.unwrap_or(Err(gst::FlowError::Error))
}
}
fn parent_fixate_src_caps(&self, caps: gst::Caps) -> gst::Caps {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
match (*parent_klass).fixate_src_caps {
Some(ref f) => from_glib_full(f(self.to_glib_none().0, caps.into_ptr())),
None => caps,
}
}
}
fn parent_negotiated_src_caps(&self, caps: &gst::CapsRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorClass;
(*parent_klass)
.negotiated_src_caps
.map(|f| from_glib(f(self.to_glib_none().0, caps.as_mut_ptr())))
.unwrap_or(false)
}
}
}
pub unsafe trait AggregatorClassExt<T: AggregatorBase>
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstAggregatorClass);
klass.flush = Some(aggregator_flush::<T>);
klass.clip = Some(aggregator_clip::<T>);
klass.finish_buffer = Some(aggregator_finish_buffer::<T>);
klass.sink_event = Some(aggregator_sink_event::<T>);
klass.sink_query = Some(aggregator_sink_query::<T>);
klass.src_event = Some(aggregator_src_event::<T>);
klass.src_query = Some(aggregator_src_query::<T>);
klass.src_activate = Some(aggregator_src_activate::<T>);
klass.aggregate = Some(aggregator_aggregate::<T>);
klass.start = Some(aggregator_start::<T>);
klass.stop = Some(aggregator_stop::<T>);
klass.get_next_time = Some(aggregator_get_next_time::<T>);
klass.create_new_pad = Some(aggregator_create_new_pad::<T>);
klass.update_src_caps = Some(aggregator_update_src_caps::<T>);
klass.fixate_src_caps = Some(aggregator_fixate_src_caps::<T>);
klass.negotiated_src_caps = Some(aggregator_negotiated_src_caps::<T>);
}
}
}
glib_wrapper! {
pub struct Aggregator(Object<ElementInstanceStruct<Aggregator>>):
[gst_base::Aggregator => gst_base_ffi::GstAggregator,
gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<Aggregator>(),
}
}
unsafe impl<T: IsA<gst::Element> + IsA<gst_base::Aggregator> + ObjectType> AggregatorBase for T {}
pub type AggregatorClass = ClassStruct<Aggregator>;
// FIXME: Boilerplate
unsafe impl AggregatorClassExt<Aggregator> for AggregatorClass {}
unsafe impl ElementClassExt<Aggregator> for AggregatorClass {}
unsafe impl ObjectClassExt<Aggregator> for AggregatorClass {}
unsafe impl Send for Aggregator {}
unsafe impl Sync for Aggregator {}
#[macro_export]
macro_rules! box_aggregator_impl(
($name:ident) => {
box_element_impl!($name);
impl<T: AggregatorBase> AggregatorImpl<T> for Box<$name<T>>
where
T::InstanceStructType: PanicPoison
{
fn flush(&self, aggregator: &T) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.flush(aggregator)
}
fn clip(&self, aggregator: &T, aggregator_pad: &gst_base::AggregatorPad, buffer: gst::Buffer) -> Option<gst::Buffer> {
let imp: &$name<T> = self.as_ref();
imp.clip(aggregator, aggregator_pad, buffer)
}
fn finish_buffer(&self, aggregator: &T, buffer: gst::Buffer) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.finish_buffer(aggregator, buffer)
}
fn sink_event(&self, aggregator: &T, aggregator_pad: &gst_base::AggregatorPad, event: gst::Event) -> bool {
let imp: &$name<T> = self.as_ref();
imp.sink_event(aggregator, aggregator_pad, event)
}
fn sink_query(&self, aggregator: &T, aggregator_pad: &gst_base::AggregatorPad, query: &mut gst::QueryRef) -> bool {
let imp: &$name<T> = self.as_ref();
imp.sink_query(aggregator, aggregator_pad, query)
}
fn src_event(&self, aggregator: &T, event: gst::Event) -> bool {
let imp: &$name<T> = self.as_ref();
imp.src_event(aggregator, event)
}
fn src_query(&self, aggregator: &T, query: &mut gst::QueryRef) -> bool {
let imp: &$name<T> = self.as_ref();
imp.src_query(aggregator, query)
}
fn src_activate(&self, aggregator: &T, mode: gst::PadMode, active: bool) -> bool {
let imp: &$name<T> = self.as_ref();
imp.src_activate(aggregator, mode, active)
}
fn aggregate(&self, aggregator: &T, timeout: bool) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.aggregate(aggregator, timeout)
}
fn start(&self, aggregator: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.start(aggregator)
}
fn stop(&self, aggregator: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.stop(aggregator)
}
fn get_next_time(&self, aggregator: &T) -> gst::ClockTime {
let imp: &$name<T> = self.as_ref();
imp.get_next_time(aggregator)
}
fn create_new_pad(&self, aggregator: &T, templ: &gst::PadTemplate, req_name: Option<&str>, caps: Option<&gst::CapsRef>) -> Option<gst_base::AggregatorPad> {
let imp: &$name<T> = self.as_ref();
imp.create_new_pad(aggregator, templ, req_name, caps)
}
fn update_src_caps(&self, aggregator: &T, caps: &gst::CapsRef) -> Result<gst::Caps, gst::FlowReturn> {
let imp: &$name<T> = self.as_ref();
imp.update_src_caps(aggregator, caps)
}
fn fixate_src_caps(&self, aggregator: &T, caps: gst::Caps) -> gst::Caps {
let imp: &$name<T> = self.as_ref();
imp.fixate_src_caps(aggregator, caps)
}
fn negotiated_src_caps(&self, aggregator: &T, caps: &gst::CapsRef) -> bool {
let imp: &$name<T> = self.as_ref();
imp.negotiated_src_caps(aggregator, caps)
}
}
};
);
box_aggregator_impl!(AggregatorImpl);
impl ObjectType for Aggregator {
const NAME: &'static str = "RsAggregator";
type ParentType = gst_base::Aggregator;
type ImplType = Box<AggregatorImpl<Self>>;
type InstanceStructType = ElementInstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut AggregatorClass) {
ObjectClassExt::override_vfuncs(klass, token);
ElementClassExt::override_vfuncs(klass, token);
AggregatorClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn aggregator_flush<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), gst::FlowReturn::Error, {
imp.flush(&wrap)
})
.to_glib()
}
unsafe extern "C" fn aggregator_clip<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
aggregator_pad: *mut gst_base_ffi::GstAggregatorPad,
buffer: *mut gst_ffi::GstBuffer,
) -> *mut gst_ffi::GstBuffer
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
let ret = panic_to_error!(&wrap, &aggregator.panicked(), None, {
imp.clip(
&wrap,
&from_glib_borrow(aggregator_pad),
from_glib_full(buffer),
)
});
ret.map(|r| r.into_ptr()).unwrap_or(ptr::null_mut())
}
unsafe extern "C" fn aggregator_finish_buffer<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
buffer: *mut gst_ffi::GstBuffer,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), gst::FlowReturn::Error, {
imp.finish_buffer(&wrap, from_glib_full(buffer))
})
.to_glib()
}
unsafe extern "C" fn aggregator_sink_event<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
aggregator_pad: *mut gst_base_ffi::GstAggregatorPad,
event: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, {
imp.sink_event(
&wrap,
&from_glib_borrow(aggregator_pad),
from_glib_full(event),
)
})
.to_glib()
}
unsafe extern "C" fn aggregator_sink_query<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
aggregator_pad: *mut gst_base_ffi::GstAggregatorPad,
query: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, {
imp.sink_query(
&wrap,
&from_glib_borrow(aggregator_pad),
gst::QueryRef::from_mut_ptr(query),
)
})
.to_glib()
}
unsafe extern "C" fn aggregator_src_event<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
event: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, {
imp.src_event(&wrap, from_glib_full(event))
})
.to_glib()
}
unsafe extern "C" fn aggregator_src_query<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
query: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, {
imp.src_query(&wrap, gst::QueryRef::from_mut_ptr(query))
})
.to_glib()
}
unsafe extern "C" fn aggregator_src_activate<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
mode: gst_ffi::GstPadMode,
active: glib_ffi::gboolean,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, {
imp.src_activate(&wrap, from_glib(mode), from_glib(active))
})
.to_glib()
}
unsafe extern "C" fn aggregator_aggregate<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
timeout: glib_ffi::gboolean,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), gst::FlowReturn::Error, {
imp.aggregate(&wrap, from_glib(timeout))
})
.to_glib()
}
unsafe extern "C" fn aggregator_start<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, { imp.start(&wrap) }).to_glib()
}
unsafe extern "C" fn aggregator_stop<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, { imp.stop(&wrap) }).to_glib()
}
unsafe extern "C" fn aggregator_get_next_time<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
) -> gst_ffi::GstClockTime
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), gst::CLOCK_TIME_NONE, {
imp.get_next_time(&wrap)
})
.to_glib()
}
unsafe extern "C" fn aggregator_create_new_pad<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
templ: *mut gst_ffi::GstPadTemplate,
req_name: *const libc::c_char,
caps: *const gst_ffi::GstCaps,
) -> *mut gst_base_ffi::GstAggregatorPad
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), None, {
let req_name: Option<String> = from_glib_none(req_name);
// FIXME: Easier way to convert Option<String> to Option<&str>?
let mut _tmp = String::new();
let req_name = match req_name {
Some(n) => {
_tmp = n;
Some(_tmp.as_str())
}
None => None,
};
imp.create_new_pad(
&wrap,
&from_glib_borrow(templ),
req_name,
if caps.is_null() {
None
} else {
Some(gst::CapsRef::from_ptr(caps))
},
)
})
.to_glib_full()
}
unsafe extern "C" fn aggregator_update_src_caps<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
caps: *mut gst_ffi::GstCaps,
res: *mut *mut gst_ffi::GstCaps,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
*res = ptr::null_mut();
panic_to_error!(&wrap, &aggregator.panicked(), gst::FlowReturn::Error, {
match imp.update_src_caps(&wrap, gst::CapsRef::from_ptr(caps)) {
Ok(res_caps) => {
*res = res_caps.into_ptr();
gst::FlowReturn::Ok
}
Err(err) => err,
}
})
.to_glib()
}
unsafe extern "C" fn aggregator_fixate_src_caps<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
caps: *mut gst_ffi::GstCaps,
) -> *mut gst_ffi::GstCaps
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), gst::Caps::new_empty(), {
imp.fixate_src_caps(&wrap, from_glib_full(caps))
})
.into_ptr()
}
unsafe extern "C" fn aggregator_negotiated_src_caps<T: AggregatorBase>(
ptr: *mut gst_base_ffi::GstAggregator,
caps: *mut gst_ffi::GstCaps,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let aggregator = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator.get_impl();
panic_to_error!(&wrap, &aggregator.panicked(), false, {
imp.negotiated_src_caps(&wrap, gst::CapsRef::from_ptr(caps))
})
.to_glib()
}

View file

@ -1,190 +0,0 @@
// Copyright (C) 2018 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_base_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gst_base;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use pad::*;
pub trait AggregatorPadImpl<T: AggregatorPadBase>:
AnyImpl + ObjectImpl<T> + PadImpl<T> + Send + Sync + 'static
{
fn flush(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
aggregator_pad.parent_flush(aggregator)
}
fn skip_buffer(
&self,
aggregator_pad: &T,
aggregator: &gst_base::Aggregator,
buffer: &gst::BufferRef,
) -> bool {
aggregator_pad.parent_skip_buffer(aggregator, buffer)
}
}
any_impl!(AggregatorPadBase, AggregatorPadImpl);
pub unsafe trait AggregatorPadBase:
IsA<gst_base::AggregatorPad> + IsA<gst::Pad> + ObjectType
{
fn parent_flush(&self, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorPadClass;
(*parent_klass)
.flush
.map(|f| from_glib(f(self.to_glib_none().0, aggregator.to_glib_none().0)))
.unwrap_or(gst::FlowReturn::Ok)
}
}
fn parent_skip_buffer(
&self,
aggregator: &gst_base::Aggregator,
buffer: &gst::BufferRef,
) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorPadClass;
(*parent_klass)
.skip_buffer
.map(|f| {
from_glib(f(
self.to_glib_none().0,
aggregator.to_glib_none().0,
buffer.as_mut_ptr(),
))
})
.unwrap_or(false)
}
}
}
pub unsafe trait AggregatorPadClassExt<T: AggregatorPadBase>
where
T::ImplType: AggregatorPadImpl<T>,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstAggregatorPadClass);
klass.flush = Some(aggregator_pad_flush::<T>);
klass.skip_buffer = Some(aggregator_pad_skip_buffer::<T>);
}
}
}
glib_wrapper! {
pub struct AggregatorPad(Object<InstanceStruct<AggregatorPad>>):
[gst_base::AggregatorPad => gst_base_ffi::GstAggregatorPad,
gst::Pad => gst_ffi::GstPad,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<AggregatorPad>(),
}
}
unsafe impl<T: IsA<gst_base::AggregatorPad> + IsA<gst::Pad> + ObjectType> AggregatorPadBase for T {}
pub type AggregatorPadClass = ClassStruct<AggregatorPad>;
// FIXME: Boilerplate
unsafe impl AggregatorPadClassExt<AggregatorPad> for AggregatorPadClass {}
unsafe impl PadClassExt<AggregatorPad> for AggregatorPadClass {}
unsafe impl ObjectClassExt<AggregatorPad> for AggregatorPadClass {}
unsafe impl Send for AggregatorPad {}
unsafe impl Sync for AggregatorPad {}
#[macro_export]
macro_rules! box_aggregator_pad_impl(
($name:ident) => {
box_pad_impl!($name);
impl<T: AggregatorPadBase> AggregatorPadImpl<T> for Box<$name<T>>
{
fn flush(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.flush(aggregator_pad, aggregator)
}
fn skip_buffer(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator, buffer: &gst::BufferRef) -> bool {
let imp: &$name<T> = self.as_ref();
imp.skip_buffer(aggregator_pad, aggregator, buffer)
}
}
};
);
box_aggregator_pad_impl!(AggregatorPadImpl);
impl ObjectType for AggregatorPad {
const NAME: &'static str = "RsAggregatorPad";
type ParentType = gst_base::AggregatorPad;
type ImplType = Box<AggregatorPadImpl<Self>>;
type InstanceStructType = InstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut AggregatorPadClass) {
ObjectClassExt::override_vfuncs(klass, token);
PadClassExt::override_vfuncs(klass, token);
AggregatorPadClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn aggregator_pad_flush<T: AggregatorPadBase>(
ptr: *mut gst_base_ffi::GstAggregatorPad,
aggregator: *mut gst_base_ffi::GstAggregator,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: AggregatorPadImpl<T>,
{
floating_reference_guard!(ptr);
let aggregator_pad = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator_pad.get_impl();
imp.flush(&wrap, &from_glib_borrow(aggregator)).to_glib()
}
unsafe extern "C" fn aggregator_pad_skip_buffer<T: AggregatorPadBase>(
ptr: *mut gst_base_ffi::GstAggregatorPad,
aggregator: *mut gst_base_ffi::GstAggregator,
buffer: *mut gst_ffi::GstBuffer,
) -> glib_ffi::gboolean
where
T::ImplType: AggregatorPadImpl<T>,
{
floating_reference_guard!(ptr);
let aggregator_pad = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = aggregator_pad.get_impl();
imp.skip_buffer(
&wrap,
&from_glib_borrow(aggregator),
gst::BufferRef::from_ptr(buffer),
)
.to_glib()
}

View file

@ -1,553 +0,0 @@
// 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_base_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gst_base;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use element::*;
use object::*;
pub trait BaseSinkImpl<T: BaseSinkBase>:
AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
where
T::InstanceStructType: PanicPoison,
{
fn start(&self, _element: &T) -> bool {
true
}
fn stop(&self, _element: &T) -> bool {
true
}
fn render(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn;
fn prepare(&self, _element: &T, _buffer: &gst::BufferRef) -> gst::FlowReturn {
gst::FlowReturn::Ok
}
fn render_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
for buffer in list.iter() {
let ret = self.render(element, buffer);
if ret != gst::FlowReturn::Ok {
return ret;
}
}
gst::FlowReturn::Ok
}
fn prepare_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
for buffer in list.iter() {
let ret = self.prepare(element, buffer);
if ret != gst::FlowReturn::Ok {
return ret;
}
}
gst::FlowReturn::Ok
}
fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
element.parent_query(query)
}
fn event(&self, element: &T, event: gst::Event) -> bool {
element.parent_event(event)
}
fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
element.parent_get_caps(filter)
}
fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
element.parent_set_caps(caps)
}
fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
element.parent_fixate(caps)
}
fn unlock(&self, _element: &T) -> bool {
true
}
fn unlock_stop(&self, _element: &T) -> bool {
true
}
}
any_impl!(BaseSinkBase, BaseSinkImpl, PanicPoison);
pub unsafe trait BaseSinkBase:
IsA<gst::Element> + IsA<gst_base::BaseSink> + ObjectType
{
fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
(*parent_klass)
.query
.map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
.unwrap_or(false)
}
}
fn parent_event(&self, event: gst::Event) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
(*parent_klass)
.event
.map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
.unwrap_or(false)
}
}
fn parent_get_caps(&self, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
let filter_ptr = if let Some(filter) = filter {
filter.as_mut_ptr()
} else {
ptr::null_mut()
};
(*parent_klass)
.get_caps
.map(|f| from_glib_full(f(self.to_glib_none().0, filter_ptr)))
.unwrap_or(None)
}
}
fn parent_set_caps(&self, caps: &gst::CapsRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
(*parent_klass)
.set_caps
.map(|f| from_glib(f(self.to_glib_none().0, caps.as_mut_ptr())))
.unwrap_or(true)
}
}
fn parent_fixate(&self, caps: gst::Caps) -> gst::Caps {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
match (*parent_klass).fixate {
Some(fixate) => from_glib_full(fixate(self.to_glib_none().0, caps.into_ptr())),
None => caps,
}
}
}
}
pub unsafe trait BaseSinkClassExt<T: BaseSinkBase>
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstBaseSinkClass);
klass.start = Some(base_sink_start::<T>);
klass.stop = Some(base_sink_stop::<T>);
klass.render = Some(base_sink_render::<T>);
klass.render_list = Some(base_sink_render_list::<T>);
klass.prepare = Some(base_sink_prepare::<T>);
klass.prepare_list = Some(base_sink_prepare_list::<T>);
klass.query = Some(base_sink_query::<T>);
klass.event = Some(base_sink_event::<T>);
klass.get_caps = Some(base_sink_get_caps::<T>);
klass.set_caps = Some(base_sink_set_caps::<T>);
klass.fixate = Some(base_sink_fixate::<T>);
klass.unlock = Some(base_sink_unlock::<T>);
klass.unlock_stop = Some(base_sink_unlock_stop::<T>);
}
}
}
glib_wrapper! {
pub struct BaseSink(Object<ElementInstanceStruct<BaseSink>>):
[gst_base::BaseSink => gst_base_ffi::GstBaseSink,
gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<BaseSink>(),
}
}
unsafe impl<T: IsA<gst::Element> + IsA<gst_base::BaseSink> + ObjectType> BaseSinkBase for T {}
pub type BaseSinkClass = ClassStruct<BaseSink>;
// FIXME: Boilerplate
unsafe impl BaseSinkClassExt<BaseSink> for BaseSinkClass {}
unsafe impl ElementClassExt<BaseSink> for BaseSinkClass {}
unsafe impl ObjectClassExt<BaseSink> for BaseSinkClass {}
unsafe impl Send for BaseSink {}
unsafe impl Sync for BaseSink {}
#[macro_export]
macro_rules! box_base_sink_impl(
($name:ident) => {
box_element_impl!($name);
impl<T: BaseSinkBase> BaseSinkImpl<T> for Box<$name<T>>
where
T::InstanceStructType: PanicPoison
{
fn start(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.start(element)
}
fn stop(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.stop(element)
}
fn render(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.render(element, buffer)
}
fn prepare(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.prepare(element, buffer)
}
fn render_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.render_list(element, list)
}
fn prepare_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.prepare_list(element, list)
}
fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
let imp: &$name<T> = self.as_ref();
BaseSinkImpl::query(imp, element, query)
}
fn event(&self, element: &T, event: gst::Event) -> bool {
let imp: &$name<T> = self.as_ref();
imp.event(element, event)
}
fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
let imp: &$name<T> = self.as_ref();
imp.get_caps(element, filter)
}
fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
let imp: &$name<T> = self.as_ref();
imp.set_caps(element, caps)
}
fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
let imp: &$name<T> = self.as_ref();
imp.fixate(element, caps)
}
fn unlock(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.unlock(element)
}
fn unlock_stop(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.unlock_stop(element)
}
}
};
);
box_base_sink_impl!(BaseSinkImpl);
impl ObjectType for BaseSink {
const NAME: &'static str = "RsBaseSink";
type ParentType = gst_base::BaseSink;
type ImplType = Box<BaseSinkImpl<Self>>;
type InstanceStructType = ElementInstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut BaseSinkClass) {
ObjectClassExt::override_vfuncs(klass, token);
ElementClassExt::override_vfuncs(klass, token);
BaseSinkClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn base_sink_start<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.start(&wrap) }).to_glib()
}
unsafe extern "C" fn base_sink_stop<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.stop(&wrap) }).to_glib()
}
unsafe extern "C" fn base_sink_render<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
buffer: *mut gst_ffi::GstBuffer,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let buffer = gst::BufferRef::from_ptr(buffer);
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
imp.render(&wrap, buffer)
})
.to_glib()
}
unsafe extern "C" fn base_sink_prepare<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
buffer: *mut gst_ffi::GstBuffer,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let buffer = gst::BufferRef::from_ptr(buffer);
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
imp.prepare(&wrap, buffer)
})
.to_glib()
}
unsafe extern "C" fn base_sink_render_list<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
list: *mut gst_ffi::GstBufferList,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let list = gst::BufferListRef::from_ptr(list);
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
imp.render_list(&wrap, list)
})
.to_glib()
}
unsafe extern "C" fn base_sink_prepare_list<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
list: *mut gst_ffi::GstBufferList,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let list = gst::BufferListRef::from_ptr(list);
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
imp.prepare_list(&wrap, list)
})
.to_glib()
}
unsafe extern "C" fn base_sink_query<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
query_ptr: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let query = gst::QueryRef::from_mut_ptr(query_ptr);
panic_to_error!(&wrap, &element.panicked(), false, {
BaseSinkImpl::query(imp, &wrap, query)
})
.to_glib()
}
unsafe extern "C" fn base_sink_event<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
event_ptr: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.event(&wrap, from_glib_full(event_ptr))
})
.to_glib()
}
unsafe extern "C" fn base_sink_get_caps<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
filter: *mut gst_ffi::GstCaps,
) -> *mut gst_ffi::GstCaps
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let filter = if filter.is_null() {
None
} else {
Some(gst::CapsRef::from_ptr(filter))
};
panic_to_error!(&wrap, &element.panicked(), None, {
imp.get_caps(&wrap, filter)
})
.map(|caps| caps.into_ptr())
.unwrap_or(ptr::null_mut())
}
unsafe extern "C" fn base_sink_set_caps<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
caps: *mut gst_ffi::GstCaps,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let caps = gst::CapsRef::from_ptr(caps);
panic_to_error!(&wrap, &element.panicked(), false, {
imp.set_caps(&wrap, caps)
})
.to_glib()
}
unsafe extern "C" fn base_sink_fixate<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
caps: *mut gst_ffi::GstCaps,
) -> *mut gst_ffi::GstCaps
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let caps = from_glib_full(caps);
panic_to_error!(&wrap, &element.panicked(), gst::Caps::new_empty(), {
imp.fixate(&wrap, caps)
})
.into_ptr()
}
unsafe extern "C" fn base_sink_unlock<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.unlock(&wrap) }).to_glib()
}
unsafe extern "C" fn base_sink_unlock_stop<T: BaseSinkBase>(
ptr: *mut gst_base_ffi::GstBaseSink,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSinkImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.unlock_stop(&wrap)
})
.to_glib()
}

View file

@ -1,668 +0,0 @@
// 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_base_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gst_base;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use element::*;
use object::*;
pub trait BaseSrcImpl<T: BaseSrcBase>:
AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
where
T::InstanceStructType: PanicPoison,
{
fn start(&self, _element: &T) -> bool {
true
}
fn stop(&self, _element: &T) -> bool {
true
}
fn is_seekable(&self, _element: &T) -> bool {
false
}
fn get_size(&self, _element: &T) -> Option<u64> {
None
}
fn fill(
&self,
_element: &T,
_offset: u64,
_length: u32,
_buffer: &mut gst::BufferRef,
) -> gst::FlowReturn {
unimplemented!()
}
fn create(&self, element: &T, offset: u64, length: u32) -> Result<gst::Buffer, gst::FlowError> {
element.parent_create(offset, length)
}
fn do_seek(&self, element: &T, segment: &mut gst::Segment) -> bool {
element.parent_do_seek(segment)
}
fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
element.parent_query(query)
}
fn event(&self, element: &T, event: &gst::Event) -> bool {
element.parent_event(event)
}
fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
element.parent_get_caps(filter)
}
fn negotiate(&self, element: &T) -> bool {
element.parent_negotiate()
}
fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
element.parent_set_caps(caps)
}
fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
element.parent_fixate(caps)
}
fn unlock(&self, _element: &T) -> bool {
true
}
fn unlock_stop(&self, _element: &T) -> bool {
true
}
}
any_impl!(BaseSrcBase, BaseSrcImpl, PanicPoison);
pub unsafe trait BaseSrcBase:
IsA<gst::Element> + IsA<gst_base::BaseSrc> + ObjectType
{
fn parent_create(&self, offset: u64, length: u32) -> Result<gst::Buffer, gst::FlowError> {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
(*parent_klass)
.create
.map(|f| {
let mut buffer: *mut gst_ffi::GstBuffer = ptr::null_mut();
// FIXME: Wrong signature in -sys bindings
// https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3
let buffer_ref = &mut buffer as *mut _ as *mut gst_ffi::GstBuffer;
let ret: gst::FlowReturn =
from_glib(f(self.to_glib_none().0, offset, length, buffer_ref));
ret.into_result_value(|| from_glib_full(buffer))
})
.unwrap_or(Err(gst::FlowError::Error))
}
}
fn parent_do_seek(&self, segment: &mut gst::Segment) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
(*parent_klass)
.do_seek
.map(|f| from_glib(f(self.to_glib_none().0, segment.to_glib_none_mut().0)))
.unwrap_or(false)
}
}
fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
(*parent_klass)
.query
.map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
.unwrap_or(false)
}
}
fn parent_event(&self, event: &gst::Event) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
(*parent_klass)
.event
.map(|f| from_glib(f(self.to_glib_none().0, event.to_glib_none().0)))
.unwrap_or(false)
}
}
fn parent_get_caps(&self, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
let filter_ptr = if let Some(filter) = filter {
filter.as_mut_ptr()
} else {
ptr::null_mut()
};
(*parent_klass)
.get_caps
.map(|f| from_glib_full(f(self.to_glib_none().0, filter_ptr)))
.unwrap_or(None)
}
}
fn parent_negotiate(&self) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
(*parent_klass)
.negotiate
.map(|f| from_glib(f(self.to_glib_none().0)))
.unwrap_or(false)
}
}
fn parent_set_caps(&self, caps: &gst::CapsRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
(*parent_klass)
.set_caps
.map(|f| from_glib(f(self.to_glib_none().0, caps.as_mut_ptr())))
.unwrap_or(true)
}
}
fn parent_fixate(&self, caps: gst::Caps) -> gst::Caps {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSrcClass;
match (*parent_klass).fixate {
Some(fixate) => from_glib_full(fixate(self.to_glib_none().0, caps.into_ptr())),
None => caps,
}
}
}
}
pub unsafe trait BaseSrcClassExt<T: BaseSrcBase>
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstBaseSrcClass);
klass.start = Some(base_src_start::<T>);
klass.stop = Some(base_src_stop::<T>);
klass.is_seekable = Some(base_src_is_seekable::<T>);
klass.get_size = Some(base_src_get_size::<T>);
klass.fill = Some(base_src_fill::<T>);
klass.create = Some(base_src_create::<T>);
klass.do_seek = Some(base_src_do_seek::<T>);
klass.query = Some(base_src_query::<T>);
klass.event = Some(base_src_event::<T>);
klass.get_caps = Some(base_src_get_caps::<T>);
klass.negotiate = Some(base_src_negotiate::<T>);
klass.set_caps = Some(base_src_set_caps::<T>);
klass.fixate = Some(base_src_fixate::<T>);
klass.unlock = Some(base_src_unlock::<T>);
klass.unlock_stop = Some(base_src_unlock_stop::<T>);
}
}
}
glib_wrapper! {
pub struct BaseSrc(Object<ElementInstanceStruct<BaseSrc>>):
[gst_base::BaseSrc => gst_base_ffi::GstBaseSrc,
gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<BaseSrc>(),
}
}
unsafe impl<T: IsA<gst::Element> + IsA<gst_base::BaseSrc> + ObjectType> BaseSrcBase for T {}
pub type BaseSrcClass = ClassStruct<BaseSrc>;
// FIXME: Boilerplate
unsafe impl BaseSrcClassExt<BaseSrc> for BaseSrcClass {}
unsafe impl ElementClassExt<BaseSrc> for BaseSrcClass {}
unsafe impl ObjectClassExt<BaseSrc> for BaseSrcClass {}
unsafe impl Send for BaseSrc {}
unsafe impl Sync for BaseSrc {}
#[macro_export]
macro_rules! box_base_src_impl(
($name:ident) => {
box_element_impl!($name);
impl<T: BaseSrcBase> BaseSrcImpl<T> for Box<$name<T>>
where
T::InstanceStructType: PanicPoison
{
fn start(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.start(element)
}
fn stop(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.stop(element)
}
fn is_seekable(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.is_seekable(element)
}
fn get_size(&self, element: &T) -> Option<u64> {
let imp: &$name<T> = self.as_ref();
imp.get_size(element)
}
fn fill(
&self,
element: &T,
offset: u64,
length: u32,
buffer: &mut gst::BufferRef,
) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.fill(element, offset, length, buffer)
}
fn create(
&self,
element: &T,
offset: u64,
length: u32,
) -> Result<gst::Buffer, gst::FlowError> {
let imp: &$name<T> = self.as_ref();
imp.create(element, offset, length)
}
fn do_seek(&self, element: &T, segment: &mut gst::Segment) -> bool {
let imp: &$name<T> = self.as_ref();
imp.do_seek(element, segment)
}
fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
let imp: &$name<T> = self.as_ref();
BaseSrcImpl::query(imp, element, query)
}
fn event(&self, element: &T, event: &gst::Event) -> bool {
let imp: &$name<T> = self.as_ref();
imp.event(element, event)
}
fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
let imp: &$name<T> = self.as_ref();
imp.get_caps(element, filter)
}
fn negotiate(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.negotiate(element)
}
fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
let imp: &$name<T> = self.as_ref();
imp.set_caps(element, caps)
}
fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
let imp: &$name<T> = self.as_ref();
imp.fixate(element, caps)
}
fn unlock(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.unlock(element)
}
fn unlock_stop(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.unlock_stop(element)
}
}
};
);
box_base_src_impl!(BaseSrcImpl);
impl ObjectType for BaseSrc {
const NAME: &'static str = "RsBaseSrc";
type ParentType = gst_base::BaseSrc;
type ImplType = Box<BaseSrcImpl<Self>>;
type InstanceStructType = ElementInstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut BaseSrcClass) {
ObjectClassExt::override_vfuncs(klass, token);
ElementClassExt::override_vfuncs(klass, token);
BaseSrcClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn base_src_start<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.start(&wrap) }).to_glib()
}
unsafe extern "C" fn base_src_stop<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.stop(&wrap) }).to_glib()
}
unsafe extern "C" fn base_src_is_seekable<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.is_seekable(&wrap)
})
.to_glib()
}
unsafe extern "C" fn base_src_get_size<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
size: *mut u64,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
match imp.get_size(&wrap) {
Some(s) => {
*size = s;
true
}
None => false,
}
})
.to_glib()
}
unsafe extern "C" fn base_src_fill<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
offset: u64,
length: u32,
buffer: *mut gst_ffi::GstBuffer,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let buffer = gst::BufferRef::from_mut_ptr(buffer);
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
imp.fill(&wrap, offset, length, buffer)
})
.to_glib()
}
unsafe extern "C" fn base_src_create<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
offset: u64,
length: u32,
buffer_ptr: *mut gst_ffi::GstBuffer,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
// FIXME: Wrong signature in -sys bindings
// https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3
let buffer_ptr = buffer_ptr as *mut *mut gst_ffi::GstBuffer;
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
match imp.create(&wrap, offset, length) {
Ok(buffer) => {
*buffer_ptr = buffer.into_ptr();
gst::FlowReturn::Ok
}
Err(err) => gst::FlowReturn::from(err),
}
})
.to_glib()
}
unsafe extern "C" fn base_src_do_seek<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
segment: *mut gst_ffi::GstSegment,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.do_seek(&wrap, &mut from_glib_borrow(segment))
})
.to_glib()
}
unsafe extern "C" fn base_src_query<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
query_ptr: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let query = gst::QueryRef::from_mut_ptr(query_ptr);
panic_to_error!(&wrap, &element.panicked(), false, {
BaseSrcImpl::query(imp, &wrap, query)
})
.to_glib()
}
unsafe extern "C" fn base_src_event<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
event_ptr: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.event(&wrap, &from_glib_borrow(event_ptr))
})
.to_glib()
}
unsafe extern "C" fn base_src_get_caps<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
filter: *mut gst_ffi::GstCaps,
) -> *mut gst_ffi::GstCaps
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let filter = if filter.is_null() {
None
} else {
Some(gst::CapsRef::from_ptr(filter))
};
panic_to_error!(&wrap, &element.panicked(), None, {
imp.get_caps(&wrap, filter)
})
.map(|caps| caps.into_ptr())
.unwrap_or(ptr::null_mut())
}
unsafe extern "C" fn base_src_negotiate<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.negotiate(&wrap) }).to_glib()
}
unsafe extern "C" fn base_src_set_caps<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
caps: *mut gst_ffi::GstCaps,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let caps = gst::CapsRef::from_ptr(caps);
panic_to_error!(&wrap, &element.panicked(), false, {
imp.set_caps(&wrap, caps)
})
.to_glib()
}
unsafe extern "C" fn base_src_fixate<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
caps: *mut gst_ffi::GstCaps,
) -> *mut gst_ffi::GstCaps
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let caps = from_glib_full(caps);
panic_to_error!(&wrap, &element.panicked(), gst::Caps::new_empty(), {
imp.fixate(&wrap, caps)
})
.into_ptr()
}
unsafe extern "C" fn base_src_unlock<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.unlock(&wrap) }).to_glib()
}
unsafe extern "C" fn base_src_unlock_stop<T: BaseSrcBase>(
ptr: *mut gst_base_ffi::GstBaseSrc,
) -> glib_ffi::gboolean
where
T::ImplType: BaseSrcImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.unlock_stop(&wrap)
})
.to_glib()
}

View file

@ -1,741 +0,0 @@
// 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_base_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gst_base;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use element::*;
use object::*;
pub trait BaseTransformImpl<T: BaseTransformBase>:
AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
where
T::InstanceStructType: PanicPoison,
{
fn start(&self, _element: &T) -> bool {
true
}
fn stop(&self, _element: &T) -> bool {
true
}
fn transform_caps(
&self,
element: &T,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
) -> gst::Caps {
element.parent_transform_caps(direction, caps, filter)
}
fn fixate_caps(
&self,
element: &T,
direction: gst::PadDirection,
caps: &gst::Caps,
othercaps: gst::Caps,
) -> gst::Caps {
element.parent_fixate_caps(direction, caps, othercaps)
}
fn set_caps(&self, _element: &T, _incaps: &gst::Caps, _outcaps: &gst::Caps) -> bool {
true
}
fn accept_caps(&self, element: &T, direction: gst::PadDirection, caps: &gst::Caps) -> bool {
element.parent_accept_caps(direction, caps)
}
fn query(&self, element: &T, direction: gst::PadDirection, query: &mut gst::QueryRef) -> bool {
element.parent_query(direction, query)
}
fn transform_size(
&self,
element: &T,
direction: gst::PadDirection,
caps: &gst::Caps,
size: usize,
othercaps: &gst::Caps,
) -> Option<usize> {
element.parent_transform_size(direction, caps, size, othercaps)
}
fn get_unit_size(&self, _element: &T, _caps: &gst::Caps) -> Option<usize> {
unimplemented!();
}
fn sink_event(&self, element: &T, event: gst::Event) -> bool {
element.parent_sink_event(event)
}
fn src_event(&self, element: &T, event: gst::Event) -> bool {
element.parent_src_event(event)
}
fn transform(
&self,
_element: &T,
_inbuf: &gst::Buffer,
_outbuf: &mut gst::BufferRef,
) -> gst::FlowReturn {
unimplemented!();
}
fn transform_ip(&self, _element: &T, _buf: &mut gst::BufferRef) -> gst::FlowReturn {
unimplemented!();
}
fn transform_ip_passthrough(&self, _element: &T, _buf: &gst::BufferRef) -> gst::FlowReturn {
unimplemented!();
}
}
any_impl!(BaseTransformBase, BaseTransformImpl, PanicPoison);
pub unsafe trait BaseTransformBase:
IsA<gst::Element> + IsA<gst_base::BaseTransform> + ObjectType
where
Self::InstanceStructType: PanicPoison,
{
fn parent_transform_caps(
&self,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
) -> gst::Caps {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstBaseTransformClass;
match (*parent_klass).transform_caps {
Some(f) => from_glib_full(f(
self.to_glib_none().0,
direction.to_glib(),
caps.to_glib_none().0,
filter.to_glib_none().0,
)),
None => caps.clone(),
}
}
}
fn parent_fixate_caps(
&self,
direction: gst::PadDirection,
caps: &gst::Caps,
othercaps: gst::Caps,
) -> gst::Caps {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstBaseTransformClass;
match (*parent_klass).fixate_caps {
Some(f) => from_glib_full(f(
self.to_glib_none().0,
direction.to_glib(),
caps.to_glib_none().0,
othercaps.into_ptr(),
)),
None => othercaps,
}
}
}
fn parent_accept_caps(&self, direction: gst::PadDirection, caps: &gst::Caps) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstBaseTransformClass;
(*parent_klass)
.accept_caps
.map(|f| {
from_glib(f(
self.to_glib_none().0,
direction.to_glib(),
caps.to_glib_none().0,
))
})
.unwrap_or(false)
}
}
fn parent_query(&self, direction: gst::PadDirection, query: &mut gst::QueryRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstBaseTransformClass;
(*parent_klass)
.query
.map(|f| {
from_glib(f(
self.to_glib_none().0,
direction.to_glib(),
query.as_mut_ptr(),
))
})
.unwrap_or(false)
}
}
fn parent_transform_size(
&self,
direction: gst::PadDirection,
caps: &gst::Caps,
size: usize,
othercaps: &gst::Caps,
) -> Option<usize> {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstBaseTransformClass;
(*parent_klass)
.transform_size
.map(|f| {
let mut othersize = 0;
let res: bool = from_glib(f(
self.to_glib_none().0,
direction.to_glib(),
caps.to_glib_none().0,
size,
othercaps.to_glib_none().0,
&mut othersize,
));
if res {
Some(othersize)
} else {
None
}
})
.unwrap_or(None)
}
}
fn parent_sink_event(&self, event: gst::Event) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstBaseTransformClass;
(*parent_klass)
.sink_event
.map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
.unwrap_or(false)
}
}
fn parent_src_event(&self, event: gst::Event) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass =
(*klass).get_parent_class() as *const gst_base_ffi::GstBaseTransformClass;
(*parent_klass)
.src_event
.map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
.unwrap_or(false)
}
}
}
pub enum BaseTransformMode {
AlwaysInPlace,
NeverInPlace,
Both,
}
pub unsafe trait BaseTransformClassExt<T: BaseTransformBase>
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
fn configure(
&mut self,
mode: BaseTransformMode,
passthrough_on_same_caps: bool,
transform_ip_on_passthrough: bool,
) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstBaseTransformClass);
klass.passthrough_on_same_caps = passthrough_on_same_caps.to_glib();
klass.transform_ip_on_passthrough = transform_ip_on_passthrough.to_glib();
match mode {
BaseTransformMode::AlwaysInPlace => {
klass.transform_ip = Some(base_transform_transform_ip::<T>);
}
BaseTransformMode::NeverInPlace => {
klass.transform = Some(base_transform_transform::<T>);
}
BaseTransformMode::Both => {
klass.transform = Some(base_transform_transform::<T>);
klass.transform_ip = Some(base_transform_transform_ip::<T>);
}
}
}
}
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstBaseTransformClass);
klass.start = Some(base_transform_start::<T>);
klass.stop = Some(base_transform_stop::<T>);
klass.transform_caps = Some(base_transform_transform_caps::<T>);
klass.fixate_caps = Some(base_transform_fixate_caps::<T>);
klass.set_caps = Some(base_transform_set_caps::<T>);
klass.accept_caps = Some(base_transform_accept_caps::<T>);
klass.query = Some(base_transform_query::<T>);
klass.transform_size = Some(base_transform_transform_size::<T>);
klass.get_unit_size = Some(base_transform_get_unit_size::<T>);
klass.sink_event = Some(base_transform_sink_event::<T>);
klass.src_event = Some(base_transform_src_event::<T>);
}
}
}
glib_wrapper! {
pub struct BaseTransform(Object<ElementInstanceStruct<BaseTransform>>):
[gst_base::BaseTransform => gst_base_ffi::GstBaseTransform,
gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<BaseTransform>(),
}
}
unsafe impl<T: IsA<gst::Element> + IsA<gst_base::BaseTransform> + ObjectType> BaseTransformBase
for T
where
T::InstanceStructType: PanicPoison,
{
}
pub type BaseTransformClass = ClassStruct<BaseTransform>;
// FIXME: Boilerplate
unsafe impl BaseTransformClassExt<BaseTransform> for BaseTransformClass {}
unsafe impl ElementClassExt<BaseTransform> for BaseTransformClass {}
unsafe impl ObjectClassExt<BaseTransform> for BaseTransformClass {}
unsafe impl Send for BaseTransform {}
unsafe impl Sync for BaseTransform {}
#[macro_export]
macro_rules! box_base_transform_impl(
($name:ident) => {
box_element_impl!($name);
impl<T: BaseTransformBase> BaseTransformImpl<T> for Box<$name<T>>
where
T::InstanceStructType: PanicPoison
{
fn start(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.start(element)
}
fn stop(&self, element: &T) -> bool {
let imp: &$name<T> = self.as_ref();
imp.stop(element)
}
fn transform_caps(&self, element: &T, direction: gst::PadDirection, caps: &gst::Caps, filter: Option<&gst::Caps>) -> gst::Caps {
let imp: &$name<T> = self.as_ref();
imp.transform_caps(element, direction, caps, filter)
}
fn fixate_caps(&self, element: &T, direction: gst::PadDirection, caps: &gst::Caps, othercaps: gst::Caps) -> gst::Caps {
let imp: &$name<T> = self.as_ref();
imp.fixate_caps(element, direction, caps, othercaps)
}
fn set_caps(&self, element: &T, incaps: &gst::Caps, outcaps: &gst::Caps) -> bool {
let imp: &$name<T> = self.as_ref();
imp.set_caps(element, incaps, outcaps)
}
fn accept_caps(&self, element: &T, direction: gst::PadDirection, caps: &gst::Caps) -> bool {
let imp: &$name<T> = self.as_ref();
imp.accept_caps(element, direction, caps)
}
fn query(&self, element: &T, direction: gst::PadDirection, query: &mut gst::QueryRef) -> bool {
let imp: &$name<T> = self.as_ref();
BaseTransformImpl::query(imp, element, direction, query)
}
fn transform_size(&self, element: &T, direction: gst::PadDirection, caps: &gst::Caps, size: usize, othercaps: &gst::Caps) -> Option<usize> {
let imp: &$name<T> = self.as_ref();
imp.transform_size(element, direction, caps, size, othercaps)
}
fn get_unit_size(&self, element: &T, caps: &gst::Caps) -> Option<usize> {
let imp: &$name<T> = self.as_ref();
imp.get_unit_size(element, caps)
}
fn sink_event(&self, element: &T, event: gst::Event) -> bool {
let imp: &$name<T> = self.as_ref();
imp.sink_event(element, event)
}
fn src_event(&self, element: &T, event: gst::Event) -> bool {
let imp: &$name<T> = self.as_ref();
imp.src_event(element, event)
}
fn transform(&self, element: &T, inbuf: &gst::Buffer, outbuf: &mut gst::BufferRef) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.transform(element, inbuf, outbuf)
}
fn transform_ip(&self, element: &T, buf: &mut gst::BufferRef) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.transform_ip(element, buf)
}
fn transform_ip_passthrough(&self, element: &T, buf: &gst::BufferRef) -> gst::FlowReturn {
let imp: &$name<T> = self.as_ref();
imp.transform_ip_passthrough(element, buf)
}
}
};
);
box_base_transform_impl!(BaseTransformImpl);
impl ObjectType for BaseTransform {
const NAME: &'static str = "RsBaseTransform";
type ParentType = gst_base::BaseTransform;
type ImplType = Box<BaseTransformImpl<Self>>;
type InstanceStructType = ElementInstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut BaseTransformClass) {
ObjectClassExt::override_vfuncs(klass, token);
ElementClassExt::override_vfuncs(klass, token);
BaseTransformClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn base_transform_start<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.start(&wrap) }).to_glib()
}
unsafe extern "C" fn base_transform_stop<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, { imp.stop(&wrap) }).to_glib()
}
unsafe extern "C" fn base_transform_transform_caps<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
direction: gst_ffi::GstPadDirection,
caps: *mut gst_ffi::GstCaps,
filter: *mut gst_ffi::GstCaps,
) -> *mut gst_ffi::GstCaps
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), gst::Caps::new_empty(), {
let filter = if filter.is_null() {
None
} else {
Some(from_glib_borrow(filter))
};
imp.transform_caps(
&wrap,
from_glib(direction),
&from_glib_borrow(caps),
filter.as_ref(),
)
})
.into_ptr()
}
unsafe extern "C" fn base_transform_fixate_caps<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
direction: gst_ffi::GstPadDirection,
caps: *mut gst_ffi::GstCaps,
othercaps: *mut gst_ffi::GstCaps,
) -> *mut gst_ffi::GstCaps
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), gst::Caps::new_empty(), {
imp.fixate_caps(
&wrap,
from_glib(direction),
&from_glib_borrow(caps),
from_glib_full(othercaps),
)
})
.into_ptr()
}
unsafe extern "C" fn base_transform_set_caps<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
incaps: *mut gst_ffi::GstCaps,
outcaps: *mut gst_ffi::GstCaps,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.set_caps(&wrap, &from_glib_borrow(incaps), &from_glib_borrow(outcaps))
})
.to_glib()
}
unsafe extern "C" fn base_transform_accept_caps<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
direction: gst_ffi::GstPadDirection,
caps: *mut gst_ffi::GstCaps,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.accept_caps(&wrap, from_glib(direction), &from_glib_borrow(caps))
})
.to_glib()
}
unsafe extern "C" fn base_transform_query<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
direction: gst_ffi::GstPadDirection,
query: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
BaseTransformImpl::query(
imp,
&wrap,
from_glib(direction),
gst::QueryRef::from_mut_ptr(query),
)
})
.to_glib()
}
unsafe extern "C" fn base_transform_transform_size<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
direction: gst_ffi::GstPadDirection,
caps: *mut gst_ffi::GstCaps,
size: usize,
othercaps: *mut gst_ffi::GstCaps,
othersize: *mut usize,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
match imp.transform_size(
&wrap,
from_glib(direction),
&from_glib_borrow(caps),
size,
&from_glib_borrow(othercaps),
) {
Some(s) => {
*othersize = s;
true
}
None => false,
}
})
.to_glib()
}
unsafe extern "C" fn base_transform_get_unit_size<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
caps: *mut gst_ffi::GstCaps,
size: *mut usize,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
match imp.get_unit_size(&wrap, &from_glib_borrow(caps)) {
Some(s) => {
*size = s;
true
}
None => false,
}
})
.to_glib()
}
unsafe extern "C" fn base_transform_sink_event<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
event: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.sink_event(&wrap, from_glib_full(event))
})
.to_glib()
}
unsafe extern "C" fn base_transform_src_event<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
event: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.src_event(&wrap, from_glib_full(event))
})
.to_glib()
}
unsafe extern "C" fn base_transform_transform<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
inbuf: *mut gst_ffi::GstBuffer,
outbuf: *mut gst_ffi::GstBuffer,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
imp.transform(
&wrap,
&from_glib_borrow(inbuf),
gst::BufferRef::from_mut_ptr(outbuf),
)
})
.to_glib()
}
unsafe extern "C" fn base_transform_transform_ip<T: BaseTransformBase>(
ptr: *mut gst_base_ffi::GstBaseTransform,
buf: *mut *mut gst_ffi::GstBuffer,
) -> gst_ffi::GstFlowReturn
where
T::ImplType: BaseTransformImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
// FIXME: Wrong signature in FFI
let buf = buf as *mut gst_ffi::GstBuffer;
panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
if from_glib(gst_base_ffi::gst_base_transform_is_passthrough(ptr)) {
imp.transform_ip_passthrough(&wrap, gst::BufferRef::from_ptr(buf))
} else {
imp.transform_ip(&wrap, gst::BufferRef::from_mut_ptr(buf))
}
})
.to_glib()
}

View file

@ -1,215 +0,0 @@
// 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use element::*;
use object::*;
pub trait BinImpl<T: BinBase>:
AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
where
T::InstanceStructType: PanicPoison,
{
fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
bin.parent_add_element(element)
}
fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
bin.parent_remove_element(element)
}
fn handle_message(&self, bin: &T, message: gst::Message) {
bin.parent_handle_message(message)
}
}
any_impl!(BinBase, BinImpl, PanicPoison);
pub unsafe trait BinBase: IsA<gst::Element> + IsA<gst::Bin> + ObjectType {
fn parent_add_element(&self, element: &gst::Element) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
(*parent_klass)
.add_element
.map(|f| from_glib(f(self.to_glib_none().0, element.to_glib_none().0)))
.unwrap_or(false)
}
}
fn parent_remove_element(&self, element: &gst::Element) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
(*parent_klass)
.remove_element
.map(|f| from_glib(f(self.to_glib_none().0, element.to_glib_none().0)))
.unwrap_or(false)
}
}
fn parent_handle_message(&self, message: gst::Message) {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
(*parent_klass)
.handle_message
.map(move |f| f(self.to_glib_none().0, message.into_ptr()));
}
}
}
pub unsafe trait BinClassExt<T: BinBase>
where
T::ImplType: BinImpl<T>,
T::InstanceStructType: PanicPoison,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_ffi::GstBinClass);
klass.add_element = Some(bin_add_element::<T>);
klass.remove_element = Some(bin_remove_element::<T>);
klass.handle_message = Some(bin_handle_message::<T>);
}
}
}
glib_wrapper! {
pub struct Bin(Object<ElementInstanceStruct<Bin>>):
[gst::Bin => gst_ffi::GstBin,
gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject,
gst::ChildProxy => gst_ffi::GstChildProxy];
match fn {
get_type => || get_type::<Bin>(),
}
}
unsafe impl<T: IsA<gst::Element> + IsA<gst::Bin> + ObjectType> BinBase for T {}
pub type BinClass = ClassStruct<Bin>;
// FIXME: Boilerplate
unsafe impl BinClassExt<Bin> for BinClass {}
unsafe impl ElementClassExt<Bin> for BinClass {}
unsafe impl ObjectClassExt<Bin> for BinClass {}
unsafe impl Send for Bin {}
unsafe impl Sync for Bin {}
#[macro_export]
macro_rules! box_bin_impl(
($name:ident) => {
box_element_impl!($name);
impl<T: BinBase> BinImpl<T> for Box<$name<T>>
where
T::InstanceStructType: PanicPoison
{
fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
let imp: &$name<T> = self.as_ref();
imp.add_element(bin, element)
}
fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
let imp: &$name<T> = self.as_ref();
imp.remove_element(bin, element)
}
fn handle_message(&self, bin: &T, message: gst::Message) {
let imp: &$name<T> = self.as_ref();
imp.handle_message(bin, message)
}
}
};
);
box_bin_impl!(BinImpl);
impl ObjectType for Bin {
const NAME: &'static str = "RsBin";
type ParentType = gst::Bin;
type ImplType = Box<BinImpl<Self>>;
type InstanceStructType = ElementInstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut BinClass) {
ObjectClassExt::override_vfuncs(klass, token);
ElementClassExt::override_vfuncs(klass, token);
BinClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn bin_add_element<T: BinBase>(
ptr: *mut gst_ffi::GstBin,
element: *mut gst_ffi::GstElement,
) -> glib_ffi::gboolean
where
T::ImplType: BinImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let bin = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = bin.get_impl();
panic_to_error!(&wrap, &bin.panicked(), false, {
imp.add_element(&wrap, &from_glib_borrow(element))
})
.to_glib()
}
unsafe extern "C" fn bin_remove_element<T: BinBase>(
ptr: *mut gst_ffi::GstBin,
element: *mut gst_ffi::GstElement,
) -> glib_ffi::gboolean
where
T::ImplType: BinImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let bin = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = bin.get_impl();
panic_to_error!(&wrap, &bin.panicked(), false, {
imp.remove_element(&wrap, &from_glib_borrow(element))
})
.to_glib()
}
unsafe extern "C" fn bin_handle_message<T: BinBase>(
ptr: *mut gst_ffi::GstBin,
message: *mut gst_ffi::GstMessage,
) where
T::ImplType: BinImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let bin = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = bin.get_impl();
panic_to_error!(&wrap, &bin.panicked(), (), {
imp.handle_message(&wrap, from_glib_full(message))
});
}

View file

@ -1,140 +0,0 @@
// Copyright (C) 2016-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.
pub use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io;
pub trait ReadBytesExtShort: io::Read {
fn read_u16le(&mut self) -> io::Result<u16> {
self.read_u16::<LittleEndian>()
}
fn read_i16le(&mut self) -> io::Result<i16> {
self.read_i16::<LittleEndian>()
}
fn read_u32le(&mut self) -> io::Result<u32> {
self.read_u32::<LittleEndian>()
}
fn read_i32le(&mut self) -> io::Result<i32> {
self.read_i32::<LittleEndian>()
}
fn read_u64le(&mut self) -> io::Result<u64> {
self.read_u64::<LittleEndian>()
}
fn read_i64le(&mut self) -> io::Result<i64> {
self.read_i64::<LittleEndian>()
}
fn read_uintle(&mut self, nbytes: usize) -> io::Result<u64> {
self.read_uint::<LittleEndian>(nbytes)
}
fn read_intle(&mut self, nbytes: usize) -> io::Result<i64> {
self.read_int::<LittleEndian>(nbytes)
}
fn read_f32le(&mut self) -> io::Result<f32> {
self.read_f32::<LittleEndian>()
}
fn read_f64le(&mut self) -> io::Result<f64> {
self.read_f64::<LittleEndian>()
}
fn read_u16be(&mut self) -> io::Result<u16> {
self.read_u16::<BigEndian>()
}
fn read_i16be(&mut self) -> io::Result<i16> {
self.read_i16::<BigEndian>()
}
fn read_u32be(&mut self) -> io::Result<u32> {
self.read_u32::<BigEndian>()
}
fn read_i32be(&mut self) -> io::Result<i32> {
self.read_i32::<BigEndian>()
}
fn read_u64be(&mut self) -> io::Result<u64> {
self.read_u64::<BigEndian>()
}
fn read_i64be(&mut self) -> io::Result<i64> {
self.read_i64::<BigEndian>()
}
fn read_uintbe(&mut self, nbytes: usize) -> io::Result<u64> {
self.read_uint::<BigEndian>(nbytes)
}
fn read_intbe(&mut self, nbytes: usize) -> io::Result<i64> {
self.read_int::<BigEndian>(nbytes)
}
fn read_f32be(&mut self) -> io::Result<f32> {
self.read_f32::<BigEndian>()
}
fn read_f64be(&mut self) -> io::Result<f64> {
self.read_f64::<BigEndian>()
}
}
impl<T> ReadBytesExtShort for T where T: ReadBytesExt {}
pub trait WriteBytesExtShort: WriteBytesExt {
fn write_u16le(&mut self, n: u16) -> io::Result<()> {
self.write_u16::<LittleEndian>(n)
}
fn write_i16le(&mut self, n: i16) -> io::Result<()> {
self.write_i16::<LittleEndian>(n)
}
fn write_u32le(&mut self, n: u32) -> io::Result<()> {
self.write_u32::<LittleEndian>(n)
}
fn write_i32le(&mut self, n: i32) -> io::Result<()> {
self.write_i32::<LittleEndian>(n)
}
fn write_u64le(&mut self, n: u64) -> io::Result<()> {
self.write_u64::<LittleEndian>(n)
}
fn write_i64le(&mut self, n: i64) -> io::Result<()> {
self.write_i64::<LittleEndian>(n)
}
fn write_uintle(&mut self, n: u64, nbytes: usize) -> io::Result<()> {
self.write_uint::<LittleEndian>(n, nbytes)
}
fn write_intle(&mut self, n: i64, nbytes: usize) -> io::Result<()> {
self.write_int::<LittleEndian>(n, nbytes)
}
fn write_f32le(&mut self, n: f32) -> io::Result<()> {
self.write_f32::<LittleEndian>(n)
}
fn write_f64le(&mut self, n: f64) -> io::Result<()> {
self.write_f64::<LittleEndian>(n)
}
fn write_u16be(&mut self, n: u16) -> io::Result<()> {
self.write_u16::<BigEndian>(n)
}
fn write_i16be(&mut self, n: i16) -> io::Result<()> {
self.write_i16::<BigEndian>(n)
}
fn write_u32be(&mut self, n: u32) -> io::Result<()> {
self.write_u32::<BigEndian>(n)
}
fn write_i32be(&mut self, n: i32) -> io::Result<()> {
self.write_i32::<BigEndian>(n)
}
fn write_u64be(&mut self, n: u64) -> io::Result<()> {
self.write_u64::<BigEndian>(n)
}
fn write_i64be(&mut self, n: i64) -> io::Result<()> {
self.write_i64::<BigEndian>(n)
}
fn write_uintbe(&mut self, n: u64, nbytes: usize) -> io::Result<()> {
self.write_uint::<BigEndian>(n, nbytes)
}
fn write_intbe(&mut self, n: i64, nbytes: usize) -> io::Result<()> {
self.write_int::<BigEndian>(n, nbytes)
}
fn write_f32be(&mut self, n: f32) -> io::Result<()> {
self.write_f32::<BigEndian>(n)
}
fn write_f64be(&mut self, n: f64) -> io::Result<()> {
self.write_f64::<BigEndian>(n)
}
}
impl<T> WriteBytesExtShort for T where T: WriteBytesExt {}

View file

@ -1,194 +0,0 @@
// Copyright (C) 2018 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_ffi;
use gobject_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use libc;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
pub trait ChildProxyImpl: AnyImpl + Send + Sync + 'static {
fn get_child_by_name(&self, object: &gst::ChildProxy, name: &str) -> Option<glib::Object> {
unsafe {
let type_ = gst_ffi::gst_child_proxy_get_type();
let iface = gobject_ffi::g_type_default_interface_ref(type_)
as *mut gst_ffi::GstChildProxyInterface;
assert!(!iface.is_null());
let ret = ((*iface).get_child_by_name.as_ref().unwrap())(
object.to_glib_none().0,
name.to_glib_none().0,
);
gobject_ffi::g_type_default_interface_unref(iface as glib_ffi::gpointer);
from_glib_full(ret)
}
}
fn get_child_by_index(&self, object: &gst::ChildProxy, index: u32) -> Option<glib::Object>;
fn get_children_count(&self, object: &gst::ChildProxy) -> u32;
fn child_added(&self, object: &gst::ChildProxy, child: &glib::Object, name: &str);
fn child_removed(&self, object: &gst::ChildProxy, child: &glib::Object, name: &str);
}
any_impl!(ChildProxyImpl);
pub trait ChildProxyImplStatic<T: ObjectType>: Send + Sync + 'static {
fn get_impl<'a>(&self, imp: &'a T::ImplType) -> &'a ChildProxyImpl;
}
struct ChildProxyStatic<T: ObjectType> {
imp_static: *const ChildProxyImplStatic<T>,
}
unsafe extern "C" fn child_proxy_get_child_by_name<T: ObjectType>(
child_proxy: *mut gst_ffi::GstChildProxy,
name: *const libc::c_char,
) -> *mut gobject_ffi::GObject {
floating_reference_guard!(child_proxy);
let klass = &**(child_proxy as *const *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_child_proxy_get_type())
as *const ChildProxyStatic<T>;
let instance = &*(child_proxy as *const T::InstanceStructType);
let imp = instance.get_impl();
let imp = (*(*interface_static).imp_static).get_impl(imp);
imp.get_child_by_name(
&from_glib_borrow(child_proxy),
String::from_glib_none(name).as_str(),
)
.to_glib_full()
}
unsafe extern "C" fn child_proxy_get_child_by_index<T: ObjectType>(
child_proxy: *mut gst_ffi::GstChildProxy,
index: u32,
) -> *mut gobject_ffi::GObject {
floating_reference_guard!(child_proxy);
let klass = &**(child_proxy as *const *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_child_proxy_get_type())
as *const ChildProxyStatic<T>;
let instance = &*(child_proxy as *const T::InstanceStructType);
let imp = instance.get_impl();
let imp = (*(*interface_static).imp_static).get_impl(imp);
imp.get_child_by_index(&from_glib_borrow(child_proxy), index)
.to_glib_full()
}
unsafe extern "C" fn child_proxy_get_children_count<T: ObjectType>(
child_proxy: *mut gst_ffi::GstChildProxy,
) -> u32 {
floating_reference_guard!(child_proxy);
let klass = &**(child_proxy as *const *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_child_proxy_get_type())
as *const ChildProxyStatic<T>;
let instance = &*(child_proxy as *const T::InstanceStructType);
let imp = instance.get_impl();
let imp = (*(*interface_static).imp_static).get_impl(imp);
imp.get_children_count(&from_glib_borrow(child_proxy))
}
unsafe extern "C" fn child_proxy_child_added<T: ObjectType>(
child_proxy: *mut gst_ffi::GstChildProxy,
child: *mut gobject_ffi::GObject,
name: *const libc::c_char,
) {
floating_reference_guard!(child_proxy);
let klass = &**(child_proxy as *const *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_child_proxy_get_type())
as *const ChildProxyStatic<T>;
let instance = &*(child_proxy as *const T::InstanceStructType);
let imp = instance.get_impl();
let imp = (*(*interface_static).imp_static).get_impl(imp);
imp.child_added(
&from_glib_borrow(child_proxy),
&from_glib_borrow(child),
String::from_glib_none(name).as_str(),
)
}
unsafe extern "C" fn child_proxy_child_removed<T: ObjectType>(
child_proxy: *mut gst_ffi::GstChildProxy,
child: *mut gobject_ffi::GObject,
name: *const libc::c_char,
) {
floating_reference_guard!(child_proxy);
let klass = &**(child_proxy as *const *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_child_proxy_get_type())
as *const ChildProxyStatic<T>;
let instance = &*(child_proxy as *const T::InstanceStructType);
let imp = instance.get_impl();
let imp = (*(*interface_static).imp_static).get_impl(imp);
imp.child_removed(
&from_glib_borrow(child_proxy),
&from_glib_borrow(child),
String::from_glib_none(name).as_str(),
)
}
unsafe extern "C" fn child_proxy_init<T: ObjectType>(
iface: glib_ffi::gpointer,
iface_data: glib_ffi::gpointer,
) {
let child_proxy_iface = &mut *(iface as *mut gst_ffi::GstChildProxyInterface);
let iface_type = (*(iface as *const gobject_ffi::GTypeInterface)).g_type;
let type_ = (*(iface as *const gobject_ffi::GTypeInterface)).g_instance_type;
let klass = &mut *(gobject_ffi::g_type_class_ref(type_) as *mut ClassStruct<T>);
let interfaces_static = &mut *(klass.interfaces_static as *mut Vec<_>);
interfaces_static.push((iface_type, iface_data));
child_proxy_iface.get_child_by_name = Some(child_proxy_get_child_by_name::<T>);
child_proxy_iface.get_child_by_index = Some(child_proxy_get_child_by_index::<T>);
child_proxy_iface.get_children_count = Some(child_proxy_get_children_count::<T>);
child_proxy_iface.child_added = Some(child_proxy_child_added::<T>);
child_proxy_iface.child_removed = Some(child_proxy_child_removed::<T>);
}
pub fn register_child_proxy<T: ObjectType, I: ChildProxyImplStatic<T>>(
_: &TypeInitToken,
type_: glib::Type,
imp: &I,
) {
unsafe {
let imp = imp as &ChildProxyImplStatic<T> as *const ChildProxyImplStatic<T>;
let interface_static = Box::new(ChildProxyStatic { imp_static: imp });
let iface_info = gobject_ffi::GInterfaceInfo {
interface_init: Some(child_proxy_init::<T>),
interface_finalize: None,
interface_data: Box::into_raw(interface_static) as glib_ffi::gpointer,
};
gobject_ffi::g_type_add_interface_static(
type_.to_glib(),
gst_ffi::gst_child_proxy_get_type(),
&iface_info,
);
}
}

View file

@ -1,415 +0,0 @@
// 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 std::any::Any;
use std::mem;
use std::ptr;
use libc;
use glib_ffi;
use gobject_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use object::*;
pub trait ElementImpl<T: ElementBase>: ObjectImpl<T> + AnyImpl + Send + Sync + 'static
where
T::InstanceStructType: PanicPoison,
{
fn change_state(&self, element: &T, transition: gst::StateChange) -> gst::StateChangeReturn {
element.parent_change_state(transition)
}
fn request_new_pad(
&self,
_element: &T,
_templ: &gst::PadTemplate,
_name: Option<String>,
_caps: Option<&gst::CapsRef>,
) -> Option<gst::Pad> {
None
}
fn release_pad(&self, _element: &T, _pad: &gst::Pad) {}
fn send_event(&self, element: &T, event: gst::Event) -> bool {
element.parent_send_event(event)
}
fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
element.parent_query(query)
}
fn set_context(&self, element: &T, context: &gst::Context) {
element.parent_set_context(context)
}
}
pub trait ElementImplExt<T> {
fn catch_panic_pad_function<R, F: FnOnce(&Self, &T) -> R, G: FnOnce() -> R>(
parent: &Option<gst::Object>,
fallback: G,
f: F,
) -> R;
}
impl<S: ElementImpl<T>, T: ObjectType + glib::IsA<gst::Element> + glib::IsA<gst::Object>>
ElementImplExt<T> for S
where
T::InstanceStructType: PanicPoison,
{
fn catch_panic_pad_function<R, F: FnOnce(&Self, &T) -> R, G: FnOnce() -> R>(
parent: &Option<gst::Object>,
fallback: G,
f: F,
) -> R {
// FIXME: Does this work for element subclasses?
let element = parent.as_ref().unwrap().downcast_ref::<T>().unwrap();
let imp = element.get_impl();
let imp = Any::downcast_ref::<Box<ElementImpl<T> + 'static>>(imp).unwrap();
let imp = imp.downcast_ref::<S>().unwrap();
element.catch_panic(fallback, |element| f(imp, element))
}
}
any_impl!(ElementBase, ElementImpl, PanicPoison);
pub unsafe trait ElementBase: IsA<gst::Element> + ObjectType
where
Self::InstanceStructType: PanicPoison,
{
fn parent_change_state(&self, transition: gst::StateChange) -> gst::StateChangeReturn {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
(*parent_klass)
.change_state
.map(|f| from_glib(f(self.to_glib_none().0, transition.to_glib())))
.unwrap_or(gst::StateChangeReturn::Success)
}
}
fn parent_send_event(&self, event: gst::Event) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
(*parent_klass)
.send_event
.map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
.unwrap_or(false)
}
}
fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
(*parent_klass)
.query
.map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
.unwrap_or(false)
}
}
fn parent_set_context(&self, context: &gst::Context) {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
(*parent_klass)
.set_context
.map(|f| f(self.to_glib_none().0, context.to_glib_none().0))
.unwrap_or(())
}
}
fn catch_panic<T, F: FnOnce(&Self) -> T, G: FnOnce() -> T>(&self, fallback: G, f: F) -> T {
let panicked = unsafe { &(*self.get_instance()).panicked() };
panic_to_error!(self, panicked, fallback(), { f(self) })
}
}
pub unsafe trait ElementClassExt<T: ElementBase>
where
T::ImplType: ElementImpl<T>,
T::InstanceStructType: PanicPoison,
{
fn add_pad_template(&mut self, pad_template: gst::PadTemplate) {
unsafe {
gst_ffi::gst_element_class_add_pad_template(
self as *const Self as *mut gst_ffi::GstElementClass,
pad_template.to_glib_none().0,
);
}
}
fn set_metadata(
&mut self,
long_name: &str,
classification: &str,
description: &str,
author: &str,
) {
unsafe {
gst_ffi::gst_element_class_set_metadata(
self as *const Self as *mut gst_ffi::GstElementClass,
long_name.to_glib_none().0,
classification.to_glib_none().0,
description.to_glib_none().0,
author.to_glib_none().0,
);
}
}
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_ffi::GstElementClass);
klass.change_state = Some(element_change_state::<T>);
klass.request_new_pad = Some(element_request_new_pad::<T>);
klass.release_pad = Some(element_release_pad::<T>);
klass.send_event = Some(element_send_event::<T>);
klass.query = Some(element_query::<T>);
klass.set_context = Some(element_set_context::<T>);
}
}
}
glib_wrapper! {
pub struct Element(Object<ElementInstanceStruct<Element>>):
[gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<Element>(),
}
}
unsafe impl<T: IsA<gst::Element> + ObjectType> ElementBase for T where
Self::InstanceStructType: PanicPoison
{
}
pub type ElementClass = ClassStruct<Element>;
// FIXME: Boilerplate
unsafe impl ElementClassExt<Element> for ElementClass {}
unsafe impl ObjectClassExt<Element> for ElementClass {}
unsafe impl Send for Element {}
unsafe impl Sync for Element {}
#[macro_export]
macro_rules! box_element_impl(
($name:ident) => {
box_object_impl!($name, PanicPoison);
impl<T: ElementBase> ElementImpl<T> for Box<$name<T>>
where
T::InstanceStructType: PanicPoison
{
fn change_state(
&self,
element: &T,
transition: gst::StateChange,
) -> gst::StateChangeReturn {
let imp: &$name<T> = self.as_ref();
imp.change_state(element, transition)
}
fn request_new_pad(&self, element: &T, templ: &gst::PadTemplate, name: Option<String>, caps: Option<&gst::CapsRef>) -> Option<gst::Pad> {
let imp: &$name<T> = self.as_ref();
imp.request_new_pad(element, templ, name, caps)
}
fn release_pad(&self, element: &T, pad: &gst::Pad) {
let imp: &$name<T> = self.as_ref();
imp.release_pad(element, pad)
}
fn send_event(&self, element: &T, event: gst::Event) -> bool {
let imp: &$name<T> = self.as_ref();
imp.send_event(element, event)
}
fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
let imp: &$name<T> = self.as_ref();
ElementImpl::query(imp, element, query)
}
fn set_context(&self, element: &T, context: &gst::Context) {
let imp: &$name<T> = self.as_ref();
imp.set_context(element, context)
}
}
};
);
box_element_impl!(ElementImpl);
impl ObjectType for Element {
const NAME: &'static str = "RsElement";
type ParentType = gst::Element;
type ImplType = Box<ElementImpl<Self>>;
type InstanceStructType = ElementInstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut ElementClass) {
ObjectClassExt::override_vfuncs(klass, token);
ElementClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn element_change_state<T: ElementBase>(
ptr: *mut gst_ffi::GstElement,
transition: gst_ffi::GstStateChange,
) -> gst_ffi::GstStateChangeReturn
where
T::ImplType: ElementImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
// *Never* fail downwards state changes, this causes bugs in GStreamer
// and leads to crashes and deadlocks.
let transition = from_glib(transition);
let fallback = match transition {
gst::StateChange::PlayingToPaused
| gst::StateChange::PausedToReady
| gst::StateChange::ReadyToNull => gst::StateChangeReturn::Success,
_ => gst::StateChangeReturn::Failure,
};
panic_to_error!(&wrap, &element.panicked(), fallback, {
imp.change_state(&wrap, transition)
})
.to_glib()
}
unsafe extern "C" fn element_request_new_pad<T: ElementBase>(
ptr: *mut gst_ffi::GstElement,
templ: *mut gst_ffi::GstPadTemplate,
name: *const libc::c_char,
caps: *const gst_ffi::GstCaps,
) -> *mut gst_ffi::GstPad
where
T::ImplType: ElementImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let caps = if caps.is_null() {
None
} else {
Some(gst::CapsRef::from_ptr(caps))
};
// XXX: This is effectively unsafe but the best we can do
// See https://bugzilla.gnome.org/show_bug.cgi?id=791193
let pad = panic_to_error!(&wrap, &element.panicked(), None, {
imp.request_new_pad(&wrap, &from_glib_borrow(templ), from_glib_none(name), caps)
});
// Ensure that the pad is owned by the element now, if a pad was returned
if let Some(ref pad) = pad {
assert_eq!(
pad.get_parent(),
Some(gst::Object::from_glib_borrow(
ptr as *mut gst_ffi::GstObject
))
);
}
pad.to_glib_none().0
}
unsafe extern "C" fn element_release_pad<T: ElementBase>(
ptr: *mut gst_ffi::GstElement,
pad: *mut gst_ffi::GstPad,
) where
T::ImplType: ElementImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), (), {
imp.release_pad(&wrap, &from_glib_borrow(pad))
})
}
unsafe extern "C" fn element_send_event<T: ElementBase>(
ptr: *mut gst_ffi::GstElement,
event: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
T::ImplType: ElementImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), false, {
imp.send_event(&wrap, from_glib_full(event))
})
.to_glib()
}
unsafe extern "C" fn element_query<T: ElementBase>(
ptr: *mut gst_ffi::GstElement,
query: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
T::ImplType: ElementImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
let query = gst::QueryRef::from_mut_ptr(query);
panic_to_error!(&wrap, &element.panicked(), false, {
imp.query(&wrap, query)
})
.to_glib()
}
unsafe extern "C" fn element_set_context<T: ElementBase>(
ptr: *mut gst_ffi::GstElement,
context: *mut gst_ffi::GstContext,
) where
T::ImplType: ElementImpl<T>,
T::InstanceStructType: PanicPoison,
{
floating_reference_guard!(ptr);
let element = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = element.get_impl();
panic_to_error!(&wrap, &element.panicked(), (), {
imp.set_context(&wrap, &from_glib_borrow(context))
})
}

View file

@ -1,91 +0,0 @@
// Copyright (C) 2016-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 std::error::Error;
use std::fmt::Error as FmtError;
use std::fmt::{Display, Formatter};
use gst;
#[macro_export]
macro_rules! panic_to_error(
($element:expr, $panicked:expr, $ret:expr, $code:block) => {{
use std::panic::{self, AssertUnwindSafe};
use std::sync::atomic::Ordering;
if $panicked.load(Ordering::Relaxed) {
$element.post_error_message(&gst_error_msg!(gst::LibraryError::Failed, ["Panicked"]));
$ret
} else {
let result = panic::catch_unwind(AssertUnwindSafe(|| $code));
match result {
Ok(result) => result,
Err(err) => {
$panicked.store(true, Ordering::Relaxed);
if let Some(cause) = err.downcast_ref::<&str>() {
$element.post_error_message(&gst_error_msg!(gst::LibraryError::Failed, ["Panicked: {}", cause]));
} else if let Some(cause) = err.downcast_ref::<String>() {
$element.post_error_message(&gst_error_msg!(gst::LibraryError::Failed, ["Panicked: {}", cause]));
} else {
$element.post_error_message(&gst_error_msg!(gst::LibraryError::Failed, ["Panicked"]));
}
$ret
}
}
}
}};
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FlowError {
Flushing,
Eos,
NotNegotiated(gst::ErrorMessage),
Error(gst::ErrorMessage),
}
impl From<FlowError> for gst::FlowReturn {
fn from(err: FlowError) -> Self {
gst::FlowReturn::from(&err)
}
}
impl<'a> From<&'a FlowError> for gst::FlowReturn {
fn from(err: &FlowError) -> gst::FlowReturn {
match *err {
FlowError::Flushing => gst::FlowReturn::Flushing,
FlowError::Eos => gst::FlowReturn::Eos,
FlowError::NotNegotiated(..) => gst::FlowReturn::NotNegotiated,
FlowError::Error(..) => gst::FlowReturn::Error,
}
}
}
impl Display for FlowError {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match *self {
FlowError::Flushing | FlowError::Eos => f.write_str(self.description()),
FlowError::NotNegotiated(ref m) => {
f.write_fmt(format_args!("{}: {}", self.description(), m))
}
FlowError::Error(ref m) => f.write_fmt(format_args!("{}: {}", self.description(), m)),
}
}
}
impl Error for FlowError {
fn description(&self) -> &str {
match *self {
FlowError::Flushing => "Flushing",
FlowError::Eos => "Eos",
FlowError::NotNegotiated(..) => "Not Negotiated",
FlowError::Error(..) => "Error",
}
}
}

View file

@ -1,90 +0,0 @@
// Copyright (C) 2018 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use pad::*;
pub trait GhostPadImpl<T: GhostPadBase>:
AnyImpl + ObjectImpl<T> + PadImpl<T> + Send + Sync + 'static
{
}
any_impl!(GhostPadBase, GhostPadImpl);
pub unsafe trait GhostPadBase: IsA<gst::GhostPad> + IsA<gst::Pad> + ObjectType {}
pub unsafe trait GhostPadClassExt<T: GhostPadBase>
where
T::ImplType: GhostPadImpl<T>,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {}
}
glib_wrapper! {
pub struct GhostPad(Object<InstanceStruct<GhostPad>>):
[gst::GhostPad => gst_ffi::GstGhostPad,
gst::ProxyPad => gst_ffi::GstProxyPad,
gst::Pad => gst_ffi::GstPad,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<GhostPad>(),
}
}
unsafe impl<T: IsA<gst::GhostPad> + IsA<gst::Pad> + ObjectType> GhostPadBase for T {}
pub type GhostPadClass = ClassStruct<GhostPad>;
// FIXME: Boilerplate
unsafe impl GhostPadClassExt<GhostPad> for GhostPadClass {}
unsafe impl PadClassExt<GhostPad> for GhostPadClass {}
unsafe impl ObjectClassExt<GhostPad> for GhostPadClass {}
unsafe impl Send for GhostPad {}
unsafe impl Sync for GhostPad {}
#[macro_export]
macro_rules! box_ghost_pad_impl(
($name:ident) => {
box_pad_impl!($name);
impl<T: GhostPadBase> GhostPadImpl<T> for Box<$name<T>>
{
}
};
);
box_ghost_pad_impl!(GhostPadImpl);
impl ObjectType for GhostPad {
const NAME: &'static str = "RsGhostPad";
type ParentType = gst::GhostPad;
type ImplType = Box<GhostPadImpl<Self>>;
type InstanceStructType = InstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut GhostPadClass) {
ObjectClassExt::override_vfuncs(klass, token);
PadClassExt::override_vfuncs(klass, token);
GhostPadClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}

View file

@ -1,65 +0,0 @@
// Copyright (C) 2016-2017 Sebastian Dröge <sebastian@centricular.com>
// 2016 Luis de Bethencourt <luisbg@osg.samsung.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.
#![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
extern crate byteorder;
pub extern crate glib_sys as glib_ffi;
pub extern crate gobject_sys as gobject_ffi;
extern crate gstreamer_base_sys as gst_base_ffi;
pub extern crate gstreamer_sys as gst_ffi;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
pub extern crate glib;
#[macro_use]
pub extern crate gstreamer as gst;
extern crate gstreamer_base as gst_base;
#[macro_use]
extern crate gobject_subclass;
pub mod object;
#[macro_use]
pub mod error;
pub mod adapter;
#[macro_use]
pub mod plugin;
pub mod bytes;
#[macro_use]
pub mod element;
#[macro_use]
pub mod bin;
#[macro_use]
pub mod pipeline;
#[macro_use]
pub mod base_src;
#[macro_use]
pub mod base_sink;
#[macro_use]
pub mod base_transform;
#[cfg(any(feature = "v1_14", feature = "dox"))]
#[macro_use]
pub mod aggregator;
#[macro_use]
pub mod pad;
#[macro_use]
pub mod ghost_pad;
#[cfg(any(feature = "v1_14", feature = "dox"))]
#[macro_use]
pub mod aggregator_pad;
pub mod child_proxy;
pub mod uri_handler;

View file

@ -1,41 +0,0 @@
use std::ptr;
use std::sync::atomic::AtomicBool;
use glib::wrapper::Wrapper;
use gobject_subclass::object::*;
#[repr(C)]
pub struct ElementInstanceStruct<T: ObjectType> {
_parent: <T::ParentType as Wrapper>::GlibType,
_imp: ptr::NonNull<T::ImplType>,
_panicked: AtomicBool,
}
pub trait PanicPoison {
fn panicked(&self) -> &AtomicBool;
}
unsafe impl<T: ObjectType> Instance<T> for ElementInstanceStruct<T> {
fn parent(&self) -> &<T::ParentType as Wrapper>::GlibType {
&self._parent
}
fn get_impl(&self) -> &T::ImplType {
unsafe { self._imp.as_ref() }
}
unsafe fn set_impl(&mut self, imp: ptr::NonNull<T::ImplType>) {
self._imp = imp;
}
unsafe fn get_class(&self) -> *const ClassStruct<T> {
*(self as *const _ as *const *const ClassStruct<T>)
}
}
impl<T: ObjectType> PanicPoison for ElementInstanceStruct<T> {
fn panicked(&self) -> &AtomicBool {
&self._panicked
}
}

View file

@ -1,150 +0,0 @@
// Copyright (C) 2018 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
pub trait PadImpl<T: PadBase>: AnyImpl + ObjectImpl<T> + Send + Sync + 'static {
fn linked(&self, pad: &T, peer: &gst::Pad) {
pad.parent_linked(peer)
}
fn unlinked(&self, pad: &T, peer: &gst::Pad) {
pad.parent_unlinked(peer)
}
}
any_impl!(PadBase, PadImpl);
pub unsafe trait PadBase: IsA<gst::Pad> + ObjectType {
fn parent_linked(&self, peer: &gst::Pad) {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstPadClass;
(*parent_klass)
.linked
.map(|f| f(self.to_glib_none().0, peer.to_glib_none().0))
.unwrap_or(())
}
}
fn parent_unlinked(&self, peer: &gst::Pad) {
unsafe {
let klass = self.get_class();
let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstPadClass;
(*parent_klass)
.unlinked
.map(|f| f(self.to_glib_none().0, peer.to_glib_none().0))
.unwrap_or(())
}
}
}
pub unsafe trait PadClassExt<T: PadBase>
where
T::ImplType: PadImpl<T>,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {
unsafe {
let klass = &mut *(self as *const Self as *mut gst_ffi::GstPadClass);
klass.linked = Some(pad_linked::<T>);
klass.unlinked = Some(pad_unlinked::<T>);
}
}
}
glib_wrapper! {
pub struct Pad(Object<InstanceStruct<Pad>>):
[gst::Pad => gst_ffi::GstPad,
gst::Object => gst_ffi::GstObject];
match fn {
get_type => || get_type::<Pad>(),
}
}
unsafe impl<T: IsA<gst::Pad> + ObjectType> PadBase for T {}
pub type PadClass = ClassStruct<Pad>;
// FIXME: Boilerplate
unsafe impl PadClassExt<Pad> for PadClass {}
unsafe impl ObjectClassExt<Pad> for PadClass {}
unsafe impl Send for Pad {}
unsafe impl Sync for Pad {}
#[macro_export]
macro_rules! box_pad_impl(
($name:ident) => {
box_object_impl!($name);
impl<T: PadBase> PadImpl<T> for Box<$name<T>>
{
fn linked(&self, pad: &T, peer: &gst::Pad) {
let imp: &$name<T> = self.as_ref();
imp.linked(pad, peer)
}
fn unlinked(&self, pad: &T, peer: &gst::Pad) {
let imp: &$name<T> = self.as_ref();
imp.unlinked(pad, peer)
}
}
};
);
box_pad_impl!(PadImpl);
impl ObjectType for Pad {
const NAME: &'static str = "RsPad";
type ParentType = gst::Pad;
type ImplType = Box<PadImpl<Self>>;
type InstanceStructType = InstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut PadClass) {
ObjectClassExt::override_vfuncs(klass, token);
PadClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}
unsafe extern "C" fn pad_linked<T: PadBase>(ptr: *mut gst_ffi::GstPad, peer: *mut gst_ffi::GstPad)
where
T::ImplType: PadImpl<T>,
{
floating_reference_guard!(ptr);
let pad = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = pad.get_impl();
imp.linked(&wrap, &from_glib_borrow(peer))
}
unsafe extern "C" fn pad_unlinked<T: PadBase>(ptr: *mut gst_ffi::GstPad, peer: *mut gst_ffi::GstPad)
where
T::ImplType: PadImpl<T>,
{
floating_reference_guard!(ptr);
let pad = &*(ptr as *mut T::InstanceStructType);
let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
let imp = pad.get_impl();
imp.unlinked(&wrap, &from_glib_borrow(peer))
}

View file

@ -1,106 +0,0 @@
// 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 std::mem;
use std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
use bin::*;
use element::*;
use object::*;
pub trait PipelineImpl<T: PipelineBase>:
AnyImpl + ObjectImpl<T> + ElementImpl<T> + BinImpl<T> + Send + Sync + 'static
where
T::InstanceStructType: PanicPoison,
{
}
any_impl!(PipelineBase, PipelineImpl, PanicPoison);
pub unsafe trait PipelineBase:
IsA<gst::Element> + IsA<gst::Bin> + IsA<gst::Pipeline> + ObjectType
{
}
pub unsafe trait PipelineClassExt<T: PipelineBase>
where
T::ImplType: PipelineImpl<T>,
T::InstanceStructType: PanicPoison,
{
fn override_vfuncs(&mut self, _: &ClassInitToken) {}
}
glib_wrapper! {
pub struct Pipeline(Object<ElementInstanceStruct<Pipeline>>):
[gst::Pipeline => gst_ffi::GstPipeline,
gst::Bin => gst_ffi::GstBin,
gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject,
gst::ChildProxy => gst_ffi::GstChildProxy];
match fn {
get_type => || get_type::<Pipeline>(),
}
}
unsafe impl<T: IsA<gst::Element> + IsA<gst::Bin> + IsA<gst::Pipeline> + ObjectType> PipelineBase
for T
{
}
pub type PipelineClass = ClassStruct<Pipeline>;
// FIXME: Boilerplate
unsafe impl PipelineClassExt<Pipeline> for PipelineClass {}
unsafe impl BinClassExt<Pipeline> for PipelineClass {}
unsafe impl ElementClassExt<Pipeline> for PipelineClass {}
unsafe impl ObjectClassExt<Pipeline> for PipelineClass {}
unsafe impl Send for Pipeline {}
unsafe impl Sync for Pipeline {}
#[macro_export]
macro_rules! box_pipeline_impl(
($name:ident) => {
box_bin_impl!($name);
impl<T: PipelineBase> PipelineImpl<T> for Box<$name<T>>
where
T::InstanceStructType: PanicPoison
{
}
};
);
box_pipeline_impl!(PipelineImpl);
impl ObjectType for Pipeline {
const NAME: &'static str = "RsPipeline";
type ParentType = gst::Pipeline;
type ImplType = Box<PipelineImpl<Self>>;
type InstanceStructType = ElementInstanceStruct<Self>;
fn class_init(token: &ClassInitToken, klass: &mut PipelineClass) {
ObjectClassExt::override_vfuncs(klass, token);
ElementClassExt::override_vfuncs(klass, token);
BinClassExt::override_vfuncs(klass, token);
PipelineClassExt::override_vfuncs(klass, token);
}
object_type_fns!();
}

View file

@ -1,92 +0,0 @@
// Copyright (C) 2016-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.
#[macro_export]
macro_rules! plugin_define(
($name:expr, $description:expr, $plugin_init:ident,
$version:expr, $license:expr, $source:expr,
$package:expr, $origin:expr, $release_datetime:expr) => {
pub mod plugin_desc {
use $crate::glib::translate::{from_glib_borrow, ToGlib, from_glib};
const MAJOR_VERSION: i32 = 1;
const MINOR_VERSION: i32 = 8;
// Not using c_char here because it requires the libc crate
#[allow(non_camel_case_types)]
type c_char = i8;
#[repr(C)]
pub struct GstPluginDesc($crate::gst_ffi::GstPluginDesc);
unsafe impl Sync for GstPluginDesc {}
#[no_mangle]
#[allow(non_upper_case_globals)]
pub static gst_plugin_desc: GstPluginDesc = GstPluginDesc($crate::gst_ffi::GstPluginDesc {
major_version: MAJOR_VERSION,
minor_version: MINOR_VERSION,
name: $name as *const u8 as *const c_char,
description: $description as *const u8 as *const c_char,
plugin_init: Some(plugin_init_trampoline),
version: $version as *const u8 as *const c_char,
license: $license as *const u8 as *const c_char,
source: $source as *const u8 as *const c_char,
package: $package as *const u8 as *const c_char,
origin: $origin as *const u8 as *const c_char,
release_datetime: $release_datetime as *const u8 as *const c_char,
_gst_reserved: [0 as $crate::glib_ffi::gpointer; 4],
});
pub fn plugin_register_static() -> bool {
unsafe {
from_glib($crate::gst_ffi::gst_plugin_register_static(
MAJOR_VERSION,
MINOR_VERSION,
$name as *const u8 as *const c_char,
$description as *const u8 as *const c_char,
Some(plugin_init_trampoline),
$version as *const u8 as *const c_char,
$license as *const u8 as *const c_char,
$source as *const u8 as *const c_char,
$package as *const u8 as *const c_char,
$origin as *const u8 as *const c_char,
))
}
}
unsafe extern "C" fn plugin_init_trampoline(plugin: *mut $crate::gst_ffi::GstPlugin) -> $crate::glib_ffi::gboolean {
use std::panic::{self, AssertUnwindSafe};
let panic_result = panic::catch_unwind(AssertUnwindSafe(|| super::$plugin_init(&from_glib_borrow(plugin))));
match panic_result {
Ok(register_result) => match register_result {
Ok(_) => $crate::glib_ffi::GTRUE,
Err(err) => {
let cat = $crate::gst::DebugCategory::get("GST_PLUGIN_LOADING").unwrap();
gst_error!(cat, "Failed to register plugin: {}", err);
$crate::glib_ffi::GFALSE
}
}
Err(err) => {
let cat = $crate::gst::DebugCategory::get("GST_PLUGIN_LOADING").unwrap();
if let Some(cause) = err.downcast_ref::<&str>() {
gst_error!(cat, "Failed to initialize plugin due to panic: {}", cause);
} else if let Some(cause) = err.downcast_ref::<String>() {
gst_error!(cat, "Failed to initialize plugin due to panic: {}", cause);
} else {
gst_error!(cat, "Failed to initialize plugin due to panic");
}
$crate::glib_ffi::GFALSE
}
}
}
}
pub use plugin_desc::plugin_register_static;
};
);

View file

@ -1,148 +0,0 @@
// 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 std::ptr;
use glib_ffi;
use gobject_ffi;
use gst_ffi;
use glib;
use glib::translate::*;
use gst;
use libc;
use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;
pub trait URIHandlerImpl: AnyImpl + Send + Sync + 'static {
fn get_uri(&self, element: &gst::URIHandler) -> Option<String>;
fn set_uri(&self, element: &gst::URIHandler, uri: Option<String>) -> Result<(), glib::Error>;
}
any_impl!(URIHandlerImpl);
pub trait URIHandlerImplStatic<T: ObjectType>: Send + Sync + 'static {
fn get_impl<'a>(&self, imp: &'a T::ImplType) -> &'a URIHandlerImpl;
fn get_type(&self) -> gst::URIType;
fn get_protocols(&self) -> Vec<String>;
}
struct URIHandlerStatic<T: ObjectType> {
imp_static: *const URIHandlerImplStatic<T>,
protocols: *const Vec<*const libc::c_char>,
}
unsafe extern "C" fn uri_handler_get_type<T: ObjectType>(
type_: glib_ffi::GType,
) -> gst_ffi::GstURIType {
let klass = gobject_ffi::g_type_class_peek(type_);
let klass = &*(klass as *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_uri_handler_get_type())
as *const URIHandlerStatic<T>;
(*(*interface_static).imp_static).get_type().to_glib()
}
unsafe extern "C" fn uri_handler_get_protocols<T: ObjectType>(
type_: glib_ffi::GType,
) -> *const *const libc::c_char {
let klass = gobject_ffi::g_type_class_peek(type_);
let klass = &*(klass as *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_uri_handler_get_type())
as *const URIHandlerStatic<T>;
(*(*interface_static).protocols).as_ptr()
}
unsafe extern "C" fn uri_handler_get_uri<T: ObjectType>(
uri_handler: *mut gst_ffi::GstURIHandler,
) -> *mut libc::c_char {
floating_reference_guard!(uri_handler);
let klass = &**(uri_handler as *const *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_uri_handler_get_type())
as *const URIHandlerStatic<T>;
let instance = &*(uri_handler as *const T::InstanceStructType);
let imp = instance.get_impl();
let imp = (*(*interface_static).imp_static).get_impl(imp);
imp.get_uri(&from_glib_borrow(uri_handler)).to_glib_full()
}
unsafe extern "C" fn uri_handler_set_uri<T: ObjectType>(
uri_handler: *mut gst_ffi::GstURIHandler,
uri: *const libc::c_char,
err: *mut *mut glib_ffi::GError,
) -> glib_ffi::gboolean {
floating_reference_guard!(uri_handler);
let klass = &**(uri_handler as *const *const ClassStruct<T>);
let interface_static = klass.get_interface_static(gst_ffi::gst_uri_handler_get_type())
as *const URIHandlerStatic<T>;
let instance = &*(uri_handler as *const T::InstanceStructType);
let imp = instance.get_impl();
let imp = (*(*interface_static).imp_static).get_impl(imp);
match imp.set_uri(&from_glib_borrow(uri_handler), from_glib_none(uri)) {
Ok(()) => true.to_glib(),
Err(error) => {
*err = error.to_glib_full() as *mut _;
false.to_glib()
}
}
}
unsafe extern "C" fn uri_handler_init<T: ObjectType>(
iface: glib_ffi::gpointer,
iface_data: glib_ffi::gpointer,
) {
let uri_handler_iface = &mut *(iface as *mut gst_ffi::GstURIHandlerInterface);
let iface_type = (*(iface as *const gobject_ffi::GTypeInterface)).g_type;
let type_ = (*(iface as *const gobject_ffi::GTypeInterface)).g_instance_type;
let klass = &mut *(gobject_ffi::g_type_class_ref(type_) as *mut ClassStruct<T>);
let interfaces_static = &mut *(klass.interfaces_static as *mut Vec<_>);
interfaces_static.push((iface_type, iface_data));
uri_handler_iface.get_type = Some(uri_handler_get_type::<T>);
uri_handler_iface.get_protocols = Some(uri_handler_get_protocols::<T>);
uri_handler_iface.get_uri = Some(uri_handler_get_uri::<T>);
uri_handler_iface.set_uri = Some(uri_handler_set_uri::<T>);
}
pub fn register_uri_handler<T: ObjectType, I: URIHandlerImplStatic<T>>(
_: &TypeInitToken,
type_: glib::Type,
imp: &I,
) {
unsafe {
let mut protocols: Vec<_> = imp
.get_protocols()
.iter()
.map(|s| s.to_glib_full())
.collect();
protocols.push(ptr::null());
let imp = imp as &URIHandlerImplStatic<T> as *const URIHandlerImplStatic<T>;
let interface_static = Box::new(URIHandlerStatic {
imp_static: imp,
protocols: Box::into_raw(Box::new(protocols)),
});
let iface_info = gobject_ffi::GInterfaceInfo {
interface_init: Some(uri_handler_init::<T>),
interface_finalize: None,
interface_data: Box::into_raw(interface_static) as glib_ffi::gpointer,
};
gobject_ffi::g_type_add_interface_static(
type_.to_glib(),
gst_ffi::gst_uri_handler_get_type(),
&iface_info,
);
}
}