From 20ad9175d8e58f2285e709b576efdc822b009577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 23 Oct 2022 12:13:23 +0300 Subject: Make GStreamer plugin/crate/library/directory names and descriptions consistent Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/238 --- video/cdg/Cargo.toml | 2 +- video/closedcaption/Cargo.toml | 2 +- video/dav1d/Cargo.toml | 4 +- video/dav1d/src/lib.rs | 4 +- video/ffv1/Cargo.toml | 2 +- video/flavors/Cargo.toml | 2 +- video/gtk4/Cargo.toml | 2 +- video/hsv/Cargo.toml | 2 +- video/png/Cargo.toml | 46 ++++++ video/png/LICENSE-APACHE | 1 + video/png/LICENSE-MIT | 1 + video/png/build.rs | 3 + video/png/examples/pngenc.rs | 47 ++++++ video/png/src/lib.rs | 36 +++++ video/png/src/pngenc/imp.rs | 340 +++++++++++++++++++++++++++++++++++++++++ video/png/src/pngenc/mod.rs | 101 ++++++++++++ video/png/tests/pngenc.rs | 94 ++++++++++++ video/rav1e/Cargo.toml | 2 +- video/rspng/Cargo.toml | 46 ------ video/rspng/LICENSE-APACHE | 1 - video/rspng/LICENSE-MIT | 1 - video/rspng/build.rs | 3 - video/rspng/examples/pngenc.rs | 47 ------ video/rspng/src/lib.rs | 36 ----- video/rspng/src/pngenc/imp.rs | 340 ----------------------------------------- video/rspng/src/pngenc/mod.rs | 101 ------------ video/rspng/tests/pngenc.rs | 94 ------------ video/videofx/Cargo.toml | 4 +- video/videofx/src/lib.rs | 4 +- video/webp/Cargo.toml | 2 +- 30 files changed, 685 insertions(+), 685 deletions(-) create mode 100644 video/png/Cargo.toml create mode 120000 video/png/LICENSE-APACHE create mode 120000 video/png/LICENSE-MIT create mode 100644 video/png/build.rs create mode 100644 video/png/examples/pngenc.rs create mode 100644 video/png/src/lib.rs create mode 100644 video/png/src/pngenc/imp.rs create mode 100644 video/png/src/pngenc/mod.rs create mode 100644 video/png/tests/pngenc.rs delete mode 100644 video/rspng/Cargo.toml delete mode 120000 video/rspng/LICENSE-APACHE delete mode 120000 video/rspng/LICENSE-MIT delete mode 100644 video/rspng/build.rs delete mode 100644 video/rspng/examples/pngenc.rs delete mode 100644 video/rspng/src/lib.rs delete mode 100644 video/rspng/src/pngenc/imp.rs delete mode 100644 video/rspng/src/pngenc/mod.rs delete mode 100644 video/rspng/tests/pngenc.rs (limited to 'video') diff --git a/video/cdg/Cargo.toml b/video/cdg/Cargo.toml index 91529faa3..2c3fe7519 100644 --- a/video/cdg/Cargo.toml +++ b/video/cdg/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.0-alpha.1" authors = ["Guillaume Desmottes "] repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" license = "MIT OR Apache-2.0" -description = "CDG Plugin" +description = "GStreamer CDG codec Plugin" edition = "2021" rust-version = "1.63" diff --git a/video/closedcaption/Cargo.toml b/video/closedcaption/Cargo.toml index af30036ef..4de680f79 100644 --- a/video/closedcaption/Cargo.toml +++ b/video/closedcaption/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Sebastian Dröge ", "Jordan Petridis Result<(), glib::BoolError> { } gst::plugin_define!( - rsdav1d, + dav1d, env!("CARGO_PKG_DESCRIPTION"), plugin_init, concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")), diff --git a/video/ffv1/Cargo.toml b/video/ffv1/Cargo.toml index 2151277d8..9b538f931 100644 --- a/video/ffv1/Cargo.toml +++ b/video/ffv1/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.0-alpha.1" authors = ["Arun Raghavan "] repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" license = "MIT OR Apache-2.0" -description = "FFV1 Decoder Plugin" +description = "GStreamer FFV1 Decoder Plugin" edition = "2021" rust-version = "1.63" diff --git a/video/flavors/Cargo.toml b/video/flavors/Cargo.toml index ed038f21c..7f8eceeb8 100644 --- a/video/flavors/Cargo.toml +++ b/video/flavors/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" license = "MIT OR Apache-2.0" edition = "2021" rust-version = "1.63" -description = "Rust FLV Plugin" +description = "GStreamer Rust FLV Plugin" [dependencies] gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } diff --git a/video/gtk4/Cargo.toml b/video/gtk4/Cargo.toml index c1f9bf134..9a33f4812 100644 --- a/video/gtk4/Cargo.toml +++ b/video/gtk4/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" license = "MPL-2.0" edition = "2021" rust-version = "1.63" -description = "GTK 4 Sink element and Paintable widget" +description = "GStreamer GTK 4 Sink element and Paintable widget" [dependencies] gtk = { package = "gtk4", git = "https://github.com/gtk-rs/gtk4-rs" } diff --git a/video/hsv/Cargo.toml b/video/hsv/Cargo.toml index 375f2ec27..bc40d2380 100644 --- a/video/hsv/Cargo.toml +++ b/video/hsv/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" license = "MIT OR Apache-2.0" edition = "2021" rust-version = "1.63" -description = "HSV manipulation elements, written in Rust" +description = "GStreamer plugin with HSV manipulation elements" [dependencies] gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } diff --git a/video/png/Cargo.toml b/video/png/Cargo.toml new file mode 100644 index 000000000..2b0460c59 --- /dev/null +++ b/video/png/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "gst-plugin-png" +version = "0.9.0-alpha.1" +authors = ["Natanael Mojica "] +repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.63" +description = "GStreamer Rust PNG encoder/decoder" + +[dependencies] +gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } +gst_video = { package = "gstreamer-video", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } +png = "0.17.2" +once_cell = "1" +parking_lot = "0.12" +atomic_refcell = "0.1" + +[dev-dependencies] +gst_check = { package = "gstreamer-check", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } + +[lib] +name = "gstrspng" +crate-type = ["cdylib", "rlib"] +path = "src/lib.rs" + +[build-dependencies] +gst-plugin-version-helper = { path="../../version-helper" } + +[features] +static = [] +capi = [] +doc = ["gst/v1_18"] + +[package.metadata.capi] +min_version = "0.8.0" + +[package.metadata.capi.header] +enabled = false + +[package.metadata.capi.library] +install_subdir = "gstreamer-1.0" +versioning = false + +[package.metadata.capi.pkg_config] +requires_private = "gstreamer-1.0, gstreamer-video-1.0, gobject-2.0, glib-2.0, gmodule-2.0" diff --git a/video/png/LICENSE-APACHE b/video/png/LICENSE-APACHE new file mode 120000 index 000000000..1cd601d0a --- /dev/null +++ b/video/png/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/video/png/LICENSE-MIT b/video/png/LICENSE-MIT new file mode 120000 index 000000000..b2cfbdc7b --- /dev/null +++ b/video/png/LICENSE-MIT @@ -0,0 +1 @@ +../../LICENSE-MIT \ No newline at end of file diff --git a/video/png/build.rs b/video/png/build.rs new file mode 100644 index 000000000..cda12e57e --- /dev/null +++ b/video/png/build.rs @@ -0,0 +1,3 @@ +fn main() { + gst_plugin_version_helper::info() +} diff --git a/video/png/examples/pngenc.rs b/video/png/examples/pngenc.rs new file mode 100644 index 000000000..0ed819757 --- /dev/null +++ b/video/png/examples/pngenc.rs @@ -0,0 +1,47 @@ +// Copyright (C) 2020 Natanael Mojica +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use gst::prelude::*; + +const ENCODE_PIPELINE: &str = "videotestsrc is-live=false num-buffers=1 ! videoconvert ! video/x-raw, format=RGB, width=160, height=120 ! + rspngenc compression-level=2 filter=4 ! filesink location=frame.png"; + +fn main() { + gst::init().unwrap(); + gstrspng::plugin_register_static().expect("Failed to register gif plugin"); + + let pipeline = gst::parse_launch(ENCODE_PIPELINE).unwrap(); + let bus = pipeline.bus().unwrap(); + + pipeline + .set_state(gst::State::Playing) + .expect("Failed to set pipeline state to playing"); + + for msg in bus.iter_timed(gst::ClockTime::NONE) { + use gst::MessageView; + + match msg.view() { + MessageView::Eos(..) => break, + MessageView::Error(err) => { + println!( + "Error from {:?}: {} ({:?})", + err.src().map(|s| s.path_string()), + err.error(), + err.debug() + ); + break; + } + _ => (), + } + } + pipeline + .set_state(gst::State::Null) + .expect("Failed to set pipeline state to null"); +} diff --git a/video/png/src/lib.rs b/video/png/src/lib.rs new file mode 100644 index 000000000..030efc918 --- /dev/null +++ b/video/png/src/lib.rs @@ -0,0 +1,36 @@ +// Copyright (C) 2020 Natanael Mojica +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// SPDX-License-Identifier: MIT OR Apache-2.0 +#![allow(clippy::non_send_fields_in_send_ty, unused_doc_comments)] + +/** + * plugin-rspng: + * + * Since: plugins-rs-0.6.0 + */ +use gst::glib; + +mod pngenc; + +fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { + pngenc::register(plugin)?; + Ok(()) +} + +gst::plugin_define!( + rspng, + env!("CARGO_PKG_DESCRIPTION"), + plugin_init, + concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")), + "MIT/X11", + env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_REPOSITORY"), + env!("BUILD_REL_DATE") +); diff --git a/video/png/src/pngenc/imp.rs b/video/png/src/pngenc/imp.rs new file mode 100644 index 000000000..851677d86 --- /dev/null +++ b/video/png/src/pngenc/imp.rs @@ -0,0 +1,340 @@ +// Copyright (C) 2020 Natanael Mojica +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use std::{io, io::Write, sync::Arc}; + +use gst::glib; +use gst::prelude::*; +use gst::subclass::prelude::*; +use gst_video::prelude::*; +use gst_video::subclass::prelude::*; + +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; + +static CAT: Lazy = Lazy::new(|| { + gst::DebugCategory::new( + "rspngenc", + gst::DebugColorFlags::empty(), + Some("PNG encoder"), + ) +}); + +// Inner buffer where the result of frame encoding is written +// before relay them downstream +struct CacheBuffer { + buffer: AtomicRefCell>, +} + +impl CacheBuffer { + pub fn new() -> Self { + Self { + buffer: AtomicRefCell::new(Vec::new()), + } + } + + pub fn clear(&self) { + self.buffer.borrow_mut().clear(); + } + + pub fn write(&self, buf: &[u8]) { + let mut buffer = self.buffer.borrow_mut(); + buffer.extend_from_slice(buf); + } + + pub fn consume(&self) -> Vec { + let mut buffer = self.buffer.borrow_mut(); + std::mem::take(&mut *buffer) + } +} +// The Encoder requires a Writer, so we use here and intermediate structure +// for caching encoded frames +struct CacheWriter { + cache: Arc, +} + +impl CacheWriter { + pub fn new(cache: Arc) -> Self { + Self { cache } + } +} + +impl Write for CacheWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.cache.write(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[derive(Debug, Clone, Copy)] +struct Settings { + compression: CompressionLevel, + filter: FilterType, +} + +impl Default for Settings { + fn default() -> Self { + Settings { + compression: DEFAULT_COMPRESSION_LEVEL, + filter: DEFAULT_FILTER_TYPE, + } + } +} + +struct State { + video_info: gst_video::VideoInfo, + cache: Arc, + writer: Option>, +} + +impl State { + fn new(video_info: gst_video::VideoInfo) -> Self { + let cache = Arc::new(CacheBuffer::new()); + Self { + video_info, + cache, + writer: None, + } + } + + fn reset(&mut self, settings: Settings) -> Result<(), gst::LoggableError> { + // clear the cache + self.cache.clear(); + let width = self.video_info.width(); + let height = self.video_info.height(); + let mut encoder = png::Encoder::new(CacheWriter::new(self.cache.clone()), width, height); + let color = match self.video_info.format() { + gst_video::VideoFormat::Gray8 | gst_video::VideoFormat::Gray16Be => { + png::ColorType::Grayscale + } + gst_video::VideoFormat::Rgb => png::ColorType::Rgb, + gst_video::VideoFormat::Rgba => png::ColorType::Rgba, + _ => { + gst::error!(CAT, "format is not supported yet"); + unreachable!() + } + }; + let depth = if self.video_info.format() == gst_video::VideoFormat::Gray16Be { + png::BitDepth::Sixteen + } else { + png::BitDepth::Eight + }; + + encoder.set_color(color); + encoder.set_depth(depth); + encoder.set_compression(png::Compression::from(settings.compression)); + encoder.set_filter(png::FilterType::from(settings.filter)); + // Write the header for this video format into our inner buffer + let writer = encoder.write_header().map_err(|e| { + gst::loggable_error!(CAT, "Failed to create encoder error: {}", e.to_string()) + })?; + self.writer = Some(writer); + Ok(()) + } + + fn write_data(&mut self, data: &[u8]) -> Result<(), png::EncodingError> { + if let Some(writer) = self.writer.as_mut() { + writer.write_image_data(data) + } else { + unreachable!() + } + } +} + +#[derive(Default)] +pub struct PngEncoder { + state: Mutex>, + settings: Mutex, +} + +#[glib::object_subclass] +impl ObjectSubclass for PngEncoder { + const NAME: &'static str = "PngEncoder"; + type Type = super::PngEncoder; + type ParentType = gst_video::VideoEncoder; +} + +impl ObjectImpl for PngEncoder { + fn properties() -> &'static [glib::ParamSpec] { + static PROPERTIES: Lazy> = Lazy::new(|| { + vec![ + glib::ParamSpecEnum::builder::( + "compression-level", + DEFAULT_COMPRESSION_LEVEL, + ) + .nick("Compression level") + .blurb("Selects the compression algorithm to use") + .mutable_ready() + .build(), + glib::ParamSpecEnum::builder::("filter", DEFAULT_FILTER_TYPE) + .nick("Filter") + .blurb("Selects the filter type to applied") + .mutable_ready() + .build(), + ] + }); + + PROPERTIES.as_ref() + } + + fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { + match pspec.name() { + "compression-level" => { + let mut settings = self.settings.lock(); + settings.compression = value + .get::() + .expect("type checked upstream"); + } + "filter" => { + let mut settings = self.settings.lock(); + settings.filter = value.get::().expect("type checked upstream"); + } + _ => unreachable!(), + } + } + + fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + match pspec.name() { + "compression-level" => { + let settings = self.settings.lock(); + settings.compression.to_value() + } + "filter" => { + let settings = self.settings.lock(); + settings.filter.to_value() + } + _ => unimplemented!(), + } + } +} + +impl GstObjectImpl for PngEncoder {} + +impl ElementImpl for PngEncoder { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "PNG encoder", + "Encoder/Video", + "PNG encoder", + "Natanael Mojica ", + ) + }); + + Some(&*ELEMENT_METADATA) + } + + fn pad_templates() -> &'static [gst::PadTemplate] { + static PAD_TEMPLATES: Lazy> = Lazy::new(|| { + let sink_caps = gst_video::VideoCapsBuilder::new() + .format_list([ + gst_video::VideoFormat::Gray8, + gst_video::VideoFormat::Gray16Be, + gst_video::VideoFormat::Rgb, + gst_video::VideoFormat::Rgba, + ]) + .build(); + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &sink_caps, + ) + .unwrap(); + + let src_caps = gst::Caps::builder("image/png").build(); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &src_caps, + ) + .unwrap(); + + vec![sink_pad_template, src_pad_template] + }); + + PAD_TEMPLATES.as_ref() + } +} + +impl VideoEncoderImpl for PngEncoder { + fn stop(&self) -> Result<(), gst::ErrorMessage> { + *self.state.lock() = None; + Ok(()) + } + + fn set_format( + &self, + state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>, + ) -> Result<(), gst::LoggableError> { + let video_info = state.info(); + gst::debug!(CAT, imp: self, "Setting format {:?}", video_info); + { + let settings = self.settings.lock(); + let mut state = State::new(video_info); + state.reset(*settings)?; + *self.state.lock() = Some(state); + } + + let instance = self.instance(); + let output_state = instance + .set_output_state(gst::Caps::builder("image/png").build(), Some(state)) + .map_err(|_| gst::loggable_error!(CAT, "Failed to set output state"))?; + instance + .negotiate(output_state) + .map_err(|_| gst::loggable_error!(CAT, "Failed to negotiate")) + } + + fn handle_frame( + &self, + mut frame: gst_video::VideoCodecFrame, + ) -> Result { + let mut state_guard = self.state.lock(); + let state = state_guard.as_mut().ok_or(gst::FlowError::NotNegotiated)?; + + gst::debug!( + CAT, + imp: self, + "Sending frame {}", + frame.system_frame_number() + ); + { + let input_buffer = frame.input_buffer().expect("frame without input buffer"); + + let input_map = input_buffer.map_readable().unwrap(); + let data = input_map.as_slice(); + state.write_data(data).map_err(|e| { + gst::element_imp_error!(self, gst::CoreError::Failed, [&e.to_string()]); + gst::FlowError::Error + })?; + } + + let buffer = state.cache.consume(); + drop(state_guard); + + let output_buffer = gst::Buffer::from_mut_slice(buffer); + // There are no such incremental frames in the png format + frame.set_flags(gst_video::VideoCodecFrameFlags::SYNC_POINT); + frame.set_output_buffer(output_buffer); + self.instance().finish_frame(Some(frame)) + } +} diff --git a/video/png/src/pngenc/mod.rs b/video/png/src/pngenc/mod.rs new file mode 100644 index 000000000..b58ea081e --- /dev/null +++ b/video/png/src/pngenc/mod.rs @@ -0,0 +1,101 @@ +// Copyright (C) 2020 Natanael Mojica +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use gst::glib; +use gst::prelude::*; + +mod imp; + +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, glib::Enum)] +#[repr(u32)] +#[enum_type(name = "GstRsPngCompressionLevel")] +pub(crate) enum CompressionLevel { + #[enum_value(name = "Default: Use the default compression level.", nick = "default")] + Default, + #[enum_value(name = "Fast: A fast compression algorithm.", nick = "fast")] + Fast, + #[enum_value( + name = "Best: Uses the algorithm with the best results.", + nick = "best" + )] + Best, + #[enum_value(name = "Huffman: Huffman compression.", nick = "huffman")] + Huffman, + #[enum_value(name = "Rle: Rle compression.", nick = "rle")] + Rle, +} + +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, glib::Enum)] +#[repr(u32)] +#[enum_type(name = "GstRsPngFilterType")] +pub(crate) enum FilterType { + #[enum_value( + name = "NoFilter: No filtering applied to the output.", + nick = "nofilter" + )] + NoFilter, + #[enum_value(name = "Sub: filter applied to each pixel.", nick = "sub")] + Sub, + #[enum_value(name = "Up: Up filter similar to Sub.", nick = "up")] + Up, + #[enum_value( + name = "Avg: The Average filter uses the average of the two neighboring pixels.", + nick = "avg" + )] + Avg, + #[enum_value( + name = "Paeth: The Paeth filter computes a simple linear function of the three neighboring pixels.", + nick = "paeth" + )] + Paeth, +} + +impl From for png::Compression { + #[allow(deprecated)] + 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 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) @extends gst_video::VideoEncoder, gst::Element, gst::Object; +} + +pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { + #[cfg(feature = "doc")] + CompressionLevel::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); + #[cfg(feature = "doc")] + FilterType::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); + + gst::Element::register( + Some(plugin), + "rspngenc", + gst::Rank::Primary, + PngEncoder::static_type(), + ) +} diff --git a/video/png/tests/pngenc.rs b/video/png/tests/pngenc.rs new file mode 100644 index 000000000..dabdb9793 --- /dev/null +++ b/video/png/tests/pngenc.rs @@ -0,0 +1,94 @@ +// Copyright (C) 2020 Natanael Mojica +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use gst::prelude::*; + +fn init() { + use std::sync::Once; + static INIT: Once = Once::new(); + + INIT.call_once(|| { + gst::init().unwrap(); + gstrspng::plugin_register_static().expect("Failed to register rspng plugin"); + }); +} + +#[test] +fn test_png_encode_gray() { + init(); + + let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Gray8, 160, 120) + .fps((30, 1)) + .build() + .unwrap(); + test_png_encode(&video_info); +} + +#[test] +fn test_png_encode_gray16() { + init(); + + let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Gray16Be, 160, 120) + .fps((30, 1)) + .build() + .unwrap(); + test_png_encode(&video_info); +} + +#[test] +fn test_png_encode_rgb() { + init(); + + let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Rgb, 160, 120) + .fps((30, 1)) + .build() + .unwrap(); + test_png_encode(&video_info); +} + +#[test] +fn test_png_encode_rgba() { + init(); + + let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Rgba, 160, 120) + .fps((30, 1)) + .build() + .unwrap(); + test_png_encode(&video_info); +} + +fn test_png_encode(video_info: &gst_video::VideoInfo) { + let mut h = gst_check::Harness::new("rspngenc"); + h.set_src_caps(video_info.to_caps().unwrap()); + h.play(); + + for pts in 0..5 { + let buffer = { + let mut buffer = gst::Buffer::with_size(video_info.size()).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(pts.seconds()); + } + let mut vframe = + gst_video::VideoFrame::from_buffer_writable(buffer, video_info).unwrap(); + for v in vframe.plane_data_mut(0).unwrap() { + *v = 128; + } + vframe.into_buffer() + }; + h.push(buffer.clone()).unwrap(); + } + h.push_event(gst::event::Eos::new()); + + (0..5).for_each(|_| { + let buffer = h.pull().unwrap(); + assert!(!buffer.flags().contains(gst::BufferFlags::DELTA_UNIT)) + }); +} diff --git a/video/rav1e/Cargo.toml b/video/rav1e/Cargo.toml index 836ff80e5..7b6adf0e2 100644 --- a/video/rav1e/Cargo.toml +++ b/video/rav1e/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.0-alpha.1" authors = ["Sebastian Dröge "] repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" license = "MIT OR Apache-2.0" -description = "rav1e AV1 Encoder Plugin" +description = "GStreamer rav1e AV1 Encoder Plugin" edition = "2021" rust-version = "1.63" diff --git a/video/rspng/Cargo.toml b/video/rspng/Cargo.toml deleted file mode 100644 index f096e7da9..000000000 --- a/video/rspng/Cargo.toml +++ /dev/null @@ -1,46 +0,0 @@ -[package] -name = "gst-plugin-rspng" -version = "0.9.0-alpha.1" -authors = ["Natanael Mojica "] -repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" -license = "MIT OR Apache-2.0" -edition = "2021" -rust-version = "1.63" -description = "An PNG encoder/decoder written in pure Rust" - -[dependencies] -gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } -gst_video = { package = "gstreamer-video", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } -png = "0.17.2" -once_cell = "1" -parking_lot = "0.12" -atomic_refcell = "0.1" - -[dev-dependencies] -gst_check = { package = "gstreamer-check", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } - -[lib] -name = "gstrspng" -crate-type = ["cdylib", "rlib"] -path = "src/lib.rs" - -[build-dependencies] -gst-plugin-version-helper = { path="../../version-helper" } - -[features] -static = [] -capi = [] -doc = ["gst/v1_18"] - -[package.metadata.capi] -min_version = "0.8.0" - -[package.metadata.capi.header] -enabled = false - -[package.metadata.capi.library] -install_subdir = "gstreamer-1.0" -versioning = false - -[package.metadata.capi.pkg_config] -requires_private = "gstreamer-1.0, gstreamer-video-1.0, gobject-2.0, glib-2.0, gmodule-2.0" diff --git a/video/rspng/LICENSE-APACHE b/video/rspng/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a..000000000 --- a/video/rspng/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/video/rspng/LICENSE-MIT b/video/rspng/LICENSE-MIT deleted file mode 120000 index b2cfbdc7b..000000000 --- a/video/rspng/LICENSE-MIT +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-MIT \ No newline at end of file diff --git a/video/rspng/build.rs b/video/rspng/build.rs deleted file mode 100644 index cda12e57e..000000000 --- a/video/rspng/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - gst_plugin_version_helper::info() -} diff --git a/video/rspng/examples/pngenc.rs b/video/rspng/examples/pngenc.rs deleted file mode 100644 index 0ed819757..000000000 --- a/video/rspng/examples/pngenc.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2020 Natanael Mojica -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// SPDX-License-Identifier: MIT OR Apache-2.0 - -use gst::prelude::*; - -const ENCODE_PIPELINE: &str = "videotestsrc is-live=false num-buffers=1 ! videoconvert ! video/x-raw, format=RGB, width=160, height=120 ! - rspngenc compression-level=2 filter=4 ! filesink location=frame.png"; - -fn main() { - gst::init().unwrap(); - gstrspng::plugin_register_static().expect("Failed to register gif plugin"); - - let pipeline = gst::parse_launch(ENCODE_PIPELINE).unwrap(); - let bus = pipeline.bus().unwrap(); - - pipeline - .set_state(gst::State::Playing) - .expect("Failed to set pipeline state to playing"); - - for msg in bus.iter_timed(gst::ClockTime::NONE) { - use gst::MessageView; - - match msg.view() { - MessageView::Eos(..) => break, - MessageView::Error(err) => { - println!( - "Error from {:?}: {} ({:?})", - err.src().map(|s| s.path_string()), - err.error(), - err.debug() - ); - break; - } - _ => (), - } - } - pipeline - .set_state(gst::State::Null) - .expect("Failed to set pipeline state to null"); -} diff --git a/video/rspng/src/lib.rs b/video/rspng/src/lib.rs deleted file mode 100644 index 030efc918..000000000 --- a/video/rspng/src/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2020 Natanael Mojica -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// SPDX-License-Identifier: MIT OR Apache-2.0 -#![allow(clippy::non_send_fields_in_send_ty, unused_doc_comments)] - -/** - * plugin-rspng: - * - * Since: plugins-rs-0.6.0 - */ -use gst::glib; - -mod pngenc; - -fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - pngenc::register(plugin)?; - Ok(()) -} - -gst::plugin_define!( - rspng, - env!("CARGO_PKG_DESCRIPTION"), - plugin_init, - concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")), - "MIT/X11", - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_REPOSITORY"), - env!("BUILD_REL_DATE") -); diff --git a/video/rspng/src/pngenc/imp.rs b/video/rspng/src/pngenc/imp.rs deleted file mode 100644 index 851677d86..000000000 --- a/video/rspng/src/pngenc/imp.rs +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright (C) 2020 Natanael Mojica -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// SPDX-License-Identifier: MIT OR Apache-2.0 - -use std::{io, io::Write, sync::Arc}; - -use gst::glib; -use gst::prelude::*; -use gst::subclass::prelude::*; -use gst_video::prelude::*; -use gst_video::subclass::prelude::*; - -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; - -static CAT: Lazy = Lazy::new(|| { - gst::DebugCategory::new( - "rspngenc", - gst::DebugColorFlags::empty(), - Some("PNG encoder"), - ) -}); - -// Inner buffer where the result of frame encoding is written -// before relay them downstream -struct CacheBuffer { - buffer: AtomicRefCell>, -} - -impl CacheBuffer { - pub fn new() -> Self { - Self { - buffer: AtomicRefCell::new(Vec::new()), - } - } - - pub fn clear(&self) { - self.buffer.borrow_mut().clear(); - } - - pub fn write(&self, buf: &[u8]) { - let mut buffer = self.buffer.borrow_mut(); - buffer.extend_from_slice(buf); - } - - pub fn consume(&self) -> Vec { - let mut buffer = self.buffer.borrow_mut(); - std::mem::take(&mut *buffer) - } -} -// The Encoder requires a Writer, so we use here and intermediate structure -// for caching encoded frames -struct CacheWriter { - cache: Arc, -} - -impl CacheWriter { - pub fn new(cache: Arc) -> Self { - Self { cache } - } -} - -impl Write for CacheWriter { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.cache.write(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[derive(Debug, Clone, Copy)] -struct Settings { - compression: CompressionLevel, - filter: FilterType, -} - -impl Default for Settings { - fn default() -> Self { - Settings { - compression: DEFAULT_COMPRESSION_LEVEL, - filter: DEFAULT_FILTER_TYPE, - } - } -} - -struct State { - video_info: gst_video::VideoInfo, - cache: Arc, - writer: Option>, -} - -impl State { - fn new(video_info: gst_video::VideoInfo) -> Self { - let cache = Arc::new(CacheBuffer::new()); - Self { - video_info, - cache, - writer: None, - } - } - - fn reset(&mut self, settings: Settings) -> Result<(), gst::LoggableError> { - // clear the cache - self.cache.clear(); - let width = self.video_info.width(); - let height = self.video_info.height(); - let mut encoder = png::Encoder::new(CacheWriter::new(self.cache.clone()), width, height); - let color = match self.video_info.format() { - gst_video::VideoFormat::Gray8 | gst_video::VideoFormat::Gray16Be => { - png::ColorType::Grayscale - } - gst_video::VideoFormat::Rgb => png::ColorType::Rgb, - gst_video::VideoFormat::Rgba => png::ColorType::Rgba, - _ => { - gst::error!(CAT, "format is not supported yet"); - unreachable!() - } - }; - let depth = if self.video_info.format() == gst_video::VideoFormat::Gray16Be { - png::BitDepth::Sixteen - } else { - png::BitDepth::Eight - }; - - encoder.set_color(color); - encoder.set_depth(depth); - encoder.set_compression(png::Compression::from(settings.compression)); - encoder.set_filter(png::FilterType::from(settings.filter)); - // Write the header for this video format into our inner buffer - let writer = encoder.write_header().map_err(|e| { - gst::loggable_error!(CAT, "Failed to create encoder error: {}", e.to_string()) - })?; - self.writer = Some(writer); - Ok(()) - } - - fn write_data(&mut self, data: &[u8]) -> Result<(), png::EncodingError> { - if let Some(writer) = self.writer.as_mut() { - writer.write_image_data(data) - } else { - unreachable!() - } - } -} - -#[derive(Default)] -pub struct PngEncoder { - state: Mutex>, - settings: Mutex, -} - -#[glib::object_subclass] -impl ObjectSubclass for PngEncoder { - const NAME: &'static str = "PngEncoder"; - type Type = super::PngEncoder; - type ParentType = gst_video::VideoEncoder; -} - -impl ObjectImpl for PngEncoder { - fn properties() -> &'static [glib::ParamSpec] { - static PROPERTIES: Lazy> = Lazy::new(|| { - vec![ - glib::ParamSpecEnum::builder::( - "compression-level", - DEFAULT_COMPRESSION_LEVEL, - ) - .nick("Compression level") - .blurb("Selects the compression algorithm to use") - .mutable_ready() - .build(), - glib::ParamSpecEnum::builder::("filter", DEFAULT_FILTER_TYPE) - .nick("Filter") - .blurb("Selects the filter type to applied") - .mutable_ready() - .build(), - ] - }); - - PROPERTIES.as_ref() - } - - fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { - match pspec.name() { - "compression-level" => { - let mut settings = self.settings.lock(); - settings.compression = value - .get::() - .expect("type checked upstream"); - } - "filter" => { - let mut settings = self.settings.lock(); - settings.filter = value.get::().expect("type checked upstream"); - } - _ => unreachable!(), - } - } - - fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { - match pspec.name() { - "compression-level" => { - let settings = self.settings.lock(); - settings.compression.to_value() - } - "filter" => { - let settings = self.settings.lock(); - settings.filter.to_value() - } - _ => unimplemented!(), - } - } -} - -impl GstObjectImpl for PngEncoder {} - -impl ElementImpl for PngEncoder { - fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - static ELEMENT_METADATA: Lazy = Lazy::new(|| { - gst::subclass::ElementMetadata::new( - "PNG encoder", - "Encoder/Video", - "PNG encoder", - "Natanael Mojica ", - ) - }); - - Some(&*ELEMENT_METADATA) - } - - fn pad_templates() -> &'static [gst::PadTemplate] { - static PAD_TEMPLATES: Lazy> = Lazy::new(|| { - let sink_caps = gst_video::VideoCapsBuilder::new() - .format_list([ - gst_video::VideoFormat::Gray8, - gst_video::VideoFormat::Gray16Be, - gst_video::VideoFormat::Rgb, - gst_video::VideoFormat::Rgba, - ]) - .build(); - let sink_pad_template = gst::PadTemplate::new( - "sink", - gst::PadDirection::Sink, - gst::PadPresence::Always, - &sink_caps, - ) - .unwrap(); - - let src_caps = gst::Caps::builder("image/png").build(); - let src_pad_template = gst::PadTemplate::new( - "src", - gst::PadDirection::Src, - gst::PadPresence::Always, - &src_caps, - ) - .unwrap(); - - vec![sink_pad_template, src_pad_template] - }); - - PAD_TEMPLATES.as_ref() - } -} - -impl VideoEncoderImpl for PngEncoder { - fn stop(&self) -> Result<(), gst::ErrorMessage> { - *self.state.lock() = None; - Ok(()) - } - - fn set_format( - &self, - state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>, - ) -> Result<(), gst::LoggableError> { - let video_info = state.info(); - gst::debug!(CAT, imp: self, "Setting format {:?}", video_info); - { - let settings = self.settings.lock(); - let mut state = State::new(video_info); - state.reset(*settings)?; - *self.state.lock() = Some(state); - } - - let instance = self.instance(); - let output_state = instance - .set_output_state(gst::Caps::builder("image/png").build(), Some(state)) - .map_err(|_| gst::loggable_error!(CAT, "Failed to set output state"))?; - instance - .negotiate(output_state) - .map_err(|_| gst::loggable_error!(CAT, "Failed to negotiate")) - } - - fn handle_frame( - &self, - mut frame: gst_video::VideoCodecFrame, - ) -> Result { - let mut state_guard = self.state.lock(); - let state = state_guard.as_mut().ok_or(gst::FlowError::NotNegotiated)?; - - gst::debug!( - CAT, - imp: self, - "Sending frame {}", - frame.system_frame_number() - ); - { - let input_buffer = frame.input_buffer().expect("frame without input buffer"); - - let input_map = input_buffer.map_readable().unwrap(); - let data = input_map.as_slice(); - state.write_data(data).map_err(|e| { - gst::element_imp_error!(self, gst::CoreError::Failed, [&e.to_string()]); - gst::FlowError::Error - })?; - } - - let buffer = state.cache.consume(); - drop(state_guard); - - let output_buffer = gst::Buffer::from_mut_slice(buffer); - // There are no such incremental frames in the png format - frame.set_flags(gst_video::VideoCodecFrameFlags::SYNC_POINT); - frame.set_output_buffer(output_buffer); - self.instance().finish_frame(Some(frame)) - } -} diff --git a/video/rspng/src/pngenc/mod.rs b/video/rspng/src/pngenc/mod.rs deleted file mode 100644 index b58ea081e..000000000 --- a/video/rspng/src/pngenc/mod.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (C) 2020 Natanael Mojica -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// SPDX-License-Identifier: MIT OR Apache-2.0 - -use gst::glib; -use gst::prelude::*; - -mod imp; - -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, glib::Enum)] -#[repr(u32)] -#[enum_type(name = "GstRsPngCompressionLevel")] -pub(crate) enum CompressionLevel { - #[enum_value(name = "Default: Use the default compression level.", nick = "default")] - Default, - #[enum_value(name = "Fast: A fast compression algorithm.", nick = "fast")] - Fast, - #[enum_value( - name = "Best: Uses the algorithm with the best results.", - nick = "best" - )] - Best, - #[enum_value(name = "Huffman: Huffman compression.", nick = "huffman")] - Huffman, - #[enum_value(name = "Rle: Rle compression.", nick = "rle")] - Rle, -} - -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, glib::Enum)] -#[repr(u32)] -#[enum_type(name = "GstRsPngFilterType")] -pub(crate) enum FilterType { - #[enum_value( - name = "NoFilter: No filtering applied to the output.", - nick = "nofilter" - )] - NoFilter, - #[enum_value(name = "Sub: filter applied to each pixel.", nick = "sub")] - Sub, - #[enum_value(name = "Up: Up filter similar to Sub.", nick = "up")] - Up, - #[enum_value( - name = "Avg: The Average filter uses the average of the two neighboring pixels.", - nick = "avg" - )] - Avg, - #[enum_value( - name = "Paeth: The Paeth filter computes a simple linear function of the three neighboring pixels.", - nick = "paeth" - )] - Paeth, -} - -impl From for png::Compression { - #[allow(deprecated)] - 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 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) @extends gst_video::VideoEncoder, gst::Element, gst::Object; -} - -pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - #[cfg(feature = "doc")] - CompressionLevel::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); - #[cfg(feature = "doc")] - FilterType::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); - - gst::Element::register( - Some(plugin), - "rspngenc", - gst::Rank::Primary, - PngEncoder::static_type(), - ) -} diff --git a/video/rspng/tests/pngenc.rs b/video/rspng/tests/pngenc.rs deleted file mode 100644 index dabdb9793..000000000 --- a/video/rspng/tests/pngenc.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (C) 2020 Natanael Mojica -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// SPDX-License-Identifier: MIT OR Apache-2.0 - -use gst::prelude::*; - -fn init() { - use std::sync::Once; - static INIT: Once = Once::new(); - - INIT.call_once(|| { - gst::init().unwrap(); - gstrspng::plugin_register_static().expect("Failed to register rspng plugin"); - }); -} - -#[test] -fn test_png_encode_gray() { - init(); - - let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Gray8, 160, 120) - .fps((30, 1)) - .build() - .unwrap(); - test_png_encode(&video_info); -} - -#[test] -fn test_png_encode_gray16() { - init(); - - let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Gray16Be, 160, 120) - .fps((30, 1)) - .build() - .unwrap(); - test_png_encode(&video_info); -} - -#[test] -fn test_png_encode_rgb() { - init(); - - let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Rgb, 160, 120) - .fps((30, 1)) - .build() - .unwrap(); - test_png_encode(&video_info); -} - -#[test] -fn test_png_encode_rgba() { - init(); - - let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Rgba, 160, 120) - .fps((30, 1)) - .build() - .unwrap(); - test_png_encode(&video_info); -} - -fn test_png_encode(video_info: &gst_video::VideoInfo) { - let mut h = gst_check::Harness::new("rspngenc"); - h.set_src_caps(video_info.to_caps().unwrap()); - h.play(); - - for pts in 0..5 { - let buffer = { - let mut buffer = gst::Buffer::with_size(video_info.size()).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(pts.seconds()); - } - let mut vframe = - gst_video::VideoFrame::from_buffer_writable(buffer, video_info).unwrap(); - for v in vframe.plane_data_mut(0).unwrap() { - *v = 128; - } - vframe.into_buffer() - }; - h.push(buffer.clone()).unwrap(); - } - h.push_event(gst::event::Eos::new()); - - (0..5).for_each(|_| { - let buffer = h.pull().unwrap(); - assert!(!buffer.flags().contains(gst::BufferFlags::DELTA_UNIT)) - }); -} diff --git a/video/videofx/Cargo.toml b/video/videofx/Cargo.toml index 4ddba4894..bfa2585f7 100644 --- a/video/videofx/Cargo.toml +++ b/video/videofx/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.0-alpha.1" authors = ["Sanchayan Maity ", "Rafael Caricio "] repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" license = "MPL-2.0" -description = "Video Effects Plugin" +description = "GStreamer Rust Video Effects Plugin" edition = "2021" rust-version = "1.63" @@ -39,7 +39,7 @@ git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" package = "gstreamer-check" [lib] -name = "gstvideofx" +name = "gstrsvideofx" crate-type = ["cdylib", "rlib"] path = "src/lib.rs" diff --git a/video/videofx/src/lib.rs b/video/videofx/src/lib.rs index 232c0b4f8..ce811038e 100644 --- a/video/videofx/src/lib.rs +++ b/video/videofx/src/lib.rs @@ -9,7 +9,7 @@ #![allow(clippy::non_send_fields_in_send_ty, unused_doc_comments)] /** - * plugin-videofx: + * plugin-rsvideofx: * * Since: plugins-rs-0.8.0 */ @@ -32,7 +32,7 @@ fn plugin_init(plugin: &gst::Plugin) -> Result<(), gst::glib::BoolError> { } gst::plugin_define!( - videofx, + rsvideofx, env!("CARGO_PKG_DESCRIPTION"), plugin_init, concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")), diff --git a/video/webp/Cargo.toml b/video/webp/Cargo.toml index 8ea1a263f..11ec86677 100644 --- a/video/webp/Cargo.toml +++ b/video/webp/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Mathieu Duponchelle "] license = "MPL-2.0" edition = "2021" rust-version = "1.63" -description = "WebP Plugin" +description = "GStreamer WebP Plugin" repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" [dependencies] -- cgit v1.2.3