analytics: Add bindings for apps/plugins

The whole API to use the Analytics meta is implemented.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1358>
This commit is contained in:
Olivier Crête 2023-11-28 09:39:18 -06:00 committed by Sebastian Dröge
parent 36792404a9
commit 7ec3c8713a
82 changed files with 2541 additions and 51 deletions

23
Cargo.lock generated
View file

@ -881,6 +881,29 @@ dependencies = [
"tempfile",
]
[[package]]
name = "gstreamer-analytics"
version = "0.22.0"
dependencies = [
"gir-format-check",
"glib",
"gstreamer",
"gstreamer-analytics-sys",
"libc",
]
[[package]]
name = "gstreamer-analytics-sys"
version = "0.22.0"
dependencies = [
"glib-sys",
"gstreamer-sys",
"libc",
"shell-words",
"system-deps",
"tempfile",
]
[[package]]
name = "gstreamer-app"
version = "0.22.0"

View file

@ -3,6 +3,7 @@ resolver = "2"
default-members = [
"gstreamer/sys",
"gstreamer-analytics/sys",
"gstreamer-app/sys",
"gstreamer-audio/sys",
"gstreamer-base/sys",
@ -22,6 +23,7 @@ default-members = [
"gstreamer-video/sys",
"gstreamer-webrtc/sys",
"gstreamer",
"gstreamer-analytics",
"gstreamer-app",
"gstreamer-audio",
"gstreamer-base",
@ -47,6 +49,7 @@ default-members = [
members = [
"gstreamer/sys",
"gstreamer-analytics/sys",
"gstreamer-app/sys",
"gstreamer-audio/sys",
"gstreamer-base/sys",
@ -71,6 +74,7 @@ members = [
"gstreamer-webrtc/sys",
"gstreamer-allocators/sys",
"gstreamer",
"gstreamer-analytics",
"gstreamer-app",
"gstreamer-audio",
"gstreamer-base",

View file

@ -13,7 +13,7 @@ get_features() {
gstreamer-audio|gstreamer-editing-services|gstreamer-gl|gstreamer-pbutils|gstreamer-rtp|gstreamer-rtsp|gstreamer-video|gstreamer)
echo "--features=serde,v1_24"
;;
gstreamer-validate)
gstreamer-analytics)
echo ""
;;
*)

@ -1 +1 @@
Subproject commit 3f9f549accb70d139a2ae049d36f32c059398060
Subproject commit 63e90a30193bf8d228057c4570a50a0a2b40f2bd

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -0,0 +1 @@
../gstreamer/CHANGELOG.md

View file

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

View file

@ -0,0 +1,31 @@
[package]
name = "gstreamer-analytics"
authors = ["Olivier Crête <olivier.crete@collabora.com>"]
description = "Rust bindings for GStreamer Analytics library"
license = "MIT OR Apache-2.0"
readme = "README.md"
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_analytics/"
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]
libc = "0.2"
ffi = { package = "gstreamer-analytics-sys", path = "sys" }
glib.workspace = true
gst.workspace = true
[dev-dependencies]
gir-format-check = "0.1"
[features]
default = []
[package.metadata.docs.rs]
all-features = true
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]

View file

@ -0,0 +1,34 @@
[options]
girs_directories = ["../gir-files", "../gst-gir-files"]
library = "GstAnalytics"
version = "1.0"
min_cfg_version = "1.24"
work_mode = "normal"
concurrency = "send+sync"
generate_safety_asserts = true
single_version_file = true
generate_display_trait = false
trust_return_value_nullability = true
external_libraries = [
"GLib",
"GObject",
"Gst",
]
generate = [
"GstAnalytics.RelTypes"
]
manual = [
"GObject.Object",
"Gst.Element",
"Gst.MiniObject",
"Gst.Object"
]
[[object]]
name = "Gst.Buffer"
status = "manual"
ref_mode = "ref"

View file

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

View file

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

View file

@ -0,0 +1,214 @@
# gstreamer-rs [![crates.io](https://img.shields.io/crates/v/gstreamer-app.svg)](https://crates.io/crates/gstreamer-app) [![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/) (App library) bindings for Rust.
Documentation can be found [here](https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_app/).
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)
<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,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
use glib::{bitflags::bitflags, translate::*};
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[doc(alias = "GstAnalyticsRelTypes")]
pub struct RelTypes: u32 {
#[doc(alias = "GST_ANALYTICS_REL_TYPE_NONE")]
const NONE = ffi::GST_ANALYTICS_REL_TYPE_NONE as _;
#[doc(alias = "GST_ANALYTICS_REL_TYPE_IS_PART_OF")]
const IS_PART_OF = ffi::GST_ANALYTICS_REL_TYPE_IS_PART_OF as _;
#[doc(alias = "GST_ANALYTICS_REL_TYPE_CONTAIN")]
const CONTAIN = ffi::GST_ANALYTICS_REL_TYPE_CONTAIN as _;
#[doc(alias = "GST_ANALYTICS_REL_TYPE_RELATE_TO")]
const RELATE_TO = ffi::GST_ANALYTICS_REL_TYPE_RELATE_TO as _;
#[doc(alias = "GST_ANALYTICS_REL_TYPE_LAST")]
const LAST = ffi::GST_ANALYTICS_REL_TYPE_LAST as _;
#[doc(alias = "GST_ANALYTICS_REL_TYPE_ANY")]
const ANY = ffi::GST_ANALYTICS_REL_TYPE_ANY as _;
}
}
#[doc(hidden)]
impl IntoGlib for RelTypes {
type GlibType = ffi::GstAnalyticsRelTypes;
#[inline]
fn into_glib(self) -> ffi::GstAnalyticsRelTypes {
self.bits()
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstAnalyticsRelTypes> for RelTypes {
#[inline]
unsafe fn from_glib(value: ffi::GstAnalyticsRelTypes) -> Self {
skip_assert_initialized!();
Self::from_bits_truncate(value)
}
}

View file

@ -0,0 +1,7 @@
// 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 flags;
pub use self::flags::RelTypes;

View file

@ -0,0 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -0,0 +1,212 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::*;
use crate::relation_meta::*;
#[derive(Debug)]
pub enum AnalyticsClassificationMtd {}
mod sealed {
pub trait Sealed {}
impl<T: super::AnalyticsRelationMetaClassificationExt> Sealed for T {}
}
pub trait AnalyticsRelationMetaClassificationExt: sealed::Sealed {
fn add_one_cls_mtd(
&mut self,
confidence_level: f32,
class_quark: glib::Quark,
) -> Result<AnalyticsMtdRef<AnalyticsClassificationMtd>, glib::BoolError>;
fn add_cls_mtd(
&mut self,
confidence_levels: &[f32],
class_quarks: &[glib::Quark],
) -> Result<AnalyticsMtdRef<AnalyticsClassificationMtd>, glib::BoolError>;
}
impl<'a> AnalyticsRelationMetaClassificationExt
for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
{
#[doc(alias = "gst_analytics_relation_meta_add_one_cls_mtd")]
fn add_one_cls_mtd(
&mut self,
confidence_level: f32,
class_quark: glib::Quark,
) -> Result<AnalyticsMtdRef<'a, AnalyticsClassificationMtd>, glib::BoolError> {
unsafe {
let mut mtd = std::mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_analytics_relation_meta_add_one_cls_mtd(
self.as_mut_ptr(),
confidence_level,
class_quark.into_glib(),
mtd.as_mut_ptr(),
));
let id = mtd.assume_init().id;
if ret {
Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
} else {
Err(glib::bool_error!("Couldn't add more data"))
}
}
}
#[doc(alias = "gst_analytics_relation_meta_add_cls_mtd")]
fn add_cls_mtd(
&mut self,
confidence_levels: &[f32],
class_quarks: &[glib::Quark],
) -> Result<AnalyticsMtdRef<'a, AnalyticsClassificationMtd>, glib::BoolError> {
let length = std::cmp::min(confidence_levels.len(), class_quarks.len());
unsafe {
let mut mtd = std::mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_analytics_relation_meta_add_cls_mtd(
self.as_mut_ptr(),
length,
mut_override(confidence_levels.as_ptr()),
class_quarks.as_ptr() as *mut _,
mtd.as_mut_ptr(),
));
let id = mtd.assume_init().id;
if ret {
Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
} else {
Err(glib::bool_error!("Couldn't add more data"))
}
}
}
}
unsafe impl AnalyticsMtd for AnalyticsClassificationMtd {
#[doc(alias = "gst_analytics_cls_mtd_get_mtd_type")]
fn mtd_type() -> ffi::GstAnalyticsMtdType {
unsafe { ffi::gst_analytics_cls_mtd_get_mtd_type() }
}
}
unsafe fn from(t: ffi::GstAnalyticsMtd) -> ffi::GstAnalyticsClsMtd {
std::mem::transmute(t)
}
impl<'a> AnalyticsMtdRef<'a, AnalyticsClassificationMtd> {
#[doc(alias = "gst_analytics_cls_mtd_get_length")]
pub fn len(&self) -> usize {
unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
ffi::gst_analytics_cls_mtd_get_length(&mut mtd)
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[doc(alias = "gst_analytics_cls_mtd_get_level")]
pub fn level(&self, index: usize) -> f32 {
assert!(index < self.len());
unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
ffi::gst_analytics_cls_mtd_get_level(&mut mtd, index)
}
}
#[doc(alias = "gst_analytics_cls_mtd_get_quark")]
pub fn quark(&self, index: usize) -> glib::Quark {
assert!(index < self.len());
unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
from_glib(ffi::gst_analytics_cls_mtd_get_quark(&mut mtd, index))
}
}
pub fn iterate(&self) -> AnalyticsClassificationIterator {
AnalyticsClassificationIterator {
mtd: self,
index: 0,
length: self.len(),
}
}
}
pub struct AnalyticsClassificationIterator<'a> {
mtd: &'a AnalyticsMtdRef<'a, AnalyticsClassificationMtd>,
index: usize,
length: usize,
}
impl<'a> Iterator for AnalyticsClassificationIterator<'a> {
type Item = (glib::Quark, f32);
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.length {
None
} else {
let ret = Some((self.mtd.quark(self.index), self.mtd.level(self.index)));
self.index += 1;
ret
}
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn one_class() {
gst::init().unwrap();
assert_eq!(AnalyticsClassificationMtd::type_name(), "classification");
let mut buf = gst::Buffer::new();
let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
assert!(meta.is_empty());
let cls = meta
.add_one_cls_mtd(0.7, glib::Quark::from_str("class1"))
.unwrap();
assert_eq!(cls.len(), 1);
assert_eq!(cls.level(0), 0.7);
assert_eq!(cls.quark(0), glib::Quark::from_str("class1"));
}
#[test]
fn many_classes() {
gst::init().unwrap();
assert_eq!(AnalyticsClassificationMtd::type_name(), "classification");
let mut buf = gst::Buffer::new();
let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
assert!(meta.is_empty());
let classes = [
glib::Quark::from_str("a"),
glib::Quark::from_str("b"),
glib::Quark::from_str("c"),
glib::Quark::from_str("d"),
];
let levels = [0.1, 0.2, 0.3, 0.4];
let cls = meta.add_cls_mtd(&levels, &classes).unwrap();
assert_eq!(cls.len(), 4);
for i in 0..4usize {
assert_eq!(cls.level(i), levels[i]);
assert_eq!(cls.quark(i), classes[i]);
}
for (i, (q, l)) in cls.iterate().enumerate() {
assert_eq!(l, levels[i]);
assert_eq!(q, classes[i]);
}
}
}

