initial commit

This commit is contained in:
Luca 2025-01-04 05:33:03 +01:00
commit eedce36083
6 changed files with 968 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

643
Cargo.lock generated Normal file
View File

@ -0,0 +1,643 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "atomic_refcell"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "cfg-expr"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d4ba6e40bd1184518716a6e1a781bf9160e286d219ccdb8ab2612e74cfe4789"
dependencies = [
"smallvec",
"target-lexicon",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "futures-channel"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-macro"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-task"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-core",
"futures-macro",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gio-sys"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8446d9b475730ebef81802c1738d972db42fde1c5a36a627ebc4d665fc87db04"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
"windows-sys",
]
[[package]]
name = "glib"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f969edf089188d821a30cde713b6f9eb08b20c63fc2e584aba2892a7984a8cc0"
dependencies = [
"bitflags",
"futures-channel",
"futures-core",
"futures-executor",
"futures-task",
"futures-util",
"gio-sys",
"glib-macros",
"glib-sys",
"gobject-sys",
"libc",
"memchr",
"smallvec",
]
[[package]]
name = "glib-macros"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715601f8f02e71baef9c1f94a657a9a77c192aea6097cf9ae7e5e177cd8cde68"
dependencies = [
"heck",
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "glib-sys"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b360ff0f90d71de99095f79c526a5888c9c92fc9ee1b19da06c6f5e75f0c2a53"
dependencies = [
"libc",
"system-deps",
]
[[package]]
name = "gobject-sys"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a56235e971a63bfd75abb13ef70064e1346388723422a68580d8a6fbac6423"
dependencies = [
"glib-sys",
"libc",
"system-deps",
]
[[package]]
name = "gst-plugin-pingxelflut"
version = "0.1.0"
dependencies = [
"gstreamer",
"gstreamer-base",
"gstreamer-video",
]
[[package]]
name = "gstreamer"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "700cb1b2e86dda424f85eb728102a111602317e40b4dd71cf1c0dc04e0cc5d95"
dependencies = [
"cfg-if",
"futures-channel",
"futures-core",
"futures-util",
"glib",
"gstreamer-sys",
"itertools",
"libc",
"muldiv",
"num-integer",
"num-rational",
"once_cell",
"option-operations",
"paste",
"pin-project-lite",
"smallvec",
"thiserror",
]
[[package]]
name = "gstreamer-base"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d152db7983f98d5950cf64e53805286548063475fb61a5e5450fba4cec05899b"
dependencies = [
"atomic_refcell",
"cfg-if",
"glib",
"gstreamer",
"gstreamer-base-sys",
"libc",
]
[[package]]
name = "gstreamer-base-sys"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d47cc2d15f2a3d5eb129e5dacbbeec9600432b706805c15dff57b6aa11b2791c"
dependencies = [
"glib-sys",
"gobject-sys",
"gstreamer-sys",
"libc",
"system-deps",
]
[[package]]
name = "gstreamer-sys"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16cf1ae0a869aa7066ce3c685b76053b4b4f48f364a5b18c4b1f36ef57469719"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
]
[[package]]
name = "gstreamer-video"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fa41e40319e923236e96f0b691711d1504746ab9c89607d77d22aa84777f33f"
dependencies = [
"cfg-if",
"futures-channel",
"glib",
"gstreamer",
"gstreamer-base",
"gstreamer-video-sys",
"libc",
"once_cell",
"thiserror",
]
[[package]]
name = "gstreamer-video-sys"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31dc0f49c117f4867b0f98c712aa55ebf25580151d794be8f9179ec2d877fd14"
dependencies = [
"glib-sys",
"gobject-sys",
"gstreamer-base-sys",
"gstreamer-sys",
"libc",
"system-deps",
]
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "indexmap"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "libc"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "muldiv"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0"
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "option-operations"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c26d27bb1aeab65138e4bf7666045169d1717febcc9ff870166be8348b223d0"
dependencies = [
"paste",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pin-project-lite"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "proc-macro-crate"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_spanned"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "syn"
version = "2.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "system-deps"
version = "7.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005"
dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"toml",
"version-compare",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "thiserror"
version = "2.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "version-compare"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [
"memchr",
]

