2022-10-12 16:45:52 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2021-09-29 10:45:04 +00:00
|
|
|
use gst::prelude::*;
|
|
|
|
use std::fmt;
|
|
|
|
use std::mem;
|
|
|
|
|
2023-10-18 18:02:55 +00:00
|
|
|
use crate::ndi::{AudioFrame, MetadataFrame, VideoFrame};
|
|
|
|
use crate::TimestampMode;
|
|
|
|
|
2021-09-29 10:45:04 +00:00
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct NdiSrcMeta(imp::NdiSrcMeta);
|
|
|
|
|
2023-10-18 18:02:55 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
|
|
|
pub enum Buffer {
|
|
|
|
Audio {
|
|
|
|
frame: AudioFrame,
|
|
|
|
discont: bool,
|
|
|
|
receive_time_gst: gst::ClockTime,
|
|
|
|
receive_time_real: gst::ClockTime,
|
|
|
|
},
|
|
|
|
Video {
|
|
|
|
frame: VideoFrame,
|
|
|
|
discont: bool,
|
|
|
|
receive_time_gst: gst::ClockTime,
|
|
|
|
receive_time_real: gst::ClockTime,
|
|
|
|
},
|
|
|
|
Metadata {
|
|
|
|
frame: MetadataFrame,
|
|
|
|
receive_time_gst: gst::ClockTime,
|
|
|
|
receive_time_real: gst::ClockTime,
|
|
|
|
},
|
2021-09-29 10:45:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl Send for NdiSrcMeta {}
|
|
|
|
unsafe impl Sync for NdiSrcMeta {}
|
|
|
|
|
|
|
|
impl NdiSrcMeta {
|
2023-10-18 18:02:55 +00:00
|
|
|
pub fn add(
|
|
|
|
buffer: &mut gst::BufferRef,
|
|
|
|
ndi_buffer: Buffer,
|
|
|
|
timestamp_mode: TimestampMode,
|
|
|
|
) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
|
2021-09-29 10:45:04 +00:00
|
|
|
unsafe {
|
|
|
|
// Manually dropping because gst_buffer_add_meta() takes ownership of the
|
|
|
|
// content of the struct
|
|
|
|
let mut params = mem::ManuallyDrop::new(imp::NdiSrcMetaParams {
|
2023-10-18 18:02:55 +00:00
|
|
|
ndi_buffer,
|
|
|
|
timestamp_mode,
|
2021-09-29 10:45:04 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
let meta = gst::ffi::gst_buffer_add_meta(
|
|
|
|
buffer.as_mut_ptr(),
|
|
|
|
imp::ndi_src_meta_get_info(),
|
|
|
|
&mut *params as *mut imp::NdiSrcMetaParams as glib::ffi::gpointer,
|
|
|
|
) as *mut imp::NdiSrcMeta;
|
|
|
|
|
|
|
|
Self::from_mut_ptr(buffer, meta)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-18 18:02:55 +00:00
|
|
|
pub fn take_ndi_buffer(&mut self) -> Buffer {
|
|
|
|
self.0.ndi_buffer.take().expect("can only take buffer once")
|
2021-09-29 10:45:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl MetaAPI for NdiSrcMeta {
|
|
|
|
type GstType = imp::NdiSrcMeta;
|
|
|
|
|
|
|
|
fn meta_api() -> glib::Type {
|
|
|
|
imp::ndi_src_meta_api_get_type()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for NdiSrcMeta {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
f.debug_struct("NdiSrcMeta")
|
2023-10-18 18:02:55 +00:00
|
|
|
.field("ndi_buffer", &self.0.ndi_buffer)
|
2021-09-29 10:45:04 +00:00
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod imp {
|
2023-10-18 18:02:55 +00:00
|
|
|
use crate::TimestampMode;
|
|
|
|
|
|
|
|
use super::Buffer;
|
2021-09-29 10:45:04 +00:00
|
|
|
use glib::translate::*;
|
2023-07-06 13:43:37 +00:00
|
|
|
use gst::glib::once_cell::sync::Lazy;
|
2021-09-29 10:45:04 +00:00
|
|
|
use std::mem;
|
|
|
|
use std::ptr;
|
|
|
|
|
|
|
|
pub(super) struct NdiSrcMetaParams {
|
2023-10-18 18:02:55 +00:00
|
|
|
pub ndi_buffer: Buffer,
|
|
|
|
pub timestamp_mode: TimestampMode,
|
2021-09-29 10:45:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct NdiSrcMeta {
|
|
|
|
parent: gst::ffi::GstMeta,
|
2023-10-18 18:02:55 +00:00
|
|
|
pub(super) ndi_buffer: Option<Buffer>,
|
|
|
|
pub(super) timestamp_mode: TimestampMode,
|
2021-09-29 10:45:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn ndi_src_meta_api_get_type() -> glib::Type {
|
|
|
|
static TYPE: Lazy<glib::Type> = Lazy::new(|| unsafe {
|
|
|
|
let t = from_glib(gst::ffi::gst_meta_api_type_register(
|
|
|
|
b"GstNdiSrcMetaAPI\0".as_ptr() as *const _,
|
|
|
|
[ptr::null::<std::os::raw::c_char>()].as_ptr() as *mut *const _,
|
|
|
|
));
|
|
|
|
|
|
|
|
assert_ne!(t, glib::Type::INVALID);
|
|
|
|
|
|
|
|
t
|
|
|
|
});
|
|
|
|
|
|
|
|
*TYPE
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe extern "C" fn ndi_src_meta_init(
|
|
|
|
meta: *mut gst::ffi::GstMeta,
|
|
|
|
params: glib::ffi::gpointer,
|
|
|
|
_buffer: *mut gst::ffi::GstBuffer,
|
|
|
|
) -> glib::ffi::gboolean {
|
|
|
|
assert!(!params.is_null());
|
|
|
|
|
|
|
|
let meta = &mut *(meta as *mut NdiSrcMeta);
|
|
|
|
let params = ptr::read(params as *const NdiSrcMetaParams);
|
|
|
|
|
2023-10-18 18:02:55 +00:00
|
|
|
ptr::write(&mut meta.ndi_buffer, Some(params.ndi_buffer));
|
|
|
|
ptr::write(&mut meta.timestamp_mode, params.timestamp_mode);
|
2021-09-29 10:45:04 +00:00
|
|
|
|
|
|
|
true.into_glib()
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe extern "C" fn ndi_src_meta_free(
|
|
|
|
meta: *mut gst::ffi::GstMeta,
|
|
|
|
_buffer: *mut gst::ffi::GstBuffer,
|
|
|
|
) {
|
|
|
|
let meta = &mut *(meta as *mut NdiSrcMeta);
|
|
|
|
|
2023-10-18 18:02:55 +00:00
|
|
|
ptr::drop_in_place(&mut meta.ndi_buffer);
|
2021-09-29 10:45:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe extern "C" fn ndi_src_meta_transform(
|
|
|
|
_dest: *mut gst::ffi::GstBuffer,
|
|
|
|
_meta: *mut gst::ffi::GstMeta,
|
|
|
|
_buffer: *mut gst::ffi::GstBuffer,
|
|
|
|
_type_: glib::ffi::GQuark,
|
|
|
|
_data: glib::ffi::gpointer,
|
|
|
|
) -> glib::ffi::gboolean {
|
|
|
|
false.into_glib()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn ndi_src_meta_get_info() -> *const gst::ffi::GstMetaInfo {
|
|
|
|
struct MetaInfo(ptr::NonNull<gst::ffi::GstMetaInfo>);
|
|
|
|
unsafe impl Send for MetaInfo {}
|
|
|
|
unsafe impl Sync for MetaInfo {}
|
|
|
|
|
|
|
|
static META_INFO: Lazy<MetaInfo> = Lazy::new(|| unsafe {
|
|
|
|
MetaInfo(
|
|
|
|
ptr::NonNull::new(gst::ffi::gst_meta_register(
|
|
|
|
ndi_src_meta_api_get_type().into_glib(),
|
|
|
|
b"GstNdiSrcMeta\0".as_ptr() as *const _,
|
|
|
|
mem::size_of::<NdiSrcMeta>(),
|
|
|
|
Some(ndi_src_meta_init),
|
|
|
|
Some(ndi_src_meta_free),
|
|
|
|
Some(ndi_src_meta_transform),
|
|
|
|
) as *mut gst::ffi::GstMetaInfo)
|
|
|
|
.expect("Failed to register meta API"),
|
|
|
|
)
|
|
|
|
});
|
|
|
|
|
|
|
|
META_INFO.0.as_ptr()
|
|
|
|
}
|
|
|
|
}
|