View file

@ -0,0 +1,36 @@
// 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)]
#![doc = include_str!("../README.md")]
pub use ffi;
pub use glib;
pub use gst;
macro_rules! skip_assert_initialized {
() => {};
}
mod auto;
pub use crate::auto::*;
mod relation_meta;
pub use crate::relation_meta::*;
mod object_detection;
pub use crate::object_detection::*;
mod tracking;
pub use crate::tracking::*;
mod classification;
pub use crate::classification::*;
// Re-export all the traits in a prelude module, so that applications
// can always "use gst_app::prelude::*" without getting conflicts
pub mod prelude {
pub use crate::classification::AnalyticsRelationMetaClassificationExt;
pub use crate::object_detection::AnalyticsRelationMetaODExt;
pub use crate::tracking::AnalyticsRelationMetaTrackingExt;
}

View file

@ -0,0 +1,171 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::*;
use crate::relation_meta::*;
#[derive(Debug)]
pub enum AnalyticsODMtd {}
mod sealed {
pub trait Sealed {}
impl<T: super::AnalyticsRelationMetaODExt> Sealed for T {}
}
pub trait AnalyticsRelationMetaODExt: sealed::Sealed {
fn add_od_mtd(
&mut self,
type_: glib::Quark,
x: i32,
y: i32,
w: i32,
h: i32,
loc_conf_lvl: f32,
) -> Result<AnalyticsMtdRef<AnalyticsODMtd>, glib::BoolError>;
}
impl<'a> AnalyticsRelationMetaODExt
for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
{
#[doc(alias = "gst_analytics_relation_meta_add_od_mtd")]
fn add_od_mtd(
&mut self,
type_: glib::Quark,
x: i32,
y: i32,
w: i32,
h: i32,
loc_conf_lvl: f32,
) -> Result<AnalyticsMtdRef<AnalyticsODMtd>, glib::BoolError> {
unsafe {
let mut mtd = std::mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_analytics_relation_meta_add_od_mtd(
self.as_mut_ptr(),
type_.into_glib(),
x,
y,
w,
h,
loc_conf_lvl,
mtd.as_mut_ptr(),
));
let id = mtd.assume_init().id;
if ret {
Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
} else {
Err(glib::bool_error!("Couldn't add more data"))
}
}
}
}
#[derive(Default, Debug)]
pub struct AnalyticsODLocation {
x: i32,
y: i32,
w: i32,
h: i32,
loc_conf_lvl: f32,
}
unsafe impl AnalyticsMtd for AnalyticsODMtd {
#[doc(alias = "gst_analytics_od_mtd_get_mtd_type")]
fn mtd_type() -> ffi::GstAnalyticsMtdType {
unsafe { ffi::gst_analytics_od_mtd_get_mtd_type() }
}
}
unsafe fn from(t: ffi::GstAnalyticsMtd) -> ffi::GstAnalyticsODMtd {
std::mem::transmute(t)
}
impl<'a> AnalyticsMtdRef<'a, AnalyticsODMtd> {
#[doc(alias = "gst_analytics_od_mtd_get_obj_type")]
pub fn obj_type(&self) -> glib::Quark {
unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
let type_ = ffi::gst_analytics_od_mtd_get_obj_type(&mut mtd);
glib::Quark::from_glib(type_)
}
}
#[doc(alias = "gst_analytics_od_mtd_get_location")]
pub fn location(&self) -> Result<AnalyticsODLocation, glib::BoolError> {
let mut loc = AnalyticsODLocation::default();
let success = unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
ffi::gst_analytics_od_mtd_get_location(
&mut mtd,
&mut loc.x,
&mut loc.y,
&mut loc.w,
&mut loc.h,
&mut loc.loc_conf_lvl,
)
};
if success != 0 {
Ok(loc)
} else {
Err(glib::bool_error!("Could retrieve location"))
}
}
#[doc(alias = "gst_analytics_od_mtd_get_confidence_lvl")]
pub fn confidence_level(&self) -> f32 {
unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
let mut lvl: f32 = 0.0;
ffi::gst_analytics_od_mtd_get_confidence_lvl(&mut mtd, &mut lvl);
lvl
}
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn object_detection() {
gst::init().unwrap();
assert_eq!(AnalyticsODMtd::type_name(), "object-detection");
let mut buf = gst::Buffer::new();
let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
assert!(meta.is_empty());
let od = meta
.add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
.unwrap();
assert_eq!(od.obj_type(), glib::Quark::from_str("blb"));
let loc = od.location().unwrap();
assert_eq!(loc.x, 0);
assert_eq!(loc.y, 1);
assert_eq!(loc.w, 10);
assert_eq!(loc.h, 20);
assert_eq!(loc.loc_conf_lvl, 0.8);
let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
assert!(meta.mtd::<AnalyticsODMtd>(1).is_none());
let meta2 = buf.meta::<AnalyticsRelationMeta>().unwrap();
let od2 = meta2.mtd::<AnalyticsODMtd>(0).unwrap();
assert_eq!(od2.obj_type(), glib::Quark::from_str("blb"));
let loc = od2.location().unwrap();
assert_eq!(loc.x, 0);
assert_eq!(loc.y, 1);
assert_eq!(loc.w, 10);
assert_eq!(loc.h, 20);
assert_eq!(loc.loc_conf_lvl, 0.8);
}
}

