From 15da7bca0eb18af6291f96c50388381a6f0bb26f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 13 May 2018 11:31:10 -0700 Subject: [PATCH] EncodingProfile: remove setters and constructors, use builders Provide builders for the EncodingProfile so that the created objects are imutable and can have the Send and Sync traits --- Gir_GstPbutils.toml | 31 +- examples/src/bin/encodebin.rs | 1 + .../src/auto/encoding_audio_profile.rs | 18 +- .../src/auto/encoding_container_profile.rs | 29 +- .../src/auto/encoding_profile.rs | 87 +-- gstreamer-pbutils/src/auto/encoding_target.rs | 4 +- .../src/auto/encoding_video_profile.rs | 28 +- .../src/encoding_audio_profile.rs | 84 --- .../src/encoding_container_profile.rs | 99 --- gstreamer-pbutils/src/encoding_profile.rs | 574 ++++++++++++++++++ .../src/encoding_video_profile.rs | 105 ---- gstreamer-pbutils/src/lib.rs | 14 +- 12 files changed, 618 insertions(+), 456 deletions(-) delete mode 100644 gstreamer-pbutils/src/encoding_audio_profile.rs delete mode 100644 gstreamer-pbutils/src/encoding_container_profile.rs create mode 100644 gstreamer-pbutils/src/encoding_profile.rs delete mode 100644 gstreamer-pbutils/src/encoding_video_profile.rs diff --git a/Gir_GstPbutils.toml b/Gir_GstPbutils.toml index 3b6bcba7c..c30589af3 100644 --- a/Gir_GstPbutils.toml +++ b/Gir_GstPbutils.toml @@ -149,6 +149,14 @@ status = "generate" name = "is_equal" ignore = true + # Ignore all setters, making it imutable. A builder will be provided. + [[object.function]] + name = "new" + ignore = true + [[object.function]] + pattern = "set_.*" + ignore = true + [[object.function]] name = "copy" [object.function.return] @@ -168,10 +176,14 @@ status = "generate" name = "GstPbutils.EncodingContainerProfile" status = "generate" + # Make it imutable, only able to be constructed for a builder + [[object.function]] + name = "new" + ignore = true + [[object.function]] name = "add_profile" - [object.function.return] - bool_return_is_error = "Failed to add profile" + ignore = true [[object]] name = "GstPbutils.EncodingTarget" @@ -199,8 +211,23 @@ status = "generate" name = "GstPbutils.EncodingAudioProfile" status = "generate" trait = false + # Ignore all setters, making it imutable. A builder will be provided. + [[object.function]] + name = "new" + ignore = true + [[object.function]] + pattern = "set_.*" + ignore = true [[object]] name = "GstPbutils.EncodingVideoProfile" status = "generate" trait = false + # Ignore all setters, making it imutable. A builder will be provided. + [[object.function]] + name = "new" + ignore = true + [[object.function]] + pattern = "set_.*" + ignore = true + diff --git a/examples/src/bin/encodebin.rs b/examples/src/bin/encodebin.rs index 7c88ba828..e106694a4 100644 --- a/examples/src/bin/encodebin.rs +++ b/examples/src/bin/encodebin.rs @@ -3,6 +3,7 @@ extern crate gstreamer as gst; use gst::prelude::*; extern crate gstreamer_pbutils as pbutils; +use pbutils::EncodingProfileBuilder; extern crate glib; diff --git a/gstreamer-pbutils/src/auto/encoding_audio_profile.rs b/gstreamer-pbutils/src/auto/encoding_audio_profile.rs index ed244aeba..4d441b59e 100644 --- a/gstreamer-pbutils/src/auto/encoding_audio_profile.rs +++ b/gstreamer-pbutils/src/auto/encoding_audio_profile.rs @@ -1,5 +1,5 @@ -// This file was generated by gir (https://github.com/gtk-rs/gir @ fe7a6ff+) -// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT use EncodingProfile; @@ -7,7 +7,6 @@ use ffi; use glib::translate::*; use glib_ffi; use gobject_ffi; -use gst; use std::mem; use std::ptr; @@ -19,18 +18,7 @@ glib_wrapper! { } } -impl EncodingAudioProfile { - pub fn new<'a, 'b, P: Into>, Q: Into>>(format: &gst::Caps, preset: P, restriction: Q, presence: u32) -> EncodingAudioProfile { - assert_initialized_main_thread!(); - let preset = preset.into(); - let preset = preset.to_glib_none(); - let restriction = restriction.into(); - let restriction = restriction.to_glib_none(); - unsafe { - from_glib_full(ffi::gst_encoding_audio_profile_new(format.to_glib_none().0, preset.0, restriction.0, presence)) - } - } -} +impl EncodingAudioProfile {} unsafe impl Send for EncodingAudioProfile {} unsafe impl Sync for EncodingAudioProfile {} diff --git a/gstreamer-pbutils/src/auto/encoding_container_profile.rs b/gstreamer-pbutils/src/auto/encoding_container_profile.rs index 506067a8e..8b39d6481 100644 --- a/gstreamer-pbutils/src/auto/encoding_container_profile.rs +++ b/gstreamer-pbutils/src/auto/encoding_container_profile.rs @@ -1,15 +1,13 @@ -// This file was generated by gir (https://github.com/gtk-rs/gir @ fe7a6ff+) -// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT use EncodingProfile; use ffi; -use glib; use glib::object::IsA; use glib::translate::*; use glib_ffi; use gobject_ffi; -use gst; use std::mem; use std::ptr; @@ -21,39 +19,16 @@ glib_wrapper! { } } -impl EncodingContainerProfile { - pub fn new<'a, 'b, 'c, P: Into>, Q: Into>, R: Into>>(name: P, description: Q, format: &gst::Caps, preset: R) -> EncodingContainerProfile { - assert_initialized_main_thread!(); - let name = name.into(); - let name = name.to_glib_none(); - let description = description.into(); - let description = description.to_glib_none(); - let preset = preset.into(); - let preset = preset.to_glib_none(); - unsafe { - from_glib_full(ffi::gst_encoding_container_profile_new(name.0, description.0, format.to_glib_none().0, preset.0)) - } - } -} - unsafe impl Send for EncodingContainerProfile {} unsafe impl Sync for EncodingContainerProfile {} pub trait EncodingContainerProfileExt { - fn add_profile>(&self, profile: &P) -> Result<(), glib::error::BoolError>; - fn contains_profile>(&self, profile: &P) -> bool; fn get_profiles(&self) -> Vec; } impl> EncodingContainerProfileExt for O { - fn add_profile>(&self, profile: &P) -> Result<(), glib::error::BoolError> { - unsafe { - glib::error::BoolError::from_glib(ffi::gst_encoding_container_profile_add_profile(self.to_glib_none().0, profile.to_glib_full()), "Failed to add profile") - } - } - fn contains_profile>(&self, profile: &P) -> bool { unsafe { from_glib(ffi::gst_encoding_container_profile_contains_profile(self.to_glib_none().0, profile.to_glib_none().0)) diff --git a/gstreamer-pbutils/src/auto/encoding_profile.rs b/gstreamer-pbutils/src/auto/encoding_profile.rs index 1d9eae7ae..25d0dba5a 100644 --- a/gstreamer-pbutils/src/auto/encoding_profile.rs +++ b/gstreamer-pbutils/src/auto/encoding_profile.rs @@ -1,5 +1,5 @@ -// This file was generated by gir (https://github.com/gtk-rs/gir @ fe7a6ff+) -// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT use DiscovererInfo; @@ -78,24 +78,6 @@ pub trait EncodingProfileExt { fn is_enabled(&self) -> bool; - fn set_allow_dynamic_output(&self, allow_dynamic_output: bool); - - fn set_description<'a, P: Into>>(&self, description: P); - - fn set_enabled(&self, enabled: bool); - - fn set_format(&self, format: &gst::Caps); - - fn set_name<'a, P: Into>>(&self, name: P); - - fn set_presence(&self, presence: u32); - - fn set_preset<'a, P: Into>>(&self, preset: P); - - fn set_preset_name<'a, P: Into>>(&self, preset_name: P); - - fn set_restriction<'a, P: Into>>(&self, restriction: P); - fn get_property_restriction_caps(&self) -> Option; fn set_property_restriction_caps(&self, restriction_caps: Option<&gst::Caps>); @@ -182,70 +164,6 @@ impl + IsA> EncodingProfileExt for } } - fn set_allow_dynamic_output(&self, allow_dynamic_output: bool) { - unsafe { - ffi::gst_encoding_profile_set_allow_dynamic_output(self.to_glib_none().0, allow_dynamic_output.to_glib()); - } - } - - fn set_description<'a, P: Into>>(&self, description: P) { - let description = description.into(); - let description = description.to_glib_none(); - unsafe { - ffi::gst_encoding_profile_set_description(self.to_glib_none().0, description.0); - } - } - - fn set_enabled(&self, enabled: bool) { - unsafe { - ffi::gst_encoding_profile_set_enabled(self.to_glib_none().0, enabled.to_glib()); - } - } - - fn set_format(&self, format: &gst::Caps) { - unsafe { - ffi::gst_encoding_profile_set_format(self.to_glib_none().0, format.to_glib_none().0); - } - } - - fn set_name<'a, P: Into>>(&self, name: P) { - let name = name.into(); - let name = name.to_glib_none(); - unsafe { - ffi::gst_encoding_profile_set_name(self.to_glib_none().0, name.0); - } - } - - fn set_presence(&self, presence: u32) { - unsafe { - ffi::gst_encoding_profile_set_presence(self.to_glib_none().0, presence); - } - } - - fn set_preset<'a, P: Into>>(&self, preset: P) { - let preset = preset.into(); - let preset = preset.to_glib_none(); - unsafe { - ffi::gst_encoding_profile_set_preset(self.to_glib_none().0, preset.0); - } - } - - fn set_preset_name<'a, P: Into>>(&self, preset_name: P) { - let preset_name = preset_name.into(); - let preset_name = preset_name.to_glib_none(); - unsafe { - ffi::gst_encoding_profile_set_preset_name(self.to_glib_none().0, preset_name.0); - } - } - - fn set_restriction<'a, P: Into>>(&self, restriction: P) { - let restriction = restriction.into(); - let restriction = restriction.to_glib_none(); - unsafe { - ffi::gst_encoding_profile_set_restriction(self.to_glib_none().0, restriction.0); - } - } - fn get_property_restriction_caps(&self) -> Option { unsafe { let mut value = Value::from_type(::static_type()); @@ -271,7 +189,6 @@ impl + IsA> EncodingProfileExt for unsafe extern "C" fn notify_restriction_caps_trampoline

