Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2020-11-15 11:08:32 +0300
committerSebastian Dröge <sebastian@centricular.com>2020-11-15 19:25:42 +0300
commit4829e31191213eda72e2eecdcbf16f7168ba81a6 (patch)
tree70c06ff9b38bb851b8a5d7149cf1749d9f88b079 /tutorial/src
parentdbf108d9a4ca8760913aaf74ca0a6891dae5bb1a (diff)
tutorial: Update for subclassing API changes
Diffstat (limited to 'tutorial/src')
-rw-r--r--tutorial/src/identity/imp.rs (renamed from tutorial/src/identity.rs)49
-rw-r--r--tutorial/src/identity/mod.rs33
-rw-r--r--tutorial/src/progressbin/imp.rs (renamed from tutorial/src/progressbin.rs)58
-rw-r--r--tutorial/src/progressbin/mod.rs52
-rw-r--r--tutorial/src/rgb2gray/imp.rs (renamed from tutorial/src/rgb2gray.rs)54
-rw-r--r--tutorial/src/rgb2gray/mod.rs33
-rw-r--r--tutorial/src/sinesrc/imp.rs (renamed from tutorial/src/sinesrc.rs)89
-rw-r--r--tutorial/src/sinesrc/mod.rs33
8 files changed, 243 insertions, 158 deletions
diff --git a/tutorial/src/identity.rs b/tutorial/src/identity/imp.rs
index e77b44fdd..a02a18388 100644
--- a/tutorial/src/identity.rs
+++ b/tutorial/src/identity/imp.rs
@@ -6,7 +6,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use glib::prelude::*;
use glib::subclass;
use glib::subclass::prelude::*;
use gst::prelude::*;
@@ -14,11 +13,7 @@ use gst::subclass::prelude::*;
use once_cell::sync::Lazy;
-// Struct containing all the element data
-struct Identity {
- srcpad: gst::Pad,
- sinkpad: gst::Pad,
-}
+// This module contains the private implementation details of our element
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new(
@@ -28,6 +23,12 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
)
});
+// Struct containing all the element data
+pub struct Identity {
+ srcpad: gst::Pad,
+ sinkpad: gst::Pad,
+}
+
impl Identity {
// Called whenever a new buffer is passed to our sink pad. Here buffers should be processed and
// whenever some output buffer is available have to push it out of the source pad.
@@ -38,7 +39,7 @@ impl Identity {
fn sink_chain(
&self,
pad: &gst::Pad,
- _element: &gst::Element,
+ _element: &super::Identity,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -52,7 +53,7 @@ impl Identity {
//
// See the documentation of gst::Event and gst::EventRef to see what can be done with
// events, and especially the gst::EventView type for inspecting events.
- fn sink_event(&self, pad: &gst::Pad, _element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, _element: &super::Identity, event: gst::Event) -> bool {
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
self.srcpad.push_event(event)
}
@@ -69,7 +70,7 @@ impl Identity {
fn sink_query(
&self,
pad: &gst::Pad,
- _element: &gst::Element,
+ _element: &super::Identity,
query: &mut gst::QueryRef,
) -> bool {
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@@ -84,7 +85,7 @@ impl Identity {
//
// See the documentation of gst::Event and gst::EventRef to see what can be done with
// events, and especially the gst::EventView type for inspecting events.
- fn src_event(&self, pad: &gst::Pad, _element: &gst::Element, event: gst::Event) -> bool {
+ fn src_event(&self, pad: &gst::Pad, _element: &super::Identity, event: gst::Event) -> bool {
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
self.sinkpad.push_event(event)
}
@@ -101,7 +102,7 @@ impl Identity {
fn src_query(
&self,
pad: &gst::Pad,
- _element: &gst::Element,
+ _element: &super::Identity,
query: &mut gst::QueryRef,
) -> bool {
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@@ -114,6 +115,7 @@ impl Identity {
// up the class data
impl ObjectSubclass for Identity {
const NAME: &'static str = "RsIdentity";
+ type Type = super::Identity;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -123,7 +125,7 @@ impl ObjectSubclass for Identity {
// Called when a new instance is to be created. We need to return an instance
// of our struct here and also get the class struct passed in case it's needed
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
// Create our two pads from the templates that were registered with
// the class and set all the functions on them.
//
@@ -189,7 +191,7 @@ impl ObjectSubclass for Identity {
//
// Actual instances can create pads based on those pad templates
// with a subset of the caps given here.
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// retrieved from the gst::Registry after initial registration
@@ -231,15 +233,14 @@ impl ObjectSubclass for Identity {
// Implementation of glib::Object virtual methods
impl ObjectImpl for Identity {
// Called right after construction of a new instance
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
// Call the parent class' ::constructed() implementation first
self.parent_constructed(obj);
// Here we actually add the pads we created in Identity::new() to the
// element so that GStreamer is aware of their existence.
- let element = obj.downcast_ref::<gst::Element>().unwrap();
- element.add_pad(&self.sinkpad).unwrap();
- element.add_pad(&self.srcpad).unwrap();
+ obj.add_pad(&self.sinkpad).unwrap();
+ obj.add_pad(&self.srcpad).unwrap();
}
}
@@ -250,7 +251,7 @@ impl ElementImpl for Identity {
// the element again.
fn change_state(
&self,
- element: &gst::Element,
+ element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
@@ -259,15 +260,3 @@ impl ElementImpl for Identity {
self.parent_change_state(element, transition)
}
}
-
-// Registers the type for our element, and then registers in GStreamer under
-// the name "rsidentity" for being able to instantiate it via e.g.
-// gst::ElementFactory::make().
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rsidentity",
- gst::Rank::None,
- Identity::get_type(),
- )
-}
diff --git a/tutorial/src/identity/mod.rs b/tutorial/src/identity/mod.rs
new file mode 100644
index 000000000..027d52a52
--- /dev/null
+++ b/tutorial/src/identity/mod.rs
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 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::prelude::*;
+
+mod imp;
+
+// The public Rust wrapper type for our element
+glib_wrapper! {
+ pub struct Identity(ObjectSubclass<imp::Identity>) @extends gst::Element, gst::Object;
+}
+
+// GStreamer elements need to be thread-safe. For the private implementation this is automatically
+// enforced but for the public wrapper type we need to specify this manually.
+unsafe impl Send for Identity {}
+unsafe impl Sync for Identity {}
+
+// Registers the type for our element, and then registers in GStreamer under
+// the name "rsidentity" for being able to instantiate it via e.g.
+// gst::ElementFactory::make().
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rsidentity",
+ gst::Rank::None,
+ Identity::static_type(),
+ )
+}
diff --git a/tutorial/src/progressbin.rs b/tutorial/src/progressbin/imp.rs
index 35a9e650d..3198d2711 100644
--- a/tutorial/src/progressbin.rs
+++ b/tutorial/src/progressbin/imp.rs
@@ -15,24 +15,9 @@ use std::sync::Mutex;
use once_cell::sync::Lazy;
-// This enum may be used to control what type of output the progressbin should produce.
-// It also serves the secondary purpose of illustrating how to add enum-type properties
-// to a plugin written in rust.
-#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
-#[repr(u32)]
-#[genum(type_name = "GstProgressBinOutput")]
-pub(crate) enum ProgressBinOutput {
- #[genum(
- name = "Println: Outputs the progress using a println! macro.",
- nick = "println"
- )]
- Println = 0,
- #[genum(
- name = "Debug Category: Outputs the progress as info logs under the element's debug category.",
- nick = "debug-category"
- )]
- DebugCategory = 1,
-}
+use super::ProgressBinOutput;
+
+// This module contains the private implementation details of our element
const DEFAULT_OUTPUT_TYPE: ProgressBinOutput = ProgressBinOutput::Println;
@@ -45,7 +30,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
// Struct containing all the element data
-struct ProgressBin {
+pub struct ProgressBin {
progress: gst::Element,
srcpad: gst::GhostPad,
sinkpad: gst::GhostPad,
@@ -72,6 +57,7 @@ static PROPERTIES: [subclass::Property; 1] = [subclass::Property("output", |name
// up the class data
impl ObjectSubclass for ProgressBin {
const NAME: &'static str = "RsProgressBin";
+ type Type = super::ProgressBin;
type ParentType = gst::Bin;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -81,7 +67,7 @@ impl ObjectSubclass for ProgressBin {
// Called when a new instance is to be created. We need to return an instance
// of our struct here and also get the class struct passed in case it's needed
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
// Create our two ghostpads from the templates that were registered with
// the class. We don't provide a target for them yet because we can only
// do so after the progressreport element was added to the bin.
@@ -112,7 +98,7 @@ impl ObjectSubclass for ProgressBin {
//
// Actual instances can create pads based on those pad templates
// with a subset of the caps given here.
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// retrieved from the gst::Registry after initial registration
@@ -158,9 +144,8 @@ impl ObjectSubclass for ProgressBin {
impl ObjectImpl for ProgressBin {
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
- fn set_property(&self, obj: &glib::Object, id: usize, value: &glib::Value) {
+ fn set_property(&self, obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
- let element = obj.downcast_ref::<gst::Bin>().unwrap();
match *prop {
subclass::Property("output", ..) => {
@@ -170,7 +155,7 @@ impl ObjectImpl for ProgressBin {
.expect("type checked upstream");
gst_info!(
CAT,
- obj: element,
+ obj: obj,
"Changing output from {:?} to {:?}",
output_type,
new_output_type
@@ -183,7 +168,7 @@ impl ObjectImpl for ProgressBin {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
- fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
+ fn get_property(&self, _obj: &Self::Type, id: usize) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
@@ -196,16 +181,15 @@ impl ObjectImpl for ProgressBin {
}
// Called right after construction of a new instance
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
// Call the parent class' ::constructed() implementation first
self.parent_constructed(obj);
// Here we actually add the pads we created in ProgressBin::new() to the
// element so that GStreamer is aware of their existence.
- let bin = obj.downcast_ref::<gst::Bin>().unwrap();
// Add the progressreport element to the bin.
- bin.add(&self.progress).unwrap();
+ obj.add(&self.progress).unwrap();
// Then set the ghost pad targets to the corresponding pads of the progressreport element.
self.sinkpad
@@ -216,8 +200,8 @@ impl ObjectImpl for ProgressBin {
.unwrap();
// And finally add the two ghostpads to the bin.
- bin.add_pad(&self.sinkpad).unwrap();
- bin.add_pad(&self.srcpad).unwrap();
+ obj.add_pad(&self.sinkpad).unwrap();
+ obj.add_pad(&self.srcpad).unwrap();
}
}
@@ -226,7 +210,7 @@ impl ElementImpl for ProgressBin {}
// Implementation of gst::Bin virtual methods
impl BinImpl for ProgressBin {
- fn handle_message(&self, bin: &gst::Bin, msg: gst::Message) {
+ fn handle_message(&self, bin: &Self::Type, msg: gst::Message) {
use gst::MessageView;
match msg.view() {
@@ -256,15 +240,3 @@ impl BinImpl for ProgressBin {
}
}
}
-
-// Registers the type for our element, and then registers in GStreamer under
-// the name "rsprogressbin" for being able to instantiate it via e.g.
-// gst::ElementFactory::make().
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rsprogressbin",
- gst::Rank::None,
- ProgressBin::get_type(),
- )
-}
diff --git a/tutorial/src/progressbin/mod.rs b/tutorial/src/progressbin/mod.rs
new file mode 100644
index 000000000..4c1a41309
--- /dev/null
+++ b/tutorial/src/progressbin/mod.rs
@@ -0,0 +1,52 @@
+// Copyright (C) 2020 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::prelude::*;
+
+mod imp;
+
+// This enum may be used to control what type of output the progressbin should produce.
+// It also serves the secondary purpose of illustrating how to add enum-type properties
+// to a plugin written in rust.
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
+#[repr(u32)]
+#[genum(type_name = "GstProgressBinOutput")]
+pub enum ProgressBinOutput {
+ #[genum(
+ name = "Println: Outputs the progress using a println! macro.",
+ nick = "println"
+ )]
+ Println = 0,
+ #[genum(
+ name = "Debug Category: Outputs the progress as info logs under the element's debug category.",
+ nick = "debug-category"
+ )]
+ DebugCategory = 1,
+}
+
+// The public Rust wrapper type for our element
+glib_wrapper! {
+ pub struct ProgressBin(ObjectSubclass<imp::ProgressBin>) @extends gst::Bin, gst::Element, gst::Object;
+}
+
+// GStreamer elements need to be thread-safe. For the private implementation this is automatically
+// enforced but for the public wrapper type we need to specify this manually.
+unsafe impl Send for ProgressBin {}
+unsafe impl Sync for ProgressBin {}
+
+// Registers the type for our element, and then registers in GStreamer under
+// the name "rsprogressbin" for being able to instantiate it via e.g.
+// gst::ElementFactory::make().
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rsprogressbin",
+ gst::Rank::None,
+ ProgressBin::static_type(),
+ )
+}
diff --git a/tutorial/src/rgb2gray.rs b/tutorial/src/rgb2gray/imp.rs
index af47ad352..4dbacbdd4 100644
--- a/tutorial/src/rgb2gray.rs
+++ b/tutorial/src/rgb2gray/imp.rs
@@ -17,6 +17,16 @@ use std::sync::Mutex;
use once_cell::sync::Lazy;
+// This module contains the private implementation details of our element
+//
+static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
+ gst::DebugCategory::new(
+ "rsrgb2gray",
+ gst::DebugColorFlags::empty(),
+ Some("Rust RGB-GRAY converter"),
+ )
+});
+
// Default values of properties
const DEFAULT_INVERT: bool = false;
const DEFAULT_SHIFT: u32 = 0;
@@ -68,19 +78,11 @@ struct State {
}
// Struct containing all the element data
-struct Rgb2Gray {
+pub struct Rgb2Gray {
settings: Mutex<Settings>,
state: Mutex<Option<State>>,
}
-static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
- gst::DebugCategory::new(
- "rsrgb2gray",
- gst::DebugColorFlags::empty(),
- Some("Rust RGB-GRAY converter"),
- )
-});
-
impl Rgb2Gray {
// Converts one pixel of BGRx to a grayscale value, shifting and/or
// inverting it as configured
@@ -113,6 +115,7 @@ impl Rgb2Gray {
// up the class data
impl ObjectSubclass for Rgb2Gray {
const NAME: &'static str = "RsRgb2Gray";
+ type Type = super::Rgb2Gray;
type ParentType = gst_base::BaseTransform;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -139,7 +142,7 @@ impl ObjectSubclass for Rgb2Gray {
// will automatically instantiate pads for them.
//
// Our element here can convert BGRx to BGRx or GRAY8, both being grayscale.
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// retrieved from the gst::Registry after initial registration
@@ -239,9 +242,8 @@ impl ObjectSubclass for Rgb2Gray {
impl ObjectImpl for Rgb2Gray {
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
- fn set_property(&self, obj: &glib::Object, id: usize, value: &glib::Value) {
+ fn set_property(&self, obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
- let element = obj.downcast_ref::<gst_base::BaseTransform>().unwrap();
match *prop {
subclass::Property("invert", ..) => {
@@ -249,7 +251,7 @@ impl ObjectImpl for Rgb2Gray {
let invert = value.get_some().expect("type checked upstream");
gst_info!(
CAT,
- obj: element,
+ obj: obj,
"Changing invert from {} to {}",
settings.invert,
invert
@@ -261,7 +263,7 @@ impl ObjectImpl for Rgb2Gray {
let shift = value.get_some().expect("type checked upstream");
gst_info!(
CAT,
- obj: element,
+ obj: obj,
"Changing shift from {} to {}",
settings.shift,
shift
@@ -274,7 +276,7 @@ impl ObjectImpl for Rgb2Gray {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
- fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
+ fn get_property(&self, _obj: &Self::Type, id: usize) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
@@ -302,7 +304,7 @@ impl BaseTransformImpl for Rgb2Gray {
// In our case that means that:
fn transform_caps(
&self,
- element: &gst_base::BaseTransform,
+ element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@@ -360,7 +362,7 @@ impl BaseTransformImpl for Rgb2Gray {
// Returns the size of one processing unit (i.e. a frame in our case) corresponding
// to the given caps. This is used for allocating a big enough output buffer and
// sanity checking the input buffer size, among other things.
- fn get_unit_size(&self, _element: &gst_base::BaseTransform, caps: &gst::Caps) -> Option<usize> {
+ fn get_unit_size(&self, _element: &Self::Type, caps: &gst::Caps) -> Option<usize> {
gst_video::VideoInfo::from_caps(caps)
.map(|info| info.size())
.ok()
@@ -374,7 +376,7 @@ impl BaseTransformImpl for Rgb2Gray {
// the width, stride, etc when transforming buffers
fn set_caps(
&self,
- element: &gst_base::BaseTransform,
+ element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
@@ -402,7 +404,7 @@ impl BaseTransformImpl for Rgb2Gray {
// Called when shutting down the element so we can release all stream-related state
// There's also start(), which is called whenever starting the element again
- fn stop(&self, element: &gst_base::BaseTransform) -> Result<(), gst::ErrorMessage> {
+ fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();
@@ -414,7 +416,7 @@ impl BaseTransformImpl for Rgb2Gray {
// Does the actual transformation of the input buffer to the output buffer
fn transform(
&self,
- element: &gst_base::BaseTransform,
+ element: &Self::Type,
inbuf: &gst::Buffer,
outbuf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {
@@ -562,15 +564,3 @@ impl BaseTransformImpl for Rgb2Gray {
Ok(gst::FlowSuccess::Ok)
}
}
-
-// Registers the type for our element, and then registers in GStreamer under
-// the name "rsrgb2gray" for being able to instantiate it via e.g.
-// gst::ElementFactory::make().
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rsrgb2gray",
- gst::Rank::None,
- Rgb2Gray::get_type(),
- )
-}
diff --git a/tutorial/src/rgb2gray/mod.rs b/tutorial/src/rgb2gray/mod.rs
new file mode 100644
index 000000000..b85d708e4
--- /dev/null
+++ b/tutorial/src/rgb2gray/mod.rs
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 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::prelude::*;
+
+mod imp;
+
+// The public Rust wrapper type for our element
+glib_wrapper! {
+ pub struct Rgb2Gray(ObjectSubclass<imp::Rgb2Gray>) @extends gst_base::BaseTransform, gst::Element, gst::Object;
+}
+
+// GStreamer elements need to be thread-safe. For the private implementation this is automatically
+// enforced but for the public wrapper type we need to specify this manually.
+unsafe impl Send for Rgb2Gray {}
+unsafe impl Sync for Rgb2Gray {}
+
+// Registers the type for our element, and then registers in GStreamer under
+// the name "rsrgb2gray" for being able to instantiate it via e.g.
+// gst::ElementFactory::make().
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rsrgb2gray",
+ gst::Rank::None,
+ Rgb2Gray::static_type(),
+ )
+}
diff --git a/tutorial/src/sinesrc.rs b/tutorial/src/sinesrc/imp.rs
index ff2e5aff5..6f4b933fd 100644
--- a/tutorial/src/sinesrc.rs
+++ b/tutorial/src/sinesrc/imp.rs
@@ -24,6 +24,16 @@ use num_traits::float::Float;
use once_cell::sync::Lazy;
+// This module contains the private implementation details of our element
+
+static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
+ gst::DebugCategory::new(
+ "rssinesrc",
+ gst::DebugColorFlags::empty(),
+ Some("Rust Sine Wave Source"),
+ )
+});
+
// Default values of properties
const DEFAULT_SAMPLES_PER_BUFFER: u32 = 1024;
const DEFAULT_FREQ: u32 = 440;
@@ -134,20 +144,12 @@ struct ClockWait {
}
// Struct containing all the element data
-struct SineSrc {
+pub struct SineSrc {
settings: Mutex<Settings>,
state: Mutex<State>,
clock_wait: Mutex<ClockWait>,
}
-static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
- gst::DebugCategory::new(
- "rssinesrc",
- gst::DebugColorFlags::empty(),
- Some("Rust Sine Wave Source"),
- )
-});
-
impl SineSrc {
fn process<F: Float + FromByteSlice>(
data: &mut [u8],
@@ -198,6 +200,7 @@ impl SineSrc {
// up the class data
impl ObjectSubclass for SineSrc {
const NAME: &'static str = "RsSineSrc";
+ type Type = super::SineSrc;
type ParentType = gst_base::PushSrc;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -228,7 +231,7 @@ impl ObjectSubclass for SineSrc {
// will automatically instantiate pads for them.
//
// Our element here can output f32 and f64
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// retrieved from the gst::Registry after initial registration
@@ -281,22 +284,20 @@ impl ObjectSubclass for SineSrc {
// Implementation of glib::Object virtual methods
impl ObjectImpl for SineSrc {
// Called right after construction of a new instance
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
// Call the parent class' ::constructed() implementation first
self.parent_constructed(obj);
// Initialize live-ness and notify the base class that
// we'd like to operate in Time format
- let basesrc = obj.downcast_ref::<gst_base::BaseSrc>().unwrap();
- basesrc.set_live(DEFAULT_IS_LIVE);
- basesrc.set_format(gst::Format::Time);
+ obj.set_live(DEFAULT_IS_LIVE);
+ obj.set_format(gst::Format::Time);
}
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
- fn set_property(&self, obj: &glib::Object, id: usize, value: &glib::Value) {
+ fn set_property(&self, obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
- let basesrc = obj.downcast_ref::<gst_base::BaseSrc>().unwrap();
match *prop {
subclass::Property("samples-per-buffer", ..) => {
@@ -304,7 +305,7 @@ impl ObjectImpl for SineSrc {
let samples_per_buffer = value.get_some().expect("type checked upstream");
gst_info!(
CAT,
- obj: basesrc,
+ obj: obj,
"Changing samples-per-buffer from {} to {}",
settings.samples_per_buffer,
samples_per_buffer
@@ -312,14 +313,14 @@ impl ObjectImpl for SineSrc {
settings.samples_per_buffer = samples_per_buffer;
drop(settings);
- let _ = basesrc.post_message(gst::message::Latency::builder().src(basesrc).build());
+ let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
}
subclass::Property("freq", ..) => {
let mut settings = self.settings.lock().unwrap();
let freq = value.get_some().expect("type checked upstream");
gst_info!(
CAT,
- obj: basesrc,
+ obj: obj,
"Changing freq from {} to {}",
settings.freq,
freq
@@ -331,7 +332,7 @@ impl ObjectImpl for SineSrc {
let volume = value.get_some().expect("type checked upstream");
gst_info!(
CAT,
- obj: basesrc,
+ obj: obj,
"Changing volume from {} to {}",
settings.volume,
volume
@@ -343,7 +344,7 @@ impl ObjectImpl for SineSrc {
let mute = value.get_some().expect("type checked upstream");
gst_info!(
CAT,
- obj: basesrc,
+ obj: obj,
"Changing mute from {} to {}",
settings.mute,
mute
@@ -355,7 +356,7 @@ impl ObjectImpl for SineSrc {
let is_live = value.get_some().expect("type checked upstream");
gst_info!(
CAT,
- obj: basesrc,
+ obj: obj,
"Changing is-live from {} to {}",
settings.is_live,
is_live
@@ -368,7 +369,7 @@ impl ObjectImpl for SineSrc {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
- fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
+ fn get_property(&self, _obj: &Self::Type, id: usize) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
@@ -404,14 +405,12 @@ impl ElementImpl for SineSrc {
// the element again.
fn change_state(
&self,
- element: &gst::Element,
+ element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
- let basesrc = element.downcast_ref::<gst_base::BaseSrc>().unwrap();
-
// Configure live'ness once here just before starting the source
if let gst::StateChange::ReadyToPaused = transition {
- basesrc.set_live(self.settings.lock().unwrap().is_live);
+ element.set_live(self.settings.lock().unwrap().is_live);
}
// Call the parent class' implementation of ::change_state()
@@ -427,11 +426,7 @@ impl BaseSrcImpl for SineSrc {
//
// We simply remember the resulting AudioInfo from the caps to be able to use this for knowing
// the sample rate, etc. when creating buffers
- fn set_caps(
- &self,
- element: &gst_base::BaseSrc,
- caps: &gst::Caps,
- ) -> Result<(), gst::LoggableError> {
+ fn set_caps(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
use std::f64::consts::PI;
let info = gst_audio::AudioInfo::from_caps(caps).map_err(|_| {
@@ -481,7 +476,7 @@ impl BaseSrcImpl for SineSrc {
}
// Called when starting, so we can initialize all stream-related state to its defaults
- fn start(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> {
+ fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// Reset state
*self.state.lock().unwrap() = Default::default();
self.unlock_stop(element)?;
@@ -492,7 +487,7 @@ impl BaseSrcImpl for SineSrc {
}
// Called when shutting down the element so we can release all stream-related state
- fn stop(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> {
+ fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// Reset state
*self.state.lock().unwrap() = Default::default();
self.unlock(element)?;
@@ -502,7 +497,7 @@ impl BaseSrcImpl for SineSrc {
Ok(())
}
- fn query(&self, element: &gst_base::BaseSrc, query: &mut gst::QueryRef) -> bool {
+ fn query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool {
use gst::QueryView;
match query.view_mut() {
@@ -528,7 +523,7 @@ impl BaseSrcImpl for SineSrc {
}
}
- fn fixate(&self, element: &gst_base::BaseSrc, mut caps: gst::Caps) -> gst::Caps {
+ fn fixate(&self, element: &Self::Type, mut caps: gst::Caps) -> gst::Caps {
// Fixate the caps. BaseSrc will do some fixation for us, but
// as we allow any rate between 1 and MAX it would fixate to 1. 1Hz
// is generally not a useful sample rate.
@@ -549,11 +544,11 @@ impl BaseSrcImpl for SineSrc {
self.parent_fixate(element, caps)
}
- fn is_seekable(&self, _element: &gst_base::BaseSrc) -> bool {
+ fn is_seekable(&self, _element: &Self::Type) -> bool {
true
}
- fn do_seek(&self, element: &gst_base::BaseSrc, segment: &mut gst::Segment) -> bool {
+ fn do_seek(&self, element: &Self::Type, segment: &mut gst::Segment) -> bool {
// Handle seeking here. For Time and Default (sample offset) seeks we can
// do something and have to update our sample offset and accumulator accordingly.
//
@@ -659,7 +654,7 @@ impl BaseSrcImpl for SineSrc {
}
}
- fn unlock(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> {
+ fn unlock(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// This should unblock the create() function ASAP, so we
// just unschedule the clock it here, if any.
gst_debug!(CAT, obj: element, "Unlocking");
@@ -672,7 +667,7 @@ impl BaseSrcImpl for SineSrc {
Ok(())
}
- fn unlock_stop(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> {
+ fn unlock_stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// This signals that unlocking is done, so we can reset
// all values again.
gst_debug!(CAT, obj: element, "Unlock stop");
@@ -685,7 +680,7 @@ impl BaseSrcImpl for SineSrc {
impl PushSrcImpl for SineSrc {
// Creates the audio buffers
- fn create(&self, element: &gst_base::PushSrc) -> Result<gst::Buffer, gst::FlowError> {
+ fn create(&self, element: &Self::Type) -> Result<gst::Buffer, gst::FlowError> {
// Keep a local copy of the values of all our properties at this very moment. This
// ensures that the mutex is never locked for long and the application wouldn't
// have to block until this function returns when getting/setting property values
@@ -830,15 +825,3 @@ impl PushSrcImpl for SineSrc {
Ok(buffer)
}
}
-
-// Registers the type for our element, and then registers in GStreamer under
-// the name "sinesrc" for being able to instantiate it via e.g.
-// gst::ElementFactory::make().
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rssinesrc",
- gst::Rank::None,
- SineSrc::get_type(),
- )
-}
diff --git a/tutorial/src/sinesrc/mod.rs b/tutorial/src/sinesrc/mod.rs
new file mode 100644
index 000000000..7baf92280
--- /dev/null
+++ b/tutorial/src/sinesrc/mod.rs
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 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::prelude::*;
+
+mod imp;
+
+// The public Rust wrapper type for our element
+glib_wrapper! {
+ pub struct SineSrc(ObjectSubclass<imp::SineSrc>) @extends gst_base::BaseSrc, gst::Element, gst::Object;
+}
+
+// GStreamer elements need to be thread-safe. For the private implementation this is automatically
+// enforced but for the public wrapper type we need to specify this manually.
+unsafe impl Send for SineSrc {}
+unsafe impl Sync for SineSrc {}
+
+// Registers the type for our element, and then registers in GStreamer under
+// the name "sinesrc" for being able to instantiate it via e.g.
+// gst::ElementFactory::make().
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rssinesrc",
+ gst::Rank::None,
+ SineSrc::static_type(),
+ )
+}