diff --git a/Gir_GstPbutils.toml b/Gir_GstPbutils.toml index c30589af3..2d0672e72 100644 --- a/Gir_GstPbutils.toml +++ b/Gir_GstPbutils.toml @@ -145,11 +145,8 @@ trait = false [[object]] name = "GstPbutils.EncodingProfile" status = "generate" - [[object.function]] - name = "is_equal" - ignore = true - # Ignore all setters, making it imutable. A builder will be provided. + # Ignore all setters, making it immutable. A builder will be provided. [[object.function]] name = "new" ignore = true @@ -172,11 +169,16 @@ status = "generate" [object.function.return] nullable = false + [[object.property]] + name = "restriction-caps" + # encodingprofile is immutable after constructed + ignore = true + [[object]] name = "GstPbutils.EncodingContainerProfile" status = "generate" - # Make it imutable, only able to be constructed for a builder + # Make it immutable, only able to be constructed for a builder [[object.function]] name = "new" ignore = true @@ -211,7 +213,7 @@ status = "generate" name = "GstPbutils.EncodingAudioProfile" status = "generate" trait = false - # Ignore all setters, making it imutable. A builder will be provided. + # Ignore all setters, making it immutable. A builder will be provided. [[object.function]] name = "new" ignore = true @@ -223,7 +225,7 @@ trait = false name = "GstPbutils.EncodingVideoProfile" status = "generate" trait = false - # Ignore all setters, making it imutable. A builder will be provided. + # Ignore all setters, making it immutable. A builder will be provided. [[object.function]] name = "new" ignore = true diff --git a/examples/src/bin/encodebin.rs b/examples/src/bin/encodebin.rs index e106694a4..d6f71da91 100644 --- a/examples/src/bin/encodebin.rs +++ b/examples/src/bin/encodebin.rs @@ -58,11 +58,11 @@ fn configure_encodebin(encodebin: &gst::Element) -> Result<(), Error> { "video/x-matroska", &[], )) - .add_profile(&(video_profile.upcast())) - .add_profile(&(audio_profile.upcast())) + .add_profile(&(video_profile)) + .add_profile(&(audio_profile)) .build()?; - encodebin.set_property("profile", &container_profile)?; + encodebin.set_property("profile", &container_profile).expect("set profile property failed"); Ok(()) } @@ -87,12 +87,12 @@ fn example_main() -> Result<(), Error> { let encodebin = gst::ElementFactory::make("encodebin", None).ok_or(MissingElement("encodebin"))?; let sink = gst::ElementFactory::make("filesink", None).ok_or(MissingElement("filesink"))?; - src.set_property("uri", &uri)?; - sink.set_property("location", &output_file)?; + src.set_property("uri", &uri).expect("setting URI Property failed"); + sink.set_property("location", &output_file).expect("setting location property failed"); configure_encodebin(&encodebin)?; - pipeline.add_many(&[&src, &encodebin, &sink])?; + pipeline.add_many(&[&src, &encodebin, &sink]).expect("failed to add elements to pipeline"); gst::Element::link_many(&[&encodebin, &sink])?; // Need to move a new reference into the closure @@ -122,7 +122,7 @@ fn example_main() -> Result<(), Error> { } }; - let insert_sink = |is_audio, is_video| -> Result<(), Error> { + let link_to_encodebin = |is_audio, is_video| -> Result<(), Error> { if is_audio { let queue = gst::ElementFactory::make("queue", None).ok_or(MissingElement("queue"))?; @@ -132,7 +132,7 @@ fn example_main() -> Result<(), Error> { .ok_or(MissingElement("audioresample"))?; let elements = &[&queue, &convert, &resample]; - pipeline.add_many(elements)?; + pipeline.add_many(elements).expect("failed to add audio elements to pipeline"); gst::Element::link_many(elements)?; let enc_sink_pad = encodebin.get_request_pad("audio_%u").expect("Could not get audio pad from encodebin"); @@ -154,7 +154,7 @@ fn example_main() -> Result<(), Error> { .ok_or(MissingElement("videoscale"))?; let elements = &[&queue, &convert, &scale]; - pipeline.add_many(elements)?; + pipeline.add_many(elements).expect("failed to add video elements to pipeline"); gst::Element::link_many(elements)?; let enc_sink_pad = encodebin.get_request_pad("video_%u").expect("Could not get video pad from encodebin"); @@ -172,7 +172,7 @@ fn example_main() -> Result<(), Error> { Ok(()) }; - if let Err(err) = insert_sink(is_audio, is_video) { + if let Err(err) = link_to_encodebin(is_audio, is_video) { #[cfg(feature = "v1_10")] gst_element_error!( dbin, diff --git a/gstreamer-pbutils/src/auto/discoverer.rs b/gstreamer-pbutils/src/auto/discoverer.rs index 45fc0668e..1893f4c15 100644 --- a/gstreamer-pbutils/src/auto/discoverer.rs +++ b/gstreamer-pbutils/src/auto/discoverer.rs @@ -19,6 +19,26 @@ use std::mem::transmute; use std::ptr; glib_wrapper! { + /// The `Discoverer` is a utility object which allows to get as much + /// information as possible from one or many URIs. + /// + /// It provides two APIs, allowing usage in blocking or non-blocking mode. + /// + /// The blocking mode just requires calling `Discoverer::discover_uri` + /// with the URI one wishes to discover. + /// + /// The non-blocking mode requires a running `glib::MainLoop` iterating a + /// `glib::MainContext`, where one connects to the various signals, appends the + /// URIs to be processed (through `Discoverer::discover_uri_async`) and then + /// asks for the discovery to begin (through `Discoverer::start`). + /// By default this will use the GLib default main context unless you have + /// set a custom context using `glib::MainContext::push_thread_default`. + /// + /// All the information is returned in a `DiscovererInfo` structure. + /// + /// # Implements + /// + /// [`glib::object::ObjectExt`](../glib/object/trait.ObjectExt.html) pub struct Discoverer(Object); match fn { @@ -27,6 +47,17 @@ glib_wrapper! { } impl Discoverer { + /// Creates a new `Discoverer` with the provided timeout. + /// ## `timeout` + /// timeout per file, in nanoseconds. Allowed are values between + /// one second (`GST_SECOND`) and one hour (3600 * `GST_SECOND`) + /// + /// # Returns + /// + /// The new `Discoverer`. + /// If an error occurred when creating the discoverer, `err` will be set + /// accordingly and `None` will be returned. If `err` is set, the caller must + /// free it when no longer needed using `glib::Error::free`. pub fn new(timeout: gst::ClockTime) -> Result { assert_initialized_main_thread!(); unsafe { diff --git a/gstreamer-pbutils/src/auto/discoverer_audio_info.rs b/gstreamer-pbutils/src/auto/discoverer_audio_info.rs index 2407d875c..3becd718e 100644 --- a/gstreamer-pbutils/src/auto/discoverer_audio_info.rs +++ b/gstreamer-pbutils/src/auto/discoverer_audio_info.rs @@ -11,6 +11,11 @@ use std::mem; use std::ptr; glib_wrapper! { + /// `DiscovererStreamInfo` specific to audio streams. + /// + /// # Implements + /// + /// [`DiscovererStreamInfoExt`](trait.DiscovererStreamInfoExt.html), [`glib::object::ObjectExt`](../glib/object/trait.ObjectExt.html) pub struct DiscovererAudioInfo(Object): DiscovererStreamInfo; match fn { @@ -19,12 +24,25 @@ glib_wrapper! { } impl DiscovererAudioInfo { + /// + /// # Returns + /// + /// the average or nominal bitrate of the stream in bits/second. pub fn get_bitrate(&self) -> u32 { unsafe { ffi::gst_discoverer_audio_info_get_bitrate(self.to_glib_none().0) } } + /// + /// Feature: `v1_14` + /// + /// + /// # Returns + /// + /// the channel-mask of the stream, refer to + /// `gst_audio_channel_positions_from_mask` for more + /// information. #[cfg(any(feature = "v1_14", feature = "dox"))] pub fn get_channel_mask(&self) -> u64 { unsafe { @@ -32,30 +50,50 @@ impl DiscovererAudioInfo { } } + /// + /// # Returns + /// + /// the number of channels in the stream. pub fn get_channels(&self) -> u32 { unsafe { ffi::gst_discoverer_audio_info_get_channels(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// the number of bits used per sample in each channel. pub fn get_depth(&self) -> u32 { unsafe { ffi::gst_discoverer_audio_info_get_depth(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// the language of the stream, or NULL if unknown. pub fn get_language(&self) -> Option { unsafe { from_glib_none(ffi::gst_discoverer_audio_info_get_language(self.to_glib_none().0)) } } + /// + /// # Returns + /// + /// the maximum bitrate of the stream in bits/second. pub fn get_max_bitrate(&self) -> u32 { unsafe { ffi::gst_discoverer_audio_info_get_max_bitrate(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// the sample rate of the stream in Hertz. pub fn get_sample_rate(&self) -> u32 { unsafe { ffi::gst_discoverer_audio_info_get_sample_rate(self.to_glib_none().0) diff --git a/gstreamer-pbutils/src/auto/discoverer_container_info.rs b/gstreamer-pbutils/src/auto/discoverer_container_info.rs index 53be43a63..fa6f5159f 100644 --- a/gstreamer-pbutils/src/auto/discoverer_container_info.rs +++ b/gstreamer-pbutils/src/auto/discoverer_container_info.rs @@ -11,6 +11,11 @@ use std::mem; use std::ptr; glib_wrapper! { + /// `DiscovererStreamInfo` specific to container streams. + /// + /// # Implements + /// + /// [`DiscovererStreamInfoExt`](trait.DiscovererStreamInfoExt.html), [`glib::object::ObjectExt`](../glib/object/trait.ObjectExt.html) pub struct DiscovererContainerInfo(Object): DiscovererStreamInfo; match fn { @@ -19,6 +24,12 @@ glib_wrapper! { } impl DiscovererContainerInfo { + /// + /// # Returns + /// + /// the list of + /// `DiscovererStreamInfo` this container stream offers. + /// Free with `DiscovererStreamInfo::list_free` after usage. pub fn get_streams(&self) -> Vec { unsafe { FromGlibPtrContainer::from_glib_full(ffi::gst_discoverer_container_info_get_streams(self.to_glib_none().0)) diff --git a/gstreamer-pbutils/src/auto/discoverer_info.rs b/gstreamer-pbutils/src/auto/discoverer_info.rs index d7212c24a..6a53840cd 100644 --- a/gstreamer-pbutils/src/auto/discoverer_info.rs +++ b/gstreamer-pbutils/src/auto/discoverer_info.rs @@ -16,6 +16,11 @@ use std::mem; use std::ptr; glib_wrapper! { + /// Structure containing the information of a URI analyzed by `Discoverer`. + /// + /// # Implements + /// + /// [`DiscovererInfoExt`](trait.DiscovererInfoExt.html), [`glib::object::ObjectExt`](../glib/object/trait.ObjectExt.html) pub struct DiscovererInfo(Object); match fn { @@ -24,6 +29,14 @@ glib_wrapper! { } impl DiscovererInfo { + /// Parses a `glib::Variant` as produced by `DiscovererInfoExt::to_variant` + /// back to a `DiscovererInfo`. + /// ## `variant` + /// A `glib::Variant` to deserialize into a `DiscovererInfo`. + /// + /// # Returns + /// + /// A newly-allocated `DiscovererInfo`. pub fn from_variant(variant: &glib::Variant) -> Option { assert_initialized_main_thread!(); unsafe { @@ -35,42 +48,167 @@ impl DiscovererInfo { unsafe impl Send for DiscovererInfo {} unsafe impl Sync for DiscovererInfo {} +/// Trait containing all `DiscovererInfo` methods. +/// +/// # Implementors +/// +/// [`DiscovererInfo`](struct.DiscovererInfo.html) pub trait DiscovererInfoExt { + /// + /// # Returns + /// + /// A copy of the `DiscovererInfo` fn copy(&self) -> DiscovererInfo; + /// Finds all the `DiscovererAudioInfo` contained in `self` + /// + /// # Returns + /// + /// A `glib::List` of + /// matching `DiscovererStreamInfo`. The caller should free it with + /// `DiscovererStreamInfo::list_free`. fn get_audio_streams(&self) -> Vec; + /// Finds all the `DiscovererContainerInfo` contained in `self` + /// + /// # Returns + /// + /// A `glib::List` of + /// matching `DiscovererStreamInfo`. The caller should free it with + /// `DiscovererStreamInfo::list_free`. fn get_container_streams(&self) -> Vec; + /// + /// # Returns + /// + /// the duration of the URI in `gst::ClockTime` (nanoseconds). fn get_duration(&self) -> gst::ClockTime; + /// + /// Feature: `v1_14` + /// + /// + /// # Returns + /// + /// whether the URI is live. #[cfg(any(feature = "v1_14", feature = "dox"))] fn get_live(&self) -> bool; + /// + /// # Deprecated + /// + /// This functions is deprecated since version 1.4, use + /// `DiscovererInfoExt::get_missing_elements_installer_details` + /// + /// # Returns + /// + /// Miscellaneous information stored as a `gst::Structure` + /// (for example: information about missing plugins). If you wish to use the + /// `gst::Structure` after the life-time of `self`, you will need to copy it. fn get_misc(&self) -> Option; + /// Get the installer details for missing elements + /// + /// # Returns + /// + /// An array of strings + /// containing informations about how to install the various missing elements + /// for `self` to be usable. If you wish to use the strings after the life-time + /// of `self`, you will need to copy them. fn get_missing_elements_installer_details(&self) -> Vec; + /// + /// # Returns + /// + /// the result of the discovery as a `DiscovererResult`. fn get_result(&self) -> DiscovererResult; + /// + /// # Returns + /// + /// the whether the URI is seekable. fn get_seekable(&self) -> bool; + /// + /// # Returns + /// + /// the structure (or topology) of the URI as a + /// `DiscovererStreamInfo`. + /// This structure can be traversed to see the original hierarchy. Unref with + /// `gst_discoverer_stream_info_unref` after usage. fn get_stream_info(&self) -> Option; + /// + /// # Returns + /// + /// the list of + /// all streams contained in the `info`. Free after usage + /// with `DiscovererStreamInfo::list_free`. fn get_stream_list(&self) -> Vec; + /// Finds the `DiscovererStreamInfo` contained in `self` that match the + /// given `streamtype`. + /// ## `streamtype` + /// a `glib::Type` derived from `DiscovererStreamInfo` + /// + /// # Returns + /// + /// A `glib::List` of + /// matching `DiscovererStreamInfo`. The caller should free it with + /// `DiscovererStreamInfo::list_free`. fn get_streams(&self, streamtype: glib::types::Type) -> Vec; + /// Finds all the `DiscovererSubtitleInfo` contained in `self` + /// + /// # Returns + /// + /// A `glib::List` of + /// matching `DiscovererStreamInfo`. The caller should free it with + /// `DiscovererStreamInfo::list_free`. fn get_subtitle_streams(&self) -> Vec; + /// + /// # Returns + /// + /// all tags contained in the URI. If you wish to use + /// the tags after the life-time of `self`, you will need to copy them. fn get_tags(&self) -> Option; + /// + /// # Returns + /// + /// TOC contained in the URI. If you wish to use + /// the TOC after the life-time of `self`, you will need to copy it. fn get_toc(&self) -> Option; + /// + /// # Returns + /// + /// the URI to which this information corresponds to. + /// Copy it if you wish to use it after the life-time of `self`. fn get_uri(&self) -> Option; + /// Finds all the `DiscovererVideoInfo` contained in `self` + /// + /// # Returns + /// + /// A `glib::List` of + /// matching `DiscovererStreamInfo`. The caller should free it with + /// `DiscovererStreamInfo::list_free`. fn get_video_streams(&self) -> Vec; + /// Serializes `self` to a `glib::Variant` that can be parsed again + /// through `DiscovererInfo::from_variant`. + /// + /// Note that any `gst::Toc` (s) that might have been discovered will not be serialized + /// for now. + /// ## `flags` + /// A combination of `DiscovererSerializeFlags` to specify + /// what needs to be serialized. + /// + /// # Returns + /// + /// A newly-allocated `glib::Variant` representing `self`. fn to_variant(&self, flags: DiscovererSerializeFlags) -> Option; } diff --git a/gstreamer-pbutils/src/auto/discoverer_stream_info.rs b/gstreamer-pbutils/src/auto/discoverer_stream_info.rs index fd7219f93..851a63e31 100644 --- a/gstreamer-pbutils/src/auto/discoverer_stream_info.rs +++ b/gstreamer-pbutils/src/auto/discoverer_stream_info.rs @@ -12,6 +12,25 @@ use std::mem; use std::ptr; glib_wrapper! { + /// Base structure for information concerning a media stream. Depending on the + /// stream type, one can find more media-specific information in + /// `DiscovererAudioInfo`, `DiscovererVideoInfo`, and + /// `DiscovererContainerInfo`. + /// + /// The `DiscovererStreamInfo` represents the topology of the stream. Siblings + /// can be iterated over with `DiscovererStreamInfoExt::get_next` and + /// `DiscovererStreamInfoExt::get_previous`. Children (sub-streams) of a + /// stream can be accessed using the `DiscovererContainerInfo` API. + /// + /// As a simple example, if you run `Discoverer` on an AVI file with one audio + /// and one video stream, you will get a `DiscovererContainerInfo` + /// corresponding to the AVI container, which in turn will have a + /// `DiscovererAudioInfo` sub-stream and a `DiscovererVideoInfo` sub-stream + /// for the audio and video streams respectively. + /// + /// # Implements + /// + /// [`DiscovererStreamInfoExt`](trait.DiscovererStreamInfoExt.html), [`glib::object::ObjectExt`](../glib/object/trait.ObjectExt.html) pub struct DiscovererStreamInfo(Object); match fn { @@ -22,21 +41,74 @@ glib_wrapper! { unsafe impl Send for DiscovererStreamInfo {} unsafe impl Sync for DiscovererStreamInfo {} +/// Trait containing all `DiscovererStreamInfo` methods. +/// +/// # Implementors +/// +/// [`DiscovererAudioInfo`](struct.DiscovererAudioInfo.html), [`DiscovererContainerInfo`](struct.DiscovererContainerInfo.html), [`DiscovererStreamInfo`](struct.DiscovererStreamInfo.html), [`DiscovererSubtitleInfo`](struct.DiscovererSubtitleInfo.html), [`DiscovererVideoInfo`](struct.DiscovererVideoInfo.html) pub trait DiscovererStreamInfoExt { + /// + /// # Returns + /// + /// the `gst::Caps` of the stream. Unref with + /// `gst_caps_unref` after usage. fn get_caps(&self) -> Option; + /// + /// # Deprecated + /// + /// This functions is deprecated since version 1.4, use + /// `DiscovererInfoExt::get_missing_elements_installer_details` + /// + /// # Returns + /// + /// additional information regarding the stream (for + /// example codec version, profile, etc..). If you wish to use the `gst::Structure` + /// after the life-time of `self` you will need to copy it. fn get_misc(&self) -> Option; + /// + /// # Returns + /// + /// the next `DiscovererStreamInfo` in a chain. `None` + /// for final streams. + /// Unref with `gst_discoverer_stream_info_unref` after usage. fn get_next(&self) -> Option; + /// + /// # Returns + /// + /// the previous `DiscovererStreamInfo` in a chain. + /// `None` for starting points. Unref with `gst_discoverer_stream_info_unref` + /// after usage. fn get_previous(&self) -> Option; + /// + /// # Returns + /// + /// the stream ID of this stream. If you wish to + /// use the stream ID after the life-time of `self` you will need to copy it. fn get_stream_id(&self) -> Option; + /// + /// # Returns + /// + /// a human readable name for the stream type of the given `self` (ex : "audio", + /// "container",...). fn get_stream_type_nick(&self) -> String; + /// + /// # Returns + /// + /// the tags contained in this stream. If you wish to + /// use the tags after the life-time of `self` you will need to copy them. fn get_tags(&self) -> Option; + /// + /// # Returns + /// + /// the TOC contained in this stream. If you wish to + /// use the TOC after the life-time of `self` you will need to copy it. fn get_toc(&self) -> Option; } diff --git a/gstreamer-pbutils/src/auto/discoverer_subtitle_info.rs b/gstreamer-pbutils/src/auto/discoverer_subtitle_info.rs index 53b1704fb..a4930c1c5 100644 --- a/gstreamer-pbutils/src/auto/discoverer_subtitle_info.rs +++ b/gstreamer-pbutils/src/auto/discoverer_subtitle_info.rs @@ -11,6 +11,12 @@ use std::mem; use std::ptr; glib_wrapper! { + /// `DiscovererStreamInfo` specific to subtitle streams (this includes text and + /// image based ones). + /// + /// # Implements + /// + /// [`DiscovererStreamInfoExt`](trait.DiscovererStreamInfoExt.html), [`glib::object::ObjectExt`](../glib/object/trait.ObjectExt.html) pub struct DiscovererSubtitleInfo(Object): DiscovererStreamInfo; match fn { @@ -19,6 +25,10 @@ glib_wrapper! { } impl DiscovererSubtitleInfo { + /// + /// # Returns + /// + /// the language of the stream, or NULL if unknown. pub fn get_language(&self) -> Option { unsafe { from_glib_none(ffi::gst_discoverer_subtitle_info_get_language(self.to_glib_none().0)) diff --git a/gstreamer-pbutils/src/auto/discoverer_video_info.rs b/gstreamer-pbutils/src/auto/discoverer_video_info.rs index 3de2a0dc0..26846b084 100644 --- a/gstreamer-pbutils/src/auto/discoverer_video_info.rs +++ b/gstreamer-pbutils/src/auto/discoverer_video_info.rs @@ -11,6 +11,11 @@ use std::mem; use std::ptr; glib_wrapper! { + /// `DiscovererStreamInfo` specific to video streams (this includes images). + /// + /// # Implements + /// + /// [`DiscovererStreamInfoExt`](trait.DiscovererStreamInfoExt.html), [`glib::object::ObjectExt`](../glib/object/trait.ObjectExt.html) pub struct DiscovererVideoInfo(Object): DiscovererStreamInfo; match fn { @@ -19,42 +24,71 @@ glib_wrapper! { } impl DiscovererVideoInfo { + /// + /// # Returns + /// + /// the average or nominal bitrate of the video stream in bits/second. pub fn get_bitrate(&self) -> u32 { unsafe { ffi::gst_discoverer_video_info_get_bitrate(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// the depth in bits of the video stream. pub fn get_depth(&self) -> u32 { unsafe { ffi::gst_discoverer_video_info_get_depth(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// the height of the video stream in pixels. pub fn get_height(&self) -> u32 { unsafe { ffi::gst_discoverer_video_info_get_height(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// the maximum bitrate of the video stream in bits/second. pub fn get_max_bitrate(&self) -> u32 { unsafe { ffi::gst_discoverer_video_info_get_max_bitrate(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// the width of the video stream in pixels. pub fn get_width(&self) -> u32 { unsafe { ffi::gst_discoverer_video_info_get_width(self.to_glib_none().0) } } + /// + /// # Returns + /// + /// `true` if the video stream corresponds to an image (i.e. only contains + /// one frame). pub fn is_image(&self) -> bool { unsafe { from_glib(ffi::gst_discoverer_video_info_is_image(self.to_glib_none().0)) } } + /// + /// # Returns + /// + /// `true` if the stream is interlaced, else `false`. pub fn is_interlaced(&self) -> bool { unsafe { from_glib(ffi::gst_discoverer_video_info_is_interlaced(self.to_glib_none().0)) diff --git a/gstreamer-pbutils/src/auto/encoding_profile.rs b/gstreamer-pbutils/src/auto/encoding_profile.rs index 25d0dba5a..244f0ec39 100644 --- a/gstreamer-pbutils/src/auto/encoding_profile.rs +++ b/gstreamer-pbutils/src/auto/encoding_profile.rs @@ -4,20 +4,12 @@ use DiscovererInfo; use ffi; -use glib; -use glib::StaticType; -use glib::Value; -use glib::object::Downcast; use glib::object::IsA; -use glib::signal::SignalHandlerId; -use glib::signal::connect; use glib::translate::*; use glib_ffi; use gobject_ffi; use gst; -use std::boxed::Box as Box_; use std::mem; -use std::mem::transmute; use std::ptr; glib_wrapper! { @@ -78,14 +70,10 @@ pub trait EncodingProfileExt { fn is_enabled(&self) -> bool; - fn get_property_restriction_caps(&self) -> Option; - - fn set_property_restriction_caps(&self, restriction_caps: Option<&gst::Caps>); - - fn connect_property_restriction_caps_notify(&self, f: F) -> SignalHandlerId; + fn is_equal>(&self, b: &P) -> bool; } -impl + IsA> EncodingProfileExt for O { +impl> EncodingProfileExt for O { fn copy(&self) -> EncodingProfile { unsafe { from_glib_full(ffi::gst_encoding_profile_copy(self.to_glib_none().0)) @@ -164,31 +152,9 @@ impl + IsA> EncodingProfileExt for } } - fn get_property_restriction_caps(&self) -> Option { + fn is_equal>(&self, b: &P) -> bool { unsafe { - let mut value = Value::from_type(::static_type()); - gobject_ffi::g_object_get_property(self.to_glib_none().0, "restriction-caps".to_glib_none().0, value.to_glib_none_mut().0); - value.get() - } - } - - fn set_property_restriction_caps(&self, restriction_caps: Option<&gst::Caps>) { - unsafe { - gobject_ffi::g_object_set_property(self.to_glib_none().0, "restriction-caps".to_glib_none().0, Value::from(restriction_caps).to_glib_none().0); - } - } - - fn connect_property_restriction_caps_notify(&self, f: F) -> SignalHandlerId { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "notify::restriction-caps", - transmute(notify_restriction_caps_trampoline:: as usize), Box_::into_raw(f) as *mut _) + from_glib(ffi::gst_encoding_profile_is_equal(self.to_glib_none().0, b.to_glib_none().0)) } } } - -unsafe extern "C" fn notify_restriction_caps_trampoline

