mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-02 00:11:01 +00:00
Allow connecting to either an NDI name or URL/address again
Apparently the SDK allows both but the documentation was a bit confusing.
This commit is contained in:
parent
8d2c025e47
commit
4d620cd737
4 changed files with 46 additions and 23 deletions
22
src/ndi.rs
22
src/ndi.rs
|
@ -182,7 +182,8 @@ impl<'a> PartialEq for Source<'a> {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct RecvBuilder<'a> {
|
||||
source_to_connect_to: (&'a str, Option<&'a str>),
|
||||
ndi_name: Option<&'a str>,
|
||||
url_address: Option<&'a str>,
|
||||
allow_video_fields: bool,
|
||||
bandwidth: NDIlib_recv_bandwidth_e,
|
||||
color_format: NDIlib_recv_color_format_e,
|
||||
|
@ -211,15 +212,20 @@ impl<'a> RecvBuilder<'a> {
|
|||
pub fn build(self) -> Option<RecvInstance> {
|
||||
unsafe {
|
||||
let ndi_recv_name = ffi::CString::new(self.ndi_recv_name).unwrap();
|
||||
let ndi_name = ffi::CString::new(self.source_to_connect_to.0).unwrap();
|
||||
let ndi_name = self
|
||||
.ndi_name
|
||||
.as_ref()
|
||||
.map(|s| ffi::CString::new(*s).unwrap());
|
||||
let url_address = self
|
||||
.source_to_connect_to
|
||||
.1
|
||||
.url_address
|
||||
.as_ref()
|
||||
.map(|s| ffi::CString::new(*s).unwrap());
|
||||
let ptr = NDIlib_recv_create_v3(&NDIlib_recv_create_v3_t {
|
||||
source_to_connect_to: NDIlib_source_t {
|
||||
p_ndi_name: ndi_name.as_ptr(),
|
||||
p_ndi_name: ndi_name
|
||||
.as_ref()
|
||||
.map(|s| s.as_ptr())
|
||||
.unwrap_or_else(|| ptr::null_mut()),
|
||||
p_url_address: url_address
|
||||
.as_ref()
|
||||
.map(|s| s.as_ptr())
|
||||
|
@ -258,11 +264,13 @@ unsafe impl Sync for RecvInstanceInner {}
|
|||
|
||||
impl RecvInstance {
|
||||
pub fn builder<'a>(
|
||||
source_to_connect_to: (&'a str, Option<&'a str>),
|
||||
ndi_name: Option<&'a str>,
|
||||
url_address: Option<&'a str>,
|
||||
ndi_recv_name: &'a str,
|
||||
) -> RecvBuilder<'a> {
|
||||
RecvBuilder {
|
||||
source_to_connect_to,
|
||||
ndi_name,
|
||||
url_address,
|
||||
allow_video_fields: true,
|
||||
bandwidth: NDIlib_recv_bandwidth_highest,
|
||||
color_format: NDIlib_recv_color_format_e::NDIlib_recv_color_format_UYVY_BGRA,
|
||||
|
|
|
@ -60,7 +60,7 @@ static PROPERTIES: [subclass::Property; 7] = [
|
|||
glib::ParamSpec::string(
|
||||
name,
|
||||
"URL/Address",
|
||||
"URL/address and port of the sender, e.g. 127.0.0.1:5961. This is used as an additional filter together with the NDI name.",
|
||||
"URL/address and port of the sender, e.g. 127.0.0.1:5961",
|
||||
None,
|
||||
glib::ParamFlags::READWRITE,
|
||||
)
|
||||
|
@ -401,17 +401,17 @@ impl BaseSrcImpl for NdiAudioSrc {
|
|||
*self.state.lock().unwrap() = Default::default();
|
||||
let settings = self.settings.lock().unwrap().clone();
|
||||
|
||||
if settings.ndi_name.is_none() {
|
||||
if settings.ndi_name.is_none() && settings.url_address.is_none() {
|
||||
return Err(gst_error_msg!(
|
||||
gst::LibraryError::Settings,
|
||||
["No IP address or NDI name given"]
|
||||
["No NDI name or URL/address given"]
|
||||
));
|
||||
}
|
||||
|
||||
let receiver = connect_ndi(
|
||||
self.cat,
|
||||
element,
|
||||
settings.ndi_name.as_ref().unwrap().as_str(),
|
||||
settings.ndi_name.as_ref().map(String::as_str),
|
||||
settings.url_address.as_ref().map(String::as_str),
|
||||
&settings.receiver_ndi_name,
|
||||
settings.connect_timeout,
|
||||
|
|
|
@ -61,7 +61,7 @@ static PROPERTIES: [subclass::Property; 7] = [
|
|||
glib::ParamSpec::string(
|
||||
name,
|
||||
"URL/Address",
|
||||
"URL/address and port of the sender, e.g. 127.0.0.1:5961. This is used as an additional filter together with the NDI name.",
|
||||
"URL/address and port of the sender, e.g. 127.0.0.1:5961",
|
||||
None,
|
||||
glib::ParamFlags::READWRITE,
|
||||
)
|
||||
|
@ -436,17 +436,17 @@ impl BaseSrcImpl for NdiVideoSrc {
|
|||
*self.state.lock().unwrap() = Default::default();
|
||||
let settings = self.settings.lock().unwrap().clone();
|
||||
|
||||
if settings.ndi_name.is_none() {
|
||||
if settings.ndi_name.is_none() && settings.url_address.is_none() {
|
||||
return Err(gst_error_msg!(
|
||||
gst::LibraryError::Settings,
|
||||
["No NDI name given"]
|
||||
["No NDI name or URL/address given"]
|
||||
));
|
||||
}
|
||||
|
||||
let receiver = connect_ndi(
|
||||
self.cat,
|
||||
element,
|
||||
settings.ndi_name.as_ref().unwrap().as_str(),
|
||||
settings.ndi_name.as_ref().map(String::as_str),
|
||||
settings.url_address.as_ref().map(String::as_str),
|
||||
&settings.receiver_ndi_name,
|
||||
settings.connect_timeout,
|
||||
|
@ -502,6 +502,8 @@ impl BaseSrcImpl for NdiVideoSrc {
|
|||
|
||||
let max = 5 * state.current_latency;
|
||||
|
||||
println!("Returning latency min {} max {}", min, max,);
|
||||
|
||||
gst_debug!(
|
||||
self.cat,
|
||||
obj: element,
|
||||
|
|
|
@ -17,7 +17,7 @@ use super::*;
|
|||
|
||||
pub struct ReceiverInfo {
|
||||
id: usize,
|
||||
ndi_name: String,
|
||||
ndi_name: Option<String>,
|
||||
url_address: Option<String>,
|
||||
recv: RecvInstance,
|
||||
video: Option<Weak<ReceiverInner<VideoReceiver>>>,
|
||||
|
@ -521,7 +521,7 @@ impl<T: ReceiverType> Drop for ReceiverInner<T> {
|
|||
pub fn connect_ndi<T: ReceiverType>(
|
||||
cat: gst::DebugCategory,
|
||||
element: &gst_base::BaseSrc,
|
||||
ndi_name: &str,
|
||||
ndi_name: Option<&str>,
|
||||
url_address: Option<&str>,
|
||||
receiver_ndi_name: &str,
|
||||
connect_timeout: u32,
|
||||
|
@ -534,12 +534,24 @@ where
|
|||
{
|
||||
gst_debug!(cat, obj: element, "Starting NDI connection...");
|
||||
|
||||
assert!(ndi_name.is_some() || url_address.is_some());
|
||||
|
||||
let mut receivers = HASHMAP_RECEIVERS.lock().unwrap();
|
||||
|
||||
// Check if we already have a receiver for this very stream
|
||||
for receiver in receivers.values_mut() {
|
||||
if receiver.ndi_name == ndi_name
|
||||
&& receiver.url_address.as_ref().map(String::as_str) == url_address
|
||||
// If both are provided they both must match, if only one is provided
|
||||
// then that one has to match and the other one does not matter
|
||||
if (ndi_name.is_some()
|
||||
&& url_address.is_some()
|
||||
&& receiver.ndi_name.as_ref().map(String::as_str) == ndi_name
|
||||
&& receiver.url_address.as_ref().map(String::as_str) == url_address)
|
||||
|| (ndi_name.is_some()
|
||||
&& url_address.is_none()
|
||||
&& receiver.ndi_name.as_ref().map(String::as_str) == ndi_name)
|
||||
|| (ndi_name.is_none()
|
||||
&& url_address.is_some()
|
||||
&& receiver.url_address.as_ref().map(String::as_str) == url_address)
|
||||
{
|
||||
if (receiver.video.is_some() || !T::IS_VIDEO)
|
||||
&& (receiver.audio.is_some() || T::IS_VIDEO)
|
||||
|
@ -548,8 +560,9 @@ where
|
|||
element,
|
||||
gst::ResourceError::OpenRead,
|
||||
[
|
||||
"Source with ndi-name '{}' already in use for {}",
|
||||
"Source with NDI name '{:?}' / URL/address '{:?}' already in use for {}",
|
||||
receiver.ndi_name,
|
||||
receiver.url_address,
|
||||
if T::IS_VIDEO { "video" } else { "audio" }
|
||||
]
|
||||
);
|
||||
|
@ -572,14 +585,14 @@ where
|
|||
gst_debug!(
|
||||
cat,
|
||||
obj: element,
|
||||
"Connecting to NDI source with ndi-name '{}' and URL/Address {:?}",
|
||||
"Connecting to NDI source with NDI name '{:?}' and URL/Address {:?}",
|
||||
ndi_name,
|
||||
url_address,
|
||||
);
|
||||
|
||||
// FIXME: Ideally we would use NDIlib_recv_color_format_fastest here but that seems to be
|
||||
// broken with interlaced content currently
|
||||
let recv = RecvInstance::builder((ndi_name, url_address), &receiver_ndi_name)
|
||||
let recv = RecvInstance::builder(ndi_name, url_address, &receiver_ndi_name)
|
||||
.bandwidth(bandwidth)
|
||||
.color_format(NDIlib_recv_color_format_e::NDIlib_recv_color_format_UYVY_BGRA)
|
||||
.allow_video_fields(true)
|
||||
|
@ -604,7 +617,7 @@ where
|
|||
let id_receiver = ID_RECEIVER.fetch_add(1, Ordering::SeqCst);
|
||||
let mut info = ReceiverInfo {
|
||||
id: id_receiver,
|
||||
ndi_name: String::from(ndi_name),
|
||||
ndi_name: ndi_name.map(String::from),
|
||||
url_address: url_address.map(String::from),
|
||||
recv,
|
||||
video: None,
|
||||
|
|
Loading…
Reference in a new issue