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()
.to_caps()
.unwrap();
let sample = gst::Sample::new(
Some(&in_buffer),
Some(&in_caps),
None::<&gst::Segment>,
None,
);
let sample = gst::Sample::new().buffer(&in_buffer).caps(&in_caps).build();
let out_caps = ::VideoInfo::new(::VideoFormat::Abgr, 320, 240)
.build()

View file

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

View file

@ -12,7 +12,6 @@ use serde::ser::{Serialize, SerializeStruct, Serializer};
use Buffer;
use BufferList;
use Caps;
use GenericFormattedValue;
use Sample;
use SampleRef;
use Segment;
@ -47,21 +46,29 @@ struct SampleDe {
impl From<SampleDe> for Sample {
fn from(mut buf_de: SampleDe) -> Self {
if buf_de.buffer.is_some() {
Sample::new::<GenericFormattedValue>(
buf_de.buffer.as_ref(),
buf_de.caps.as_ref(),
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(),
)
let mut builder = Sample::new();
if let Some(buffer) = buf_de.buffer.as_ref() {
builder = builder.buffer(buffer);
}
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)
.build();
Sample::new::<GenericFormattedValue>(
Some(&buffer),
Some(&caps),
Some(&segment),
Some(info),
)
Sample::new()
.buffer(&buffer)
.caps(&caps)
.segment(&segment)
.info(info)
.build()
};
let res = ron::ser::to_string_pretty(&sample, pretty_config.clone());
@ -187,7 +194,7 @@ mod tests {
buffer.set_offset_end(4);
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
@ -354,12 +361,12 @@ mod tests {
.field("f3", &123i32)
.build();
Sample::new::<GenericFormattedValue>(
Some(&buffer),
Some(&caps),
Some(&segment),
Some(info),
)
Sample::new()
.buffer(&buffer)
.caps(&caps)
.segment(&segment)
.info(info)
.build()
};
let sample_ser = ron::ser::to_string(&sample).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 Buffer;
use GenericFormattedValue;
use Sample;
use TagMergeMode;
use TagScope;
@ -354,7 +353,7 @@ mod tests {
buffer.set_offset(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
}
@ -569,7 +568,7 @@ mod tests {
buffer.set_offset(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
}