(this: *mut ffi::GstEncodingProfile, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) -where P: IsA { - let f: &&(Fn(&P) + Send + Sync + 'static) = transmute(f); - f(&EncodingProfile::from_glib_borrow(this).downcast_unchecked()) -} diff --git a/gstreamer-pbutils/src/auto/enums.rs b/gstreamer-pbutils/src/auto/enums.rs index 37f60915c..1af9e9d3e 100644 --- a/gstreamer-pbutils/src/auto/enums.rs +++ b/gstreamer-pbutils/src/auto/enums.rs @@ -12,6 +12,7 @@ use glib::value::SetValue; use glib::value::Value; use gobject_ffi; +/// Result values for the discovery process. #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Clone, Copy)] pub enum DiscovererResult { diff --git a/gstreamer-pbutils/src/encoding_profile.rs b/gstreamer-pbutils/src/encoding_profile.rs index b0dd540f1..c88289d8e 100644 --- a/gstreamer-pbutils/src/encoding_profile.rs +++ b/gstreamer-pbutils/src/encoding_profile.rs @@ -1,23 +1,21 @@ - -use gst; -use glib; use ffi; +use glib; +use gst; use gst_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; +use auto::EncodingContainerProfileExt; +use auto::EncodingProfile; +use auto::EncodingVideoProfile; -trait EncodingProfileEdit { +trait EncodingProfileBuilderCommon { fn set_allow_dynamic_output(&self, allow_dynamic_output: bool); fn set_description<'a, P: Into>>(&self, description: P); @@ -37,11 +35,13 @@ trait EncodingProfileEdit { fn set_restriction<'a, P: Into>>(&self, restriction: P); } -impl + IsA> EncodingProfileEdit for O { - +impl + IsA> EncodingProfileBuilderCommon 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()); + ffi::gst_encoding_profile_set_allow_dynamic_output( + self.to_glib_none().0, + allow_dynamic_output.to_glib(), + ); } } @@ -109,27 +109,47 @@ impl + IsA> EncodingProfileEdit fo } impl EncodingAudioProfile { - fn new<'a, 'b, P: Into>, Q: Into>>(format: &gst::Caps, preset: P, restriction: Q, presence: u32) -> 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)) + 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 { + 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)) + from_glib_full(ffi::gst_encoding_video_profile_new( + format.to_glib_none().0, + preset.0, + restriction.0, + presence, + )) } } @@ -141,13 +161,28 @@ impl EncodingVideoProfile { fn set_variableframerate(&self, variableframerate: bool) { unsafe { - ffi::gst_encoding_video_profile_set_variableframerate(self.to_glib_none().0, variableframerate.to_glib()); + 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 { + 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(); @@ -156,13 +191,27 @@ impl EncodingContainerProfile { 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)) + 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> { + 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") + 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", + ) } } } @@ -186,47 +235,47 @@ impl error::Error for EncodingProfileBuilderError { } } -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>, +struct EncodingProfileBuilderCommonData<'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 + enabled: bool, } -impl<'a> EncodingProfileBuilderData<'a> { - fn new() -> EncodingProfileBuilderData<'a> { - EncodingProfileBuilderData { +impl<'a> EncodingProfileBuilderCommonData<'a> { + fn new() -> EncodingProfileBuilderCommonData<'a> { + EncodingProfileBuilderCommonData { name: None, description: None, format: None, preset: None, - preset_name : None, + preset_name: None, restriction: None, presence: 0, allow_dynamic_output: true, - enabled: 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 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( +macro_rules! declare_encoding_profile_builder_common( ($name:ident) => { impl<'a> EncodingProfileBuilder<'a> for $name<'a> { fn name(mut self, name: &'a str) -> $name<'a> { @@ -277,7 +326,10 @@ macro_rules! declare_encoding_profile_builder( } ); -fn set_common_fields(profile: &mut T, base_data: &EncodingProfileBuilderData) { +fn set_common_fields( + profile: &T, + base_data: &EncodingProfileBuilderCommonData, +) { profile.set_name(base_data.name); profile.set_description(base_data.description); profile.set_preset(base_data.preset); @@ -289,47 +341,49 @@ fn set_common_fields(profile: &mut T, base_data: &Encodi } pub struct EncodingAudioProfileBuilder<'a> { - base : EncodingProfileBuilderData<'a> + base: EncodingProfileBuilderCommonData<'a>, } -declare_encoding_profile_builder!(EncodingAudioProfileBuilder); +declare_encoding_profile_builder_common!(EncodingAudioProfileBuilder); impl<'a> EncodingAudioProfileBuilder<'a> { pub fn new() -> Self { EncodingAudioProfileBuilder { - base: EncodingProfileBuilderData::new(), + base: EncodingProfileBuilderCommonData::new(), } } - pub fn build(self) -> Result { + 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); + 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); + set_common_fields(&profile, &self.base); Ok(profile) } } pub struct EncodingVideoProfileBuilder<'a> { - base : EncodingProfileBuilderData<'a>, + base: EncodingProfileBuilderCommonData<'a>, pass: u32, variable_framerate: bool, } -declare_encoding_profile_builder!(EncodingVideoProfileBuilder); +declare_encoding_profile_builder_common!(EncodingVideoProfileBuilder); impl<'a> EncodingVideoProfileBuilder<'a> { pub fn new() -> Self { EncodingVideoProfileBuilder { - base: EncodingProfileBuilderData::new(), + base: EncodingProfileBuilderCommonData::new(), pass: 0, - variable_framerate: false + variable_framerate: false, } } @@ -343,70 +397,90 @@ impl<'a> EncodingVideoProfileBuilder<'a> { self } - pub fn build(self) -> Result { + 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); + 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) + set_common_fields(&video_profile, &self.base); + Ok(video_profile) } } pub struct EncodingContainerProfileBuilder<'a> { - base : EncodingProfileBuilderData<'a>, - profiles: LinkedList<& 'a EncodingProfile> + base: EncodingProfileBuilderCommonData<'a>, + /* + * Not proud of this. + * Couldn't figure out how to store a IsA to be used + * only when building the final profile object. So I'm using a real + * EncodingContainerProfile object just as a means to store it under + * the ffi APIs. This preserves the public APIs of this builder as + * they should be at the end. + */ + helper_profile: EncodingContainerProfile, } -declare_encoding_profile_builder!(EncodingContainerProfileBuilder); +declare_encoding_profile_builder_common!(EncodingContainerProfileBuilder); impl<'a> EncodingContainerProfileBuilder<'a> { pub fn new() -> Self { EncodingContainerProfileBuilder { - base: EncodingProfileBuilderData::new(), - profiles: LinkedList::new() + base: EncodingProfileBuilderCommonData::new(), + helper_profile: EncodingContainerProfile::new( + "helper", + None, + &gst::Caps::new_any(), + None, + ), } } - pub fn build(self) -> Result { + 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); + 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))?; + for profile in self.helper_profile.get_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) + set_common_fields(&container_profile, &self.base); + Ok(container_profile) } - pub fn add_profile(mut self, profile: & 'a EncodingProfile) -> Self { - self.profiles.push_back(profile); + pub fn add_profile>(mut self, profile: &P) -> Self { + self.helper_profile.add_profile(profile).unwrap(); self } - } #[cfg(test)] mod tests { use super::*; - use gst; - use auto::EncodingProfileExt; - use auto::EncodingVideoProfile; use auto::EncodingContainerProfile; use auto::EncodingContainerProfileExt; + use auto::EncodingProfileExt; + use auto::EncodingVideoProfile; + use gst; const AUDIO_PROFILE_NAME: &'static str = "audio-profile"; const AUDIO_PROFILE_DESCRIPTION: &'static str = "audio-profile-description"; @@ -430,17 +504,9 @@ mod tests { fn test_encoding_audio_profile_builder() { gst::init().unwrap(); - let caps = gst::Caps::new_simple( - "audio/x-raw", - &[], - ); + let caps = gst::Caps::new_simple("audio/x-raw", &[]); - 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 = EncodingAudioProfileBuilder::new() .name(AUDIO_PROFILE_NAME) @@ -452,16 +518,23 @@ mod tests { .presence(PRESENCE) .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT) .enabled(ENABLED) - .build().unwrap(); + .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_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.get_allow_dynamic_output(), + ALLOW_DYNAMIC_OUTPUT + ); assert_eq!(audio_profile.is_enabled(), ENABLED); } @@ -469,17 +542,9 @@ mod tests { fn test_encoding_video_profile_builder() { gst::init().unwrap(); - let caps = gst::Caps::new_simple( - "video/x-raw", - &[], - ); + let caps = gst::Caps::new_simple("video/x-raw", &[]); - 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 = EncodingVideoProfileBuilder::new() .name(VIDEO_PROFILE_NAME) @@ -493,20 +558,28 @@ mod tests { .enabled(ENABLED) .pass(PASS) .variable_framerate(VARIABLE_FRAMERATE) - .build().unwrap(); + .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_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.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(); + 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); } @@ -515,35 +588,23 @@ mod tests { 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 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(); + .build() + .unwrap(); let audio_profile = EncodingAudioProfileBuilder::new() .name(AUDIO_PROFILE_NAME) .description(AUDIO_PROFILE_DESCRIPTION) .format(&audio_caps) - .build().unwrap(); + .build() + .unwrap(); let profile = EncodingContainerProfileBuilder::new() .name(CONTAINER_PROFILE_NAME) @@ -557,10 +618,14 @@ mod tests { .enabled(ENABLED) .add_profile(&audio_profile) .add_profile(&video_profile) - .build().unwrap(); + .build() + .unwrap(); assert_eq!(profile.get_name().unwrap(), CONTAINER_PROFILE_NAME); - assert_eq!(profile.get_description().unwrap(), CONTAINER_PROFILE_DESCRIPTION); + 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);