From d72f1f716b630bc31973fc559c5f5d82255965a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 10 Apr 2017 13:30:07 +0300 Subject: [PATCH] Port C code for the source to pure Rust --- gst-plugin-file/src/filesink.rs | 18 +- gst-plugin-file/src/filesrc.rs | 22 +- gst-plugin-file/src/lib.rs | 32 +-- gst-plugin-flv/src/flvdemux.rs | 61 ++--- gst-plugin-flv/src/lib.rs | 20 +- gst-plugin-http/src/httpsrc.rs | 19 +- gst-plugin-http/src/lib.rs | 14 +- gst-plugin/Cargo.toml | 1 + gst-plugin/build.rs | 2 +- gst-plugin/src/demuxer.rs | 14 +- gst-plugin/src/error.rs | 12 +- gst-plugin/src/lib.rs | 1 + gst-plugin/src/miniobject.rs | 2 +- gst-plugin/src/sink.rs | 8 +- gst-plugin/src/source.c | 385 -------------------------------- gst-plugin/src/source.h | 49 ---- gst-plugin/src/source.rs | 368 ++++++++++++++++++++++-------- gst-plugin/src/utils.rs | 11 - 18 files changed, 381 insertions(+), 658 deletions(-) delete mode 100644 gst-plugin/src/source.c delete mode 100644 gst-plugin/src/source.h diff --git a/gst-plugin-file/src/filesink.rs b/gst-plugin-file/src/filesink.rs index 18533d0c..e90a5ed5 100644 --- a/gst-plugin-file/src/filesink.rs +++ b/gst-plugin-file/src/filesink.rs @@ -51,11 +51,10 @@ impl FileSink { } fn validate_uri(uri: &Url) -> Result<(), UriError> { - let _ = try!(uri.to_file_path() - .or_else(|_| { - Err(UriError::new(UriErrorKind::UnsupportedProtocol, + let _ = try!(uri.to_file_path().or_else(|_| { + Err(UriError::new(UriErrorKind::UnsupportedProtocol, Some(format!("Unsupported file URI '{}'", uri.as_str())))) - })); + })); Ok(()) } @@ -69,12 +68,11 @@ impl Sink for FileSink { return Err(error_msg!(SinkError::Failure, ["Sink already started"])); } - let location = try!(uri.to_file_path() - .or_else(|_| { - error!(self.logger, "Unsupported file URI '{}'", uri.as_str()); - Err(error_msg!(SinkError::Failure, - ["Unsupported file URI '{}'", uri.as_str()])) - })); + let location = try!(uri.to_file_path().or_else(|_| { + error!(self.logger, "Unsupported file URI '{}'", uri.as_str()); + Err(error_msg!(SinkError::Failure, + ["Unsupported file URI '{}'", uri.as_str()])) + })); let file = try!(File::create(location.as_path()).or_else(|err| { diff --git a/gst-plugin-file/src/filesrc.rs b/gst-plugin-file/src/filesrc.rs index 2e7da9db..35fa8134 100644 --- a/gst-plugin-file/src/filesrc.rs +++ b/gst-plugin-file/src/filesrc.rs @@ -49,11 +49,10 @@ impl FileSrc { } fn validate_uri(uri: &Url) -> Result<(), UriError> { - let _ = try!(uri.to_file_path() - .or_else(|_| { - Err(UriError::new(UriErrorKind::UnsupportedProtocol, + let _ = try!(uri.to_file_path().or_else(|_| { + Err(UriError::new(UriErrorKind::UnsupportedProtocol, Some(format!("Unsupported file URI '{}'", uri.as_str())))) - })); + })); Ok(()) } @@ -68,9 +67,7 @@ impl Source for FileSrc { fn get_size(&self) -> Option { if let StreamingState::Started { ref file, .. } = self.streaming_state { - file.metadata() - .ok() - .map(|m| m.len()) + file.metadata().ok().map(|m| m.len()) } else { None } @@ -81,12 +78,11 @@ impl Source for FileSrc { return Err(error_msg!(SourceError::Failure, ["Source already started"])); } - let location = try!(uri.to_file_path() - .or_else(|_| { - error!(self.logger, "Unsupported file URI '{}'", uri.as_str()); - Err(error_msg!(SourceError::Failure, - ["Unsupported file URI '{}'", uri.as_str()])) - })); + let location = try!(uri.to_file_path().or_else(|_| { + error!(self.logger, "Unsupported file URI '{}'", uri.as_str()); + Err(error_msg!(SourceError::Failure, + ["Unsupported file URI '{}'", uri.as_str()])) + })); let file = try!(File::open(location.as_path()).or_else(|err| { error!(self.logger, diff --git a/gst-plugin-file/src/lib.rs b/gst-plugin-file/src/lib.rs index d118bbd9..8b430262 100644 --- a/gst-plugin-file/src/lib.rs +++ b/gst-plugin-file/src/lib.rs @@ -26,29 +26,29 @@ use filesink::FileSink; fn plugin_init(plugin: &Plugin) -> bool { source_register(plugin, - &SourceInfo { - name: "rsfilesrc", - long_name: "File Source", - description: "Reads local files", - classification: "Source/File", - author: "Sebastian Dröge ", + SourceInfo { + name: "rsfilesrc".into(), + long_name: "File Source".into(), + description: "Reads local files".into(), + classification: "Source/File".into(), + author: "Sebastian Dröge ".into(), rank: 256 + 100, create_instance: FileSrc::new_boxed, - protocols: "file", + protocols: vec!["file".into()], push_only: false, }); sink_register(plugin, &SinkInfo { - name: "rsfilesink", - long_name: "File Sink", - description: "Writes to local files", - classification: "Sink/File", - author: "Luis de Bethencourt ", - rank: 256 + 100, - create_instance: FileSink::new_boxed, - protocols: "file", - }); + name: "rsfilesink", + long_name: "File Sink", + description: "Writes to local files", + classification: "Sink/File", + author: "Luis de Bethencourt ", + rank: 256 + 100, + create_instance: FileSink::new_boxed, + protocols: "file", + }); true } diff --git a/gst-plugin-flv/src/flvdemux.rs b/gst-plugin-flv/src/flvdemux.rs index 16affa39..75470004 100644 --- a/gst-plugin-flv/src/flvdemux.rs +++ b/gst-plugin-flv/src/flvdemux.rs @@ -160,10 +160,10 @@ impl AudioFormat { &[("layout", &"interleaved".into()), ("format", &if self.width == 8 { - "U8".into() - } else { - "S16LE".into() - })])) + "U8".into() + } else { + "S16LE".into() + })])) } else { None } @@ -236,14 +236,17 @@ impl AudioFormat { }; if self.rate != 0 { - caps.as_mut() - .map(|c| c.get_mut().unwrap().set_simple(&[("rate", &(self.rate as i32).into())])); + caps.as_mut().map(|c| { + c.get_mut().unwrap().set_simple(&[("rate", + &(self.rate as i32).into())]) + }); } if self.channels != 0 { - caps.as_mut() - .map(|c| { - c.get_mut().unwrap().set_simple(&[("channels", &(self.channels as i32).into())]) - }); + caps.as_mut().map(|c| { + c.get_mut().unwrap().set_simple(&[("channels", + &(self.channels as i32) + .into())]) + }); } caps @@ -342,23 +345,27 @@ impl VideoFormat { if let (Some(width), Some(height)) = (self.width, self.height) { caps.as_mut().map(|c| { - c.get_mut().unwrap().set_simple(&[("width", &(width as i32).into()), - ("height", &(height as i32).into())]) - }); + c.get_mut().unwrap().set_simple(&[("width", + &(width as i32).into()), + ("height", + &(height as i32).into())]) + }); } if let Some(par) = self.pixel_aspect_ratio { if *par.numer() != 0 && par.numer() != par.denom() { caps.as_mut().map(|c| { - c.get_mut().unwrap().set_simple(&[("pixel-aspect-ratio", &par.into())]) - }); + c.get_mut().unwrap().set_simple(&[("pixel-aspect-ratio", + &par.into())]) + }); } } if let Some(fps) = self.framerate { if *fps.numer() != 0 { - caps.as_mut() - .map(|c| c.get_mut().unwrap().set_simple(&[("framerate", &fps.into())])); + caps.as_mut().map(|c| { + c.get_mut().unwrap().set_simple(&[("framerate", &fps.into())]) + }); } } @@ -538,16 +545,14 @@ impl FlvDemux { let mut streams = Vec::new(); if audio_changed { - if let Some(caps) = streaming_state.audio - .as_ref() - .and_then(|a| a.to_caps()) { + if let Some(caps) = + streaming_state.audio.as_ref().and_then(|a| a.to_caps()) { streams.push(Stream::new(AUDIO_STREAM_ID, caps, String::from("audio"))); } } if video_changed { - if let Some(caps) = streaming_state.video - .as_ref() - .and_then(|v| v.to_caps()) { + if let Some(caps) = + streaming_state.video.as_ref().and_then(|v| v.to_caps()) { streams.push(Stream::new(VIDEO_STREAM_ID, caps, String::from("video"))); } } @@ -692,9 +697,8 @@ impl FlvDemux { self.adapter.flush(offset as usize).unwrap(); } - let mut buffer = self.adapter - .get_buffer((tag_header.data_size - 1 - offset) as usize) - .unwrap(); + let mut buffer = + self.adapter.get_buffer((tag_header.data_size - 1 - offset) as usize).unwrap(); { let buffer = buffer.get_mut().unwrap(); @@ -847,9 +851,8 @@ impl FlvDemux { self.adapter.flush(offset as usize).unwrap(); } - let mut buffer = self.adapter - .get_buffer((tag_header.data_size - 1 - offset) as usize) - .unwrap(); + let mut buffer = + self.adapter.get_buffer((tag_header.data_size - 1 - offset) as usize).unwrap(); { let buffer = buffer.get_mut().unwrap(); diff --git a/gst-plugin-flv/src/lib.rs b/gst-plugin-flv/src/lib.rs index 1789cd41..d43e785e 100644 --- a/gst-plugin-flv/src/lib.rs +++ b/gst-plugin-flv/src/lib.rs @@ -28,16 +28,16 @@ use flvdemux::FlvDemux; fn plugin_init(plugin: &Plugin) -> bool { demuxer_register(plugin, &DemuxerInfo { - name: "rsflvdemux", - long_name: "FLV Demuxer", - description: "Demuxes FLV Streams", - classification: "Codec/Demuxer", - author: "Sebastian Dröge ", - rank: 256 + 100, - create_instance: FlvDemux::new_boxed, - input_caps: &Caps::new_simple("video/x-flv", &[]), - output_caps: &Caps::new_any(), - }); + name: "rsflvdemux", + long_name: "FLV Demuxer", + description: "Demuxes FLV Streams", + classification: "Codec/Demuxer", + author: "Sebastian Dröge ", + rank: 256 + 100, + create_instance: FlvDemux::new_boxed, + input_caps: &Caps::new_simple("video/x-flv", &[]), + output_caps: &Caps::new_any(), + }); true } diff --git a/gst-plugin-http/src/httpsrc.rs b/gst-plugin-http/src/httpsrc.rs index 7e1ac95d..c9478c34 100644 --- a/gst-plugin-http/src/httpsrc.rs +++ b/gst-plugin-http/src/httpsrc.rs @@ -91,8 +91,7 @@ impl HttpSrc { let size = response.headers().get().map(|&ContentLength(cl)| cl + start); let accept_byte_ranges = if let Some(&AcceptRanges(ref ranges)) = - response.headers() - .get() { + response.headers().get() { ranges.iter().any(|u| *u == RangeUnit::Bytes) } else { false @@ -117,14 +116,14 @@ impl HttpSrc { debug!(self.logger, "Request successful: {:?}", response); Ok(StreamingState::Started { - uri: uri, - response: response, - seekable: seekable, - position: 0, - size: size, - start: start, - stop: stop, - }) + uri: uri, + response: response, + seekable: seekable, + position: 0, + size: size, + start: start, + stop: stop, + }) } } diff --git a/gst-plugin-http/src/lib.rs b/gst-plugin-http/src/lib.rs index 5d2a2c03..6a9163f2 100644 --- a/gst-plugin-http/src/lib.rs +++ b/gst-plugin-http/src/lib.rs @@ -24,15 +24,15 @@ use httpsrc::HttpSrc; fn plugin_init(plugin: &Plugin) -> bool { source_register(plugin, - &SourceInfo { - name: "rshttpsrc", - long_name: "HTTP/HTTPS Source", - description: "Reads HTTP/HTTPS streams", - classification: "Source/File", - author: "Sebastian Dröge ", + SourceInfo { + name: "rshttpsrc".into(), + long_name: "HTTP/HTTPS Source".into(), + description: "Reads HTTP/HTTPS streams".into(), + classification: "Source/File".into(), + author: "Sebastian Dröge ".into(), rank: 256 + 100, create_instance: HttpSrc::new_boxed, - protocols: "http:https", + protocols: vec!["http".into(), "https".into()], push_only: true, }); diff --git a/gst-plugin/Cargo.toml b/gst-plugin/Cargo.toml index e4295ae1..140668ca 100644 --- a/gst-plugin/Cargo.toml +++ b/gst-plugin/Cargo.toml @@ -17,6 +17,7 @@ num-rational = { version = "0.1", default-features = false, features = [] } glib-sys = { git = "https://github.com/gtk-rs/sys.git" } gobject-sys = { git = "https://github.com/gtk-rs/sys.git" } gstreamer-sys = { git = "https://github.com/sdroege/gstreamer-sys.git", features = ["v1_10"] } +gstreamer-base-sys = { git = "https://github.com/sdroege/gstreamer-sys.git", features = ["v1_10"] } derivative = "1.0" [build-dependencies] diff --git a/gst-plugin/build.rs b/gst-plugin/build.rs index 46ad8d28..f550a9ea 100644 --- a/gst-plugin/build.rs +++ b/gst-plugin/build.rs @@ -14,7 +14,7 @@ fn main() { let gstbase = pkg_config::probe_library("gstreamer-base-1.0").unwrap(); let includes = [gstreamer.include_paths, gstbase.include_paths]; - let files = ["src/source.c", "src/sink.c", "src/demuxer.c"]; + let files = ["src/sink.c", "src/demuxer.c"]; let mut config = gcc::Config::new(); config.include("src"); diff --git a/gst-plugin/src/demuxer.rs b/gst-plugin/src/demuxer.rs index 628a1fea..1608fb47 100644 --- a/gst-plugin/src/demuxer.rs +++ b/gst-plugin/src/demuxer.rs @@ -247,7 +247,7 @@ impl DemuxerWrapper { } } - fn handle_buffer(&self, buffer: GstRc) -> GstFlowReturn { + fn handle_buffer(&self, buffer: GstRc) -> gst::GstFlowReturn { extern "C" { fn gst_rs_demuxer_stream_eos(raw: *mut gst::GstElement, index: u32); fn gst_rs_demuxer_add_stream(raw: *mut gst::GstElement, @@ -262,7 +262,7 @@ impl DemuxerWrapper { fn gst_rs_demuxer_stream_push_buffer(raw: *mut gst::GstElement, index: u32, buffer: *mut gst::GstBuffer) - -> GstFlowReturn; + -> gst::GstFlowReturn; }; let mut res = { @@ -290,7 +290,7 @@ impl DemuxerWrapper { match res { HandleBufferResult::NeedMoreData => { - return GstFlowReturn::Ok; + return gst::GST_FLOW_OK; } HandleBufferResult::StreamAdded(stream) => { let stream_id_cstr = CString::new(stream.stream_id.as_bytes()).unwrap(); @@ -323,7 +323,7 @@ impl DemuxerWrapper { let flow_ret = unsafe { gst_rs_demuxer_stream_push_buffer(self.raw, index, buffer.into_ptr()) }; - if flow_ret != GstFlowReturn::Ok { + if flow_ret != gst::GST_FLOW_OK { return flow_ret; } } @@ -334,7 +334,7 @@ impl DemuxerWrapper { gst_rs_demuxer_stream_eos(self.raw, index); } - return GstFlowReturn::Eos; + return gst::GST_FLOW_EOS; } HandleBufferResult::Again => { // nothing, just call again @@ -483,10 +483,10 @@ pub unsafe extern "C" fn demuxer_seek(ptr: *mut DemuxerWrapper, #[no_mangle] pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper, buffer: *mut gst::GstBuffer) - -> GstFlowReturn { + -> gst::GstFlowReturn { let wrap: &mut DemuxerWrapper = &mut *ptr; - panic_to_error!(wrap, GstFlowReturn::Error, { + panic_to_error!(wrap, gst::GST_FLOW_ERROR, { let buffer = GstRc::new_from_owned_ptr(buffer); wrap.handle_buffer(buffer) }) diff --git a/gst-plugin/src/error.rs b/gst-plugin/src/error.rs index 9655fa7a..adf81719 100644 --- a/gst-plugin/src/error.rs +++ b/gst-plugin/src/error.rs @@ -15,8 +15,6 @@ use std::borrow::Cow; use url::Url; -use utils::*; - use glib; use gst; @@ -145,12 +143,12 @@ pub enum FlowError { } impl FlowError { - pub fn to_native(&self) -> GstFlowReturn { + pub fn to_native(&self) -> gst::GstFlowReturn { match *self { - FlowError::Flushing => GstFlowReturn::Flushing, - FlowError::Eos => GstFlowReturn::Eos, - FlowError::NotNegotiated(..) => GstFlowReturn::NotNegotiated, - FlowError::Error(..) => GstFlowReturn::Error, + FlowError::Flushing => gst::GST_FLOW_FLUSHING, + FlowError::Eos => gst::GST_FLOW_EOS, + FlowError::NotNegotiated(..) => gst::GST_FLOW_NOT_NEGOTIATED, + FlowError::Error(..) => gst::GST_FLOW_ERROR, } } } diff --git a/gst-plugin/src/lib.rs b/gst-plugin/src/lib.rs index 300bea09..86e7271c 100644 --- a/gst-plugin/src/lib.rs +++ b/gst-plugin/src/lib.rs @@ -22,6 +22,7 @@ extern crate derivative; pub extern crate gobject_sys as gobject; pub extern crate glib_sys as glib; pub extern crate gstreamer_sys as gst; +pub extern crate gstreamer_base_sys as gst_base; #[macro_use] pub mod utils; diff --git a/gst-plugin/src/miniobject.rs b/gst-plugin/src/miniobject.rs index d2772c0e..7ce9286b 100644 --- a/gst-plugin/src/miniobject.rs +++ b/gst-plugin/src/miniobject.rs @@ -153,7 +153,7 @@ impl<'a, T: MiniObject> From<&'a mut T> for GstRc { } #[repr(C)] -pub struct GstRefPtr(*mut T::PtrType); +pub struct GstRefPtr(pub *mut T::PtrType); #[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct GstRef<'a, T: 'a + MiniObject> { diff --git a/gst-plugin/src/sink.rs b/gst-plugin/src/sink.rs index 80b9173d..c848743a 100644 --- a/gst-plugin/src/sink.rs +++ b/gst-plugin/src/sink.rs @@ -177,13 +177,13 @@ impl SinkWrapper { } } - fn render(&self, buffer: &Buffer) -> GstFlowReturn { + fn render(&self, buffer: &Buffer) -> gst::GstFlowReturn { let sink = &mut self.sink.lock().unwrap(); trace!(self.logger, "Rendering buffer {:?}", buffer); match sink.render(buffer) { - Ok(..) => GstFlowReturn::Ok, + Ok(..) => gst::GST_FLOW_OK, Err(flow_error) => { error!(self.logger, "Failed to render: {:?}", flow_error); match flow_error { @@ -281,9 +281,9 @@ pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> glib::gboolean { #[no_mangle] pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper, buffer: GstRefPtr) - -> GstFlowReturn { + -> gst::GstFlowReturn { let wrap: &SinkWrapper = &*ptr; - panic_to_error!(wrap, GstFlowReturn::Error, { + panic_to_error!(wrap, gst::GST_FLOW_ERROR, { let buffer: GstRef = GstRef::new(&buffer); wrap.render(buffer.as_ref()) }) diff --git a/gst-plugin/src/source.c b/gst-plugin/src/source.c deleted file mode 100644 index 72d3d80b..00000000 --- a/gst-plugin/src/source.c +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright (C) 2016-2017 Sebastian Dröge - * - * Licensed under the Apache License, Version 2.0 or the MIT license - * , at your - * option. This file may not be copied, modified, or distributed - * except according to those terms. - */ - -#include "source.h" - -#include -#include - -typedef struct -{ - gchar *long_name; - gchar *description; - gchar *classification; - gchar *author; - void *create_instance; - gchar **protocols; -} ElementData; -static GHashTable *sources; - -/* Declarations for Rust code */ -extern gboolean sources_register (void *plugin); -extern void *source_new (GstRsSrc * source, void *create_instance); -extern void source_drop (void *rssource); -extern GstFlowReturn source_fill (void *rssource, guint64 offset, guint size, - GstBuffer * buffer); -extern gboolean source_seek (void *rssource, uint64_t start, uint64_t stop); -extern gboolean source_set_uri (void *rssource, const char *uri, GError ** err); -extern char *source_get_uri (void *rssource); -extern uint64_t source_get_size (void *rssource); -extern gboolean source_is_seekable (void *rssource); -extern gboolean source_start (void *rssource); -extern gboolean source_stop (void *rssource); - -extern void cstring_drop (void *str); - -GST_DEBUG_CATEGORY_STATIC (gst_rs_src_debug); -#define GST_CAT_DEFAULT gst_rs_src_debug - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -enum -{ - PROP_0, - PROP_URI -}; - -static void gst_rs_src_uri_handler_init (gpointer g_iface, gpointer iface_data); - -static void gst_rs_src_finalize (GObject * object); - -static void gst_rs_src_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rs_src_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_rs_src_start (GstBaseSrc * basesrc); -static gboolean gst_rs_src_stop (GstBaseSrc * basesrc); - -static gboolean gst_rs_src_is_seekable (GstBaseSrc * src); -static gboolean gst_rs_src_get_size (GstBaseSrc * src, guint64 * size); -static GstFlowReturn gst_rs_src_fill (GstBaseSrc * src, guint64 offset, - guint length, GstBuffer * buf); -static gboolean gst_rs_src_do_seek (GstBaseSrc * src, GstSegment * segment); - -static GObjectClass *parent_class; - -static void -gst_rs_src_class_init (GstRsSrcClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSrcClass *gstbasesrc_class; - ElementData *data = g_hash_table_lookup (sources, - GSIZE_TO_POINTER (G_TYPE_FROM_CLASS (klass))); - g_assert (data != NULL); - - gobject_class = G_OBJECT_CLASS (klass); - gstelement_class = GST_ELEMENT_CLASS (klass); - gstbasesrc_class = GST_BASE_SRC_CLASS (klass); - - gobject_class->set_property = gst_rs_src_set_property; - gobject_class->get_property = gst_rs_src_get_property; - - g_object_class_install_property (gobject_class, PROP_URI, - g_param_spec_string ("uri", "URI", - "URI to read from", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | - GST_PARAM_MUTABLE_READY)); - - gobject_class->finalize = gst_rs_src_finalize; - - gst_element_class_set_static_metadata (gstelement_class, - data->long_name, data->classification, data->description, data->author); - gst_element_class_add_static_pad_template (gstelement_class, &src_template); - - gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_rs_src_start); - gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rs_src_stop); - gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_rs_src_is_seekable); - gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_rs_src_get_size); - gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_rs_src_fill); - gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_rs_src_do_seek); -} - -static void -gst_rs_src_init (GstRsSrc * src, GstRsSrcClass * klass) -{ - ElementData *data = g_hash_table_lookup (sources, - GSIZE_TO_POINTER (G_TYPE_FROM_CLASS (klass))); - g_assert (data != NULL); - - gst_base_src_set_blocksize (GST_BASE_SRC (src), 4096); - - GST_DEBUG_OBJECT (src, "Instantiating"); - - src->instance = source_new (src, data->create_instance); -} - -static void -gst_rs_src_finalize (GObject * object) -{ - GstRsSrc *src = GST_RS_SRC (object); - - GST_DEBUG_OBJECT (src, "Finalizing"); - - source_drop (src->instance); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_rs_src_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRsSrc *src = GST_RS_SRC (object); - - switch (prop_id) { - case PROP_URI: - source_set_uri (src->instance, g_value_get_string (value), NULL); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rs_src_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRsSrc *src = GST_RS_SRC (object); - - switch (prop_id) { - case PROP_URI:{ - gchar *str = source_get_uri (src->instance); - g_value_set_string (value, str); - if (str) - cstring_drop (str); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstFlowReturn -gst_rs_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, - GstBuffer * buf) -{ - GstRsSrc *src = GST_RS_SRC (basesrc); - GstFlowReturn ret; - - GST_TRACE_OBJECT (src, - "Filling buffer %p, offset %" G_GUINT64_FORMAT " and length %" - G_GUINT64_FORMAT, *buf, offset, length); - - ret = source_fill (src->instance, offset, length, buf); - - GST_TRACE_OBJECT (src, "Filled buffer: %s", gst_flow_get_name (ret)); - - return ret; -} - -static gboolean -gst_rs_src_is_seekable (GstBaseSrc * basesrc) -{ - GstRsSrc *src = GST_RS_SRC (basesrc); - gboolean res; - - res = source_is_seekable (src->instance); - - GST_DEBUG_OBJECT (src, "Returning seekable %d", res); -} - -static gboolean -gst_rs_src_get_size (GstBaseSrc * basesrc, guint64 * size) -{ - GstRsSrc *src = GST_RS_SRC (basesrc); - - *size = source_get_size (src->instance); - - GST_DEBUG_OBJECT (src, "Returning size %" G_GUINT64_FORMAT, *size); - - return TRUE; -} - -/* open the rs, necessary to go to READY state */ -static gboolean -gst_rs_src_start (GstBaseSrc * basesrc) -{ - GstRsSrc *src = GST_RS_SRC (basesrc); - - GST_DEBUG_OBJECT (src, "Starting"); - - return source_start (src->instance); -} - -static gboolean -gst_rs_src_stop (GstBaseSrc * basesrc) -{ - GstRsSrc *src = GST_RS_SRC (basesrc); - - GST_DEBUG_OBJECT (src, "Stopping"); - - /* Ignore stop failures */ - source_stop (src->instance); - - return TRUE; -} - -static gboolean -gst_rs_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment) -{ - GstRsSrc *src = GST_RS_SRC (basesrc); - gboolean ret; - - GST_DEBUG_OBJECT (src, "Seeking to %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, - GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop)); - - ret = source_seek (src->instance, segment->start, segment->stop); - if (!ret) { - GST_DEBUG_OBJECT (src, "Failed to seek"); - return FALSE; - } - - return GST_BASE_SRC_CLASS (parent_class)->do_seek (basesrc, segment); -} - -static GstURIType -gst_rs_src_uri_get_type (GType type) -{ - return GST_URI_SRC; -} - -static const gchar *const * -gst_rs_src_uri_get_protocols (GType type) -{ - ElementData *data = g_hash_table_lookup (sources, GSIZE_TO_POINTER (type)); - g_assert (data != NULL); - - return (const gchar * const *) data->protocols; -} - -static gchar * -gst_rs_src_uri_get_uri (GstURIHandler * handler) -{ - GstRsSrc *src = GST_RS_SRC (handler); - gchar *res; - - res = source_get_uri (src->instance); - - GST_DEBUG_OBJECT (src, "Returning URI %s", res); - - return res; -} - -static gboolean -gst_rs_src_uri_set_uri (GstURIHandler * handler, const gchar * uri, - GError ** err) -{ - GstRsSrc *src = GST_RS_SRC (handler); - - GST_DEBUG_OBJECT (src, "Setting URI %s", uri); - - if (!source_set_uri (src->instance, uri, err)) { - GST_ERROR_OBJECT (src, "Failed to set URI: %s", (*err)->message); - return FALSE; - } - - return TRUE; -} - -static void -gst_rs_src_uri_handler_init (gpointer g_iface, gpointer iface_data) -{ - GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; - - iface->get_type = gst_rs_src_uri_get_type; - iface->get_protocols = gst_rs_src_uri_get_protocols; - iface->get_uri = gst_rs_src_uri_get_uri; - iface->set_uri = gst_rs_src_uri_set_uri; -} - -static gpointer -gst_rs_source_init_class (gpointer data) -{ - sources = g_hash_table_new (g_direct_hash, g_direct_equal); - GST_DEBUG_CATEGORY_INIT (gst_rs_src_debug, "rssrc", 0, - "Rust source base class"); - - parent_class = g_type_class_ref (GST_TYPE_BASE_SRC); - - return NULL; -} - -gboolean -gst_rs_source_register (GstPlugin * plugin, const gchar * name, - const gchar * long_name, const gchar * description, - const gchar * classification, const gchar * author, GstRank rank, - void *create_instance, const gchar * protocols, gboolean push_only) -{ - static GOnce gonce = G_ONCE_INIT; - GTypeInfo type_info = { - sizeof (GstRsSrcClass), - NULL, - NULL, - (GClassInitFunc) gst_rs_src_class_init, - NULL, - NULL, - sizeof (GstRsSrc), - 0, - (GInstanceInitFunc) gst_rs_src_init - }; - GInterfaceInfo iface_info = { - gst_rs_src_uri_handler_init, - NULL, - NULL - }; - GType type; - gchar *type_name; - ElementData *data; - - g_once (&gonce, gst_rs_source_init_class, NULL); - - GST_DEBUG ("Registering for %" GST_PTR_FORMAT ": %s", plugin, name); - GST_DEBUG (" long name: %s", long_name); - GST_DEBUG (" description: %s", description); - GST_DEBUG (" classification: %s", classification); - GST_DEBUG (" author: %s", author); - GST_DEBUG (" rank: %d", rank); - GST_DEBUG (" protocols: %s", protocols); - GST_DEBUG (" push only: %d", push_only); - - data = g_new0 (ElementData, 1); - data->long_name = g_strdup (long_name); - data->description = g_strdup (description); - data->classification = g_strdup (classification); - data->author = g_strdup (author); - data->create_instance = create_instance; - data->protocols = g_strsplit (protocols, ":", -1); - - type_name = g_strconcat ("RsSrc-", name, NULL); - type = - g_type_register_static (push_only ? GST_TYPE_PUSH_SRC : GST_TYPE_BASE_SRC, - type_name, &type_info, 0); - g_free (type_name); - - g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &iface_info); - - g_hash_table_insert (sources, GSIZE_TO_POINTER (type), data); - - if (!gst_element_register (plugin, name, rank, type)) - return FALSE; - - return TRUE; -} diff --git a/gst-plugin/src/source.h b/gst-plugin/src/source.h deleted file mode 100644 index a395b50a..00000000 --- a/gst-plugin/src/source.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) 2016 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_RS_SRC_H__ -#define __GST_RS_SRC_H__ - -#include -#include - -G_BEGIN_DECLS - -#define GST_RS_SRC(obj) \ - ((GstRsSrc *)obj) -#define GST_RS_SRC_CLASS(klass) \ - ((GstRsSrcKlass *)klass) - -typedef struct _GstRsSrc GstRsSrc; -typedef struct _GstRsSrcClass GstRsSrcClass; - -struct _GstRsSrc { - GstPushSrc element; - - gpointer instance; -}; - -struct _GstRsSrcClass { - GstPushSrcClass parent_class; -}; - -G_GNUC_INTERNAL gboolean gst_rs_source_plugin_init (GstPlugin * plugin); - -G_END_DECLS - -#endif /* __GST_RS_SRC_H__ */ diff --git a/gst-plugin/src/source.rs b/gst-plugin/src/source.rs index d49a5ca2..41705bda 100644 --- a/gst-plugin/src/source.rs +++ b/gst-plugin/src/source.rs @@ -7,9 +7,9 @@ // except according to those terms. use libc::c_char; -use std::os::raw::c_void; use std::ffi::{CStr, CString}; use std::ptr; +use std::mem; use std::u64; use std::panic::{self, AssertUnwindSafe}; @@ -27,9 +27,12 @@ use error::*; use buffer::*; use miniobject::*; use log::*; +use caps::*; use glib; +use gobject; use gst; +use gst_base; #[derive(Debug)] pub enum SourceError { @@ -190,7 +193,7 @@ impl SourceWrapper { } } - fn fill(&self, offset: u64, length: u32, buffer: &mut Buffer) -> GstFlowReturn { + fn fill(&self, offset: u64, length: u32, buffer: &mut Buffer) -> gst::GstFlowReturn { let source = &mut self.source.lock().unwrap(); trace!(self.logger, @@ -200,7 +203,7 @@ impl SourceWrapper { length); match source.fill(offset, length, buffer) { - Ok(()) => GstFlowReturn::Ok, + Ok(()) => gst::GST_FLOW_OK, Err(flow_error) => { error!(self.logger, "Failed to fill: {:?}", flow_error); match flow_error { @@ -235,26 +238,12 @@ impl SourceWrapper { } } -#[no_mangle] -pub unsafe extern "C" fn source_new(source: *mut gst::GstElement, - create_instance: fn(Element) -> Box) - -> *mut SourceWrapper { - let instance = create_instance(Element::new(source)); - - Box::into_raw(Box::new(SourceWrapper::new(source, instance))) -} - -#[no_mangle] -pub unsafe extern "C" fn source_drop(ptr: *mut SourceWrapper) { - let _ = Box::from_raw(ptr); -} - -#[no_mangle] -pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper, - uri_ptr: *const c_char, - cerr: *mut *mut glib::GError) - -> glib::gboolean { - let wrap: &SourceWrapper = &*ptr; +unsafe fn source_set_uri(ptr: *const RsSrc, + uri_ptr: *const c_char, + cerr: *mut *mut glib::GError) + -> glib::gboolean { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; panic_to_error!(wrap, glib::GFALSE, { let uri_str = if uri_ptr.is_null() { @@ -274,20 +263,21 @@ pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper, }) } -#[no_mangle] -pub unsafe extern "C" fn source_get_uri(ptr: *const SourceWrapper) -> *mut c_char { - let wrap: &SourceWrapper = &*ptr; +unsafe fn source_get_uri(ptr: *const RsSrc) -> *mut c_char { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; + panic_to_error!(wrap, ptr::null_mut(), { match wrap.get_uri() { - Some(uri_str) => CString::new(uri_str).unwrap().into_raw(), + Some(uri_str) => glib::g_strdup(CString::new(uri_str).unwrap().as_ptr()), None => ptr::null_mut(), } }) } -#[no_mangle] -pub unsafe extern "C" fn source_is_seekable(ptr: *const SourceWrapper) -> glib::gboolean { - let wrap: &SourceWrapper = &*ptr; +unsafe extern "C" fn source_is_seekable(ptr: *mut gst_base::GstBaseSrc) -> glib::gboolean { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; panic_to_error!(wrap, glib::GFALSE, { if wrap.is_seekable() { @@ -298,17 +288,21 @@ pub unsafe extern "C" fn source_is_seekable(ptr: *const SourceWrapper) -> glib:: }) } -#[no_mangle] -pub unsafe extern "C" fn source_get_size(ptr: *const SourceWrapper) -> u64 { - let wrap: &SourceWrapper = &*ptr; - panic_to_error!(wrap, u64::MAX, { - wrap.get_size() +unsafe extern "C" fn source_get_size(ptr: *mut gst_base::GstBaseSrc, + size: *mut u64) + -> glib::gboolean { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; + + panic_to_error!(wrap, glib::GFALSE, { + *size = wrap.get_size(); + glib::GTRUE }) } -#[no_mangle] -pub unsafe extern "C" fn source_start(ptr: *const SourceWrapper) -> glib::gboolean { - let wrap: &SourceWrapper = &*ptr; +unsafe extern "C" fn source_start(ptr: *mut gst_base::GstBaseSrc) -> glib::gboolean { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; panic_to_error!(wrap, glib::GFALSE, { if wrap.start() { @@ -319,9 +313,9 @@ pub unsafe extern "C" fn source_start(ptr: *const SourceWrapper) -> glib::gboole }) } -#[no_mangle] -pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> glib::gboolean { - let wrap: &SourceWrapper = &*ptr; +unsafe extern "C" fn source_stop(ptr: *mut gst_base::GstBaseSrc) -> glib::gboolean { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; panic_to_error!(wrap, glib::GTRUE, { if wrap.stop() { @@ -332,26 +326,29 @@ pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> glib::gboolea }) } -#[no_mangle] -pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper, - offset: u64, - length: u32, - buffer: GstRefPtr) - -> GstFlowReturn { - let wrap: &SourceWrapper = &*ptr; +unsafe extern "C" fn source_fill(ptr: *mut gst_base::GstBaseSrc, + offset: u64, + length: u32, + buffer: *mut gst::GstBuffer) + -> gst::GstFlowReturn { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; + let buffer = GstRefPtr(buffer); - panic_to_error!(wrap, GstFlowReturn::Error, { + panic_to_error!(wrap, gst::GST_FLOW_ERROR, { let mut buffer: GstRef = GstRef::new(&buffer); wrap.fill(offset, length, buffer.get_mut().unwrap()) }) } -#[no_mangle] -pub unsafe extern "C" fn source_seek(ptr: *const SourceWrapper, - start: u64, - stop: u64) - -> glib::gboolean { - let wrap: &SourceWrapper = &*ptr; +unsafe extern "C" fn source_seek(ptr: *mut gst_base::GstBaseSrc, + segment: *mut gst::GstSegment) + -> glib::gboolean { + let src = &*(ptr as *const RsSrc); + let wrap: &SourceWrapper = &*src.wrap; + + let start = (*segment).start; + let stop = (*segment).stop; panic_to_error!(wrap, glib::GFALSE, { if wrap.seek(start, if stop == u64::MAX { None } else { Some(stop) }) { @@ -362,55 +359,230 @@ pub unsafe extern "C" fn source_seek(ptr: *const SourceWrapper, }) } -pub struct SourceInfo<'a> { - pub name: &'a str, - pub long_name: &'a str, - pub description: &'a str, - pub classification: &'a str, - pub author: &'a str, - pub rank: i32, +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(Element) -> Box, - pub protocols: &'a str, + pub protocols: Vec, pub push_only: bool, } -pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) { +#[repr(C)] +struct RsSrc { + parent: gst_base::GstPushSrc, + wrap: *mut SourceWrapper, + source_info: *const SourceInfo, +} - extern "C" { - fn gst_rs_source_register(plugin: *const gst::GstPlugin, - name: *const c_char, - long_name: *const c_char, - description: *const c_char, - classification: *const c_char, - author: *const c_char, - rank: i32, - create_instance: *const c_void, - protocols: *const c_char, - push_only: glib::gboolean) - -> glib::gboolean; - } +#[repr(C)] +struct RsSrcClass { + parent_class: gst_base::GstPushSrcClass, + source_info: *const SourceInfo, + protocols: *const Vec<*const c_char>, + parent_vtable: glib::gconstpointer, +} - let cname = CString::new(source_info.name).unwrap(); - let clong_name = CString::new(source_info.long_name).unwrap(); - let cdescription = CString::new(source_info.description).unwrap(); - let cclassification = CString::new(source_info.classification).unwrap(); - let cauthor = CString::new(source_info.author).unwrap(); - let cprotocols = CString::new(source_info.protocols).unwrap(); +unsafe extern "C" fn source_finalize(obj: *mut gobject::GObject) { + let src = &mut *(obj as *mut RsSrc); - unsafe { - gst_rs_source_register(plugin.as_ptr(), - cname.as_ptr(), - clong_name.as_ptr(), - cdescription.as_ptr(), - cclassification.as_ptr(), - cauthor.as_ptr(), - source_info.rank, - source_info.create_instance as *const c_void, - cprotocols.as_ptr(), - if source_info.push_only { - glib::GTRUE - } else { - glib::GFALSE - }); + drop(Box::from_raw(src.wrap)); + + let src_klass = &**(obj as *const *const RsSrcClass); + let parent_klass = &*(src_klass.parent_vtable as *const gobject::GObjectClass); + parent_klass.finalize.map(|f| f(obj)); +} + +unsafe extern "C" fn source_set_property(obj: *mut gobject::GObject, + id: u32, + value: *mut gobject::GValue, + _pspec: *mut gobject::GParamSpec) { + let src = &*(obj as *const RsSrc); + + match id { + 1 => { + let uri_ptr = gobject::g_value_get_string(value); + source_set_uri(src, uri_ptr, ptr::null_mut()); + } + _ => unreachable!(), + } +} + +unsafe extern "C" fn source_get_property(obj: *mut gobject::GObject, + id: u32, + value: *mut gobject::GValue, + _pspec: *mut gobject::GParamSpec) { + let src = &*(obj as *const RsSrc); + + match id { + 1 => { + let uri_ptr = source_get_uri(src); + gobject::g_value_take_string(value, uri_ptr); + } + _ => unreachable!(), + } +} + +unsafe extern "C" fn source_class_init(klass: glib::gpointer, klass_data: glib::gpointer) { + let src_klass = &mut *(klass as *mut RsSrcClass); + let source_info = &*(klass_data as *const SourceInfo); + + { + let gobject_klass = &mut src_klass.parent_class + .parent_class + .parent_class + .parent_class + .parent_class; + gobject_klass.set_property = Some(source_set_property); + gobject_klass.get_property = Some(source_get_property); + gobject_klass.finalize = Some(source_finalize); + + let name_cstr = CString::new("uri").unwrap(); + let nick_cstr = CString::new("URI").unwrap(); + let blurb_cstr = CString::new("URI to read from").unwrap(); + + gobject::g_object_class_install_property(klass as *mut gobject::GObjectClass, 1, + gobject::g_param_spec_string(name_cstr.as_ptr(), + nick_cstr.as_ptr(), + blurb_cstr.as_ptr(), + ptr::null_mut(), + gobject::G_PARAM_READWRITE)); + } + + { + let element_klass = &mut src_klass.parent_class.parent_class.parent_class; + + let longname_cstr = CString::new(source_info.long_name.clone()).unwrap(); + let classification_cstr = CString::new(source_info.description.clone()).unwrap(); + let description_cstr = CString::new(source_info.classification.clone()).unwrap(); + let author_cstr = CString::new(source_info.author.clone()).unwrap(); + + gst::gst_element_class_set_static_metadata(element_klass, + longname_cstr.into_raw(), + classification_cstr.into_raw(), + description_cstr.into_raw(), + author_cstr.into_raw()); + + let caps = Caps::new_any(); + let templ_name = CString::new("src").unwrap(); + let pad_template = gst::gst_pad_template_new(templ_name.into_raw(), + gst::GST_PAD_SRC, + gst::GST_PAD_ALWAYS, + caps.as_ptr()); + gst::gst_element_class_add_pad_template(element_klass, pad_template); + } + + { + let basesrc_klass = &mut src_klass.parent_class.parent_class; + basesrc_klass.start = Some(source_start); + basesrc_klass.stop = Some(source_stop); + basesrc_klass.is_seekable = Some(source_is_seekable); + basesrc_klass.get_size = Some(source_get_size); + basesrc_klass.fill = Some(source_fill); + basesrc_klass.do_seek = Some(source_seek); + } + + src_klass.source_info = source_info; + let mut protocols = Box::new(Vec::with_capacity(source_info.protocols.len())); + for p in &source_info.protocols { + let p_cstr = CString::new(p.clone().into_bytes()).unwrap(); + protocols.push(p_cstr.into_raw() as *const c_char); + } + protocols.push(ptr::null()); + src_klass.protocols = Box::into_raw(protocols) as *const Vec<*const c_char>; + src_klass.parent_vtable = gobject::g_type_class_peek_parent(klass); +} + +unsafe extern "C" fn source_init(instance: *mut gobject::GTypeInstance, klass: glib::gpointer) { + let src = &mut *(instance as *mut RsSrc); + let src_klass = &*(klass as *const RsSrcClass); + let source_info = &*src_klass.source_info; + + src.source_info = source_info; + + let wrap = Box::new(SourceWrapper::new(&mut src.parent.parent.element, + (source_info.create_instance)(Element::new(&mut src.parent.parent.element)))); + src.wrap = Box::into_raw(wrap); + + gst_base::gst_base_src_set_blocksize(&mut src.parent.parent, 4096); +} + +unsafe extern "C" fn source_uri_handler_get_type(_type: glib::GType) -> gst::GstURIType { + gst::GST_URI_SRC +} + +unsafe extern "C" fn source_uri_handler_get_protocols(type_: glib::GType) -> *const *const c_char { + let klass = gobject::g_type_class_peek(type_); + let src_klass = &*(klass as *const RsSrcClass); + (*src_klass.protocols).as_ptr() +} + +unsafe extern "C" fn source_uri_handler_get_uri(uri_handler: *mut gst::GstURIHandler) + -> *mut c_char { + source_get_uri(uri_handler as *const RsSrc) +} + +unsafe extern "C" fn source_uri_handler_set_uri(uri_handler: *mut gst::GstURIHandler, + uri: *const c_char, + err: *mut *mut glib::GError) + -> glib::gboolean { + source_set_uri(uri_handler as *const RsSrc, uri, err) +} + +unsafe extern "C" fn source_uri_handler_init(iface: glib::gpointer, _iface_data: glib::gpointer) { + let uri_handler_iface = &mut *(iface as *mut gst::GstURIHandlerInterface); + + uri_handler_iface.get_type = Some(source_uri_handler_get_type); + uri_handler_iface.get_protocols = Some(source_uri_handler_get_protocols); + uri_handler_iface.get_uri = Some(source_uri_handler_get_uri); + uri_handler_iface.set_uri = Some(source_uri_handler_set_uri); +} + +pub fn source_register(plugin: &Plugin, source_info: SourceInfo) { + unsafe { + let parent_type = if source_info.push_only { + gst_base::gst_push_src_get_type() + } else { + gst_base::gst_base_src_get_type() + }; + let mut type_name = String::from("RsSrc-"); + type_name.push_str(&source_info.name); + let type_name_cstr = CString::new(type_name.into_bytes()).unwrap(); + + let name_cstr = CString::new(source_info.name.clone().into_bytes()).unwrap(); + let rank = source_info.rank; + + let source_info = Box::new(source_info); + let source_info_ptr = Box::into_raw(source_info) as glib::gpointer; + + let type_info = gobject::GTypeInfo { + class_size: mem::size_of::() as u16, + base_init: None, + base_finalize: None, + class_init: Some(source_class_init), + class_finalize: None, + class_data: source_info_ptr, + instance_size: mem::size_of::() as u16, + n_preallocs: 0, + instance_init: Some(source_init), + value_table: ptr::null(), + }; + + let type_ = gobject::g_type_register_static(parent_type, + type_name_cstr.as_ptr(), + &type_info, + gobject::GTypeFlags::empty()); + + let iface_info = gobject::GInterfaceInfo { + interface_init: Some(source_uri_handler_init), + interface_finalize: None, + interface_data: ptr::null_mut(), + }; + gobject::g_type_add_interface_static(type_, gst::gst_uri_handler_get_type(), &iface_info); + + gst::gst_element_register(plugin.as_ptr(), name_cstr.as_ptr(), rank, type_); } } diff --git a/gst-plugin/src/utils.rs b/gst-plugin/src/utils.rs index e0e8b0d2..2c300775 100644 --- a/gst-plugin/src/utils.rs +++ b/gst-plugin/src/utils.rs @@ -13,17 +13,6 @@ use num_rational::Rational32; use gst; -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum GstFlowReturn { - Ok = 0, - NotLinked = -1, - Flushing = -2, - Eos = -3, - NotNegotiated = -4, - Error = -5, -} - pub struct Element(*mut gst::GstElement); impl Element {