View file

@ -0,0 +1,706 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::*;
use gst::prelude::*;
use std::marker::PhantomData;
use crate::RelTypes;
#[repr(transparent)]
#[doc(alias = "GstAnalyticsRelationMeta")]
pub struct AnalyticsRelationMeta(ffi::GstAnalyticsRelationMeta);
unsafe impl Send for AnalyticsRelationMeta {}
unsafe impl Sync for AnalyticsRelationMeta {}
#[derive(Debug, Copy, Clone)]
#[doc(alias = "GstAnalyticsRelationMetaInitParams")]
pub struct AnalyticsRelationMetaInitParams(ffi::GstAnalyticsRelationMetaInitParams);
impl Default for AnalyticsRelationMetaInitParams {
fn default() -> Self {
Self(ffi::GstAnalyticsRelationMetaInitParams {
initial_relation_order: 0,
initial_buf_size: 0,
})
}
}
impl AnalyticsRelationMetaInitParams {
pub fn new(initial_relation_order: usize, initial_buf_size: usize) -> Self {
skip_assert_initialized!();
Self(ffi::GstAnalyticsRelationMetaInitParams {
initial_relation_order,
initial_buf_size,
})
}
}
#[derive(Debug, Clone)]
pub struct AnalyticsMtdRef<'a, T: AnalyticsMtd> {
id: u32,
meta: gst::MetaRef<'a, AnalyticsRelationMeta>,
mtd_type: PhantomData<&'a T>,
}
#[derive(Debug)]
pub struct AnalyticsMtdRefMut<'a, T: AnalyticsMtd> {
id: u32,
meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
mtd_type: PhantomData<&'a T>,
}
pub struct AnalyticsRelationPath {
garray: *mut glib::ffi::GArray,
}
impl std::fmt::Debug for AnalyticsRelationMeta {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
f.debug_struct("AnalyticsRelationMeta")
.field("len", &self.len())
.finish()
}
}
impl AnalyticsRelationMeta {
#[doc(alias = "gst_buffer_add_analytics_relation_meta")]
pub fn add(buffer: &mut gst::BufferRef) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
skip_assert_initialized!();
unsafe {
let meta_ptr = ffi::gst_buffer_add_analytics_relation_meta(buffer.as_mut_ptr());
Self::from_mut_ptr(buffer, meta_ptr)
}
}
#[doc(alias = "gst_buffer_add_analytics_relation_meta_full")]
pub fn add_full<'a>(
buffer: &'a mut gst::BufferRef,
init_params: &AnalyticsRelationMetaInitParams,
) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
skip_assert_initialized!();
unsafe {
let meta_ptr = ffi::gst_buffer_add_analytics_relation_meta_full(
buffer.as_mut_ptr(),
mut_override(&init_params.0),
);
Self::from_mut_ptr(buffer, meta_ptr)
}
}
#[doc(alias = "gst_analytics_relation_get_length")]
pub fn len(&self) -> usize {
unsafe { ffi::gst_analytics_relation_get_length(self.as_mut_ptr()) }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[doc(alias = "gst_analytics_relation_meta_set_relation")]
pub fn set_relation(
&mut self,
type_: crate::RelTypes,
an_meta_first_id: u32,
an_meta_second_id: u32,
) -> Result<(), glib::BoolError> {
let ret = unsafe {
from_glib(ffi::gst_analytics_relation_meta_set_relation(
self.as_mut_ptr(),
type_.into_glib(),
an_meta_first_id,
an_meta_second_id,
))
};
if ret {
Ok(())
} else {
Err(glib::bool_error!(
"Could not set relation {:}->{:} of type {:?}",
an_meta_first_id,
an_meta_second_id,
type_
))
}
}
#[doc(alias = "gst_analytics_relation_meta_get_relation")]
pub fn relation(&self, an_meta_first_id: u32, an_meta_second_id: u32) -> crate::RelTypes {
unsafe {
from_glib(ffi::gst_analytics_relation_meta_get_relation(
self.as_mut_ptr(),
an_meta_first_id,
an_meta_second_id,
))
}
}
#[doc(alias = "gst_analytics_relation_meta_exist")]
pub fn exist(
&self,
an_meta_first_id: u32,
an_meta_second_id: u32,
relation_span: i32,
cond_types: crate::RelTypes,
) -> bool {
unsafe {
from_glib(ffi::gst_analytics_relation_meta_exist(
self.as_mut_ptr(),
an_meta_first_id,
an_meta_second_id,
relation_span,
cond_types.into_glib(),
std::ptr::null_mut(),
))
}
}
#[doc(alias = "gst_analytics_relation_meta_exist")]
pub fn exist_path(
&self,
an_meta_first_id: u32,
an_meta_second_id: u32,
relation_span: i32,
cond_types: crate::RelTypes,
) -> Result<AnalyticsRelationPath, glib::BoolError> {
let mut array = std::ptr::null_mut::<glib::ffi::GArray>();
let ret = unsafe {
from_glib(ffi::gst_analytics_relation_meta_exist(
self.as_mut_ptr(),
an_meta_first_id,
an_meta_second_id,
relation_span,
cond_types.into_glib(),
&mut array,
))
};
if ret {
Ok(AnalyticsRelationPath { garray: array })
} else {
Err(glib::bool_error!("Such relation doesn't exist"))
}
}
pub unsafe fn as_mut_ptr(&self) -> *mut ffi::GstAnalyticsRelationMeta {
mut_override(&self.0)
}
}
impl UnsafeFrom<&AnalyticsRelationMeta> for ffi::GstAnalyticsMtd {
unsafe fn unsafe_from(t: &AnalyticsRelationMeta) -> Self {
ffi::GstAnalyticsMtd {
id: 0,
meta: t.as_mut_ptr(),
}
}
}
impl AnalyticsRelationPath {
pub fn as_slice(&self) -> &[u32] {
unsafe {
std::slice::from_raw_parts(
(*self.garray).data as *const u32,
(*self.garray).len as usize,
)
}
}
}
impl Drop for AnalyticsRelationPath {
fn drop(&mut self) {
unsafe {
glib::ffi::g_array_free(self.garray, glib::ffi::GTRUE);
}
}
}
mod sealed {
pub trait Sealed {}
impl<T> Sealed for T {}
}
pub trait AnalyticsMetaRefExt<'a>: sealed::Sealed {
#[doc(alias = "gst_analytics_relation_meta_get_mtd")]
fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>>;
fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<T>;
fn iter_direct_related<T: AnalyticsMtd>(
&'a self,
an_meta_id: u32,
rel_type: RelTypes,
) -> AnalyticsMtdIter<T>;
}
impl<'a> AnalyticsMetaRefExt<'a> for gst::MetaRef<'a, AnalyticsRelationMeta> {
fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>> {
unsafe {
let mut mtd = std::mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
self.as_mut_ptr(),
an_meta_id,
T::mtd_type(),
mtd.as_mut_ptr(),
));
let id = mtd.assume_init().id;
if ret {
Some(AnalyticsMtdRef::from_meta(self, id))
} else {
None
}
}
}
fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<'a, T> {
AnalyticsMtdIter::new(self)
}
fn iter_direct_related<T: AnalyticsMtd>(
&'a self,
an_meta_id: u32,
rel_type: RelTypes,
) -> AnalyticsMtdIter<T> {
AnalyticsMtdIter::new_direct_related(self, an_meta_id, rel_type.into_glib())
}
}
impl<'a, T: AnalyticsMtd> AnalyticsMtdRef<'a, T> {
pub fn id(&self) -> u32 {
self.id
}
pub unsafe fn from_meta(meta: &gst::MetaRef<'a, AnalyticsRelationMeta>, id: u32) -> Self {
skip_assert_initialized!();
AnalyticsMtdRef {
meta: meta.clone(),
id,
mtd_type: PhantomData,
}
}
#[doc(alias = "gst_analytics_mtd_get_mtd_type")]
pub fn mtd_type(&self) -> ffi::GstAnalyticsMtdType {
unsafe {
let mut mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
ffi::gst_analytics_mtd_get_mtd_type(&mut mtd)
}
}
}
impl<'a> AnalyticsMtdRef<'a, AnalyticsAnyMtd> {
pub fn downcast<T: AnalyticsMtd>(
self,
) -> Result<AnalyticsMtdRef<'a, T>, AnalyticsMtdRef<'a, AnalyticsAnyMtd>> {
if self.mtd_type() == T::mtd_type() {
Ok(AnalyticsMtdRef {
id: self.id,
meta: self.meta,
mtd_type: PhantomData,
})
} else {
Err(self)
}
}
pub fn downcast_ref<T: AnalyticsMtd>(&self) -> Option<&AnalyticsMtdRef<'a, T>> {
unsafe {
if self.mtd_type() == T::mtd_type() {
Some(&*(self as *const _ as *const _))
} else {
None
}
}
}
}
impl<'a> AnalyticsMtdRefMut<'a, AnalyticsAnyMtd> {
pub fn downcast_mut<T: AnalyticsMtd>(&mut self) -> Option<&mut AnalyticsMtdRefMut<'a, T>> {
unsafe {
if self.as_ref().mtd_type() == T::mtd_type() {
Some(&mut *(self as *mut _ as *mut _))
} else {
None
}
}
}
}
impl<'a, T: AnalyticsMtd> UnsafeFrom<&AnalyticsMtdRef<'a, T>> for ffi::GstAnalyticsMtd {
unsafe fn unsafe_from(t: &AnalyticsMtdRef<'a, T>) -> Self {
ffi::GstAnalyticsMtd {
id: t.id,
meta: t.meta.as_mut_ptr(),
}
}
}
pub trait AnalyticsMetaRefMutExt<'a>: sealed::Sealed {
#[doc(alias = "gst_analytics_relation_meta_get_mtd")]
fn mtd_mut<T: AnalyticsMtd>(&'a mut self, an_meta_id: u32)
-> Option<AnalyticsMtdRefMut<'a, T>>;
fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<T>;
fn iter_direct_related_mut<T: AnalyticsMtd>(
&'a mut self,
an_meta_id: u32,
rel_type: RelTypes,
) -> AnalyticsMtdIterMut<T>;
}
impl<'a> AnalyticsMetaRefMutExt<'a>
for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
{
fn mtd_mut<T: AnalyticsMtd>(
&'a mut self,
an_meta_id: u32,
) -> Option<AnalyticsMtdRefMut<'a, T>> {
unsafe {
let mut mtd = std::mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
self.as_mut_ptr(),
an_meta_id,
T::mtd_type(),
mtd.as_mut_ptr(),
));
let id = mtd.assume_init().id;
if ret {
Some(AnalyticsMtdRefMut::from_meta(self, id))
} else {
None
}
}
}
fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<T> {
AnalyticsMtdIterMut::new(self)
}
fn iter_direct_related_mut<T: AnalyticsMtd>(
&'a mut self,
an_meta_id: u32,
rel_type: RelTypes,
) -> AnalyticsMtdIterMut<T> {
AnalyticsMtdIterMut::new_direct_related(self, an_meta_id, rel_type.into_glib())
}
}
unsafe impl MetaAPI for AnalyticsRelationMeta {
type GstType = ffi::GstAnalyticsRelationMeta;
#[doc(alias = "gst_analytics_relation_meta_api_get_type")]
#[inline]
fn meta_api() -> glib::Type {
unsafe { from_glib(ffi::gst_analytics_relation_meta_api_get_type()) }
}
}
pub unsafe trait AnalyticsMtd {
fn mtd_type() -> ffi::GstAnalyticsMtdType;
}
pub trait AnalyticsMtdExt: AnalyticsMtd {
#[doc(alias = "gst_analytics_mtd_type_get_name")]
fn type_name() -> &'static str {
unsafe {
let ptr = ffi::gst_analytics_mtd_type_get_name(Self::mtd_type());
std::ffi::CStr::from_ptr(ptr).to_str().unwrap()
}
}
}
impl<T: AnalyticsMtd> AnalyticsMtdExt for T {}
impl<'a, T: AnalyticsMtd> AnalyticsMtdRefMut<'a, T> {
pub fn id(&self) -> u32 {
self.id
}
pub unsafe fn from_meta(
meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
id: u32,
) -> Self {
skip_assert_initialized!();
AnalyticsMtdRefMut {
meta,
id,
mtd_type: PhantomData,
}
}
}
impl<'a, T: AnalyticsMtd> UnsafeFrom<&mut AnalyticsMtdRefMut<'a, T>> for ffi::GstAnalyticsMtd {
unsafe fn unsafe_from(t: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
ffi::GstAnalyticsMtd {
id: t.id,
meta: t.meta.as_mut_ptr(),
}
}
}
impl<'a, T: AnalyticsMtd> From<AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
fn from(value: AnalyticsMtdRefMut<'a, T>) -> Self {
skip_assert_initialized!();
AnalyticsMtdRef {
meta: value.meta.as_ref().clone(),
id: value.id,
mtd_type: value.mtd_type,
}
}
}
impl<'a, T: AnalyticsMtd> From<&mut AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
fn from(value: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
skip_assert_initialized!();
AnalyticsMtdRef {
meta: value.meta.as_ref().clone(),
id: value.id,
mtd_type: value.mtd_type,
}
}
}
impl<'a, T: AnalyticsMtd> AsRef<AnalyticsMtdRef<'a, T>> for AnalyticsMtdRefMut<'a, T> {
#[inline]
fn as_ref(&self) -> &AnalyticsMtdRef<'a, T> {
unsafe { &*(self as *const AnalyticsMtdRefMut<'a, T> as *const AnalyticsMtdRef<'a, T>) }
}
}
macro_rules! define_mtd_iter {
($name:ident, $metaref:ty, $itemref:ty, $copy_meta:expr) => {
pub struct $name<'a, T: AnalyticsMtd> {
meta: $metaref,
state: glib::ffi::gpointer,
mtd_type: ffi::GstAnalyticsMtdType,
an_meta_id: u32,
rel_type: ffi::GstAnalyticsRelTypes,
phantom: std::marker::PhantomData<T>,
}
impl<'a, T: AnalyticsMtd> $name<'a, T> {
fn new(meta: $metaref) -> Self {
skip_assert_initialized!();
$name {
meta,
state: std::ptr::null_mut(),
mtd_type: T::mtd_type(),
an_meta_id: std::u32::MAX,
rel_type: RelTypes::ANY.into_glib(),
phantom: PhantomData,
}
}
fn new_direct_related(
meta: $metaref,
an_meta_id: u32,
rel_type: ffi::GstAnalyticsRelTypes,
) -> Self {
skip_assert_initialized!();
$name {
meta,
state: std::ptr::null_mut(),
mtd_type: T::mtd_type(),
an_meta_id,
rel_type,
phantom: PhantomData,
}
}
}
impl<'a, T: AnalyticsMtd + 'a> Iterator for $name<'a, T> {
type Item = $itemref;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
let mut mtd = ffi::GstAnalyticsMtd::unsafe_from(&**self.meta);
let ret = {
if self.an_meta_id == std::u32::MAX {
ffi::gst_analytics_relation_meta_iterate(
self.meta.as_mut_ptr(),
&mut self.state,
self.mtd_type,
&mut mtd,
)
} else {
ffi::gst_analytics_relation_meta_get_direct_related(
self.meta.as_mut_ptr(),
self.an_meta_id,
self.rel_type,
self.mtd_type,
&mut self.state,
&mut mtd,
)
}
};
if from_glib(ret) {
// This is a known clippy limitation
// https://github.com/rust-lang/rust-clippy/issues/1553
#[allow(clippy::redundant_closure_call)]
Some(Self::Item::from_meta($copy_meta(self.meta), mtd.id))
} else {
None
}
}
}
}
};
}
define_mtd_iter!(
AnalyticsMtdIter,
&'a gst::MetaRef<'a, AnalyticsRelationMeta>,
AnalyticsMtdRef<'a, T>,
|meta| meta
);
define_mtd_iter!(
AnalyticsMtdIterMut,
&'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
AnalyticsMtdRefMut<'a, T>,
|meta: &mut _| &mut *(meta as *mut gst::MetaRefMut<
'a,
AnalyticsRelationMeta,
gst::meta::Standalone,
>)
);
#[derive(Debug)]
pub enum AnalyticsAnyMtd {}
unsafe impl AnalyticsMtd for AnalyticsAnyMtd {
fn mtd_type() -> ffi::GstAnalyticsMtdType {
ffi::GST_ANALYTICS_MTD_TYPE_ANY as ffi::GstAnalyticsMtdType
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn build_relation_meta() {
gst::init().unwrap();
let mut buf = gst::Buffer::new();
let meta = AnalyticsRelationMeta::add(buf.make_mut());
assert!(meta.is_empty());
}
#[test]
fn build_relation_meta_full() {
gst::init().unwrap();
let mut buf = gst::Buffer::new();
let params = AnalyticsRelationMetaInitParams::new(10, 10);
let meta = AnalyticsRelationMeta::add_full(buf.make_mut(), &params);
assert!(meta.is_empty());
}
#[test]
fn relations() {
gst::init().unwrap();
let mut buf = gst::Buffer::new();
let _ = AnalyticsRelationMeta::add(buf.make_mut());
let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
let od = meta
.add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
.unwrap();
let od1_id = od.id();
let od = meta
.add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
.unwrap();
let od2_id = od.id();
let od: AnalyticsMtdRef<'_, AnalyticsODMtd> = meta
.add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
.unwrap();
let od3_id = od.id();
meta.set_relation(RelTypes::IS_PART_OF, od1_id, od2_id)
.unwrap();
meta.set_relation(RelTypes::IS_PART_OF, od2_id, od3_id)
.unwrap();
meta.set_relation(RelTypes::IS_PART_OF, 8888, 9999)
.expect_err("Invalid id");
let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
assert!(meta.relation(od1_id, od2_id) == crate::RelTypes::IS_PART_OF);
assert!(meta.relation(od2_id, od3_id) == crate::RelTypes::IS_PART_OF);
assert!(meta.exist(od1_id, od2_id, 1, crate::RelTypes::IS_PART_OF));
assert!(meta.exist(od1_id, od3_id, 2, crate::RelTypes::IS_PART_OF));
assert!(!meta.exist(od2_id, od1_id, 1, crate::RelTypes::IS_PART_OF));
assert!(!meta.exist(od1_id, od3_id, 1, crate::RelTypes::IS_PART_OF));
assert!(!meta.exist(od1_id, od2_id, 1, crate::RelTypes::CONTAIN));
let path = meta
.exist_path(od1_id, od3_id, 3, crate::RelTypes::ANY)
.unwrap();
assert_eq!(path.as_slice().len(), 3);
assert_eq!(path.as_slice()[0], od1_id);
assert_eq!(path.as_slice()[1], od2_id);
assert_eq!(path.as_slice()[2], od3_id);
assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
assert_eq!(meta.len(), meta.iter::<AnalyticsODMtd>().count());
for mtd in meta.iter::<AnalyticsODMtd>() {
assert_eq!(mtd.obj_type(), glib::Quark::from_str("blb"))
}
assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
for mtd in meta.iter::<AnalyticsAnyMtd>() {
if let Ok(mtd) = mtd.downcast::<AnalyticsODMtd>() {
assert_eq!(mtd.obj_type(), glib::Quark::from_str("blb"))
}
}
assert_eq!(
meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF)
.count(),
1
);
assert_eq!(
meta.iter_direct_related::<AnalyticsODMtd>(od2_id, crate::RelTypes::IS_PART_OF)
.count(),
1
);
assert_eq!(
meta.iter_direct_related::<AnalyticsODMtd>(od3_id, crate::RelTypes::IS_PART_OF)
.count(),
0
);
assert_eq!(
meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::CONTAIN)
.count(),
0
);
assert_eq!(
meta.iter_direct_related::<AnalyticsAnyMtd>(od1_id, crate::RelTypes::CONTAIN)
.count(),
0
);
for mtd in meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF) {
assert_eq!(mtd.obj_type(), glib::Quark::from_str("blb"))
}
let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
assert_eq!(meta.len(), meta.iter_mut::<AnalyticsAnyMtd>().count());
let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
for mut item in meta.iter_mut::<AnalyticsTrackingMtd>() {
item.set_lost().unwrap();
}
}
}

