diff --git a/gstreamer-net/Cargo.toml b/gstreamer-net/Cargo.toml index b71c30b72..e3513b32f 100644 --- a/gstreamer-net/Cargo.toml +++ b/gstreamer-net/Cargo.toml @@ -19,6 +19,7 @@ gstreamer-sys = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-s gstreamer-net-sys = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys", features = ["v1_8"] } glib = { git = "https://github.com/gtk-rs/glib" } gstreamer = { path = "../gstreamer" } +gio = { git = "https://github.com/gtk-rs/gio" } [build-dependencies.rustdoc-stripper] version = "0.1" diff --git a/gstreamer-net/src/lib.rs b/gstreamer-net/src/lib.rs index b5652f48d..a38af1035 100644 --- a/gstreamer-net/src/lib.rs +++ b/gstreamer-net/src/lib.rs @@ -6,6 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate gio; extern crate glib_sys as glib_ffi; extern crate gobject_sys as gobject_ffi; extern crate gstreamer as gst; @@ -37,6 +38,9 @@ mod net_time_provider; mod ntp_clock; mod ptp_clock; +pub use net_address_meta::*; +mod net_address_meta; + // Re-export all the traits in a prelude module, so that applications // can always "use gst::prelude::*" without getting conflicts pub mod prelude { diff --git a/gstreamer-net/src/net_address_meta.rs b/gstreamer-net/src/net_address_meta.rs new file mode 100644 index 000000000..dd911c90d --- /dev/null +++ b/gstreamer-net/src/net_address_meta.rs @@ -0,0 +1,106 @@ +use std::fmt; + +use ffi; +use gio; +use glib; +use glib::translate::*; +use gst; +use gst::prelude::*; + +#[repr(C)] +pub struct NetAddressMeta(ffi::GstNetAddressMeta); + +impl NetAddressMeta { + pub fn add<'a, A: IsA>( + buffer: &'a mut gst::BufferRef, + addr: &A, + ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> { + unsafe { + let meta = ffi::gst_buffer_add_net_address_meta( + buffer.as_mut_ptr(), + addr.as_ref().to_glib_none().0, + ); + Self::from_mut_ptr(buffer, meta) + } + } + + pub fn get_addr(&self) -> gio::SocketAddress { + unsafe { from_glib_none(self.0.addr) } + } + + pub fn set_addr>(&mut self, addr: &T) { + #![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] + unsafe { + gobject_ffi::g_object_unref(self.0.addr as *mut _); + self.0.addr = addr.as_ref().to_glib_full(); + } + } +} + +unsafe impl MetaAPI for NetAddressMeta { + type GstType = ffi::GstNetAddressMeta; + + fn get_meta_api() -> glib::Type { + unsafe { from_glib(ffi::gst_net_address_meta_api_get_type()) } + } +} + +impl fmt::Debug for NetAddressMeta { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("NetAddressMeta") + .field("addr", &self.get_addr()) + .finish() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use gio::InetAddressExt; + use gio::InetSocketAddressExt; + + #[test] + fn test_add_get_meta() { + gst::init().unwrap(); + + let mut buffer = gst::Buffer::new(); + let port = 5000; + let inet_addr = gio::InetAddress::new_from_string("127.0.0.1"); + + let expected_addr = &gio::InetSocketAddress::new(&inet_addr, port); + + let expected_inet_addr = expected_addr.get_address().unwrap(); + + { + let meta = NetAddressMeta::add( + buffer.get_mut().unwrap(), + &gio::InetSocketAddress::new(&inet_addr, port), + ); + + let actual_addr = meta + .get_addr() + .downcast::() + .unwrap(); + + assert_eq!(actual_addr.get_port(), expected_addr.get_port()); + + let actual_inet_addr = actual_addr.get_address().unwrap(); + + assert!(actual_inet_addr.equal(&expected_inet_addr)); + } + + { + let meta = buffer.get_meta::().unwrap(); + let actual_addr = meta + .get_addr() + .downcast::() + .unwrap(); + + assert_eq!(actual_addr.get_port(), expected_addr.get_port()); + + let actual_inet_addr = actual_addr.get_address().unwrap(); + + assert!(actual_inet_addr.equal(&expected_inet_addr)); + } + } +}