diff --git a/gstreamer/src/sample.rs b/gstreamer/src/sample.rs index c443e0bbe..18ef48a1f 100644 --- a/gstreamer/src/sample.rs +++ b/gstreamer/src/sample.rs @@ -127,6 +127,75 @@ impl fmt::Debug for SampleRef { unsafe impl Sync for SampleRef {} unsafe impl Send for SampleRef {} +#[cfg(feature = "ser_de")] +pub(crate) mod serde { + use serde::de::{Deserialize, Deserializer}; + use serde::ser::{Serialize, Serializer, SerializeStruct}; + + use Buffer; + use BufferList; + use Caps; + use GenericFormattedValue; + use Sample; + use SampleRef; + use Segment; + use Structure; + + impl<'a> Serialize for SampleRef { + fn serialize(&self, serializer: S) -> Result { + let mut sample = serializer.serialize_struct("Sample", 5)?; + sample.serialize_field("buffer", &self.get_buffer())?; + sample.serialize_field("buffer_list", &self.get_buffer_list())?; + sample.serialize_field("caps", &self.get_caps())?; + sample.serialize_field("segment", &self.get_segment())?; + sample.serialize_field("info", &self.get_info())?; + sample.end() + } + } + + impl<'a> Serialize for Sample { + fn serialize(&self, serializer: S) -> Result { + self.as_ref().serialize(serializer) + } + } + + #[derive(Deserialize)] + struct SampleDe { + buffer: Option, + buffer_list: Option, + caps: Option, + segment: Option, + info: Option, + } + + impl From for Sample { + fn from(mut buf_de: SampleDe) -> Self { + if buf_de.buffer.is_some() { + Sample::new::( + buf_de.buffer.as_ref(), + buf_de.caps.as_ref(), + buf_de.segment.as_ref(), + buf_de.info.take(), + ) + } else { + Sample::with_buffer_list::( + buf_de.buffer_list.as_ref(), + buf_de.caps.as_ref(), + buf_de.segment.as_ref(), + buf_de.info.take(), + ) + } + } + } + + impl<'de> Deserialize<'de> for Sample { + fn deserialize>(deserializer: D) -> Result { + SampleDe::deserialize(deserializer) + .and_then(|sample_de| Ok(sample_de.into())) + } + } +} + #[cfg(test)] mod tests { @@ -145,4 +214,258 @@ mod tests { assert!(sample.get_info().is_some()); } + + #[cfg(feature = "ser_de")] + #[test] + fn test_serialize() { + extern crate ron; + + use Buffer; + use Caps; + use ClockTime; + use Format; + use GenericFormattedValue; + use Sample; + use Segment; + use SegmentFlags; + use Structure; + + ::init().unwrap(); + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let sample = { + let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(1.into()); + buffer.set_offset(0); + buffer.set_offset_end(4); + buffer.set_duration(4.into()); + } + + let caps = Caps::builder("sample/caps") + .field("int", &12) + .field("bool", &true) + .build(); + + let mut segment = Segment::new(); + segment.set_flags(SegmentFlags::RESET | SegmentFlags::SEGMENT); + segment.set_rate(1f64); + segment.set_applied_rate(0.9f64); + segment.set_format(Format::Time); + segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); + segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); + segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); + segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); + segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); + segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); + segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); + + let info = Structure::builder("sample.info") + .field("f3", &123i32) + .build(); + + Sample::new::( + Some(&buffer), + Some(&caps), + Some(&segment), + Some(info), + ) + }; + + let res = ron::ser::to_string_pretty(&sample, pretty_config.clone()); + assert_eq!( + Ok( + concat!( + "(", + " buffer: Some((", + " pts: Some(1),", + " dts: None,", + " duration: Some(4),", + " offset: 0,", + " offset_end: 4,", + " flags: (", + " bits: 0,", + " ),", + " buffer: \"AQIDBA==\",", + " )),", + " buffer_list: None,", + " caps: Some([", + " (\"sample/caps\", [", + " (\"int\", \"i32\", 12),", + " (\"bool\", \"bool\", true),", + " ]),", + " ]),", + " segment: Some((", + " flags: (", + " bits: 9,", + " ),", + " rate: 1,", + " applied_rate: 0.9,", + " format: Time,", + " base: 123,", + " offset: 42,", + " start: 1024,", + " stop: 2048,", + " time: 1042,", + " position: 256,", + " duration: -1,", + " )),", + " info: Some((\"sample.info\", [", + " (\"f3\", \"i32\", 123),", + " ])),", + ")" + ) + .to_owned() + ), + res + ); + + let sample = { + let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(1.into()); + buffer.set_offset(0); + buffer.set_offset_end(4); + buffer.set_duration(4.into()); + } + Sample::new::(Some(&buffer), None, None, None) + }; + + // `Sample`'s `Segment` is allocated in GStreamer 1.x, should be fixed in version 2.0 + + let res = ron::ser::to_string_pretty(&sample, pretty_config); + assert_eq!( + Ok( + concat!( + "(", + " buffer: Some((", + " pts: Some(1),", + " dts: None,", + " duration: Some(4),", + " offset: 0,", + " offset_end: 4,", + " flags: (", + " bits: 0,", + " ),", + " buffer: \"AQIDBA==\",", + " )),", + " buffer_list: None,", + " caps: None,", + " segment: Some((", + " flags: (", + " bits: 0,", + " ),", + " rate: 1,", + " applied_rate: 1,", + " format: Time,", + " base: 0,", + " offset: 0,", + " start: 0,", + " stop: -1,", + " time: 0,", + " position: 0,", + " duration: -1,", + " )),", + " info: None,", + ")" + ) + .to_owned() + ), + res + ); + } + + #[cfg(feature = "ser_de")] + #[test] + fn test_deserialize() { + extern crate ron; + + use Sample; + + ::init().unwrap(); + + let buffer_ron = r#" + ( + buffer: Some(( + pts: Some(1), + dts: None, + duration: Some(4), + offset: 0, + offset_end: 4, + flags: ( + bits: 0, + ), + buffer: "AQIDBA==", + )), + buffer_list: None, + caps: Some([ + ("sample/caps", [ + ("int", "i32", 12), + ("bool", "bool", true), + ]), + ]), + segment: Some(( + flags: ( + bits: 0, + ), + rate: 1, + applied_rate: 0.9, + format: Time, + base: 123, + offset: 42, + start: 1024, + stop: 2048, + time: 1042, + position: 256, + duration: -1, + )), + info: Some(("sample.info", [ + ("f3", "i32", 123), + ])), + )"#; + let sample: Sample = ron::de::from_str(buffer_ron).unwrap(); + let buffer = sample.get_buffer().unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_offset_end(), 4); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + assert!(sample.get_buffer_list().is_none()); + assert!(sample.get_caps().is_some()); + assert!(sample.get_segment().is_some()); + assert!(sample.get_info().is_some()); + + let buffer_ron = r#" + ( + buffer: None, + buffer_list: Some([ + ( + pts: Some(1), + dts: None, + duration: Some(4), + offset: 0, + offset_end: 4, + flags: ( + bits: 0, + ), + buffer: "AQIDBA==", + ), + ]), + caps: None, + segment: None, + info: None, + )"#; + let sample: Sample = ron::de::from_str(buffer_ron).unwrap(); + assert!(sample.get_buffer().is_none()); + assert!(sample.get_buffer_list().is_some()); + assert!(sample.get_caps().is_none()); + // Not true in GStreamer 1.x, should be fixed in version 2.0 + //assert!(sample.get_segment().is_none()); + assert!(sample.get_info().is_none()); + } } diff --git a/gstreamer/src/structure.rs b/gstreamer/src/structure.rs index b2835da05..273fc465c 100644 --- a/gstreamer/src/structure.rs +++ b/gstreamer/src/structure.rs @@ -668,7 +668,7 @@ pub(crate) mod serde { use std::fmt; use DateTime; - //use Sample; + use Sample; use value::*; use value::serde::*; diff --git a/gstreamer/src/value.rs b/gstreamer/src/value.rs index 18bffb71b..4402a8ede 100644 --- a/gstreamer/src/value.rs +++ b/gstreamer/src/value.rs @@ -874,7 +874,7 @@ pub(crate) mod serde { use std::mem; use DateTime; - //use Sample; + use Sample; use super::*; @@ -900,7 +900,7 @@ pub(crate) mod serde { pub(crate) static ref INT_RANGE_I64_OTHER_TYPE_ID: usize = get_other_type_id::>(); pub(crate) static ref LIST_OTHER_TYPE_ID: usize = get_other_type_id::(); - //pub(crate) static ref SAMPLE_OTHER_TYPE_ID: usize = get_other_type_id::(); + pub(crate) static ref SAMPLE_OTHER_TYPE_ID: usize = get_other_type_id::(); } impl<'a> Serialize for Fraction { @@ -954,8 +954,8 @@ pub(crate) mod serde { ser_value!($value, "IntRange", IntRange, $ser_closure) } else if *LIST_OTHER_TYPE_ID == type_id { ser_value!($value, LIST_TYPE_NAME, List, $ser_closure) - /*} else if *SAMPLE_OTHER_TYPE_ID == type_id { - ser_value!($value, "Sample", Sample, $ser_closure)*/ + } else if *SAMPLE_OTHER_TYPE_ID == type_id { + ser_value!($value, "Sample", Sample, $ser_closure) } else { Err( ser::Error::custom( @@ -1068,7 +1068,7 @@ pub(crate) mod serde { "FractionRange" => de_send_value!($type_name, $seq, FractionRange), "IntRange" => de_send_value!($type_name, $seq, IntRange), "IntRange" => de_send_value!($type_name, $seq, IntRange), - //"Sample" => de_send_value!($type_name, $seq, Sample), + "Sample" => de_send_value!($type_name, $seq, Sample), _ => return Err( de::Error::custom( format!(