16
Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "gst-plugin-pingxelflut"
version = "0.1.0"
edition = "2021"
description = "GStreamer pingxelflut sink element"
repository = "https://git.luj0ga.de/luca/gst-plugin-pingxelflut"
license = "MPL-2.0"
[lib]
name = "gstpingxelflut"
crate-type = ["cdylib"]
[dependencies]
gstreamer = "0.23.4"
gstreamer-base = "0.23.4"
gstreamer-video = "0.23.4"

20
src/lib.rs Normal file
View File

@ -0,0 +1,20 @@
mod pingxelflutsink;
use gstreamer::glib::BoolError;
use gstreamer::Plugin;
fn plugin_init(plugin: &Plugin) -> Result<(), BoolError> {
pingxelflutsink::register(plugin)?;
Ok(())
}
gstreamer::plugin_define!(
pingxelflut,
env!("CARGO_PKG_DESCRIPTION"),
plugin_init,
env!("CARGO_PKG_VERSION"),
env!("CARGO_PKG_LICENSE"),
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_REPOSITORY")
);

266
src/pingxelflutsink/imp.rs Normal file
View File

@ -0,0 +1,266 @@
use gstreamer::glib::{self, ParamSpec, ParamSpecString, Value};
use gstreamer::prelude::*;
use gstreamer::subclass::prelude::*;
use gstreamer::subclass::ElementMetadata;
use gstreamer::{
Buffer, Caps, CapsIntersectMode, DebugCategory, DebugColorFlags, ErrorMessage, FlowError,
FlowSuccess, LoggableError, PadDirection, PadPresence, PadTemplate, ResourceError,
};
use gstreamer_base::prelude::*;
use gstreamer_base::subclass::prelude::*;
use gstreamer_video::prelude::*;
use gstreamer_video::subclass::prelude::*;
use gstreamer_video::{VideoCapsBuilder, VideoFormat, VideoFrame, VideoInfo, VideoSink};
use std::cmp;
use std::net::{Ipv6Addr, SocketAddr, UdpSocket};
use std::sync::{LazyLock, Mutex};
const HEIGHT: u32 = 196;
const WIDTH: u32 = 346;
static CAT: LazyLock<DebugCategory> = LazyLock::new(|| {
DebugCategory::new(
"pingxelflutsink",
DebugColorFlags::empty(),
Some("Pingxelflut sink"),
)
});
#[derive(Default)]
struct Settings {
bind_address: Option<SocketAddr>,
prefix: Option<Ipv6Addr>,
}
#[derive(Default)]
enum State {
#[default]
Stopped,
Started {
socket: UdpSocket,
},
}
#[derive(Default)]
pub struct PingxelflutSink {
caps: Mutex<Option<Caps>>,
info: Mutex<Option<VideoInfo>>,
settings: Mutex<Settings>,
state: Mutex<State>,
}
#[glib::object_subclass]
impl ObjectSubclass for PingxelflutSink {
const NAME: &'static str = "GstPingxelflutSink";
type Type = super::PingxelflutSink;
type ParentType = VideoSink;
}
impl ObjectImpl for PingxelflutSink {
fn properties() -> &'static [ParamSpec] {
static PROPERTIES: LazyLock<Vec<ParamSpec>> = LazyLock::new(|| {
vec![
ParamSpecString::builder("bind-address")
.nick("Bind address")
.blurb("Local address to bind to")
.build(),
ParamSpecString::builder("prefix")
.nick("Destination prefix")
.blurb("Prefix of pingxelflut server")
.build(),
]
});
PROPERTIES.as_ref()
}
fn set_property(&self, _id: usize, value: &Value, pspec: &ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"bind-address" => {
settings.bind_address = value
.get::<Option<String>>()
.unwrap()
.map(|s| s.parse().ok())
.unwrap_or(None);
}
"prefix" => {
settings.prefix = value
.get::<Option<String>>()
.unwrap()
.map(|s| s.parse().ok())
.unwrap_or(None);
}
_ => unimplemented!(),
}
}
fn property(&self, _id: usize, pspec: &ParamSpec) -> Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"bind-address" => settings
.bind_address
.as_ref()
.map(|addr| addr.to_string())
.to_value(),
"prefix" => settings
.prefix
.as_ref()
.map(|addr| addr.to_string())
.to_value(),
_ => unimplemented!(),
}
}
}
impl GstObjectImpl for PingxelflutSink {}
impl ElementImpl for PingxelflutSink {
fn metadata() -> Option<&'static ElementMetadata> {
static ELEMENT_METADATA: LazyLock<ElementMetadata> = LazyLock::new(|| {
ElementMetadata::new(
"Pingxelflut sink",
"Sink/Video",
"Send stream to a pingxelflut screen",
"Luca <Luca@hackerspace-bamberg.de>",
)
});
Some(&*ELEMENT_METADATA)
}
fn pad_templates() -> &'static [PadTemplate] {
static PAD_TEMPLATES: LazyLock<Vec<PadTemplate>> = LazyLock::new(|| {
vec![PadTemplate::new(
"sink",
PadDirection::Sink,
PadPresence::Always,
&VideoCapsBuilder::new().format(VideoFormat::Rgb).build(),
)
.unwrap()]
});
PAD_TEMPLATES.as_ref()
}
}
impl BaseSinkImpl for PingxelflutSink {
fn start(&self) -> Result<(), ErrorMessage> {
let mut state = self.state.lock().unwrap();
if let State::Started { .. } = *state {
unreachable!("PingxelflutSink already started");
}
let settings = self.settings.lock().unwrap();
let bind_address = settings.bind_address.as_ref().ok_or_else(|| {
gstreamer::error_msg!(ResourceError::Settings, ["Bind address is not defined"])
})?;
if let None = settings.prefix {
return Err(gstreamer::error_msg!(
ResourceError::Settings,
["Prefix is not defined"]
));
}
let socket = UdpSocket::bind(bind_address).map_err(|_| {
gstreamer::error_msg!(
ResourceError::OpenWrite,
["Could not bind UDP socket to address {}", bind_address]
)
})?;
*state = State::Started { socket };
Ok(())
}
fn stop(&self) -> Result<(), ErrorMessage> {
let mut state = self.state.lock().unwrap();
if let State::Stopped = *state {
return Err(gstreamer::error_msg!(
ResourceError::Settings,
["PingxelflutSink not started"]
));
}
*state = State::Stopped;
Ok(())
}
fn caps(&self, filter: Option<&Caps>) -> Option<Caps> {
let mut caps = self
.caps
.lock()
.unwrap()
.clone()
.unwrap_or_else(|| Self::pad_templates()[0].caps().clone());
if let Some(filter_caps) = filter {
caps = filter_caps.intersect_with_mode(&caps, CapsIntersectMode::First);
}
Some(caps)
}
fn set_caps(&self, caps: &Caps) -> Result<(), LoggableError> {
let video_info = VideoInfo::from_caps(caps)
.map_err(|_| gstreamer::loggable_error!(CAT, "Invalid caps"))?;
*self.info.lock().unwrap() = Some(video_info);
Ok(())
}
}
impl VideoSinkImpl for PingxelflutSink {
fn show_frame(&self, buffer: &Buffer) -> Result<FlowSuccess, FlowError> {
let info = self.info.lock().unwrap();
let info = info.as_ref().ok_or_else(|| FlowError::NotNegotiated)?;
let frame =
VideoFrame::from_buffer_readable(buffer.clone(), info).map_err(|_| FlowError::Error)?;
let data = frame.plane_data(0).unwrap();
let settings = self.settings.lock().unwrap();
let prefix = settings.prefix.as_ref().unwrap();
if let State::Started { ref socket } = *self.state.lock().unwrap() {
for y in 0..cmp::min(frame.height(), HEIGHT) {
for x in 0..cmp::min(frame.width(), WIDTH) {
let i =
(y * frame.plane_stride()[0] as u32 + x * frame.n_components()) as usize;
let (r, g, b) = (data[i] as u16, data[i + 1] as u16, data[i + 2] as u16);
let _ = socket.send_to(
&[],
(
prefix
| Ipv6Addr::new(
0,
0,
0,
0,
x as u16,
y as u16,
(r << 8) | g,
b << 8,
),
1337,
),
);
}
}
}
Ok(FlowSuccess::Ok)
}
}

View File

@ -0,0 +1,22 @@
mod imp;
use gstreamer::glib::{self, BoolError};
use gstreamer::prelude::*;
use gstreamer::{Element, Object, Plugin, Rank};
use gstreamer_base::BaseSink;
use gstreamer_video::VideoSink;
glib::wrapper! {
pub struct PingxelflutSink(ObjectSubclass<imp::PingxelflutSink>) @extends VideoSink, BaseSink, Element, Object;
}
pub fn register(plugin: &Plugin) -> Result<(), BoolError> {
Element::register(
Some(plugin),
"pingxelflutsink",
Rank::NONE,
PingxelflutSink::static_type(),
)
}