diff --git a/README.md b/README.md index 9344ffab9..5704660ea 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ GStreamer NDI Plugin for Linux ==================== -*Compiled and tested with Ubuntu 16.04.5, GStreamer 1.12 and NDI SDK 3.5.1* +*Compiled and tested with NDI SDK 3.5, 3.8, 4.0 and 4.1* This is a plugin for the [GStreamer](https://gstreamer.freedesktop.org/) multimedia framework that allows GStreamer to receive a stream from a [NDI](https://www.newtek.com/ndi/) source. This plugin has been developed by [Teltek](http://teltek.es/) and was funded by the [University of the Arts London](https://www.arts.ac.uk/) and [The University of Manchester](https://www.manchester.ac.uk/). diff --git a/src/ndi.rs b/src/ndi.rs index 6f04ad452..f17170b88 100644 --- a/src/ndi.rs +++ b/src/ndi.rs @@ -1,3 +1,4 @@ +use crate::ndisys; use crate::ndisys::*; use std::ffi; use std::mem; @@ -135,15 +136,15 @@ impl<'a> Source<'a> { } } - pub fn ip_address(&self) -> &str { + pub fn url_address(&self) -> &str { unsafe { let ptr = match *self { Source::Borrowed(ptr, _) => &*ptr.as_ptr(), Source::Owned(ref source, _, _) => source, }; - assert!(!ptr.p_ip_address.is_null()); - ffi::CStr::from_ptr(ptr.p_ip_address).to_str().unwrap() + assert!(!ptr.p_url_address.is_null()); + ffi::CStr::from_ptr(ptr.p_url_address).to_str().unwrap() } } @@ -156,34 +157,35 @@ impl<'a> Source<'a> { } } - fn ip_address_ptr(&self) -> *const ::std::os::raw::c_char { + fn url_address_ptr(&self) -> *const ::std::os::raw::c_char { unsafe { match *self { - Source::Borrowed(ptr, _) => ptr.as_ref().p_ip_address, - Source::Owned(_, _, ref ip_address) => ip_address.as_ptr(), + Source::Borrowed(ptr, _) => ptr.as_ref().p_url_address, + Source::Owned(_, _, ref url_address) => url_address.as_ptr(), } } } pub fn to_owned<'b>(&self) -> Source<'b> { unsafe { - let (ndi_name, ip_address) = match *self { - Source::Borrowed(ptr, _) => (ptr.as_ref().p_ndi_name, ptr.as_ref().p_ip_address), - Source::Owned(_, ref ndi_name, ref ip_address) => { - (ndi_name.as_ptr(), ip_address.as_ptr()) + let (ndi_name, url_address) = match *self { + Source::Borrowed(ptr, _) => (ptr.as_ref().p_ndi_name, ptr.as_ref().p_url_address), + Source::Owned(_, ref ndi_name, ref url_address) => { + (ndi_name.as_ptr(), url_address.as_ptr()) } }; let ndi_name = ffi::CString::new(ffi::CStr::from_ptr(ndi_name).to_bytes()).unwrap(); - let ip_address = ffi::CString::new(ffi::CStr::from_ptr(ip_address).to_bytes()).unwrap(); + let url_address = + ffi::CString::new(ffi::CStr::from_ptr(url_address).to_bytes()).unwrap(); Source::Owned( NDIlib_source_t { p_ndi_name: ndi_name.as_ptr(), - p_ip_address: ip_address.as_ptr(), + p_url_address: url_address.as_ptr(), }, ndi_name, - ip_address, + url_address, ) } } @@ -223,12 +225,12 @@ impl<'a> RecvBuilder<'a> { let ptr = NDIlib_recv_create_v3(&NDIlib_recv_create_v3_t { source_to_connect_to: NDIlib_source_t { p_ndi_name: self.source_to_connect_to.ndi_name_ptr(), - p_ip_address: self.source_to_connect_to.ip_address_ptr(), + p_url_address: self.source_to_connect_to.url_address_ptr(), }, allow_video_fields: self.allow_video_fields, bandwidth: self.bandwidth, color_format: self.color_format, - p_ndi_name: ndi_name.as_ptr(), + p_ndi_recv_name: ndi_name.as_ptr(), }); if ptr.is_null() { @@ -410,7 +412,7 @@ impl<'a> VideoFrame<'a> { } } - pub fn fourcc(&self) -> NDIlib_FourCC_type_e { + pub fn fourcc(&self) -> NDIlib_FourCC_video_type_e { match self { VideoFrame::Borrowed(ref frame, _) => frame.FourCC, } @@ -448,9 +450,9 @@ impl<'a> VideoFrame<'a> { || self.frame_format_type() == NDIlib_frame_format_type_e::NDIlib_frame_format_type_field_1 { - self.yres() * self.line_stride_in_bytes() / 2 + self.yres() * self.line_stride_or_data_size_in_bytes() / 2 } else { - self.yres() * self.line_stride_in_bytes() + self.yres() * self.line_stride_or_data_size_in_bytes() }; unsafe { @@ -463,9 +465,32 @@ impl<'a> VideoFrame<'a> { } } - pub fn line_stride_in_bytes(&self) -> i32 { + pub fn line_stride_or_data_size_in_bytes(&self) -> i32 { match self { - VideoFrame::Borrowed(ref frame, _) => frame.line_stride_in_bytes, + VideoFrame::Borrowed(ref frame, _) => { + let stride = frame.line_stride_or_data_size_in_bytes; + + if stride != 0 { + return stride; + } + + let xres = frame.xres; + + match frame.FourCC { + ndisys::NDIlib_FourCC_video_type_UYVY + | ndisys::NDIlib_FourCC_video_type_UYVA + | ndisys::NDIlib_FourCC_video_type_YV12 + | ndisys::NDIlib_FourCC_video_type_NV12 + | ndisys::NDIlib_FourCC_video_type_I420 + | ndisys::NDIlib_FourCC_video_type_BGRA + | ndisys::NDIlib_FourCC_video_type_BGRX + | ndisys::NDIlib_FourCC_video_type_RGBA + | ndisys::NDIlib_FourCC_video_type_RGBX => xres, + ndisys::NDIlib_FourCC_video_type_P216 + | ndisys::NDIlib_FourCC_video_type_PA16 => 2 * xres, + _ => 0, + } + } } } diff --git a/src/ndiaudiosrc.rs b/src/ndiaudiosrc.rs index 2d06bb34f..47a41fdc7 100644 --- a/src/ndiaudiosrc.rs +++ b/src/ndiaudiosrc.rs @@ -24,7 +24,6 @@ use crate::DEFAULT_RECEIVER_NDI_NAME; #[derive(Debug, Clone)] struct Settings { ndi_name: Option, - ip_address: Option, connect_timeout: u32, timeout: u32, receiver_ndi_name: String, @@ -36,7 +35,6 @@ impl Default for Settings { fn default() -> Self { Settings { ndi_name: None, - ip_address: None, receiver_ndi_name: DEFAULT_RECEIVER_NDI_NAME.clone(), connect_timeout: 10000, timeout: 5000, @@ -46,7 +44,7 @@ impl Default for Settings { } } -static PROPERTIES: [subclass::Property; 7] = [ +static PROPERTIES: [subclass::Property; 6] = [ subclass::Property("ndi-name", |name| { glib::ParamSpec::string( name, @@ -56,15 +54,6 @@ static PROPERTIES: [subclass::Property; 7] = [ glib::ParamFlags::READWRITE, ) }), - subclass::Property("ip-address", |name| { - glib::ParamSpec::string( - name, - "IP Address", - "IP address and port of the sender, e.g. 127.0.0.1:5961", - None, - glib::ParamFlags::READWRITE, - ) - }), subclass::Property("receiver-ndi-name", |name| { glib::ParamSpec::string( name, @@ -227,18 +216,6 @@ impl ObjectImpl for NdiAudioSrc { ); settings.ndi_name = ndi_name; } - subclass::Property("ip-address", ..) => { - let mut settings = self.settings.lock().unwrap(); - let ip_address = value.get().unwrap(); - gst_debug!( - self.cat, - obj: basesrc, - "Changing ip from {:?} to {:?}", - settings.ip_address, - ip_address, - ); - settings.ip_address = ip_address; - } subclass::Property("receiver-ndi-name", ..) => { let mut settings = self.settings.lock().unwrap(); let receiver_ndi_name = value.get().unwrap(); @@ -316,10 +293,6 @@ impl ObjectImpl for NdiAudioSrc { let settings = self.settings.lock().unwrap(); Ok(settings.ndi_name.to_value()) } - subclass::Property("ip-address", ..) => { - let settings = self.settings.lock().unwrap(); - Ok(settings.ip_address.to_value()) - } subclass::Property("receiver-ndi-name", ..) => { let settings = self.settings.lock().unwrap(); Ok(settings.receiver_ndi_name.to_value()) @@ -401,18 +374,19 @@ impl BaseSrcImpl for NdiAudioSrc { *self.state.lock().unwrap() = Default::default(); let settings = self.settings.lock().unwrap().clone(); - if settings.ip_address.is_none() && settings.ndi_name.is_none() { + let ndi_name = if let Some(ref ndi_name) = settings.ndi_name { + ndi_name + } else { return Err(gst_error_msg!( gst::LibraryError::Settings, ["No IP address or NDI name given"] )); - } + }; let receiver = connect_ndi( self.cat, element, - settings.ip_address.as_ref().map(String::as_str), - settings.ndi_name.as_ref().map(String::as_str), + ndi_name, &settings.receiver_ndi_name, settings.connect_timeout, settings.bandwidth, diff --git a/src/ndisys.rs b/src/ndisys.rs index 90bff4952..ddadd43dc 100644 --- a/src/ndisys.rs +++ b/src/ndisys.rs @@ -78,7 +78,7 @@ pub struct NDIlib_find_create_t { #[derive(Debug, Copy, Clone)] pub struct NDIlib_source_t { pub p_ndi_name: *const ::std::os::raw::c_char, - pub p_ip_address: *const ::std::os::raw::c_char, + pub p_url_address: *const ::std::os::raw::c_char, } #[repr(i32)] @@ -107,21 +107,21 @@ pub enum NDIlib_recv_color_format_e { NDIlib_recv_color_format_RGBX_RGBA = 2, NDIlib_recv_color_format_UYVY_RGBA = 3, NDIlib_recv_color_format_fastest = 100, + NDIlib_recv_color_format_best = 101, } -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum NDIlib_FourCC_type_e { - NDIlib_FourCC_type_UYVY = 0x59_56_59_55, - NDIlib_FourCC_type_YV12 = 0x32_31_56_59, - NDIlib_FourCC_type_NV12 = 0x32_31_56_4e, - NDIlib_FourCC_type_I420 = 0x30_32_34_49, - NDIlib_FourCC_type_BGRA = 0x41_52_47_42, - NDIlib_FourCC_type_BGRX = 0x58_52_47_42, - NDIlib_FourCC_type_RGBA = 0x41_42_47_52, - NDIlib_FourCC_type_RGBX = 0x58_42_47_52, - NDIlib_FourCC_type_UYVA = 0x41_56_56_55, -} +pub type NDIlib_FourCC_video_type_e = u32; +pub const NDIlib_FourCC_video_type_UYVY: NDIlib_FourCC_video_type_e = 0x59_56_59_55; +pub const NDIlib_FourCC_video_type_UYVA: NDIlib_FourCC_video_type_e = 0x41_56_56_55; +pub const NDIlib_FourCC_video_type_P216: NDIlib_FourCC_video_type_e = 0x36_31_32_50; +pub const NDIlib_FourCC_video_type_PA16: NDIlib_FourCC_video_type_e = 0x36_31_41_50; +pub const NDIlib_FourCC_video_type_YV12: NDIlib_FourCC_video_type_e = 0x32_31_56_59; +pub const NDIlib_FourCC_video_type_I420: NDIlib_FourCC_video_type_e = 0x30_32_34_49; +pub const NDIlib_FourCC_video_type_NV12: NDIlib_FourCC_video_type_e = 0x32_31_56_4e; +pub const NDIlib_FourCC_video_type_BGRA: NDIlib_FourCC_video_type_e = 0x41_52_47_42; +pub const NDIlib_FourCC_video_type_BGRX: NDIlib_FourCC_video_type_e = 0x58_52_47_42; +pub const NDIlib_FourCC_video_type_RGBA: NDIlib_FourCC_video_type_e = 0x41_42_47_52; +pub const NDIlib_FourCC_video_type_RGBX: NDIlib_FourCC_video_type_e = 0x58_42_47_52; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -133,7 +133,6 @@ pub enum NDIlib_frame_format_type_e { } pub const NDIlib_send_timecode_synthesize: i64 = ::std::i64::MAX; -pub const NDIlib_send_timecode_empty: i64 = 0; pub const NDIlib_recv_timestamp_undefined: i64 = ::std::i64::MAX; #[repr(C)] @@ -143,7 +142,7 @@ pub struct NDIlib_recv_create_v3_t { pub color_format: NDIlib_recv_color_format_e, pub bandwidth: NDIlib_recv_bandwidth_e, pub allow_video_fields: bool, - pub p_ndi_name: *const ::std::os::raw::c_char, + pub p_ndi_recv_name: *const ::std::os::raw::c_char, } pub type NDIlib_recv_instance_t = *mut ::std::os::raw::c_void; @@ -176,14 +175,14 @@ pub struct NDIlib_metadata_frame_t { pub struct NDIlib_video_frame_v2_t { pub xres: ::std::os::raw::c_int, pub yres: ::std::os::raw::c_int, - pub FourCC: NDIlib_FourCC_type_e, + pub FourCC: NDIlib_FourCC_video_type_e, pub frame_rate_N: ::std::os::raw::c_int, pub frame_rate_D: ::std::os::raw::c_int, pub picture_aspect_ratio: ::std::os::raw::c_float, pub frame_format_type: NDIlib_frame_format_type_e, pub timecode: i64, pub p_data: *const ::std::os::raw::c_char, - pub line_stride_in_bytes: ::std::os::raw::c_int, + pub line_stride_or_data_size_in_bytes: ::std::os::raw::c_int, pub p_metadata: *const ::std::os::raw::c_char, pub timestamp: i64, } @@ -221,5 +220,5 @@ pub struct NDIlib_audio_frame_interleaved_16s_t { pub no_samples: ::std::os::raw::c_int, pub timecode: i64, pub reference_level: ::std::os::raw::c_int, - pub p_data: *mut ::std::os::raw::c_short, + pub p_data: *mut i16, } diff --git a/src/ndivideosrc.rs b/src/ndivideosrc.rs index 790385bc8..359ede6f3 100644 --- a/src/ndivideosrc.rs +++ b/src/ndivideosrc.rs @@ -25,7 +25,6 @@ use crate::DEFAULT_RECEIVER_NDI_NAME; #[derive(Debug, Clone)] struct Settings { ndi_name: Option, - ip_address: Option, connect_timeout: u32, timeout: u32, receiver_ndi_name: String, @@ -37,7 +36,6 @@ impl Default for Settings { fn default() -> Self { Settings { ndi_name: None, - ip_address: None, receiver_ndi_name: DEFAULT_RECEIVER_NDI_NAME.clone(), connect_timeout: 10000, timeout: 5000, @@ -47,7 +45,7 @@ impl Default for Settings { } } -static PROPERTIES: [subclass::Property; 7] = [ +static PROPERTIES: [subclass::Property; 6] = [ subclass::Property("ndi-name", |name| { glib::ParamSpec::string( name, @@ -57,15 +55,6 @@ static PROPERTIES: [subclass::Property; 7] = [ glib::ParamFlags::READWRITE, ) }), - subclass::Property("ip-address", |name| { - glib::ParamSpec::string( - name, - "IP Address", - "IP address and port of the sender, e.g. 127.0.0.1:5961", - None, - glib::ParamFlags::READWRITE, - ) - }), subclass::Property("receiver-ndi-name", |name| { glib::ParamSpec::string( name, @@ -262,18 +251,6 @@ impl ObjectImpl for NdiVideoSrc { ); settings.ndi_name = ndi_name; } - subclass::Property("ip-address", ..) => { - let mut settings = self.settings.lock().unwrap(); - let ip_address = value.get().unwrap(); - gst_debug!( - self.cat, - obj: basesrc, - "Changing ip from {:?} to {:?}", - settings.ip_address, - ip_address, - ); - settings.ip_address = ip_address; - } subclass::Property("receiver-ndi-name", ..) => { let mut settings = self.settings.lock().unwrap(); let receiver_ndi_name = value.get().unwrap(); @@ -351,10 +328,6 @@ impl ObjectImpl for NdiVideoSrc { let settings = self.settings.lock().unwrap(); Ok(settings.ndi_name.to_value()) } - subclass::Property("ip-address", ..) => { - let settings = self.settings.lock().unwrap(); - Ok(settings.ip_address.to_value()) - } subclass::Property("receiver-ndi-name", ..) => { let settings = self.settings.lock().unwrap(); Ok(settings.receiver_ndi_name.to_value()) @@ -436,18 +409,19 @@ impl BaseSrcImpl for NdiVideoSrc { *self.state.lock().unwrap() = Default::default(); let settings = self.settings.lock().unwrap().clone(); - if settings.ip_address.is_none() && settings.ndi_name.is_none() { + let ndi_name = if let Some(ref ndi_name) = settings.ndi_name { + ndi_name + } else { return Err(gst_error_msg!( gst::LibraryError::Settings, ["No IP address or NDI name given"] )); - } + }; let receiver = connect_ndi( self.cat, element, - settings.ip_address.as_ref().map(String::as_str), - settings.ndi_name.as_ref().map(String::as_str), + ndi_name, &settings.receiver_ndi_name, settings.connect_timeout, settings.bandwidth, diff --git a/src/receiver.rs b/src/receiver.rs index 7b9b0a5c9..3b8dab30e 100644 --- a/src/receiver.rs +++ b/src/receiver.rs @@ -18,8 +18,7 @@ use super::*; enum ReceiverInfo { Connecting { id: usize, - ndi_name: Option, - ip_address: Option, + ndi_name: String, video: Option>>, audio: Option>>, observations: Observations, @@ -27,7 +26,6 @@ enum ReceiverInfo { Connected { id: usize, ndi_name: String, - ip_address: String, recv: RecvInstance, video: Option>>, audio: Option>>, @@ -557,8 +555,7 @@ impl Drop for ReceiverInner { pub fn connect_ndi( cat: gst::DebugCategory, element: &gst_base::BaseSrc, - ip_address: Option<&str>, - ndi_name: Option<&str>, + ndi_name: &str, receiver_ndi_name: &str, connect_timeout: u32, bandwidth: NDIlib_recv_bandwidth_e, @@ -570,45 +567,33 @@ where { gst_debug!(cat, obj: element, "Starting NDI connection..."); - let ip_address = ip_address.map(str::to_lowercase); - let mut receivers = HASHMAP_RECEIVERS.lock().unwrap(); // Check if we already have a receiver for this very stream for val in receivers.values_mut() { - let (val_audio, val_video, val_ip_address, val_ndi_name) = match val { + let (val_audio, val_video, val_ndi_name) = match val { ReceiverInfo::Connecting { ref mut audio, ref mut video, - ref ip_address, ref ndi_name, .. - } => ( - audio, - video, - ip_address.as_ref(), - ndi_name.as_ref().map(String::as_ref), - ), + } => (audio, video, ndi_name.as_str()), ReceiverInfo::Connected { ref mut audio, ref mut video, - ref ip_address, ref ndi_name, .. - } => (audio, video, Some(ip_address), Some(ndi_name.as_str())), + } => (audio, video, ndi_name.as_str()), }; - if (val_ip_address.is_some() && val_ip_address == ip_address.as_ref()) - || (val_ip_address.is_none() && val_ndi_name == ndi_name) - { + if val_ndi_name == ndi_name { if (val_video.is_some() || !T::IS_VIDEO) && (val_audio.is_some() || T::IS_VIDEO) { gst_element_error!( element, gst::ResourceError::OpenRead, [ - "Source with ndi-name '{:?}' and ip-address '{:?}' already in use for {}", + "Source with ndi-name '{}' already in use for {}", val_ndi_name, - val_ip_address, if T::IS_VIDEO { "video" } else { "audio" } ] ); @@ -624,8 +609,7 @@ where let id_receiver = ID_RECEIVER.fetch_add(1, Ordering::SeqCst); let mut info = ReceiverInfo::Connecting { id: id_receiver, - ndi_name: ndi_name.map(String::from), - ip_address, + ndi_name: String::from(ndi_name), video: None, audio: None, observations: Observations::new(), @@ -746,9 +730,9 @@ fn connect_ndi_async( gst_debug!( cat, obj: element, - "Found source '{}' with IP {}", + "Found source '{}' with URL {}", source.ndi_name(), - source.ip_address(), + source.url_address(), ); } @@ -758,24 +742,20 @@ fn connect_ndi_async( Some(val) => val, }; - let (ndi_name, ip_address) = match info { + let ndi_name = match info { ReceiverInfo::Connecting { ref ndi_name, - ref ip_address, ref audio, ref video, .. } => { assert!(audio.is_some() || video.is_some()); - (ndi_name, ip_address) + ndi_name } ReceiverInfo::Connected { .. } => unreachable!(), }; - let source = sources.iter().find(|s| { - Some(s.ndi_name()) == ndi_name.as_ref().map(String::as_str) - || Some(&s.ip_address().to_lowercase()) == ip_address.as_ref() - }); + let source = sources.iter().find(|s| s.ndi_name() == ndi_name.as_str()); if let Some(source) = source { break source.to_owned(); @@ -793,9 +773,9 @@ fn connect_ndi_async( gst_debug!( cat, obj: element, - "Connecting to NDI source with ndi-name '{}' and ip-address '{}'", + "Connecting to NDI source with ndi-name '{}' and URL {}", source.ndi_name(), - source.ip_address(), + source.url_address(), ); // FIXME: Ideally we would use NDIlib_recv_color_format_fastest here but that seems to be @@ -841,7 +821,6 @@ fn connect_ndi_async( *info = ReceiverInfo::Connected { id: id_receiver, ndi_name: source.ndi_name().to_owned(), - ip_address: source.ip_address().to_lowercase(), recv: recv.clone(), video: video.clone(), audio: audio.clone(), @@ -1252,15 +1231,26 @@ impl Receiver { ) -> Result { // YV12 and I420 are swapped in the NDI SDK compared to GStreamer let format = match video_frame.fourcc() { - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_UYVY => gst_video::VideoFormat::Uyvy, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_YV12 => gst_video::VideoFormat::I420, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_NV12 => gst_video::VideoFormat::Nv12, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_I420 => gst_video::VideoFormat::Yv12, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_BGRA => gst_video::VideoFormat::Bgra, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_BGRX => gst_video::VideoFormat::Bgrx, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_RGBA => gst_video::VideoFormat::Rgba, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_RGBX => gst_video::VideoFormat::Rgbx, - ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_UYVA => gst_video::VideoFormat::Uyvy, + ndisys::NDIlib_FourCC_video_type_UYVY => gst_video::VideoFormat::Uyvy, + // FIXME: This drops the alpha plane! + ndisys::NDIlib_FourCC_video_type_UYVA => gst_video::VideoFormat::Uyvy, + ndisys::NDIlib_FourCC_video_type_YV12 => gst_video::VideoFormat::I420, + ndisys::NDIlib_FourCC_video_type_NV12 => gst_video::VideoFormat::Nv12, + ndisys::NDIlib_FourCC_video_type_I420 => gst_video::VideoFormat::Yv12, + ndisys::NDIlib_FourCC_video_type_BGRA => gst_video::VideoFormat::Bgra, + ndisys::NDIlib_FourCC_video_type_BGRX => gst_video::VideoFormat::Bgrx, + ndisys::NDIlib_FourCC_video_type_RGBA => gst_video::VideoFormat::Rgba, + ndisys::NDIlib_FourCC_video_type_RGBX => gst_video::VideoFormat::Rgbx, + _ => { + gst_element_error!( + element, + gst::StreamError::Format, + ["Unsupported video fourcc {:08x}", video_frame.fourcc()] + ); + + return Err(gst::FlowError::NotNegotiated); + } // TODO: NDIlib_FourCC_video_type_P216 and NDIlib_FourCC_video_type_PA16 not + // supported by GStreamer }; let par = gst::Fraction::approximate_f32(video_frame.picture_aspect_ratio()) @@ -1447,7 +1437,7 @@ impl Receiver { }; let dest_stride = vframe.plane_stride()[0] as usize; let dest = vframe.plane_data_mut(0).unwrap(); - let src_stride = video_frame.line_stride_in_bytes() as usize; + let src_stride = video_frame.line_stride_or_data_size_in_bytes() as usize; let src = video_frame.data(); for (dest, src) in dest @@ -1464,7 +1454,7 @@ impl Receiver { let line_bytes = vframe.width() as usize; let dest_stride = vframe.plane_stride()[0] as usize; let dest = vframe.plane_data_mut(0).unwrap(); - let src_stride = video_frame.line_stride_in_bytes() as usize; + let src_stride = video_frame.line_stride_or_data_size_in_bytes() as usize; let src = video_frame.data(); for (dest, src) in dest @@ -1480,7 +1470,7 @@ impl Receiver { let line_bytes = vframe.width() as usize; let dest_stride = vframe.plane_stride()[1] as usize; let dest = vframe.plane_data_mut(1).unwrap(); - let src_stride = video_frame.line_stride_in_bytes() as usize; + let src_stride = video_frame.line_stride_or_data_size_in_bytes() as usize; let src = &video_frame.data()[(video_frame.yres() as usize * src_stride)..]; for (dest, src) in dest @@ -1497,7 +1487,7 @@ impl Receiver { let line_bytes = vframe.width() as usize; let dest_stride = vframe.plane_stride()[0] as usize; let dest = vframe.plane_data_mut(0).unwrap(); - let src_stride = video_frame.line_stride_in_bytes() as usize; + let src_stride = video_frame.line_stride_or_data_size_in_bytes() as usize; let src = video_frame.data(); for (dest, src) in dest @@ -1513,8 +1503,8 @@ impl Receiver { let line_bytes = (vframe.width() as usize + 1) / 2; let dest_stride = vframe.plane_stride()[1] as usize; let dest = vframe.plane_data_mut(1).unwrap(); - let src_stride = video_frame.line_stride_in_bytes() as usize; - let src_stride1 = video_frame.line_stride_in_bytes() as usize / 2; + let src_stride = video_frame.line_stride_or_data_size_in_bytes() as usize; + let src_stride1 = video_frame.line_stride_or_data_size_in_bytes() as usize / 2; let src = &video_frame.data()[(video_frame.yres() as usize * src_stride)..]; for (dest, src) in dest @@ -1530,8 +1520,8 @@ impl Receiver { let line_bytes = (vframe.width() as usize + 1) / 2; let dest_stride = vframe.plane_stride()[2] as usize; let dest = vframe.plane_data_mut(2).unwrap(); - let src_stride = video_frame.line_stride_in_bytes() as usize; - let src_stride1 = video_frame.line_stride_in_bytes() as usize / 2; + let src_stride = video_frame.line_stride_or_data_size_in_bytes() as usize; + let src_stride1 = video_frame.line_stride_or_data_size_in_bytes() as usize / 2; let src = &video_frame.data()[(video_frame.yres() as usize * src_stride + (video_frame.yres() as usize + 1) / 2 * src_stride1)..];