(this: *mut ffi::GstEncodingProfile, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) where P: IsA { - callback_guard!(); let f: &&(Fn(&P) + Send + Sync + 'static) = transmute(f); f(&EncodingProfile::from_glib_borrow(this).downcast_unchecked()) } diff --git a/gstreamer-pbutils/src/auto/encoding_target.rs b/gstreamer-pbutils/src/auto/encoding_target.rs index c45d64bb8..8fcc3285a 100644 --- a/gstreamer-pbutils/src/auto/encoding_target.rs +++ b/gstreamer-pbutils/src/auto/encoding_target.rs @@ -1,5 +1,5 @@ -// This file was generated by gir (https://github.com/gtk-rs/gir @ fe7a6ff+) -// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT use EncodingProfile; diff --git a/gstreamer-pbutils/src/auto/encoding_video_profile.rs b/gstreamer-pbutils/src/auto/encoding_video_profile.rs index 9e1d2d77e..5aeab3c57 100644 --- a/gstreamer-pbutils/src/auto/encoding_video_profile.rs +++ b/gstreamer-pbutils/src/auto/encoding_video_profile.rs @@ -1,5 +1,5 @@ -// This file was generated by gir (https://github.com/gtk-rs/gir @ fe7a6ff+) -// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT use EncodingProfile; @@ -7,7 +7,6 @@ use ffi; use glib::translate::*; use glib_ffi; use gobject_ffi; -use gst; use std::mem; use std::ptr; @@ -20,17 +19,6 @@ glib_wrapper! { } impl EncodingVideoProfile { - pub fn new<'a, 'b, P: Into>, Q: Into>>(format: &gst::Caps, preset: P, restriction: Q, presence: u32) -> EncodingVideoProfile { - assert_initialized_main_thread!(); - let preset = preset.into(); - let preset = preset.to_glib_none(); - let restriction = restriction.into(); - let restriction = restriction.to_glib_none(); - unsafe { - from_glib_full(ffi::gst_encoding_video_profile_new(format.to_glib_none().0, preset.0, restriction.0, presence)) - } - } - pub fn get_pass(&self) -> u32 { unsafe { ffi::gst_encoding_video_profile_get_pass(self.to_glib_none().0) @@ -42,18 +30,6 @@ impl EncodingVideoProfile { from_glib(ffi::gst_encoding_video_profile_get_variableframerate(self.to_glib_none().0)) } } - - pub fn set_pass(&self, pass: u32) { - unsafe { - ffi::gst_encoding_video_profile_set_pass(self.to_glib_none().0, pass); - } - } - - pub fn set_variableframerate(&self, variableframerate: bool) { - unsafe { - ffi::gst_encoding_video_profile_set_variableframerate(self.to_glib_none().0, variableframerate.to_glib()); - } - } } unsafe impl Send for EncodingVideoProfile {} diff --git a/gstreamer-pbutils/src/encoding_audio_profile.rs b/gstreamer-pbutils/src/encoding_audio_profile.rs deleted file mode 100644 index d0e3e962d..000000000 --- a/gstreamer-pbutils/src/encoding_audio_profile.rs +++ /dev/null @@ -1,84 +0,0 @@ - -use gst; - -use std::error; -use std::fmt; - -use auto::EncodingAudioProfile; - - -#[derive(Debug, Clone)] -pub struct EncodingAudioProfileBuilderError; - -impl fmt::Display for EncodingAudioProfileBuilderError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "failed to build encoding audio profile") - } -} - -impl error::Error for EncodingAudioProfileBuilderError { - fn description(&self) -> &str { - "invalid parameters to build encoding audio profile" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} - -pub struct EncodingAudioProfileBuilder<'a> { - format: Option<& 'a gst::Caps>, - preset: Option<& 'a str>, - restriction: Option<& 'a gst::Caps>, - presence: u32 -} - -impl<'a> EncodingAudioProfileBuilder<'a> { - pub fn new() -> Self { - EncodingAudioProfileBuilder { - format: None, - preset: None, - restriction: None, - presence: 0, - } - } - - pub fn build(self) -> Result { - if self.format.is_none() { - return Err(EncodingAudioProfileBuilderError); - } - - let profile = EncodingAudioProfile::new( - self.format.unwrap(), self.preset, self.restriction, self.presence); - - Ok(profile) - } - - pub fn format(self, format: & 'a gst::Caps) -> Self { - Self { - format: Some(format), - ..self - } - } - - pub fn restriction(self, restriction: & 'a gst::Caps) -> Self { - Self { - restriction: Some(restriction), - ..self - } - } - - pub fn preset(self, preset: & 'a str) -> Self { - Self { - preset: Some(preset), - ..self - } - } - - pub fn presence(self, presence: u32) -> Self { - Self { - presence: presence, - ..self - } - } -} diff --git a/gstreamer-pbutils/src/encoding_container_profile.rs b/gstreamer-pbutils/src/encoding_container_profile.rs deleted file mode 100644 index fb44d6165..000000000 --- a/gstreamer-pbutils/src/encoding_container_profile.rs +++ /dev/null @@ -1,99 +0,0 @@ - -use gst; - -use std::error; -use std::fmt; - -use auto::EncodingProfile; -use auto::EncodingContainerProfile; -use auto::EncodingContainerProfileExt; - -use std::collections::LinkedList; - -#[derive(Debug, Clone)] -pub struct EncodingContainerProfileBuilderError; - -impl fmt::Display for EncodingContainerProfileBuilderError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "failed to build encoding video profile") - } -} - -impl error::Error for EncodingContainerProfileBuilderError { - fn description(&self) -> &str { - "invalid parameters to build encoding container profile" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} - -pub struct EncodingContainerProfileBuilder<'a> { - name: Option<& 'a str>, - description: Option<& 'a str>, - format: Option<& 'a gst::Caps>, - preset: Option<& 'a str>, - profiles: LinkedList<& 'a EncodingProfile> -} - -impl<'a> EncodingContainerProfileBuilder<'a> { - pub fn new() -> Self { - EncodingContainerProfileBuilder { - name: None, - description: None, - format: None, - preset: None, - profiles: LinkedList::new() - } - } - - pub fn build(self) -> Result { - if self.format.is_none() { - return Err(EncodingContainerProfileBuilderError); - } - - let container_profile = EncodingContainerProfile::new( - self.name, self.description, self.format.unwrap(), self.preset); - - for profile in self.profiles { - container_profile.add_profile(profile).or_else(|_error| Err(EncodingContainerProfileBuilderError))?; - } - - Ok(container_profile) - } - - pub fn name(self, name: & 'a str) -> Self { - Self { - name: Some(name), - ..self - } - } - - pub fn description(self, description: & 'a str) -> Self { - Self { - description: Some(description), - ..self - } - } - - pub fn format(self, format: & 'a gst::Caps) -> Self { - Self { - format: Some(format), - ..self - } - } - - pub fn preset(self, preset: & 'a str) -> Self { - Self { - preset: Some(preset), - ..self - } - } - - pub fn add_profile(mut self, profile: & 'a EncodingProfile) -> Self { - self.profiles.push_back(profile); - self - } - -} diff --git a/gstreamer-pbutils/src/encoding_profile.rs b/gstreamer-pbutils/src/encoding_profile.rs new file mode 100644 index 000000000..1ad7d4ba4 --- /dev/null +++ b/gstreamer-pbutils/src/encoding_profile.rs @@ -0,0 +1,574 @@ + +use gst; +use glib; +use ffi; + +use std::error; +use std::fmt; +use std::collections::LinkedList; + +use glib::Cast; +use glib::object::IsA; +use glib::translate::*; + +use auto::EncodingProfile; +use auto::EncodingAudioProfile; +use auto::EncodingVideoProfile; +use auto::EncodingContainerProfile; + +trait EncodingProfileEdit { + fn set_allow_dynamic_output(&self, allow_dynamic_output: bool); + + fn set_description<'a, P: Into>>(&self, description: P); + + fn set_enabled(&self, enabled: bool); + + fn set_format(&self, format: &gst::Caps); + + fn set_name<'a, P: Into>>(&self, name: P); + + fn set_presence(&self, presence: u32); + + fn set_preset<'a, P: Into>>(&self, preset: P); + + fn set_preset_name<'a, P: Into>>(&self, preset_name: P); + + fn set_restriction<'a, P: Into>>(&self, restriction: P); +} + +impl + IsA> EncodingProfileEdit for O { + + fn set_allow_dynamic_output(&self, allow_dynamic_output: bool) { + unsafe { + ffi::gst_encoding_profile_set_allow_dynamic_output(self.to_glib_none().0, allow_dynamic_output.to_glib()); + } + } + + fn set_description<'a, P: Into>>(&self, description: P) { + let description = description.into(); + let description = description.to_glib_none(); + unsafe { + ffi::gst_encoding_profile_set_description(self.to_glib_none().0, description.0); + } + } + + fn set_enabled(&self, enabled: bool) { + unsafe { + ffi::gst_encoding_profile_set_enabled(self.to_glib_none().0, enabled.to_glib()); + } + } + + fn set_format(&self, format: &gst::Caps) { + unsafe { + ffi::gst_encoding_profile_set_format(self.to_glib_none().0, format.to_glib_none().0); + } + } + + fn set_name<'a, P: Into>>(&self, name: P) { + let name = name.into(); + let name = name.to_glib_none(); + unsafe { + ffi::gst_encoding_profile_set_name(self.to_glib_none().0, name.0); + } + } + + fn set_presence(&self, presence: u32) { + unsafe { + ffi::gst_encoding_profile_set_presence(self.to_glib_none().0, presence); + } + } + + fn set_preset<'a, P: Into>>(&self, preset: P) { + let preset = preset.into(); + let preset = preset.to_glib_none(); + unsafe { + ffi::gst_encoding_profile_set_preset(self.to_glib_none().0, preset.0); + } + } + + fn set_preset_name<'a, P: Into>>(&self, preset_name: P) { + let preset_name = preset_name.into(); + let preset_name = preset_name.to_glib_none(); + unsafe { + ffi::gst_encoding_profile_set_preset_name(self.to_glib_none().0, preset_name.0); + } + } + + fn set_restriction<'a, P: Into>>(&self, restriction: P) { + let restriction = restriction.into(); + let restriction = restriction.to_glib_none(); + unsafe { + ffi::gst_encoding_profile_set_restriction(self.to_glib_none().0, restriction.0); + } + } +} + +impl EncodingAudioProfile { + fn new<'a, 'b, P: Into>, Q: Into>>(format: &gst::Caps, preset: P, restriction: Q, presence: u32) -> EncodingAudioProfile { + assert_initialized_main_thread!(); + let preset = preset.into(); + let preset = preset.to_glib_none(); + let restriction = restriction.into(); + let restriction = restriction.to_glib_none(); + unsafe { + from_glib_full(ffi::gst_encoding_audio_profile_new(format.to_glib_none().0, preset.0, restriction.0, presence)) + } + } +} + +impl EncodingVideoProfile { + fn new<'a, 'b, P: Into>, Q: Into>>(format: &gst::Caps, preset: P, restriction: Q, presence: u32) -> EncodingVideoProfile { + assert_initialized_main_thread!(); + let preset = preset.into(); + let preset = preset.to_glib_none(); + let restriction = restriction.into(); + let restriction = restriction.to_glib_none(); + unsafe { + from_glib_full(ffi::gst_encoding_video_profile_new(format.to_glib_none().0, preset.0, restriction.0, presence)) + } + } + + fn set_pass(&self, pass: u32) { + unsafe { + ffi::gst_encoding_video_profile_set_pass(self.to_glib_none().0, pass); + } + } + + fn set_variableframerate(&self, variableframerate: bool) { + unsafe { + ffi::gst_encoding_video_profile_set_variableframerate(self.to_glib_none().0, variableframerate.to_glib()); + } + } +} + +impl EncodingContainerProfile { + fn new<'a, 'b, 'c, P: Into>, Q: Into>, R: Into>>(name: P, description: Q, format: &gst::Caps, preset: R) -> EncodingContainerProfile { + assert_initialized_main_thread!(); + let name = name.into(); + let name = name.to_glib_none(); + let description = description.into(); + let description = description.to_glib_none(); + let preset = preset.into(); + let preset = preset.to_glib_none(); + unsafe { + from_glib_full(ffi::gst_encoding_container_profile_new(name.0, description.0, format.to_glib_none().0, preset.0)) + } + } + + fn add_profile>(&self, profile: &P) -> Result<(), glib::error::BoolError> { + unsafe { + glib::error::BoolError::from_glib(ffi::gst_encoding_container_profile_add_profile(self.to_glib_none().0, profile.to_glib_full()), "Failed to add profile") + } + } +} + +#[derive(Debug, Clone)] +pub struct EncodingProfileBuilderError; + +impl fmt::Display for EncodingProfileBuilderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "failed to build encoding profile") + } +} + +impl error::Error for EncodingProfileBuilderError { + fn description(&self) -> &str { + "invalid parameters to build encoding profile" + } + + fn cause(&self) -> Option<&error::Error> { + None + } +} + +struct EncodingProfileBuilderData<'a> { + name: Option<& 'a str>, + description: Option<& 'a str>, + format: Option<& 'a gst::Caps>, + preset: Option<& 'a str>, + preset_name: Option<& 'a str>, + restriction: Option<& 'a gst::Caps>, + presence: u32, + allow_dynamic_output: bool, + enabled: bool +} + +impl<'a> EncodingProfileBuilderData<'a> { + fn new() -> EncodingProfileBuilderData<'a> { + EncodingProfileBuilderData { + name: None, + description: None, + format: None, + preset: None, + preset_name : None, + restriction: None, + presence: 0, + allow_dynamic_output: true, + enabled: true + } + } +} + +pub trait EncodingProfileBuilder<'a>: Sized { + fn name(self, name: & 'a str) -> Self; + fn description(self, description: & 'a str) -> Self; + fn format(self, format: & 'a gst::Caps) -> Self; + fn preset(self, preset: & 'a str) -> Self; + fn preset_name(self, preset_name: & 'a str) -> Self; + fn restriction(self, format: & 'a gst::Caps) -> Self; + fn presence(self, presence: u32) -> Self; + fn allow_dynamic_output(self, allow: bool) -> Self; + fn enabled(self, enabled: bool) -> Self; +} + +macro_rules! declare_encoding_profile_builder( + ($name:ident) => { + impl<'a> EncodingProfileBuilder<'a> for $name<'a> { + fn name(mut self, name: &'a str) -> $name<'a> { + self.base.name = Some(name); + self + } + + fn description(mut self, description: &'a str) -> $name<'a> { + self.base.description = Some(description); + 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> { + self.base.preset = Some(preset); + self + } + + fn preset_name(mut self, preset_name: &'a str) -> $name<'a> { + self.base.preset_name = Some(preset_name); + self + } + + fn restriction(mut self, restriction: &'a gst::Caps) -> $name<'a> { + self.base.restriction = Some(restriction); + self + } + + fn presence(mut self, presence: u32) -> $name<'a> { + self.base.presence = presence; + self + } + + fn allow_dynamic_output(mut self, allow: bool) -> $name<'a> { + self.base.allow_dynamic_output = allow; + self + } + + fn enabled(mut self, enabled: bool) -> $name<'a> { + self.base.enabled = enabled; + self + } + } + } +); + +fn set_common_fields(profile: &mut T, base_data: &EncodingProfileBuilderData) { + profile.set_name(base_data.name); + profile.set_description(base_data.description); + profile.set_preset(base_data.preset); + profile.set_preset_name(base_data.preset_name); + profile.set_allow_dynamic_output(base_data.allow_dynamic_output); + profile.set_enabled(base_data.enabled); + + profile.set_restriction(base_data.restriction); + profile.set_presence(base_data.presence); +} + +pub struct EncodingAudioProfileBuilder<'a> { + base : EncodingProfileBuilderData<'a> +} + +declare_encoding_profile_builder!(EncodingAudioProfileBuilder); + +impl<'a> EncodingAudioProfileBuilder<'a> { + pub fn new() -> Self { + EncodingAudioProfileBuilder { + base: EncodingProfileBuilderData::new(), + } + } + + pub fn build(self) -> Result { + if self.base.format.is_none() { + return Err(EncodingProfileBuilderError); + } + + let profile = EncodingAudioProfile::new( + self.base.format.unwrap(), self.base.preset, + self.base.restriction, self.base.presence); + + let mut profile = profile.upcast(); + set_common_fields(&mut profile, &self.base); + Ok(profile) + } +} + +pub struct EncodingVideoProfileBuilder<'a> { + base : EncodingProfileBuilderData<'a>, + pass: u32, + variable_framerate: bool, +} + +declare_encoding_profile_builder!(EncodingVideoProfileBuilder); + +impl<'a> EncodingVideoProfileBuilder<'a> { + pub fn new() -> Self { + EncodingVideoProfileBuilder { + base: EncodingProfileBuilderData::new(), + pass: 0, + variable_framerate: false + } + } + + pub fn pass(mut self, pass: u32) -> Self { + self.pass = pass; + self + } + + pub fn variable_framerate(mut self, variable_framerate: bool) -> Self { + self.variable_framerate = variable_framerate; + self + } + + pub fn build(self) -> Result { + if self.base.format.is_none() { + return Err(EncodingProfileBuilderError); + } + + let video_profile = EncodingVideoProfile::new( + self.base.format.unwrap(), self.base.preset, self.base.restriction, self.base.presence); + + video_profile.set_pass(self.pass); + video_profile.set_variableframerate(self.variable_framerate); + + let mut profile = video_profile.upcast(); + set_common_fields(&mut profile, &self.base); + Ok(profile) + } +} + +pub struct EncodingContainerProfileBuilder<'a> { + base : EncodingProfileBuilderData<'a>, + profiles: LinkedList<& 'a EncodingProfile> +} + +declare_encoding_profile_builder!(EncodingContainerProfileBuilder); + +impl<'a> EncodingContainerProfileBuilder<'a> { + pub fn new() -> Self { + EncodingContainerProfileBuilder { + base: EncodingProfileBuilderData::new(), + profiles: LinkedList::new() + } + } + + pub fn build(self) -> Result { + if self.base.format.is_none() { + return Err(EncodingProfileBuilderError); + } + + let container_profile = EncodingContainerProfile::new( + self.base.name, self.base.description, self.base.format.unwrap(), self.base.preset); + + for profile in self.profiles { + container_profile.add_profile(profile).or_else(|_error| Err(EncodingProfileBuilderError))?; + } + + let mut profile = container_profile.upcast(); + set_common_fields(&mut profile, &self.base); + Ok(profile) + } + + pub fn add_profile(mut self, profile: & 'a EncodingProfile) -> Self { + self.profiles.push_back(profile); + self + } + +} + +#[cfg(test)] +mod tests { + use super::*; + use gst; + use auto::EncodingProfileExt; + use auto::EncodingVideoProfile; + use auto::EncodingContainerProfile; + use auto::EncodingContainerProfileExt; + + const AUDIO_PROFILE_NAME: &'static str = "audio-profile"; + const AUDIO_PROFILE_DESCRIPTION: &'static str = "audio-profile-description"; + const PRESET: &'static str = "preset"; + const PRESET_NAME: &'static str = "preset-name"; + const PRESENCE: u32 = 5; + const ALLOW_DYNAMIC_OUTPUT: bool = false; + const ENABLED: bool = false; + + const VIDEO_PROFILE_NAME: &'static str = "video-profile"; + const VIDEO_PROFILE_DESCRIPTION: &'static str = "video-profile-description"; + + const CONTAINER_PROFILE_NAME: &'static str = "container-profile"; + const CONTAINER_PROFILE_DESCRIPTION: &'static str = "container-profile-description"; + + // Video profile exclusive attributes + const PASS: u32 = 8; + const VARIABLE_FRAMERATE: bool = true; + + #[test] + fn test_encoding_audio_profile_builder() { + gst::init().unwrap(); + + let caps = gst::Caps::new_simple( + "audio/x-raw", + &[], + ); + + let restriction = gst::Caps::new_simple( + "audio/x-raw", + &[ + ("format", &"S32LE"), + ], + ); + + let audio_profile = EncodingAudioProfileBuilder::new() + .name(AUDIO_PROFILE_NAME) + .description(AUDIO_PROFILE_DESCRIPTION) + .format(&caps) + .preset(PRESET) + .preset_name(PRESET_NAME) + .restriction(&restriction) + .presence(PRESENCE) + .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT) + .enabled(ENABLED) + .build().unwrap(); + + assert_eq!(audio_profile.get_name().unwrap(), AUDIO_PROFILE_NAME); + assert_eq!(audio_profile.get_description().unwrap(), AUDIO_PROFILE_DESCRIPTION); + assert_eq!(audio_profile.get_format(), caps); + assert_eq!(audio_profile.get_preset().unwrap(), PRESET); + assert_eq!(audio_profile.get_preset_name().unwrap(), PRESET_NAME); + assert_eq!(audio_profile.get_restriction().unwrap(), restriction); + assert_eq!(audio_profile.get_presence(), PRESENCE); + assert_eq!(audio_profile.get_allow_dynamic_output(), ALLOW_DYNAMIC_OUTPUT); + assert_eq!(audio_profile.is_enabled(), ENABLED); + } + + #[test] + fn test_encoding_video_profile_builder() { + gst::init().unwrap(); + + let caps = gst::Caps::new_simple( + "video/x-raw", + &[], + ); + + let restriction = gst::Caps::new_simple( + "video/x-raw", + &[ + ("format", &"RGBA"), + ], + ); + + let video_profile = EncodingVideoProfileBuilder::new() + .name(VIDEO_PROFILE_NAME) + .description(VIDEO_PROFILE_DESCRIPTION) + .format(&caps) + .preset(PRESET) + .preset_name(PRESET_NAME) + .restriction(&restriction) + .presence(PRESENCE) + .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT) + .enabled(ENABLED) + .pass(PASS) + .variable_framerate(VARIABLE_FRAMERATE) + .build().unwrap(); + + assert_eq!(video_profile.get_name().unwrap(), VIDEO_PROFILE_NAME); + assert_eq!(video_profile.get_description().unwrap(), VIDEO_PROFILE_DESCRIPTION); + assert_eq!(video_profile.get_format(), caps); + assert_eq!(video_profile.get_preset().unwrap(), PRESET); + assert_eq!(video_profile.get_preset_name().unwrap(), PRESET_NAME); + assert_eq!(video_profile.get_restriction().unwrap(), restriction); + assert_eq!(video_profile.get_presence(), PRESENCE); + assert_eq!(video_profile.get_allow_dynamic_output(), ALLOW_DYNAMIC_OUTPUT); + assert_eq!(video_profile.is_enabled(), ENABLED); + + let video_profile: EncodingVideoProfile = + glib::object::Downcast::downcast(video_profile).ok().unwrap(); + assert_eq!(video_profile.get_variableframerate(), VARIABLE_FRAMERATE); + assert_eq!(video_profile.get_pass(), PASS); + } + + #[test] + fn test_encoding_container_profile_builder() { + gst::init().unwrap(); + + let container_caps = gst::Caps::new_simple( + "container/x-caps", + &[], + ); + let restriction = gst::Caps::new_simple( + "container/x-caps", + &[ + ("field", &"somevalue") + ], + ); + let video_caps = gst::Caps::new_simple( + "video/x-raw", + &[], + ); + let audio_caps = gst::Caps::new_simple( + "audio/x-raw", + &[], + ); + + let video_profile = EncodingVideoProfileBuilder::new() + .name(VIDEO_PROFILE_NAME) + .description(VIDEO_PROFILE_DESCRIPTION) + .format(&video_caps) + .build().unwrap(); + let audio_profile = EncodingAudioProfileBuilder::new() + .name(AUDIO_PROFILE_NAME) + .description(AUDIO_PROFILE_DESCRIPTION) + .format(&audio_caps) + .build().unwrap(); + + let profile = EncodingContainerProfileBuilder::new() + .name(CONTAINER_PROFILE_NAME) + .description(CONTAINER_PROFILE_DESCRIPTION) + .format(&container_caps) + .preset(PRESET) + .preset_name(PRESET_NAME) + .restriction(&restriction) + .presence(PRESENCE) + .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT) + .enabled(ENABLED) + .add_profile(&audio_profile) + .add_profile(&video_profile) + .build().unwrap(); + + assert_eq!(profile.get_name().unwrap(), CONTAINER_PROFILE_NAME); + assert_eq!(profile.get_description().unwrap(), CONTAINER_PROFILE_DESCRIPTION); + assert_eq!(profile.get_format(), container_caps); + assert_eq!(profile.get_preset().unwrap(), PRESET); + assert_eq!(profile.get_preset_name().unwrap(), PRESET_NAME); + assert_eq!(profile.get_restriction().unwrap(), restriction); + assert_eq!(profile.get_presence(), PRESENCE); + assert_eq!(profile.get_allow_dynamic_output(), ALLOW_DYNAMIC_OUTPUT); + assert_eq!(profile.is_enabled(), ENABLED); + + let container_profile: EncodingContainerProfile = + glib::object::Downcast::downcast(profile).ok().unwrap(); + + assert!(container_profile.contains_profile(&video_profile)); + assert!(container_profile.contains_profile(&audio_profile)); + } +} diff --git a/gstreamer-pbutils/src/encoding_video_profile.rs b/gstreamer-pbutils/src/encoding_video_profile.rs deleted file mode 100644 index c6f97552e..000000000 --- a/gstreamer-pbutils/src/encoding_video_profile.rs +++ /dev/null @@ -1,105 +0,0 @@ - -use gst; - -use std::error; -use std::fmt; - -use auto::EncodingVideoProfile; - - -#[derive(Debug, Clone)] -pub struct EncodingVideoProfileBuilderError; - -impl fmt::Display for EncodingVideoProfileBuilderError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "failed to build encoding video profile") - } -} - -impl error::Error for EncodingVideoProfileBuilderError { - fn description(&self) -> &str { - "invalid parameters to build encoding video profile" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} - -pub struct EncodingVideoProfileBuilder<'a> { - format: Option<& 'a gst::Caps>, - preset: Option<& 'a str>, - restriction: Option<& 'a gst::Caps>, - presence: u32, - pass: u32, - variable_framerate: bool, -} - -impl<'a> EncodingVideoProfileBuilder<'a> { - pub fn new() -> Self { - EncodingVideoProfileBuilder { - format: None, - preset: None, - restriction: None, - presence: 0, - pass: 0, - variable_framerate: false, - } - } - - pub fn build(self) -> Result { - if self.format.is_none() { - return Err(EncodingVideoProfileBuilderError); - } - - let profile = EncodingVideoProfile::new( - self.format.unwrap(), self.preset, self.restriction, self.presence); - - profile.set_pass(self.pass); - profile.set_variableframerate(self.variable_framerate); - - Ok(profile) - } - - pub fn format(self, format: & 'a gst::Caps) -> Self { - Self { - format: Some(format), - ..self - } - } - - pub fn restriction(self, restriction: & 'a gst::Caps) -> Self { - Self { - restriction: Some(restriction), - ..self - } - } - - pub fn preset(self, preset: & 'a str) -> Self { - Self { - preset: Some(preset), - ..self - } - } - - pub fn presence(self, presence: u32) -> Self { - Self { - presence: presence, - ..self - } - } - - pub fn pass(self, pass: u32) -> Self { - Self { - pass: pass, - ..self - } - } - - pub fn variable_framerate(self, variable_framerate: bool) -> Self { - Self { - variable_framerate: variable_framerate, - ..self - } - } -} diff --git a/gstreamer-pbutils/src/lib.rs b/gstreamer-pbutils/src/lib.rs index 28aa0a2a4..d5479f156 100644 --- a/gstreamer-pbutils/src/lib.rs +++ b/gstreamer-pbutils/src/lib.rs @@ -55,14 +55,8 @@ pub mod discoverer_stream_info; mod discoverer_video_info; pub use discoverer_video_info::*; -mod encoding_container_profile; -pub use encoding_container_profile::*; - -mod encoding_audio_profile; -pub use encoding_audio_profile::*; - -mod encoding_video_profile; -pub use encoding_video_profile::*; +mod encoding_profile; +pub use encoding_profile::*; // Re-export all the traits in a prelude module, so that applications // can always "use gst::prelude::*" without getting conflicts @@ -74,9 +68,7 @@ pub mod prelude { pub use discoverer_stream_info::*; pub use discoverer_video_info::*; - pub use encoding_container_profile::*; - pub use encoding_video_profile::*; - pub use encoding_audio_profile::*; + pub use encoding_profile::*; pub use auto::traits::*; }