forked from mirrors/gstreamer-rs
Compare commits
108 commits
Author | SHA1 | Date | |
---|---|---|---|
|
6359c2ddf0 | ||
|
8017fa541a | ||
|
9f7eae9693 | ||
|
8c286faaa6 | ||
|
0f6bbcfb6c | ||
|
35ce5d1494 | ||
|
42c028672f | ||
|
2871edeca7 | ||
|
5c8c29f7e4 | ||
|
593de5c551 | ||
|
02f4e7dad0 | ||
|
9f3ae6aa77 | ||
|
ef84e3e71b | ||
|
bd3a053ff1 | ||
|
d1be4756b0 | ||
|
80eaa01ce8 | ||
|
7ea168a6a0 | ||
|
eedac4642c | ||
|
48ee57c63f | ||
|
e982c07255 | ||
|
fc3fb363e7 | ||
|
70ee948623 | ||
|
25e13209db | ||
|
c0a4545c83 | ||
|
408e97ad70 | ||
|
a4c3a484cf | ||
|
db82a4d591 | ||
|
7324d27869 | ||
|
12fd38a33e | ||
|
01c4151870 | ||
|
36f13a8007 | ||
|
905a0b6887 | ||
|
6b95762ea7 | ||
|
cb40917ac9 | ||
|
4c0f03d5fd | ||
|
07d9fba822 | ||
|
8e4a561a41 | ||
|
40637647b9 | ||
|
9b92261c42 | ||
|
a97de245c9 | ||
|
5abf146212 | ||
|
763cddfba6 | ||
|
df223af719 | ||
|
27380d237c | ||
|
cb150485b1 | ||
|
7d77858bc8 | ||
|
437ec48ae1 | ||
|
03c4721aa3 | ||
|
0a82caa706 | ||
|
470b727252 | ||
|
8027269c7b | ||
|
6f52f3e4fa | ||
|
db2b39d382 | ||
|
66e822dbf7 | ||
|
c5262fa69f | ||
|
08ce9f5b2f | ||
|
de87e6061e | ||
|
c2b5341b8f | ||
|
43096963de | ||
|
3b30546461 | ||
|
7975383e96 | ||
|
d3e54789fe | ||
|
f2a5960c36 | ||
|
b1c7d225b1 | ||
|
08efe21002 | ||
|
e531c7f565 | ||
|
7622ceb03a | ||
|
bc69e3dafd | ||
|
7b6ae13008 | ||
|
71bbcc00e2 | ||
|
7d5f8e95bf | ||
|
c407ce825d | ||
|
11699fda0f | ||
|
4e9b155b90 | ||
|
66a0e36e22 | ||
|
f525e7cea7 | ||
|
6a41f4b9b5 | ||
|
44facc5a82 | ||
|
1a4a725793 | ||
|
e1fd8b36c8 | ||
|
73a6aa1f26 | ||
|
6c6384e9cd | ||
|
3c7ace5451 | ||
|
fcad4e5aa3 | ||
|
8c384e387a | ||
|
f8893ec6fb | ||
|
acae1d6037 | ||
|
4cefb512cd | ||
|
ee176b9b07 | ||
|
ac5eeb7259 | ||
|
f5dc2578fa | ||
|
2507d8262f | ||
|
8c40e8b5b8 | ||
|
411b1802ba | ||
|
c38dd726a7 | ||
|
682d0a1ac6 | ||
|
d10b1b2722 | ||
|
b0e5419d7d | ||
|
fd40a98f8c | ||
|
f53b78a0cb | ||
|
5022d85b83 | ||
|
639dbcd6bb | ||
|
7f773090ce | ||
|
cee6d20ad8 | ||
|
9d8fbb7d7c | ||
|
214f050a24 | ||
|
4988cc7bb2 | ||
|
5b928af1f5 |
591 changed files with 5175 additions and 15048 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
target/
|
target/
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
||||||
|
|
|
@ -56,7 +56,7 @@ variables:
|
||||||
# latest release must be at the top
|
# latest release must be at the top
|
||||||
# (only relevant on main branch)
|
# (only relevant on main branch)
|
||||||
RELEASES:
|
RELEASES:
|
||||||
0.22=0.22
|
0.21=0.21
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- "trigger"
|
- "trigger"
|
||||||
|
@ -73,7 +73,6 @@ trigger:
|
||||||
stage: 'trigger'
|
stage: 'trigger'
|
||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: none
|
GIT_STRATEGY: none
|
||||||
tags: [ 'placeholder-job' ]
|
|
||||||
script:
|
script:
|
||||||
- echo "Trigger job done, now running the pipeline."
|
- echo "Trigger job done, now running the pipeline."
|
||||||
rules:
|
rules:
|
||||||
|
@ -142,7 +141,6 @@ trigger:
|
||||||
libpango1.0-dev libcairo2-dev libjson-glib-dev libgdk-pixbuf-2.0-dev
|
libpango1.0-dev libcairo2-dev libjson-glib-dev libgdk-pixbuf-2.0-dev
|
||||||
libtiff-dev libpng-dev libjpeg-dev libepoxy-dev libsass-dev sassc
|
libtiff-dev libpng-dev libjpeg-dev libepoxy-dev libsass-dev sassc
|
||||||
libcsound64-dev llvm clang nasm libsodium-dev libwebp-dev
|
libcsound64-dev llvm clang nasm libsodium-dev libwebp-dev
|
||||||
libflac-dev
|
|
||||||
FDO_DISTRIBUTION_EXEC: >-
|
FDO_DISTRIBUTION_EXEC: >-
|
||||||
bash ci/install-gst.sh &&
|
bash ci/install-gst.sh &&
|
||||||
bash ci/install-dav1d.sh &&
|
bash ci/install-dav1d.sh &&
|
||||||
|
@ -313,7 +311,6 @@ test nightly sys:
|
||||||
rustfmt:
|
rustfmt:
|
||||||
extends: .img-stable
|
extends: .img-stable
|
||||||
stage: "lint"
|
stage: "lint"
|
||||||
tags: [ 'placeholder-job' ]
|
|
||||||
script:
|
script:
|
||||||
- cargo fmt --version
|
- cargo fmt --version
|
||||||
- cargo fmt -- --color=always --check
|
- cargo fmt -- --color=always --check
|
||||||
|
@ -324,7 +321,6 @@ rustfmt:
|
||||||
check commits:
|
check commits:
|
||||||
extends: .img-stable
|
extends: .img-stable
|
||||||
stage: "lint"
|
stage: "lint"
|
||||||
tags: [ 'placeholder-job' ]
|
|
||||||
script:
|
script:
|
||||||
- ci-fairy check-commits --textwidth 0 --no-signed-off-by
|
- ci-fairy check-commits --textwidth 0 --no-signed-off-by
|
||||||
needs:
|
needs:
|
||||||
|
@ -334,7 +330,6 @@ check commits:
|
||||||
typos:
|
typos:
|
||||||
extends: .img-stable
|
extends: .img-stable
|
||||||
stage: "lint"
|
stage: "lint"
|
||||||
tags: [ 'placeholder-job' ]
|
|
||||||
script:
|
script:
|
||||||
- typos
|
- typos
|
||||||
needs:
|
needs:
|
||||||
|
@ -363,7 +358,6 @@ deny:
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||||
script:
|
script:
|
||||||
- cargo update --color=always
|
|
||||||
- cargo deny --color=always --workspace --all-features check all
|
- cargo deny --color=always --workspace --all-features check all
|
||||||
|
|
||||||
gir-checks:
|
gir-checks:
|
||||||
|
@ -371,7 +365,6 @@ gir-checks:
|
||||||
GIT_SUBMODULE_STRATEGY: recursive
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
extends: .img-stable
|
extends: .img-stable
|
||||||
stage: 'extras'
|
stage: 'extras'
|
||||||
tags: [ 'placeholder-job' ]
|
|
||||||
needs:
|
needs:
|
||||||
- job: 'build-stable'
|
- job: 'build-stable'
|
||||||
artifacts: false
|
artifacts: false
|
||||||
|
@ -388,7 +381,6 @@ outdated:
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||||
script:
|
script:
|
||||||
- cargo update --color=always
|
|
||||||
- cargo outdated --color=always --root-deps-only --exit-code 1 -v
|
- cargo outdated --color=always --root-deps-only --exit-code 1 -v
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
|
@ -514,6 +506,7 @@ pages:
|
||||||
# We also don't need a CONTEXT_DIR var as its also
|
# We also don't need a CONTEXT_DIR var as its also
|
||||||
# hardcoded to be windows-docker/
|
# hardcoded to be windows-docker/
|
||||||
DOCKERFILE: 'ci/windows-docker/Dockerfile'
|
DOCKERFILE: 'ci/windows-docker/Dockerfile'
|
||||||
|
GST_UPSTREAM_BRANCH: 'main'
|
||||||
tags:
|
tags:
|
||||||
- 'windows'
|
- 'windows'
|
||||||
- 'shell'
|
- 'shell'
|
||||||
|
|
1021
Cargo.lock
generated
1021
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
51
Cargo.toml
51
Cargo.toml
|
@ -3,7 +3,6 @@ resolver = "2"
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
"gstreamer/sys",
|
"gstreamer/sys",
|
||||||
"gstreamer-analytics/sys",
|
|
||||||
"gstreamer-app/sys",
|
"gstreamer-app/sys",
|
||||||
"gstreamer-audio/sys",
|
"gstreamer-audio/sys",
|
||||||
"gstreamer-base/sys",
|
"gstreamer-base/sys",
|
||||||
|
@ -23,7 +22,6 @@ default-members = [
|
||||||
"gstreamer-video/sys",
|
"gstreamer-video/sys",
|
||||||
"gstreamer-webrtc/sys",
|
"gstreamer-webrtc/sys",
|
||||||
"gstreamer",
|
"gstreamer",
|
||||||
"gstreamer-analytics",
|
|
||||||
"gstreamer-app",
|
"gstreamer-app",
|
||||||
"gstreamer-audio",
|
"gstreamer-audio",
|
||||||
"gstreamer-base",
|
"gstreamer-base",
|
||||||
|
@ -39,7 +37,6 @@ default-members = [
|
||||||
"gstreamer-rtsp",
|
"gstreamer-rtsp",
|
||||||
"gstreamer-rtsp-server",
|
"gstreamer-rtsp-server",
|
||||||
"gstreamer-sdp",
|
"gstreamer-sdp",
|
||||||
"gstreamer-tag",
|
|
||||||
"gstreamer-validate",
|
"gstreamer-validate",
|
||||||
"gstreamer-video",
|
"gstreamer-video",
|
||||||
"gstreamer-webrtc",
|
"gstreamer-webrtc",
|
||||||
|
@ -49,7 +46,6 @@ default-members = [
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"gstreamer/sys",
|
"gstreamer/sys",
|
||||||
"gstreamer-analytics/sys",
|
|
||||||
"gstreamer-app/sys",
|
"gstreamer-app/sys",
|
||||||
"gstreamer-audio/sys",
|
"gstreamer-audio/sys",
|
||||||
"gstreamer-base/sys",
|
"gstreamer-base/sys",
|
||||||
|
@ -74,7 +70,6 @@ members = [
|
||||||
"gstreamer-webrtc/sys",
|
"gstreamer-webrtc/sys",
|
||||||
"gstreamer-allocators/sys",
|
"gstreamer-allocators/sys",
|
||||||
"gstreamer",
|
"gstreamer",
|
||||||
"gstreamer-analytics",
|
|
||||||
"gstreamer-app",
|
"gstreamer-app",
|
||||||
"gstreamer-audio",
|
"gstreamer-audio",
|
||||||
"gstreamer-base",
|
"gstreamer-base",
|
||||||
|
@ -94,7 +89,6 @@ members = [
|
||||||
"gstreamer-rtsp",
|
"gstreamer-rtsp",
|
||||||
"gstreamer-rtsp-server",
|
"gstreamer-rtsp-server",
|
||||||
"gstreamer-sdp",
|
"gstreamer-sdp",
|
||||||
"gstreamer-tag",
|
|
||||||
"gstreamer-validate",
|
"gstreamer-validate",
|
||||||
"gstreamer-video",
|
"gstreamer-video",
|
||||||
"gstreamer-webrtc",
|
"gstreamer-webrtc",
|
||||||
|
@ -105,48 +99,3 @@ members = [
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = ["gir"]
|
exclude = ["gir"]
|
||||||
|
|
||||||
[workspace.package]
|
|
||||||
version = "0.23.0"
|
|
||||||
categories = ["api-bindings", "multimedia"]
|
|
||||||
repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs"
|
|
||||||
homepage = "https://gstreamer.freedesktop.org"
|
|
||||||
edition = "2021"
|
|
||||||
rust-version = "1.70"
|
|
||||||
|
|
||||||
[workspace.dependencies]
|
|
||||||
gio = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
gio-sys = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
glib = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
glib-sys = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
gobject-sys = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
cairo-rs = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
pango = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
pangocairo = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "master" }
|
|
||||||
gstreamer-audio-sys = { path = "./gstreamer-audio/sys"}
|
|
||||||
gstreamer-base-sys = { path = "./gstreamer-base/sys"}
|
|
||||||
gstreamer-gl-sys = { path = "./gstreamer-gl/sys"}
|
|
||||||
gstreamer-net-sys = { path = "./gstreamer-net/sys"}
|
|
||||||
gstreamer-pbutils-sys = { path = "./gstreamer-pbutils/sys"}
|
|
||||||
gstreamer-rtsp-sys = { path = "./gstreamer-rtsp/sys"}
|
|
||||||
gstreamer-sdp-sys = { path = "./gstreamer-sdp/sys"}
|
|
||||||
gstreamer-sys = { path = "./gstreamer/sys"}
|
|
||||||
gstreamer-video-sys = { path = "./gstreamer-video/sys"}
|
|
||||||
ges = { package = "gstreamer-editing-services", path = "./gstreamer-editing-services" }
|
|
||||||
gst = { package = "gstreamer", path = "./gstreamer" }
|
|
||||||
gst-allocators = { package = "gstreamer-allocators", path = "./gstreamer-allocators" }
|
|
||||||
gst-app = { package = "gstreamer-app", path = "./gstreamer-app" }
|
|
||||||
gst-audio = { package = "gstreamer-audio", path = "./gstreamer-audio" }
|
|
||||||
gst-base = { package = "gstreamer-base", path = "./gstreamer-base" }
|
|
||||||
gst-check = { package = "gstreamer-check", path = "./gstreamer-check" }
|
|
||||||
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-pbutils = { package = "gstreamer-pbutils", path = "./gstreamer-pbutils" }
|
|
||||||
gst-play = { package = "gstreamer-play", path = "./gstreamer-play" }
|
|
||||||
gst-player = { package = "gstreamer-player", path = "./gstreamer-player" }
|
|
||||||
gst-rtsp = { package = "gstreamer-rtsp", path = "./gstreamer-rtsp" }
|
|
||||||
gst-rtsp-server = { package = "gstreamer-rtsp-server", path = "./gstreamer-rtsp-server" }
|
|
||||||
gst-sdp = { package = "gstreamer-sdp", path = "./gstreamer-sdp" }
|
|
||||||
gst-video = { package = "gstreamer-video", path = "./gstreamer-video" }
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
variables:
|
variables:
|
||||||
GST_RS_IMG_TAG: "2024-05-10.0"
|
GST_RS_IMG_TAG: "2023-11-16.0"
|
||||||
GST_RS_STABLE: "1.78.0"
|
GST_RS_STABLE: "1.74.0"
|
||||||
GST_RS_MSRV: "1.70.0"
|
GST_RS_MSRV: "1.70.0"
|
||||||
# The branch we use to build GStreamer from in the docker images
|
|
||||||
# Ex. main, 1.24, my-test-branch
|
|
||||||
GST_UPSTREAM_BRANCH: 'main'
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
RELEASE=1.4.1
|
RELEASE=1.1.0
|
||||||
|
|
||||||
git clone https://code.videolan.org/videolan/dav1d.git --branch $RELEASE
|
git clone https://code.videolan.org/videolan/dav1d.git --branch $RELEASE
|
||||||
cd dav1d
|
cd dav1d
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
DEFAULT_BRANCH="$GST_UPSTREAM_BRANCH"
|
|
||||||
|
|
||||||
pip3 install meson==1.1.1 --break-system-packages
|
pip3 install meson==1.1.1 --break-system-packages
|
||||||
|
|
||||||
# gstreamer-rs already has a 'gstreamer' directory so don't clone there
|
# gstreamer-rs already has a 'gstreamer' directory so don't clone there
|
||||||
|
@ -11,7 +9,7 @@ pushd .
|
||||||
cd ..
|
cd ..
|
||||||
git clone https://gitlab.freedesktop.org/gstreamer/gstreamer.git \
|
git clone https://gitlab.freedesktop.org/gstreamer/gstreamer.git \
|
||||||
--depth 1 \
|
--depth 1 \
|
||||||
--branch "$DEFAULT_BRANCH"
|
--branch main
|
||||||
|
|
||||||
cd gstreamer
|
cd gstreamer
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ source ./ci/env.sh
|
||||||
set -e
|
set -e
|
||||||
export CARGO_HOME='/usr/local/cargo'
|
export CARGO_HOME='/usr/local/cargo'
|
||||||
|
|
||||||
RUSTUP_VERSION=1.27.1
|
RUSTUP_VERSION=1.26.0
|
||||||
RUST_VERSION=$1
|
RUST_VERSION=$1
|
||||||
RUST_IMAGE_FULL=$2
|
RUST_IMAGE_FULL=$2
|
||||||
RUST_ARCH="x86_64-unknown-linux-gnu"
|
RUST_ARCH="x86_64-unknown-linux-gnu"
|
||||||
|
@ -26,26 +26,20 @@ if [ "$RUST_IMAGE_FULL" = "1" ]; then
|
||||||
rustup component add clippy-preview
|
rustup component add clippy-preview
|
||||||
rustup component add rustfmt
|
rustup component add rustfmt
|
||||||
|
|
||||||
cargo install --locked --force cargo-deny
|
cargo install --force cargo-deny
|
||||||
cargo install --locked --force cargo-outdated
|
cargo install --force cargo-outdated
|
||||||
cargo install --locked --force typos-cli --version "1.19.0"
|
cargo install --force typos-cli
|
||||||
|
|
||||||
# Coverage tools
|
# Coverage tools
|
||||||
rustup component add llvm-tools-preview
|
rustup component add llvm-tools-preview
|
||||||
cargo install --locked --force grcov
|
cargo install --force grcov
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$RUST_VERSION" = "nightly" ]; then
|
cargo install cargo-c --version 0.9.22+cargo-0.72
|
||||||
# FIXME: Don't build cargo-c with --locked for now because otherwise a
|
|
||||||
# version of ahash is used that doesn't build on nightly anymore
|
|
||||||
cargo install cargo-c --version 0.9.22+cargo-0.72
|
|
||||||
else
|
|
||||||
cargo install --locked cargo-c --version 0.9.22+cargo-0.72
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$RUST_VERSION" = "nightly" ]; then
|
if [ "$RUST_VERSION" = "nightly" ]; then
|
||||||
rustup component add rustfmt --toolchain nightly
|
rustup component add rustfmt --toolchain nightly
|
||||||
|
|
||||||
# Documentation tools
|
# Documentation tools
|
||||||
cargo install --locked --force rustdoc-stripper
|
cargo install --force rustdoc-stripper
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -11,10 +11,13 @@ get_features() {
|
||||||
crate=$1
|
crate=$1
|
||||||
case "$crate" in
|
case "$crate" in
|
||||||
gstreamer-audio|gstreamer-editing-services|gstreamer-gl|gstreamer-pbutils|gstreamer-rtp|gstreamer-rtsp|gstreamer-video|gstreamer)
|
gstreamer-audio|gstreamer-editing-services|gstreamer-gl|gstreamer-pbutils|gstreamer-rtp|gstreamer-rtsp|gstreamer-video|gstreamer)
|
||||||
echo "--features=serde,v1_26"
|
echo "--features=serde,v1_24"
|
||||||
|
;;
|
||||||
|
gstreamer-validate)
|
||||||
|
echo ""
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "--features=v1_26"
|
echo "--features=v1_24"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,11 @@ for crate in gstreamer*/sys gstreamer-gl/*/sys; do
|
||||||
done
|
done
|
||||||
|
|
||||||
for crate in gstreamer/sys \
|
for crate in gstreamer/sys \
|
||||||
gstreamer-allocators/sys \
|
|
||||||
gstreamer-analytics/sys \
|
|
||||||
gstreamer-app/sys \
|
gstreamer-app/sys \
|
||||||
gstreamer-audio/sys \
|
gstreamer-audio/sys \
|
||||||
gstreamer-base/sys \
|
gstreamer-base/sys \
|
||||||
gstreamer-check/sys \
|
gstreamer-check/sys \
|
||||||
gstreamer-controller/sys \
|
gstreamer-controller/sys \
|
||||||
gstreamer-editing-services/sys \
|
|
||||||
gstreamer-gl/sys \
|
gstreamer-gl/sys \
|
||||||
gstreamer-gl/egl/sys \
|
gstreamer-gl/egl/sys \
|
||||||
gstreamer-gl/wayland/sys \
|
gstreamer-gl/wayland/sys \
|
||||||
|
@ -28,14 +25,11 @@ for crate in gstreamer/sys \
|
||||||
gstreamer-mpegts/sys \
|
gstreamer-mpegts/sys \
|
||||||
gstreamer-net/sys \
|
gstreamer-net/sys \
|
||||||
gstreamer-pbutils/sys \
|
gstreamer-pbutils/sys \
|
||||||
gstreamer-play/sys \
|
|
||||||
gstreamer-player/sys \
|
gstreamer-player/sys \
|
||||||
gstreamer-rtp/sys \
|
|
||||||
gstreamer-rtsp-server/sys \
|
gstreamer-rtsp-server/sys \
|
||||||
gstreamer-rtsp/sys \
|
gstreamer-rtsp/sys \
|
||||||
gstreamer-sdp/sys \
|
gstreamer-sdp/sys \
|
||||||
gstreamer-tag/sys \
|
gstreamer-tag/sys \
|
||||||
gstreamer-validate/sys \
|
|
||||||
gstreamer-video/sys \
|
gstreamer-video/sys \
|
||||||
gstreamer-webrtc/sys; do
|
gstreamer-webrtc/sys; do
|
||||||
echo "Testing $crate with --all-features)"
|
echo "Testing $crate with --all-features)"
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
# 'gstreamer-gl/egl',
|
# 'gstreamer-gl/egl',
|
||||||
# 'gstreamer-gl/wayland',
|
# 'gstreamer-gl/wayland',
|
||||||
# 'gstreamer-gl/x11',
|
# 'gstreamer-gl/x11',
|
||||||
'gstreamer-mpegts',
|
# only has sys
|
||||||
|
# 'gstreamer-mpegts',
|
||||||
'gstreamer-mpegts/sys',
|
'gstreamer-mpegts/sys',
|
||||||
'gstreamer-net',
|
'gstreamer-net',
|
||||||
'gstreamer-pbutils',
|
'gstreamer-pbutils',
|
||||||
|
@ -25,7 +26,8 @@
|
||||||
'gstreamer-rtsp',
|
'gstreamer-rtsp',
|
||||||
'gstreamer-rtsp-server',
|
'gstreamer-rtsp-server',
|
||||||
'gstreamer-sdp',
|
'gstreamer-sdp',
|
||||||
'gstreamer-tag',
|
# only has sys
|
||||||
|
# 'gstreamer-tag',
|
||||||
'gstreamer-tag/sys',
|
'gstreamer-tag/sys',
|
||||||
'gstreamer-video',
|
'gstreamer-video',
|
||||||
'gstreamer-webrtc',
|
'gstreamer-webrtc',
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
FROM "registry.freedesktop.org/gstreamer/gstreamer/amd64/windows:2023-07-17.0-main"
|
FROM "registry.freedesktop.org/gstreamer/gstreamer/amd64/windows:2023-07-17.0-main"
|
||||||
|
|
||||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
# Make sure any failure in PowerShell is fatal
|
||||||
|
ENV ErrorActionPreference='Stop'
|
||||||
|
SHELL ["powershell","-NoLogo", "-NonInteractive", "-Command"]
|
||||||
|
|
||||||
ARG DEFAULT_BRANCH="1.24"
|
ARG DEFAULT_BRANCH="main"
|
||||||
ARG RUST_VERSION="invalid"
|
ARG RUST_VERSION="invalid"
|
||||||
|
|
||||||
RUN choco install -y pkgconfiglite nasm llvm openssl
|
RUN choco install -y pkgconfiglite nasm llvm openssl
|
||||||
|
@ -19,4 +21,4 @@ RUN C:\install_dav1d.ps1
|
||||||
|
|
||||||
RUN Invoke-WebRequest -Uri https://win.rustup.rs/x86_64 -OutFile C:\rustup-init.exe
|
RUN Invoke-WebRequest -Uri https://win.rustup.rs/x86_64 -OutFile C:\rustup-init.exe
|
||||||
RUN C:\rustup-init.exe -y --profile minimal --default-toolchain $env:RUST_VERSION
|
RUN C:\rustup-init.exe -y --profile minimal --default-toolchain $env:RUST_VERSION
|
||||||
RUN cargo install --locked cargo-c --version 0.9.22+cargo-0.72
|
RUN cargo install cargo-c --version 0.9.22+cargo-0.72
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
|
||||||
|
|
||||||
# Download gstreamer and all its subprojects
|
# Download gstreamer and all its subprojects
|
||||||
git clone -b 1.4.1 --depth 1 https://code.videolan.org/videolan/dav1d.git C:\dav1d
|
git clone -b 1.1.0 --depth 1 https://code.videolan.org/videolan/dav1d.git C:\dav1d
|
||||||
if (!$?) {
|
if (!$?) {
|
||||||
Write-Host "Failed to clone dav1d"
|
Write-Host "Failed to clone dav1d"
|
||||||
Exit 1
|
Exit 1
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
|
||||||
|
# Make sure powershell exits on errors
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
# Download gstreamer and all its subprojects
|
# Download gstreamer and all its subprojects
|
||||||
git clone -b $env:DEFAULT_BRANCH --depth 1 https://gitlab.freedesktop.org/gstreamer/gstreamer.git C:\gstreamer
|
git clone -b $env:DEFAULT_BRANCH --depth 1 https://gitlab.freedesktop.org/gstreamer/gstreamer.git C:\gstreamer
|
||||||
if (!$?) {
|
|
||||||
Write-Host "Failed to clone gstreamer"
|
|
||||||
Exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-Location C:\gstreamer
|
Set-Location C:\gstreamer
|
||||||
|
|
||||||
|
@ -15,10 +13,6 @@ Move-Item C:/subprojects/* C:\gstreamer\subprojects
|
||||||
# Update the subprojects cache
|
# Update the subprojects cache
|
||||||
Write-Output "Running meson subproject reset"
|
Write-Output "Running meson subproject reset"
|
||||||
meson subprojects update --reset
|
meson subprojects update --reset
|
||||||
if (!$?) {
|
|
||||||
Write-Host "Failed to update gstreamer subprojects"
|
|
||||||
Exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
$MESON_ARGS = @(`
|
$MESON_ARGS = @(`
|
||||||
"--prefix=C:\gst-install", `
|
"--prefix=C:\gst-install", `
|
||||||
|
@ -48,24 +42,9 @@ echo "subproject('gtk')" >> meson.build
|
||||||
|
|
||||||
Write-Output "Building gstreamer"
|
Write-Output "Building gstreamer"
|
||||||
meson setup --vsenv $MESON_ARGS _build
|
meson setup --vsenv $MESON_ARGS _build
|
||||||
if (!$?) {
|
|
||||||
type "_build\meson-logs\meson-log.txt"
|
|
||||||
Write-Host "Failed to run meson setup, see log above"
|
|
||||||
Exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Output "Compiling gstreamer"
|
|
||||||
meson compile -C _build
|
meson compile -C _build
|
||||||
if (!$?) {
|
|
||||||
Write-Host "Failed to run meson compile"
|
|
||||||
Exit 1
|
|
||||||
}
|
|
||||||
# meson install does a spurious rebuild sometimes that then fails
|
# meson install does a spurious rebuild sometimes that then fails
|
||||||
meson install --no-rebuild -C _build
|
meson install --no-rebuild -C _build
|
||||||
if (!$?) {
|
|
||||||
Write-Host "Failed to run meson install"
|
|
||||||
Exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
cd c:\
|
cd c:\
|
||||||
Remove-Item -LiteralPath "C:\gstreamer" -Force -Recurse
|
Remove-Item -LiteralPath "C:\gstreamer" -Force -Recurse
|
||||||
|
|
17
deny.toml
17
deny.toml
|
@ -23,15 +23,20 @@ multiple-versions = "deny"
|
||||||
wildcards = "allow"
|
wildcards = "allow"
|
||||||
highlight = "all"
|
highlight = "all"
|
||||||
|
|
||||||
# proc-macro-crate depends on an older version of toml_edit
|
|
||||||
# https://github.com/bkchr/proc-macro-crate/pull/50
|
|
||||||
[[bans.skip]]
|
|
||||||
name = "toml_edit"
|
|
||||||
version = "0.21"
|
|
||||||
|
|
||||||
[sources]
|
[sources]
|
||||||
unknown-registry = "deny"
|
unknown-registry = "deny"
|
||||||
unknown-git = "deny"
|
unknown-git = "deny"
|
||||||
allow-git = [
|
allow-git = [
|
||||||
"https://github.com/gtk-rs/gtk-rs-core",
|
"https://github.com/gtk-rs/gtk-rs-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Various crates depend on an older version of syn
|
||||||
|
[[bans.skip]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
# proc-macro-crate depends on an older version of toml_edit
|
||||||
|
# https://github.com/bkchr/proc-macro-crate/pull/41
|
||||||
|
[[bans.skip]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.20"
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
[package]
|
[package]
|
||||||
name = "examples"
|
name = "examples"
|
||||||
version.workspace = true
|
version = "0.21.3"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
||||||
edition.workspace = true
|
edition = "2021"
|
||||||
rust-version.workspace = true
|
rust-version = "1.70"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
glib.workspace = true
|
glib = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "0.18", version = "0.18" }
|
||||||
gst.workspace = true
|
gst = { package = "gstreamer", path = "../gstreamer", version = "0.21" }
|
||||||
gst-gl = { workspace = true, optional = true }
|
gst-gl = { package = "gstreamer-gl", path = "../gstreamer-gl", version = "0.21", optional = true }
|
||||||
gst-gl-egl = { workspace = true, optional = true }
|
gst-gl-egl = { package = "gstreamer-gl-egl", path = "../gstreamer-gl/egl", version = "0.21", optional = true }
|
||||||
gst-gl-x11 = { workspace = true, optional = true }
|
gst-gl-x11 = { package = "gstreamer-gl-x11", path = "../gstreamer-gl/x11", version = "0.21", optional = true }
|
||||||
gst-app.workspace = true
|
gst-app = { package = "gstreamer-app", path = "../gstreamer-app", version = "0.21" }
|
||||||
gst-audio.workspace = true
|
gst-audio = { package = "gstreamer-audio", path = "../gstreamer-audio", version = "0.21" }
|
||||||
gst-base.workspace = true
|
gst-base = { package = "gstreamer-base", path = "../gstreamer-base", version = "0.21" }
|
||||||
gst-video.workspace = true
|
gst-video = { package = "gstreamer-video", path = "../gstreamer-video", version = "0.21" }
|
||||||
gst-pbutils.workspace = true
|
gst-pbutils = { package = "gstreamer-pbutils", path = "../gstreamer-pbutils", version = "0.21" }
|
||||||
gst-play = { workspace = true, optional = true }
|
gst-play = { package = "gstreamer-play", path = "../gstreamer-play", version = "0.21", optional = true }
|
||||||
gst-player = { workspace = true, optional = true }
|
gst-player = { package = "gstreamer-player", path = "../gstreamer-player", version = "0.21", optional = true }
|
||||||
ges = { workspace = true, optional = true }
|
ges = { package = "gstreamer-editing-services", path = "../gstreamer-editing-services", version = "0.21", optional = true }
|
||||||
gst-sdp = { workspace = true, optional = true }
|
gst-sdp = { package = "gstreamer-sdp", path = "../gstreamer-sdp", version = "0.21", optional = true }
|
||||||
gst-rtsp = { workspace = true, optional = true }
|
gst-rtsp = { package = "gstreamer-rtsp", path = "../gstreamer-rtsp", version = "0.21", optional = true }
|
||||||
gst-rtsp-server = { workspace = true, optional = true }
|
gst-rtsp-server = { package = "gstreamer-rtsp-server", path = "../gstreamer-rtsp-server", version = "0.21", optional = true }
|
||||||
gst-allocators = { workspace = true, optional = true }
|
gst-allocators = { package = "gstreamer-allocators", path = "../gstreamer-allocators", version = "0.21", optional = true }
|
||||||
gio = { workspace = true, optional = true }
|
gio = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "0.18", version = "0.18", optional = true }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
byte-slice-cast = "1"
|
byte-slice-cast = "1"
|
||||||
cairo-rs = { workspace = true, features=["use_glib"], optional = true }
|
cairo-rs = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "0.18", version = "0.18", features=["use_glib"], optional = true }
|
||||||
derive_more = "0.99.5"
|
derive_more = "0.99.5"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
glutin = { version = "0.31", optional = true, default-features = false }
|
glutin = { version = "0.31", optional = true, default-features = false }
|
||||||
|
@ -35,17 +35,15 @@ glutin-winit = { version = "0.4", optional = true, default-features = false }
|
||||||
image = { version = "0.24", optional = true, default-features = false, features = ["png", "jpeg"] }
|
image = { version = "0.24", optional = true, default-features = false, features = ["png", "jpeg"] }
|
||||||
memfd = { version = "0.6", optional = true }
|
memfd = { version = "0.6", optional = true }
|
||||||
memmap2 = { version = "0.9", optional = true }
|
memmap2 = { version = "0.9", optional = true }
|
||||||
pango = { workspace = true, optional = true }
|
pango = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "0.18", version = "0.18", optional = true }
|
||||||
pangocairo = { workspace = true, optional = true }
|
pangocairo = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "0.18", version = "0.18", optional = true }
|
||||||
raw-window-handle = { version = "0.5", optional = true }
|
raw-window-handle = { version = "0.5", optional = true }
|
||||||
uds = { version = "0.4", optional = true }
|
uds = { version = "0.4", optional = true }
|
||||||
winit = { version = "0.29", optional = true, default-features = false, features = ["rwh_05"] }
|
winit = { version = "0.29", optional = true, default-features = false, features = ["rwh_05"] }
|
||||||
atomic_refcell = "0.1"
|
atomic_refcell = "0.1"
|
||||||
data-encoding = "2.0"
|
|
||||||
once_cell = "1"
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows = { version = "0.56", features=["Win32_Graphics_Direct3D11",
|
windows = { version = "0.52", features=["Win32_Graphics_Direct3D11",
|
||||||
"Win32_Foundation", "Win32_Graphics_Direct3D", "Win32_Graphics_Dxgi",
|
"Win32_Foundation", "Win32_Graphics_Direct3D", "Win32_Graphics_Dxgi",
|
||||||
"Win32_Graphics_Dxgi_Common", "Win32_Graphics_Direct2D",
|
"Win32_Graphics_Dxgi_Common", "Win32_Graphics_Direct2D",
|
||||||
"Win32_Graphics_Direct2D_Common", "Win32_Graphics_DirectWrite",
|
"Win32_Graphics_Direct2D_Common", "Win32_Graphics_DirectWrite",
|
||||||
|
@ -53,7 +51,6 @@ windows = { version = "0.56", features=["Win32_Graphics_Direct3D11",
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
cocoa = "0.25"
|
cocoa = "0.25"
|
||||||
objc = "0.2.7"
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gl_generator = { version = "0.14", optional = true }
|
gl_generator = { version = "0.14", optional = true }
|
||||||
|
@ -136,10 +133,6 @@ required-features = ["rtsp-server"]
|
||||||
name = "rtsp-server-subclass"
|
name = "rtsp-server-subclass"
|
||||||
required-features = ["rtsp-server"]
|
required-features = ["rtsp-server"]
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "rtsp-server-custom-auth"
|
|
||||||
required-features = ["rtsp-server", "gst-rtsp-server/v1_22"]
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "tagsetter"
|
name = "tagsetter"
|
||||||
|
|
||||||
|
@ -204,6 +197,3 @@ required-features = ["cairo-rs", "gst-video/v1_18"]
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "d3d11videosink"
|
name = "d3d11videosink"
|
||||||
required-features = ["windows"]
|
required-features = ["windows"]
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "audio_multichannel_interleave"
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use derive_more::{Display, Error};
|
use derive_more::{Display, Error};
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
use gst_video::prelude::*;
|
|
||||||
|
|
||||||
#[path = "../examples-common.rs"]
|
#[path = "../examples-common.rs"]
|
||||||
mod examples_common;
|
mod examples_common;
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
// This example demonstrates how to mix multiple audio
|
|
||||||
// streams into a single output using the audiomixer element.
|
|
||||||
// In this case, we're mixing 4 stereo streams into a single 8 channel output.
|
|
||||||
|
|
||||||
use gst::prelude::*;
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
#[path = "../examples-common.rs"]
|
|
||||||
mod examples_common;
|
|
||||||
|
|
||||||
const TRACKS: i32 = 4;
|
|
||||||
|
|
||||||
fn create_source_and_link(pipeline: &gst::Pipeline, mixer: &gst::Element, track_number: i32) {
|
|
||||||
let freq = ((track_number + 1) * 1000) as f64;
|
|
||||||
let audiosrc = gst::ElementFactory::make("audiotestsrc")
|
|
||||||
.property("freq", freq)
|
|
||||||
.property("num-buffers", 2000)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
let caps = gst_audio::AudioCapsBuilder::new().channels(2).build();
|
|
||||||
let capsfilter = gst::ElementFactory::make("capsfilter")
|
|
||||||
.property("caps", &caps)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
pipeline.add_many([&audiosrc, &capsfilter]).unwrap();
|
|
||||||
gst::Element::link_many([&audiosrc, &capsfilter]).unwrap();
|
|
||||||
|
|
||||||
let src_pad = capsfilter.static_pad("src").unwrap();
|
|
||||||
let mixer_pad = mixer.request_pad_simple("sink_%u").unwrap();
|
|
||||||
|
|
||||||
// audiomixer expects a mix-matrix set on each input pad,
|
|
||||||
// indicating which output channels our input should appear in.
|
|
||||||
// Rows => input channels, columns => output channels.
|
|
||||||
// Here each input channel will appear in exactly one output channel.
|
|
||||||
let mut mix_matrix: Vec<Vec<f32>> = vec![];
|
|
||||||
for i in 0..TRACKS {
|
|
||||||
if i == track_number {
|
|
||||||
mix_matrix.push(vec![1.0, 0.0]);
|
|
||||||
mix_matrix.push(vec![0.0, 1.0]);
|
|
||||||
} else {
|
|
||||||
mix_matrix.push(vec![0.0, 0.0]);
|
|
||||||
mix_matrix.push(vec![0.0, 0.0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut audiomixer_config = gst_audio::AudioConverterConfig::new();
|
|
||||||
audiomixer_config.set_mix_matrix(&mix_matrix);
|
|
||||||
mixer_pad.set_property("converter-config", audiomixer_config);
|
|
||||||
|
|
||||||
src_pad.link(&mixer_pad).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn example_main() {
|
|
||||||
gst::init().unwrap();
|
|
||||||
|
|
||||||
let args: Vec<_> = env::args().collect();
|
|
||||||
let output_file = if args.len() == 2 {
|
|
||||||
&args[1]
|
|
||||||
} else {
|
|
||||||
println!("Usage: audiomixer <output file>");
|
|
||||||
std::process::exit(-1);
|
|
||||||
};
|
|
||||||
|
|
||||||
let pipeline = gst::Pipeline::new();
|
|
||||||
let audiomixer = gst::ElementFactory::make("audiomixer").build().unwrap();
|
|
||||||
|
|
||||||
// Using an arbitrary layout of 4 stereo pairs.
|
|
||||||
let positions = [
|
|
||||||
gst_audio::AudioChannelPosition::FrontLeft,
|
|
||||||
gst_audio::AudioChannelPosition::FrontRight,
|
|
||||||
gst_audio::AudioChannelPosition::RearLeft,
|
|
||||||
gst_audio::AudioChannelPosition::RearRight,
|
|
||||||
gst_audio::AudioChannelPosition::SideLeft,
|
|
||||||
gst_audio::AudioChannelPosition::SideRight,
|
|
||||||
gst_audio::AudioChannelPosition::TopFrontLeft,
|
|
||||||
gst_audio::AudioChannelPosition::TopFrontRight,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mask = gst_audio::AudioChannelPosition::positions_to_mask(&positions, true).unwrap();
|
|
||||||
let caps = gst_audio::AudioCapsBuilder::new()
|
|
||||||
.channels(positions.len() as i32)
|
|
||||||
.channel_mask(mask)
|
|
||||||
.build();
|
|
||||||
let capsfilter = gst::ElementFactory::make("capsfilter")
|
|
||||||
.property("caps", &caps)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let audioconvert = gst::ElementFactory::make("audioconvert").build().unwrap();
|
|
||||||
let audioresample = gst::ElementFactory::make("audioresample").build().unwrap();
|
|
||||||
let wavenc = gst::ElementFactory::make("wavenc").build().unwrap();
|
|
||||||
let sink = gst::ElementFactory::make("filesink")
|
|
||||||
.property("location", output_file)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
pipeline
|
|
||||||
.add_many([
|
|
||||||
&audiomixer,
|
|
||||||
&capsfilter,
|
|
||||||
&audioconvert,
|
|
||||||
&audioresample,
|
|
||||||
&wavenc,
|
|
||||||
&sink,
|
|
||||||
])
|
|
||||||
.unwrap();
|
|
||||||
gst::Element::link_many([
|
|
||||||
&audiomixer,
|
|
||||||
&capsfilter,
|
|
||||||
&audioconvert,
|
|
||||||
&audioresample,
|
|
||||||
&wavenc,
|
|
||||||
&sink,
|
|
||||||
])
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for i in 0..TRACKS {
|
|
||||||
create_source_and_link(&pipeline, &audiomixer, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
let bus = pipeline.bus().expect("Pipeline without bus");
|
|
||||||
|
|
||||||
pipeline
|
|
||||||
.set_state(gst::State::Playing)
|
|
||||||
.expect("Unable to start pipeline");
|
|
||||||
|
|
||||||
for msg in bus.iter_timed(gst::ClockTime::NONE) {
|
|
||||||
use gst::MessageView;
|
|
||||||
match msg.view() {
|
|
||||||
MessageView::Eos(..) => break,
|
|
||||||
MessageView::Error(err) => {
|
|
||||||
eprintln!(
|
|
||||||
"Error from {:?}: {} ({:?})",
|
|
||||||
msg.src().map(|s| s.path_string()),
|
|
||||||
err.error(),
|
|
||||||
err.debug()
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pipeline
|
|
||||||
.set_state(gst::State::Null)
|
|
||||||
.expect("Unable to change pipeline state to NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// tutorials_common::run is only required to set up the application environment on macOS
|
|
||||||
// (but not necessary in normal Cocoa applications where this is set up automatically)
|
|
||||||
examples_common::run(example_main);
|
|
||||||
}
|
|
|
@ -10,6 +10,7 @@ mod examples_common;
|
||||||
|
|
||||||
// Our custom compositor element is defined in this module.
|
// Our custom compositor element is defined in this module.
|
||||||
mod cairo_compositor {
|
mod cairo_compositor {
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
use gst_base::subclass::prelude::*;
|
use gst_base::subclass::prelude::*;
|
||||||
use gst_video::{prelude::*, subclass::prelude::*};
|
use gst_video::{prelude::*, subclass::prelude::*};
|
||||||
|
|
||||||
|
@ -56,16 +57,15 @@ mod cairo_compositor {
|
||||||
// In this case a single property for configuring the background color of the
|
// In this case a single property for configuring the background color of the
|
||||||
// composition.
|
// composition.
|
||||||
fn properties() -> &'static [glib::ParamSpec] {
|
fn properties() -> &'static [glib::ParamSpec] {
|
||||||
static PROPERTIES: std::sync::OnceLock<Vec<glib::ParamSpec>> =
|
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
PROPERTIES.get_or_init(|| {
|
|
||||||
vec![glib::ParamSpecUInt::builder("background-color")
|
vec![glib::ParamSpecUInt::builder("background-color")
|
||||||
.nick("Background Color")
|
.nick("Background Color")
|
||||||
.blurb("Background color as 0xRRGGBB")
|
.blurb("Background color as 0xRRGGBB")
|
||||||
.default_value(Settings::default().background_color)
|
.default_value(Settings::default().background_color)
|
||||||
.build()]
|
.build()]
|
||||||
})
|
});
|
||||||
|
|
||||||
|
&PROPERTIES
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the application whenever the value of a property should be changed.
|
// Called by the application whenever the value of a property should be changed.
|
||||||
|
@ -100,24 +100,20 @@ mod cairo_compositor {
|
||||||
// gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry
|
// gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry
|
||||||
// after initial registration without having to load the plugin in memory.
|
// after initial registration without having to load the plugin in memory.
|
||||||
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
|
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
|
||||||
static ELEMENT_METADATA: std::sync::OnceLock<gst::subclass::ElementMetadata> =
|
static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
Some(ELEMENT_METADATA.get_or_init(|| {
|
|
||||||
gst::subclass::ElementMetadata::new(
|
gst::subclass::ElementMetadata::new(
|
||||||
"Cairo Compositor",
|
"Cairo Compositor",
|
||||||
"Compositor/Video",
|
"Compositor/Video",
|
||||||
"Cairo based compositor",
|
"Cairo based compositor",
|
||||||
"Sebastian Dröge <sebastian@centricular.com>",
|
"Sebastian Dröge <sebastian@centricular.com>",
|
||||||
)
|
)
|
||||||
}))
|
});
|
||||||
|
|
||||||
|
Some(&*ELEMENT_METADATA)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pad_templates() -> &'static [gst::PadTemplate] {
|
fn pad_templates() -> &'static [gst::PadTemplate] {
|
||||||
static PAD_TEMPLATES: std::sync::OnceLock<Vec<gst::PadTemplate>> =
|
static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
PAD_TEMPLATES.get_or_init(|| {
|
|
||||||
// Create pad templates for our sink and source pad. These are later used for
|
// Create pad templates for our sink and source pad. These are later used for
|
||||||
// actually creating the pads and beforehand already provide information to
|
// actually creating the pads and beforehand already provide information to
|
||||||
// GStreamer about all possible pads that could exist for this type.
|
// GStreamer about all possible pads that could exist for this type.
|
||||||
|
@ -152,7 +148,9 @@ mod cairo_compositor {
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
]
|
]
|
||||||
})
|
});
|
||||||
|
|
||||||
|
PAD_TEMPLATES.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify via the child proxy interface whenever a new pad is added or removed.
|
// Notify via the child proxy interface whenever a new pad is added or removed.
|
||||||
|
@ -459,10 +457,7 @@ mod cairo_compositor {
|
||||||
// In this case there are various properties for defining the position and otherwise
|
// In this case there are various properties for defining the position and otherwise
|
||||||
// the appearance of the stream corresponding to this pad.
|
// the appearance of the stream corresponding to this pad.
|
||||||
fn properties() -> &'static [glib::ParamSpec] {
|
fn properties() -> &'static [glib::ParamSpec] {
|
||||||
static PROPERTIES: std::sync::OnceLock<Vec<glib::ParamSpec>> =
|
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
PROPERTIES.get_or_init(|| {
|
|
||||||
vec![
|
vec![
|
||||||
glib::ParamSpecDouble::builder("alpha")
|
glib::ParamSpecDouble::builder("alpha")
|
||||||
.nick("Alpha")
|
.nick("Alpha")
|
||||||
|
@ -500,7 +495,9 @@ mod cairo_compositor {
|
||||||
.default_value(Settings::default().ypos)
|
.default_value(Settings::default().ypos)
|
||||||
.build(),
|
.build(),
|
||||||
]
|
]
|
||||||
})
|
});
|
||||||
|
|
||||||
|
PROPERTIES.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the application whenever the value of a property should be changed.
|
// Called by the application whenever the value of a property should be changed.
|
||||||
|
|
|
@ -48,7 +48,7 @@ fn example_main() {
|
||||||
let main_loop = glib::MainLoop::new(None, false);
|
let main_loop = glib::MainLoop::new(None, false);
|
||||||
|
|
||||||
// This creates a pipeline by parsing the gst-launch pipeline syntax.
|
// This creates a pipeline by parsing the gst-launch pipeline syntax.
|
||||||
let pipeline = gst::parse::launch(
|
let pipeline = gst::parse_launch(
|
||||||
"audiotestsrc name=src ! queue max-size-time=2000000000 ! fakesink name=sink sync=true",
|
"audiotestsrc name=src ! queue max-size-time=2000000000 ! fakesink name=sink sync=true",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -71,6 +71,7 @@ mod custom_meta {
|
||||||
mod imp {
|
mod imp {
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
use glib::translate::*;
|
use glib::translate::*;
|
||||||
|
|
||||||
pub(super) struct CustomMetaParams {
|
pub(super) struct CustomMetaParams {
|
||||||
|
@ -86,10 +87,8 @@ mod custom_meta {
|
||||||
|
|
||||||
// Function to register the meta API and get a type back.
|
// Function to register the meta API and get a type back.
|
||||||
pub(super) fn custom_meta_api_get_type() -> glib::Type {
|
pub(super) fn custom_meta_api_get_type() -> glib::Type {
|
||||||
static TYPE: std::sync::OnceLock<glib::Type> = std::sync::OnceLock::new();
|
static TYPE: Lazy<glib::Type> = Lazy::new(|| unsafe {
|
||||||
|
let t = from_glib(gst::ffi::gst_meta_api_type_register(
|
||||||
*TYPE.get_or_init(|| unsafe {
|
|
||||||
let t = glib::Type::from_glib(gst::ffi::gst_meta_api_type_register(
|
|
||||||
b"MyCustomMetaAPI\0".as_ptr() as *const _,
|
b"MyCustomMetaAPI\0".as_ptr() as *const _,
|
||||||
// We provide no tags here as our meta is just a label and does
|
// We provide no tags here as our meta is just a label and does
|
||||||
// not refer to any specific aspect of the buffer.
|
// not refer to any specific aspect of the buffer.
|
||||||
|
@ -99,7 +98,9 @@ mod custom_meta {
|
||||||
assert_ne!(t, glib::Type::INVALID);
|
assert_ne!(t, glib::Type::INVALID);
|
||||||
|
|
||||||
t
|
t
|
||||||
})
|
});
|
||||||
|
|
||||||
|
*TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialization function for our meta. This needs to ensure all fields are correctly
|
// Initialization function for our meta. This needs to ensure all fields are correctly
|
||||||
|
@ -156,24 +157,21 @@ mod custom_meta {
|
||||||
unsafe impl Send for MetaInfo {}
|
unsafe impl Send for MetaInfo {}
|
||||||
unsafe impl Sync for MetaInfo {}
|
unsafe impl Sync for MetaInfo {}
|
||||||
|
|
||||||
static META_INFO: std::sync::OnceLock<MetaInfo> = std::sync::OnceLock::new();
|
static META_INFO: Lazy<MetaInfo> = Lazy::new(|| unsafe {
|
||||||
|
MetaInfo(
|
||||||
|
ptr::NonNull::new(gst::ffi::gst_meta_register(
|
||||||
|
custom_meta_api_get_type().into_glib(),
|
||||||
|
b"MyCustomMeta\0".as_ptr() as *const _,
|
||||||
|
mem::size_of::<CustomMeta>(),
|
||||||
|
Some(custom_meta_init),
|
||||||
|
Some(custom_meta_free),
|
||||||
|
Some(custom_meta_transform),
|
||||||
|
) as *mut gst::ffi::GstMetaInfo)
|
||||||
|
.expect("Failed to register meta API"),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
META_INFO
|
META_INFO.0.as_ptr()
|
||||||
.get_or_init(|| unsafe {
|
|
||||||
MetaInfo(
|
|
||||||
ptr::NonNull::new(gst::ffi::gst_meta_register(
|
|
||||||
custom_meta_api_get_type().into_glib(),
|
|
||||||
b"MyCustomMeta\0".as_ptr() as *const _,
|
|
||||||
mem::size_of::<CustomMeta>(),
|
|
||||||
Some(custom_meta_init),
|
|
||||||
Some(custom_meta_free),
|
|
||||||
Some(custom_meta_transform),
|
|
||||||
) as *mut gst::ffi::GstMetaInfo)
|
|
||||||
.expect("Failed to register meta API"),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.0
|
|
||||||
.as_ptr()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ fn main() -> Result<()> {
|
||||||
let mut metrics = DWRITE_TEXT_METRICS::default();
|
let mut metrics = DWRITE_TEXT_METRICS::default();
|
||||||
layout.GetMetrics(&mut metrics).unwrap();
|
layout.GetMetrics(&mut metrics).unwrap();
|
||||||
layout
|
layout
|
||||||
.GetFontSize(0, &mut font_size, Some(&mut range))
|
.GetFontSize2(0, &mut font_size, Some(&mut range))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if metrics.widthIncludingTrailingWhitespace >= desc.Width as f32 {
|
if metrics.widthIncludingTrailingWhitespace >= desc.Width as f32 {
|
||||||
|
|
|
@ -19,15 +19,15 @@ fn example_main() {
|
||||||
|
|
||||||
/* Disable stdout debug, then configure the debug ringbuffer and enable
|
/* Disable stdout debug, then configure the debug ringbuffer and enable
|
||||||
* all debug */
|
* all debug */
|
||||||
gst::log::remove_default_log_function();
|
gst::debug_remove_default_log_function();
|
||||||
/* Keep 1KB of logs per thread, removing old threads after 10 seconds */
|
/* Keep 1KB of logs per thread, removing old threads after 10 seconds */
|
||||||
gst::log::add_ring_buffer_logger(1024, 10);
|
gst::debug_add_ring_buffer_logger(1024, 10);
|
||||||
/* Enable all debug categories */
|
/* Enable all debug categories */
|
||||||
gst::log::set_default_threshold(gst::DebugLevel::Log);
|
gst::debug_set_default_threshold(gst::DebugLevel::Log);
|
||||||
|
|
||||||
let mut context = gst::ParseContext::new();
|
let mut context = gst::ParseContext::new();
|
||||||
let pipeline =
|
let pipeline =
|
||||||
match gst::parse::launch_full(pipeline_str, Some(&mut context), gst::ParseFlags::empty()) {
|
match gst::parse_launch_full(pipeline_str, Some(&mut context), gst::ParseFlags::empty()) {
|
||||||
Ok(pipeline) => pipeline,
|
Ok(pipeline) => pipeline,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let Some(gst::ParseError::NoSuchElement) = err.kind::<gst::ParseError>() {
|
if let Some(gst::ParseError::NoSuchElement) = err.kind::<gst::ParseError>() {
|
||||||
|
@ -73,7 +73,7 @@ fn example_main() {
|
||||||
gst::error!(gst::CAT_DEFAULT, "Hi from the debug log ringbuffer example");
|
gst::error!(gst::CAT_DEFAULT, "Hi from the debug log ringbuffer example");
|
||||||
|
|
||||||
println!("Dumping debug logs\n");
|
println!("Dumping debug logs\n");
|
||||||
for s in gst::log::ring_buffer_logger_get_logs().iter() {
|
for s in gst::debug_ring_buffer_logger_get_logs().iter() {
|
||||||
println!("{s}\n------------------");
|
println!("{s}\n------------------");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ fn example_main() {
|
||||||
let main_loop = glib::MainLoop::new(None, false);
|
let main_loop = glib::MainLoop::new(None, false);
|
||||||
|
|
||||||
// This creates a pipeline by parsing the gst-launch pipeline syntax.
|
// This creates a pipeline by parsing the gst-launch pipeline syntax.
|
||||||
let pipeline = gst::parse::launch("audiotestsrc ! fakesink").unwrap();
|
let pipeline = gst::parse_launch("audiotestsrc ! fakesink").unwrap();
|
||||||
let bus = pipeline.bus().unwrap();
|
let bus = pipeline.bus().unwrap();
|
||||||
|
|
||||||
pipeline
|
pipeline
|
||||||
|
|
|
@ -361,11 +361,11 @@ mod video_filter {
|
||||||
use std::{mem::ManuallyDrop, os::unix::prelude::FromRawFd};
|
use std::{mem::ManuallyDrop, os::unix::prelude::FromRawFd};
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
use gst::{subclass::prelude::*, PadDirection, PadPresence, PadTemplate};
|
use gst::{subclass::prelude::*, PadDirection, PadPresence, PadTemplate};
|
||||||
use gst_app::gst_base::subclass::BaseTransformMode;
|
use gst_app::gst_base::subclass::BaseTransformMode;
|
||||||
use gst_video::{prelude::*, subclass::prelude::*, VideoFrameRef};
|
use gst_video::{subclass::prelude::*, VideoFrameRef};
|
||||||
use memmap2::MmapMut;
|
use memmap2::MmapMut;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
||||||
gst::DebugCategory::new(
|
gst::DebugCategory::new(
|
||||||
|
@ -430,10 +430,7 @@ mod video_filter {
|
||||||
|
|
||||||
impl ElementImpl for FdMemoryFadeInVideoFilter {
|
impl ElementImpl for FdMemoryFadeInVideoFilter {
|
||||||
fn pad_templates() -> &'static [PadTemplate] {
|
fn pad_templates() -> &'static [PadTemplate] {
|
||||||
static PAD_TEMPLATES: std::sync::OnceLock<Vec<PadTemplate>> =
|
static PAD_TEMPLATES: Lazy<Vec<PadTemplate>> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
PAD_TEMPLATES.get_or_init(|| {
|
|
||||||
let caps = gst_video::VideoCapsBuilder::new()
|
let caps = gst_video::VideoCapsBuilder::new()
|
||||||
.format(gst_video::VideoFormat::Bgra)
|
.format(gst_video::VideoFormat::Bgra)
|
||||||
.build();
|
.build();
|
||||||
|
@ -443,7 +440,9 @@ mod video_filter {
|
||||||
PadTemplate::new("src", PadDirection::Src, PadPresence::Always, &caps)
|
PadTemplate::new("src", PadDirection::Src, PadPresence::Always, &caps)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
]
|
]
|
||||||
})
|
});
|
||||||
|
|
||||||
|
PAD_TEMPLATES.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ fn example_main() {
|
||||||
gst::init().unwrap();
|
gst::init().unwrap();
|
||||||
|
|
||||||
// Create a pipeline from the launch-syntax given on the cli.
|
// Create a pipeline from the launch-syntax given on the cli.
|
||||||
let pipeline = gst::parse::launch(&pipeline_str).unwrap();
|
let pipeline = gst::parse_launch(&pipeline_str).unwrap();
|
||||||
let bus = pipeline.bus().unwrap();
|
let bus = pipeline.bus().unwrap();
|
||||||
|
|
||||||
pipeline
|
pipeline
|
||||||
|
|
|
@ -32,13 +32,13 @@ void main () {
|
||||||
mod mirror {
|
mod mirror {
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
use gst_base::subclass::BaseTransformMode;
|
use gst_base::subclass::BaseTransformMode;
|
||||||
use gst_gl::{
|
use gst_gl::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
subclass::{prelude::*, GLFilterMode},
|
subclass::{prelude::*, GLFilterMode},
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
use super::{gl, FRAGMENT_SHADER};
|
use super::{gl, FRAGMENT_SHADER};
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ fn example_main() {
|
||||||
gst::init().unwrap();
|
gst::init().unwrap();
|
||||||
|
|
||||||
// Create a pipeline from the launch-syntax given on the cli.
|
// Create a pipeline from the launch-syntax given on the cli.
|
||||||
let pipeline = gst::parse::launch(&pipeline_str).unwrap();
|
let pipeline = gst::parse_launch(&pipeline_str).unwrap();
|
||||||
let bus = pipeline.bus().unwrap();
|
let bus = pipeline.bus().unwrap();
|
||||||
|
|
||||||
pipeline
|
pipeline
|
||||||
|
|
|
@ -26,22 +26,19 @@ fn example_main() {
|
||||||
// Especially GUIs should probably handle this case, to tell users that they need to
|
// Especially GUIs should probably handle this case, to tell users that they need to
|
||||||
// install the corresponding gstreamer plugins.
|
// install the corresponding gstreamer plugins.
|
||||||
let mut context = gst::ParseContext::new();
|
let mut context = gst::ParseContext::new();
|
||||||
let pipeline = match gst::parse::launch_full(
|
let pipeline =
|
||||||
&pipeline_str,
|
match gst::parse_launch_full(&pipeline_str, Some(&mut context), gst::ParseFlags::empty()) {
|
||||||
Some(&mut context),
|
Ok(pipeline) => pipeline,
|
||||||
gst::ParseFlags::empty(),
|
Err(err) => {
|
||||||
) {
|
if let Some(gst::ParseError::NoSuchElement) = err.kind::<gst::ParseError>() {
|
||||||
Ok(pipeline) => pipeline,
|
println!("Missing element(s): {:?}", context.missing_elements());
|
||||||
Err(err) => {
|
} else {
|
||||||
if let Some(gst::ParseError::NoSuchElement) = err.kind::<gst::ParseError>() {
|
println!("Failed to parse pipeline: {err}");
|
||||||
println!("Missing element(s): {:?}", context.missing_elements());
|
}
|
||||||
} else {
|
|
||||||
println!("Failed to parse pipeline: {err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
process::exit(-1)
|
process::exit(-1)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let bus = pipeline.bus().unwrap();
|
let bus = pipeline.bus().unwrap();
|
||||||
|
|
||||||
pipeline
|
pipeline
|
||||||
|
|
|
@ -24,7 +24,7 @@ fn example_main() {
|
||||||
let main_loop = glib::MainLoop::new(None, false);
|
let main_loop = glib::MainLoop::new(None, false);
|
||||||
|
|
||||||
// Let GStreamer create a pipeline from the parsed launch syntax on the cli.
|
// Let GStreamer create a pipeline from the parsed launch syntax on the cli.
|
||||||
let pipeline = gst::parse::launch(&pipeline_str).unwrap();
|
let pipeline = gst::parse_launch(&pipeline_str).unwrap();
|
||||||
let bus = pipeline.bus().unwrap();
|
let bus = pipeline.bus().unwrap();
|
||||||
|
|
||||||
pipeline
|
pipeline
|
||||||
|
|
|
@ -22,7 +22,7 @@ fn example_main() {
|
||||||
// Parse the pipeline we want to probe from a static in-line string.
|
// Parse the pipeline we want to probe from a static in-line string.
|
||||||
// Here we give our audiotestsrc a name, so we can retrieve that element
|
// Here we give our audiotestsrc a name, so we can retrieve that element
|
||||||
// from the resulting pipeline.
|
// from the resulting pipeline.
|
||||||
let pipeline = gst::parse::launch(&format!(
|
let pipeline = gst::parse_launch(&format!(
|
||||||
"audiotestsrc name=src ! audio/x-raw,format={},channels=1 ! fakesink",
|
"audiotestsrc name=src ! audio/x-raw,format={},channels=1 ! fakesink",
|
||||||
gst_audio::AUDIO_FORMAT_S16
|
gst_audio::AUDIO_FORMAT_S16
|
||||||
))
|
))
|
||||||
|
|
|
@ -36,14 +36,14 @@ fn example_main() {
|
||||||
// For flags handling
|
// For flags handling
|
||||||
// With flags, one can configure playbin's behavior such as whether it
|
// With flags, one can configure playbin's behavior such as whether it
|
||||||
// should play back contained video streams, or if it should render subtitles.
|
// should play back contained video streams, or if it should render subtitles.
|
||||||
// let flags = playbin.property_value("flags");
|
// let flags = playbin.get_property("flags").unwrap();
|
||||||
// let flags_class = FlagsClass::with_type(flags.type_()).unwrap();
|
// let flags_class = FlagsClass::new(flags.type_()).unwrap();
|
||||||
// let flags = flags_class.builder_with_value(flags).unwrap()
|
// let flags = flags_class.builder_with_value(flags).unwrap()
|
||||||
// .unset_by_nick("text")
|
// .unset_by_nick("text")
|
||||||
// .unset_by_nick("video")
|
// .unset_by_nick("video")
|
||||||
// .build()
|
// .build()
|
||||||
// .unwrap();
|
// .unwrap();
|
||||||
// playbin.set_property_from_value("flags", &flags);
|
// playbin.set_property_from_value("flags", &flags).unwrap();
|
||||||
|
|
||||||
// The playbin also provides any kind of metadata that it found in the played stream.
|
// The playbin also provides any kind of metadata that it found in the played stream.
|
||||||
// For this, the playbin provides signals notifying about changes in the metadata.
|
// For this, the playbin provides signals notifying about changes in the metadata.
|
||||||
|
|
|
@ -28,7 +28,7 @@ fn example_main() {
|
||||||
let main_loop = glib::MainLoop::new(None, false);
|
let main_loop = glib::MainLoop::new(None, false);
|
||||||
|
|
||||||
// Let GStreamer create a pipeline from the parsed launch syntax on the cli.
|
// Let GStreamer create a pipeline from the parsed launch syntax on the cli.
|
||||||
let pipeline = gst::parse::launch(&pipeline_str).unwrap();
|
let pipeline = gst::parse_launch(&pipeline_str).unwrap();
|
||||||
let bus = pipeline.bus().unwrap();
|
let bus = pipeline.bus().unwrap();
|
||||||
|
|
||||||
pipeline
|
pipeline
|
||||||
|
|
|
@ -252,7 +252,11 @@ fn example_main() -> Result<(), Error> {
|
||||||
if let Some(element) = msg.src() {
|
if let Some(element) = msg.src() {
|
||||||
if element == &pipeline && s.current() == gst::State::Playing {
|
if element == &pipeline && s.current() == gst::State::Playing {
|
||||||
eprintln!("PLAYING");
|
eprintln!("PLAYING");
|
||||||
pipeline.debug_to_dot_file(gst::DebugGraphDetails::all(), "client-playing");
|
gst::debug_bin_to_dot_file(
|
||||||
|
&pipeline,
|
||||||
|
gst::DebugGraphDetails::all(),
|
||||||
|
"client-playing",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,7 +179,11 @@ fn example_main() -> Result<(), Error> {
|
||||||
if let Some(element) = msg.src() {
|
if let Some(element) = msg.src() {
|
||||||
if element == &pipeline && s.current() == gst::State::Playing {
|
if element == &pipeline && s.current() == gst::State::Playing {
|
||||||
eprintln!("PLAYING");
|
eprintln!("PLAYING");
|
||||||
pipeline.debug_to_dot_file(gst::DebugGraphDetails::all(), "server-playing");
|
gst::debug_bin_to_dot_file(
|
||||||
|
&pipeline,
|
||||||
|
gst::DebugGraphDetails::all(),
|
||||||
|
"server-playing",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,223 +0,0 @@
|
||||||
// This example demonstrates how to set up a rtsp server using GStreamer
|
|
||||||
// and extending the default auth module behaviour by subclassing RTSPAuth
|
|
||||||
// For this, the example creates a videotestsrc pipeline manually to be used
|
|
||||||
// by the RTSP server for providing data
|
|
||||||
#![allow(clippy::non_send_fields_in_send_ty)]
|
|
||||||
|
|
||||||
use anyhow::Error;
|
|
||||||
use derive_more::{Display, Error};
|
|
||||||
use gst_rtsp_server::prelude::*;
|
|
||||||
|
|
||||||
#[path = "../examples-common.rs"]
|
|
||||||
mod examples_common;
|
|
||||||
|
|
||||||
#[derive(Debug, Display, Error)]
|
|
||||||
#[display(fmt = "Could not get mount points")]
|
|
||||||
struct NoMountPoints;
|
|
||||||
|
|
||||||
fn main_loop() -> Result<(), Error> {
|
|
||||||
let main_loop = glib::MainLoop::new(None, false);
|
|
||||||
let server = gst_rtsp_server::RTSPServer::new();
|
|
||||||
|
|
||||||
// We create our custom auth module.
|
|
||||||
// The job of the auth module is to authenticate users and authorize
|
|
||||||
// factories access/construction.
|
|
||||||
let auth = auth::Auth::default();
|
|
||||||
server.set_auth(Some(&auth));
|
|
||||||
|
|
||||||
// Much like HTTP servers, RTSP servers have multiple endpoints that
|
|
||||||
// provide different streams. Here, we ask our server to give
|
|
||||||
// us a reference to his list of endpoints, so we can add our
|
|
||||||
// test endpoint, providing the pipeline from the cli.
|
|
||||||
let mounts = server.mount_points().ok_or(NoMountPoints)?;
|
|
||||||
|
|
||||||
// Next, we create a factory for the endpoint we want to create.
|
|
||||||
// The job of the factory is to create a new pipeline for each client that
|
|
||||||
// connects, or (if configured to do so) to reuse an existing pipeline.
|
|
||||||
let factory = gst_rtsp_server::RTSPMediaFactory::new();
|
|
||||||
// Here we tell the media factory the media we want to serve.
|
|
||||||
// This is done in the launch syntax. When the first client connects,
|
|
||||||
// the factory will use this syntax to create a new pipeline instance.
|
|
||||||
factory.set_launch("( videotestsrc ! vp8enc ! rtpvp8pay name=pay0 )");
|
|
||||||
// This setting specifies whether each connecting client gets the output
|
|
||||||
// of a new instance of the pipeline, or whether all connected clients share
|
|
||||||
// the output of the same pipeline.
|
|
||||||
// If you want to stream a fixed video you have stored on the server to any
|
|
||||||
// client, you would not set this to shared here (since every client wants
|
|
||||||
// to start at the beginning of the video). But if you want to distribute
|
|
||||||
// a live source, you will probably want to set this to shared, to save
|
|
||||||
// computing and memory capacity on the server.
|
|
||||||
factory.set_shared(true);
|
|
||||||
|
|
||||||
// Now we add a new mount-point and tell the RTSP server to serve the content
|
|
||||||
// provided by the factory we configured above, when a client connects to
|
|
||||||
// this specific path.
|
|
||||||
mounts.add_factory("/test", factory);
|
|
||||||
|
|
||||||
// Attach the server to our main context.
|
|
||||||
// A main context is the thing where other stuff is registering itself for its
|
|
||||||
// events (e.g. sockets, GStreamer bus, ...) and the main loop is something that
|
|
||||||
// polls the main context for its events and dispatches them to whoever is
|
|
||||||
// interested in them. In this example, we only do have one, so we can
|
|
||||||
// leave the context parameter empty, it will automatically select
|
|
||||||
// the default one.
|
|
||||||
let id = server.attach(None)?;
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Stream ready at rtsp://127.0.0.1:{}/test",
|
|
||||||
server.bound_port()
|
|
||||||
);
|
|
||||||
println!("user admin/password can access stream");
|
|
||||||
println!("user demo/demo passes authentication but receives 404");
|
|
||||||
println!("other users do not pass pass authentication and receive 401");
|
|
||||||
|
|
||||||
// Start the mainloop. From this point on, the server will start to serve
|
|
||||||
// our quality content to connecting clients.
|
|
||||||
main_loop.run();
|
|
||||||
|
|
||||||
id.remove();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Our custom auth module
|
|
||||||
mod auth {
|
|
||||||
// In the imp submodule we include the actual implementation
|
|
||||||
mod imp {
|
|
||||||
use gst_rtsp::{RTSPHeaderField, RTSPStatusCode};
|
|
||||||
use gst_rtsp_server::{prelude::*, subclass::prelude::*, RTSPContext};
|
|
||||||
|
|
||||||
// This is the private data of our auth
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Auth;
|
|
||||||
|
|
||||||
impl Auth {
|
|
||||||
// Simulate external auth validation and user extraction
|
|
||||||
// authorized users are admin/password and demo/demo
|
|
||||||
fn external_auth(&self, auth: &str) -> Option<String> {
|
|
||||||
if let Ok(decoded) = data_encoding::BASE64.decode(auth.as_bytes()) {
|
|
||||||
if let Ok(decoded) = std::str::from_utf8(&decoded) {
|
|
||||||
let tokens = decoded.split(':').collect::<Vec<_>>();
|
|
||||||
if tokens == vec!["admin", "password"] || tokens == vec!["demo", "demo"] {
|
|
||||||
return Some(tokens[0].into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simulate external role check
|
|
||||||
// admin user can construct and access media factory
|
|
||||||
fn external_access_check(&self, user: &str) -> bool {
|
|
||||||
user == "admin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This trait registers our type with the GObject object system and
|
|
||||||
// provides the entry points for creating a new instance and setting
|
|
||||||
// up the class data
|
|
||||||
#[glib::object_subclass]
|
|
||||||
impl ObjectSubclass for Auth {
|
|
||||||
const NAME: &'static str = "RsRTSPAuth";
|
|
||||||
type Type = super::Auth;
|
|
||||||
type ParentType = gst_rtsp_server::RTSPAuth;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of glib::Object virtual methods
|
|
||||||
impl ObjectImpl for Auth {}
|
|
||||||
|
|
||||||
// Implementation of gst_rtsp_server::RTSPAuth virtual methods
|
|
||||||
impl RTSPAuthImpl for Auth {
|
|
||||||
fn authenticate(&self, ctx: &RTSPContext) -> bool {
|
|
||||||
// authenticate should always be called with a valid context request
|
|
||||||
let req = ctx
|
|
||||||
.request()
|
|
||||||
.expect("Context without request. Should not happen !");
|
|
||||||
|
|
||||||
if let Some(auth_credentials) = req.parse_auth_credentials().first() {
|
|
||||||
if let Some(authorization) = auth_credentials.authorization() {
|
|
||||||
if let Some(user) = self.external_auth(authorization) {
|
|
||||||
// Update context token with authenticated username
|
|
||||||
ctx.set_token(
|
|
||||||
gst_rtsp_server::RTSPToken::builder()
|
|
||||||
.field("user", user)
|
|
||||||
.build(),
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check(&self, ctx: &RTSPContext, role: &glib::GString) -> bool {
|
|
||||||
// We only check media factory access
|
|
||||||
if !role.starts_with("auth.check.media.factory") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.token().is_none() {
|
|
||||||
// If we do not have a context token yet, check if there are any auth credentials in request
|
|
||||||
if !self.authenticate(ctx) {
|
|
||||||
// If there were no credentials, send a "401 Unauthorized" response
|
|
||||||
if let Some(resp) = ctx.response() {
|
|
||||||
resp.init_response(RTSPStatusCode::Unauthorized, ctx.request());
|
|
||||||
resp.add_header(
|
|
||||||
RTSPHeaderField::WwwAuthenticate,
|
|
||||||
"Basic realm=\"CustomRealm\"",
|
|
||||||
);
|
|
||||||
if let Some(client) = ctx.client() {
|
|
||||||
client.send_message(resp, ctx.session());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(token) = ctx.token() {
|
|
||||||
// If we already have a user token...
|
|
||||||
if self.external_access_check(&token.string("user").unwrap_or_default()) {
|
|
||||||
// grant access if user may access factory
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// send a "404 Not Found" response if user may not access factory
|
|
||||||
if let Some(resp) = ctx.response() {
|
|
||||||
resp.init_response(RTSPStatusCode::NotFound, ctx.request());
|
|
||||||
if let Some(client) = ctx.client() {
|
|
||||||
client.send_message(resp, ctx.session());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This here defines the public interface of our auth and implements
|
|
||||||
// the corresponding traits so that it behaves like any other RTSPAuth
|
|
||||||
glib::wrapper! {
|
|
||||||
pub struct Auth(ObjectSubclass<imp::Auth>) @extends gst_rtsp_server::RTSPAuth;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Auth {
|
|
||||||
// Creates a new instance of our auth
|
|
||||||
fn default() -> Self {
|
|
||||||
glib::Object::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn example_main() -> Result<(), Error> {
|
|
||||||
gst::init()?;
|
|
||||||
main_loop()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
match examples_common::run(example_main) {
|
|
||||||
Ok(r) => r,
|
|
||||||
Err(e) => eprintln!("Error! {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,10 +4,11 @@
|
||||||
// send to the server. For this, the launch syntax pipeline, that is passed
|
// send to the server. For this, the launch syntax pipeline, that is passed
|
||||||
// to this example's cli is spawned and the client's media is streamed into it.
|
// to this example's cli is spawned and the client's media is streamed into it.
|
||||||
|
|
||||||
use std::env;
|
use std::{env, ptr};
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use derive_more::{Display, Error};
|
use derive_more::{Display, Error};
|
||||||
|
use glib::translate::*;
|
||||||
use gst_rtsp_server::prelude::*;
|
use gst_rtsp_server::prelude::*;
|
||||||
|
|
||||||
#[path = "../examples-common.rs"]
|
#[path = "../examples-common.rs"]
|
||||||
|
@ -44,9 +45,10 @@ fn main_loop() -> Result<(), Error> {
|
||||||
// Here we configure a method of authentication that we want the
|
// Here we configure a method of authentication that we want the
|
||||||
// server to require from clients.
|
// server to require from clients.
|
||||||
let auth = gst_rtsp_server::RTSPAuth::new();
|
let auth = gst_rtsp_server::RTSPAuth::new();
|
||||||
let token = gst_rtsp_server::RTSPToken::builder()
|
let token = gst_rtsp_server::RTSPToken::new(&[(
|
||||||
.field(gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE, "user")
|
gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE,
|
||||||
.build();
|
&"user",
|
||||||
|
)]);
|
||||||
let basic = gst_rtsp_server::RTSPAuth::make_basic("user", "password");
|
let basic = gst_rtsp_server::RTSPAuth::make_basic("user", "password");
|
||||||
// For proper authentication, we want to use encryption. And there's no
|
// For proper authentication, we want to use encryption. And there's no
|
||||||
// encryption without a certificate!
|
// encryption without a certificate!
|
||||||
|
@ -76,14 +78,24 @@ fn main_loop() -> Result<(), Error> {
|
||||||
W535W8UBbEg=-----END PRIVATE KEY-----",
|
W535W8UBbEg=-----END PRIVATE KEY-----",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// Bindable versions were added in b1f515178a363df0322d7adbd5754e1f6e2083c9
|
||||||
// This declares that the user "user" (once authenticated) has a role that
|
// This declares that the user "user" (once authenticated) has a role that
|
||||||
// allows them to access and construct media factories.
|
// allows them to access and construct media factories.
|
||||||
factory.add_role_from_structure(
|
unsafe {
|
||||||
&gst::Structure::builder("user")
|
gst_rtsp_server::ffi::gst_rtsp_media_factory_add_role(
|
||||||
.field(gst_rtsp_server::RTSP_PERM_MEDIA_FACTORY_ACCESS, true)
|
factory.to_glib_none().0,
|
||||||
.field(gst_rtsp_server::RTSP_PERM_MEDIA_FACTORY_CONSTRUCT, true)
|
"user".to_glib_none().0,
|
||||||
.build(),
|
gst_rtsp_server::RTSP_PERM_MEDIA_FACTORY_ACCESS
|
||||||
);
|
.to_glib_none()
|
||||||
|
.0,
|
||||||
|
<bool as StaticType>::static_type().into_glib() as *const u8,
|
||||||
|
true.into_glib() as *const u8,
|
||||||
|
gst_rtsp_server::RTSP_PERM_MEDIA_FACTORY_CONSTRUCT.as_ptr() as *const u8,
|
||||||
|
<bool as StaticType>::static_type().into_glib() as *const u8,
|
||||||
|
true.into_glib() as *const u8,
|
||||||
|
ptr::null_mut::<u8>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
auth.set_tls_certificate(Some(&cert));
|
auth.set_tls_certificate(Some(&cert));
|
||||||
auth.add_basic(basic.as_str(), &token);
|
auth.add_basic(basic.as_str(), &token);
|
||||||
|
|
|
@ -19,6 +19,10 @@ mod examples_common;
|
||||||
#[display(fmt = "Could not get mount points")]
|
#[display(fmt = "Could not get mount points")]
|
||||||
struct NoMountPoints;
|
struct NoMountPoints;
|
||||||
|
|
||||||
|
#[derive(Debug, Display, Error)]
|
||||||
|
#[display(fmt = "Usage: {_0} LAUNCH_LINE")]
|
||||||
|
struct UsageError(#[error(not(source))] String);
|
||||||
|
|
||||||
fn main_loop() -> Result<(), Error> {
|
fn main_loop() -> Result<(), Error> {
|
||||||
let main_loop = glib::MainLoop::new(None, false);
|
let main_loop = glib::MainLoop::new(None, false);
|
||||||
let server = server::Server::default();
|
let server = server::Server::default();
|
||||||
|
|
|
@ -17,8 +17,8 @@ mod examples_common;
|
||||||
// Our custom FIR filter element is defined in this module
|
// Our custom FIR filter element is defined in this module
|
||||||
mod fir_filter {
|
mod fir_filter {
|
||||||
use byte_slice_cast::*;
|
use byte_slice_cast::*;
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
use gst_base::subclass::prelude::*;
|
use gst_base::subclass::prelude::*;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
// The debug category we use below for our filter
|
// The debug category we use below for our filter
|
||||||
pub static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
pub static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
||||||
|
@ -63,24 +63,20 @@ mod fir_filter {
|
||||||
// gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry
|
// gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry
|
||||||
// after initial registration without having to load the plugin in memory.
|
// after initial registration without having to load the plugin in memory.
|
||||||
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
|
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
|
||||||
static ELEMENT_METADATA: std::sync::OnceLock<gst::subclass::ElementMetadata> =
|
static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
Some(ELEMENT_METADATA.get_or_init(|| {
|
|
||||||
gst::subclass::ElementMetadata::new(
|
gst::subclass::ElementMetadata::new(
|
||||||
"FIR Filter",
|
"FIR Filter",
|
||||||
"Filter/Effect/Audio",
|
"Filter/Effect/Audio",
|
||||||
"A FIR audio filter",
|
"A FIR audio filter",
|
||||||
"Sebastian Dröge <sebastian@centricular.com>",
|
"Sebastian Dröge <sebastian@centricular.com>",
|
||||||
)
|
)
|
||||||
}))
|
});
|
||||||
|
|
||||||
|
Some(&*ELEMENT_METADATA)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pad_templates() -> &'static [gst::PadTemplate] {
|
fn pad_templates() -> &'static [gst::PadTemplate] {
|
||||||
static PAD_TEMPLATES: std::sync::OnceLock<Vec<gst::PadTemplate>> =
|
static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
PAD_TEMPLATES.get_or_init(|| {
|
|
||||||
// Create pad templates for our sink and source pad. These are later used for
|
// Create pad templates for our sink and source pad. These are later used for
|
||||||
// actually creating the pads and beforehand already provide information to
|
// actually creating the pads and beforehand already provide information to
|
||||||
// GStreamer about all possible pads that could exist for this type.
|
// GStreamer about all possible pads that could exist for this type.
|
||||||
|
@ -111,7 +107,9 @@ mod fir_filter {
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
]
|
]
|
||||||
})
|
});
|
||||||
|
|
||||||
|
PAD_TEMPLATES.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
use std::{collections::VecDeque, sync::Mutex};
|
use std::{collections::VecDeque, sync::Mutex};
|
||||||
|
|
||||||
use glib::prelude::*;
|
use glib::{once_cell::sync::Lazy, prelude::*};
|
||||||
use gst_audio::subclass::prelude::*;
|
use gst_audio::subclass::prelude::*;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
use byte_slice_cast::*;
|
use byte_slice_cast::*;
|
||||||
|
|
||||||
|
@ -153,14 +152,15 @@ impl BaseTransformImpl for IirFilter {
|
||||||
|
|
||||||
impl AudioFilterImpl for IirFilter {
|
impl AudioFilterImpl for IirFilter {
|
||||||
fn allowed_caps() -> &'static gst::Caps {
|
fn allowed_caps() -> &'static gst::Caps {
|
||||||
static CAPS: std::sync::OnceLock<gst::Caps> = std::sync::OnceLock::new();
|
static CAPS: Lazy<gst::Caps> = Lazy::new(|| {
|
||||||
CAPS.get_or_init(|| {
|
|
||||||
// On both of pads we can only handle F32 mono at any sample rate.
|
// On both of pads we can only handle F32 mono at any sample rate.
|
||||||
gst_audio::AudioCapsBuilder::new_interleaved()
|
gst_audio::AudioCapsBuilder::new_interleaved()
|
||||||
.format(gst_audio::AUDIO_FORMAT_F32)
|
.format(gst_audio::AUDIO_FORMAT_F32)
|
||||||
.channels(1)
|
.channels(1)
|
||||||
.build()
|
.build()
|
||||||
})
|
});
|
||||||
|
|
||||||
|
&CAPS
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(&self, info: &gst_audio::AudioInfo) -> Result<(), gst::LoggableError> {
|
fn setup(&self, info: &gst_audio::AudioInfo) -> Result<(), gst::LoggableError> {
|
||||||
|
|
|
@ -51,7 +51,7 @@ impl<T: IirFilterImpl> IirFilterImplExt for T {}
|
||||||
/// Class struct for `IirFilter`.
|
/// Class struct for `IirFilter`.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
parent: <<imp::IirFilter as ObjectSubclass>::ParentType as ObjectType>::GlibClassType,
|
parent: <<imp::IirFilter as ObjectSubclass>::ParentType as glib::ObjectType>::GlibClassType,
|
||||||
|
|
||||||
set_rate: fn(&IirFilter, rate: u32),
|
set_rate: fn(&IirFilter, rate: u32),
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use glib::prelude::*;
|
use glib::{once_cell::sync::Lazy, prelude::*};
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
use gst_audio::subclass::prelude::*;
|
use gst_audio::subclass::prelude::*;
|
||||||
|
|
||||||
|
@ -45,9 +45,7 @@ impl ObjectSubclass for Lowpass {
|
||||||
// Implementation of glib::Object virtual methods
|
// Implementation of glib::Object virtual methods
|
||||||
impl ObjectImpl for Lowpass {
|
impl ObjectImpl for Lowpass {
|
||||||
fn properties() -> &'static [glib::ParamSpec] {
|
fn properties() -> &'static [glib::ParamSpec] {
|
||||||
static PROPERTIES: std::sync::OnceLock<Vec<glib::ParamSpec>> = std::sync::OnceLock::new();
|
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||||
|
|
||||||
PROPERTIES.get_or_init(|| {
|
|
||||||
vec![glib::ParamSpecFloat::builder("cutoff")
|
vec![glib::ParamSpecFloat::builder("cutoff")
|
||||||
.nick("Cutoff")
|
.nick("Cutoff")
|
||||||
.blurb("Cutoff frequency in Hz")
|
.blurb("Cutoff frequency in Hz")
|
||||||
|
@ -55,7 +53,9 @@ impl ObjectImpl for Lowpass {
|
||||||
.minimum(0.0)
|
.minimum(0.0)
|
||||||
.mutable_playing()
|
.mutable_playing()
|
||||||
.build()]
|
.build()]
|
||||||
})
|
});
|
||||||
|
|
||||||
|
PROPERTIES.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||||
|
@ -84,16 +84,16 @@ impl ElementImpl for Lowpass {
|
||||||
// gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry
|
// gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry
|
||||||
// after initial registration without having to load the plugin in memory.
|
// after initial registration without having to load the plugin in memory.
|
||||||
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
|
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
|
||||||
static ELEMENT_METADATA: std::sync::OnceLock<gst::subclass::ElementMetadata> =
|
static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
|
||||||
std::sync::OnceLock::new();
|
|
||||||
Some(ELEMENT_METADATA.get_or_init(|| {
|
|
||||||
gst::subclass::ElementMetadata::new(
|
gst::subclass::ElementMetadata::new(
|
||||||
"Lowpass Filter",
|
"Lowpass Filter",
|
||||||
"Filter/Effect/Audio",
|
"Filter/Effect/Audio",
|
||||||
"A Lowpass audio filter",
|
"A Lowpass audio filter",
|
||||||
"Sebastian Dröge <sebastian@centricular.com>",
|
"Sebastian Dröge <sebastian@centricular.com>",
|
||||||
)
|
)
|
||||||
}))
|
});
|
||||||
|
|
||||||
|
Some(&*ELEMENT_METADATA)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ fn example_main() -> Result<(), Error> {
|
||||||
|
|
||||||
// Parse the pipeline we want to probe from a static in-line string.
|
// Parse the pipeline we want to probe from a static in-line string.
|
||||||
let mut context = gst::ParseContext::new();
|
let mut context = gst::ParseContext::new();
|
||||||
let pipeline = match gst::parse::launch_full(
|
let pipeline = match gst::parse_launch_full(
|
||||||
"audiotestsrc wave=white-noise num-buffers=100 ! flacenc ! filesink location=test.flac",
|
"audiotestsrc wave=white-noise num-buffers=100 ! flacenc ! filesink location=test.flac",
|
||||||
Some(&mut context),
|
Some(&mut context),
|
||||||
gst::ParseFlags::empty(),
|
gst::ParseFlags::empty(),
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use derive_more::{Display, Error};
|
use derive_more::{Display, Error};
|
||||||
use gst::{element_error, prelude::*};
|
use gst::{element_error, prelude::*};
|
||||||
use gst_video::prelude::*;
|
|
||||||
|
|
||||||
#[path = "../examples-common.rs"]
|
#[path = "../examples-common.rs"]
|
||||||
mod examples_common;
|
mod examples_common;
|
||||||
|
@ -27,7 +26,7 @@ fn create_pipeline(uri: String, out_path: std::path::PathBuf) -> Result<gst::Pip
|
||||||
gst::init()?;
|
gst::init()?;
|
||||||
|
|
||||||
// Create our pipeline from a pipeline description string.
|
// Create our pipeline from a pipeline description string.
|
||||||
let pipeline = gst::parse::launch(&format!(
|
let pipeline = gst::parse_launch(&format!(
|
||||||
"uridecodebin uri={uri} ! videoconvert ! appsink name=sink"
|
"uridecodebin uri={uri} ! videoconvert ! appsink name=sink"
|
||||||
))?
|
))?
|
||||||
.downcast::<gst::Pipeline>()
|
.downcast::<gst::Pipeline>()
|
||||||
|
|
|
@ -11,7 +11,7 @@ fn example_main() {
|
||||||
gst::init().unwrap();
|
gst::init().unwrap();
|
||||||
|
|
||||||
// This creates a pipeline by parsing the gst-launch pipeline syntax.
|
// This creates a pipeline by parsing the gst-launch pipeline syntax.
|
||||||
let pipeline = gst::parse::launch(
|
let pipeline = gst::parse_launch(
|
||||||
"videotestsrc name=src ! video/x-raw,width=640,height=480 ! compositor0.sink_0 \
|
"videotestsrc name=src ! video/x-raw,width=640,height=480 ! compositor0.sink_0 \
|
||||||
compositor ! video/x-raw,width=1280,height=720 ! videoconvert ! autovideosink",
|
compositor ! video/x-raw,width=1280,height=720 ! videoconvert ! autovideosink",
|
||||||
)
|
)
|
||||||
|
|
|
@ -83,7 +83,7 @@ fn example_main() {
|
||||||
|
|
||||||
gst::init().unwrap();
|
gst::init().unwrap();
|
||||||
|
|
||||||
let pipeline = gst::parse::launch(&format!(
|
let pipeline = gst::parse_launch(&format!(
|
||||||
"compositor name=mix background=1 sink_0::xpos=0 sink_0::ypos=0 sink_0::zorder=0 sink_0::width={WIDTH} sink_0::height={HEIGHT} ! xvimagesink \
|
"compositor name=mix background=1 sink_0::xpos=0 sink_0::ypos=0 sink_0::zorder=0 sink_0::width={WIDTH} sink_0::height={HEIGHT} ! xvimagesink \
|
||||||
videotestsrc name=src ! video/x-raw,framerate=30/1,width={WIDTH},height={HEIGHT},pixel-aspect-ratio=1/1 ! queue ! mix.sink_0"
|
videotestsrc name=src ! video/x-raw,framerate=30/1,width={WIDTH},height={HEIGHT},pixel-aspect-ratio=1/1 ! queue ! mix.sink_0"
|
||||||
)).unwrap().downcast::<gst::Pipeline>().unwrap();
|
)).unwrap().downcast::<gst::Pipeline>().unwrap();
|
||||||
|
|
|
@ -17,47 +17,13 @@ pub fn run<T, F: FnOnce() -> T + Send + 'static>(main: F) -> T
|
||||||
where
|
where
|
||||||
T: Send + 'static,
|
T: Send + 'static,
|
||||||
{
|
{
|
||||||
use std::{
|
use std::thread;
|
||||||
ffi::c_void,
|
|
||||||
sync::mpsc::{channel, Sender},
|
|
||||||
thread,
|
|
||||||
};
|
|
||||||
|
|
||||||
use cocoa::{
|
use cocoa::appkit::NSApplication;
|
||||||
appkit::{NSApplication, NSWindow},
|
|
||||||
base::id,
|
|
||||||
delegate,
|
|
||||||
};
|
|
||||||
use objc::{
|
|
||||||
class, msg_send,
|
|
||||||
runtime::{Object, Sel},
|
|
||||||
sel, sel_impl,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let app = cocoa::appkit::NSApp();
|
let app = cocoa::appkit::NSApp();
|
||||||
let (send, recv) = channel::<()>();
|
let t = thread::spawn(|| {
|
||||||
|
|
||||||
extern "C" fn on_finish_launching(this: &Object, _cmd: Sel, _notification: id) {
|
|
||||||
let send = unsafe {
|
|
||||||
let send_pointer = *this.get_ivar::<*const c_void>("send");
|
|
||||||
let boxed = Box::from_raw(send_pointer as *mut Sender<()>);
|
|
||||||
*boxed
|
|
||||||
};
|
|
||||||
send.send(()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let delegate = delegate!("AppDelegate", {
|
|
||||||
app: id = app,
|
|
||||||
send: *const c_void = Box::into_raw(Box::new(send)) as *const c_void,
|
|
||||||
(applicationDidFinishLaunching:) => on_finish_launching as extern fn(&Object, Sel, id)
|
|
||||||
});
|
|
||||||
app.setDelegate_(delegate);
|
|
||||||
|
|
||||||
let t = thread::spawn(move || {
|
|
||||||
// Wait for the NSApp to launch to avoid possibly calling stop_() too early
|
|
||||||
recv.recv().unwrap();
|
|
||||||
|
|
||||||
let res = main();
|
let res = main();
|
||||||
|
|
||||||
let app = cocoa::appkit::NSApp();
|
let app = cocoa::appkit::NSApp();
|
||||||
|
|
|
@ -691,7 +691,7 @@ pub(crate) fn main_loop(app: App) -> Result<()> {
|
||||||
..
|
..
|
||||||
} = app;
|
} = app;
|
||||||
|
|
||||||
let mut curr_frame: Option<gst_gl::GLVideoFrame<gst_gl::gl_video_frame::Readable>> = None;
|
let mut curr_frame: Option<gst_video::VideoFrame<gst_video::video_frame::Readable>> = None;
|
||||||
|
|
||||||
let mut running_state = None::<(
|
let mut running_state = None::<(
|
||||||
Gl,
|
Gl,
|
||||||
|
@ -740,7 +740,7 @@ pub(crate) fn main_loop(app: App) -> Result<()> {
|
||||||
},
|
},
|
||||||
// Receive a frame
|
// Receive a frame
|
||||||
winit::event::Event::UserEvent(Message::Frame(info, buffer)) => {
|
winit::event::Event::UserEvent(Message::Frame(info, buffer)) => {
|
||||||
if let Ok(frame) = gst_gl::GLVideoFrame::from_buffer_readable(buffer, &info) {
|
if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) {
|
||||||
curr_frame = Some(frame);
|
curr_frame = Some(frame);
|
||||||
needs_redraw = true;
|
needs_redraw = true;
|
||||||
}
|
}
|
||||||
|
@ -808,7 +808,7 @@ pub(crate) fn main_loop(app: App) -> Result<()> {
|
||||||
if let Some(frame) = curr_frame.as_ref() {
|
if let Some(frame) = curr_frame.as_ref() {
|
||||||
let sync_meta = frame.buffer().meta::<gst_gl::GLSyncMeta>().unwrap();
|
let sync_meta = frame.buffer().meta::<gst_gl::GLSyncMeta>().unwrap();
|
||||||
sync_meta.wait(&shared_context);
|
sync_meta.wait(&shared_context);
|
||||||
if let Ok(texture) = frame.texture_id(0) {
|
if let Some(texture) = frame.texture_id(0) {
|
||||||
gl.draw_frame(texture as gl::types::GLuint);
|
gl.draw_frame(texture as gl::types::GLuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
gir
2
gir
|
@ -1 +1 @@
|
||||||
Subproject commit 5223ce91b97a833b09d6cbd04bbeab1bf18112b7
|
Subproject commit 23d7c100187cb4767ef77e0e4b3a511cbfadf035
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6cd7b656acd61172ab7f125a7059e4d0ecfc9637
|
Subproject commit 6415239ef4354633334410cfae108e64ae7ff708
|
|
@ -1 +1 @@
|
||||||
Subproject commit c988e03b5e99349efb8ffb6f502879ad4ddbc248
|
Subproject commit 62054dc7234dfe1499245ce19ac9454dcb5dd594
|
|
@ -1,24 +1,23 @@
|
||||||
[package]
|
[package]
|
||||||
name = "gstreamer-allocators"
|
name = "gstreamer-allocators"
|
||||||
|
version = "0.21.3"
|
||||||
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
||||||
|
categories = ["api-bindings", "multimedia"]
|
||||||
description = "Rust bindings for GStreamer Allocators library"
|
description = "Rust bindings for GStreamer Allocators library"
|
||||||
|
repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
homepage = "https://gstreamer.freedesktop.org"
|
||||||
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_allocators/"
|
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_allocators/"
|
||||||
keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"]
|
keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"]
|
||||||
version.workspace = true
|
edition = "2021"
|
||||||
categories.workspace = true
|
rust-version = "1.70"
|
||||||
repository.workspace = true
|
|
||||||
homepage.workspace = true
|
|
||||||
edition.workspace = true
|
|
||||||
rust-version.workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
ffi = { package = "gstreamer-allocators-sys", path = "sys" }
|
ffi = { package = "gstreamer-allocators-sys", path = "sys", version = "0.21" }
|
||||||
glib.workspace = true
|
glib = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "0.18", version = "0.18" }
|
||||||
gst.workspace = true
|
gst = { package = "gstreamer", path = "../gstreamer", version = "0.21" }
|
||||||
once_cell = "1"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
gir-format-check = "0.1"
|
gir-format-check = "0.1"
|
||||||
|
@ -30,7 +29,6 @@ v1_18 = ["gst/v1_18", "ffi/v1_18", "v1_16"]
|
||||||
v1_20 = ["gst/v1_20", "ffi/v1_20", "v1_18"]
|
v1_20 = ["gst/v1_20", "ffi/v1_20", "v1_18"]
|
||||||
v1_22 = ["gst/v1_22", "ffi/v1_22", "v1_20"]
|
v1_22 = ["gst/v1_22", "ffi/v1_22", "v1_20"]
|
||||||
v1_24 = ["gst/v1_24", "ffi/v1_24", "v1_22"]
|
v1_24 = ["gst/v1_24", "ffi/v1_24", "v1_22"]
|
||||||
v1_26 = ["gst/v1_26", "ffi/v1_26", "v1_24"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub use self::shm_allocator::ShmAllocator;
|
||||||
mod flags;
|
mod flags;
|
||||||
pub use self::flags::FdMemoryFlags;
|
pub use self::flags::FdMemoryFlags;
|
||||||
|
|
||||||
pub(crate) mod functions;
|
pub mod functions;
|
||||||
|
|
||||||
mod constants;
|
mod constants;
|
||||||
pub use self::constants::ALLOCATOR_DMABUF;
|
pub use self::constants::ALLOCATOR_DMABUF;
|
||||||
|
@ -51,6 +51,7 @@ pub use self::constants::ALLOCATOR_FD;
|
||||||
pub use self::constants::ALLOCATOR_SHM;
|
pub use self::constants::ALLOCATOR_SHM;
|
||||||
pub use self::constants::CAPS_FEATURE_MEMORY_DMABUF;
|
pub use self::constants::CAPS_FEATURE_MEMORY_DMABUF;
|
||||||
|
|
||||||
pub(crate) mod traits {
|
#[doc(hidden)]
|
||||||
|
pub mod traits {
|
||||||
pub use super::phys_memory_allocator::PhysMemoryAllocatorExt;
|
pub use super::phys_memory_allocator::PhysMemoryAllocatorExt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Generated by gir (https://github.com/gtk-rs/gir @ 5223ce91b97a)
|
Generated by gir (https://github.com/gtk-rs/gir @ 23d7c100187c)
|
||||||
from gir-files (https://github.com/gtk-rs/gir-files @ 6cd7b656acd6)
|
from gir-files (https://github.com/gtk-rs/gir-files @ 6415239ef435)
|
||||||
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ c988e03b5e99)
|
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 62054dc7234d)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Take a look at the license at the top of the repository in the LICENSE file.
|
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||||
|
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
use gst::CapsFeatures;
|
use gst::CapsFeatures;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
pub static CAPS_FEATURES_MEMORY_DMABUF: Lazy<CapsFeatures> =
|
pub static CAPS_FEATURES_MEMORY_DMABUF: Lazy<CapsFeatures> =
|
||||||
Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_DMABUF]));
|
Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_DMABUF]));
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::{
|
||||||
os::unix::prelude::{IntoRawFd, RawFd},
|
os::unix::prelude::{IntoRawFd, RawFd},
|
||||||
};
|
};
|
||||||
|
|
||||||
use glib::{prelude::*, translate::*};
|
use glib::{translate::*, Cast};
|
||||||
use gst::{Memory, MemoryRef};
|
use gst::{Memory, MemoryRef};
|
||||||
|
|
||||||
#[cfg(feature = "v1_16")]
|
#[cfg(feature = "v1_16")]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{fmt, mem, os::unix::prelude::IntoRawFd};
|
use std::{fmt, mem, os::unix::prelude::IntoRawFd};
|
||||||
|
|
||||||
use glib::{prelude::*, translate::*};
|
use glib::{translate::*, Cast};
|
||||||
use gst::{Memory, MemoryRef};
|
use gst::{Memory, MemoryRef};
|
||||||
|
|
||||||
use crate::{DRMDumbAllocator, DmaBufMemory};
|
use crate::{DRMDumbAllocator, DmaBufMemory};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{fmt, os::unix::prelude::RawFd};
|
use std::{fmt, os::unix::prelude::RawFd};
|
||||||
|
|
||||||
use glib::{prelude::*, translate::*};
|
use glib::{translate::*, Cast};
|
||||||
use gst::{Memory, MemoryRef};
|
use gst::{Memory, MemoryRef};
|
||||||
|
|
||||||
use crate::{FdAllocator, FdMemoryFlags};
|
use crate::{FdAllocator, FdMemoryFlags};
|
||||||
|
|
|
@ -56,8 +56,6 @@ pub use phys_memory::*;
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use gst::prelude::*;
|
pub use gst::prelude::*;
|
||||||
|
|
||||||
pub use crate::auto::traits::*;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod subclass;
|
pub mod subclass;
|
||||||
|
|
|
@ -4,14 +4,22 @@ system-deps = "6"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
||||||
[dependencies.glib-sys]
|
[dependencies.glib]
|
||||||
workspace = true
|
git = "https://github.com/gtk-rs/gtk-rs-core"
|
||||||
|
package = "glib-sys"
|
||||||
|
branch = "0.18"
|
||||||
|
version = "0.18"
|
||||||
|
|
||||||
[dependencies.gobject-sys]
|
[dependencies.gobject]
|
||||||
workspace = true
|
git = "https://github.com/gtk-rs/gtk-rs-core"
|
||||||
|
package = "gobject-sys"
|
||||||
|
branch = "0.18"
|
||||||
|
version = "0.18"
|
||||||
|
|
||||||
[dependencies.gstreamer-sys]
|
[dependencies.gst]
|
||||||
workspace = true
|
package = "gstreamer-sys"
|
||||||
|
path = "../../gstreamer/sys"
|
||||||
|
version = "0.21"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
shell-words = "1.0.0"
|
shell-words = "1.0.0"
|
||||||
|
@ -23,7 +31,6 @@ v1_18 = ["v1_16"]
|
||||||
v1_20 = ["v1_18"]
|
v1_20 = ["v1_18"]
|
||||||
v1_22 = ["v1_20"]
|
v1_22 = ["v1_20"]
|
||||||
v1_24 = ["v1_22"]
|
v1_24 = ["v1_22"]
|
||||||
v1_26 = ["v1_24"]
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "gstreamer_allocators_sys"
|
name = "gstreamer_allocators_sys"
|
||||||
|
@ -33,28 +40,15 @@ authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
description = "FFI bindings to libgstallocators-1.0"
|
description = "FFI bindings to libgstallocators-1.0"
|
||||||
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_allocators_sys/"
|
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_allocators_sys/"
|
||||||
|
edition = "2021"
|
||||||
|
homepage = "https://gstreamer.freedesktop.org"
|
||||||
keywords = ["ffi", "gstreamer", "gnome", "multimedia"]
|
keywords = ["ffi", "gstreamer", "gnome", "multimedia"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "gstreamer-allocators-sys"
|
name = "gstreamer-allocators-sys"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs"
|
||||||
[package.version]
|
rust-version = "1.70"
|
||||||
workspace = true
|
version = "0.21.3"
|
||||||
|
|
||||||
[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]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
@ -78,7 +72,4 @@ version = "1.20"
|
||||||
version = "1.22"
|
version = "1.22"
|
||||||
|
|
||||||
[package.metadata.system-deps.gstreamer_allocators_1_0.v1_24]
|
[package.metadata.system-deps.gstreamer_allocators_1_0.v1_24]
|
||||||
version = "1.24"
|
version = "1.23"
|
||||||
|
|
||||||
[package.metadata.system-deps.gstreamer_allocators_1_0.v1_26]
|
|
||||||
version = "1.25"
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Generated by gir (https://github.com/gtk-rs/gir @ 5223ce91b97a)
|
Generated by gir (https://github.com/gtk-rs/gir @ 23d7c100187c)
|
||||||
from gir-files (https://github.com/gtk-rs/gir-files @ 6cd7b656acd6)
|
from gir-files (https://github.com/gtk-rs/gir-files @ 6415239ef435)
|
||||||
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ c988e03b5e99)
|
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 62054dc7234d)
|
||||||
|
|
|
@ -12,18 +12,11 @@
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
|
||||||
use glib_sys as glib;
|
|
||||||
use gobject_sys as gobject;
|
|
||||||
use gstreamer_sys as gst;
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use libc::{
|
use libc::{
|
||||||
c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void,
|
c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void,
|
||||||
intptr_t, off_t, size_t, ssize_t, time_t, uintptr_t, FILE,
|
intptr_t, size_t, ssize_t, uintptr_t, FILE,
|
||||||
};
|
};
|
||||||
#[cfg(unix)]
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use libc::{dev_t, gid_t, pid_t, socklen_t, uid_t};
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use glib::{gboolean, gconstpointer, gpointer, GType};
|
use glib::{gboolean, gconstpointer, gpointer, GType};
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::error::Error;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::mem::{align_of, size_of};
|
use std::mem::{align_of, size_of};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::Command;
|
||||||
use std::str;
|
use std::str;
|
||||||
use tempfile::Builder;
|
use tempfile::Builder;
|
||||||
|
|
||||||
|
@ -71,11 +71,9 @@ fn pkg_config_cflags(packages: &[&str]) -> Result<Vec<String>, Box<dyn Error>> {
|
||||||
let mut cmd = Command::new(pkg_config);
|
let mut cmd = Command::new(pkg_config);
|
||||||
cmd.arg("--cflags");
|
cmd.arg("--cflags");
|
||||||
cmd.args(packages);
|
cmd.args(packages);
|
||||||
cmd.stderr(Stdio::inherit());
|
|
||||||
let out = cmd.output()?;
|
let out = cmd.output()?;
|
||||||
if !out.status.success() {
|
if !out.status.success() {
|
||||||
let (status, stdout) = (out.status, String::from_utf8_lossy(&out.stdout));
|
return Err(format!("command {cmd:?} returned {}", out.status).into());
|
||||||
return Err(format!("command {cmd:?} failed, {status:?}\nstdout: {stdout}").into());
|
|
||||||
}
|
}
|
||||||
let stdout = str::from_utf8(&out.stdout)?;
|
let stdout = str::from_utf8(&out.stdout)?;
|
||||||
Ok(shell_words::split(stdout.trim())?)
|
Ok(shell_words::split(stdout.trim())?)
|
||||||
|
@ -190,15 +188,13 @@ fn get_c_output(name: &str) -> Result<String, Box<dyn Error>> {
|
||||||
let cc = Compiler::new().expect("configured compiler");
|
let cc = Compiler::new().expect("configured compiler");
|
||||||
cc.compile(&c_file, &exe)?;
|
cc.compile(&c_file, &exe)?;
|
||||||
|
|
||||||
let mut cmd = Command::new(exe);
|
let mut abi_cmd = Command::new(exe);
|
||||||
cmd.stderr(Stdio::inherit());
|
let output = abi_cmd.output()?;
|
||||||
let out = cmd.output()?;
|
if !output.status.success() {
|
||||||
if !out.status.success() {
|
return Err(format!("command {abi_cmd:?} failed, {output:?}").into());
|
||||||
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)?)
|
Ok(String::from_utf8(output.stdout)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
const RUST_LAYOUTS: &[(&str, Layout)] = &[
|
const RUST_LAYOUTS: &[(&str, Layout)] = &[
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../gstreamer/CHANGELOG.md
|
|
|
@ -1 +0,0 @@
|
||||||
../COPYRIGHT
|
|
|
@ -1,32 +0,0 @@
|
||||||
[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 = []
|
|
||||||
v1_26 = ["gst/v1_26", "ffi/v1_26"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
all-features = true
|
|
||||||
rustc-args = ["--cfg", "docsrs"]
|
|
||||||
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]
|
|
|
@ -1,34 +0,0 @@
|
||||||
[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"
|
|
|
@ -1 +0,0 @@
|
||||||
../LICENSE-APACHE
|
|
|
@ -1 +0,0 @@
|
||||||
../LICENSE-MIT
|
|
|
@ -1,214 +0,0 @@
|
||||||
# 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.
|
|
|
@ -1,44 +0,0 @@
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
// 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;
|
|
|
@ -1,3 +0,0 @@
|
||||||
Generated by gir (https://github.com/gtk-rs/gir @ 5223ce91b97a)
|
|
||||||
from gir-files (https://github.com/gtk-rs/gir-files @ 6cd7b656acd6)
|
|
||||||
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ c988e03b5e99)
|
|
|
@ -1,212 +0,0 @@
|
||||||
// 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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
// 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;
|
|
||||||
}
|
|
|
@ -1,175 +0,0 @@
|
||||||
// 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(Clone, Copy, Default, Debug)]
|
|
||||||
pub struct AnalyticsODLocation {
|
|
||||||
pub x: i32,
|
|
||||||
pub y: i32,
|
|
||||||
pub w: i32,
|
|
||||||
pub h: i32,
|
|
||||||
pub 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) -> Option<glib::Quark> {
|
|
||||||
unsafe {
|
|
||||||
let mut mtd = from(ffi::GstAnalyticsMtd::unsafe_from(self));
|
|
||||||
let type_ = ffi::gst_analytics_od_mtd_get_obj_type(&mut mtd);
|
|
||||||
if type_ == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(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().unwrap(), 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().unwrap(), 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,706 +0,0 @@
|
||||||
// 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(), ¶ms);
|
|
||||||
|
|
||||||
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().unwrap(), 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().unwrap(), 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().unwrap(), 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
../../gstreamer/CHANGELOG.md
|
|
|
@ -1 +0,0 @@
|
||||||
../../COPYRIGHT
|
|
|
@ -1,61 +0,0 @@
|
||||||
[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.24"
|
|
||||||
|
|
||||||
[package.metadata.system-deps.gstreamer_analytics_1_0.v1_26]
|
|
||||||
version = "1.25"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
v1_26 = []
|
|
|
@ -1,48 +0,0 @@
|
||||||
[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
|
|
|
@ -1 +0,0 @@
|
||||||
../../LICENSE-MIT
|
|
|
@ -1,31 +0,0 @@
|
||||||
# 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.
|
|
|
@ -1,18 +0,0 @@
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
Generated by gir (https://github.com/gtk-rs/gir @ 5223ce91b97a)
|
|
||||||
from gir-files (https://github.com/gtk-rs/gir-files @ 6cd7b656acd6)
|
|
||||||
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ c988e03b5e99)
|
|
|
@ -1,338 +0,0 @@
|
||||||
// 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, off_t, size_t, ssize_t, time_t, uintptr_t, FILE,
|
|
||||||
};
|
|
||||||
#[cfg(unix)]
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use libc::{dev_t, gid_t, pid_t, socklen_t, uid_t};
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use glib::{gboolean, gconstpointer, gpointer, GType};
|
|
||||||
|
|
||||||
// Aliases
|
|
||||||
pub type GstAnalyticsMtdType = uintptr_t;
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
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)
|
|
||||||
.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;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,272 +0,0 @@
|
||||||
// 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_INF_RELATION_SPAN", "-1"),
|
|
||||||
];
|
|
|
@ -1,41 +0,0 @@
|
||||||
// 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_INF_RELATION_SPAN);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// 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;
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
// Feel free to edit this file, it won't be regenerated by gir generator unless removed.
|
|
||||||
|
|
||||||
#include <gst/analytics/analytics.h>
|
|
|
@ -1,26 +1,26 @@
|
||||||
[package]
|
[package]
|
||||||
name = "gstreamer-app"
|
name = "gstreamer-app"
|
||||||
|
version = "0.21.3"
|
||||||
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
||||||
|
categories = ["api-bindings", "multimedia"]
|
||||||
description = "Rust bindings for GStreamer App library"
|
description = "Rust bindings for GStreamer App library"
|
||||||
|
repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
homepage = "https://gstreamer.freedesktop.org"
|
||||||
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_app/"
|
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_app/"
|
||||||
keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"]
|
keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"]
|
||||||
version.workspace = true
|
edition = "2021"
|
||||||
categories.workspace = true
|
rust-version = "1.70"
|
||||||
repository.workspace = true
|
|
||||||
homepage.workspace = true
|
|
||||||
edition.workspace = true
|
|
||||||
rust-version.workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures-core = "0.3"
|
futures-core = "0.3"
|
||||||
futures-sink = "0.3"
|
futures-sink = "0.3"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
ffi = { package = "gstreamer-app-sys", path = "sys" }
|
ffi = { package = "gstreamer-app-sys", path = "sys", version = "0.21.1" }
|
||||||
glib.workspace = true
|
glib = { git = "https://github.com/gtk-rs/gtk-rs-core", branch = "0.18", version = "0.18" }
|
||||||
gst.workspace = true
|
gst = { package = "gstreamer", path = "../gstreamer", version = "0.21" }
|
||||||
gst-base.workspace = true
|
gst-base = { package = "gstreamer-base", path = "../gstreamer-base", version = "0.21" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures-util = { version = "0.3", features = ["sink"] }
|
futures-util = { version = "0.3", features = ["sink"] }
|
||||||
|
@ -34,7 +34,6 @@ v1_18 = ["gst/v1_18", "gst-base/v1_18", "ffi/v1_18", "v1_16"]
|
||||||
v1_20 = ["gst/v1_20", "gst-base/v1_20", "ffi/v1_20", "v1_18"]
|
v1_20 = ["gst/v1_20", "gst-base/v1_20", "ffi/v1_20", "v1_18"]
|
||||||
v1_22 = ["gst/v1_22", "gst-base/v1_22", "ffi/v1_22", "v1_20"]
|
v1_22 = ["gst/v1_22", "gst-base/v1_22", "ffi/v1_22", "v1_20"]
|
||||||
v1_24 = ["gst/v1_24", "gst-base/v1_24", "ffi/v1_24", "v1_22"]
|
v1_24 = ["gst/v1_24", "gst-base/v1_24", "ffi/v1_24", "v1_22"]
|
||||||
v1_26 = ["gst/v1_26", "gst-base/v1_26", "ffi/v1_26", "v1_24"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
|
@ -4,13 +4,13 @@ use std::{
|
||||||
mem, panic,
|
mem, panic,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
ptr,
|
ptr,
|
||||||
sync::{Arc, Mutex},
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc, Mutex,
|
||||||
|
},
|
||||||
task::{Context, Poll, Waker},
|
task::{Context, Poll, Waker},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
use futures_core::Stream;
|
use futures_core::Stream;
|
||||||
use glib::{ffi::gpointer, prelude::*, translate::*};
|
use glib::{ffi::gpointer, prelude::*, translate::*};
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ pub struct AppSinkCallbacks {
|
||||||
new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>,
|
new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>,
|
||||||
propose_allocation:
|
propose_allocation:
|
||||||
Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>,
|
Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>,
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
panicked: AtomicBool,
|
panicked: AtomicBool,
|
||||||
callbacks: ffi::GstAppSinkCallbacks,
|
callbacks: ffi::GstAppSinkCallbacks,
|
||||||
}
|
}
|
||||||
|
@ -72,14 +71,6 @@ impl AppSinkCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eos_if_some<F: FnMut(&AppSink) + Send + 'static>(self, eos: Option<F>) -> Self {
|
|
||||||
if let Some(eos) = eos {
|
|
||||||
self.eos(eos)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_preroll<
|
pub fn new_preroll<
|
||||||
F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
|
F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
|
||||||
>(
|
>(
|
||||||
|
@ -92,19 +83,6 @@ impl AppSinkCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_preroll_if_some<
|
|
||||||
F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
|
|
||||||
>(
|
|
||||||
self,
|
|
||||||
new_preroll: Option<F>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(new_preroll) = new_preroll {
|
|
||||||
self.new_preroll(new_preroll)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_sample<
|
pub fn new_sample<
|
||||||
F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
|
F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
|
||||||
>(
|
>(
|
||||||
|
@ -117,19 +95,6 @@ impl AppSinkCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_sample_if_some<
|
|
||||||
F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
|
|
||||||
>(
|
|
||||||
self,
|
|
||||||
new_sample: Option<F>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(new_sample) = new_sample {
|
|
||||||
self.new_sample(new_sample)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "v1_20")]
|
#[cfg(feature = "v1_20")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
|
||||||
pub fn new_event<F: FnMut(&AppSink) -> bool + Send + 'static>(self, new_event: F) -> Self {
|
pub fn new_event<F: FnMut(&AppSink) -> bool + Send + 'static>(self, new_event: F) -> Self {
|
||||||
|
@ -139,19 +104,6 @@ impl AppSinkCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v1_20")]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
|
|
||||||
pub fn new_event_if_some<F: FnMut(&AppSink) -> bool + Send + 'static>(
|
|
||||||
self,
|
|
||||||
new_event: Option<F>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(new_event) = new_event {
|
|
||||||
self.new_event(new_event)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "v1_24")]
|
#[cfg(feature = "v1_24")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
|
||||||
pub fn propose_allocation<
|
pub fn propose_allocation<
|
||||||
|
@ -166,21 +118,6 @@ impl AppSinkCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v1_24")]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
|
|
||||||
pub fn propose_allocation_if_some<
|
|
||||||
F: FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static,
|
|
||||||
>(
|
|
||||||
self,
|
|
||||||
propose_allocation: Option<F>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(propose_allocation) = propose_allocation {
|
|
||||||
self.propose_allocation(propose_allocation)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use = "Building the callbacks without using them has no effect"]
|
#[must_use = "Building the callbacks without using them has no effect"]
|
||||||
pub fn build(self) -> AppSinkCallbacks {
|
pub fn build(self) -> AppSinkCallbacks {
|
||||||
let have_eos = self.eos.is_some();
|
let have_eos = self.eos.is_some();
|
||||||
|
@ -195,7 +132,6 @@ impl AppSinkCallbacksBuilder {
|
||||||
new_sample: self.new_sample,
|
new_sample: self.new_sample,
|
||||||
new_event: self.new_event,
|
new_event: self.new_event,
|
||||||
propose_allocation: self.propose_allocation,
|
propose_allocation: self.propose_allocation,
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
panicked: AtomicBool::new(false),
|
panicked: AtomicBool::new(false),
|
||||||
callbacks: ffi::GstAppSinkCallbacks {
|
callbacks: ffi::GstAppSinkCallbacks {
|
||||||
eos: if have_eos { Some(trampoline_eos) } else { None },
|
eos: if have_eos { Some(trampoline_eos) } else { None },
|
||||||
|
@ -229,7 +165,6 @@ unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gp
|
||||||
let callbacks = callbacks as *mut AppSinkCallbacks;
|
let callbacks = callbacks as *mut AppSinkCallbacks;
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -241,19 +176,12 @@ unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gp
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,7 +194,6 @@ unsafe extern "C" fn trampoline_new_preroll(
|
||||||
let callbacks = callbacks as *mut AppSinkCallbacks;
|
let callbacks = callbacks as *mut AppSinkCallbacks;
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -278,21 +205,14 @@ unsafe extern "C" fn trampoline_new_preroll(
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
|
|
||||||
gst::FlowReturn::Error
|
gst::FlowReturn::Error
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -309,7 +229,6 @@ unsafe extern "C" fn trampoline_new_sample(
|
||||||
let callbacks = callbacks as *mut AppSinkCallbacks;
|
let callbacks = callbacks as *mut AppSinkCallbacks;
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -321,21 +240,14 @@ unsafe extern "C" fn trampoline_new_sample(
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
|
|
||||||
gst::FlowReturn::Error
|
gst::FlowReturn::Error
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -352,7 +264,6 @@ unsafe extern "C" fn trampoline_new_event(
|
||||||
let callbacks = callbacks as *mut AppSinkCallbacks;
|
let callbacks = callbacks as *mut AppSinkCallbacks;
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -364,21 +275,14 @@ unsafe extern "C" fn trampoline_new_event(
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -396,7 +300,6 @@ unsafe extern "C" fn trampoline_propose_allocation(
|
||||||
let callbacks = callbacks as *mut AppSinkCallbacks;
|
let callbacks = callbacks as *mut AppSinkCallbacks;
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -414,20 +317,14 @@ unsafe extern "C" fn trampoline_propose_allocation(
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
false
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -453,23 +350,23 @@ impl AppSink {
|
||||||
|
|
||||||
#[doc(alias = "gst_app_sink_set_callbacks")]
|
#[doc(alias = "gst_app_sink_set_callbacks")]
|
||||||
pub fn set_callbacks(&self, callbacks: AppSinkCallbacks) {
|
pub fn set_callbacks(&self, callbacks: AppSinkCallbacks) {
|
||||||
|
#[cfg(not(feature = "v1_18"))]
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
|
#[cfg(not(feature = "v1_18"))]
|
||||||
|
static SET_ONCE_QUARK: Lazy<glib::Quark> =
|
||||||
|
Lazy::new(|| glib::Quark::from_str("gstreamer-rs-app-sink-callbacks"));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let sink = self.to_glib_none().0;
|
let sink = self.to_glib_none().0;
|
||||||
|
|
||||||
#[cfg(not(feature = "v1_18"))]
|
#[cfg(not(feature = "v1_18"))]
|
||||||
{
|
{
|
||||||
static SET_ONCE_QUARK: std::sync::OnceLock<glib::Quark> =
|
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
let set_once_quark = SET_ONCE_QUARK
|
|
||||||
.get_or_init(|| glib::Quark::from_str("gstreamer-rs-app-sink-callbacks"));
|
|
||||||
|
|
||||||
// This is not thread-safe before 1.16.3, see
|
// This is not thread-safe before 1.16.3, see
|
||||||
// https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/570
|
// https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/570
|
||||||
if gst::version() < (1, 16, 3, 0) {
|
if gst::version() < (1, 16, 3, 0) {
|
||||||
if !glib::gobject_ffi::g_object_get_qdata(
|
if !glib::gobject_ffi::g_object_get_qdata(
|
||||||
sink as *mut _,
|
sink as *mut _,
|
||||||
set_once_quark.into_glib(),
|
SET_ONCE_QUARK.into_glib(),
|
||||||
)
|
)
|
||||||
.is_null()
|
.is_null()
|
||||||
{
|
{
|
||||||
|
@ -478,7 +375,7 @@ impl AppSink {
|
||||||
|
|
||||||
glib::gobject_ffi::g_object_set_qdata(
|
glib::gobject_ffi::g_object_set_qdata(
|
||||||
sink as *mut _,
|
sink as *mut _,
|
||||||
set_once_quark.into_glib(),
|
SET_ONCE_QUARK.into_glib(),
|
||||||
1 as *mut _,
|
1 as *mut _,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ use std::{
|
||||||
mem, panic,
|
mem, panic,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
ptr,
|
ptr,
|
||||||
sync::{Arc, Mutex},
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc, Mutex,
|
||||||
|
},
|
||||||
task::{Context, Poll, Waker},
|
task::{Context, Poll, Waker},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
use futures_sink::Sink;
|
use futures_sink::Sink;
|
||||||
use glib::{
|
use glib::{
|
||||||
ffi::{gboolean, gpointer},
|
ffi::{gboolean, gpointer},
|
||||||
|
@ -25,7 +25,6 @@ pub struct AppSrcCallbacks {
|
||||||
need_data: Option<Box<dyn FnMut(&AppSrc, u32) + Send + 'static>>,
|
need_data: Option<Box<dyn FnMut(&AppSrc, u32) + Send + 'static>>,
|
||||||
enough_data: Option<Box<dyn Fn(&AppSrc) + Send + Sync + 'static>>,
|
enough_data: Option<Box<dyn Fn(&AppSrc) + Send + Sync + 'static>>,
|
||||||
seek_data: Option<Box<dyn Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>>,
|
seek_data: Option<Box<dyn Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>>,
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
panicked: AtomicBool,
|
panicked: AtomicBool,
|
||||||
callbacks: ffi::GstAppSrcCallbacks,
|
callbacks: ffi::GstAppSrcCallbacks,
|
||||||
}
|
}
|
||||||
|
@ -61,17 +60,6 @@ impl AppSrcCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn need_data_if_some<F: FnMut(&AppSrc, u32) + Send + 'static>(
|
|
||||||
self,
|
|
||||||
need_data: Option<F>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(need_data) = need_data {
|
|
||||||
self.need_data(need_data)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn enough_data<F: Fn(&AppSrc) + Send + Sync + 'static>(self, enough_data: F) -> Self {
|
pub fn enough_data<F: Fn(&AppSrc) + Send + Sync + 'static>(self, enough_data: F) -> Self {
|
||||||
Self {
|
Self {
|
||||||
enough_data: Some(Box::new(enough_data)),
|
enough_data: Some(Box::new(enough_data)),
|
||||||
|
@ -79,17 +67,6 @@ impl AppSrcCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enough_data_if_some<F: Fn(&AppSrc) + Send + Sync + 'static>(
|
|
||||||
self,
|
|
||||||
enough_data: Option<F>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(enough_data) = enough_data {
|
|
||||||
self.enough_data(enough_data)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn seek_data<F: Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>(
|
pub fn seek_data<F: Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>(
|
||||||
self,
|
self,
|
||||||
seek_data: F,
|
seek_data: F,
|
||||||
|
@ -100,17 +77,6 @@ impl AppSrcCallbacksBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seek_data_if_some<F: Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>(
|
|
||||||
self,
|
|
||||||
seek_data: Option<F>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(seek_data) = seek_data {
|
|
||||||
self.seek_data(seek_data)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use = "Building the callbacks without using them has no effect"]
|
#[must_use = "Building the callbacks without using them has no effect"]
|
||||||
pub fn build(self) -> AppSrcCallbacks {
|
pub fn build(self) -> AppSrcCallbacks {
|
||||||
let have_need_data = self.need_data.is_some();
|
let have_need_data = self.need_data.is_some();
|
||||||
|
@ -121,7 +87,6 @@ impl AppSrcCallbacksBuilder {
|
||||||
need_data: self.need_data,
|
need_data: self.need_data,
|
||||||
enough_data: self.enough_data,
|
enough_data: self.enough_data,
|
||||||
seek_data: self.seek_data,
|
seek_data: self.seek_data,
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
panicked: AtomicBool::new(false),
|
panicked: AtomicBool::new(false),
|
||||||
callbacks: ffi::GstAppSrcCallbacks {
|
callbacks: ffi::GstAppSrcCallbacks {
|
||||||
need_data: if have_need_data {
|
need_data: if have_need_data {
|
||||||
|
@ -158,7 +123,6 @@ unsafe extern "C" fn trampoline_need_data(
|
||||||
let callbacks = callbacks as *mut AppSrcCallbacks;
|
let callbacks = callbacks as *mut AppSrcCallbacks;
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -170,19 +134,12 @@ unsafe extern "C" fn trampoline_need_data(
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,7 +149,6 @@ unsafe extern "C" fn trampoline_enough_data(appsrc: *mut ffi::GstAppSrc, callbac
|
||||||
let callbacks = callbacks as *const AppSrcCallbacks;
|
let callbacks = callbacks as *const AppSrcCallbacks;
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -204,19 +160,12 @@ unsafe extern "C" fn trampoline_enough_data(appsrc: *mut ffi::GstAppSrc, callbac
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,7 +179,6 @@ unsafe extern "C" fn trampoline_seek_data(
|
||||||
let callbacks = callbacks as *const AppSrcCallbacks;
|
let callbacks = callbacks as *const AppSrcCallbacks;
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||||
|
|
||||||
#[cfg(not(panic = "abort"))]
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||||
|
@ -242,21 +190,14 @@ unsafe extern "C" fn trampoline_seek_data(
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
#[cfg(panic = "abort")]
|
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||||
{
|
gst::subclass::post_panic_error_message(
|
||||||
unreachable!("{err:?}");
|
element.upcast_ref(),
|
||||||
}
|
element.upcast_ref(),
|
||||||
#[cfg(not(panic = "abort"))]
|
Some(err),
|
||||||
{
|
);
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
|
||||||
gst::subclass::post_panic_error_message(
|
|
||||||
element.upcast_ref(),
|
|
||||||
element.upcast_ref(),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -282,22 +223,22 @@ impl AppSrc {
|
||||||
|
|
||||||
#[doc(alias = "gst_app_src_set_callbacks")]
|
#[doc(alias = "gst_app_src_set_callbacks")]
|
||||||
pub fn set_callbacks(&self, callbacks: AppSrcCallbacks) {
|
pub fn set_callbacks(&self, callbacks: AppSrcCallbacks) {
|
||||||
|
#[cfg(not(feature = "v1_18"))]
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
|
#[cfg(not(feature = "v1_18"))]
|
||||||
|
static SET_ONCE_QUARK: Lazy<glib::Quark> =
|
||||||
|
Lazy::new(|| glib::Quark::from_str("gstreamer-rs-app-src-callbacks"));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let src = self.to_glib_none().0;
|
let src = self.to_glib_none().0;
|
||||||
#[cfg(not(feature = "v1_18"))]
|
#[cfg(not(feature = "v1_18"))]
|
||||||
{
|
{
|
||||||
static SET_ONCE_QUARK: std::sync::OnceLock<glib::Quark> =
|
|
||||||
std::sync::OnceLock::new();
|
|
||||||
|
|
||||||
let set_once_quark = SET_ONCE_QUARK
|
|
||||||
.get_or_init(|| glib::Quark::from_str("gstreamer-rs-app-src-callbacks"));
|
|
||||||
|
|
||||||
// This is not thread-safe before 1.16.3, see
|
// This is not thread-safe before 1.16.3, see
|
||||||
// https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/570
|
// https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/570
|
||||||
if gst::version() < (1, 16, 3, 0) {
|
if gst::version() < (1, 16, 3, 0) {
|
||||||
if !glib::gobject_ffi::g_object_get_qdata(
|
if !glib::gobject_ffi::g_object_get_qdata(
|
||||||
src as *mut _,
|
src as *mut _,
|
||||||
set_once_quark.into_glib(),
|
SET_ONCE_QUARK.into_glib(),
|
||||||
)
|
)
|
||||||
.is_null()
|
.is_null()
|
||||||
{
|
{
|
||||||
|
@ -306,7 +247,7 @@ impl AppSrc {
|
||||||
|
|
||||||
glib::gobject_ffi::g_object_set_qdata(
|
glib::gobject_ffi::g_object_set_qdata(
|
||||||
src as *mut _,
|
src as *mut _,
|
||||||
set_once_quark.into_glib(),
|
SET_ONCE_QUARK.into_glib(),
|
||||||
1 as *mut _,
|
1 as *mut _,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use glib::{
|
||||||
signal::{connect_raw, SignalHandlerId},
|
signal::{connect_raw, SignalHandlerId},
|
||||||
translate::*,
|
translate::*,
|
||||||
};
|
};
|
||||||
use std::boxed::Box as Box_;
|
use std::{boxed::Box as Box_, mem::transmute};
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
#[doc(alias = "GstAppSink")]
|
#[doc(alias = "GstAppSink")]
|
||||||
|
@ -233,7 +233,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::buffer-list\0".as_ptr() as *const _,
|
b"notify::buffer-list\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_buffer_list_trampoline::<F> as *const (),
|
notify_buffer_list_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -259,7 +259,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::caps\0".as_ptr() as *const _,
|
b"notify::caps\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_caps_trampoline::<F> as *const (),
|
notify_caps_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -285,7 +285,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::drop\0".as_ptr() as *const _,
|
b"notify::drop\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_drop_trampoline::<F> as *const (),
|
notify_drop_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -311,7 +311,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::eos\0".as_ptr() as *const _,
|
b"notify::eos\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_eos_trampoline::<F> as *const (),
|
notify_eos_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -339,7 +339,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::max-buffers\0".as_ptr() as *const _,
|
b"notify::max-buffers\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_max_buffers_trampoline::<F> as *const (),
|
notify_max_buffers_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -369,7 +369,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::max-bytes\0".as_ptr() as *const _,
|
b"notify::max-bytes\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_max_bytes_trampoline::<F> as *const (),
|
notify_max_bytes_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -397,7 +397,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::max-time\0".as_ptr() as *const _,
|
b"notify::max-time\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_max_time_trampoline::<F> as *const (),
|
notify_max_time_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -425,7 +425,7 @@ impl AppSink {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::wait-on-eos\0".as_ptr() as *const _,
|
b"notify::wait-on-eos\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_wait_on_eos_trampoline::<F> as *const (),
|
notify_wait_on_eos_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
|
|
@ -12,7 +12,7 @@ use glib::{
|
||||||
signal::{connect_raw, SignalHandlerId},
|
signal::{connect_raw, SignalHandlerId},
|
||||||
translate::*,
|
translate::*,
|
||||||
};
|
};
|
||||||
use std::boxed::Box as Box_;
|
use std::{boxed::Box as Box_, mem::transmute};
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
#[doc(alias = "GstAppSrc")]
|
#[doc(alias = "GstAppSrc")]
|
||||||
|
@ -297,7 +297,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::block\0".as_ptr() as *const _,
|
b"notify::block\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_block_trampoline::<F> as *const (),
|
notify_block_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -323,7 +323,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::caps\0".as_ptr() as *const _,
|
b"notify::caps\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_caps_trampoline::<F> as *const (),
|
notify_caps_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -353,7 +353,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::current-level-buffers\0".as_ptr() as *const _,
|
b"notify::current-level-buffers\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_current_level_buffers_trampoline::<F> as *const (),
|
notify_current_level_buffers_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -381,7 +381,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::current-level-bytes\0".as_ptr() as *const _,
|
b"notify::current-level-bytes\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_current_level_bytes_trampoline::<F> as *const (),
|
notify_current_level_bytes_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -411,7 +411,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::current-level-time\0".as_ptr() as *const _,
|
b"notify::current-level-time\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_current_level_time_trampoline::<F> as *const (),
|
notify_current_level_time_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -437,7 +437,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::duration\0".as_ptr() as *const _,
|
b"notify::duration\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_duration_trampoline::<F> as *const (),
|
notify_duration_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -463,7 +463,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::format\0".as_ptr() as *const _,
|
b"notify::format\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_format_trampoline::<F> as *const (),
|
notify_format_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -493,7 +493,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::handle-segment-change\0".as_ptr() as *const _,
|
b"notify::handle-segment-change\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_handle_segment_change_trampoline::<F> as *const (),
|
notify_handle_segment_change_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -519,7 +519,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::is-live\0".as_ptr() as *const _,
|
b"notify::is-live\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_is_live_trampoline::<F> as *const (),
|
notify_is_live_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -549,7 +549,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::leaky-type\0".as_ptr() as *const _,
|
b"notify::leaky-type\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_leaky_type_trampoline::<F> as *const (),
|
notify_leaky_type_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -579,7 +579,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::max-buffers\0".as_ptr() as *const _,
|
b"notify::max-buffers\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_max_buffers_trampoline::<F> as *const (),
|
notify_max_buffers_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -605,7 +605,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::max-bytes\0".as_ptr() as *const _,
|
b"notify::max-bytes\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_max_bytes_trampoline::<F> as *const (),
|
notify_max_bytes_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -633,7 +633,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::max-latency\0".as_ptr() as *const _,
|
b"notify::max-latency\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_max_latency_trampoline::<F> as *const (),
|
notify_max_latency_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -661,7 +661,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::max-time\0".as_ptr() as *const _,
|
b"notify::max-time\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_max_time_trampoline::<F> as *const (),
|
notify_max_time_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -689,7 +689,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::min-latency\0".as_ptr() as *const _,
|
b"notify::min-latency\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_min_latency_trampoline::<F> as *const (),
|
notify_min_latency_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -717,7 +717,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::min-percent\0".as_ptr() as *const _,
|
b"notify::min-percent\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_min_percent_trampoline::<F> as *const (),
|
notify_min_percent_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -743,7 +743,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::size\0".as_ptr() as *const _,
|
b"notify::size\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_size_trampoline::<F> as *const (),
|
notify_size_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
@ -771,7 +771,7 @@ impl AppSrc {
|
||||||
connect_raw(
|
connect_raw(
|
||||||
self.as_ptr() as *mut _,
|
self.as_ptr() as *mut _,
|
||||||
b"notify::stream-type\0".as_ptr() as *const _,
|
b"notify::stream-type\0".as_ptr() as *const _,
|
||||||
Some(std::mem::transmute::<_, unsafe extern "C" fn()>(
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
notify_stream_type_trampoline::<F> as *const (),
|
notify_stream_type_trampoline::<F> as *const (),
|
||||||
)),
|
)),
|
||||||
Box_::into_raw(f),
|
Box_::into_raw(f),
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Generated by gir (https://github.com/gtk-rs/gir @ 5223ce91b97a)
|
Generated by gir (https://github.com/gtk-rs/gir @ 23d7c100187c)
|
||||||
from gir-files (https://github.com/gtk-rs/gir-files @ 6cd7b656acd6)
|
from gir-files (https://github.com/gtk-rs/gir-files @ 6415239ef435)
|
||||||
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ c988e03b5e99)
|
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 62054dc7234d)
|
||||||
|
|
|
@ -4,14 +4,21 @@ system-deps = "6"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
||||||
[dependencies.glib-sys]
|
[dependencies.glib]
|
||||||
workspace = true
|
package = "glib-sys"
|
||||||
|
git = "https://github.com/gtk-rs/gtk-rs-core"
|
||||||
|
branch = "0.18"
|
||||||
|
version = "0.18"
|
||||||
|
|
||||||
[dependencies.gstreamer-sys]
|
[dependencies.gst_base]
|
||||||
workspace = true
|
package = "gstreamer-base-sys"
|
||||||
|
path = "../../gstreamer-base/sys"
|
||||||
|
version = "0.21"
|
||||||
|
|
||||||
[dependencies.gstreamer-base-sys]
|
[dependencies.gst]
|
||||||
workspace = true
|
package = "gstreamer-sys"
|
||||||
|
path = "../../gstreamer/sys"
|
||||||
|
version = "0.21"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
shell-words = "1.0.0"
|
shell-words = "1.0.0"
|
||||||
|
@ -23,7 +30,6 @@ v1_18 = ["v1_16"]
|
||||||
v1_20 = ["v1_18"]
|
v1_20 = ["v1_18"]
|
||||||
v1_22 = ["v1_20"]
|
v1_22 = ["v1_20"]
|
||||||
v1_24 = ["v1_22"]
|
v1_24 = ["v1_22"]
|
||||||
v1_26 = ["v1_24"]
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "gstreamer_app_sys"
|
name = "gstreamer_app_sys"
|
||||||
|
@ -33,28 +39,15 @@ authors = ["Sebastian Dröge <sebastian@centricular.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
description = "FFI bindings to libgstapp-1.0"
|
description = "FFI bindings to libgstapp-1.0"
|
||||||
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_app_sys/"
|
documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_app_sys/"
|
||||||
|
homepage = "https://gstreamer.freedesktop.org"
|
||||||
keywords = ["ffi", "gstreamer", "gnome", "multimedia"]
|
keywords = ["ffi", "gstreamer", "gnome", "multimedia"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "gstreamer-app-sys"
|
name = "gstreamer-app-sys"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs"
|
||||||
[package.version]
|
version = "0.21.3"
|
||||||
workspace = true
|
edition = "2021"
|
||||||
|
rust-version = "1.70"
|
||||||
[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]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
@ -78,7 +71,4 @@ version = "1.20"
|
||||||
version = "1.22"
|
version = "1.22"
|
||||||
|
|
||||||
[package.metadata.system-deps.gstreamer_app_1_0.v1_24]
|
[package.metadata.system-deps.gstreamer_app_1_0.v1_24]
|
||||||
version = "1.24"
|
version = "1.23"
|
||||||
|
|
||||||
[package.metadata.system-deps.gstreamer_app_1_0.v1_26]
|
|
||||||
version = "1.25"
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Generated by gir (https://github.com/gtk-rs/gir @ 5223ce91b97a)
|
Generated by gir (https://github.com/gtk-rs/gir @ 23d7c100187c)
|
||||||
from gir-files (https://github.com/gtk-rs/gir-files @ 6cd7b656acd6)
|
from gir-files (https://github.com/gtk-rs/gir-files @ 6415239ef435)
|
||||||
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ c988e03b5e99)
|
from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 62054dc7234d)
|
||||||
|
|
|
@ -12,18 +12,11 @@
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
|
||||||
use glib_sys as glib;
|
|
||||||
use gstreamer_base_sys as gst_base;
|
|
||||||
use gstreamer_sys as gst;
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use libc::{
|
use libc::{
|
||||||
c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void,
|
c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void,
|
||||||
intptr_t, off_t, size_t, ssize_t, time_t, uintptr_t, FILE,
|
intptr_t, size_t, ssize_t, uintptr_t, FILE,
|
||||||
};
|
};
|
||||||
#[cfg(unix)]
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use libc::{dev_t, gid_t, pid_t, socklen_t, uid_t};
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use glib::{gboolean, gconstpointer, gpointer, GType};
|
use glib::{gboolean, gconstpointer, gpointer, GType};
|
||||||
|
@ -104,7 +97,7 @@ pub struct _GstAppSinkPrivate {
|
||||||
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
|
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type GstAppSinkPrivate = _GstAppSinkPrivate;
|
pub type GstAppSinkPrivate = *mut _GstAppSinkPrivate;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -163,7 +156,7 @@ pub struct _GstAppSrcPrivate {
|
||||||
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
|
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type GstAppSrcPrivate = _GstAppSrcPrivate;
|
pub type GstAppSrcPrivate = *mut _GstAppSrcPrivate;
|
||||||
|
|
||||||
// Classes
|
// Classes
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue