gstreamer: Change Sample constructor to the builder pattern

Simplifies construction of Samples considerably.
This commit is contained in:
Sebastian Dröge 2019-10-22 23:32:39 +03:00
parent dc3a039a3b
commit 8dcf3fec20
4 changed files with 115 additions and 70 deletions

View file

@ -137,12 +137,7 @@ mod tests {
.unwrap() .unwrap()
.to_caps() .to_caps()
.unwrap(); .unwrap();
let sample = gst::Sample::new( let sample = gst::Sample::new().buffer(&in_buffer).caps(&in_caps).build();
Some(&in_buffer),
Some(&in_caps),
None::<&gst::Segment>,
None,
);
let out_caps = ::VideoInfo::new(::VideoFormat::Abgr, 320, 240) let out_caps = ::VideoInfo::new(::VideoFormat::Abgr, 320, 240)
.build() .build()

View file

@ -31,43 +31,89 @@ gst_define_mini_object_wrapper!(Sample, SampleRef, gst_sys::GstSample, [Debug,],
gst_sys::gst_sample_get_type() gst_sys::gst_sample_get_type()
}); });
impl Sample { #[derive(Debug, Clone)]
pub fn new<F: FormattedValue>( pub struct SampleBuilder<'a> {
buffer: Option<&Buffer>, buffer: Option<&'a Buffer>,
caps: Option<&Caps>, buffer_list: Option<&'a BufferList>,
segment: Option<&FormattedSegment<F>>, caps: Option<&'a Caps>,
segment: Option<&'a Segment>,
info: Option<Structure>, info: Option<Structure>,
) -> Self { }
assert_initialized_main_thread!();
unsafe {
let info = info.map(|i| i.into_ptr()).unwrap_or(ptr::null_mut());
from_glib_full(gst_sys::gst_sample_new( impl<'a> SampleBuilder<'a> {
buffer.to_glib_none().0, pub fn buffer(self, buffer: &'a Buffer) -> Self {
caps.to_glib_none().0, Self {
segment.to_glib_none().0, buffer: Some(buffer),
buffer_list: None,
..self
}
}
pub fn buffer_list(self, buffer_list: &'a BufferList) -> Self {
Self {
buffer: None,
buffer_list: Some(buffer_list),
..self
}
}
pub fn caps(self, caps: &'a Caps) -> Self {
Self {
caps: Some(caps),
..self
}
}
pub fn segment<F: FormattedValue>(self, segment: &'a FormattedSegment<F>) -> Self {
Self {
segment: Some(segment.upcast_ref()),
..self
}
}
pub fn info(self, info: Structure) -> Self {
Self {
info: Some(info),
..self
}
}
pub fn build(self) -> Sample {
assert_initialized_main_thread!();
unsafe {
let info = self.info.map(|i| i.into_ptr()).unwrap_or(ptr::null_mut());
let sample: Sample = from_glib_full(gst_sys::gst_sample_new(
self.buffer.to_glib_none().0,
self.caps.to_glib_none().0,
self.segment.to_glib_none().0,
mut_override(info), mut_override(info),
)) ));
}
}
pub fn with_buffer_list<F: FormattedValue>( if let Some(buffer_list) = self.buffer_list {
buffer_list: Option<&BufferList>,
caps: Option<&Caps>,
segment: Option<&FormattedSegment<F>>,
info: Option<Structure>,
) -> Self {
assert_initialized_main_thread!();
let sample = Self::new(None, caps, segment, info);
unsafe {
gst_sys::gst_sample_set_buffer_list( gst_sys::gst_sample_set_buffer_list(
sample.to_glib_none().0, sample.to_glib_none().0,
buffer_list.to_glib_none().0, buffer_list.to_glib_none().0,
); );
} }
sample sample
} }
} }
}
impl Sample {
pub fn new<'a>() -> SampleBuilder<'a> {
SampleBuilder {
buffer: None,
buffer_list: None,
caps: None,
segment: None,
info: None,
}
}
}
impl SampleRef { impl SampleRef {
pub fn get_buffer(&self) -> Option<&BufferRef> { pub fn get_buffer(&self) -> Option<&BufferRef> {
@ -182,10 +228,8 @@ impl fmt::Debug for SampleRef {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]
fn test_sample_new_with_info() { fn test_sample_new_with_info() {
use GenericFormattedValue;
use Sample; use Sample;
use Structure; use Structure;
@ -194,7 +238,7 @@ mod tests {
let info = Structure::builder("sample.info") let info = Structure::builder("sample.info")
.field("f3", &123i32) .field("f3", &123i32)
.build(); .build();
let sample = Sample::new::<GenericFormattedValue>(None, None, None, Some(info)); let sample = Sample::new().info(info).build();
assert!(sample.get_info().is_some()); assert!(sample.get_info().is_some());
} }

View file

@ -12,7 +12,6 @@ use serde::ser::{Serialize, SerializeStruct, Serializer};
use Buffer; use Buffer;
use BufferList; use BufferList;
use Caps; use Caps;
use GenericFormattedValue;
use Sample; use Sample;
use SampleRef; use SampleRef;
use Segment; use Segment;
@ -47,21 +46,29 @@ struct SampleDe {
impl From<SampleDe> for Sample { impl From<SampleDe> for Sample {
fn from(mut buf_de: SampleDe) -> Self { fn from(mut buf_de: SampleDe) -> Self {
if buf_de.buffer.is_some() { let mut builder = Sample::new();
Sample::new::<GenericFormattedValue>(
buf_de.buffer.as_ref(), if let Some(buffer) = buf_de.buffer.as_ref() {
buf_de.caps.as_ref(), builder = builder.buffer(buffer);
buf_de.segment.as_ref(),
buf_de.info.take(),
)
} else {
Sample::with_buffer_list::<GenericFormattedValue>(
buf_de.buffer_list.as_ref(),
buf_de.caps.as_ref(),
buf_de.segment.as_ref(),
buf_de.info.take(),
)
} }
if let Some(buffer_list) = buf_de.buffer_list.as_ref() {
builder = builder.buffer_list(buffer_list);
}
if let Some(caps) = buf_de.caps.as_ref() {
builder = builder.caps(caps);
}
if let Some(segment) = buf_de.segment.as_ref() {
builder = builder.segment(segment);
}
if let Some(info) = buf_de.info {
builder = builder.info(info);
}
builder.build()
} }
} }
@ -124,12 +131,12 @@ mod tests {
.field("f3", &123i32) .field("f3", &123i32)
.build(); .build();
Sample::new::<GenericFormattedValue>( Sample::new()
Some(&buffer), .buffer(&buffer)
Some(&caps), .caps(&caps)
Some(&segment), .segment(&segment)
Some(info), .info(info)
) .build()
}; };
let res = ron::ser::to_string_pretty(&sample, pretty_config.clone()); let res = ron::ser::to_string_pretty(&sample, pretty_config.clone());
@ -187,7 +194,7 @@ mod tests {
buffer.set_offset_end(4); buffer.set_offset_end(4);
buffer.set_duration(4.into()); buffer.set_duration(4.into());
} }
Sample::new::<GenericFormattedValue>(Some(&buffer), None, None, None) Sample::new().buffer(&buffer).build()
}; };
// `Sample`'s `Segment` is allocated in GStreamer 1.x, should be fixed in version 2.0 // `Sample`'s `Segment` is allocated in GStreamer 1.x, should be fixed in version 2.0
@ -354,12 +361,12 @@ mod tests {
.field("f3", &123i32) .field("f3", &123i32)
.build(); .build();
Sample::new::<GenericFormattedValue>( Sample::new()
Some(&buffer), .buffer(&buffer)
Some(&caps), .caps(&caps)
Some(&segment), .segment(&segment)
Some(info), .info(info)
) .build()
}; };
let sample_ser = ron::ser::to_string(&sample).unwrap(); let sample_ser = ron::ser::to_string(&sample).unwrap();
let sample_de: Sample = ron::de::from_str(sample_ser.as_str()).unwrap(); let sample_de: Sample = ron::de::from_str(sample_ser.as_str()).unwrap();

View file

@ -323,7 +323,6 @@ mod tests {
use tags::*; use tags::*;
use Buffer; use Buffer;
use GenericFormattedValue;
use Sample; use Sample;
use TagMergeMode; use TagMergeMode;
use TagScope; use TagScope;
@ -354,7 +353,7 @@ mod tests {
buffer.set_offset(0); buffer.set_offset(0);
buffer.set_offset_end(0); buffer.set_offset_end(0);
} }
Sample::new::<GenericFormattedValue>(Some(&buffer), None, None, None) Sample::new().buffer(&buffer).build()
}; };
tags.add::<Image>(&sample, TagMergeMode::Append); // Sample tags.add::<Image>(&sample, TagMergeMode::Append); // Sample
} }
@ -569,7 +568,7 @@ mod tests {
buffer.set_offset(0); buffer.set_offset(0);
buffer.set_offset_end(0); buffer.set_offset_end(0);
} }
Sample::new::<GenericFormattedValue>(Some(&buffer), None, None, None) Sample::new().buffer(&buffer).build()
}; };
tags.add::<Image>(&sample, TagMergeMode::Append); // Sample tags.add::<Image>(&sample, TagMergeMode::Append); // Sample
} }