View file

@ -0,0 +1,158 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::*;
use crate::relation_meta::*;
#[derive(Debug)]
pub enum AnalyticsTrackingMtd {}
mod sealed {
pub trait Sealed {}
impl<T: super::AnalyticsRelationMetaTrackingExt> Sealed for T {}
}
pub trait AnalyticsRelationMetaTrackingExt: sealed::Sealed {
fn add_tracking_mtd(
&mut self,
tracking_id: u64,
tracking_first_seen: gst::ClockTime,
) -> Result<AnalyticsMtdRef<AnalyticsTrackingMtd>, glib::BoolError>;
}
impl<'a> AnalyticsRelationMetaTrackingExt
for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
{
#[doc(alias = "gst_analytics_relation_meta_add_tracking_mtd")]
fn add_tracking_mtd(
&mut self,
tracking_id: u64,
tracking_first_seen: gst::ClockTime,
) -> Result<AnalyticsMtdRef<AnalyticsTrackingMtd>, glib::BoolError> {
unsafe {
let mut mtd = std::mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_analytics_relation_meta_add_tracking_mtd(
self.as_mut_ptr(),
tracking_id,
tracking_first_seen.into_glib(),
mtd.as_mut_ptr(),
));
let id = mtd.assume_init().id;
if ret {
Ok(AnalyticsMtdRef::from_meta(self.as_ref(), id))
} else {
Err(glib::bool_error!("Couldn't add more data"))
}
}
}
}
unsafe impl AnalyticsMtd for AnalyticsTrackingMtd {
#[doc(alias = "gst_analytics_tracking_mtd_get_mtd_type")]
fn mtd_type() -> ffi::GstAnalyticsMtdType {
unsafe { ffi::gst_analytics_tracking_mtd_get_mtd_type() }
}
}
unsafe fn from(t: ffi::GstAnalyticsMtd) -> ffi::GstAnalyticsTrackingMtd {
std::mem::transmute(t)
}
impl<'a> AnalyticsMtdRef<'a, AnalyticsTrackingMtd> {
#[doc(alias = "gst_analytics_tracking_mtd_get_info")]
pub fn info(&self) -> (u64, gst::ClockTime, gst::ClockTime, bool) {
let mut tracking_id: u64 = 0;
let mut tracking_first_seen: u64 = 0;
let mut tracking_last_seen: u64 = 0;
let mut tracking_lost: i32 = 0;
unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
ffi::gst_analytics_tracking_mtd_get_info(
&mut mtd,
&mut tracking_id,
&mut tracking_first_seen,
&mut tracking_last_seen,
&mut tracking_lost,
);
};
(
tracking_id,
gst::ClockTime::from_nseconds(tracking_first_seen),
gst::ClockTime::from_nseconds(tracking_last_seen),
tracking_lost != 0,
)
}
}
impl<'a> AnalyticsMtdRefMut<'a, AnalyticsTrackingMtd> {
#[doc(alias = "gst_analytics_tracking_mtd_update_last_seen")]
pub fn update_last_seen(&mut self, last_seen: gst::ClockTime) -> Result<(), glib::BoolError> {
let ret: bool = unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
from_glib(ffi::gst_analytics_tracking_mtd_update_last_seen(
&mut mtd,
last_seen.into_glib(),
))
};
assert!(ret);
Ok(())
}
#[doc(alias = "gst_analytics_tracking_mtd_set_lost")]
pub fn set_lost(&mut self) -> Result<(), glib::BoolError> {
let ret: bool = unsafe {
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
from_glib(ffi::gst_analytics_tracking_mtd_set_lost(&mut mtd))
};
assert!(ret);
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn tracking() {
gst::init().unwrap();
assert_eq!(AnalyticsTrackingMtd::type_name(), "object-tracking");
let mut buf = gst::Buffer::new();
let mut meta = AnalyticsRelationMeta::add(buf.make_mut());
assert!(meta.is_empty());
let track = meta
.add_tracking_mtd(10, gst::ClockTime::from_seconds(10))
.unwrap();
let (tracking_id, tracking_first_seen, tracking_last_seen, tracking_lost) = track.info();
assert_eq!(tracking_id, 10);
assert_eq!(tracking_first_seen, gst::ClockTime::from_seconds(10));
assert_eq!(tracking_last_seen, gst::ClockTime::from_seconds(10));
assert!(!tracking_lost);
let track_id = track.id();
let mut tracking_mut = meta.mtd_mut::<AnalyticsTrackingMtd>(track_id).unwrap();
tracking_mut
.update_last_seen(gst::ClockTime::from_seconds(20))
.unwrap();
tracking_mut.set_lost().unwrap();
let tracking: AnalyticsMtdRef<_> = tracking_mut.into();
let (tracking_id, tracking_first_seen, tracking_last_seen, tracking_lost) = tracking.info();
assert_eq!(tracking_id, 10);
assert_eq!(tracking_first_seen, gst::ClockTime::from_seconds(10));
assert_eq!(tracking_last_seen, gst::ClockTime::from_seconds(20));
assert!(tracking_lost);
}
}

