ndi: Refactor frame structs to have static lifetimes

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1365>
This commit is contained in:
Sebastian Dröge 2023-10-18 19:04:45 +03:00
parent eb137ec6dc
commit 99d7cce0d6
2 changed files with 215 additions and 195 deletions

View file

@ -6,6 +6,7 @@ use std::ffi;
use std::fmt; use std::fmt;
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use std::sync::Arc;
use byte_slice_cast::*; use byte_slice_cast::*;
@ -247,14 +248,32 @@ impl<'a> RecvBuilder<'a> {
if ptr.is_null() { if ptr.is_null() {
None None
} else { } else {
Some(RecvInstance(ptr::NonNull::new_unchecked(ptr))) #[allow(clippy::arc_with_non_send_sync)]
Some(RecvInstance(Arc::new(RecvInstancePtr(
ptr::NonNull::new_unchecked(ptr),
))))
} }
} }
} }
} }
#[derive(Debug, Clone)]
struct RecvInstancePtr(ptr::NonNull<::std::os::raw::c_void>);
impl Drop for RecvInstancePtr {
fn drop(&mut self) {
unsafe { NDIlib_recv_destroy(self.0.as_ptr() as *mut _) }
}
}
impl RecvInstancePtr {
fn as_ptr(&self) -> *mut ::std::os::raw::c_void {
self.0.as_ptr()
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct RecvInstance(ptr::NonNull<::std::os::raw::c_void>); pub struct RecvInstance(Arc<RecvInstancePtr>);
unsafe impl Send for RecvInstance {} unsafe impl Send for RecvInstance {}
@ -318,15 +337,17 @@ impl RecvInstance {
); );
match res { match res {
NDIlib_frame_type_e::NDIlib_frame_type_audio => Ok(Some(Frame::Audio( NDIlib_frame_type_e::NDIlib_frame_type_audio => Ok(Some(Frame::Audio(AudioFrame(
AudioFrame::BorrowedRecv(audio_frame, self), AudioFrameInner::BorrowedRecv(audio_frame, Arc::clone(&self.0)),
))), )))),
NDIlib_frame_type_e::NDIlib_frame_type_video => Ok(Some(Frame::Video( NDIlib_frame_type_e::NDIlib_frame_type_video => Ok(Some(Frame::Video(VideoFrame(
VideoFrame::BorrowedRecv(video_frame, self), VideoFrameInner::BorrowedRecv(video_frame, Arc::clone(&self.0)),
))), )))),
NDIlib_frame_type_e::NDIlib_frame_type_metadata => Ok(Some(Frame::Metadata( NDIlib_frame_type_e::NDIlib_frame_type_metadata => {
MetadataFrame::Borrowed(metadata_frame, self), Ok(Some(Frame::Metadata(MetadataFrame(
))), MetadataFrameInner::Borrowed(metadata_frame, Arc::clone(&self.0)),
))))
}
NDIlib_frame_type_e::NDIlib_frame_type_error => Err(ReceiveError), NDIlib_frame_type_e::NDIlib_frame_type_error => Err(ReceiveError),
_ => Ok(None), _ => Ok(None),
} }
@ -334,12 +355,6 @@ impl RecvInstance {
} }
} }
impl Drop for RecvInstance {
fn drop(&mut self) {
unsafe { NDIlib_recv_destroy(self.0.as_ptr() as *mut _) }
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct SendBuilder<'a> { pub struct SendBuilder<'a> {
ndi_name: &'a str, ndi_name: &'a str,
@ -420,7 +435,6 @@ impl Drop for SendInstance {
#[derive(Debug)] #[derive(Debug)]
pub struct Tally(NDIlib_tally_t); pub struct Tally(NDIlib_tally_t);
unsafe impl Send for Tally {}
impl Default for Tally { impl Default for Tally {
fn default() -> Self { fn default() -> Self {
@ -449,23 +463,40 @@ impl Tally {
} }
#[derive(Debug)] #[derive(Debug)]
pub enum Frame<'a> { pub enum Frame {
Video(VideoFrame<'a>), Video(VideoFrame),
Audio(AudioFrame<'a>), Audio(AudioFrame),
Metadata(MetadataFrame<'a>), Metadata(MetadataFrame),
} }
#[derive(Debug)] #[derive(Debug)]
pub enum VideoFrame<'a> { pub struct VideoFrame(VideoFrameInner);
#[derive(Debug)]
enum VideoFrameInner {
//Owned(NDIlib_video_frame_v2_t, Option<ffi::CString>, Option<Vec<u8>>), //Owned(NDIlib_video_frame_v2_t, Option<ffi::CString>, Option<Vec<u8>>),
BorrowedRecv(NDIlib_video_frame_v2_t, &'a RecvInstance), BorrowedRecv(NDIlib_video_frame_v2_t, Arc<RecvInstancePtr>),
BorrowedGst( BorrowedGst(
NDIlib_video_frame_v2_t, NDIlib_video_frame_v2_t,
&'a gst_video::VideoFrameRef<&'a gst::BufferRef>, gst_video::VideoFrame<gst_video::video_frame::Readable>,
Option<&'a std::ffi::CStr>, Option<std::ffi::CString>,
), ),
} }
impl Drop for VideoFrameInner {
#[allow(irrefutable_let_patterns)]
fn drop(&mut self) {
if let VideoFrameInner::BorrowedRecv(ref mut frame, ref recv) = *self {
unsafe {
NDIlib_recv_free_video_v2(recv.0.as_ptr() as *mut _, frame);
}
}
}
}
unsafe impl Send for VideoFrameInner {}
unsafe impl Sync for VideoFrameInner {}
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct TryFromVideoFrameError; pub struct TryFromVideoFrameError;
@ -477,60 +508,55 @@ impl fmt::Display for TryFromVideoFrameError {
impl std::error::Error for TryFromVideoFrameError {} impl std::error::Error for TryFromVideoFrameError {}
impl<'a> VideoFrame<'a> { impl VideoFrame {
pub fn xres(&self) -> i32 { pub fn xres(&self) -> i32 {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame.xres | VideoFrameInner::BorrowedGst(ref frame, ..) => frame.xres,
}
} }
} }
pub fn yres(&self) -> i32 { pub fn yres(&self) -> i32 {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame.yres | VideoFrameInner::BorrowedGst(ref frame, ..) => frame.yres,
}
} }
} }
pub fn fourcc(&self) -> NDIlib_FourCC_video_type_e { pub fn fourcc(&self) -> NDIlib_FourCC_video_type_e {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame.FourCC | VideoFrameInner::BorrowedGst(ref frame, ..) => frame.FourCC,
}
} }
} }
pub fn frame_rate(&self) -> (i32, i32) { pub fn frame_rate(&self) -> (i32, i32) {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
| VideoFrameInner::BorrowedGst(ref frame, ..) => {
(frame.frame_rate_N, frame.frame_rate_D) (frame.frame_rate_N, frame.frame_rate_D)
} }
} }
} }
pub fn picture_aspect_ratio(&self) -> f32 { pub fn picture_aspect_ratio(&self) -> f32 {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame.picture_aspect_ratio | VideoFrameInner::BorrowedGst(ref frame, ..) => frame.picture_aspect_ratio,
}
} }
} }
pub fn frame_format_type(&self) -> NDIlib_frame_format_type_e { pub fn frame_format_type(&self) -> NDIlib_frame_format_type_e {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame.frame_format_type | VideoFrameInner::BorrowedGst(ref frame, ..) => frame.frame_format_type,
}
} }
} }
pub fn timecode(&self) -> i64 { pub fn timecode(&self) -> i64 {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame.timecode | VideoFrameInner::BorrowedGst(ref frame, ..) => frame.timecode,
}
} }
} }
@ -566,9 +592,9 @@ impl<'a> VideoFrame<'a> {
return unsafe { return unsafe {
use std::slice; use std::slice;
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, ..) VideoFrameInner::BorrowedRecv(ref frame, ..)
| VideoFrame::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts( | VideoFrameInner::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts(
frame.p_data as *const u8, frame.p_data as *const u8,
frame_size as usize, frame_size as usize,
)), )),
@ -589,9 +615,9 @@ impl<'a> VideoFrame<'a> {
{ {
return unsafe { return unsafe {
use std::slice; use std::slice;
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, ..) VideoFrameInner::BorrowedRecv(ref frame, ..)
| VideoFrame::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts( | VideoFrameInner::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts(
frame.p_data as *const u8, frame.p_data as *const u8,
frame.line_stride_or_data_size_in_bytes as usize, frame.line_stride_or_data_size_in_bytes as usize,
)), )),
@ -626,9 +652,9 @@ impl<'a> VideoFrame<'a> {
return None; return None;
} }
let data = match self { let data = match self.0 {
VideoFrame::BorrowedRecv(ref frame, ..) VideoFrameInner::BorrowedRecv(ref frame, ..)
| VideoFrame::BorrowedGst(ref frame, ..) => slice::from_raw_parts( | VideoFrameInner::BorrowedGst(ref frame, ..) => slice::from_raw_parts(
frame.p_data as *const u8, frame.p_data as *const u8,
frame.line_stride_or_data_size_in_bytes as usize, frame.line_stride_or_data_size_in_bytes as usize,
), ),
@ -675,8 +701,9 @@ impl<'a> VideoFrame<'a> {
} }
pub fn line_stride_or_data_size_in_bytes(&self) -> i32 { pub fn line_stride_or_data_size_in_bytes(&self) -> i32 {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
| VideoFrameInner::BorrowedGst(ref frame, ..) => {
let stride = frame.line_stride_or_data_size_in_bytes; let stride = frame.line_stride_or_data_size_in_bytes;
if stride != 0 { if stride != 0 {
@ -705,8 +732,9 @@ impl<'a> VideoFrame<'a> {
pub fn metadata(&self) -> Option<&str> { pub fn metadata(&self) -> Option<&str> {
unsafe { unsafe {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
| VideoFrameInner::BorrowedGst(ref frame, ..) => {
if frame.p_metadata.is_null() { if frame.p_metadata.is_null() {
None None
} else { } else {
@ -718,24 +746,22 @@ impl<'a> VideoFrame<'a> {
} }
pub fn timestamp(&self) -> i64 { pub fn timestamp(&self) -> i64 {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame.timestamp | VideoFrameInner::BorrowedGst(ref frame, ..) => frame.timestamp,
}
} }
} }
pub fn as_ptr(&self) -> *const NDIlib_video_frame_v2_t { pub fn as_ptr(&self) -> *const NDIlib_video_frame_v2_t {
match self { match self.0 {
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => { VideoFrameInner::BorrowedRecv(ref frame, _)
frame | VideoFrameInner::BorrowedGst(ref frame, ..) => frame,
}
} }
} }
pub fn try_from_video_frame( pub fn try_from_video_frame(
frame: &'a gst_video::VideoFrameRef<&'a gst::BufferRef>, frame: gst_video::VideoFrame<gst_video::video_frame::Readable>,
metadata: Option<&'a std::ffi::CStr>, metadata: Option<std::ffi::CString>,
timecode: i64, timecode: i64,
) -> Result<Self, TryFromVideoFrameError> { ) -> Result<Self, TryFromVideoFrameError> {
// Planar formats must be in contiguous memory // Planar formats must be in contiguous memory
@ -841,35 +867,43 @@ impl<'a> VideoFrame<'a> {
timecode, timecode,
p_data: frame.plane_data(0).unwrap().as_ptr() as *const ::std::os::raw::c_char, p_data: frame.plane_data(0).unwrap().as_ptr() as *const ::std::os::raw::c_char,
line_stride_or_data_size_in_bytes: frame.plane_stride()[0], line_stride_or_data_size_in_bytes: frame.plane_stride()[0],
p_metadata: metadata.map_or(ptr::null(), |meta| meta.as_ptr()), p_metadata: metadata.as_ref().map_or(ptr::null(), |meta| meta.as_ptr()),
timestamp: 0, timestamp: 0,
}; };
Ok(VideoFrame::BorrowedGst(ndi_frame, frame, metadata)) Ok(VideoFrame(VideoFrameInner::BorrowedGst(
} ndi_frame, frame, metadata,
} )))
impl<'a> Drop for VideoFrame<'a> {
#[allow(irrefutable_let_patterns)]
fn drop(&mut self) {
if let VideoFrame::BorrowedRecv(ref mut frame, recv) = *self {
unsafe {
NDIlib_recv_free_video_v2(recv.0.as_ptr() as *mut _, frame);
}
}
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub enum AudioFrame<'a> { pub struct AudioFrame(AudioFrameInner);
#[derive(Debug)]
enum AudioFrameInner {
Owned( Owned(
NDIlib_audio_frame_v3_t, NDIlib_audio_frame_v3_t,
Option<ffi::CString>, Option<ffi::CString>,
Option<Vec<f32>>, Option<Vec<f32>>,
), ),
BorrowedRecv(NDIlib_audio_frame_v3_t, &'a RecvInstance), BorrowedRecv(NDIlib_audio_frame_v3_t, Arc<RecvInstancePtr>),
} }
impl Drop for AudioFrameInner {
#[allow(irrefutable_let_patterns)]
fn drop(&mut self) {
if let AudioFrameInner::BorrowedRecv(ref mut frame, ref recv) = *self {
unsafe {
NDIlib_recv_free_audio_v3(recv.0.as_ptr() as *mut _, frame);
}
}
}
}
unsafe impl Send for AudioFrameInner {}
unsafe impl Sync for AudioFrameInner {}
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct TryFromAudioBufferError; pub struct TryFromAudioBufferError;
@ -881,44 +915,39 @@ impl fmt::Display for TryFromAudioBufferError {
impl std::error::Error for TryFromAudioBufferError {} impl std::error::Error for TryFromAudioBufferError {}
impl<'a> AudioFrame<'a> { impl AudioFrame {
pub fn sample_rate(&self) -> i32 { pub fn sample_rate(&self) -> i32 {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
frame.sample_rate | AudioFrameInner::Owned(ref frame, _, _) => frame.sample_rate,
}
} }
} }
pub fn no_channels(&self) -> i32 { pub fn no_channels(&self) -> i32 {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
frame.no_channels | AudioFrameInner::Owned(ref frame, _, _) => frame.no_channels,
}
} }
} }
pub fn no_samples(&self) -> i32 { pub fn no_samples(&self) -> i32 {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
frame.no_samples | AudioFrameInner::Owned(ref frame, _, _) => frame.no_samples,
}
} }
} }
pub fn timecode(&self) -> i64 { pub fn timecode(&self) -> i64 {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
frame.timecode | AudioFrameInner::Owned(ref frame, _, _) => frame.timecode,
}
} }
} }
pub fn fourcc(&self) -> NDIlib_FourCC_audio_type_e { pub fn fourcc(&self) -> NDIlib_FourCC_audio_type_e {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
frame.FourCC | AudioFrameInner::Owned(ref frame, _, _) => frame.FourCC,
}
} }
} }
@ -929,26 +958,23 @@ impl<'a> AudioFrame<'a> {
let fourcc = self.fourcc(); let fourcc = self.fourcc();
if [NDIlib_FourCC_audio_type_FLTp].contains(&fourcc) { if [NDIlib_FourCC_audio_type_FLTp].contains(&fourcc) {
return match self { return match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
Some(slice::from_raw_parts( | AudioFrameInner::Owned(ref frame, _, _) => Some(slice::from_raw_parts(
frame.p_data as *const u8, frame.p_data as *const u8,
(frame.no_channels * frame.channel_stride_or_data_size_in_bytes) (frame.no_channels * frame.channel_stride_or_data_size_in_bytes) as usize,
as usize, )),
))
}
}; };
} }
#[cfg(feature = "advanced-sdk")] #[cfg(feature = "advanced-sdk")]
if [NDIlib_FourCC_audio_type_Opus].contains(&fourcc) { if [NDIlib_FourCC_audio_type_Opus].contains(&fourcc) {
return match self { return match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
Some(slice::from_raw_parts( | AudioFrameInner::Owned(ref frame, _, _) => Some(slice::from_raw_parts(
frame.p_data as *const u8, frame.p_data as *const u8,
frame.channel_stride_or_data_size_in_bytes as usize, frame.channel_stride_or_data_size_in_bytes as usize,
)) )),
}
}; };
} }
@ -969,13 +995,12 @@ impl<'a> AudioFrame<'a> {
return None; return None;
} }
let data = match self { let data = match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
slice::from_raw_parts( | AudioFrameInner::Owned(ref frame, _, _) => slice::from_raw_parts(
frame.p_data as *const u8, frame.p_data as *const u8,
frame.channel_stride_or_data_size_in_bytes as usize, frame.channel_stride_or_data_size_in_bytes as usize,
) ),
}
}; };
let mut cursor = Cursor::new(data); let mut cursor = Cursor::new(data);
@ -1019,17 +1044,17 @@ impl<'a> AudioFrame<'a> {
} }
pub fn channel_stride_or_data_size_in_bytes(&self) -> i32 { pub fn channel_stride_or_data_size_in_bytes(&self) -> i32 {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
frame.channel_stride_or_data_size_in_bytes | AudioFrameInner::Owned(ref frame, _, _) => frame.channel_stride_or_data_size_in_bytes,
}
} }
} }
pub fn metadata(&self) -> Option<&str> { pub fn metadata(&self) -> Option<&str> {
unsafe { unsafe {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
| AudioFrameInner::Owned(ref frame, _, _) => {
if frame.p_metadata.is_null() { if frame.p_metadata.is_null() {
None None
} else { } else {
@ -1041,16 +1066,16 @@ impl<'a> AudioFrame<'a> {
} }
pub fn timestamp(&self) -> i64 { pub fn timestamp(&self) -> i64 {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => { AudioFrameInner::BorrowedRecv(ref frame, _)
frame.timestamp | AudioFrameInner::Owned(ref frame, _, _) => frame.timestamp,
}
} }
} }
pub fn as_ptr(&self) -> *const NDIlib_audio_frame_v3_t { pub fn as_ptr(&self) -> *const NDIlib_audio_frame_v3_t {
match self { match self.0 {
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => frame, AudioFrameInner::BorrowedRecv(ref frame, _)
| AudioFrameInner::Owned(ref frame, _, _) => frame,
} }
} }
@ -1099,18 +1124,11 @@ impl<'a> AudioFrame<'a> {
timestamp: 0, timestamp: 0,
}; };
Ok(AudioFrame::Owned(dest, None, Some(dest_data))) Ok(AudioFrame(AudioFrameInner::Owned(
} dest,
} None,
Some(dest_data),
impl<'a> Drop for AudioFrame<'a> { )))
#[allow(irrefutable_let_patterns)]
fn drop(&mut self) {
if let AudioFrame::BorrowedRecv(ref mut frame, recv) = *self {
unsafe {
NDIlib_recv_free_audio_v3(recv.0.as_ptr() as *mut _, frame);
}
}
} }
} }
@ -1125,16 +1143,32 @@ pub struct CompressedPacket<'a> {
} }
#[derive(Debug)] #[derive(Debug)]
pub enum MetadataFrame<'a> { pub struct MetadataFrame(MetadataFrameInner);
#[derive(Debug)]
enum MetadataFrameInner {
Owned(NDIlib_metadata_frame_t, Option<ffi::CString>), Owned(NDIlib_metadata_frame_t, Option<ffi::CString>),
Borrowed(NDIlib_metadata_frame_t, &'a RecvInstance), Borrowed(NDIlib_metadata_frame_t, Arc<RecvInstancePtr>),
} }
impl<'a> MetadataFrame<'a> { impl Drop for MetadataFrameInner {
fn drop(&mut self) {
if let MetadataFrameInner::Borrowed(ref mut frame, ref recv) = *self {
unsafe {
NDIlib_recv_free_metadata(recv.0.as_ptr() as *mut _, frame);
}
}
}
}
unsafe impl Send for MetadataFrameInner {}
unsafe impl Sync for MetadataFrameInner {}
impl MetadataFrame {
pub fn new(timecode: i64, data: Option<&str>) -> Self { pub fn new(timecode: i64, data: Option<&str>) -> Self {
let data = data.map(|s| ffi::CString::new(s).unwrap()); let data = data.map(|s| ffi::CString::new(s).unwrap());
MetadataFrame::Owned( MetadataFrame(MetadataFrameInner::Owned(
NDIlib_metadata_frame_t { NDIlib_metadata_frame_t {
length: data length: data
.as_ref() .as_ref()
@ -1147,23 +1181,23 @@ impl<'a> MetadataFrame<'a> {
.unwrap_or(ptr::null_mut()), .unwrap_or(ptr::null_mut()),
}, },
data, data,
) ))
} }
pub fn timecode(&self) -> i64 { pub fn timecode(&self) -> i64 {
match self { match self.0 {
MetadataFrame::Owned(ref frame, _) => frame.timecode, MetadataFrameInner::Owned(ref frame, _) => frame.timecode,
MetadataFrame::Borrowed(ref frame, _) => frame.timecode, MetadataFrameInner::Borrowed(ref frame, _) => frame.timecode,
} }
} }
pub fn metadata(&self) -> Option<&str> { pub fn metadata(&self) -> Option<&str> {
unsafe { unsafe {
match self { match self.0 {
MetadataFrame::Owned(_, ref metadata) => { MetadataFrameInner::Owned(_, ref metadata) => {
metadata.as_ref().map(|s| s.to_str().unwrap()) metadata.as_ref().map(|s| s.to_str().unwrap())
} }
MetadataFrame::Borrowed(ref frame, _) => { MetadataFrameInner::Borrowed(ref frame, _) => {
if frame.p_data.is_null() || frame.length == 0 { if frame.p_data.is_null() || frame.length == 0 {
None None
} else if frame.length != 0 { } else if frame.length != 0 {
@ -1186,33 +1220,23 @@ impl<'a> MetadataFrame<'a> {
} }
pub fn as_ptr(&self) -> *const NDIlib_metadata_frame_t { pub fn as_ptr(&self) -> *const NDIlib_metadata_frame_t {
match self { match self.0 {
MetadataFrame::Owned(ref frame, _) => frame, MetadataFrameInner::Owned(ref frame, _) => frame,
MetadataFrame::Borrowed(ref frame, _) => frame, MetadataFrameInner::Borrowed(ref frame, _) => frame,
} }
} }
} }
impl<'a> Default for MetadataFrame<'a> { impl Default for MetadataFrame {
fn default() -> Self { fn default() -> Self {
MetadataFrame::Owned( MetadataFrame(MetadataFrameInner::Owned(
NDIlib_metadata_frame_t { NDIlib_metadata_frame_t {
length: 0, length: 0,
timecode: 0, //NDIlib_send_timecode_synthesize, timecode: 0, //NDIlib_send_timecode_synthesize,
p_data: ptr::null(), p_data: ptr::null(),
}, },
None, None,
) ))
}
}
impl<'a> Drop for MetadataFrame<'a> {
fn drop(&mut self) {
if let MetadataFrame::Borrowed(ref mut frame, recv) = *self {
unsafe {
NDIlib_recv_free_metadata(recv.0.as_ptr() as *mut _, frame);
}
}
} }
} }

View file

@ -315,17 +315,13 @@ impl BaseSinkImpl for NdiSink {
ndi_meta = ndi_cc_encoder.encode(buffer); ndi_meta = ndi_cc_encoder.encode(buffer);
} }
let frame = gst_video::VideoFrameRef::from_buffer_ref_readable(buffer, info) let frame = gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info)
.map_err(|_| { .map_err(|_| {
gst::error!(CAT, imp: self, "Failed to map buffer"); gst::error!(CAT, imp: self, "Failed to map buffer");
gst::FlowError::Error gst::FlowError::Error
})?; })?;
let frame = crate::ndi::VideoFrame::try_from_video_frame( let frame = crate::ndi::VideoFrame::try_from_video_frame(frame, ndi_meta, timecode)
&frame,
ndi_meta.as_deref(),
timecode,
)
.map_err(|_| { .map_err(|_| {
gst::error!(CAT, imp: self, "Unsupported video frame"); gst::error!(CAT, imp: self, "Unsupported video frame");
gst::FlowError::NotNegotiated gst::FlowError::NotNegotiated