diff --git a/Gir_Gst.toml b/Gir_Gst.toml index a5790f967..39b830f28 100644 --- a/Gir_Gst.toml +++ b/Gir_Gst.toml @@ -45,7 +45,6 @@ generate = [ "Gst.PadProbeType", "Gst.PadProbeReturn", "Gst.CapsIntersectMode", - "Gst.BufferFlags", "Gst.BufferCopyFlags", "Gst.SegmentFlags", "Gst.PadMode", @@ -149,6 +148,13 @@ trait = false [object.function.return] bool_return_is_error = "Failed to post message" +[[object]] +name = "Gst.BufferFlags" +status = "generate" + [[object.derive]] + name = "Serialize, Deserialize" + cfg_condition = "feature = \"ser_de\"" + [[object]] name = "Gst.Structure" status = "manual" diff --git a/gstreamer/Cargo.toml b/gstreamer/Cargo.toml index 11dab9cd2..2faa8a97a 100644 --- a/gstreamer/Cargo.toml +++ b/gstreamer/Cargo.toml @@ -25,6 +25,7 @@ lazy_static = "1.0" futures-core-preview = { version = "0.2", optional = true } muldiv = "0.2" serde = { version = "1.0", optional = true } +serde_bytes = { version = "0.10", optional = true } serde_derive = { version = "1.0", optional = true } [build-dependencies.rustdoc-stripper] @@ -32,8 +33,9 @@ version = "0.1" optional = true [dev-dependencies] -ron = "0.2" +ron = "0.3" serde_json = "1.0" +serde-pickle = "0.4" [features] v1_10 = ["gstreamer-sys/v1_10"] @@ -43,7 +45,7 @@ embed-lgpl-docs = ["rustdoc-stripper"] purge-lgpl-docs = ["rustdoc-stripper"] dox = ["gstreamer-sys/dox", "glib/dox", "futures", "ser_de"] futures = ["futures-core-preview"] -ser_de = ["num-rational/serde", "serde", "serde_derive"] +ser_de = ["num-rational/serde", "serde", "serde_bytes", "serde_derive"] default-features = [] [badges] diff --git a/gstreamer/src/auto/flags.rs b/gstreamer/src/auto/flags.rs index 584c2c7aa..6a37d7560 100644 --- a/gstreamer/src/auto/flags.rs +++ b/gstreamer/src/auto/flags.rs @@ -66,6 +66,7 @@ impl SetValue for BufferCopyFlags { } bitflags! { + #[cfg_attr(feature = "ser_de", derive(Serialize, Deserialize))] pub struct BufferFlags: u32 { const LIVE = 16; const DECODE_ONLY = 32; diff --git a/gstreamer/src/buffer.rs b/gstreamer/src/buffer.rs index fedb51deb..023a0d732 100644 --- a/gstreamer/src/buffer.rs +++ b/gstreamer/src/buffer.rs @@ -579,6 +579,79 @@ lazy_static! { *BUFFER_COPY_METADATA | ::BufferCopyFlags::MEMORY; } +#[cfg(feature = "ser_de")] +pub(crate) mod serde { + use serde::de::{Deserialize, Deserializer}; + use serde::ser::{Serialize, Serializer, SerializeStruct}; + use serde_bytes::{Bytes, ByteBuf}; + + use Buffer; + use BufferFlags; + use BufferRef; + use ClockTime; + + impl<'a> Serialize for BufferRef { + fn serialize(&self, serializer: S) -> Result { + let mut datetime = serializer.serialize_struct("Buffer", 6)?; + datetime.serialize_field("pts", &self.get_pts())?; + datetime.serialize_field("dts", &self.get_dts())?; + datetime.serialize_field("duration", &self.get_duration())?; + datetime.serialize_field("offset", &self.get_offset())?; + datetime.serialize_field("offset_end", &self.get_offset_end())?; + datetime.serialize_field("flags", &self.get_flags())?; + { + let data = self.map_readable().unwrap(); + datetime.serialize_field("buffer", &Bytes::new(data.as_slice()))?; + } + datetime.end() + } + } + + impl<'a> Serialize for Buffer { + fn serialize(&self, serializer: S) -> Result { + self.as_ref().serialize(serializer) + } + } + + #[derive(Deserialize)] + struct BufferDe { + pts: ClockTime, + dts: ClockTime, + duration: ClockTime, + offset: u64, + offset_end: u64, + flags: BufferFlags, + buffer: ByteBuf, + } + + impl From for Buffer { + fn from(mut buf_de: BufferDe) -> Self { + // Move the `ByteBuff`'s byte array into the `gst::Buffer` + // Are we really avoiding copies with that? + let drained_buffer: &mut Vec = buf_de.buffer.as_mut(); + let mut buffer = + Buffer::from_slice(drained_buffer.drain(..).collect::>()).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(buf_de.pts); + buffer.set_dts(buf_de.dts); + buffer.set_duration(buf_de.duration); + buffer.set_offset(buf_de.offset); + buffer.set_offset_end(buf_de.offset_end); + buffer.set_flags(buf_de.flags); + } + buffer + } + } + + impl<'de> Deserialize<'de> for Buffer { + fn deserialize>(deserializer: D) -> Result { + BufferDe::deserialize(deserializer) + .and_then(|buffer_de| Ok(buffer_de.into())) + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -650,4 +723,165 @@ mod tests { assert_eq!(data.as_slice(), vec![0, 2, 3, 4].as_slice()); } } + + #[cfg(feature = "ser_de")] + #[test] + fn test_serialize() { + extern crate ron; + extern crate serde_json; + extern crate serde_pickle; + + use Buffer; + use BufferFlags; + + ::init().unwrap(); + + 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(3); + buffer.set_offset_end(4); + buffer.set_duration(5.into()); + buffer.set_flags(BufferFlags::LIVE | BufferFlags::LAST); + } + + // don't use newlines + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&buffer, pretty_config); + assert_eq!( + Ok( + concat!( + "(", + " pts: Some(1),", + " dts: None,", + " duration: Some(5),", + " offset: 3,", + " offset_end: 4,", + " flags: (", + " bits: 1048592,", + " ),", + " buffer: \"AQIDBA==\",", + ")" + ) + .to_owned() + ), + res + ); + + let res = serde_json::to_string(&buffer).unwrap(); + assert_eq!( + concat!( + "{", + "\"pts\":1,", + "\"dts\":null,", + "\"duration\":5,", + "\"offset\":3,", + "\"offset_end\":4,", + "\"flags\":{\"bits\":1048592},", + "\"buffer\":[1,2,3,4]", + "}" + ) + .to_owned(), + res + ); + + let res = serde_pickle::to_vec(&buffer, true).unwrap(); + assert_eq!( + vec![ + 128, 3, 125, 40, 88, 3, 0, 0, 0, 112, 116, 115, 74, 1, 0, 0, 0, 88, 3, 0, 0, 0, 100, + 116, 115, 78, 88, 8, 0, 0, 0, 100, 117, 114, 97, 116, 105, 111, 110, 74, 5, 0, 0, 0, + 88, 6, 0, 0, 0, 111, 102, 102, 115, 101, 116, 74, 3, 0, 0, 0, 88, 10, 0, 0, 0, 111, + 102, 102, 115, 101, 116, 95, 101, 110, 100, 74, 4, 0, 0, 0, 88, 5, 0, 0, 0, 102, 108, + 97, 103, 115, 125, 40, 88, 4, 0, 0, 0, 98, 105, 116, 115, 74, 16, 0, 16, 0, 117, 88, + 6, 0, 0, 0, 98, 117, 102, 102, 101, 114, 67, + 4, 1, 2, 3, 4, 117, 46 + ], + res + ); + } + + #[cfg(feature = "ser_de")] + #[test] + fn test_deserialize() { + extern crate ron; + extern crate serde_json; + extern crate serde_pickle; + + use Buffer; + use BufferFlags; + + ::init().unwrap(); + + let buffer_ron = r#" + ( + pts: Some(1), + dts: None, + duration: Some(5), + offset: 3, + offset_end: 4, + flags: ( + bits: 1048592, + ), + buffer: "AQIDBA==", + ) + "#; + let buffer: Buffer = ron::de::from_str(buffer_ron).unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_dts(), None.into()); + assert_eq!(buffer.get_offset(), 3); + assert_eq!(buffer.get_offset_end(), 4); + assert_eq!(buffer.get_duration(), 5.into()); + assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + + let buffer_json = r#" + { + "pts":1, + "dts":null, + "duration":5, + "offset":3, + "offset_end":4, + "flags":{"bits":1048592}, + "buffer":[1,2,3,4] + } + "#; + let buffer: Buffer = serde_json::from_str(buffer_json).unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_dts(), None.into()); + assert_eq!(buffer.get_offset(), 3); + assert_eq!(buffer.get_offset_end(), 4); + assert_eq!(buffer.get_duration(), 5.into()); + assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + + let buffer_pickle: &[u8] = &[ + 128, 3, 125, 40, 88, 3, 0, 0, 0, 112, 116, 115, 74, 1, 0, 0, 0, 88, 3, 0, 0, 0, 100, + 116, 115, 78, 88, 8, 0, 0, 0, 100, 117, 114, 97, 116, 105, 111, 110, 74, 5, 0, 0, 0, + 88, 6, 0, 0, 0, 111, 102, 102, 115, 101, 116, 74, 3, 0, 0, 0, 88, 10, 0, 0, 0, 111, + 102, 102, 115, 101, 116, 95, 101, 110, 100, 74, 4, 0, 0, 0, 88, 5, 0, 0, 0, 102, 108, + 97, 103, 115, 125, 40, 88, 4, 0, 0, 0, 98, 105, 116, 115, 74, 16, 0, 16, 0, 117, 88, + 6, 0, 0, 0, 98, 117, 102, 102, 101, 114, 67, + 4, 1, 2, 3, 4, 117, 46 + ]; + let buffer: Buffer = serde_pickle::from_slice(buffer_pickle).unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_dts(), None.into()); + assert_eq!(buffer.get_offset(), 3); + assert_eq!(buffer.get_offset_end(), 4); + assert_eq!(buffer.get_duration(), 5.into()); + assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + } } diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index 4b624c287..fd342b87c 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -33,6 +33,8 @@ extern crate muldiv; #[cfg(feature = "ser_de")] extern crate serde; #[cfg(feature = "ser_de")] +extern crate serde_bytes; +#[cfg(feature = "ser_de")] #[macro_use] extern crate serde_derive;