diff --git a/Cargo.toml b/Cargo.toml index 3519ff3e7..8f47e109a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ members = [ "gstreamer-tag/sys", "gstreamer-video/sys", "gstreamer-webrtc/sys", + "gstreamer-allocators/sys", "gstreamer", "gstreamer-app", "gstreamer-audio", @@ -43,6 +44,7 @@ members = [ "gstreamer-sdp", "gstreamer-video", "gstreamer-webrtc", + "gstreamer-allocators", "examples", "tutorials", ] diff --git a/gstreamer-allocators/CHANGELOG.md b/gstreamer-allocators/CHANGELOG.md new file mode 120000 index 000000000..670919a56 --- /dev/null +++ b/gstreamer-allocators/CHANGELOG.md @@ -0,0 +1 @@ +../gstreamer/CHANGELOG.md \ No newline at end of file diff --git a/gstreamer-allocators/COPYRIGHT b/gstreamer-allocators/COPYRIGHT new file mode 120000 index 000000000..dc5f40a22 --- /dev/null +++ b/gstreamer-allocators/COPYRIGHT @@ -0,0 +1 @@ +../COPYRIGHT \ No newline at end of file diff --git a/gstreamer-allocators/Cargo.toml b/gstreamer-allocators/Cargo.toml new file mode 100644 index 000000000..94d7583d0 --- /dev/null +++ b/gstreamer-allocators/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "gstreamer-allocators" +version = "0.19.0" +authors = ["Sebastian Dröge "] +categories = ["api-bindings", "multimedia"] +description = "Rust bindings for GStreamer Allocators library" +repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" +license = "MIT/Apache-2.0" +readme = "README.md" +homepage = "https://gstreamer.freedesktop.org" +documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_allocators/" +keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"] +edition = "2021" +rust-version = "1.56" + +[dependencies] +libc = "0.2" +bitflags = "1.0" +ffi = { package = "gstreamer-allocators-sys", path = "sys" } +glib = { git = "https://github.com/gtk-rs/gtk-rs-core" } +gst = { package = "gstreamer", path = "../gstreamer" } +once_cell = "1.0" + +[dev-dependencies] +gir-format-check = "0.1" + +[features] +default = [] +v1_10 = ["gst/v1_10", "ffi/v1_10"] +v1_12 = ["gst/v1_12", "ffi/v1_12", "v1_10"] +v1_14 = ["gst/v1_14", "ffi/v1_14", "v1_12"] +v1_16 = ["gst/v1_16", "ffi/v1_16", "v1_14"] +v1_18 = ["gst/v1_18", "ffi/v1_18", "v1_16"] +v1_20 = ["gst/v1_20", "ffi/v1_20", "v1_18"] +dox = ["v1_20", "ffi/dox", "glib/dox", "gst/dox"] + +[package.metadata.docs.rs] +features = ["dox"] diff --git a/gstreamer-allocators/Gir.toml b/gstreamer-allocators/Gir.toml new file mode 100644 index 000000000..0586dc2e5 --- /dev/null +++ b/gstreamer-allocators/Gir.toml @@ -0,0 +1,72 @@ +[options] +concurrency = "send+sync" +generate_display_trait = false +generate_safety_asserts = true +girs_directories = ["../gir-files", "../gst-gir-files"] +library = "GstAllocators" +min_cfg_version = "1.8" +single_version_file = true +trust_return_value_nullability = true +version = "1.0" +work_mode = "normal" + +external_libraries = [ + "GLib", + "GObject", + "Gst", +] + +generate = [ + "GstAllocators.FdMemoryFlags", + "GstAllocators.PhysMemoryAllocator", +] + +manual = [ + "Gst.Allocator", + "Gst.Memory", +] + +[[object]] +name = "Gst.Buffer" +ref_mode = "ref" +status = "manual" + +[[object]] +name = "GstAllocators.*" +status = "generate" + [[object.function]] + name = "dmabuf_memory_get_fd" + manual = true + [[object.function]] + name = "fd_memory_get_fd" + manual = true + [[object.function]] + name = "is_dmabuf_memory" + manual = true + [[object.function]] + name = "is_fd_memory" + manual = true + [[object.function]] + name = "is_phys_memory" + manual = true + [[object.function]] + name = "phys_memory_get_phys_addr" + manual = true + +[[object]] +name = "GstAllocators.DmaBufAllocator" +status = "generate" +cfg_condition = "target_os = \"linux\"" + [[object.function]] + name = "alloc" + manual = true + [[object.function]] + name = "alloc_with_flags" + manual = true + +[[object]] +name = "GstAllocators.FdAllocator" +status = "generate" + [[object.function]] + name = "alloc" + manual = true \ No newline at end of file diff --git a/gstreamer-allocators/LICENSE-APACHE b/gstreamer-allocators/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/gstreamer-allocators/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/gstreamer-allocators/LICENSE-MIT b/gstreamer-allocators/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/gstreamer-allocators/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/gstreamer-allocators/README.md b/gstreamer-allocators/README.md new file mode 100644 index 000000000..641e118f4 --- /dev/null +++ b/gstreamer-allocators/README.md @@ -0,0 +1,202 @@ +# gstreamer-rs [![crates.io](https://img.shields.io/crates/v/gstreamer-allocators.svg)](https://crates.io/crates/gstreamer-allocators) [![pipeline status](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/badges/main/pipeline.svg)](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/commits/main) + +[GStreamer](https://gstreamer.freedesktop.org/) (Allocators library) bindings for Rust. +Documentation can be found [here](https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_allocators/). + +These bindings are providing a safe API that can be used to interface with +GStreamer, e.g. for writing GStreamer-based applications and GStreamer plugins. + +The bindings are mostly autogenerated with [gir](https://github.com/gtk-rs/gir/) +based on the [GObject-Introspection](https://wiki.gnome.org/Projects/GObjectIntrospection/) +API metadata provided by the GStreamer project. + +## Table of Contents +1. [Installation](#installation) + 1. [Linux/BSDs](#installation-linux) + 1. [macOS](#installation-macos) + 1. [Windows](#installation-windows) +1. [Getting Started](#getting-started) +1. [License](#license) +1. [Contribution](#contribution) + + + +## Installation + +To build the GStreamer bindings or anything depending on them, you need to +have at least GStreamer 1.8 and gst-plugins-base 1.8 installed. In addition, +some of the examples/tutorials require various GStreamer plugins to be +available, which can be found in gst-plugins-base, gst-plugins-good, +gst-plugins-bad, gst-plugins-ugly and/or gst-libav. + + + +### Linux/BSDs + +You need to install the above mentioned packages with your distributions +package manager, or build them from source. + +On Debian/Ubuntu they can be installed with + +```console +$ apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \ + gstreamer1.0-libav libgstrtspserver-1.0-dev libges-1.0-dev +``` + +The minimum required version of the above libraries is >= 1.8. If you +build the gstreamer-player sub-crate, or any of the examples that +depend on gstreamer-player, you must ensure that in addition to the +above packages, `libgstreamer-plugins-bad1.0-dev` is installed and +that the version is >= 1.12. See the `Cargo.toml` files for the full +details, + +```console +$ # Only if you wish to install gstreamer-player, make sure the version +$ # of this package is >= 1.12. +$ apt-get install libgstreamer-plugins-bad1.0-dev +``` + +Package names on other distributions should be similar. +Please submit a pull request with instructions for yours. + + + +### macOS + +You can install GStreamer and the plugins via [Homebrew](https://brew.sh/) or +by installing the [binaries](https://gstreamer.freedesktop.org/data/pkg/osx/) +provided by the GStreamer project. + +#### Homebrew + +Homebrew only installs various plugins if explicitly enabled, so some extra +`--with-*` flags may be required. + +```console +$ brew install gstreamer gst-plugins-base gst-plugins-good \ + gst-plugins-bad gst-plugins-ugly gst-libav gst-rtsp-server \ + gst-editing-services --with-orc --with-libogg --with-opus \ + --with-pango --with-theora --with-libvorbis --with-libvpx \ + --enable-gtk3 +``` + +If you wish to install the gstreamer-player sub-crate, make sure the +version of these libraries is >= 1.12. Otherwise, a version >= 1.8 is +sufficient. + +#### GStreamer Binaries + +You need to download the *two* `.pkg` files from the GStreamer website and +install them, e.g. `gstreamer-1.0-1.12.3-x86_64.pkg` and +`gstreamer-1.0-devel-1.12.3-x86_64.pkg`. + +After installation, you also need to install `pkg-config` (e.g. via Homebrew) +and set the `PKG_CONFIG_PATH` environment variable + +```console +$ export PKG_CONFIG_PATH="/Library/Frameworks/GStreamer.framework/Versions/Current/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" +``` + + + +### Windows + +You can install GStreamer and the plugins via [MSYS2](http://www.msys2.org/) +with `pacman` or by installing the +[binaries](https://gstreamer.freedesktop.org/data/pkg/windows/) provided by +the GStreamer project. + +#### MSYS2 / pacman + +```console +$ pacman -S glib2-devel pkg-config \ + mingw-w64-x86_64-gstreamer mingw-w64-x86_64-gst-plugins-base \ + mingw-w64-x86_64-gst-plugins-good mingw-w64-x86_64-gst-plugins-bad \ + mingw-w64-x86_64-gst-plugins-ugly mingw-w64-x86_64-gst-libav \ + mingw-w64-x86_64-gst-rtsp-server +``` + +If you wish to install the gstreamer-player sub-crate, make sure the +version of these libraries is >= 1.12. Otherwise, a version >= 1.8 is +sufficient. + +Note that the version of `pkg-config` included in `MSYS2` is +[known to have problems](https://github.com/rust-lang/pkg-config-rs/issues/51#issuecomment-346300858) +compiling GStreamer, so you may need to install another version. One option +would be [`pkg-config-lite`](https://sourceforge.net/projects/pkgconfiglite/). + +#### GStreamer Binaries + +You need to download the *two* `.msi` files for your platform from the +GStreamer website and install them, e.g. `gstreamer-1.0-x86_64-1.12.3.msi` and +`gstreamer-1.0-devel-x86_64-1.12.3.msi`. + +After installation, you also need to install `pkg-config` (e.g. via MSYS2 or +from [here](https://sourceforge.net/projects/pkgconfiglite/)) +and set the `PKG_CONFIG_PATH` environment variable + +```console +$ export PKG_CONFIG_PATH="c:\\gstreamer\\1.0\\x86_64\\lib\\pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" +``` + + + +## Getting Started + +The API reference can be found +[here](https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer/), however it is +only the Rust API reference and does not explain any of the concepts. + +For getting started with GStreamer development, the best would be to follow +the [documentation](https://gstreamer.freedesktop.org/documentation/) on the +GStreamer website, especially the [Application Development +Manual](https://gstreamer.freedesktop.org/documentation/application-development/). +While being C-centric, it explains all the fundamental concepts of GStreamer +and the code examples should be relatively easily translatable to Rust. The +API is basically the same, function/struct names are the same and everything +is only more convenient (hopefully) and safer. + +In addition there are +[tutorials](https://gstreamer.freedesktop.org/documentation/tutorials/) on the +GStreamer website. Many of them were ported to Rust already and the code can +be found in the +[tutorials](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/tree/main/tutorials) +directory. + +Some further examples for various aspects of GStreamer and how to use it from +Rust can be found in the +[examples](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/tree/main/examples) +directory. + +Various GStreamer plugins written in Rust can be found in the +[gst-plugins-rs](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs) +repository. + + + +## LICENSE + +gstreamer-rs and all crates contained in here are licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. + +GStreamer itself is licensed under the Lesser General Public License version +2.1 or (at your option) any later version: +https://www.gnu.org/licenses/lgpl-2.1.html + + + +## Contribution + +Any kinds of contributions are welcome as a pull request. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in gstreamer-rs by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/gstreamer-allocators/src/auto/constants.rs b/gstreamer-allocators/src/auto/constants.rs new file mode 100644 index 000000000..86b3b67aa --- /dev/null +++ b/gstreamer-allocators/src/auto/constants.rs @@ -0,0 +1,26 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use std::ffi::CStr; + +#[doc(alias = "GST_ALLOCATOR_DMABUF")] +pub static ALLOCATOR_DMABUF: once_cell::sync::Lazy<&'static str> = + once_cell::sync::Lazy::new(|| unsafe { + CStr::from_ptr(ffi::GST_ALLOCATOR_DMABUF).to_str().unwrap() + }); +#[doc(alias = "GST_ALLOCATOR_FD")] +pub static ALLOCATOR_FD: once_cell::sync::Lazy<&'static str> = + once_cell::sync::Lazy::new(|| unsafe { + CStr::from_ptr(ffi::GST_ALLOCATOR_FD).to_str().unwrap() + }); +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +#[doc(alias = "GST_CAPS_FEATURE_MEMORY_DMABUF")] +pub static CAPS_FEATURE_MEMORY_DMABUF: once_cell::sync::Lazy<&'static str> = + once_cell::sync::Lazy::new(|| unsafe { + CStr::from_ptr(ffi::GST_CAPS_FEATURE_MEMORY_DMABUF) + .to_str() + .unwrap() + }); diff --git a/gstreamer-allocators/src/auto/dma_buf_allocator.rs b/gstreamer-allocators/src/auto/dma_buf_allocator.rs new file mode 100644 index 000000000..7cd494f6a --- /dev/null +++ b/gstreamer-allocators/src/auto/dma_buf_allocator.rs @@ -0,0 +1,36 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use crate::FdAllocator; +use glib::object::Cast; +use glib::translate::*; + +glib::wrapper! { + #[doc(alias = "GstDmaBufAllocator")] + pub struct DmaBufAllocator(Object) @extends FdAllocator, gst::Allocator; + + match fn { + type_ => || ffi::gst_dmabuf_allocator_get_type(), + } +} + +impl DmaBufAllocator { + pub const NONE: Option<&'static DmaBufAllocator> = None; + + #[doc(alias = "gst_dmabuf_allocator_new")] + pub fn new() -> DmaBufAllocator { + assert_initialized_main_thread!(); + unsafe { gst::Allocator::from_glib_full(ffi::gst_dmabuf_allocator_new()).unsafe_cast() } + } +} + +impl Default for DmaBufAllocator { + fn default() -> Self { + Self::new() + } +} + +unsafe impl Send for DmaBufAllocator {} +unsafe impl Sync for DmaBufAllocator {} diff --git a/gstreamer-allocators/src/auto/fd_allocator.rs b/gstreamer-allocators/src/auto/fd_allocator.rs new file mode 100644 index 000000000..f296a7a94 --- /dev/null +++ b/gstreamer-allocators/src/auto/fd_allocator.rs @@ -0,0 +1,35 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use glib::object::Cast; +use glib::translate::*; + +glib::wrapper! { + #[doc(alias = "GstFdAllocator")] + pub struct FdAllocator(Object) @extends gst::Allocator; + + match fn { + type_ => || ffi::gst_fd_allocator_get_type(), + } +} + +impl FdAllocator { + pub const NONE: Option<&'static FdAllocator> = None; + + #[doc(alias = "gst_fd_allocator_new")] + pub fn new() -> FdAllocator { + assert_initialized_main_thread!(); + unsafe { gst::Allocator::from_glib_full(ffi::gst_fd_allocator_new()).unsafe_cast() } + } +} + +impl Default for FdAllocator { + fn default() -> Self { + Self::new() + } +} + +unsafe impl Send for FdAllocator {} +unsafe impl Sync for FdAllocator {} diff --git a/gstreamer-allocators/src/auto/flags.rs b/gstreamer-allocators/src/auto/flags.rs new file mode 100644 index 000000000..352874cc9 --- /dev/null +++ b/gstreamer-allocators/src/auto/flags.rs @@ -0,0 +1,38 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use bitflags::bitflags; +use glib::translate::*; + +bitflags! { + #[doc(alias = "GstFdMemoryFlags")] + pub struct FdMemoryFlags: u32 { + #[doc(alias = "GST_FD_MEMORY_FLAG_NONE")] + const NONE = ffi::GST_FD_MEMORY_FLAG_NONE as u32; + #[doc(alias = "GST_FD_MEMORY_FLAG_KEEP_MAPPED")] + const KEEP_MAPPED = ffi::GST_FD_MEMORY_FLAG_KEEP_MAPPED as u32; + #[doc(alias = "GST_FD_MEMORY_FLAG_MAP_PRIVATE")] + const MAP_PRIVATE = ffi::GST_FD_MEMORY_FLAG_MAP_PRIVATE as u32; + #[doc(alias = "GST_FD_MEMORY_FLAG_DONT_CLOSE")] + const DONT_CLOSE = ffi::GST_FD_MEMORY_FLAG_DONT_CLOSE as u32; + } +} + +#[doc(hidden)] +impl IntoGlib for FdMemoryFlags { + type GlibType = ffi::GstFdMemoryFlags; + + fn into_glib(self) -> ffi::GstFdMemoryFlags { + self.bits() + } +} + +#[doc(hidden)] +impl FromGlib for FdMemoryFlags { + unsafe fn from_glib(value: ffi::GstFdMemoryFlags) -> Self { + skip_assert_initialized!(); + Self::from_bits_truncate(value) + } +} diff --git a/gstreamer-allocators/src/auto/functions.rs b/gstreamer-allocators/src/auto/functions.rs new file mode 100644 index 000000000..d1dffad71 --- /dev/null +++ b/gstreamer-allocators/src/auto/functions.rs @@ -0,0 +1,6 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use glib::translate::*; diff --git a/gstreamer-allocators/src/auto/mod.rs b/gstreamer-allocators/src/auto/mod.rs new file mode 100644 index 000000000..262245900 --- /dev/null +++ b/gstreamer-allocators/src/auto/mod.rs @@ -0,0 +1,44 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +#[cfg(any(target_os = "linux", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(target_os = "linux")))] +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +mod dma_buf_allocator; +#[cfg(any(target_os = "linux", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(target_os = "linux")))] +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +pub use self::dma_buf_allocator::DmaBufAllocator; + +mod fd_allocator; +pub use self::fd_allocator::FdAllocator; + +#[cfg(any(feature = "v1_14", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] +mod phys_memory_allocator; +#[cfg(any(feature = "v1_14", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] +pub use self::phys_memory_allocator::PhysMemoryAllocator; + +mod flags; +pub use self::flags::FdMemoryFlags; + +pub mod functions; + +mod constants; +pub use self::constants::ALLOCATOR_DMABUF; +pub use self::constants::ALLOCATOR_FD; +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +pub use self::constants::CAPS_FEATURE_MEMORY_DMABUF; + +#[doc(hidden)] +pub mod traits { + #[cfg(any(feature = "v1_14", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] + pub use super::phys_memory_allocator::PhysMemoryAllocatorExt; +} diff --git a/gstreamer-allocators/src/auto/phys_memory_allocator.rs b/gstreamer-allocators/src/auto/phys_memory_allocator.rs new file mode 100644 index 000000000..68741e746 --- /dev/null +++ b/gstreamer-allocators/src/auto/phys_memory_allocator.rs @@ -0,0 +1,26 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use glib::object::IsA; + +glib::wrapper! { + #[doc(alias = "GstPhysMemoryAllocator")] + pub struct PhysMemoryAllocator(Interface) @requires gst::Allocator; + + match fn { + type_ => || ffi::gst_phys_memory_allocator_get_type(), + } +} + +impl PhysMemoryAllocator { + pub const NONE: Option<&'static PhysMemoryAllocator> = None; +} + +unsafe impl Send for PhysMemoryAllocator {} +unsafe impl Sync for PhysMemoryAllocator {} + +pub trait PhysMemoryAllocatorExt: 'static {} + +impl> PhysMemoryAllocatorExt for O {} diff --git a/gstreamer-allocators/src/auto/versions.txt b/gstreamer-allocators/src/auto/versions.txt new file mode 100644 index 000000000..87263bda9 --- /dev/null +++ b/gstreamer-allocators/src/auto/versions.txt @@ -0,0 +1,3 @@ +Generated by gir (https://github.com/gtk-rs/gir @ e0d8d8d645b1) +from gir-files (https://github.com/gtk-rs/gir-files @ 3ff4d3275258) +from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 233e3205cb17) diff --git a/gstreamer-allocators/src/caps_features.rs b/gstreamer-allocators/src/caps_features.rs new file mode 100644 index 000000000..a4697d8cb --- /dev/null +++ b/gstreamer-allocators/src/caps_features.rs @@ -0,0 +1,8 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +use gst::CapsFeatures; + +use once_cell::sync::Lazy; + +pub static CAPS_FEATURES_MEMORY_DMABUF: Lazy = + Lazy::new(|| CapsFeatures::new(&[*crate::CAPS_FEATURE_MEMORY_DMABUF])); diff --git a/gstreamer-allocators/src/dma_buf_allocator.rs b/gstreamer-allocators/src/dma_buf_allocator.rs new file mode 100644 index 000000000..8a40614b9 --- /dev/null +++ b/gstreamer-allocators/src/dma_buf_allocator.rs @@ -0,0 +1,74 @@ +use std::{ + fmt, + os::unix::prelude::{IntoRawFd, RawFd}, +}; + +use glib::{translate::*, Cast}; + +use gst::{Memory, MemoryRef}; + +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +use crate::FdMemoryFlags; +use crate::{DmaBufAllocator, FdMemory, FdMemoryRef}; + +gst::memory_object_wrapper!( + DmaBufMemory, + DmaBufMemoryRef, + gst::ffi::GstMemory, + |mem: &gst::MemoryRef| { unsafe { from_glib(ffi::gst_is_dmabuf_memory(mem.as_mut_ptr())) } }, + FdMemory, + FdMemoryRef, + Memory, + MemoryRef +); + +impl fmt::Debug for DmaBufMemory { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + DmaBufMemoryRef::fmt(self, f) + } +} + +impl fmt::Debug for DmaBufMemoryRef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + MemoryRef::fmt(self, f) + } +} + +impl DmaBufMemoryRef { + #[doc(alias = "gst_dmabuf_memory_get_fd")] + pub fn fd(&self) -> RawFd { + assert_initialized_main_thread!(); + unsafe { ffi::gst_dmabuf_memory_get_fd(self.as_mut_ptr()) } + } +} + +impl DmaBufAllocator { + #[doc(alias = "gst_dmabuf_allocator_alloc")] + pub unsafe fn alloc(&self, fd: A, size: usize) -> gst::Memory { + assert_initialized_main_thread_unsafe!(); + from_glib_full(ffi::gst_dmabuf_allocator_alloc( + self.unsafe_cast_ref::().to_glib_none().0, + fd.into_raw_fd(), + size, + )) + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + #[doc(alias = "gst_dmabuf_allocator_alloc_with_flags")] + pub unsafe fn alloc_with_flags( + &self, + fd: RawFd, + size: usize, + flags: FdMemoryFlags, + ) -> gst::Memory { + assert_initialized_main_thread_unsafe!(); + from_glib_full(ffi::gst_dmabuf_allocator_alloc_with_flags( + self.unsafe_cast_ref::().to_glib_none().0, + fd, + size, + flags.into_glib(), + )) + } +} diff --git a/gstreamer-allocators/src/fd_allocator.rs b/gstreamer-allocators/src/fd_allocator.rs new file mode 100644 index 000000000..63f53cb6b --- /dev/null +++ b/gstreamer-allocators/src/fd_allocator.rs @@ -0,0 +1,59 @@ +use std::{fmt, os::unix::prelude::RawFd}; + +use glib::{translate::*, Cast}; + +use gst::{Memory, MemoryRef}; + +use crate::{FdAllocator, FdMemoryFlags}; + +gst::memory_object_wrapper!( + FdMemory, + FdMemoryRef, + gst::ffi::GstMemory, + |mem: &gst::MemoryRef| { unsafe { from_glib(ffi::gst_is_fd_memory(mem.as_mut_ptr())) } }, + Memory, + MemoryRef, +); + +impl fmt::Debug for FdMemory { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + FdMemoryRef::fmt(self, f) + } +} + +impl fmt::Debug for FdMemoryRef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FdMemory") + .field("ptr", unsafe { &self.as_ptr() }) + .field("allocator", &self.allocator()) + .field("parent", &self.parent()) + .field("maxsize", &self.maxsize()) + .field("align", &self.align()) + .field("offset", &self.offset()) + .field("size", &self.size()) + .field("flags", &self.flags()) + .field("fd", &self.fd()) + .finish() + } +} + +impl FdMemoryRef { + #[doc(alias = "gst_fd_memory_get_fd")] + pub fn fd(&self) -> RawFd { + assert_initialized_main_thread!(); + unsafe { ffi::gst_fd_memory_get_fd(self.as_mut_ptr()) } + } +} + +impl FdAllocator { + #[doc(alias = "gst_fd_allocator_alloc")] + pub unsafe fn alloc(&self, fd: RawFd, size: usize, flags: FdMemoryFlags) -> gst::Memory { + assert_initialized_main_thread_unsafe!(); + from_glib_full(ffi::gst_fd_allocator_alloc( + self.unsafe_cast_ref::().to_glib_none().0, + fd, + size, + flags.into_glib(), + )) + } +} diff --git a/gstreamer-allocators/src/lib.rs b/gstreamer-allocators/src/lib.rs new file mode 100644 index 000000000..a92ad6747 --- /dev/null +++ b/gstreamer-allocators/src/lib.rs @@ -0,0 +1,74 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +#![cfg_attr(feature = "dox", feature(doc_cfg))] +#![allow(clippy::missing_safety_doc)] +#![allow(clippy::non_send_fields_in_send_ty)] +#![doc = include_str!("../README.md")] + +pub use ffi; +pub use glib; +pub use gst; + +macro_rules! assert_initialized_main_thread { + () => { + if unsafe { gst::ffi::gst_is_initialized() } != glib::ffi::GTRUE { + panic!("GStreamer has not been initialized. Call `gst::init` first."); + } + }; +} + +macro_rules! assert_initialized_main_thread_unsafe { + () => { + if gst::ffi::gst_is_initialized() != glib::ffi::GTRUE { + panic!("GStreamer has not been initialized. Call `gst::init` first."); + } + }; +} + +macro_rules! skip_assert_initialized { + () => {}; +} + +#[allow(clippy::unreadable_literal)] +#[allow(clippy::too_many_arguments)] +#[allow(clippy::match_same_arms)] +#[allow(clippy::type_complexity)] +#[allow(clippy::use_self)] +#[allow(unused_imports)] +mod auto; +pub use crate::auto::*; + +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +mod caps_features; +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +pub use crate::caps_features::CAPS_FEATURES_MEMORY_DMABUF; + +mod fd_allocator; +pub use fd_allocator::*; + +#[cfg(any(target_os = "linux", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(target_os = "linux")))] +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +mod dma_buf_allocator; +#[cfg(any(target_os = "linux", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(target_os = "linux")))] +#[cfg(any(feature = "v1_12", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] +pub use dma_buf_allocator::*; + +#[cfg(any(feature = "v1_14", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] +mod phys_memory; +#[cfg(any(feature = "v1_14", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] +pub use phys_memory::*; + +// Re-export all the traits in a prelude module, so that applications +// can always "use gst_base::prelude::*" without getting conflicts +pub mod prelude { + #[doc(hidden)] + pub use gst::prelude::*; +} diff --git a/gstreamer-allocators/src/phys_memory.rs b/gstreamer-allocators/src/phys_memory.rs new file mode 100644 index 000000000..5591b1db5 --- /dev/null +++ b/gstreamer-allocators/src/phys_memory.rs @@ -0,0 +1,44 @@ +use std::fmt; + +use glib::translate::*; + +use gst::{Memory, MemoryRef}; + +gst::memory_object_wrapper!( + PhysMemory, + PhysMemoryRef, + gst::ffi::GstMemory, + |mem: &gst::MemoryRef| { unsafe { from_glib(ffi::gst_is_phys_memory(mem.as_mut_ptr())) } }, + Memory, + MemoryRef, +); + +impl fmt::Debug for PhysMemory { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + PhysMemoryRef::fmt(self, f) + } +} + +impl fmt::Debug for PhysMemoryRef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FdMemory") + .field("ptr", unsafe { &self.as_ptr() }) + .field("allocator", &self.allocator()) + .field("parent", &self.parent()) + .field("maxsize", &self.maxsize()) + .field("align", &self.align()) + .field("offset", &self.offset()) + .field("size", &self.size()) + .field("flags", &self.flags()) + .field("phys_addr", &format!("{:x}", self.phys_addr())) + .finish() + } +} + +impl PhysMemoryRef { + #[doc(alias = "gst_phys_memory_get_phys_addr")] + pub fn phys_addr(&self) -> libc::uintptr_t { + assert_initialized_main_thread!(); + unsafe { ffi::gst_phys_memory_get_phys_addr(self.as_mut_ptr()) } + } +} diff --git a/gstreamer-allocators/sys/CHANGELOG.md b/gstreamer-allocators/sys/CHANGELOG.md new file mode 120000 index 000000000..d6a7bdb06 --- /dev/null +++ b/gstreamer-allocators/sys/CHANGELOG.md @@ -0,0 +1 @@ +../../gstreamer/CHANGELOG.md \ No newline at end of file diff --git a/gstreamer-allocators/sys/COPYRIGHT b/gstreamer-allocators/sys/COPYRIGHT new file mode 120000 index 000000000..8b0161cc9 --- /dev/null +++ b/gstreamer-allocators/sys/COPYRIGHT @@ -0,0 +1 @@ +../../COPYRIGHT \ No newline at end of file diff --git a/gstreamer-allocators/sys/Cargo.toml b/gstreamer-allocators/sys/Cargo.toml new file mode 100644 index 000000000..9c2694770 --- /dev/null +++ b/gstreamer-allocators/sys/Cargo.toml @@ -0,0 +1,71 @@ +[build-dependencies] +system-deps = "6" + +[dependencies] +libc = "0.2" + +[dependencies.glib] +git = "https://github.com/gtk-rs/gtk-rs-core" +package = "glib-sys" + +[dependencies.gobject] +git = "https://github.com/gtk-rs/gtk-rs-core" +package = "gobject-sys" + +[dependencies.gst] +package = "gstreamer-sys" +path = "../../gstreamer/sys" + +[dev-dependencies] +shell-words = "1.0.0" +tempfile = "3" + +[features] +dox = [] +v1_10 = [] +v1_12 = ["v1_10"] +v1_14 = ["v1_12"] +v1_16 = ["v1_14"] +v1_18 = ["v1_16"] +v1_20 = ["v1_18"] + +[lib] +name = "gstreamer_allocators_sys" + +[package] +authors = ["Sebastian Dröge "] +build = "build.rs" +description = "FFI bindings to libgstallocators-1.0" +documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_allocators_sys/" +edition = "2021" +homepage = "https://gstreamer.freedesktop.org" +keywords = ["ffi", "gstreamer", "gnome", "multimedia"] +license = "MIT" +name = "gstreamer-allocators-sys" +readme = "README.md" +repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" +rust-version = "1.56" +version = "0.19.0" +[package.metadata.docs.rs] +features = ["dox"] +[package.metadata.system-deps.gstreamer_allocators_1_0] +name = "gstreamer-allocators-1.0" +version = "1.8" + +[package.metadata.system-deps.gstreamer_allocators_1_0.v1_10] +version = "1.10" + +[package.metadata.system-deps.gstreamer_allocators_1_0.v1_12] +version = "1.12" + +[package.metadata.system-deps.gstreamer_allocators_1_0.v1_14] +version = "1.14" + +[package.metadata.system-deps.gstreamer_allocators_1_0.v1_16] +version = "1.16" + +[package.metadata.system-deps.gstreamer_allocators_1_0.v1_18] +version = "1.18" + +[package.metadata.system-deps.gstreamer_allocators_1_0.v1_20] +version = "1.20" \ No newline at end of file diff --git a/gstreamer-allocators/sys/Gir.toml b/gstreamer-allocators/sys/Gir.toml new file mode 100644 index 000000000..776b96700 --- /dev/null +++ b/gstreamer-allocators/sys/Gir.toml @@ -0,0 +1,23 @@ +[options] +girs_directories = ["../../gir-files", "../../gst-gir-files"] +library = "GstAllocators" +version = "1.0" +min_cfg_version = "1.8" +work_mode = "sys" + +extra_versions = [ + "1.20", + "1.18", + "1.16", + "1.14", + "1.12", + "1.10", +] + +external_libraries = [ + "GLib", + "GObject", +] + +[external_libraries] +gstreamer="Gst" diff --git a/gstreamer-allocators/sys/LICENSE b/gstreamer-allocators/sys/LICENSE new file mode 120000 index 000000000..b2cfbdc7b --- /dev/null +++ b/gstreamer-allocators/sys/LICENSE @@ -0,0 +1 @@ +../../LICENSE-MIT \ No newline at end of file diff --git a/gstreamer-allocators/sys/README.md b/gstreamer-allocators/sys/README.md new file mode 100644 index 000000000..cedca180b --- /dev/null +++ b/gstreamer-allocators/sys/README.md @@ -0,0 +1,31 @@ +# gstreamer-sys [![crates.io](https://img.shields.io/crates/v/gstreamer-allocators-sys.svg)](https://crates.io/crates/gstreamer-allocators-sys) [![pipeline status](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/badges/main/pipeline.svg)](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/commits/main) + +[GStreamer](https://gstreamer.freedesktop.org/) (Allocators library) FFI bindings for Rust. + +These bindings are providing unsafe FFI API that can be used to interface with +GStreamer. Generally they are meant to be used as the building block for +higher-level abstractions like: + + * Bindings for GStreamer applications and plugins: https://gitlab.freedesktop.org/gstreamer/gstreamer-rs + * Various GStreamer plugins written in Rust: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs + +The bindings are autogenerated with [gir](https://github.com/gtk-rs/gir/) +based on the [GObject-Introspection](https://wiki.gnome.org/Projects/GObjectIntrospection/) +API metadata provided by the GStreamer project. + +## LICENSE + +gstreamer-sys and all crates contained here are licensed under the MIT +license ([LICENSE](LICENSE) or http://opensource.org/licenses/MIT). + +GStreamer itself is licensed under the Lesser General Public License version +2.1 or (at your option) any later version: +https://www.gnu.org/licenses/lgpl-2.1.html + +## Contribution + +Any kinds of contributions are welcome as a pull request. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in gstreamer-rs by you shall be licensed under the MIT license as above, +without any additional terms or conditions. diff --git a/gstreamer-allocators/sys/build.rs b/gstreamer-allocators/sys/build.rs new file mode 100644 index 000000000..76428e220 --- /dev/null +++ b/gstreamer-allocators/sys/build.rs @@ -0,0 +1,18 @@ +// Generated by gir (https://github.com/gtk-rs/gir @ e0d8d8d645b1) +// from gir-files (https://github.com/gtk-rs/gir-files @ 3ff4d3275258) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 233e3205cb17) +// DO NOT EDIT + +#[cfg(not(feature = "dox"))] +use std::process; + +#[cfg(feature = "dox")] +fn main() {} // prevent linking libraries to avoid documentation failure + +#[cfg(not(feature = "dox"))] +fn main() { + if let Err(s) = system_deps::Config::new().probe() { + println!("cargo:warning={}", s); + process::exit(1); + } +} diff --git a/gstreamer-allocators/sys/src/lib.rs b/gstreamer-allocators/sys/src/lib.rs new file mode 100644 index 000000000..c0b3dccce --- /dev/null +++ b/gstreamer-allocators/sys/src/lib.rs @@ -0,0 +1,183 @@ +// Generated by gir (https://github.com/gtk-rs/gir @ e0d8d8d645b1) +// from gir-files (https://github.com/gtk-rs/gir-files @ 3ff4d3275258) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 233e3205cb17) +// DO NOT EDIT + +#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] +#![allow( + clippy::approx_constant, + clippy::type_complexity, + clippy::unreadable_literal, + clippy::upper_case_acronyms +)] +#![cfg_attr(feature = "dox", feature(doc_cfg))] + +#[allow(unused_imports)] +use libc::{ + c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void, + intptr_t, size_t, ssize_t, uintptr_t, FILE, +}; + +#[allow(unused_imports)] +use glib::{gboolean, gconstpointer, gpointer, GType}; + +// Constants +pub const GST_ALLOCATOR_DMABUF: *const c_char = b"dmabuf\0" as *const u8 as *const c_char; +pub const GST_ALLOCATOR_FD: *const c_char = b"fd\0" as *const u8 as *const c_char; +pub const GST_CAPS_FEATURE_MEMORY_DMABUF: *const c_char = + b"memory:DMABuf\0" as *const u8 as *const c_char; + +// Flags +pub type GstFdMemoryFlags = c_uint; +pub const GST_FD_MEMORY_FLAG_NONE: GstFdMemoryFlags = 0; +pub const GST_FD_MEMORY_FLAG_KEEP_MAPPED: GstFdMemoryFlags = 1; +pub const GST_FD_MEMORY_FLAG_MAP_PRIVATE: GstFdMemoryFlags = 2; +pub const GST_FD_MEMORY_FLAG_DONT_CLOSE: GstFdMemoryFlags = 4; + +// Records +#[derive(Copy, Clone)] +#[repr(C)] +pub struct GstDmaBufAllocatorClass { + pub parent_class: GstFdAllocatorClass, + pub _gst_reserved: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstDmaBufAllocatorClass { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstDmaBufAllocatorClass @ {:p}", self)) + .field("parent_class", &self.parent_class) + .finish() + } +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct GstFdAllocatorClass { + pub parent_class: gst::GstAllocatorClass, +} + +impl ::std::fmt::Debug for GstFdAllocatorClass { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstFdAllocatorClass @ {:p}", self)) + .field("parent_class", &self.parent_class) + .finish() + } +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct GstPhysMemoryAllocatorInterface { + pub parent_iface: gobject::GTypeInterface, + pub get_phys_addr: + Option uintptr_t>, +} + +impl ::std::fmt::Debug for GstPhysMemoryAllocatorInterface { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstPhysMemoryAllocatorInterface @ {:p}", self)) + .field("get_phys_addr", &self.get_phys_addr) + .finish() + } +} + +// Classes +#[derive(Copy, Clone)] +#[repr(C)] +pub struct GstDmaBufAllocator { + pub parent: GstFdAllocator, + pub _gst_reserved: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstDmaBufAllocator { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstDmaBufAllocator @ {:p}", self)) + .field("parent", &self.parent) + .finish() + } +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct GstFdAllocator { + pub parent: gst::GstAllocator, +} + +impl ::std::fmt::Debug for GstFdAllocator { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstFdAllocator @ {:p}", self)) + .field("parent", &self.parent) + .finish() + } +} + +// Interfaces +#[repr(C)] +pub struct GstPhysMemoryAllocator { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +impl ::std::fmt::Debug for GstPhysMemoryAllocator { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "GstPhysMemoryAllocator @ {:p}", self) + } +} + +#[link(name = "gstallocators-1.0")] +extern "C" { + + //========================================================================= + // GstDmaBufAllocator + //========================================================================= + #[cfg(any(feature = "v1_12", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))] + pub fn gst_dmabuf_allocator_get_type() -> GType; + pub fn gst_dmabuf_allocator_new() -> *mut gst::GstAllocator; + pub fn gst_dmabuf_allocator_alloc( + allocator: *mut gst::GstAllocator, + fd: c_int, + size: size_t, + ) -> *mut gst::GstMemory; + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + pub fn gst_dmabuf_allocator_alloc_with_flags( + allocator: *mut gst::GstAllocator, + fd: c_int, + size: size_t, + flags: GstFdMemoryFlags, + ) -> *mut gst::GstMemory; + + //========================================================================= + // GstFdAllocator + //========================================================================= + pub fn gst_fd_allocator_get_type() -> GType; + pub fn gst_fd_allocator_new() -> *mut gst::GstAllocator; + pub fn gst_fd_allocator_alloc( + allocator: *mut gst::GstAllocator, + fd: c_int, + size: size_t, + flags: GstFdMemoryFlags, + ) -> *mut gst::GstMemory; + + //========================================================================= + // GstPhysMemoryAllocator + //========================================================================= + #[cfg(any(feature = "v1_14", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] + pub fn gst_phys_memory_allocator_get_type() -> GType; + + //========================================================================= + // Other functions + //========================================================================= + pub fn gst_dmabuf_memory_get_fd(mem: *mut gst::GstMemory) -> c_int; + pub fn gst_fd_memory_get_fd(mem: *mut gst::GstMemory) -> c_int; + pub fn gst_is_dmabuf_memory(mem: *mut gst::GstMemory) -> gboolean; + pub fn gst_is_fd_memory(mem: *mut gst::GstMemory) -> gboolean; + #[cfg(any(feature = "v1_14", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] + pub fn gst_is_phys_memory(mem: *mut gst::GstMemory) -> gboolean; + #[cfg(any(feature = "v1_14", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] + pub fn gst_phys_memory_get_phys_addr(mem: *mut gst::GstMemory) -> uintptr_t; + +} diff --git a/gstreamer-allocators/sys/tests/abi.rs b/gstreamer-allocators/sys/tests/abi.rs new file mode 100644 index 000000000..3425ed198 --- /dev/null +++ b/gstreamer-allocators/sys/tests/abi.rs @@ -0,0 +1,268 @@ +// Generated by gir (https://github.com/gtk-rs/gir @ e0d8d8d645b1) +// from gir-files (https://github.com/gtk-rs/gir-files @ 3ff4d3275258) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 233e3205cb17) +// DO NOT EDIT + +use gstreamer_allocators_sys::*; +use std::env; +use std::error::Error; +use std::ffi::OsString; +use std::mem::{align_of, size_of}; +use std::path::Path; +use std::process::Command; +use std::str; +use tempfile::Builder; + +static PACKAGES: &[&str] = &["gstreamer-allocators-1.0"]; + +#[derive(Clone, Debug)] +struct Compiler { + pub args: Vec, +} + +impl Compiler { + pub fn new() -> Result> { + let mut args = get_var("CC", "cc")?; + args.push("-Wno-deprecated-declarations".to_owned()); + // For _Generic + args.push("-std=c11".to_owned()); + // For %z support in printf when using MinGW. + args.push("-D__USE_MINGW_ANSI_STDIO".to_owned()); + args.extend(get_var("CFLAGS", "")?); + args.extend(get_var("CPPFLAGS", "")?); + args.extend(pkg_config_cflags(PACKAGES)?); + Ok(Self { args }) + } + + pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box> { + let mut cmd = self.to_command(); + cmd.arg(src); + cmd.arg("-o"); + cmd.arg(out); + let status = cmd.spawn()?.wait()?; + if !status.success() { + return Err(format!("compilation command {:?} failed, {}", &cmd, status).into()); + } + Ok(()) + } + + fn to_command(&self) -> Command { + let mut cmd = Command::new(&self.args[0]); + cmd.args(&self.args[1..]); + cmd + } +} + +fn get_var(name: &str, default: &str) -> Result, Box> { + match env::var(name) { + Ok(value) => Ok(shell_words::split(&value)?), + Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?), + Err(err) => Err(format!("{} {}", name, err).into()), + } +} + +fn pkg_config_cflags(packages: &[&str]) -> Result, Box> { + if packages.is_empty() { + return Ok(Vec::new()); + } + let pkg_config = env::var_os("PKG_CONFIG").unwrap_or_else(|| OsString::from("pkg-config")); + let mut cmd = Command::new(pkg_config); + cmd.arg("--cflags"); + cmd.args(packages); + let out = cmd.output()?; + if !out.status.success() { + return Err(format!("command {:?} returned {}", &cmd, out.status).into()); + } + let stdout = str::from_utf8(&out.stdout)?; + Ok(shell_words::split(stdout.trim())?) +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct Layout { + size: usize, + alignment: usize, +} + +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +struct Results { + /// Number of successfully completed tests. + passed: usize, + /// Total number of failed tests (including those that failed to compile). + failed: usize, +} + +impl Results { + fn record_passed(&mut self) { + self.passed += 1; + } + fn record_failed(&mut self) { + self.failed += 1; + } + fn summary(&self) -> String { + format!("{} passed; {} failed", self.passed, self.failed) + } + fn expect_total_success(&self) { + if self.failed == 0 { + println!("OK: {}", self.summary()); + } else { + panic!("FAILED: {}", self.summary()); + }; + } +} + +#[test] +#[cfg(target_os = "linux")] +fn cross_validate_constants_with_c() { + let mut c_constants: Vec<(String, String)> = Vec::new(); + + for l in get_c_output("constant").unwrap().lines() { + let mut words = l.trim().split(';'); + let name = words.next().expect("Failed to parse name").to_owned(); + let value = words + .next() + .and_then(|s| s.parse().ok()) + .expect("Failed to parse value"); + c_constants.push((name, value)); + } + + let mut results = Results::default(); + + for ((rust_name, rust_value), (c_name, c_value)) in + RUST_CONSTANTS.iter().zip(c_constants.iter()) + { + if rust_name != c_name { + results.record_failed(); + eprintln!("Name mismatch:\nRust: {:?}\nC: {:?}", rust_name, c_name,); + continue; + } + + if rust_value != c_value { + results.record_failed(); + eprintln!( + "Constant value mismatch for {}\nRust: {:?}\nC: {:?}", + rust_name, rust_value, &c_value + ); + continue; + } + + results.record_passed(); + } + + results.expect_total_success(); +} + +#[test] +#[cfg(target_os = "linux")] +fn cross_validate_layout_with_c() { + let mut c_layouts = Vec::new(); + + for l in get_c_output("layout").unwrap().lines() { + let mut words = l.trim().split(';'); + let name = words.next().expect("Failed to parse name").to_owned(); + let size = words + .next() + .and_then(|s| s.parse().ok()) + .expect("Failed to parse size"); + let alignment = words + .next() + .and_then(|s| s.parse().ok()) + .expect("Failed to parse alignment"); + c_layouts.push((name, Layout { size, alignment })); + } + + let mut results = Results::default(); + + for ((rust_name, rust_layout), (c_name, c_layout)) in RUST_LAYOUTS.iter().zip(c_layouts.iter()) + { + if rust_name != c_name { + results.record_failed(); + eprintln!("Name mismatch:\nRust: {:?}\nC: {:?}", rust_name, c_name,); + continue; + } + + if rust_layout != c_layout { + results.record_failed(); + eprintln!( + "Layout mismatch for {}\nRust: {:?}\nC: {:?}", + rust_name, rust_layout, &c_layout + ); + continue; + } + + results.record_passed(); + } + + results.expect_total_success(); +} + +fn get_c_output(name: &str) -> Result> { + let tmpdir = Builder::new().prefix("abi").tempdir()?; + let exe = tmpdir.path().join(name); + let c_file = Path::new("tests").join(name).with_extension("c"); + + let cc = Compiler::new().expect("configured compiler"); + cc.compile(&c_file, &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into()); + } + + Ok(String::from_utf8(output.stdout)?) +} + +const RUST_LAYOUTS: &[(&str, Layout)] = &[ + ( + "GstDmaBufAllocator", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstDmaBufAllocatorClass", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstFdAllocator", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstFdAllocatorClass", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstFdMemoryFlags", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstPhysMemoryAllocatorInterface", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), +]; + +const RUST_CONSTANTS: &[(&str, &str)] = &[ + ("GST_ALLOCATOR_DMABUF", "dmabuf"), + ("GST_ALLOCATOR_FD", "fd"), + ("GST_CAPS_FEATURE_MEMORY_DMABUF", "memory:DMABuf"), + ("(guint) GST_FD_MEMORY_FLAG_DONT_CLOSE", "4"), + ("(guint) GST_FD_MEMORY_FLAG_KEEP_MAPPED", "1"), + ("(guint) GST_FD_MEMORY_FLAG_MAP_PRIVATE", "2"), + ("(guint) GST_FD_MEMORY_FLAG_NONE", "0"), +]; diff --git a/gstreamer-allocators/sys/tests/constant.c b/gstreamer-allocators/sys/tests/constant.c new file mode 100644 index 000000000..c890bb7b6 --- /dev/null +++ b/gstreamer-allocators/sys/tests/constant.c @@ -0,0 +1,40 @@ +// Generated by gir (https://github.com/gtk-rs/gir @ e0d8d8d645b1) +// from gir-files (https://github.com/gtk-rs/gir-files @ 3ff4d3275258) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 233e3205cb17) +// DO NOT EDIT + +#include "manual.h" +#include + +#define PRINT_CONSTANT(CONSTANT_NAME) \ + printf("%s;", #CONSTANT_NAME); \ + printf(_Generic((CONSTANT_NAME), \ + char *: "%s", \ + const char *: "%s", \ + char: "%c", \ + signed char: "%hhd", \ + unsigned char: "%hhu", \ + short int: "%hd", \ + unsigned short int: "%hu", \ + int: "%d", \ + unsigned int: "%u", \ + long: "%ld", \ + unsigned long: "%lu", \ + long long: "%lld", \ + unsigned long long: "%llu", \ + float: "%f", \ + double: "%f", \ + long double: "%ld"), \ + CONSTANT_NAME); \ + printf("\n"); + +int main() { + PRINT_CONSTANT(GST_ALLOCATOR_DMABUF); + PRINT_CONSTANT(GST_ALLOCATOR_FD); + PRINT_CONSTANT(GST_CAPS_FEATURE_MEMORY_DMABUF); + PRINT_CONSTANT((guint) GST_FD_MEMORY_FLAG_DONT_CLOSE); + PRINT_CONSTANT((guint) GST_FD_MEMORY_FLAG_KEEP_MAPPED); + PRINT_CONSTANT((guint) GST_FD_MEMORY_FLAG_MAP_PRIVATE); + PRINT_CONSTANT((guint) GST_FD_MEMORY_FLAG_NONE); + return 0; +} diff --git a/gstreamer-allocators/sys/tests/layout.c b/gstreamer-allocators/sys/tests/layout.c new file mode 100644 index 000000000..bc5071fb4 --- /dev/null +++ b/gstreamer-allocators/sys/tests/layout.c @@ -0,0 +1,18 @@ +// Generated by gir (https://github.com/gtk-rs/gir @ e0d8d8d645b1) +// from gir-files (https://github.com/gtk-rs/gir-files @ 3ff4d3275258) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 233e3205cb17) +// DO NOT EDIT + +#include "manual.h" +#include +#include + +int main() { + printf("%s;%zu;%zu\n", "GstDmaBufAllocator", sizeof(GstDmaBufAllocator), alignof(GstDmaBufAllocator)); + printf("%s;%zu;%zu\n", "GstDmaBufAllocatorClass", sizeof(GstDmaBufAllocatorClass), alignof(GstDmaBufAllocatorClass)); + printf("%s;%zu;%zu\n", "GstFdAllocator", sizeof(GstFdAllocator), alignof(GstFdAllocator)); + printf("%s;%zu;%zu\n", "GstFdAllocatorClass", sizeof(GstFdAllocatorClass), alignof(GstFdAllocatorClass)); + printf("%s;%zu;%zu\n", "GstFdMemoryFlags", sizeof(GstFdMemoryFlags), alignof(GstFdMemoryFlags)); + printf("%s;%zu;%zu\n", "GstPhysMemoryAllocatorInterface", sizeof(GstPhysMemoryAllocatorInterface), alignof(GstPhysMemoryAllocatorInterface)); + return 0; +} diff --git a/gstreamer-allocators/sys/tests/manual.h b/gstreamer-allocators/sys/tests/manual.h new file mode 100644 index 000000000..144bbeeed --- /dev/null +++ b/gstreamer-allocators/sys/tests/manual.h @@ -0,0 +1,3 @@ +// Feel free to edit this file, it won't be regenerated by gir generator unless removed. + +#include diff --git a/gstreamer-allocators/tests/check_gir.rs b/gstreamer-allocators/tests/check_gir.rs new file mode 100644 index 000000000..b095c0444 --- /dev/null +++ b/gstreamer-allocators/tests/check_gir.rs @@ -0,0 +1,8 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +#[test] +fn check_gir_file() { + let res = gir_format_check::check_gir_file("Gir.toml"); + println!("{}", res); + assert_eq!(res.nb_errors, 0); +}