mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-09-28 23:02:13 +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::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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue