Add high-level bindings for gstreamer-mse

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1634>
This commit is contained in:
Simon Wülker 2025-01-14 18:49:48 +01:00 committed by Sebastian Dröge
parent a6e9c8116c
commit 5f4c34d9a5
24 changed files with 2167 additions and 15 deletions

33
Cargo.lock generated
View file

@ -875,18 +875,6 @@ dependencies = [
"system-deps",
]
[[package]]
name = "gst-mse-sys"
version = "0.0.1"
dependencies = [
"glib-sys",
"gstreamer-sys",
"libc",
"shell-words",
"system-deps",
"tempfile",
]
[[package]]
name = "gstreamer"
version = "0.24.0"
@ -1254,6 +1242,27 @@ dependencies = [
"tempfile",
]
[[package]]
name = "gstreamer-mse"
version = "0.24.0"
dependencies = [
"glib",
"gstreamer",
"gstreamer-mse-sys",
]
[[package]]
name = "gstreamer-mse-sys"
version = "0.24.0"
dependencies = [
"glib-sys",
"gstreamer-sys",
"libc",
"shell-words",
"system-deps",
"tempfile",
]
[[package]]
name = "gstreamer-net"
version = "0.24.0"

View file

@ -32,6 +32,7 @@ default-members = [
"gstreamer-controller",
"gstreamer-editing-services",
"gstreamer-mpegts",
"gstreamer-mse",
"gstreamer-net",
"gstreamer-pbutils",
"gstreamer-play",
@ -88,6 +89,7 @@ members = [
"gstreamer-gl/wayland",
"gstreamer-gl/x11",
"gstreamer-mpegts",
"gstreamer-mse",
"gstreamer-net",
"gstreamer-pbutils",
"gstreamer-play",
@ -163,6 +165,7 @@ gst-gl = { package = "gstreamer-gl", path = "./gstreamer-gl" }
gst-gl-egl = { package = "gstreamer-gl-egl", path = "./gstreamer-gl/egl" }
gst-gl-x11 = { package = "gstreamer-gl-x11", path = "./gstreamer-gl/x11" }
gst-net = { package = "gstreamer-net", path = "./gstreamer-net" }
gst-mse = { package = "gstreamer-mse", path = "./gstreamer-mse" }
gst-pbutils = { package = "gstreamer-pbutils", path = "./gstreamer-pbutils" }
gst-play = { package = "gstreamer-play", path = "./gstreamer-play" }
gst-player = { package = "gstreamer-player", path = "./gstreamer-player" }

1
gstreamer-mse/COPYRIGHT Symbolic link
View file

@ -0,0 +1 @@
../COPYRIGHT

25
gstreamer-mse/Cargo.toml Normal file
View file

@ -0,0 +1,25 @@
[package]
name = "gstreamer-mse"
authors = ["Sebastian Dröge <sebastian@centricular.com>", "Simon Wülker <simon.wuelker@arcor.de>"]
description = "Rust bindings for GStreamer MSE library"
license = "MIT OR Apache-2.0"
readme = "README.md"
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_mse/"
keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"]
version.workspace = true
categories.workspace = true
repository.workspace = true
homepage.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
gstreamer-mse-sys.workspace = true
gst = { workspace = true, features = ["v1_26"] }
glib.workspace = true
[package.metadata.docs.rs]
all-features = true
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]

59
gstreamer-mse/Gir.toml Normal file
View file

@ -0,0 +1,59 @@
[options]
girs_directories = ["../gir-files", "../gst-gir-files"]
library = "GstMse"
version = "1.0"
min_cfg_version = "1.26"
work_mode = "normal"
target_path = "."
concurrency = "send+sync"
generate_safety_asserts = true
single_version_file = true
generate_display_trait = false
deprecate_by_min_version = true
trust_return_value_nullability = true
generate = [
"GstMse.MediaSourceEOSError",
"GstMse.MediaSourceError",
"GstMse.MediaSourceReadyState",
"GstMse.MseSrc",
"GstMse.MseSrcPad",
"GstMse.MseSrcReadyState",
"GstMse.SourceBuffer",
"GstMse.SourceBufferAppendMode",
"GstMse.SourceBufferList",
]
manual = [
"GstMse.MediaSourceRange",
"GstMse.SourceBufferInterval",
"Gst.Element",
"Gst.Pad",
]
[[object]]
name = "Gst.Buffer"
status = "manual"
ref_mode = "ref"
[[object]]
name = "Gst.ClockTime"
status = "manual"
conversion_type = "Option"
[[object]]
name = "GLib.Error"
status = "manual"
[[object]]
name = "Gst.Object"
status = "manual"
ref_mode = "ref"
[[object]]
name = "GstMse.MediaSource"
status = "generate"
[[object.property]]
name = "position"
# pass GstClockTime instead of u64 for setter
generate = ["notify"]

View file

@ -0,0 +1 @@
../LICENSE-APACHE

1
gstreamer-mse/LICENSE-MIT Symbolic link
View file

@ -0,0 +1 @@
../LICENSE-MIT

220
gstreamer-mse/README.md Normal file
View file

@ -0,0 +1,220 @@
# gstreamer-rs [![crates.io](https://img.shields.io/crates/v/gstreamer-mse.svg)](https://crates.io/crates/gstreamer-mse) [![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/) (MSE library) bindings for Rust.
Documentation can be found [here](https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_mse/).
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
- [gstreamer-rs ](#gstreamer-rs--)
- [Table of Contents](#table-of-contents)
- [Installation](#installation)
- [Linux/BSDs](#linuxbsds)
- [macOS](#macos)
- [GStreamer Binaries](#gstreamer-binaries)
- [Homebrew](#homebrew)
- [Windows](#windows)
- [GStreamer Binaries](#gstreamer-binaries-1)
- [MSYS2 / pacman](#msys2--pacman)
- [Getting Started](#getting-started)
- [LICENSE](#license)
- [Contribution](#contribution)
<a name="installation"/>
## Installation
To build the GStreamer bindings or anything depending on them, you need to
have at least GStreamer 1.14 and gst-plugins-base 1.14 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.
<a name="installation-linux"/>
### 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.14. 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. See the `Cargo.toml`
files for the full details,
```console
$ 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.
<a name="installation-macos"/>
### 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.
We recommend using the official GStreamer binaries over Homebrew, especially
as GStreamer in Homebrew is [currently broken](https://github.com/orgs/Homebrew/discussions/3740#discussioncomment-3804964).
#### GStreamer Binaries
You need to download the *two* `.pkg` files from the GStreamer website and
install them, e.g. `gstreamer-1.0-1.20.4-universal.pkg` and
`gstreamer-1.0-devel-1.20.4-universal.pkg`.
After installation, you also need to set the `PATH` environment variable as
follows
```console
$ export PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/bin${PATH:+:$PATH}"
```
Also note that the `pkg-config` from GStreamer should be the first one in
the `PATH` as other versions have all kinds of quirks that will cause
problems.
#### 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
```
Make sure the version of these libraries is >= 1.14.
<a name="installation-windows"/>
### 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.
We recommend using the official GStreamer binaries over MSYS2.
#### 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.20.4.msi` and
`gstreamer-1.0-devel-x86_64-1.20.4.msi`. Make sure to select the version that
matches your Rust toolchain, i.e. MinGW or MSVC.
After installation set the ``PATH` environment variable as follows:
```console
# For a UNIX-style shell:
$ export PATH="c:/gstreamer/1.0/msvc_x86_64/bin${PATH:+:$PATH}"
# For cmd.exe:
$ set PATH=C:\gstreamer\1.0\msvc_x86_64\bin;%PATH%
```
Make sure to update the path to where you have actually installed GStreamer
and for the corresponding toolchain.
Also note that the `pkg-config.exe` from GStreamer should be the first one in
the `PATH` as other versions have all kinds of quirks that will cause
problems.
#### 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
```
Make sure the version of these libraries is >= 1.14.
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/).
<a name="getting-started"/>
## 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.
<a name="license"/>
## 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
<a name="contribution"/>
## 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.

View file

@ -0,0 +1,454 @@
// 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::{
ffi, MediaSourceEOSError, MediaSourceRange, MediaSourceReadyState, MseSrc, SourceBuffer,
SourceBufferList,
};
use glib::{
object::ObjectType as _,
prelude::*,
signal::{connect_raw, SignalHandlerId},
translate::*,
};
use std::boxed::Box as Box_;
glib::wrapper! {
#[doc(alias = "GstMediaSource")]
pub struct MediaSource(Object<ffi::GstMediaSource, ffi::GstMediaSourceClass>) @extends gst::Object;
match fn {
type_ => || ffi::gst_media_source_get_type(),
}
}
impl MediaSource {
#[doc(alias = "gst_media_source_new")]
pub fn new() -> MediaSource {
assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_media_source_new()) }
}
#[doc(alias = "gst_media_source_add_source_buffer")]
pub fn add_source_buffer(&self, type_: &str) -> Result<SourceBuffer, glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let ret = ffi::gst_media_source_add_source_buffer(
self.to_glib_none().0,
type_.to_glib_none().0,
&mut error,
);
if error.is_null() {
Ok(from_glib_full(ret))
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_media_source_attach")]
pub fn attach(&self, element: &MseSrc) {
unsafe {
ffi::gst_media_source_attach(self.to_glib_none().0, element.to_glib_none().0);
}
}
#[doc(alias = "gst_media_source_clear_live_seekable_range")]
pub fn clear_live_seekable_range(&self) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok =
ffi::gst_media_source_clear_live_seekable_range(self.to_glib_none().0, &mut error);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_media_source_detach")]
pub fn detach(&self) {
unsafe {
ffi::gst_media_source_detach(self.to_glib_none().0);
}
}
#[doc(alias = "gst_media_source_end_of_stream")]
pub fn end_of_stream(&self, eos_error: MediaSourceEOSError) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_media_source_end_of_stream(
self.to_glib_none().0,
eos_error.into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_media_source_get_active_source_buffers")]
#[doc(alias = "get_active_source_buffers")]
#[doc(alias = "active-source-buffers")]
pub fn active_source_buffers(&self) -> SourceBufferList {
unsafe {
from_glib_full(ffi::gst_media_source_get_active_source_buffers(
self.to_glib_none().0,
))
}
}
#[doc(alias = "gst_media_source_get_duration")]
#[doc(alias = "get_duration")]
pub fn duration(&self) -> Option<gst::ClockTime> {
unsafe { from_glib(ffi::gst_media_source_get_duration(self.to_glib_none().0)) }
}
#[doc(alias = "gst_media_source_get_live_seekable_range")]
#[doc(alias = "get_live_seekable_range")]
pub fn live_seekable_range(&self) -> MediaSourceRange {
unsafe {
let mut range = MediaSourceRange::uninitialized();
ffi::gst_media_source_get_live_seekable_range(
self.to_glib_none().0,
range.to_glib_none_mut().0,
);
range
}
}
#[doc(alias = "gst_media_source_get_position")]
#[doc(alias = "get_position")]
pub fn position(&self) -> Option<gst::ClockTime> {
unsafe { from_glib(ffi::gst_media_source_get_position(self.to_glib_none().0)) }
}
#[doc(alias = "gst_media_source_get_ready_state")]
#[doc(alias = "get_ready_state")]
#[doc(alias = "ready-state")]
pub fn ready_state(&self) -> MediaSourceReadyState {
unsafe { from_glib(ffi::gst_media_source_get_ready_state(self.to_glib_none().0)) }
}
#[doc(alias = "gst_media_source_get_source_buffers")]
#[doc(alias = "get_source_buffers")]
#[doc(alias = "source-buffers")]
pub fn source_buffers(&self) -> SourceBufferList {
unsafe {
from_glib_full(ffi::gst_media_source_get_source_buffers(
self.to_glib_none().0,
))
}
}
#[doc(alias = "gst_media_source_remove_source_buffer")]
pub fn remove_source_buffer(&self, buffer: &SourceBuffer) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_media_source_remove_source_buffer(
self.to_glib_none().0,
buffer.to_glib_none().0,
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_media_source_set_duration")]
#[doc(alias = "duration")]
pub fn set_duration(
&self,
duration: impl Into<Option<gst::ClockTime>>,
) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_media_source_set_duration(
self.to_glib_none().0,
duration.into().into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_media_source_set_live_seekable_range")]
pub fn set_live_seekable_range(
&self,
start: impl Into<Option<gst::ClockTime>>,
end: impl Into<Option<gst::ClockTime>>,
) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_media_source_set_live_seekable_range(
self.to_glib_none().0,
start.into().into_glib(),
end.into().into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_media_source_is_type_supported")]
pub fn is_type_supported(type_: &str) -> bool {
assert_initialized_main_thread!();
unsafe {
from_glib(ffi::gst_media_source_is_type_supported(
type_.to_glib_none().0,
))
}
}
#[doc(alias = "on-source-close")]
pub fn connect_on_source_close<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn on_source_close_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-source-close".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_source_close_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "on-source-ended")]
pub fn connect_on_source_ended<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn on_source_ended_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-source-ended".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_source_ended_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "on-source-open")]
pub fn connect_on_source_open<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn on_source_open_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-source-open".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_source_open_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "active-source-buffers")]
pub fn connect_active_source_buffers_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_active_source_buffers_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::active-source-buffers".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_active_source_buffers_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "duration")]
pub fn connect_duration_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_duration_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::duration".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_duration_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "position")]
pub fn connect_position_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_position_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::position".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_position_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "ready-state")]
pub fn connect_ready_state_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_ready_state_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::ready-state".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_ready_state_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "source-buffers")]
pub fn connect_source_buffers_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_source_buffers_trampoline<
F: Fn(&MediaSource) + Send + Sync + 'static,
>(
this: *mut ffi::GstMediaSource,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::source-buffers".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_source_buffers_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}
impl Default for MediaSource {
fn default() -> Self {
Self::new()
}
}
unsafe impl Send for MediaSource {}
unsafe impl Sync for MediaSource {}

View file

@ -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
mod media_source;
pub use self::media_source::MediaSource;
mod mse_src;
pub use self::mse_src::MseSrc;
mod mse_src_pad;
pub use self::mse_src_pad::MseSrcPad;
mod source_buffer;
pub use self::source_buffer::SourceBuffer;
mod source_buffer_list;
pub use self::source_buffer_list::SourceBufferList;
mod enums;
pub use self::enums::MediaSourceEOSError;
pub use self::enums::MediaSourceError;
pub use self::enums::MediaSourceReadyState;
pub use self::enums::MseSrcReadyState;
pub use self::enums::SourceBufferAppendMode;

View file

@ -0,0 +1,228 @@
// 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::{ffi, MseSrcReadyState};
use glib::{
prelude::*,
signal::{connect_raw, SignalHandlerId},
translate::*,
};
use std::boxed::Box as Box_;
glib::wrapper! {
#[doc(alias = "GstMseSrc")]
pub struct MseSrc(Object<ffi::GstMseSrc, ffi::GstMseSrcClass>) @extends gst::Element, gst::Object;
match fn {
type_ => || ffi::gst_mse_src_get_type(),
}
}
impl MseSrc {
#[doc(alias = "gst_mse_src_get_duration")]
#[doc(alias = "get_duration")]
pub fn duration(&self) -> Option<gst::ClockTime> {
unsafe { from_glib(ffi::gst_mse_src_get_duration(self.to_glib_none().0)) }
}
#[doc(alias = "gst_mse_src_get_n_audio")]
#[doc(alias = "get_n_audio")]
#[doc(alias = "n-audio")]
pub fn n_audio(&self) -> u32 {
unsafe { ffi::gst_mse_src_get_n_audio(self.to_glib_none().0) }
}
#[doc(alias = "gst_mse_src_get_n_text")]
#[doc(alias = "get_n_text")]
#[doc(alias = "n-text")]
pub fn n_text(&self) -> u32 {
unsafe { ffi::gst_mse_src_get_n_text(self.to_glib_none().0) }
}
#[doc(alias = "gst_mse_src_get_n_video")]
#[doc(alias = "get_n_video")]
#[doc(alias = "n-video")]
pub fn n_video(&self) -> u32 {
unsafe { ffi::gst_mse_src_get_n_video(self.to_glib_none().0) }
}
#[doc(alias = "gst_mse_src_get_position")]
#[doc(alias = "get_position")]
pub fn position(&self) -> Option<gst::ClockTime> {
unsafe { from_glib(ffi::gst_mse_src_get_position(self.to_glib_none().0)) }
}
#[doc(alias = "gst_mse_src_get_ready_state")]
#[doc(alias = "get_ready_state")]
#[doc(alias = "ready-state")]
pub fn ready_state(&self) -> MseSrcReadyState {
unsafe { from_glib(ffi::gst_mse_src_get_ready_state(self.to_glib_none().0)) }
}
pub fn set_duration(&self, duration: u64) {
ObjectExt::set_property(self, "duration", duration)
}
#[doc(alias = "duration")]
pub fn connect_duration_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_duration_trampoline<F: Fn(&MseSrc) + Send + Sync + 'static>(
this: *mut ffi::GstMseSrc,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::duration".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_duration_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "n-audio")]
pub fn connect_n_audio_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_n_audio_trampoline<F: Fn(&MseSrc) + Send + Sync + 'static>(
this: *mut ffi::GstMseSrc,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::n-audio".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_n_audio_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "n-text")]
pub fn connect_n_text_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_n_text_trampoline<F: Fn(&MseSrc) + Send + Sync + 'static>(
this: *mut ffi::GstMseSrc,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::n-text".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_n_text_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "n-video")]
pub fn connect_n_video_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_n_video_trampoline<F: Fn(&MseSrc) + Send + Sync + 'static>(
this: *mut ffi::GstMseSrc,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::n-video".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_n_video_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "position")]
pub fn connect_position_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_position_trampoline<F: Fn(&MseSrc) + Send + Sync + 'static>(
this: *mut ffi::GstMseSrc,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::position".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_position_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "ready-state")]
pub fn connect_ready_state_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_ready_state_trampoline<
F: Fn(&MseSrc) + Send + Sync + 'static,
>(
this: *mut ffi::GstMseSrc,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::ready-state".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_ready_state_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}
unsafe impl Send for MseSrc {}
unsafe impl Sync for MseSrc {}

View file

@ -0,0 +1,20 @@
// 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::ffi;
glib::wrapper! {
#[doc(alias = "GstMseSrcPad")]
pub struct MseSrcPad(Object<ffi::GstMseSrcPad, ffi::GstMseSrcPadClass>) @extends gst::Pad, gst::Object;
match fn {
type_ => || ffi::gst_mse_src_pad_get_type(),
}
}
impl MseSrcPad {}
unsafe impl Send for MseSrcPad {}
unsafe impl Sync for MseSrcPad {}

View file

@ -0,0 +1,572 @@
// 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::{ffi, SourceBufferAppendMode};
use glib::{
object::ObjectType as _,
prelude::*,
signal::{connect_raw, SignalHandlerId},
translate::*,
};
use std::boxed::Box as Box_;
glib::wrapper! {
#[doc(alias = "GstSourceBuffer")]
pub struct SourceBuffer(Object<ffi::GstSourceBuffer, ffi::GstSourceBufferClass>) @extends gst::Object;
match fn {
type_ => || ffi::gst_source_buffer_get_type(),
}
}
impl SourceBuffer {
#[doc(alias = "gst_source_buffer_abort")]
pub fn abort(&self) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_abort(self.to_glib_none().0, &mut error);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_source_buffer_append_buffer")]
pub fn append_buffer(&self, buf: &gst::Buffer) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_append_buffer(
self.to_glib_none().0,
buf.to_glib_none().0,
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_source_buffer_change_content_type")]
pub fn change_content_type(&self, type_: &str) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_change_content_type(
self.to_glib_none().0,
type_.to_glib_none().0,
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_source_buffer_get_append_mode")]
#[doc(alias = "get_append_mode")]
#[doc(alias = "append-mode")]
pub fn append_mode(&self) -> SourceBufferAppendMode {
unsafe {
from_glib(ffi::gst_source_buffer_get_append_mode(
self.to_glib_none().0,
))
}
}
#[doc(alias = "gst_source_buffer_get_append_window_end")]
#[doc(alias = "get_append_window_end")]
#[doc(alias = "append-window-end")]
pub fn append_window_end(&self) -> Option<gst::ClockTime> {
unsafe {
from_glib(ffi::gst_source_buffer_get_append_window_end(
self.to_glib_none().0,
))
}
}
#[doc(alias = "gst_source_buffer_get_append_window_start")]
#[doc(alias = "get_append_window_start")]
#[doc(alias = "append-window-start")]
pub fn append_window_start(&self) -> Option<gst::ClockTime> {
unsafe {
from_glib(ffi::gst_source_buffer_get_append_window_start(
self.to_glib_none().0,
))
}
}
//#[doc(alias = "gst_source_buffer_get_buffered")]
//#[doc(alias = "get_buffered")]
//pub fn buffered(&self) -> Result</*Unknown conversion*//*Unimplemented*/Array TypeId { ns_id: 1, id: 5 }, glib::Error> {
// unsafe { TODO: call ffi:gst_source_buffer_get_buffered() }
//}
#[doc(alias = "gst_source_buffer_get_content_type")]
#[doc(alias = "get_content_type")]
#[doc(alias = "content-type")]
pub fn content_type(&self) -> glib::GString {
unsafe {
from_glib_full(ffi::gst_source_buffer_get_content_type(
self.to_glib_none().0,
))
}
}
#[doc(alias = "gst_source_buffer_get_timestamp_offset")]
#[doc(alias = "get_timestamp_offset")]
#[doc(alias = "timestamp-offset")]
pub fn timestamp_offset(&self) -> Option<gst::ClockTime> {
unsafe {
from_glib(ffi::gst_source_buffer_get_timestamp_offset(
self.to_glib_none().0,
))
}
}
#[doc(alias = "gst_source_buffer_get_updating")]
#[doc(alias = "get_updating")]
#[doc(alias = "updating")]
pub fn is_updating(&self) -> bool {
unsafe { from_glib(ffi::gst_source_buffer_get_updating(self.to_glib_none().0)) }
}
#[doc(alias = "gst_source_buffer_remove")]
pub fn remove(
&self,
start: impl Into<Option<gst::ClockTime>>,
end: impl Into<Option<gst::ClockTime>>,
) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_remove(
self.to_glib_none().0,
start.into().into_glib(),
end.into().into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_source_buffer_set_append_mode")]
#[doc(alias = "append-mode")]
pub fn set_append_mode(&self, mode: SourceBufferAppendMode) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_set_append_mode(
self.to_glib_none().0,
mode.into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_source_buffer_set_append_window_end")]
pub fn set_append_window_end(
&self,
end: impl Into<Option<gst::ClockTime>>,
) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_set_append_window_end(
self.to_glib_none().0,
end.into().into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_source_buffer_set_append_window_start")]
pub fn set_append_window_start(
&self,
start: impl Into<Option<gst::ClockTime>>,
) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_set_append_window_start(
self.to_glib_none().0,
start.into().into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "gst_source_buffer_set_timestamp_offset")]
#[doc(alias = "timestamp-offset")]
pub fn set_timestamp_offset(
&self,
offset: impl Into<Option<gst::ClockTime>>,
) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::gst_source_buffer_set_timestamp_offset(
self.to_glib_none().0,
offset.into().into_glib(),
&mut error,
);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() {
Ok(())
} else {
Err(from_glib_full(error))
}
}
}
#[doc(alias = "content-type")]
pub fn set_content_type(&self, content_type: Option<&str>) {
ObjectExt::set_property(self, "content-type", content_type)
}
#[doc(alias = "on-abort")]
pub fn connect_on_abort<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn on_abort_trampoline<F: Fn(&SourceBuffer) + Send + Sync + 'static>(
this: *mut ffi::GstSourceBuffer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-abort".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_abort_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "on-error")]
pub fn connect_on_error<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn on_error_trampoline<F: Fn(&SourceBuffer) + Send + Sync + 'static>(
this: *mut ffi::GstSourceBuffer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-error".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_error_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "on-update")]
pub fn connect_on_update<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn on_update_trampoline<F: Fn(&SourceBuffer) + Send + Sync + 'static>(
this: *mut ffi::GstSourceBuffer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-update".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_update_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "on-update-end")]
pub fn connect_on_update_end<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn on_update_end_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-update-end".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_update_end_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "on-update-start")]
pub fn connect_on_update_start<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn on_update_start_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-update-start".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_update_start_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "append-mode")]
pub fn connect_append_mode_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_append_mode_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::append-mode".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_append_mode_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "append-window-end")]
pub fn connect_append_window_end_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_append_window_end_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::append-window-end".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_append_window_end_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "append-window-start")]
pub fn connect_append_window_start_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_append_window_start_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::append-window-start".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_append_window_start_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "buffered")]
pub fn connect_buffered_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_buffered_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::buffered".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_buffered_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "content-type")]
pub fn connect_content_type_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_content_type_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::content-type".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_content_type_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "timestamp-offset")]
pub fn connect_timestamp_offset_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_timestamp_offset_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::timestamp-offset".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_timestamp_offset_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "updating")]
pub fn connect_updating_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_updating_trampoline<
F: Fn(&SourceBuffer) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBuffer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::updating".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_updating_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}
unsafe impl Send for SourceBuffer {}
unsafe impl Sync for SourceBuffer {}

View file

@ -0,0 +1,125 @@
// 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::{ffi, SourceBuffer};
use glib::{
object::ObjectType as _,
prelude::*,
signal::{connect_raw, SignalHandlerId},
translate::*,
};
use std::boxed::Box as Box_;
glib::wrapper! {
#[doc(alias = "GstSourceBufferList")]
pub struct SourceBufferList(Object<ffi::GstSourceBufferList, ffi::GstSourceBufferListClass>) @extends gst::Object;
match fn {
type_ => || ffi::gst_source_buffer_list_get_type(),
}
}
impl SourceBufferList {
#[doc(alias = "gst_source_buffer_list_get_length")]
#[doc(alias = "get_length")]
pub fn length(&self) -> u32 {
unsafe { ffi::gst_source_buffer_list_get_length(self.to_glib_none().0) }
}
#[doc(alias = "gst_source_buffer_list_index")]
pub fn index(&self, index: u32) -> Option<SourceBuffer> {
unsafe {
from_glib_full(ffi::gst_source_buffer_list_index(
self.to_glib_none().0,
index,
))
}
}
#[doc(alias = "on-sourcebuffer-added")]
pub fn connect_on_sourcebuffer_added<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn on_sourcebuffer_added_trampoline<
F: Fn(&SourceBufferList) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBufferList,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-sourcebuffer-added".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_sourcebuffer_added_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "on-sourcebuffer-removed")]
pub fn connect_on_sourcebuffer_removed<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn on_sourcebuffer_removed_trampoline<
F: Fn(&SourceBufferList) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBufferList,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"on-sourcebuffer-removed".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
on_sourcebuffer_removed_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
#[doc(alias = "length")]
pub fn connect_length_notify<F: Fn(&Self) + Send + Sync + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn notify_length_trampoline<
F: Fn(&SourceBufferList) + Send + Sync + 'static,
>(
this: *mut ffi::GstSourceBufferList,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
c"notify::length".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
notify_length_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}
unsafe impl Send for SourceBufferList {}
unsafe impl Sync for SourceBufferList {}

View file

@ -0,0 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 491114ad76bd)
from gir-files (https://github.com/gtk-rs/gir-files @ 56728a5eb215)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ ce667eb782d7)

33
gstreamer-mse/src/lib.rs Normal file
View file

@ -0,0 +1,33 @@
// Take a look at the license at the top of the repository in the LICENSE file.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::manual_c_str_literals)]
#![doc = include_str!("../README.md")]
pub use gstreamer_mse_sys as ffi;
macro_rules! assert_initialized_main_thread {
() => {
if !gst::INITIALIZED.load(std::sync::atomic::Ordering::SeqCst) {
gst::assert_initialized();
}
};
}
macro_rules! skip_assert_initialized {
() => {};
}
#[allow(unused_imports)]
mod auto;
#[allow(unused_imports)]
pub use auto::*;
mod source_buffer_interval;
pub use source_buffer_interval::SourceBufferInterval;
mod media_source;
mod media_source_range;
pub use media_source_range::MediaSourceRange;

View file

@ -0,0 +1,12 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::prelude::*;
use glib::translate::IntoGlib;
use crate::MediaSource;
impl MediaSource {
pub fn set_position(&self, position: impl Into<Option<gst::ClockTime>>) {
ObjectExt::set_property(self, "position", position.into().into_glib())
}
}

View file

@ -0,0 +1,61 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use std::fmt;
use crate::ffi;
glib::wrapper! {
#[doc(alias = "GstMediaSourceRange")]
pub struct MediaSourceRange(BoxedInline<ffi::GstMediaSourceRange>);
match fn {}
}
impl MediaSourceRange {
pub fn new(start: gst::ClockTime, end: gst::ClockTime) -> Self {
skip_assert_initialized!();
let inner = ffi::GstMediaSourceRange {
start: start.nseconds(),
end: end.nseconds(),
};
Self { inner }
}
pub fn start(&self) -> gst::ClockTime {
gst::ClockTime::from_nseconds(self.inner.start)
}
pub fn set_start(&mut self, start: gst::ClockTime) {
self.inner.start = start.nseconds();
}
pub fn end(&self) -> gst::ClockTime {
gst::ClockTime::from_nseconds(self.inner.end)
}
pub fn set_end(&mut self, end: gst::ClockTime) {
self.inner.end = end.nseconds();
}
}
unsafe impl Send for MediaSourceRange {}
unsafe impl Sync for MediaSourceRange {}
impl PartialEq for MediaSourceRange {
fn eq(&self, other: &Self) -> bool {
self.inner.start == other.inner.start && self.inner.end == other.inner.end
}
}
impl Eq for MediaSourceRange {}
impl fmt::Debug for MediaSourceRange {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MediaSourceRange")
.field("start", &self.start())
.field("end", &self.end())
.finish()
}
}

View file

@ -0,0 +1,61 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use std::fmt;
use crate::ffi;
glib::wrapper! {
#[doc(alias = "GstSourceBufferInterval")]
pub struct SourceBufferInterval(BoxedInline<ffi::GstSourceBufferInterval>);
match fn {}
}
impl SourceBufferInterval {
pub fn new(start: gst::ClockTime, end: gst::ClockTime) -> Self {
skip_assert_initialized!();
let inner = ffi::GstSourceBufferInterval {
start: start.nseconds(),
end: end.nseconds(),
};
Self { inner }
}
pub fn start(&self) -> gst::ClockTime {
gst::ClockTime::from_nseconds(self.inner.start)
}
pub fn set_start(&mut self, start: gst::ClockTime) {
self.inner.start = start.nseconds();
}
pub fn end(&self) -> gst::ClockTime {
gst::ClockTime::from_nseconds(self.inner.end)
}
pub fn set_end(&mut self, end: gst::ClockTime) {
self.inner.end = end.nseconds();
}
}
unsafe impl Send for SourceBufferInterval {}
unsafe impl Sync for SourceBufferInterval {}
impl PartialEq for SourceBufferInterval {
fn eq(&self, other: &Self) -> bool {
self.inner.start == other.inner.start && self.inner.end == other.inner.end
}
}
impl Eq for SourceBufferInterval {}
impl fmt::Debug for SourceBufferInterval {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("SourceBufferInterval")
.field("start", &self.start())
.field("end", &self.end())
.finish()
}
}

1
gstreamer-mse/sys/COPYRIGHT Symbolic link
View file

@ -0,0 +1 @@
../COPYRIGHT

View file

@ -1,7 +1,5 @@
[package]
name = "gstreamer-mse-sys"
version = "0.0.1"
edition = "2021"
build = "build.rs"
authors = ["Sebastian Dröge <sebastian@centricular.com>", "Simon Wülker <simon.wuelker@arcor.de>"]
description = "FFI bindings to libgstmse-1.0"
@ -9,6 +7,24 @@ documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/lat
keywords = ["ffi", "gstreamer", "gnome", "multimedia"]
readme = "README.md"
[package.version]
workspace = true
[package.categories]
workspace = true
[package.repository]
workspace = true
[package.homepage]
workspace = true
[package.edition]
workspace = true
[package.rust-version]
workspace = true
[package.metadata.system-deps.gstreamer_mse_1_0]
name = "gstreamer-mse-1.0"
version = "1.26"
@ -38,4 +54,3 @@ shell-words = "1.0.0"
tempfile = "3"
[features]
v1_24 = []

View file

@ -0,0 +1 @@
../LICENSE-APACHE

View file

@ -0,0 +1 @@
../LICENSE-MIT

220
gstreamer-mse/sys/README.md Normal file
View file

@ -0,0 +1,220 @@
# gstreamer-rs [![crates.io](https://img.shields.io/crates/v/gstreamer-mse-sys.svg)](https://crates.io/crates/gstreamer-mse-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/) (MSE library) bindings for Rust.
Documentation can be found [here](https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_mse/).
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
- [gstreamer-rs ](#gstreamer-rs--)
- [Table of Contents](#table-of-contents)
- [Installation](#installation)
- [Linux/BSDs](#linuxbsds)
- [macOS](#macos)
- [GStreamer Binaries](#gstreamer-binaries)
- [Homebrew](#homebrew)
- [Windows](#windows)
- [GStreamer Binaries](#gstreamer-binaries-1)
- [MSYS2 / pacman](#msys2--pacman)
- [Getting Started](#getting-started)
- [LICENSE](#license)
- [Contribution](#contribution)
<a name="installation"/>
## Installation
To build the GStreamer bindings or anything depending on them, you need to
have at least GStreamer 1.14 and gst-plugins-base 1.14 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.
<a name="installation-linux"/>
### 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.14. 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. See the `Cargo.toml`
files for the full details,
```console
$ 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.
<a name="installation-macos"/>
### 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.
We recommend using the official GStreamer binaries over Homebrew, especially
as GStreamer in Homebrew is [currently broken](https://github.com/orgs/Homebrew/discussions/3740#discussioncomment-3804964).
#### GStreamer Binaries
You need to download the *two* `.pkg` files from the GStreamer website and
install them, e.g. `gstreamer-1.0-1.20.4-universal.pkg` and
`gstreamer-1.0-devel-1.20.4-universal.pkg`.
After installation, you also need to set the `PATH` environment variable as
follows
```console
$ export PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/bin${PATH:+:$PATH}"
```
Also note that the `pkg-config` from GStreamer should be the first one in
the `PATH` as other versions have all kinds of quirks that will cause
problems.
#### 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
```
Make sure the version of these libraries is >= 1.14.
<a name="installation-windows"/>
### 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.
We recommend using the official GStreamer binaries over MSYS2.
#### 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.20.4.msi` and
`gstreamer-1.0-devel-x86_64-1.20.4.msi`. Make sure to select the version that
matches your Rust toolchain, i.e. MinGW or MSVC.
After installation set the ``PATH` environment variable as follows:
```console
# For a UNIX-style shell:
$ export PATH="c:/gstreamer/1.0/msvc_x86_64/bin${PATH:+:$PATH}"
# For cmd.exe:
$ set PATH=C:\gstreamer\1.0\msvc_x86_64\bin;%PATH%
```
Make sure to update the path to where you have actually installed GStreamer
and for the corresponding toolchain.
Also note that the `pkg-config.exe` from GStreamer should be the first one in
the `PATH` as other versions have all kinds of quirks that will cause
problems.
#### 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
```
Make sure the version of these libraries is >= 1.14.
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/).
<a name="getting-started"/>
## 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.
<a name="license"/>
## 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
<a name="contribution"/>
## 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.