View file

@ -0,0 +1 @@
../../gstreamer/CHANGELOG.md

View file

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

View file

@ -0,0 +1,57 @@
[build-dependencies]
system-deps = "6"
[dependencies]
libc = "0.2"
[dependencies.glib-sys]
workspace = true
[dependencies.gstreamer-sys]
workspace = true
[dev-dependencies]
shell-words = "1.0.0"
tempfile = "3"
[lib]
name = "gstreamer_analytics_sys"
[package]
authors = ["Olivier Crête <olivier.crete@collabora.com"]
build = "build.rs"
description = "FFI bindings to libgstanalytics-1.0"
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_analytics_sys/"
keywords = ["ffi", "gstreamer", "gnome", "multimedia"]
license = "MIT"
name = "gstreamer-analytics-sys"
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.docs.rs]
all-features = true
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]
[package.metadata.system-deps.gstreamer_analytics_1_0]
name = "gstreamer-analytics-1.0"
version = "1.23"
[features]

View file

@ -0,0 +1,48 @@
[options]
girs_directories = ["../../gir-files", "../../gst-gir-files"]
library = "GstAnalytics"
version = "1.0"
min_cfg_version = "1.24"
work_mode = "sys"
single_version_file = true
external_libraries = [
"GLib",
]
manual = [
"GObject.Object",
"Gst.Element",
"Gst.MiniObject",
"Gst.Object",
]
[external_libraries]
gstreamer="Gst"
[[object]]
name = "GstAnalytics.RelationMeta"
status = "generate"
[[object.function]]
name = "relation_meta_api_get_type"
version = "1.24"
[[object]]
name = "GstAnalytics.ClsMtd"
status = "generate"
boxed_inline = true
[[object]]
name = "GstAnalytics.TrackingMtd"
status = "generate"
boxed_inline = true
[[object]]
name = "GstAnalytics.ODMtd"
status = "generate"
boxed_inline = true
[[object]]
name = "GstAnalytics.Mtd"
status = "generate"
boxed_inline = true

