mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-26 05:21:00 +00:00
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:
parent
eb137ec6dc
commit
99d7cce0d6
2 changed files with 215 additions and 195 deletions
|
@ -6,6 +6,7 @@ use std::ffi;
|
|||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use byte_slice_cast::*;
|
||||
|
||||
|
@ -247,14 +248,32 @@ impl<'a> RecvBuilder<'a> {
|
|||
if ptr.is_null() {
|
||||
None
|
||||
} 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)]
|
||||
pub struct RecvInstance(ptr::NonNull<::std::os::raw::c_void>);
|
||||
pub struct RecvInstance(Arc<RecvInstancePtr>);
|
||||
|
||||
unsafe impl Send for RecvInstance {}
|
||||
|
||||
|
@ -318,15 +337,17 @@ impl RecvInstance {
|
|||
);
|
||||
|
||||
match res {
|
||||
NDIlib_frame_type_e::NDIlib_frame_type_audio => Ok(Some(Frame::Audio(
|
||||
AudioFrame::BorrowedRecv(audio_frame, self),
|
||||
))),
|
||||
NDIlib_frame_type_e::NDIlib_frame_type_video => Ok(Some(Frame::Video(
|
||||
VideoFrame::BorrowedRecv(video_frame, self),
|
||||
))),
|
||||
NDIlib_frame_type_e::NDIlib_frame_type_metadata => Ok(Some(Frame::Metadata(
|
||||
MetadataFrame::Borrowed(metadata_frame, self),
|
||||
))),
|
||||
NDIlib_frame_type_e::NDIlib_frame_type_audio => Ok(Some(Frame::Audio(AudioFrame(
|
||||
AudioFrameInner::BorrowedRecv(audio_frame, Arc::clone(&self.0)),
|
||||
)))),
|
||||
NDIlib_frame_type_e::NDIlib_frame_type_video => Ok(Some(Frame::Video(VideoFrame(
|
||||
VideoFrameInner::BorrowedRecv(video_frame, Arc::clone(&self.0)),
|
||||
)))),
|
||||
NDIlib_frame_type_e::NDIlib_frame_type_metadata => {
|
||||
Ok(Some(Frame::Metadata(MetadataFrame(
|
||||
MetadataFrameInner::Borrowed(metadata_frame, Arc::clone(&self.0)),
|
||||
))))
|
||||
}
|
||||
NDIlib_frame_type_e::NDIlib_frame_type_error => Err(ReceiveError),
|
||||
_ => 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)]
|
||||
pub struct SendBuilder<'a> {
|
||||
ndi_name: &'a str,
|
||||
|
@ -420,7 +435,6 @@ impl Drop for SendInstance {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Tally(NDIlib_tally_t);
|
||||
unsafe impl Send for Tally {}
|
||||
|
||||
impl Default for Tally {
|
||||
fn default() -> Self {
|
||||
|
@ -449,23 +463,40 @@ impl Tally {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Frame<'a> {
|
||||
Video(VideoFrame<'a>),
|
||||
Audio(AudioFrame<'a>),
|
||||
Metadata(MetadataFrame<'a>),
|
||||
pub enum Frame {
|
||||
Video(VideoFrame),
|
||||
Audio(AudioFrame),
|
||||
Metadata(MetadataFrame),
|
||||
}
|
||||
|
||||
#[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>>),
|
||||
BorrowedRecv(NDIlib_video_frame_v2_t, &'a RecvInstance),
|
||||
BorrowedRecv(NDIlib_video_frame_v2_t, Arc<RecvInstancePtr>),
|
||||
BorrowedGst(
|
||||
NDIlib_video_frame_v2_t,
|
||||
&'a gst_video::VideoFrameRef<&'a gst::BufferRef>,
|
||||
Option<&'a std::ffi::CStr>,
|
||||
gst_video::VideoFrame<gst_video::video_frame::Readable>,
|
||||
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)]
|
||||
pub struct TryFromVideoFrameError;
|
||||
|
||||
|
@ -477,60 +508,55 @@ impl fmt::Display for TryFromVideoFrameError {
|
|||
|
||||
impl std::error::Error for TryFromVideoFrameError {}
|
||||
|
||||
impl<'a> VideoFrame<'a> {
|
||||
impl VideoFrame {
|
||||
pub fn xres(&self) -> i32 {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame.xres
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame.xres,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn yres(&self) -> i32 {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame.yres
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame.yres,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fourcc(&self) -> NDIlib_FourCC_video_type_e {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame.FourCC
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame.FourCC,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frame_rate(&self) -> (i32, i32) {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => {
|
||||
(frame.frame_rate_N, frame.frame_rate_D)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn picture_aspect_ratio(&self) -> f32 {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame.picture_aspect_ratio
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame.picture_aspect_ratio,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frame_format_type(&self) -> NDIlib_frame_format_type_e {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame.frame_format_type
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame.frame_format_type,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn timecode(&self) -> i64 {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame.timecode
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame.timecode,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,9 +592,9 @@ impl<'a> VideoFrame<'a> {
|
|||
|
||||
return unsafe {
|
||||
use std::slice;
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, ..)
|
||||
| VideoFrame::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts(
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, ..)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
frame_size as usize,
|
||||
)),
|
||||
|
@ -589,9 +615,9 @@ impl<'a> VideoFrame<'a> {
|
|||
{
|
||||
return unsafe {
|
||||
use std::slice;
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, ..)
|
||||
| VideoFrame::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts(
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, ..)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => Some(slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
frame.line_stride_or_data_size_in_bytes as usize,
|
||||
)),
|
||||
|
@ -626,9 +652,9 @@ impl<'a> VideoFrame<'a> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let data = match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, ..)
|
||||
| VideoFrame::BorrowedGst(ref frame, ..) => slice::from_raw_parts(
|
||||
let data = match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, ..)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
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 {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => {
|
||||
let stride = frame.line_stride_or_data_size_in_bytes;
|
||||
|
||||
if stride != 0 {
|
||||
|
@ -705,8 +732,9 @@ impl<'a> VideoFrame<'a> {
|
|||
|
||||
pub fn metadata(&self) -> Option<&str> {
|
||||
unsafe {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => {
|
||||
if frame.p_metadata.is_null() {
|
||||
None
|
||||
} else {
|
||||
|
@ -718,24 +746,22 @@ impl<'a> VideoFrame<'a> {
|
|||
}
|
||||
|
||||
pub fn timestamp(&self) -> i64 {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame.timestamp
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame.timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const NDIlib_video_frame_v2_t {
|
||||
match self {
|
||||
VideoFrame::BorrowedRecv(ref frame, _) | VideoFrame::BorrowedGst(ref frame, ..) => {
|
||||
frame
|
||||
}
|
||||
match self.0 {
|
||||
VideoFrameInner::BorrowedRecv(ref frame, _)
|
||||
| VideoFrameInner::BorrowedGst(ref frame, ..) => frame,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_from_video_frame(
|
||||
frame: &'a gst_video::VideoFrameRef<&'a gst::BufferRef>,
|
||||
metadata: Option<&'a std::ffi::CStr>,
|
||||
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>,
|
||||
metadata: Option<std::ffi::CString>,
|
||||
timecode: i64,
|
||||
) -> Result<Self, TryFromVideoFrameError> {
|
||||
// Planar formats must be in contiguous memory
|
||||
|
@ -841,35 +867,43 @@ impl<'a> VideoFrame<'a> {
|
|||
timecode,
|
||||
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],
|
||||
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,
|
||||
};
|
||||
|
||||
Ok(VideoFrame::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);
|
||||
}
|
||||
}
|
||||
Ok(VideoFrame(VideoFrameInner::BorrowedGst(
|
||||
ndi_frame, frame, metadata,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AudioFrame<'a> {
|
||||
pub struct AudioFrame(AudioFrameInner);
|
||||
|
||||
#[derive(Debug)]
|
||||
enum AudioFrameInner {
|
||||
Owned(
|
||||
NDIlib_audio_frame_v3_t,
|
||||
Option<ffi::CString>,
|
||||
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)]
|
||||
pub struct TryFromAudioBufferError;
|
||||
|
||||
|
@ -881,44 +915,39 @@ impl fmt::Display for TryFromAudioBufferError {
|
|||
|
||||
impl std::error::Error for TryFromAudioBufferError {}
|
||||
|
||||
impl<'a> AudioFrame<'a> {
|
||||
impl AudioFrame {
|
||||
pub fn sample_rate(&self) -> i32 {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
frame.sample_rate
|
||||
}
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame.sample_rate,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_channels(&self) -> i32 {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
frame.no_channels
|
||||
}
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame.no_channels,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_samples(&self) -> i32 {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
frame.no_samples
|
||||
}
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame.no_samples,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn timecode(&self) -> i64 {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
frame.timecode
|
||||
}
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame.timecode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fourcc(&self) -> NDIlib_FourCC_audio_type_e {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
frame.FourCC
|
||||
}
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame.FourCC,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -929,26 +958,23 @@ impl<'a> AudioFrame<'a> {
|
|||
let fourcc = self.fourcc();
|
||||
|
||||
if [NDIlib_FourCC_audio_type_FLTp].contains(&fourcc) {
|
||||
return match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
Some(slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
(frame.no_channels * frame.channel_stride_or_data_size_in_bytes)
|
||||
as usize,
|
||||
))
|
||||
}
|
||||
return match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => Some(slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
(frame.no_channels * frame.channel_stride_or_data_size_in_bytes) as usize,
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "advanced-sdk")]
|
||||
if [NDIlib_FourCC_audio_type_Opus].contains(&fourcc) {
|
||||
return match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
Some(slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
frame.channel_stride_or_data_size_in_bytes as usize,
|
||||
))
|
||||
}
|
||||
return match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => Some(slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
frame.channel_stride_or_data_size_in_bytes as usize,
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -969,13 +995,12 @@ impl<'a> AudioFrame<'a> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let data = match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
frame.channel_stride_or_data_size_in_bytes as usize,
|
||||
)
|
||||
}
|
||||
let data = match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => slice::from_raw_parts(
|
||||
frame.p_data as *const u8,
|
||||
frame.channel_stride_or_data_size_in_bytes as usize,
|
||||
),
|
||||
};
|
||||
|
||||
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 {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
frame.channel_stride_or_data_size_in_bytes
|
||||
}
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame.channel_stride_or_data_size_in_bytes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Option<&str> {
|
||||
unsafe {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => {
|
||||
if frame.p_metadata.is_null() {
|
||||
None
|
||||
} else {
|
||||
|
@ -1041,16 +1066,16 @@ impl<'a> AudioFrame<'a> {
|
|||
}
|
||||
|
||||
pub fn timestamp(&self) -> i64 {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => {
|
||||
frame.timestamp
|
||||
}
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame.timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const NDIlib_audio_frame_v3_t {
|
||||
match self {
|
||||
AudioFrame::BorrowedRecv(ref frame, _) | AudioFrame::Owned(ref frame, _, _) => frame,
|
||||
match self.0 {
|
||||
AudioFrameInner::BorrowedRecv(ref frame, _)
|
||||
| AudioFrameInner::Owned(ref frame, _, _) => frame,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1099,18 +1124,11 @@ impl<'a> AudioFrame<'a> {
|
|||
timestamp: 0,
|
||||
};
|
||||
|
||||
Ok(AudioFrame::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);
|
||||
}
|
||||
}
|
||||
Ok(AudioFrame(AudioFrameInner::Owned(
|
||||
dest,
|
||||
None,
|
||||
Some(dest_data),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1125,16 +1143,32 @@ pub struct CompressedPacket<'a> {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MetadataFrame<'a> {
|
||||
pub struct MetadataFrame(MetadataFrameInner);
|
||||
|
||||
#[derive(Debug)]
|
||||
enum MetadataFrameInner {
|
||||
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 {
|
||||
let data = data.map(|s| ffi::CString::new(s).unwrap());
|
||||
|
||||
MetadataFrame::Owned(
|
||||
MetadataFrame(MetadataFrameInner::Owned(
|
||||
NDIlib_metadata_frame_t {
|
||||
length: data
|
||||
.as_ref()
|
||||
|
@ -1147,23 +1181,23 @@ impl<'a> MetadataFrame<'a> {
|
|||
.unwrap_or(ptr::null_mut()),
|
||||
},
|
||||
data,
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
pub fn timecode(&self) -> i64 {
|
||||
match self {
|
||||
MetadataFrame::Owned(ref frame, _) => frame.timecode,
|
||||
MetadataFrame::Borrowed(ref frame, _) => frame.timecode,
|
||||
match self.0 {
|
||||
MetadataFrameInner::Owned(ref frame, _) => frame.timecode,
|
||||
MetadataFrameInner::Borrowed(ref frame, _) => frame.timecode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Option<&str> {
|
||||
unsafe {
|
||||
match self {
|
||||
MetadataFrame::Owned(_, ref metadata) => {
|
||||
match self.0 {
|
||||
MetadataFrameInner::Owned(_, ref metadata) => {
|
||||
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 {
|
||||
None
|
||||
} else if frame.length != 0 {
|
||||
|
@ -1186,33 +1220,23 @@ impl<'a> MetadataFrame<'a> {
|
|||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const NDIlib_metadata_frame_t {
|
||||
match self {
|
||||
MetadataFrame::Owned(ref frame, _) => frame,
|
||||
MetadataFrame::Borrowed(ref frame, _) => frame,
|
||||
match self.0 {
|
||||
MetadataFrameInner::Owned(ref frame, _) => frame,
|
||||
MetadataFrameInner::Borrowed(ref frame, _) => frame,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Default for MetadataFrame<'a> {
|
||||
impl Default for MetadataFrame {
|
||||
fn default() -> Self {
|
||||
MetadataFrame::Owned(
|
||||
MetadataFrame(MetadataFrameInner::Owned(
|
||||
NDIlib_metadata_frame_t {
|
||||
length: 0,
|
||||
timecode: 0, //NDIlib_send_timecode_synthesize,
|
||||
p_data: ptr::null(),
|
||||
},
|
||||
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);
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -315,21 +315,17 @@ impl BaseSinkImpl for NdiSink {
|
|||
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(|_| {
|
||||
gst::error!(CAT, imp: self, "Failed to map buffer");
|
||||
gst::FlowError::Error
|
||||
})?;
|
||||
|
||||
let frame = crate::ndi::VideoFrame::try_from_video_frame(
|
||||
&frame,
|
||||
ndi_meta.as_deref(),
|
||||
timecode,
|
||||
)
|
||||
.map_err(|_| {
|
||||
gst::error!(CAT, imp: self, "Unsupported video frame");
|
||||
gst::FlowError::NotNegotiated
|
||||
})?;
|
||||
let frame = crate::ndi::VideoFrame::try_from_video_frame(frame, ndi_meta, timecode)
|
||||
.map_err(|_| {
|
||||
gst::error!(CAT, imp: self, "Unsupported video frame");
|
||||
gst::FlowError::NotNegotiated
|
||||
})?;
|
||||
|
||||
gst::trace!(
|
||||
CAT,
|
||||
|
|
Loading…
Reference in a new issue