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:
-rw-r--r--video/cdg/src/cdgdec/imp.rs (renamed from video/cdg/src/cdgdec.rs)32
-rw-r--r--video/cdg/src/cdgdec/mod.rs29
-rw-r--r--video/cdg/src/cdgparse/imp.rs (renamed from video/cdg/src/cdgparse.rs)20
-rw-r--r--video/cdg/src/cdgparse/mod.rs29
-rw-r--r--video/cdg/src/lib.rs83
-rw-r--r--video/cdg/src/typefind.rs87
-rw-r--r--video/closedcaption/src/caption_frame.rs2
-rw-r--r--video/closedcaption/src/ccdetect/imp.rs (renamed from video/closedcaption/src/ccdetect.rs)28
-rw-r--r--video/closedcaption/src/ccdetect/mod.rs38
-rw-r--r--video/closedcaption/src/cea608overlay/imp.rs (renamed from video/closedcaption/src/cea608overlay.rs)45
-rw-r--r--video/closedcaption/src/cea608overlay/mod.rs44
-rw-r--r--video/closedcaption/src/cea608tott/imp.rs (renamed from video/closedcaption/src/cea608tott.rs)30
-rw-r--r--video/closedcaption/src/cea608tott/mod.rs29
-rw-r--r--video/closedcaption/src/ffi.rs (renamed from video/closedcaption/src/cea608tott_ffi.rs)0
-rw-r--r--video/closedcaption/src/lib.rs16
-rw-r--r--video/closedcaption/src/mcc_enc/headers.rs (renamed from video/closedcaption/src/mcc_enc_headers.rs)0
-rw-r--r--video/closedcaption/src/mcc_enc/imp.rs (renamed from video/closedcaption/src/mcc_enc.rs)48
-rw-r--r--video/closedcaption/src/mcc_enc/mod.rs39
-rw-r--r--video/closedcaption/src/mcc_parse/imp.rs (renamed from video/closedcaption/src/mcc_parse.rs)70
-rw-r--r--video/closedcaption/src/mcc_parse/mod.rs39
-rw-r--r--video/closedcaption/src/mcc_parse/parser.rs (renamed from video/closedcaption/src/mcc_parser.rs)2
-rw-r--r--video/closedcaption/src/scc_enc/imp.rs (renamed from video/closedcaption/src/scc_enc.rs)43
-rw-r--r--video/closedcaption/src/scc_enc/mod.rs39
-rw-r--r--video/closedcaption/src/scc_parse/imp.rs (renamed from video/closedcaption/src/scc_parse.rs)51
-rw-r--r--video/closedcaption/src/scc_parse/mod.rs40
-rw-r--r--video/closedcaption/src/scc_parse/parser.rs (renamed from video/closedcaption/src/scc_parser.rs)2
-rw-r--r--video/closedcaption/src/tttocea608/imp.rs (renamed from video/closedcaption/src/tttocea608.rs)55
-rw-r--r--video/closedcaption/src/tttocea608/mod.rs49
-rw-r--r--video/dav1d/src/dav1ddec/imp.rs (renamed from video/dav1d/src/dav1ddec.rs)37
-rw-r--r--video/dav1d/src/dav1ddec/mod.rs29
-rw-r--r--video/flavors/src/flvdemux/imp.rs (renamed from video/flavors/src/flvdemux.rs)73
-rw-r--r--video/flavors/src/flvdemux/mod.rs29
-rw-r--r--video/gif/src/gifenc/imp.rs (renamed from video/gif/src/gifenc.rs)38
-rw-r--r--video/gif/src/gifenc/mod.rs29
-rw-r--r--video/gif/src/lib.rs1
-rw-r--r--video/rav1e/src/rav1enc/imp.rs (renamed from video/rav1e/src/rav1enc.rs)33
-rw-r--r--video/rav1e/src/rav1enc/mod.rs29
-rw-r--r--video/rspng/src/pngenc/imp.rs (renamed from video/rspng/src/pngenc.rs)97
-rw-r--r--video/rspng/src/pngenc/mod.rs98
39 files changed, 943 insertions, 539 deletions
diff --git a/video/cdg/src/cdgdec.rs b/video/cdg/src/cdgdec/imp.rs
index 92d1a34ad..2a2365d1c 100644
--- a/video/cdg/src/cdgdec.rs
+++ b/video/cdg/src/cdgdec/imp.rs
@@ -17,18 +17,19 @@ use std::sync::Mutex;
use crate::constants::{CDG_HEIGHT, CDG_WIDTH};
-struct CdgDec {
- cdg_inter: Mutex<Box<cdg_renderer::CdgInterpreter>>,
- output_info: Mutex<Option<gst_video::VideoInfo>>,
-}
-
lazy_static! {
static ref CAT: gst::DebugCategory =
gst::DebugCategory::new("cdgdec", gst::DebugColorFlags::empty(), Some("CDG decoder"),);
}
+pub struct CdgDec {
+ cdg_inter: Mutex<Box<cdg_renderer::CdgInterpreter>>,
+ output_info: Mutex<Option<gst_video::VideoInfo>>,
+}
+
impl ObjectSubclass for CdgDec {
const NAME: &'static str = "CdgDec";
+ type Type = super::CdgDec;
type ParentType = gst_video::VideoDecoder;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -42,7 +43,7 @@ impl ObjectSubclass for CdgDec {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"CDG decoder",
"Decoder/Video",
@@ -85,14 +86,14 @@ impl ObjectImpl for CdgDec {}
impl ElementImpl for CdgDec {}
impl VideoDecoderImpl for CdgDec {
- fn start(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> {
+ fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
let mut out_info = self.output_info.lock().unwrap();
*out_info = None;
self.parent_start(element)
}
- fn stop(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> {
+ fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
{
let mut cdg_inter = self.cdg_inter.lock().unwrap();
cdg_inter.reset(true);
@@ -102,7 +103,7 @@ impl VideoDecoderImpl for CdgDec {
fn handle_frame(
&self,
- element: &gst_video::VideoDecoder,
+ element: &Self::Type,
mut frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
{
@@ -192,7 +193,7 @@ impl VideoDecoderImpl for CdgDec {
fn decide_allocation(
&self,
- element: &gst_video::VideoDecoder,
+ element: &Self::Type,
query: &mut gst::QueryRef,
) -> Result<(), gst::ErrorMessage> {
if let gst::query::QueryView::Allocation(allocation) = query.view() {
@@ -216,7 +217,7 @@ impl VideoDecoderImpl for CdgDec {
self.parent_decide_allocation(element, query)
}
- fn flush(&self, element: &gst_video::VideoDecoder) -> bool {
+ fn flush(&self, element: &Self::Type) -> bool {
gst_debug!(CAT, obj: element, "flushing, reset CDG interpreter");
let mut cdg_inter = self.cdg_inter.lock().unwrap();
@@ -224,12 +225,3 @@ impl VideoDecoderImpl for CdgDec {
true
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "cdgdec",
- gst::Rank::Primary,
- CdgDec::get_type(),
- )
-}
diff --git a/video/cdg/src/cdgdec/mod.rs b/video/cdg/src/cdgdec/mod.rs
new file mode 100644
index 000000000..daf17cb42
--- /dev/null
+++ b/video/cdg/src/cdgdec/mod.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.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;
+
+glib_wrapper! {
+ pub struct CdgDec(ObjectSubclass<imp::CdgDec>) @extends gst_video::VideoDecoder, 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 CdgDec {}
+unsafe impl Sync for CdgDec {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "cdgdec",
+ gst::Rank::Primary,
+ CdgDec::static_type(),
+ )
+}
diff --git a/video/cdg/src/cdgparse.rs b/video/cdg/src/cdgparse/imp.rs
index 50b46072b..7b564a5a1 100644
--- a/video/cdg/src/cdgparse.rs
+++ b/video/cdg/src/cdgparse/imp.rs
@@ -23,7 +23,7 @@ const CDG_CMD_MEMORY_PRESET: u8 = 1;
const CDG_CMD_MEMORY_LOAD_COLOR_TABLE_1: u8 = 30;
const CDG_CMD_MEMORY_LOAD_COLOR_TABLE_2: u8 = 31;
-struct CdgParse;
+pub struct CdgParse;
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
@@ -35,6 +35,7 @@ lazy_static! {
impl ObjectSubclass for CdgParse {
const NAME: &'static str = "CdgParse";
+ type Type = super::CdgParse;
type ParentType = gst_base::BaseParse;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -45,7 +46,7 @@ impl ObjectSubclass for CdgParse {
Self
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"CDG parser",
"Codec/Parser/Video",
@@ -108,7 +109,7 @@ fn time_to_bytes(time: gst::ClockTime) -> Bytes {
}
impl BaseParseImpl for CdgParse {
- fn start(&self, element: &gst_base::BaseParse) -> Result<(), gst::ErrorMessage> {
+ fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
element.set_min_frame_size(CDG_PACKET_SIZE as u32);
/* Set duration */
@@ -125,7 +126,7 @@ impl BaseParseImpl for CdgParse {
fn handle_frame(
&self,
- element: &gst_base::BaseParse,
+ element: &Self::Type,
mut frame: gst_base::BaseParseFrame,
) -> Result<(gst::FlowSuccess, u32), gst::FlowError> {
let pad = element.get_src_pad();
@@ -212,7 +213,7 @@ impl BaseParseImpl for CdgParse {
fn convert<V: Into<gst::GenericFormattedValue>>(
&self,
- _element: &gst_base::BaseParse,
+ _element: &Self::Type,
src_val: V,
dest_format: gst::Format,
) -> Option<gst::GenericFormattedValue> {
@@ -229,12 +230,3 @@ impl BaseParseImpl for CdgParse {
}
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "cdgparse",
- gst::Rank::Primary,
- CdgParse::get_type(),
- )
-}
diff --git a/video/cdg/src/cdgparse/mod.rs b/video/cdg/src/cdgparse/mod.rs
new file mode 100644
index 000000000..10cac351f
--- /dev/null
+++ b/video/cdg/src/cdgparse/mod.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.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;
+
+glib_wrapper! {
+ pub struct CdgParse(ObjectSubclass<imp::CdgParse>) @extends gst_base::BaseParse, 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 CdgParse {}
+unsafe impl Sync for CdgParse {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "cdgparse",
+ gst::Rank::Primary,
+ CdgParse::static_type(),
+ )
+}
diff --git a/video/cdg/src/lib.rs b/video/cdg/src/lib.rs
index 4083adc7b..c5e5bb513 100644
--- a/video/cdg/src/lib.rs
+++ b/video/cdg/src/lib.rs
@@ -18,91 +18,12 @@ extern crate lazy_static;
mod cdgdec;
mod cdgparse;
mod constants;
-
-use constants::{CDG_COMMAND, CDG_MASK, CDG_PACKET_PERIOD, CDG_PACKET_SIZE};
-use gst::{Caps, TypeFind, TypeFindProbability};
-use std::cmp;
-
-const NB_WINDOWS: u64 = 8;
-const TYPEFIND_SEARCH_WINDOW_SEC: i64 = 4;
-const TYPEFIND_SEARCH_WINDOW: i64 =
- TYPEFIND_SEARCH_WINDOW_SEC * (CDG_PACKET_SIZE as i64 * CDG_PACKET_PERIOD as i64); /* in bytes */
-
-/* Return the percentage of CDG packets in the first @len bytes of @typefind */
-fn cdg_packets_ratio(typefind: &mut TypeFind, start: i64, len: i64) -> i64 {
- let mut count = 0;
- let total = len / CDG_PACKET_SIZE as i64;
-
- for offset in (0..len).step_by(CDG_PACKET_SIZE as usize) {
- match typefind.peek(start + offset, CDG_PACKET_SIZE as u32) {
- Some(data) => {
- if data[0] & CDG_MASK == CDG_COMMAND {
- count += 1;
- }
- }
- None => break,
- }
- }
- (count * 100) / total
-}
-
-/* Some CDG files starts drawing right away and then pause for a while
- * (typically because of the song intro) while other wait for a few
- * seconds before starting to draw.
- * In order to support all variants, scan through all the file per block
- * of size TYPEFIND_SEARCH_WINDOW and keep the highest ratio of CDG packets
- * detected. */
-fn compute_probability(typefind: &mut TypeFind) -> TypeFindProbability {
- let mut best = TypeFindProbability::None;
- // Try looking at the start of the file if its length isn't available
- let len = typefind
- .get_length()
- .unwrap_or(TYPEFIND_SEARCH_WINDOW as u64 * NB_WINDOWS);
- let step = len / NB_WINDOWS;
-
- // Too short file
- if step == 0 {
- return TypeFindProbability::None;
- }
-
- for offset in (0..len).step_by(step as usize) {
- let proba = match cdg_packets_ratio(typefind, offset as i64, TYPEFIND_SEARCH_WINDOW) {
- 0..=5 => TypeFindProbability::None,
- 6..=10 => TypeFindProbability::Possible,
- _ => TypeFindProbability::Likely,
- };
-
- if proba == TypeFindProbability::Likely {
- return proba;
- }
-
- best = cmp::max(best, proba);
- }
-
- best
-}
-
-fn typefind_register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- TypeFind::register(
- Some(plugin),
- "cdg_typefind",
- gst::Rank::None,
- Some("cdg"),
- Some(&Caps::new_simple("video/x-cdg", &[])),
- |mut typefind| {
- let proba = compute_probability(&mut typefind);
-
- if proba != gst::TypeFindProbability::None {
- typefind.suggest(proba, &Caps::new_simple("video/x-cdg", &[]));
- }
- },
- )
-}
+mod typefind;
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
cdgdec::register(plugin)?;
cdgparse::register(plugin)?;
- typefind_register(plugin)?;
+ typefind::register(plugin)?;
Ok(())
}
diff --git a/video/cdg/src/typefind.rs b/video/cdg/src/typefind.rs
new file mode 100644
index 000000000..e81438497
--- /dev/null
+++ b/video/cdg/src/typefind.rs
@@ -0,0 +1,87 @@
+// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.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 crate::constants::{CDG_COMMAND, CDG_MASK, CDG_PACKET_PERIOD, CDG_PACKET_SIZE};
+use gst::{Caps, TypeFind, TypeFindProbability};
+use std::cmp;
+
+const NB_WINDOWS: u64 = 8;
+const TYPEFIND_SEARCH_WINDOW_SEC: i64 = 4;
+const TYPEFIND_SEARCH_WINDOW: i64 =
+ TYPEFIND_SEARCH_WINDOW_SEC * (CDG_PACKET_SIZE as i64 * CDG_PACKET_PERIOD as i64); /* in bytes */
+
+/* Return the percentage of CDG packets in the first @len bytes of @typefind */
+fn cdg_packets_ratio(typefind: &mut TypeFind, start: i64, len: i64) -> i64 {
+ let mut count = 0;
+ let total = len / CDG_PACKET_SIZE as i64;
+
+ for offset in (0..len).step_by(CDG_PACKET_SIZE as usize) {
+ match typefind.peek(start + offset, CDG_PACKET_SIZE as u32) {
+ Some(data) => {
+ if data[0] & CDG_MASK == CDG_COMMAND {
+ count += 1;
+ }
+ }
+ None => break,
+ }
+ }
+ (count * 100) / total
+}
+
+/* Some CDG files starts drawing right away and then pause for a while
+ * (typically because of the song intro) while other wait for a few
+ * seconds before starting to draw.
+ * In order to support all variants, scan through all the file per block
+ * of size TYPEFIND_SEARCH_WINDOW and keep the highest ratio of CDG packets
+ * detected. */
+fn compute_probability(typefind: &mut TypeFind) -> TypeFindProbability {
+ let mut best = TypeFindProbability::None;
+ // Try looking at the start of the file if its length isn't available
+ let len = typefind
+ .get_length()
+ .unwrap_or(TYPEFIND_SEARCH_WINDOW as u64 * NB_WINDOWS);
+ let step = len / NB_WINDOWS;
+
+ // Too short file
+ if step == 0 {
+ return TypeFindProbability::None;
+ }
+
+ for offset in (0..len).step_by(step as usize) {
+ let proba = match cdg_packets_ratio(typefind, offset as i64, TYPEFIND_SEARCH_WINDOW) {
+ 0..=5 => TypeFindProbability::None,
+ 6..=10 => TypeFindProbability::Possible,
+ _ => TypeFindProbability::Likely,
+ };
+
+ if proba == TypeFindProbability::Likely {
+ return proba;
+ }
+
+ best = cmp::max(best, proba);
+ }
+
+ best
+}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ TypeFind::register(
+ Some(plugin),
+ "cdg_typefind",
+ gst::Rank::None,
+ Some("cdg"),
+ Some(&Caps::new_simple("video/x-cdg", &[])),
+ |mut typefind| {
+ let proba = compute_probability(&mut typefind);
+
+ if proba != gst::TypeFindProbability::None {
+ typefind.suggest(proba, &Caps::new_simple("video/x-cdg", &[]));
+ }
+ },
+ )
+}
diff --git a/video/closedcaption/src/caption_frame.rs b/video/closedcaption/src/caption_frame.rs
index ac5aad5df..724757500 100644
--- a/video/closedcaption/src/caption_frame.rs
+++ b/video/closedcaption/src/caption_frame.rs
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use super::cea608tott_ffi as ffi;
+use super::ffi;
use std::mem;
#[derive(Copy, Clone, Debug)]
diff --git a/video/closedcaption/src/ccdetect.rs b/video/closedcaption/src/ccdetect/imp.rs
index 6c51c538d..488c1b16e 100644
--- a/video/closedcaption/src/ccdetect.rs
+++ b/video/closedcaption/src/ccdetect/imp.rs
@@ -69,7 +69,7 @@ struct State {
last_cc708_change: gst::ClockTime,
}
-struct CCDetect {
+pub struct CCDetect {
settings: Mutex<Settings>,
state: Mutex<Option<State>>,
}
@@ -321,7 +321,7 @@ impl CCDetect {
fn maybe_update_properties(
&self,
- element: &gst_base::BaseTransform,
+ element: &super::CCDetect,
ts: gst::ClockTime,
cc_packet: CCPacketContents,
) -> Result<(), gst::FlowError> {
@@ -382,6 +382,7 @@ impl CCDetect {
impl ObjectSubclass for CCDetect {
const NAME: &'static str = "CCDetect";
+ type Type = super::CCDetect;
type ParentType = gst_base::BaseTransform;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -395,7 +396,7 @@ impl ObjectSubclass for CCDetect {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Closed Caption Detect",
"Filter/Video/ClosedCaption/Detect",
@@ -441,7 +442,7 @@ impl ObjectSubclass for CCDetect {
}
impl ObjectImpl for CCDetect {
- 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];
match *prop {
@@ -453,7 +454,7 @@ impl ObjectImpl for CCDetect {
}
}
- 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 {
@@ -479,7 +480,7 @@ impl ElementImpl for CCDetect {}
impl BaseTransformImpl for CCDetect {
fn transform_ip_passthrough(
&self,
- element: &gst_base::BaseTransform,
+ element: &Self::Type,
buf: &gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let map = buf.map_readable().map_err(|_| gst::FlowError::Error)?;
@@ -517,7 +518,7 @@ impl BaseTransformImpl for CCDetect {
Ok(gst::FlowSuccess::Ok)
}
- fn sink_event(&self, element: &gst_base::BaseTransform, event: gst::Event) -> bool {
+ fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
match event.view() {
gst::event::EventView::Gap(gap) => {
let _ = self.maybe_update_properties(
@@ -536,7 +537,7 @@ impl BaseTransformImpl for CCDetect {
fn set_caps(
&self,
- _element: &gst_base::BaseTransform,
+ _element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
@@ -569,19 +570,10 @@ impl BaseTransformImpl for CCDetect {
Ok(())
}
- 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();
Ok(())
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "ccdetect",
- gst::Rank::None,
- CCDetect::get_type(),
- )
-}
diff --git a/video/closedcaption/src/ccdetect/mod.rs b/video/closedcaption/src/ccdetect/mod.rs
new file mode 100644
index 000000000..11a82b86b
--- /dev/null
+++ b/video/closedcaption/src/ccdetect/mod.rs
@@ -0,0 +1,38 @@
+// Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
+//
+// 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 Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+use glib::prelude::*;
+
+mod imp;
+
+glib_wrapper! {
+ pub struct CCDetect(ObjectSubclass<imp::CCDetect>) @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 CCDetect {}
+unsafe impl Sync for CCDetect {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "ccdetect",
+ gst::Rank::None,
+ CCDetect::static_type(),
+ )
+}
diff --git a/video/closedcaption/src/cea608overlay.rs b/video/closedcaption/src/cea608overlay/imp.rs
index 0df857c78..e55c16c8c 100644
--- a/video/closedcaption/src/cea608overlay.rs
+++ b/video/closedcaption/src/cea608overlay/imp.rs
@@ -15,13 +15,6 @@
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.
-// Example command-line:
-//
-// gst-launch-1.0 cccombiner name=ccc ! cea608overlay ! autovideosink \
-// videotestsrc ! video/x-raw, width=1280, height=720 ! queue ! ccc.sink \
-// filesrc location=input.srt ! subparse ! tttocea608 ! queue ! ccc.caption
-
-use glib::prelude::*;
use glib::subclass;
use glib::subclass::prelude::*;
use gst::prelude::*;
@@ -68,7 +61,7 @@ impl Default for State {
unsafe impl Send for State {}
-struct Cea608Overlay {
+pub struct Cea608Overlay {
srcpad: gst::Pad,
sinkpad: gst::Pad,
state: Mutex<State>,
@@ -86,7 +79,7 @@ impl Cea608Overlay {
// TODO: switch to the API presented in this post once it's been exposed
fn recalculate_layout(
&self,
- element: &gst::Element,
+ element: &super::Cea608Overlay,
state: &mut State,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let video_info = state.video_info.as_ref().unwrap();
@@ -242,7 +235,7 @@ impl Cea608Overlay {
fn negotiate(
&self,
- element: &gst::Element,
+ element: &super::Cea608Overlay,
state: &mut State,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let video_info = match state.video_info.as_ref() {
@@ -294,7 +287,7 @@ impl Cea608Overlay {
fn sink_chain(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::Cea608Overlay,
mut buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -358,7 +351,12 @@ impl Cea608Overlay {
self.srcpad.push(buffer)
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(
+ &self,
+ pad: &gst::Pad,
+ element: &super::Cea608Overlay,
+ event: gst::Event,
+ ) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -388,13 +386,14 @@ impl Cea608Overlay {
impl ObjectSubclass for Cea608Overlay {
const NAME: &'static str = "RsCea608Overlay";
+ type Type = super::Cea608Overlay;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
@@ -426,7 +425,7 @@ impl ObjectSubclass for Cea608Overlay {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Cea 608 overlay",
"Video/Overlay/Subtitle",
@@ -460,19 +459,18 @@ impl ObjectSubclass for Cea608Overlay {
}
impl ObjectImpl for Cea608Overlay {
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- 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();
}
}
impl ElementImpl for Cea608Overlay {
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);
@@ -489,12 +487,3 @@ impl ElementImpl for Cea608Overlay {
self.parent_change_state(element, transition)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "cea608overlay",
- gst::Rank::Primary,
- Cea608Overlay::get_type(),
- )
-}
diff --git a/video/closedcaption/src/cea608overlay/mod.rs b/video/closedcaption/src/cea608overlay/mod.rs
new file mode 100644
index 000000000..54669bf3e
--- /dev/null
+++ b/video/closedcaption/src/cea608overlay/mod.rs
@@ -0,0 +1,44 @@
+// Copyright (C) 2020 Mathieu Duponchelle <mathieu@centricular.com>
+//
+// 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 Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+// Example command-line:
+//
+// gst-launch-1.0 cccombiner name=ccc ! cea608overlay ! autovideosink \
+// videotestsrc ! video/x-raw, width=1280, height=720 ! queue ! ccc.sink \
+// filesrc location=input.srt ! subparse ! tttocea608 ! queue ! ccc.caption
+
+use glib::prelude::*;
+
+mod imp;
+
+glib_wrapper! {
+ pub struct Cea608Overlay(ObjectSubclass<imp::Cea608Overlay>) @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 Cea608Overlay {}
+unsafe impl Sync for Cea608Overlay {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "cea608overlay",
+ gst::Rank::Primary,
+ Cea608Overlay::static_type(),
+ )
+}
diff --git a/video/closedcaption/src/cea608tott.rs b/video/closedcaption/src/cea608tott/imp.rs
index edcb8002f..6dbc36ace 100644
--- a/video/closedcaption/src/cea608tott.rs
+++ b/video/closedcaption/src/cea608tott/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::*;
@@ -42,7 +41,7 @@ impl Default for State {
}
}
-struct Cea608ToTt {
+pub struct Cea608ToTt {
srcpad: gst::Pad,
sinkpad: gst::Pad,
@@ -61,7 +60,7 @@ impl Cea608ToTt {
fn sink_chain(
&self,
pad: &gst::Pad,
- _element: &gst::Element,
+ _element: &super::Cea608ToTt,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -271,7 +270,7 @@ impl Cea608ToTt {
buffer
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, element: &super::Cea608ToTt, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -371,13 +370,14 @@ impl Cea608ToTt {
impl ObjectSubclass for Cea608ToTt {
const NAME: &'static str = "Cea608ToTt";
+ type Type = super::Cea608ToTt;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
@@ -409,7 +409,7 @@ impl ObjectSubclass for Cea608ToTt {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"CEA-608 to TT",
"Generic",
@@ -461,19 +461,18 @@ impl ObjectSubclass for Cea608ToTt {
}
impl ObjectImpl for Cea608ToTt {
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- 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();
}
}
impl ElementImpl for Cea608ToTt {
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);
@@ -499,12 +498,3 @@ impl ElementImpl for Cea608ToTt {
Ok(ret)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "cea608tott",
- gst::Rank::None,
- Cea608ToTt::get_type(),
- )
-}
diff --git a/video/closedcaption/src/cea608tott/mod.rs b/video/closedcaption/src/cea608tott/mod.rs
new file mode 100644
index 000000000..51b23dc8a
--- /dev/null
+++ b/video/closedcaption/src/cea608tott/mod.rs
@@ -0,0 +1,29 @@
+// 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;
+
+glib_wrapper! {
+ pub struct Cea608ToTt(ObjectSubclass<imp::Cea608ToTt>) @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 Cea608ToTt {}
+unsafe impl Sync for Cea608ToTt {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "cea608tott",
+ gst::Rank::None,
+ Cea608ToTt::static_type(),
+ )
+}
diff --git a/video/closedcaption/src/cea608tott_ffi.rs b/video/closedcaption/src/ffi.rs
index a59e87fca..a59e87fca 100644
--- a/video/closedcaption/src/cea608tott_ffi.rs
+++ b/video/closedcaption/src/ffi.rs
diff --git a/video/closedcaption/src/lib.rs b/video/closedcaption/src/lib.rs
index 9ba22abf8..65690d40c 100644
--- a/video/closedcaption/src/lib.rs
+++ b/video/closedcaption/src/lib.rs
@@ -17,11 +17,6 @@
#![recursion_limit = "128"]
-// These macros are in weird paths currently,
-// and extern crate is used to avoid the explicit imports
-// should not be needed ideally in the upcoming releases.
-// https://github.com/gtk-rs/glib/issues/420
-// https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/issues/170
#[macro_use]
extern crate glib;
#[macro_use]
@@ -33,21 +28,20 @@ extern crate lazy_static;
#[macro_use]
extern crate pretty_assertions;
+#[allow(non_camel_case_types, non_upper_case_globals, unused)]
+#[allow(clippy::redundant_static_lifetimes, clippy::unreadable_literal)]
+#[allow(clippy::useless_transmute, clippy::trivially_copy_pass_by_ref)]
+mod ffi;
+
mod caption_frame;
mod ccdetect;
mod cea608overlay;
mod cea608tott;
-#[allow(non_camel_case_types, non_upper_case_globals)]
-#[allow(clippy::redundant_static_lifetimes, clippy::unreadable_literal)]
-#[allow(clippy::useless_transmute, clippy::trivially_copy_pass_by_ref)]
-pub mod cea608tott_ffi;
mod line_reader;
mod mcc_enc;
mod mcc_parse;
-mod mcc_parser;
mod scc_enc;
mod scc_parse;
-mod scc_parser;
mod tttocea608;
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
diff --git a/video/closedcaption/src/mcc_enc_headers.rs b/video/closedcaption/src/mcc_enc/headers.rs
index 6995c99c3..6995c99c3 100644
--- a/video/closedcaption/src/mcc_enc_headers.rs
+++ b/video/closedcaption/src/mcc_enc/headers.rs
diff --git a/video/closedcaption/src/mcc_enc.rs b/video/closedcaption/src/mcc_enc/imp.rs
index 6acfb3aab..9dac0fe28 100644
--- a/video/closedcaption/src/mcc_enc.rs
+++ b/video/closedcaption/src/mcc_enc/imp.rs
@@ -28,9 +28,7 @@ use uuid::Uuid;
use std::io::Write;
use std::sync::Mutex;
-#[path = "mcc_enc_headers.rs"]
-mod mcc_enc_headers;
-use self::mcc_enc_headers::*;
+use super::headers::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Format {
@@ -89,7 +87,7 @@ static PROPERTIES: [subclass::Property; 2] = [
}),
];
-struct MccEnc {
+pub struct MccEnc {
srcpad: gst::Pad,
sinkpad: gst::Pad,
state: Mutex<State>,
@@ -291,7 +289,7 @@ impl MccEnc {
fn generate_caption(
&self,
- element: &gst::Element,
+ element: &super::MccEnc,
state: &State,
buffer: &gst::Buffer,
outbuf: &mut Vec<u8>,
@@ -359,7 +357,7 @@ impl MccEnc {
fn sink_chain(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::MccEnc,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -383,7 +381,7 @@ impl MccEnc {
self.srcpad.push(buf)
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, element: &super::MccEnc, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -426,7 +424,7 @@ impl MccEnc {
}
}
- fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn src_event(&self, pad: &gst::Pad, element: &super::MccEnc, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -439,7 +437,12 @@ impl MccEnc {
}
}
- fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
+ fn src_query(
+ &self,
+ pad: &gst::Pad,
+ element: &super::MccEnc,
+ query: &mut gst::QueryRef,
+ ) -> bool {
use gst::QueryView;
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@@ -462,13 +465,14 @@ impl MccEnc {
impl ObjectSubclass for MccEnc {
const NAME: &'static str = "RsMccEnc";
+ type Type = super::MccEnc;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
@@ -513,7 +517,7 @@ impl ObjectSubclass for MccEnc {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Mcc Encoder",
"Encoder/ClosedCaption",
@@ -571,7 +575,7 @@ impl ObjectSubclass for MccEnc {
}
impl ObjectImpl for MccEnc {
- 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];
match *prop {
@@ -587,7 +591,7 @@ impl ObjectImpl for MccEnc {
}
}
- 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 {
@@ -603,19 +607,18 @@ impl ObjectImpl for MccEnc {
}
}
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- 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();
}
}
impl ElementImpl for MccEnc {
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);
@@ -632,12 +635,3 @@ impl ElementImpl for MccEnc {
self.parent_change_state(element, transition)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "mccenc",
- gst::Rank::Primary,
- MccEnc::get_type(),
- )
-}
diff --git a/video/closedcaption/src/mcc_enc/mod.rs b/video/closedcaption/src/mcc_enc/mod.rs
new file mode 100644
index 000000000..f3c1f0d30
--- /dev/null
+++ b/video/closedcaption/src/mcc_enc/mod.rs
@@ -0,0 +1,39 @@
+// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
+//
+// 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 Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+use glib::prelude::*;
+
+mod headers;
+mod imp;
+
+glib_wrapper! {
+ pub struct MccEnc(ObjectSubclass<imp::MccEnc>) @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 MccEnc {}
+unsafe impl Sync for MccEnc {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "mccenc",
+ gst::Rank::Primary,
+ MccEnc::static_type(),
+ )
+}
diff --git a/video/closedcaption/src/mcc_parse.rs b/video/closedcaption/src/mcc_parse/imp.rs
index 90304b2f7..1f93db5e8 100644
--- a/video/closedcaption/src/mcc_parse.rs
+++ b/video/closedcaption/src/mcc_parse/imp.rs
@@ -26,8 +26,8 @@ use std::cmp;
use std::convert::TryInto;
use std::sync::{Mutex, MutexGuard};
+use super::parser::{MccLine, MccParser, TimeCode};
use crate::line_reader::LineReader;
-use crate::mcc_parser::{MccLine, MccParser, TimeCode};
lazy_static! {
static ref CAT: gst::DebugCategory = {
@@ -54,7 +54,7 @@ struct PullState {
}
impl PullState {
- fn new(element: &gst::Element, pad: &gst::Pad) -> Self {
+ fn new(element: &super::MccParse, pad: &gst::Pad) -> Self {
Self {
need_stream_start: true,
stream_id: pad
@@ -180,7 +180,7 @@ impl State {
fn handle_timecode(
&mut self,
- element: &gst::Element,
+ element: &super::MccParse,
framerate: gst::Fraction,
drop_frame: bool,
tc: TimeCode,
@@ -219,7 +219,7 @@ impl State {
/// not produce timestamps jumping backwards
fn update_timestamp(
&mut self,
- element: &gst::Element,
+ element: &super::MccParse,
timecode: &gst_video::ValidVideoTimeCode,
) {
let nsecs = gst::ClockTime::from(timecode.nsec_since_daily_jam());
@@ -255,7 +255,7 @@ impl State {
fn add_buffer_metadata(
&mut self,
- element: &gst::Element,
+ element: &super::MccParse,
buffer: &mut gst::buffer::Buffer,
timecode: &gst_video::ValidVideoTimeCode,
framerate: gst::Fraction,
@@ -281,7 +281,7 @@ impl State {
fn create_events(
&mut self,
- element: &gst::Element,
+ element: &super::MccParse,
format: Option<Format>,
framerate: gst::Fraction,
) -> Vec<gst::Event> {
@@ -341,7 +341,7 @@ impl State {
}
}
-struct MccParse {
+pub struct MccParse {
srcpad: gst::Pad,
sinkpad: gst::Pad,
state: Mutex<State>,
@@ -369,7 +369,7 @@ impl AsMut<[u8]> for OffsetVec {
impl MccParse {
fn handle_buffer(
&self,
- element: &gst::Element,
+ element: &super::MccParse,
buffer: Option<gst::Buffer>,
scan_tc_rate: bool,
) -> Result<gst::FlowSuccess, gst::FlowError> {
@@ -513,7 +513,7 @@ impl MccParse {
fn handle_skipped_line(
&self,
- element: &gst::Element,
+ element: &super::MccParse,
tc: TimeCode,
mut state: MutexGuard<State>,
) -> Result<MutexGuard<State>, gst::FlowError> {
@@ -537,7 +537,7 @@ impl MccParse {
fn handle_line(
&self,
- element: &gst::Element,
+ element: &super::MccParse,
tc: TimeCode,
data: Vec<u8>,
format: Format,
@@ -587,7 +587,7 @@ impl MccParse {
fn sink_activate(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::MccParse,
) -> Result<(), gst::LoggableError> {
let mode = {
let mut query = gst::query::Scheduling::new();
@@ -616,7 +616,7 @@ impl MccParse {
Ok(())
}
- fn start_task(&self, element: &gst::Element) -> Result<(), gst::LoggableError> {
+ fn start_task(&self, element: &super::MccParse) -> Result<(), gst::LoggableError> {
let element_weak = element.downgrade();
let pad_weak = self.sinkpad.downgrade();
let res = self.sinkpad.start_task(move || {
@@ -642,7 +642,7 @@ impl MccParse {
fn sink_activatemode(
&self,
_pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::MccParse,
mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
@@ -659,7 +659,7 @@ impl MccParse {
fn scan_duration(
&self,
- element: &gst::Element,
+ element: &super::MccParse,
) -> Result<Option<ValidVideoTimeCode>, gst::LoggableError> {
gst_debug!(CAT, obj: element, "Scanning duration");
@@ -748,7 +748,7 @@ impl MccParse {
}
}
- fn push_eos(&self, element: &gst::Element) {
+ fn push_eos(&self, element: &super::MccParse) {
let mut state = self.state.lock().unwrap();
if state.seeking {
@@ -784,7 +784,7 @@ impl MccParse {
}
}
- fn loop_fn(&self, element: &gst::Element) {
+ fn loop_fn(&self, element: &super::MccParse) {
let mut state = self.state.lock().unwrap();
let State {
timecode_rate: ref tc_rate,
@@ -882,7 +882,7 @@ impl MccParse {
fn sink_chain(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::MccParse,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -910,7 +910,7 @@ impl MccParse {
self.state.lock().unwrap()
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, element: &super::MccParse, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -956,7 +956,7 @@ impl MccParse {
}
}
- fn perform_seek(&self, event: &gst::event::Seek, element: &gst::Element) -> bool {
+ fn perform_seek(&self, event: &gst::event::Seek, element: &super::MccParse) -> bool {
let mut state = self.state.lock().unwrap();
if state.pull.is_none() {
@@ -1049,7 +1049,7 @@ impl MccParse {
}
}
- fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn src_event(&self, pad: &gst::Pad, element: &super::MccParse, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -1059,7 +1059,12 @@ impl MccParse {
}
}
- fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
+ fn src_query(
+ &self,
+ pad: &gst::Pad,
+ element: &super::MccParse,
+ query: &mut gst::QueryRef,
+ ) -> bool {
use gst::QueryView;
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@@ -1120,13 +1125,14 @@ impl MccParse {
impl ObjectSubclass for MccParse {
const NAME: &'static str = "RsMccParse";
+ type Type = super::MccParse;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.activate_function(|pad, parent| {
@@ -1189,7 +1195,7 @@ impl ObjectSubclass for MccParse {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Mcc Parse",
"Parser/ClosedCaption",
@@ -1241,19 +1247,18 @@ impl ObjectSubclass for MccParse {
}
impl ObjectImpl for MccParse {
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- 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();
}
}
impl ElementImpl for MccParse {
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);
@@ -1270,12 +1275,3 @@ impl ElementImpl for MccParse {
self.parent_change_state(element, transition)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "mccparse",
- gst::Rank::Primary,
- MccParse::get_type(),
- )
-}
diff --git a/video/closedcaption/src/mcc_parse/mod.rs b/video/closedcaption/src/mcc_parse/mod.rs
new file mode 100644
index 000000000..d3ee283e0
--- /dev/null
+++ b/video/closedcaption/src/mcc_parse/mod.rs
@@ -0,0 +1,39 @@
+// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
+//
+// 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 Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+use glib::prelude::*;
+
+mod imp;
+mod parser;
+
+glib_wrapper! {
+ pub struct MccParse(ObjectSubclass<imp::MccParse>) @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 MccParse {}
+unsafe impl Sync for MccParse {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "mccparse",
+ gst::Rank::Primary,
+ MccParse::static_type(),
+ )
+}
diff --git a/video/closedcaption/src/mcc_parser.rs b/video/closedcaption/src/mcc_parse/parser.rs
index c2ec97069..b57e95e44 100644
--- a/video/closedcaption/src/mcc_parser.rs
+++ b/video/closedcaption/src/mcc_parse/parser.rs
@@ -752,7 +752,7 @@ mod tests {
#[test]
fn test_parser() {
- let mcc_file = include_bytes!("../tests/captions-test_708.mcc");
+ let mcc_file = include_bytes!("../../tests/captions-test_708.mcc");
let mut reader = crate::line_reader::LineReader::new();
let mut parser = MccParser::new();
let mut line_cnt = 0;
diff --git a/video/closedcaption/src/scc_enc.rs b/video/closedcaption/src/scc_enc/imp.rs
index 00b3bf85e..c9c473931 100644
--- a/video/closedcaption/src/scc_enc.rs
+++ b/video/closedcaption/src/scc_enc/imp.rs
@@ -16,7 +16,6 @@
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.
-use glib::prelude::*;
use glib::subclass;
use glib::subclass::prelude::*;
use gst::prelude::*;
@@ -70,7 +69,7 @@ impl State {
fn generate_caption(
&mut self,
- element: &gst::Element,
+ element: &super::SccEnc,
buffer: gst::Buffer,
) -> Result<Option<gst::Buffer>, gst::FlowError> {
// Arbitrary number that was chosen to keep in order
@@ -141,7 +140,7 @@ impl State {
// Flush the internal buffers into a line
fn write_line(
&mut self,
- element: &gst::Element,
+ element: &super::SccEnc,
) -> Result<Option<gst::Buffer>, gst::FlowError> {
let mut outbuf = Vec::new();
let mut line_start = true;
@@ -218,7 +217,7 @@ impl State {
}
}
-struct SccEnc {
+pub struct SccEnc {
srcpad: gst::Pad,
sinkpad: gst::Pad,
state: Mutex<State>,
@@ -228,7 +227,7 @@ impl SccEnc {
fn sink_chain(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::SccEnc,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -246,7 +245,7 @@ impl SccEnc {
Ok(gst::FlowSuccess::Ok)
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, element: &super::SccEnc, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -294,7 +293,7 @@ impl SccEnc {
}
}
- fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn src_event(&self, pad: &gst::Pad, element: &super::SccEnc, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -307,7 +306,12 @@ impl SccEnc {
}
}
- fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
+ fn src_query(
+ &self,
+ pad: &gst::Pad,
+ element: &super::SccEnc,
+ query: &mut gst::QueryRef,
+ ) -> bool {
use gst::QueryView;
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@@ -330,13 +334,14 @@ impl SccEnc {
impl ObjectSubclass for SccEnc {
const NAME: &'static str = "RsSccEnc";
+ type Type = super::SccEnc;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
@@ -380,7 +385,7 @@ impl ObjectSubclass for SccEnc {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Scc Encoder",
"Encoder/ClosedCaption",
@@ -416,19 +421,18 @@ impl ObjectSubclass for SccEnc {
}
impl ObjectImpl for SccEnc {
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- 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();
}
}
impl ElementImpl for SccEnc {
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);
@@ -445,12 +449,3 @@ impl ElementImpl for SccEnc {
self.parent_change_state(element, transition)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "sccenc",
- gst::Rank::Primary,
- SccEnc::get_type(),
- )
-}
diff --git a/video/closedcaption/src/scc_enc/mod.rs b/video/closedcaption/src/scc_enc/mod.rs
new file mode 100644
index 000000000..46998d753
--- /dev/null
+++ b/video/closedcaption/src/scc_enc/mod.rs
@@ -0,0 +1,39 @@
+// Copyright (C) 2019 Sebastian Dröge <sebastian@centricular.com>
+// Copyright (C) 2019 Jordan Petridis <jordan@centricular.com>
+//
+// 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 Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+use glib::prelude::*;
+
+mod imp;
+
+glib_wrapper! {
+ pub struct SccEnc(ObjectSubclass<imp::SccEnc>) @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 SccEnc {}
+unsafe impl Sync for SccEnc {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "sccenc",
+ gst::Rank::Primary,
+ SccEnc::static_type(),
+ )
+}
diff --git a/video/closedcaption/src/scc_parse.rs b/video/closedcaption/src/scc_parse/imp.rs
index 1b70bc015..5e2781ec3 100644
--- a/video/closedcaption/src/scc_parse.rs
+++ b/video/closedcaption/src/scc_parse/imp.rs
@@ -16,7 +16,6 @@
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.
-use glib::prelude::*;
use glib::subclass;
use glib::subclass::prelude::*;
use gst::prelude::*;
@@ -24,8 +23,8 @@ use gst::subclass::prelude::*;
use std::sync::{Mutex, MutexGuard};
+use super::parser::{SccLine, SccParser, TimeCode};
use crate::line_reader::LineReader;
-use crate::scc_parser::{SccLine, SccParser, TimeCode};
lazy_static! {
static ref CAT: gst::DebugCategory = {
@@ -83,7 +82,7 @@ impl State {
&mut self,
tc: TimeCode,
framerate: gst::Fraction,
- element: &gst::Element,
+ element: &super::SccParse,
) -> Result<gst_video::ValidVideoTimeCode, gst::FlowError> {
use std::convert::TryInto;
@@ -137,7 +136,7 @@ impl State {
fn update_timestamp(
&mut self,
timecode: &gst_video::ValidVideoTimeCode,
- element: &gst::Element,
+ element: &super::SccParse,
) {
let nsecs = gst::ClockTime::from(timecode.nsec_since_daily_jam());
@@ -159,7 +158,7 @@ impl State {
buffer: &mut gst::buffer::Buffer,
timecode: &gst_video::ValidVideoTimeCode,
framerate: gst::Fraction,
- element: &gst::Element,
+ element: &super::SccParse,
) {
let buffer = buffer.get_mut().unwrap();
gst_video::VideoTimeCodeMeta::add(buffer, &timecode);
@@ -175,7 +174,7 @@ impl State {
}
}
-struct SccParse {
+pub struct SccParse {
srcpad: gst::Pad,
sinkpad: gst::Pad,
state: Mutex<State>,
@@ -184,7 +183,7 @@ struct SccParse {
impl SccParse {
fn handle_buffer(
&self,
- element: &gst::Element,
+ element: &super::SccParse,
buffer: Option<gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state = self.state.lock().unwrap();
@@ -234,7 +233,7 @@ impl SccParse {
&self,
tc: TimeCode,
data: Vec<u8>,
- element: &gst::Element,
+ element: &super::SccParse,
mut state: MutexGuard<State>,
) -> Result<MutexGuard<State>, gst::FlowError> {
gst_trace!(
@@ -309,7 +308,7 @@ impl SccParse {
fn sink_chain(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::SccParse,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -317,7 +316,7 @@ impl SccParse {
self.handle_buffer(element, Some(buffer))
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, element: &super::SccParse, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -367,7 +366,7 @@ impl SccParse {
}
}
- fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn src_event(&self, pad: &gst::Pad, element: &super::SccParse, event: gst::Event) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -380,7 +379,12 @@ impl SccParse {
}
}
- fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
+ fn src_query(
+ &self,
+ pad: &gst::Pad,
+ element: &super::SccParse,
+ query: &mut gst::QueryRef,
+ ) -> bool {
use gst::QueryView;
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@@ -413,13 +417,14 @@ impl SccParse {
impl ObjectSubclass for SccParse {
const NAME: &'static str = "RsSccParse";
+ type Type = super::SccParse;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
@@ -463,7 +468,7 @@ impl ObjectSubclass for SccParse {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Scc Parse",
"Parser/ClosedCaption",
@@ -500,19 +505,18 @@ impl ObjectSubclass for SccParse {
}
impl ObjectImpl for SccParse {
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- 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();
}
}
impl ElementImpl for SccParse {
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);
@@ -529,12 +533,3 @@ impl ElementImpl for SccParse {
self.parent_change_state(element, transition)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "sccparse",
- gst::Rank::Primary,
- SccParse::get_type(),
- )
-}
diff --git a/video/closedcaption/src/scc_parse/mod.rs b/video/closedcaption/src/scc_parse/mod.rs
new file mode 100644
index 000000000..19cf93f87
--- /dev/null
+++ b/video/closedcaption/src/scc_parse/mod.rs
@@ -0,0 +1,40 @@
+// Copyright (C) 2019 Sebastian Dröge <sebastian@centricular.com>
+// Copyright (C) 2019 Jordan Petridis <jordan@centricular.com>
+//
+// 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 Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+use glib::prelude::*;
+
+mod imp;
+mod parser;
+
+glib_wrapper! {
+ pub struct SccParse(ObjectSubclass<imp::SccParse>) @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 SccParse {}
+unsafe impl Sync for SccParse {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "sccparse",
+ gst::Rank::Primary,
+ SccParse::static_type(),
+ )
+}
diff --git a/video/closedcaption/src/scc_parser.rs b/video/closedcaption/src/scc_parse/parser.rs
index bd02f3e94..7aff8848a 100644
--- a/video/closedcaption/src/scc_parser.rs
+++ b/video/closedcaption/src/scc_parse/parser.rs
@@ -455,7 +455,7 @@ mod tests {
#[test]
fn test_parser() {
- let scc_file = include_bytes!("../tests/dn2018-1217.scc");
+ let scc_file = include_bytes!("../../tests/dn2018-1217.scc");
let mut reader = crate::line_reader::LineReader::new();
let mut parser = SccParser::new();
let mut line_cnt = 0;
diff --git a/video/closedcaption/src/tttocea608.rs b/video/closedcaption/src/tttocea608/imp.rs
index 935f04ea6..beb05e82a 100644
--- a/video/closedcaption/src/tttocea608.rs
+++ b/video/closedcaption/src/tttocea608/imp.rs
@@ -18,13 +18,14 @@
use glib::prelude::*;
use glib::subclass;
use glib::subclass::prelude::*;
-use glib::GEnum;
use gst::prelude::*;
use gst::subclass::prelude::*;
-use super::cea608tott_ffi as ffi;
+use crate::ffi;
use std::sync::Mutex;
+use super::Mode;
+
fn decrement_pts(
min_frame_no: u64,
frame_no: &mut u64,
@@ -208,16 +209,6 @@ const DEFAULT_FPS_D: i32 = 1;
*/
const LATENCY_BUFFERS: u64 = 74;
-#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
-#[repr(u32)]
-#[genum(type_name = "GstTtToCea608Mode")]
-enum Mode {
- PopOn,
- RollUp2,
- RollUp3,
- RollUp4,
-}
-
const DEFAULT_MODE: Mode = Mode::RollUp2;
static PROPERTIES: [subclass::Property; 1] = [subclass::Property("mode", |name| {
@@ -264,7 +255,7 @@ impl Default for State {
}
}
-struct TtToCea608 {
+pub struct TtToCea608 {
srcpad: gst::Pad,
sinkpad: gst::Pad,
@@ -346,7 +337,7 @@ impl TtToCea608 {
fn sink_chain(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::TtToCea608,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let pts = match buffer.get_pts() {
@@ -628,7 +619,12 @@ impl TtToCea608 {
}
}
- fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
+ fn src_query(
+ &self,
+ pad: &gst::Pad,
+ element: &super::TtToCea608,
+ query: &mut gst::QueryRef,
+ ) -> bool {
use gst::QueryView;
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@@ -671,7 +667,7 @@ impl TtToCea608 {
}
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, element: &super::TtToCea608, event: gst::Event) -> bool {
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
use gst::EventView;
@@ -785,13 +781,14 @@ impl TtToCea608 {
impl ObjectSubclass for TtToCea608 {
const NAME: &'static str = "TtToCea608";
+ type Type = super::TtToCea608;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
@@ -831,7 +828,7 @@ impl ObjectSubclass for TtToCea608 {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"TT to CEA-608",
"Generic",
@@ -874,15 +871,14 @@ impl ObjectSubclass for TtToCea608 {
}
impl ObjectImpl for TtToCea608 {
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- 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();
}
- 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];
match *prop {
@@ -894,7 +890,7 @@ impl ObjectImpl for TtToCea608 {
}
}
- 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 {
@@ -910,7 +906,7 @@ impl ObjectImpl for TtToCea608 {
impl ElementImpl for TtToCea608 {
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);
@@ -941,12 +937,3 @@ impl ElementImpl for TtToCea608 {
Ok(ret)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "tttocea608",
- gst::Rank::None,
- TtToCea608::get_type(),
- )
-}
diff --git a/video/closedcaption/src/tttocea608/mod.rs b/video/closedcaption/src/tttocea608/mod.rs
new file mode 100644
index 000000000..790e71511
--- /dev/null
+++ b/video/closedcaption/src/tttocea608/mod.rs
@@ -0,0 +1,49 @@
+// Copyright (C) 2020 Mathieu Duponchelle <mathieu@centricular.com>
+//
+// 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 Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+use glib::prelude::*;
+use glib::GEnum;
+
+mod imp;
+
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
+#[repr(u32)]
+#[genum(type_name = "GstTtToCea608Mode")]
+enum Mode {
+ PopOn,
+ RollUp2,
+ RollUp3,
+ RollUp4,
+}
+
+glib_wrapper! {
+ pub struct TtToCea608(ObjectSubclass<imp::TtToCea608>) @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 TtToCea608 {}
+unsafe impl Sync for TtToCea608 {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "tttocea608",
+ gst::Rank::None,
+ TtToCea608::static_type(),
+ )
+}
diff --git a/video/dav1d/src/dav1ddec.rs b/video/dav1d/src/dav1ddec/imp.rs
index 4212232a3..3e4983bec 100644
--- a/video/dav1d/src/dav1ddec.rs
+++ b/video/dav1d/src/dav1ddec/imp.rs
@@ -18,7 +18,7 @@ use std::i32;
use std::str::FromStr;
use std::sync::Mutex;
-pub struct NegotiationInfos {
+struct NegotiationInfos {
input_state:
Option<gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>>,
output_info: Option<gst_video::VideoInfo>,
@@ -84,7 +84,7 @@ impl Dav1dDec {
pub fn handle_resolution_change(
&self,
- element: &gst_video::VideoDecoder,
+ element: &super::Dav1dDec,
pic: &dav1d::Picture,
format: gst_video::VideoFormat,
) -> Result<(), gst::FlowError> {
@@ -251,7 +251,7 @@ impl Dav1dDec {
fn handle_picture(
&self,
- element: &gst_video::VideoDecoder,
+ element: &super::Dav1dDec,
pic: &dav1d::Picture,
format: gst_video::VideoFormat,
) -> Result<gst::FlowSuccess, gst::FlowError> {
@@ -297,7 +297,7 @@ impl Dav1dDec {
fn forward_pending_pictures(
&self,
- element: &gst_video::VideoDecoder,
+ element: &super::Dav1dDec,
) -> Result<gst::FlowSuccess, gst::FlowError> {
for (pic, format) in self.get_pending_pictures()? {
self.handle_picture(element, &pic, format)?;
@@ -344,6 +344,7 @@ fn video_output_formats() -> Vec<glib::SendValue> {
impl ObjectSubclass for Dav1dDec {
const NAME: &'static str = "RsDav1dDec";
+ type Type = super::Dav1dDec;
type ParentType = gst_video::VideoDecoder;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -361,7 +362,7 @@ impl ObjectSubclass for Dav1dDec {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Dav1d AV1 Decoder",
"Codec/Decoder/Video",
@@ -410,7 +411,7 @@ impl ObjectImpl for Dav1dDec {}
impl ElementImpl for Dav1dDec {}
impl VideoDecoderImpl for Dav1dDec {
- fn start(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> {
+ fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
{
let mut infos = self.negotiation_infos.lock().unwrap();
infos.output_info = None;
@@ -421,7 +422,7 @@ impl VideoDecoderImpl for Dav1dDec {
fn set_format(
&self,
- element: &gst_video::VideoDecoder,
+ element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
{
@@ -434,7 +435,7 @@ impl VideoDecoderImpl for Dav1dDec {
fn handle_frame(
&self,
- element: &gst_video::VideoDecoder,
+ element: &Self::Type,
frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let input_buffer = frame
@@ -447,24 +448,21 @@ impl VideoDecoderImpl for Dav1dDec {
Ok(gst::FlowSuccess::Ok)
}
- fn flush(&self, element: &gst_video::VideoDecoder) -> bool {
+ fn flush(&self, element: &Self::Type) -> bool {
gst_info!(CAT, obj: element, "Flushing");
self.flush_decoder();
self.drop_decoded_pictures();
true
}
- fn drain(&self, element: &gst_video::VideoDecoder) -> Result<gst::FlowSuccess, gst::FlowError> {
+ fn drain(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_info!(CAT, obj: element, "Draining");
self.flush_decoder();
self.forward_pending_pictures(element)?;
self.parent_drain(element)
}
- fn finish(
- &self,
- element: &gst_video::VideoDecoder,
- ) -> Result<gst::FlowSuccess, gst::FlowError> {
+ fn finish(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_info!(CAT, obj: element, "Finishing");
self.flush_decoder();
self.forward_pending_pictures(element)?;
@@ -473,7 +471,7 @@ impl VideoDecoderImpl for Dav1dDec {
fn decide_allocation(
&self,
- element: &gst_video::VideoDecoder,
+ element: &Self::Type,
query: &mut gst::QueryRef,
) -> Result<(), gst::ErrorMessage> {
if let gst::query::QueryView::Allocation(allocation) = query.view() {
@@ -498,12 +496,3 @@ impl VideoDecoderImpl for Dav1dDec {
self.parent_decide_allocation(element, query)
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rsdav1ddec",
- gst::Rank::Primary + 1,
- Dav1dDec::get_type(),
- )
-}
diff --git a/video/dav1d/src/dav1ddec/mod.rs b/video/dav1d/src/dav1ddec/mod.rs
new file mode 100644
index 000000000..276fd0893
--- /dev/null
+++ b/video/dav1d/src/dav1ddec/mod.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 Philippe Normand <philn@igalia.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;
+
+glib_wrapper! {
+ pub struct Dav1dDec(ObjectSubclass<imp::Dav1dDec>) @extends gst_video::VideoDecoder, 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 Dav1dDec {}
+unsafe impl Sync for Dav1dDec {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rsdav1ddec",
+ gst::Rank::Primary + 1,
+ Dav1dDec::static_type(),
+ )
+}
diff --git a/video/flavors/src/flvdemux.rs b/video/flavors/src/flvdemux/imp.rs
index 7908cf11d..fdc388369 100644
--- a/video/flavors/src/flvdemux.rs
+++ b/video/flavors/src/flvdemux/imp.rs
@@ -31,8 +31,7 @@ lazy_static! {
};
}
-#[derive(Debug)]
-struct FlvDemux {
+pub struct FlvDemux {
sinkpad: gst::Pad,
audio_srcpad: Mutex<Option<gst::Pad>>,
video_srcpad: Mutex<Option<gst::Pad>>,
@@ -42,7 +41,6 @@ struct FlvDemux {
}
#[allow(clippy::large_enum_variant)]
-#[derive(Debug)]
enum State {
Stopped,
NeedHeader,
@@ -60,14 +58,13 @@ enum Stream {
Video,
}
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
enum Event {
StreamChanged(Stream, gst::Caps),
Buffer(Stream, gst::Buffer),
HaveAllStreams,
}
-#[derive(Debug)]
struct StreamingState {
audio: Option<AudioFormat>,
expect_audio: bool,
@@ -124,13 +121,14 @@ struct Metadata {
impl ObjectSubclass for FlvDemux {
const NAME: &'static str = "RsFlvDemux";
+ type Type = super::FlvDemux;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
- fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
+ fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.activate_function(|pad, parent| {
@@ -178,7 +176,7 @@ impl ObjectSubclass for FlvDemux {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"FLV Demuxer",
"Codec/Demuxer",
@@ -274,11 +272,10 @@ impl ObjectSubclass for FlvDemux {
}
impl ObjectImpl for FlvDemux {
- fn constructed(&self, obj: &glib::Object) {
+ fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- let element = obj.downcast_ref::<gst::Element>().unwrap();
- element.add_pad(&self.sinkpad).unwrap();
+ obj.add_pad(&self.sinkpad).unwrap();
}
}
@@ -288,7 +285,7 @@ impl FlvDemux {
fn sink_activate(
&self,
pad: &gst::Pad,
- _element: &gst::Element,
+ _element: &super::FlvDemux,
) -> Result<(), gst::LoggableError> {
let mode = {
let mut query = gst::query::Scheduling::new();
@@ -317,7 +314,7 @@ impl FlvDemux {
fn sink_activatemode(
&self,
_pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::FlvDemux,
mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
@@ -346,13 +343,17 @@ impl FlvDemux {
Ok(())
}
- fn start(&self, _element: &gst::Element, _mode: gst::PadMode) -> Result<(), gst::ErrorMessage> {
+ fn start(
+ &self,
+ _element: &super::FlvDemux,
+ _mode: gst::PadMode,
+ ) -> Result<(), gst::ErrorMessage> {
*self.state.lock().unwrap() = State::NeedHeader;
Ok(())
}
- fn stop(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> {
+ fn stop(&self, element: &super::FlvDemux) -> Result<(), gst::ErrorMessage> {
*self.state.lock().unwrap() = State::Stopped;
self.adapter.lock().unwrap().clear();
@@ -372,7 +373,7 @@ impl FlvDemux {
Ok(())
}
- fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn sink_event(&self, pad: &gst::Pad, element: &super::FlvDemux, event: gst::Event) -> bool {
use crate::gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@@ -397,7 +398,12 @@ impl FlvDemux {
}
}
- fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
+ fn src_query(
+ &self,
+ pad: &gst::Pad,
+ element: &super::FlvDemux,
+ query: &mut gst::QueryRef,
+ ) -> bool {
use crate::gst::QueryView;
match query.view_mut() {
@@ -445,7 +451,7 @@ impl FlvDemux {
}
}
- fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
+ fn src_event(&self, pad: &gst::Pad, element: &super::FlvDemux, event: gst::Event) -> bool {
use crate::gst::EventView;
match event.view() {
@@ -460,7 +466,7 @@ impl FlvDemux {
fn sink_chain(
&self,
pad: &gst::Pad,
- element: &gst::Element,
+ element: &super::FlvDemux,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@@ -541,7 +547,7 @@ impl FlvDemux {
fn find_header(
&self,
- element: &gst::Element,
+ element: &super::FlvDemux,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<flavors::Header, ()> {
while adapter.available() >= 9 {
@@ -564,7 +570,7 @@ impl FlvDemux {
fn handle_events(
&self,
- element: &gst::Element,
+ element: &super::FlvDemux,
events: SmallVec<[Event; 4]>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
for event in events {
@@ -633,7 +639,7 @@ impl FlvDemux {
Ok(gst::FlowSuccess::Ok)
}
- fn create_srcpad(&self, element: &gst::Element, name: &str, caps: &gst::Caps) -> gst::Pad {
+ fn create_srcpad(&self, element: &super::FlvDemux, name: &str, caps: &gst::Caps) -> gst::Pad {
let templ = element.get_element_class().get_pad_template(name).unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some(name))
.event_function(|pad, parent, event| {
@@ -688,7 +694,7 @@ impl StreamingState {
fn handle_tag(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<Option<SmallVec<[Event; 4]>>, gst::ErrorMessage> {
use nom::number::complete::be_u32;
@@ -750,7 +756,7 @@ impl StreamingState {
fn handle_script_tag(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<SmallVec<[Event; 4]>, gst::ErrorMessage> {
@@ -811,7 +817,7 @@ impl StreamingState {
fn update_audio_stream(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
data_header: &flavors::AudioDataHeader,
) -> Result<SmallVec<[Event; 4]>, gst::ErrorMessage> {
let mut events = SmallVec::new();
@@ -855,7 +861,7 @@ impl StreamingState {
fn handle_aac_audio_packet_header(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<bool, gst::ErrorMessage> {
@@ -912,7 +918,7 @@ impl StreamingState {
fn handle_audio_tag(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<SmallVec<[Event; 4]>, gst::ErrorMessage> {
@@ -981,7 +987,7 @@ impl StreamingState {
fn update_video_stream(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
data_header: &flavors::VideoDataHeader,
) -> Result<SmallVec<[Event; 4]>, gst::ErrorMessage> {
let mut events = SmallVec::new();
@@ -1025,7 +1031,7 @@ impl StreamingState {
fn handle_avc_video_packet_header(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<Option<i32>, gst::ErrorMessage> {
@@ -1093,7 +1099,7 @@ impl StreamingState {
fn handle_video_tag(
&mut self,
- element: &gst::Element,
+ element: &super::FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<SmallVec<[Event; 4]>, gst::ErrorMessage> {
@@ -1565,12 +1571,3 @@ impl Metadata {
metadata
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rsflvdemux",
- gst::Rank::None,
- FlvDemux::get_type(),
- )
-}
diff --git a/video/flavors/src/flvdemux/mod.rs b/video/flavors/src/flvdemux/mod.rs
new file mode 100644
index 000000000..aca2b41a4
--- /dev/null
+++ b/video/flavors/src/flvdemux/mod.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2016-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::prelude::*;
+
+mod imp;
+
+glib_wrapper! {
+ pub struct FlvDemux(ObjectSubclass<imp::FlvDemux>) @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 FlvDemux {}
+unsafe impl Sync for FlvDemux {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rsflvdemux",
+ gst::Rank::None,
+ FlvDemux::static_type(),
+ )
+}
diff --git a/video/gif/src/gifenc.rs b/video/gif/src/gifenc/imp.rs
index 7d0ec9919..3d0c56e3b 100644
--- a/video/gif/src/gifenc.rs
+++ b/video/gif/src/gifenc/imp.rs
@@ -12,7 +12,6 @@ use glib::subclass::prelude::*;
use gst::subclass::prelude::*;
use gst_video::prelude::*;
use gst_video::subclass::prelude::*;
-use gstreamer_video as gst_video;
use once_cell::sync::Lazy;
use std::{
io,
@@ -29,6 +28,7 @@ const DEFAULT_REPEAT: i32 = 0;
struct CacheBuffer {
buffer: AtomicRefCell<Vec<u8>>,
}
+
impl CacheBuffer {
pub fn new() -> Self {
Self {
@@ -47,6 +47,7 @@ impl CacheBuffer {
std::mem::replace(&mut *buffer, Vec::new())
}
}
+
/// Writer for a CacheBuffer instance. This class is passed to the gif::Encoder.
/// Everything written to the CacheBufferWriter is stored in the underlying CacheBuffer.
struct CacheBufferWriter {
@@ -98,6 +99,7 @@ struct State {
last_actual_pts: gst::ClockTime,
context: Option<gif::Encoder<CacheBufferWriter>>,
}
+
impl State {
pub fn new(video_info: gst_video::VideoInfo) -> Self {
Self {
@@ -130,7 +132,7 @@ impl State {
}
}
-struct GifEnc {
+pub struct GifEnc {
state: AtomicRefCell<Option<State>>,
settings: Mutex<Settings>,
}
@@ -141,6 +143,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
impl ObjectSubclass for GifEnc {
const NAME: &'static str = "GifEnc";
+ type Type = super::GifEnc;
type ParentType = gst_video::VideoEncoder;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -154,7 +157,7 @@ impl ObjectSubclass for GifEnc {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"GIF encoder",
"Encoder/Video",
@@ -211,7 +214,7 @@ impl ObjectSubclass for GifEnc {
}
impl ObjectImpl for GifEnc {
- 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];
match *prop {
@@ -223,7 +226,7 @@ impl ObjectImpl for GifEnc {
}
}
- 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 {
@@ -239,14 +242,14 @@ impl ObjectImpl for GifEnc {
impl ElementImpl for GifEnc {}
impl VideoEncoderImpl for GifEnc {
- fn stop(&self, _element: &gst_video::VideoEncoder) -> Result<(), gst::ErrorMessage> {
+ fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
}
fn set_format(
&self,
- element: &gst_video::VideoEncoder,
+ element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
self.flush_encoder(element)
@@ -272,16 +275,13 @@ impl VideoEncoderImpl for GifEnc {
self.parent_set_format(element, state)
}
- fn finish(
- &self,
- element: &gst_video::VideoEncoder,
- ) -> Result<gst::FlowSuccess, gst::FlowError> {
+ fn finish(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
self.flush_encoder(element)
}
fn handle_frame(
&self,
- element: &gst_video::VideoEncoder,
+ element: &Self::Type,
mut frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.borrow_mut();
@@ -388,10 +388,7 @@ impl VideoEncoderImpl for GifEnc {
}
impl GifEnc {
- fn flush_encoder(
- &self,
- element: &gst_video::VideoEncoder,
- ) -> Result<gst::FlowSuccess, gst::FlowError> {
+ fn flush_encoder(&self, element: &super::GifEnc) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(CAT, obj: element, "Flushing");
let trailer_buffer = self.state.borrow_mut().as_mut().map(|state| {
@@ -440,12 +437,3 @@ fn get_tightly_packed_framebuffer(frame: &gst_video::VideoFrameRef<&gst::BufferR
raw_frame
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "gifenc",
- gst::Rank::Primary,
- GifEnc::get_type(),
- )
-}
diff --git a/video/gif/src/gifenc/mod.rs b/video/gif/src/gifenc/mod.rs
new file mode 100644
index 000000000..40543d41d
--- /dev/null
+++ b/video/gif/src/gifenc/mod.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2020 Markus Ebner <info@ebner-markus.de>
+//
+// 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;
+
+glib_wrapper! {
+ pub struct GifEnc(ObjectSubclass<imp::GifEnc>) @extends gst_video::VideoEncoder, 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 GifEnc {}
+unsafe impl Sync for GifEnc {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "gifenc",
+ gst::Rank::Primary,
+ GifEnc::static_type(),
+ )
+}
diff --git a/video/gif/src/lib.rs b/video/gif/src/lib.rs
index 64cb03308..7b14fbd0c 100644
--- a/video/gif/src/lib.rs
+++ b/video/gif/src/lib.rs
@@ -10,6 +10,7 @@
extern crate glib;
#[macro_use]
extern crate gstreamer as gst;
+extern crate gstreamer_video as gst_video;
mod gifenc;
diff --git a/video/rav1e/src/rav1enc.rs b/video/rav1e/src/rav1enc/imp.rs
index cab69e5a1..f681eda3b 100644
--- a/video/rav1e/src/rav1enc.rs
+++ b/video/rav1e/src/rav1enc/imp.rs
@@ -281,7 +281,7 @@ struct State {
video_info: gst_video::VideoInfo,
}
-struct Rav1Enc {
+pub struct Rav1Enc {
state: AtomicRefCell<Option<State>>,
settings: Mutex<Settings>,
}
@@ -296,6 +296,7 @@ lazy_static! {
impl ObjectSubclass for Rav1Enc {
const NAME: &'static str = "Rav1Enc";
+ type Type = super::Rav1Enc;
type ParentType = gst_video::VideoEncoder;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -309,7 +310,7 @@ impl ObjectSubclass for Rav1Enc {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"rav1e AV1 encoder",
"Encoder/Video",
@@ -370,7 +371,7 @@ impl ObjectSubclass for Rav1Enc {
}
impl ObjectImpl for Rav1Enc {
- 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];
match *prop {
@@ -421,7 +422,7 @@ impl ObjectImpl for Rav1Enc {
}
}
- 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 {
@@ -473,7 +474,7 @@ impl ObjectImpl for Rav1Enc {
impl ElementImpl for Rav1Enc {}
impl VideoEncoderImpl for Rav1Enc {
- fn stop(&self, _element: &gst_video::VideoEncoder) -> Result<(), gst::ErrorMessage> {
+ fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
@@ -483,7 +484,7 @@ impl VideoEncoderImpl for Rav1Enc {
#[allow(clippy::wildcard_in_or_patterns)]
fn set_format(
&self,
- element: &gst_video::VideoEncoder,
+ element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
self.finish(element)
@@ -629,7 +630,7 @@ impl VideoEncoderImpl for Rav1Enc {
self.parent_set_format(element, state)
}
- fn flush(&self, element: &gst_video::VideoEncoder) -> bool {
+ fn flush(&self, element: &Self::Type) -> bool {
gst_debug!(CAT, obj: element, "Flushing");
let mut state_guard = self.state.borrow_mut();
@@ -643,10 +644,7 @@ impl VideoEncoderImpl for Rav1Enc {
true
}
- fn finish(
- &self,
- element: &gst_video::VideoEncoder,
- ) -> Result<gst::FlowSuccess, gst::FlowError> {
+ fn finish(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(CAT, obj: element, "Finishing");
let mut state_guard = self.state.borrow_mut();
@@ -663,7 +661,7 @@ impl VideoEncoderImpl for Rav1Enc {
fn handle_frame(
&self,
- element: &gst_video::VideoEncoder,
+ element: &Self::Type,
frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.borrow_mut();
@@ -721,7 +719,7 @@ impl VideoEncoderImpl for Rav1Enc {
impl Rav1Enc {
fn output_frames(
&self,
- element: &gst_video::VideoEncoder,
+ element: &super::Rav1Enc,
state: &mut State,
) -> Result<gst::FlowSuccess, gst::FlowError> {
loop {
@@ -768,12 +766,3 @@ impl Rav1Enc {
}
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rav1enc",
- gst::Rank::Primary,
- Rav1Enc::get_type(),
- )
-}
diff --git a/video/rav1e/src/rav1enc/mod.rs b/video/rav1e/src/rav1enc/mod.rs
new file mode 100644
index 000000000..b953bf9f5
--- /dev/null
+++ b/video/rav1e/src/rav1enc/mod.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 Sebastian Dröge <sebastian@centricular.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use glib::prelude::*;
+
+mod imp;
+
+glib_wrapper! {
+ pub struct Rav1Enc(ObjectSubclass<imp::Rav1Enc>) @extends gst_video::VideoEncoder, 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 Rav1Enc {}
+unsafe impl Sync for Rav1Enc {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rav1enc",
+ gst::Rank::Primary,
+ Rav1Enc::static_type(),
+ )
+}
diff --git a/video/rspng/src/pngenc.rs b/video/rspng/src/pngenc/imp.rs
index da638b8f4..2e7e5ea03 100644
--- a/video/rspng/src/pngenc.rs
+++ b/video/rspng/src/pngenc/imp.rs
@@ -8,9 +8,9 @@
use std::{io, io::Write, sync::Arc};
+use glib::glib_object_subclass;
use glib::subclass;
use glib::subclass::prelude::*;
-use glib::{glib_object_subclass, GEnum};
use gst::prelude::*;
use gst::subclass::prelude::*;
@@ -22,77 +22,12 @@ use atomic_refcell::AtomicRefCell;
use once_cell::sync::Lazy;
use parking_lot::Mutex;
+use super::CompressionLevel;
+use super::FilterType;
+
const DEFAULT_COMPRESSION_LEVEL: CompressionLevel = CompressionLevel::Default;
const DEFAULT_FILTER_TYPE: FilterType = FilterType::NoFilter;
-#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
-#[repr(u32)]
-#[genum(type_name = "GstRsPngCompressionLevel")]
-pub(crate) enum CompressionLevel {
- #[genum(name = "Default: Use the default compression level.", nick = "default")]
- Default,
- #[genum(name = "Fast: A fast compression algorithm.", nick = "fast")]
- Fast,
- #[genum(
- name = "Best: Uses the algorithm with the best results.",
- nick = "best"
- )]
- Best,
- #[genum(name = "Huffman: Huffman compression.", nick = "huffman")]
- Huffman,
- #[genum(name = "Rle: Rle compression.", nick = "rle")]
- Rle,
-}
-
-#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
-#[repr(u32)]
-#[genum(type_name = "GstRsPngFilterType")]
-pub(crate) enum FilterType {
- #[genum(
- name = "NoFilter: No filtering applied to the output.",
- nick = "nofilter"
- )]
- NoFilter,
- #[genum(name = "Sub: filter applied to each pixel.", nick = "sub")]
- Sub,
- #[genum(name = "Up: Up filter similar to Sub.", nick = "up")]
- Up,
- #[genum(
- name = "Avg: The Average filter uses the average of the two neighboring pixels.",
- nick = "avg"
- )]
- Avg,
- #[genum(
- name = "Paeth: The Paeth filter computes a simple linear function of the three neighboring pixels.",
- nick = "paeth"
- )]
- Paeth,
-}
-
-impl From<CompressionLevel> for png::Compression {
- fn from(value: CompressionLevel) -> Self {
- match value {
- CompressionLevel::Default => png::Compression::Default,
- CompressionLevel::Fast => png::Compression::Fast,
- CompressionLevel::Best => png::Compression::Best,
- CompressionLevel::Huffman => png::Compression::Huffman,
- CompressionLevel::Rle => png::Compression::Rle,
- }
- }
-}
-
-impl From<FilterType> for png::FilterType {
- fn from(value: FilterType) -> Self {
- match value {
- FilterType::NoFilter => png::FilterType::NoFilter,
- FilterType::Sub => png::FilterType::Sub,
- FilterType::Up => png::FilterType::Up,
- FilterType::Avg => png::FilterType::Avg,
- FilterType::Paeth => png::FilterType::Paeth,
- }
- }
-}
-
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new(
"rspngenc",
@@ -249,13 +184,14 @@ impl State {
}
}
-struct PngEncoder {
+pub struct PngEncoder {
state: Mutex<Option<State>>,
settings: Mutex<Settings>,
}
impl ObjectSubclass for PngEncoder {
const NAME: &'static str = "PngEncoder";
+ type Type = super::PngEncoder;
type ParentType = gst_video::VideoEncoder;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -269,7 +205,7 @@ impl ObjectSubclass for PngEncoder {
}
}
- fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
+ fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"PNG encoder",
"Encoder/Video",
@@ -323,7 +259,7 @@ impl ObjectSubclass for PngEncoder {
}
impl ObjectImpl for PngEncoder {
- 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];
match *prop {
@@ -343,7 +279,7 @@ impl ObjectImpl for PngEncoder {
}
}
- 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 {
@@ -363,14 +299,14 @@ impl ObjectImpl for PngEncoder {
impl ElementImpl for PngEncoder {}
impl VideoEncoderImpl for PngEncoder {
- fn stop(&self, _element: &gst_video::VideoEncoder) -> Result<(), gst::ErrorMessage> {
+ fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
*self.state.lock() = None;
Ok(())
}
fn set_format(
&self,
- element: &gst_video::VideoEncoder,
+ element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
let video_info = state.get_info();
@@ -392,7 +328,7 @@ impl VideoEncoderImpl for PngEncoder {
fn handle_frame(
&self,
- element: &gst_video::VideoEncoder,
+ element: &Self::Type,
mut frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.lock();
@@ -427,12 +363,3 @@ impl VideoEncoderImpl for PngEncoder {
element.finish_frame(Some(frame))
}
}
-
-pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
- gst::Element::register(
- Some(plugin),
- "rspngenc",
- gst::Rank::Primary,
- PngEncoder::get_type(),
- )
-}
diff --git a/video/rspng/src/pngenc/mod.rs b/video/rspng/src/pngenc/mod.rs
new file mode 100644
index 000000000..c0004022c
--- /dev/null
+++ b/video/rspng/src/pngenc/mod.rs
@@ -0,0 +1,98 @@
+// Copyright (C) 2020 Natanael Mojica <neithanmo@gmail.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::*;
+use glib::{glib_wrapper, GEnum};
+
+mod imp;
+
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
+#[repr(u32)]
+#[genum(type_name = "GstRsPngCompressionLevel")]
+pub(crate) enum CompressionLevel {
+ #[genum(name = "Default: Use the default compression level.", nick = "default")]
+ Default,
+ #[genum(name = "Fast: A fast compression algorithm.", nick = "fast")]
+ Fast,
+ #[genum(
+ name = "Best: Uses the algorithm with the best results.",
+ nick = "best"
+ )]
+ Best,
+ #[genum(name = "Huffman: Huffman compression.", nick = "huffman")]
+ Huffman,
+ #[genum(name = "Rle: Rle compression.", nick = "rle")]
+ Rle,
+}
+
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, GEnum)]
+#[repr(u32)]
+#[genum(type_name = "GstRsPngFilterType")]
+pub(crate) enum FilterType {
+ #[genum(
+ name = "NoFilter: No filtering applied to the output.",
+ nick = "nofilter"
+ )]
+ NoFilter,
+ #[genum(name = "Sub: filter applied to each pixel.", nick = "sub")]
+ Sub,
+ #[genum(name = "Up: Up filter similar to Sub.", nick = "up")]
+ Up,
+ #[genum(
+ name = "Avg: The Average filter uses the average of the two neighboring pixels.",
+ nick = "avg"
+ )]
+ Avg,
+ #[genum(
+ name = "Paeth: The Paeth filter computes a simple linear function of the three neighboring pixels.",
+ nick = "paeth"
+ )]
+ Paeth,
+}
+
+impl From<CompressionLevel> for png::Compression {
+ fn from(value: CompressionLevel) -> Self {
+ match value {
+ CompressionLevel::Default => png::Compression::Default,
+ CompressionLevel::Fast => png::Compression::Fast,
+ CompressionLevel::Best => png::Compression::Best,
+ CompressionLevel::Huffman => png::Compression::Huffman,
+ CompressionLevel::Rle => png::Compression::Rle,
+ }
+ }
+}
+
+impl From<FilterType> for png::FilterType {
+ fn from(value: FilterType) -> Self {
+ match value {
+ FilterType::NoFilter => png::FilterType::NoFilter,
+ FilterType::Sub => png::FilterType::Sub,
+ FilterType::Up => png::FilterType::Up,
+ FilterType::Avg => png::FilterType::Avg,
+ FilterType::Paeth => png::FilterType::Paeth,
+ }
+ }
+}
+
+glib_wrapper! {
+ pub struct PngEncoder(ObjectSubclass<imp::PngEncoder>) @extends gst_video::VideoEncoder, 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 PngEncoder {}
+unsafe impl Sync for PngEncoder {}
+
+pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
+ gst::Element::register(
+ Some(plugin),
+ "rspngenc",
+ gst::Rank::Primary,
+ PngEncoder::static_type(),
+ )
+}