View file

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

View file

@ -0,0 +1,31 @@
# gstreamer-sys [![crates.io](https://img.shields.io/crates/v/gstreamer-app-sys.svg)](https://crates.io/crates/gstreamer-app-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/) (App 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.

View file

@ -0,0 +1,18 @@
// 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(not(docsrs))]
use std::process;
#[cfg(docsrs)]
fn main() {} // prevent linking libraries to avoid documentation failure
#[cfg(not(docsrs))]
fn main() {
if let Err(s) = system_deps::Config::new().probe() {
println!("cargo:warning={s}");
process::exit(1);
}
}

View file

@ -0,0 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -0,0 +1,337 @@
// 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
#![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(docsrs, feature(doc_cfg))]
use glib_sys as glib;
use gstreamer_sys as gst;
#[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};
// Aliases
pub type GstAnalyticsMtdType = uintptr_t;
// Constants
pub const GST_AN_RELATION_META_TAG: &[u8] = b"GST-ANALYSIS-RELATION-META-TAG\0";
pub const GST_INF_RELATION_SPAN: c_int = -1;
pub const GST_ANALYTICS_MTD_TYPE_ANY: c_int = 0;
// Flags
pub type GstAnalyticsRelTypes = c_uint;
pub const GST_ANALYTICS_REL_TYPE_NONE: GstAnalyticsRelTypes = 0;
pub const GST_ANALYTICS_REL_TYPE_IS_PART_OF: GstAnalyticsRelTypes = 2;
pub const GST_ANALYTICS_REL_TYPE_CONTAIN: GstAnalyticsRelTypes = 4;
pub const GST_ANALYTICS_REL_TYPE_RELATE_TO: GstAnalyticsRelTypes = 8;
pub const GST_ANALYTICS_REL_TYPE_LAST: GstAnalyticsRelTypes = 16;
pub const GST_ANALYTICS_REL_TYPE_ANY: GstAnalyticsRelTypes = 2147483647;
// Records
#[derive(Copy, Clone)]
#[repr(C)]
pub struct GstAnalyticsClsMtd {
pub id: c_uint,
pub meta: *mut GstAnalyticsRelationMeta,
}
impl ::std::fmt::Debug for GstAnalyticsClsMtd {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(&format!("GstAnalyticsClsMtd @ {self:p}"))
.field("id", &self.id)
.field("meta", &self.meta)
.finish()
}
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct GstAnalyticsMtd {
pub id: c_uint,
pub meta: *mut GstAnalyticsRelationMeta,
}
impl ::std::fmt::Debug for GstAnalyticsMtd {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(&format!("GstAnalyticsMtd @ {self:p}"))
.field("id", &self.id)
.field("meta", &self.meta)
.finish()
}
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct GstAnalyticsMtdImpl {
pub name: *const c_char,
pub mtd_meta_transform: Option<
unsafe extern "C" fn(
*mut gst::GstBuffer,
*mut GstAnalyticsMtd,
*mut gst::GstBuffer,
glib::GQuark,
gpointer,
) -> gboolean,
>,
pub _reserved: [gpointer; 20],
}
impl ::std::fmt::Debug for GstAnalyticsMtdImpl {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(&format!("GstAnalyticsMtdImpl @ {self:p}"))
.field("name", &self.name)
.field("mtd_meta_transform", &self.mtd_meta_transform)
.field("_reserved", &self._reserved)
.finish()
}
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct GstAnalyticsODMtd {
pub id: c_uint,
pub meta: *mut GstAnalyticsRelationMeta,
}
impl ::std::fmt::Debug for GstAnalyticsODMtd {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(&format!("GstAnalyticsODMtd @ {self:p}"))
.field("id", &self.id)
.field("meta", &self.meta)
.finish()
}
}
#[repr(C)]
pub struct _GstAnalyticsRelationMeta {
_data: [u8; 0],
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}
pub type GstAnalyticsRelationMeta = _GstAnalyticsRelationMeta;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct GstAnalyticsRelationMetaInitParams {
pub initial_relation_order: size_t,
pub initial_buf_size: size_t,
}
impl ::std::fmt::Debug for GstAnalyticsRelationMetaInitParams {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(&format!("GstAnalyticsRelationMetaInitParams @ {self:p}"))
.field("initial_relation_order", &self.initial_relation_order)
.field("initial_buf_size", &self.initial_buf_size)
.finish()
}
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct GstAnalyticsTrackingMtd {
pub id: c_uint,
pub meta: *mut GstAnalyticsRelationMeta,
}
impl ::std::fmt::Debug for GstAnalyticsTrackingMtd {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(&format!("GstAnalyticsTrackingMtd @ {self:p}"))
.field("id", &self.id)
.field("meta", &self.meta)
.finish()
}
}
#[link(name = "gstanalytics-1.0")]
extern "C" {
//=========================================================================
// GstAnalyticsClsMtd
//=========================================================================
pub fn gst_analytics_cls_mtd_get_index_by_quark(
handle: *mut GstAnalyticsClsMtd,
quark: glib::GQuark,
) -> c_int;
pub fn gst_analytics_cls_mtd_get_length(handle: *mut GstAnalyticsClsMtd) -> size_t;
pub fn gst_analytics_cls_mtd_get_level(
handle: *mut GstAnalyticsClsMtd,
index: size_t,
) -> c_float;
pub fn gst_analytics_cls_mtd_get_quark(
handle: *mut GstAnalyticsClsMtd,
index: size_t,
) -> glib::GQuark;
pub fn gst_analytics_cls_mtd_get_mtd_type() -> GstAnalyticsMtdType;
//=========================================================================
// GstAnalyticsMtd
//=========================================================================
pub fn gst_analytics_mtd_get_id(instance: *mut GstAnalyticsMtd) -> c_uint;
pub fn gst_analytics_mtd_get_mtd_type(instance: *mut GstAnalyticsMtd) -> GstAnalyticsMtdType;
pub fn gst_analytics_mtd_get_size(instance: *mut GstAnalyticsMtd) -> size_t;
pub fn gst_analytics_mtd_type_get_name(type_: GstAnalyticsMtdType) -> *const c_char;
//=========================================================================
// GstAnalyticsODMtd
//=========================================================================
pub fn gst_analytics_od_mtd_get_confidence_lvl(
instance: *mut GstAnalyticsODMtd,
loc_conf_lvl: *mut c_float,
) -> gboolean;
pub fn gst_analytics_od_mtd_get_location(
instance: *mut GstAnalyticsODMtd,
x: *mut c_int,
y: *mut c_int,
w: *mut c_int,
h: *mut c_int,
loc_conf_lvl: *mut c_float,
) -> gboolean;
pub fn gst_analytics_od_mtd_get_obj_type(handle: *mut GstAnalyticsODMtd) -> glib::GQuark;
pub fn gst_analytics_od_mtd_get_mtd_type() -> GstAnalyticsMtdType;
//=========================================================================
// GstAnalyticsRelationMeta
//=========================================================================
pub fn gst_analytics_relation_meta_add_cls_mtd(
instance: *mut GstAnalyticsRelationMeta,
length: size_t,
confidence_levels: *mut c_float,
class_quarks: *mut glib::GQuark,
cls_mtd: *mut GstAnalyticsClsMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_add_mtd(
meta: *mut GstAnalyticsRelationMeta,
impl_: *const GstAnalyticsMtdImpl,
size: size_t,
rlt_mtd: *mut GstAnalyticsMtd,
) -> gpointer;
pub fn gst_analytics_relation_meta_add_od_mtd(
instance: *mut GstAnalyticsRelationMeta,
type_: glib::GQuark,
x: c_int,
y: c_int,
w: c_int,
h: c_int,
loc_conf_lvl: c_float,
od_mtd: *mut GstAnalyticsODMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_add_one_cls_mtd(
instance: *mut GstAnalyticsRelationMeta,
confidence_level: c_float,
class_quark: glib::GQuark,
cls_mtd: *mut GstAnalyticsClsMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_add_tracking_mtd(
instance: *mut GstAnalyticsRelationMeta,
tracking_id: u64,
tracking_first_seen: gst::GstClockTime,
trk_mtd: *mut GstAnalyticsTrackingMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_exist(
rmeta: *mut GstAnalyticsRelationMeta,
an_meta_first_id: c_uint,
an_meta_second_id: c_uint,
max_relation_span: c_int,
cond_types: GstAnalyticsRelTypes,
relations_path: *mut *mut glib::GArray,
) -> gboolean;
pub fn gst_analytics_relation_meta_get_cls_mtd(
meta: *mut GstAnalyticsRelationMeta,
an_meta_id: c_uint,
rlt: *mut GstAnalyticsClsMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_get_direct_related(
meta: *mut GstAnalyticsRelationMeta,
an_meta_id: c_uint,
relation_type: GstAnalyticsRelTypes,
type_: GstAnalyticsMtdType,
state: *mut gpointer,
rlt_mtd: *mut GstAnalyticsMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_get_mtd(
meta: *mut GstAnalyticsRelationMeta,
an_meta_id: c_uint,
type_: GstAnalyticsMtdType,
rlt: *mut GstAnalyticsMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_get_mtd_data(
meta: *mut GstAnalyticsRelationMeta,
an_meta_id: c_uint,
) -> gpointer;
pub fn gst_analytics_relation_meta_get_od_mtd(
meta: *mut GstAnalyticsRelationMeta,
an_meta_id: c_uint,
rlt: *mut GstAnalyticsODMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_get_relation(
meta: *mut GstAnalyticsRelationMeta,
an_meta_first_id: c_uint,
an_meta_second_id: c_uint,
) -> GstAnalyticsRelTypes;
pub fn gst_analytics_relation_meta_get_tracking_mtd(
meta: *mut GstAnalyticsRelationMeta,
an_meta_id: c_uint,
rlt: *mut GstAnalyticsTrackingMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_iterate(
meta: *mut GstAnalyticsRelationMeta,
state: *mut gpointer,
type_: GstAnalyticsMtdType,
rlt_mtd: *mut GstAnalyticsMtd,
) -> gboolean;
pub fn gst_analytics_relation_meta_set_relation(
meta: *mut GstAnalyticsRelationMeta,
type_: GstAnalyticsRelTypes,
an_meta_first_id: c_uint,
an_meta_second_id: c_uint,
) -> gboolean;
pub fn gst_analytics_relation_meta_get_info() -> *const gst::GstMetaInfo;
//=========================================================================
// GstAnalyticsTrackingMtd
//=========================================================================
pub fn gst_analytics_tracking_mtd_get_info(
instance: *mut GstAnalyticsTrackingMtd,
tracking_id: *mut u64,
tracking_first_seen: *mut gst::GstClockTime,
tracking_last_seen: *mut gst::GstClockTime,
tracking_lost: *mut gboolean,
) -> gboolean;
pub fn gst_analytics_tracking_mtd_set_lost(instance: *mut GstAnalyticsTrackingMtd) -> gboolean;
pub fn gst_analytics_tracking_mtd_update_last_seen(
instance: *mut GstAnalyticsTrackingMtd,
last_seen: gst::GstClockTime,
) -> gboolean;
pub fn gst_analytics_tracking_mtd_get_mtd_type() -> GstAnalyticsMtdType;
//=========================================================================
// Other functions
//=========================================================================
pub fn gst_buffer_add_analytics_relation_meta(
buffer: *mut gst::GstBuffer,
) -> *mut GstAnalyticsRelationMeta;
pub fn gst_buffer_add_analytics_relation_meta_full(
buffer: *mut gst::GstBuffer,
init_params: *mut GstAnalyticsRelationMetaInitParams,
) -> *mut GstAnalyticsRelationMeta;
pub fn gst_buffer_get_analytics_relation_meta(
buffer: *mut gst::GstBuffer,
) -> *mut GstAnalyticsRelationMeta;
pub fn gst_analytics_relation_get_length(instance: *mut GstAnalyticsRelationMeta) -> size_t;
pub fn gst_analytics_relation_meta_api_get_type() -> GType;
}

View file

@ -0,0 +1,273 @@
// 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(unix)]
use gstreamer_analytics_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, Stdio};
use std::str;
use tempfile::Builder;
static PACKAGES: &[&str] = &["gstreamer-analytics-1.0"];
#[derive(Clone, Debug)]
struct Compiler {
pub args: Vec<String>,
}
impl Compiler {
pub fn new() -> Result<Self, Box<dyn Error>> {
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<dyn Error>> {
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 {cmd:?} failed, {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<Vec<String>, Box<dyn Error>> {
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<Vec<String>, Box<dyn Error>> {
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);
cmd.stderr(Stdio::inherit());
let out = cmd.output()?;
if !out.status.success() {
let (status, stdout) = (out.status, String::from_utf8_lossy(&out.stdout));
return Err(format!("command {cmd:?} failed, {status:?}\nstdout: {stdout}").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]
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 (name, value) = l.split_once(';').expect("Missing ';' separator");
c_constants.push((name.to_owned(), value.to_owned()));
}
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: {rust_name:?}\nC: {c_name:?}");
continue;
}
if rust_value != c_value {
results.record_failed();
eprintln!(
"Constant value mismatch for {rust_name}\nRust: {rust_value:?}\nC: {c_value:?}",
);
continue;
}
results.record_passed();
}
results.expect_total_success();
}
#[test]
fn cross_validate_layout_with_c() {
let mut c_layouts = Vec::new();
for l in get_c_output("layout").unwrap().lines() {
let (name, value) = l.split_once(';').expect("Missing first ';' separator");
let (size, alignment) = value.split_once(';').expect("Missing second ';' separator");
let size = size.parse().expect("Failed to parse size");
let alignment = alignment.parse().expect("Failed to parse alignment");
c_layouts.push((name.to_owned(), 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: {rust_name:?}\nC: {c_name:?}");
continue;
}
if rust_layout != c_layout {
results.record_failed();
eprintln!("Layout mismatch for {rust_name}\nRust: {rust_layout:?}\nC: {c_layout:?}",);
continue;
}
results.record_passed();
}
results.expect_total_success();
}
fn get_c_output(name: &str) -> Result<String, Box<dyn Error>> {
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 cmd = Command::new(exe);
cmd.stderr(Stdio::inherit());
let out = cmd.output()?;
if !out.status.success() {
let (status, stdout) = (out.status, String::from_utf8_lossy(&out.stdout));
return Err(format!("command {cmd:?} failed, {status:?}\nstdout: {stdout}").into());
}
Ok(String::from_utf8(out.stdout)?)
}
const RUST_LAYOUTS: &[(&str, Layout)] = &[
(
"GstAnalyticsClsMtd",
Layout {
size: size_of::<GstAnalyticsClsMtd>(),
alignment: align_of::<GstAnalyticsClsMtd>(),
},
),
(
"GstAnalyticsMtd",
Layout {
size: size_of::<GstAnalyticsMtd>(),
alignment: align_of::<GstAnalyticsMtd>(),
},
),
(
"GstAnalyticsMtdImpl",
Layout {
size: size_of::<GstAnalyticsMtdImpl>(),
alignment: align_of::<GstAnalyticsMtdImpl>(),
},
),
(
"GstAnalyticsMtdType",
Layout {
size: size_of::<GstAnalyticsMtdType>(),
alignment: align_of::<GstAnalyticsMtdType>(),
},
),
(
"GstAnalyticsODMtd",
Layout {
size: size_of::<GstAnalyticsODMtd>(),
alignment: align_of::<GstAnalyticsODMtd>(),
},
),
(
"GstAnalyticsRelTypes",
Layout {
size: size_of::<GstAnalyticsRelTypes>(),
alignment: align_of::<GstAnalyticsRelTypes>(),
},
),
(
"GstAnalyticsRelationMetaInitParams",
Layout {
size: size_of::<GstAnalyticsRelationMetaInitParams>(),
alignment: align_of::<GstAnalyticsRelationMetaInitParams>(),
},
),
(
"GstAnalyticsTrackingMtd",
Layout {
size: size_of::<GstAnalyticsTrackingMtd>(),
alignment: align_of::<GstAnalyticsTrackingMtd>(),
},
),
];
const RUST_CONSTANTS: &[(&str, &str)] = &[
("GST_ANALYTICS_MTD_TYPE_ANY", "0"),
("(guint) GST_ANALYTICS_REL_TYPE_ANY", "2147483647"),
("(guint) GST_ANALYTICS_REL_TYPE_CONTAIN", "4"),
("(guint) GST_ANALYTICS_REL_TYPE_IS_PART_OF", "2"),
("(guint) GST_ANALYTICS_REL_TYPE_LAST", "16"),
("(guint) GST_ANALYTICS_REL_TYPE_NONE", "0"),
("(guint) GST_ANALYTICS_REL_TYPE_RELATE_TO", "8"),
("GST_AN_RELATION_META_TAG", "GST-ANALYSIS-RELATION-META-TAG"),
("GST_INF_RELATION_SPAN", "-1"),
];

View file

@ -0,0 +1,42 @@
// 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
#include "manual.h"
#include <stdio.h>
#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_ANALYTICS_MTD_TYPE_ANY);
PRINT_CONSTANT((guint) GST_ANALYTICS_REL_TYPE_ANY);
PRINT_CONSTANT((guint) GST_ANALYTICS_REL_TYPE_CONTAIN);
PRINT_CONSTANT((guint) GST_ANALYTICS_REL_TYPE_IS_PART_OF);
PRINT_CONSTANT((guint) GST_ANALYTICS_REL_TYPE_LAST);
PRINT_CONSTANT((guint) GST_ANALYTICS_REL_TYPE_NONE);
PRINT_CONSTANT((guint) GST_ANALYTICS_REL_TYPE_RELATE_TO);
PRINT_CONSTANT(GST_AN_RELATION_META_TAG);
PRINT_CONSTANT(GST_INF_RELATION_SPAN);
return 0;
}

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
#include "manual.h"
#include <stdalign.h>
#include <stdio.h>
int main() {
printf("%s;%zu;%zu\n", "GstAnalyticsClsMtd", sizeof(GstAnalyticsClsMtd), alignof(GstAnalyticsClsMtd));
printf("%s;%zu;%zu\n", "GstAnalyticsMtd", sizeof(GstAnalyticsMtd), alignof(GstAnalyticsMtd));
printf("%s;%zu;%zu\n", "GstAnalyticsMtdImpl", sizeof(GstAnalyticsMtdImpl), alignof(GstAnalyticsMtdImpl));
printf("%s;%zu;%zu\n", "GstAnalyticsMtdType", sizeof(GstAnalyticsMtdType), alignof(GstAnalyticsMtdType));
printf("%s;%zu;%zu\n", "GstAnalyticsODMtd", sizeof(GstAnalyticsODMtd), alignof(GstAnalyticsODMtd));
printf("%s;%zu;%zu\n", "GstAnalyticsRelTypes", sizeof(GstAnalyticsRelTypes), alignof(GstAnalyticsRelTypes));
printf("%s;%zu;%zu\n", "GstAnalyticsRelationMetaInitParams", sizeof(GstAnalyticsRelationMetaInitParams), alignof(GstAnalyticsRelationMetaInitParams));
printf("%s;%zu;%zu\n", "GstAnalyticsTrackingMtd", sizeof(GstAnalyticsTrackingMtd), alignof(GstAnalyticsTrackingMtd));
return 0;
}

View file

@ -0,0 +1,3 @@
// Feel free to edit this file, it won't be regenerated by gir generator unless removed.
#include <gst/analytics/analytics.h>

View file

@ -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);
}

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)

View file

@ -1,3 +1,3 @@
Generated by gir (https://github.com/gtk-rs/gir @ 5975266da3b0)
from gir-files (https://github.com/gtk-rs/gir-files @ fe8258109e60)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 3f9f549accb7)
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 63e90a30193b)