pbutils/encoding_profile: Require passing the format caps to the builders and make construction infallible

There's no way it can fail if a format is provided and we don't pass
random pointers around.
This commit is contained in:
Sebastian Dröge 2021-10-24 18:39:55 +03:00
parent 06916b23c7
commit 984ab87c79

View file

@ -1,7 +1,5 @@
// Take a look at the license at the top of the repository in the LICENSE file. // Take a look at the license at the top of the repository in the LICENSE file.
use thiserror::Error;
use glib::prelude::*; use glib::prelude::*;
use glib::translate::*; use glib::translate::*;
@ -176,8 +174,8 @@ impl EncodingAudioProfile {
} }
#[doc(alias = "gst_encoding_audio_profile_new")] #[doc(alias = "gst_encoding_audio_profile_new")]
pub fn builder<'a>() -> EncodingAudioProfileBuilder<'a> { pub fn builder<'a>(format: &'a gst::Caps) -> EncodingAudioProfileBuilder<'a> {
EncodingAudioProfileBuilder::new() EncodingAudioProfileBuilder::new(format)
} }
} }
@ -204,8 +202,8 @@ impl EncodingVideoProfile {
} }
#[doc(alias = "gst_encoding_video_profile_new")] #[doc(alias = "gst_encoding_video_profile_new")]
pub fn builder<'a>() -> EncodingVideoProfileBuilder<'a> { pub fn builder<'a>(format: &'a gst::Caps) -> EncodingVideoProfileBuilder<'a> {
EncodingVideoProfileBuilder::new() EncodingVideoProfileBuilder::new(format)
} }
fn set_pass(&self, pass: u32) { fn set_pass(&self, pass: u32) {
@ -248,35 +246,27 @@ impl EncodingContainerProfile {
} }
#[doc(alias = "gst_encoding_container_profile_new")] #[doc(alias = "gst_encoding_container_profile_new")]
pub fn builder<'a>() -> EncodingContainerProfileBuilder<'a> { pub fn builder<'a>(format: &'a gst::Caps) -> EncodingContainerProfileBuilder<'a> {
EncodingContainerProfileBuilder::new() EncodingContainerProfileBuilder::new(format)
} }
fn add_profile<P: IsA<EncodingProfile>>( fn add_profile<P: IsA<EncodingProfile>>(&self, profile: &P) {
&self,
profile: &P,
) -> Result<(), glib::error::BoolError> {
unsafe { unsafe {
glib::result_from_gboolean!( let res = ffi::gst_encoding_container_profile_add_profile(
ffi::gst_encoding_container_profile_add_profile( self.to_glib_none().0,
self.to_glib_none().0, profile.as_ref().to_glib_full(),
profile.as_ref().to_glib_full(), );
), // Can't possibly fail unless we pass random pointers
"Failed to add profile", assert_ne!(res, glib::ffi::GFALSE);
)
} }
} }
} }
#[derive(Debug, Clone, Error)]
#[error("failed to build encoding profile")]
pub struct EncodingProfileBuilderError(());
#[derive(Debug)] #[derive(Debug)]
struct EncodingProfileBuilderCommonData<'a> { struct EncodingProfileBuilderCommonData<'a> {
format: &'a gst::Caps,
name: Option<&'a str>, name: Option<&'a str>,
description: Option<&'a str>, description: Option<&'a str>,
format: Option<&'a gst::Caps>,
preset: Option<&'a str>, preset: Option<&'a str>,
preset_name: Option<&'a str>, preset_name: Option<&'a str>,
presence: u32, presence: u32,
@ -287,11 +277,11 @@ struct EncodingProfileBuilderCommonData<'a> {
} }
impl<'a> EncodingProfileBuilderCommonData<'a> { impl<'a> EncodingProfileBuilderCommonData<'a> {
fn new() -> EncodingProfileBuilderCommonData<'a> { fn new(format: &'a gst::Caps) -> EncodingProfileBuilderCommonData<'a> {
EncodingProfileBuilderCommonData { EncodingProfileBuilderCommonData {
name: None, name: None,
description: None, description: None,
format: None, format,
preset: None, preset: None,
preset_name: None, preset_name: None,
presence: 0, presence: 0,
@ -308,8 +298,6 @@ pub trait EncodingProfileBuilder<'a>: Sized {
fn name(self, name: &'a str) -> Self; fn name(self, name: &'a str) -> Self;
#[doc(alias = "gst_encoding_profile_set_description")] #[doc(alias = "gst_encoding_profile_set_description")]
fn description(self, description: &'a str) -> Self; fn description(self, description: &'a str) -> Self;
#[doc(alias = "gst_encoding_profile_set_format")]
fn format(self, format: &'a gst::Caps) -> Self;
#[doc(alias = "gst_encoding_profile_set_preset")] #[doc(alias = "gst_encoding_profile_set_preset")]
fn preset(self, preset: &'a str) -> Self; fn preset(self, preset: &'a str) -> Self;
#[doc(alias = "gst_encoding_profile_set_preset_name")] #[doc(alias = "gst_encoding_profile_set_preset_name")]
@ -327,12 +315,6 @@ pub trait EncodingProfileBuilder<'a>: Sized {
macro_rules! declare_encoding_profile_builder_common( macro_rules! declare_encoding_profile_builder_common(
($name:ident) => { ($name:ident) => {
impl<'a> Default for $name<'a> {
fn default() -> Self {
Self::new()
}
}
impl<'a> EncodingProfileBuilder<'a> for $name<'a> { impl<'a> EncodingProfileBuilder<'a> for $name<'a> {
fn name(mut self, name: &'a str) -> $name<'a> { fn name(mut self, name: &'a str) -> $name<'a> {
self.base.name = Some(name); self.base.name = Some(name);
@ -344,11 +326,6 @@ macro_rules! declare_encoding_profile_builder_common(
self self
} }
fn format(mut self, format: &'a gst::Caps) -> $name<'a> {
self.base.format = Some(format);
self
}
fn preset(mut self, preset: &'a str) -> $name<'a> { fn preset(mut self, preset: &'a str) -> $name<'a> {
self.base.preset = Some(preset); self.base.preset = Some(preset);
self self
@ -410,9 +387,9 @@ pub struct EncodingAudioProfileBuilder<'a> {
declare_encoding_profile_builder_common!(EncodingAudioProfileBuilder); declare_encoding_profile_builder_common!(EncodingAudioProfileBuilder);
impl<'a> EncodingAudioProfileBuilder<'a> { impl<'a> EncodingAudioProfileBuilder<'a> {
fn new() -> Self { fn new(format: &'a gst::Caps) -> Self {
EncodingAudioProfileBuilder { EncodingAudioProfileBuilder {
base: EncodingProfileBuilderCommonData::new(), base: EncodingProfileBuilderCommonData::new(format),
restriction: None, restriction: None,
} }
} }
@ -423,20 +400,17 @@ impl<'a> EncodingAudioProfileBuilder<'a> {
self self
} }
pub fn build(self) -> Result<EncodingAudioProfile, EncodingProfileBuilderError> { pub fn build(self) -> EncodingAudioProfile {
if self.base.format.is_none() {
return Err(EncodingProfileBuilderError(()));
}
let profile = EncodingAudioProfile::new( let profile = EncodingAudioProfile::new(
self.base.format.unwrap(), self.base.format,
self.base.preset, self.base.preset,
self.restriction, self.restriction,
self.base.presence, self.base.presence,
); );
set_common_fields(&profile, &self.base); set_common_fields(&profile, &self.base);
Ok(profile)
profile
} }
} }
@ -451,9 +425,9 @@ pub struct EncodingVideoProfileBuilder<'a> {
declare_encoding_profile_builder_common!(EncodingVideoProfileBuilder); declare_encoding_profile_builder_common!(EncodingVideoProfileBuilder);
impl<'a> EncodingVideoProfileBuilder<'a> { impl<'a> EncodingVideoProfileBuilder<'a> {
fn new() -> Self { fn new(format: &'a gst::Caps) -> Self {
EncodingVideoProfileBuilder { EncodingVideoProfileBuilder {
base: EncodingProfileBuilderCommonData::new(), base: EncodingProfileBuilderCommonData::new(format),
restriction: None, restriction: None,
pass: 0, pass: 0,
variable_framerate: false, variable_framerate: false,
@ -478,13 +452,9 @@ impl<'a> EncodingVideoProfileBuilder<'a> {
self self
} }
pub fn build(self) -> Result<EncodingVideoProfile, EncodingProfileBuilderError> { pub fn build(self) -> EncodingVideoProfile {
if self.base.format.is_none() {
return Err(EncodingProfileBuilderError(()));
}
let video_profile = EncodingVideoProfile::new( let video_profile = EncodingVideoProfile::new(
self.base.format.unwrap(), self.base.format,
self.base.preset, self.base.preset,
self.restriction, self.restriction,
self.base.presence, self.base.presence,
@ -494,7 +464,8 @@ impl<'a> EncodingVideoProfileBuilder<'a> {
video_profile.set_variableframerate(self.variable_framerate); video_profile.set_variableframerate(self.variable_framerate);
set_common_fields(&video_profile, &self.base); set_common_fields(&video_profile, &self.base);
Ok(video_profile)
video_profile
} }
} }
@ -507,33 +478,28 @@ pub struct EncodingContainerProfileBuilder<'a> {
declare_encoding_profile_builder_common!(EncodingContainerProfileBuilder); declare_encoding_profile_builder_common!(EncodingContainerProfileBuilder);
impl<'a> EncodingContainerProfileBuilder<'a> { impl<'a> EncodingContainerProfileBuilder<'a> {
fn new() -> Self { fn new(format: &'a gst::Caps) -> Self {
EncodingContainerProfileBuilder { EncodingContainerProfileBuilder {
base: EncodingProfileBuilderCommonData::new(), base: EncodingProfileBuilderCommonData::new(format),
profiles: Vec::new(), profiles: Vec::new(),
} }
} }
pub fn build(self) -> Result<EncodingContainerProfile, EncodingProfileBuilderError> { pub fn build(self) -> EncodingContainerProfile {
if self.base.format.is_none() {
return Err(EncodingProfileBuilderError(()));
}
let container_profile = EncodingContainerProfile::new( let container_profile = EncodingContainerProfile::new(
self.base.name, self.base.name,
self.base.description, self.base.description,
self.base.format.unwrap(), self.base.format,
self.base.preset, self.base.preset,
); );
for profile in self.profiles { for profile in self.profiles {
container_profile container_profile.add_profile(&profile);
.add_profile(&profile)
.map_err(|_error| EncodingProfileBuilderError(()))?;
} }
set_common_fields(&container_profile, &self.base); set_common_fields(&container_profile, &self.base);
Ok(container_profile)
container_profile
} }
#[doc(alias = "gst_encoding_container_profile_add_profile")] #[doc(alias = "gst_encoding_container_profile_add_profile")]
@ -576,18 +542,16 @@ mod tests {
let restriction = gst::Caps::new_simple("audio/x-raw", &[("format", &"S32LE")]); let restriction = gst::Caps::new_simple("audio/x-raw", &[("format", &"S32LE")]);
let audio_profile = EncodingAudioProfile::builder() let audio_profile = EncodingAudioProfile::builder(&caps)
.name(AUDIO_PROFILE_NAME) .name(AUDIO_PROFILE_NAME)
.description(AUDIO_PROFILE_DESCRIPTION) .description(AUDIO_PROFILE_DESCRIPTION)
.format(&caps)
.preset(PRESET) .preset(PRESET)
.preset_name(PRESET_NAME) .preset_name(PRESET_NAME)
.restriction(&restriction) .restriction(&restriction)
.presence(PRESENCE) .presence(PRESENCE)
.allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT) .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT)
.enabled(ENABLED) .enabled(ENABLED)
.build() .build();
.unwrap();
assert_eq!(audio_profile.name().unwrap(), AUDIO_PROFILE_NAME); assert_eq!(audio_profile.name().unwrap(), AUDIO_PROFILE_NAME);
assert_eq!( assert_eq!(
@ -615,10 +579,9 @@ mod tests {
let restriction = gst::Caps::new_simple("video/x-raw", &[("format", &"RGBA")]); let restriction = gst::Caps::new_simple("video/x-raw", &[("format", &"RGBA")]);
let video_profile = EncodingVideoProfile::builder() let video_profile = EncodingVideoProfile::builder(&caps)
.name(VIDEO_PROFILE_NAME) .name(VIDEO_PROFILE_NAME)
.description(VIDEO_PROFILE_DESCRIPTION) .description(VIDEO_PROFILE_DESCRIPTION)
.format(&caps)
.preset(PRESET) .preset(PRESET)
.preset_name(PRESET_NAME) .preset_name(PRESET_NAME)
.restriction(&restriction) .restriction(&restriction)
@ -627,8 +590,7 @@ mod tests {
.enabled(ENABLED) .enabled(ENABLED)
.pass(PASS) .pass(PASS)
.variable_framerate(VARIABLE_FRAMERATE) .variable_framerate(VARIABLE_FRAMERATE)
.build() .build();
.unwrap();
assert_eq!(video_profile.name().unwrap(), VIDEO_PROFILE_NAME); assert_eq!(video_profile.name().unwrap(), VIDEO_PROFILE_NAME);
assert_eq!( assert_eq!(
@ -661,23 +623,18 @@ mod tests {
let video_caps = gst::Caps::new_simple("video/x-raw", &[]); let video_caps = gst::Caps::new_simple("video/x-raw", &[]);
let audio_caps = gst::Caps::new_simple("audio/x-raw", &[]); let audio_caps = gst::Caps::new_simple("audio/x-raw", &[]);
let video_profile = EncodingVideoProfile::builder() let video_profile = EncodingVideoProfile::builder(&video_caps)
.name(VIDEO_PROFILE_NAME) .name(VIDEO_PROFILE_NAME)
.description(VIDEO_PROFILE_DESCRIPTION) .description(VIDEO_PROFILE_DESCRIPTION)
.format(&video_caps) .build();
.build() let audio_profile = EncodingAudioProfile::builder(&audio_caps)
.unwrap();
let audio_profile = EncodingAudioProfile::builder()
.name(AUDIO_PROFILE_NAME) .name(AUDIO_PROFILE_NAME)
.description(AUDIO_PROFILE_DESCRIPTION) .description(AUDIO_PROFILE_DESCRIPTION)
.format(&audio_caps) .build();
.build()
.unwrap();
let profile = EncodingContainerProfile::builder() let profile = EncodingContainerProfile::builder(&container_caps)
.name(CONTAINER_PROFILE_NAME) .name(CONTAINER_PROFILE_NAME)
.description(CONTAINER_PROFILE_DESCRIPTION) .description(CONTAINER_PROFILE_DESCRIPTION)
.format(&container_caps)
.preset(PRESET) .preset(PRESET)
.preset_name(PRESET_NAME) .preset_name(PRESET_NAME)
.presence(PRESENCE) .presence(PRESENCE)
@ -685,8 +642,7 @@ mod tests {
.enabled(ENABLED) .enabled(ENABLED)
.add_profile(&audio_profile) .add_profile(&audio_profile)
.add_profile(&video_profile) .add_profile(&video_profile)
.build() .build();
.unwrap();
assert_eq!(profile.name().unwrap(), CONTAINER_PROFILE_NAME); assert_eq!(profile.name().unwrap(), CONTAINER_PROFILE_NAME);
assert_eq!( assert_eq!(