ndi: Add support for loading NDI SDK v6

The library name and environment variable name have changed but the ABI
is completely compatible.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1607>
This commit is contained in:
Sebastian Dröge 2024-06-06 16:20:43 +03:00 committed by GStreamer Marge Bot
parent 1e964233c6
commit 30252a1b2e
2 changed files with 52 additions and 19 deletions

View file

@ -1,7 +1,7 @@
GStreamer NDI Plugin GStreamer NDI Plugin
==================== ====================
*Compatible with NDI SDK 5.x* *Compatible with NDI SDK 6.x and 5.x*
This is a plugin for the [GStreamer](https://gstreamer.freedesktop.org/) This is a plugin for the [GStreamer](https://gstreamer.freedesktop.org/)
multimedia framework that allows GStreamer to receive or send an multimedia framework that allows GStreamer to receive or send an
@ -16,8 +16,8 @@ sink element to provide an NDI source and a device provider for discovering
NDI sources on the network. NDI sources on the network.
The plugin is loading the NDI SDK at runtime, either from the default library The plugin is loading the NDI SDK at runtime, either from the default library
path or, if set, from the directory given by the `NDI_RUNTIME_DIR_V5` path or, if set, from the directory given by the `NDI_RUNTIME_DIR_V6` or
environment variable. `NDI_RUNTIME_DIR_V5` environment variables.
Some examples of how to use these elements from the command line: Some examples of how to use these elements from the command line:

View file

@ -8,7 +8,7 @@
clippy::missing_safety_doc clippy::missing_safety_doc
)] )]
use once_cell::sync::OnceCell; use once_cell::sync::{Lazy, OnceCell};
#[cfg(unix)] #[cfg(unix)]
use libloading::os::unix::{Library, Symbol}; use libloading::os::unix::{Library, Symbol};
@ -16,15 +16,15 @@ use libloading::os::unix::{Library, Symbol};
use libloading::os::windows::{Library, Symbol}; use libloading::os::windows::{Library, Symbol};
#[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[cfg(all(target_arch = "x86_64", target_os = "windows"))]
const LIBRARY_NAME: &str = "Processing.NDI.Lib.x64.dll"; const LIBRARY_NAMES: &[&str] = &["Processing.NDI.Lib.x64.dll"];
#[cfg(all(target_arch = "x86", target_os = "windows"))] #[cfg(all(target_arch = "x86", target_os = "windows"))]
const LIBRARY_NAME: &str = "Processing.NDI.Lib.x86.dll"; const LIBRARY_NAMES: &[&str] = &["Processing.NDI.Lib.x86.dll"];
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
const LIBRARY_NAME: &str = "libndi.so.5"; const LIBRARY_NAMES: &[&str] = &["libndi.so.6", "libndi.so.5"];
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
const LIBRARY_NAME: &str = "libndi.dylib"; const LIBRARY_NAMES: &[&str] = &["libndi.dylib"];
#[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))] #[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))]
const LIBRARY_NAME: &str = "libndi.so"; const LIBRARY_NAMES: &[&str] = &["libndi.so"];
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
struct FFI { struct FFI {
@ -326,6 +326,9 @@ pub const NDIlib_compressed_packet_flags_keyframe: u32 = 1;
#[cfg(feature = "advanced-sdk")] #[cfg(feature = "advanced-sdk")]
pub const NDIlib_compressed_packet_version_0: u32 = 44; pub const NDIlib_compressed_packet_version_0: u32 = 44;
static CAT: Lazy<gst::DebugCategory> =
Lazy::new(|| gst::DebugCategory::new("ndi", gst::DebugColorFlags::empty(), Some("NewTek NDI")));
static FFI: OnceCell<FFI> = OnceCell::new(); static FFI: OnceCell<FFI> = OnceCell::new();
pub fn load() -> Result<(), glib::BoolError> { pub fn load() -> Result<(), glib::BoolError> {
@ -335,17 +338,47 @@ pub fn load() -> Result<(), glib::BoolError> {
use std::env; use std::env;
use std::path; use std::path;
let library_directory = env::var_os("NDI_RUNTIME_DIR_V5"); const ENV_VARS: &[&str] = &["NDI_RUNTIME_DIR_V6", "NDI_RUNTIME_DIR_V5", ""];
let library_path = if let Some(library_directory) = library_directory {
let mut path = path::PathBuf::from(library_directory); let mut library = None;
path.push(LIBRARY_NAME); 'outer_loop: for env_var in ENV_VARS {
path let library_directory = if !env_var.is_empty() {
let Some(library_directory) = env::var_os(env_var) else {
continue;
};
Some(library_directory)
} else { } else {
path::PathBuf::from(LIBRARY_NAME) None
}; };
let library = Library::new(library_path) for library_name in LIBRARY_NAMES {
.map_err(|err| glib::bool_error!("Failed to load NDI SDK: {}", err))?; let library_path = if let Some(ref library_directory) = library_directory {
let mut path = path::PathBuf::from(library_directory);
path.push(library_name);
path
} else {
path::PathBuf::from(library_name)
};
match Library::new(&library_path) {
Ok(lib) => {
gst::log!(CAT, "Loaded NDI SDK from {}", library_path.display());
library = Some(lib);
break 'outer_loop;
}
Err(err) => {
gst::log!(
CAT,
"Failed loading NDI SDK from {}: {err}",
library_path.display()
);
continue;
}
}
}
}
let library = library.ok_or_else(|| glib::bool_error!("Failed loading NDI SDK"))?;
macro_rules! load_symbol { macro_rules! load_symbol {
($name:ident) => {{ ($name:ident) => {{