mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2025-02-04 21:32:29 +00:00
512 lines
14 KiB
Rust
512 lines
14 KiB
Rust
use std::ops::{Deref, DerefMut};
|
|
|
|
use gst::{prelude::*, IdStr};
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Wrapper around `gst::Structure` for `element-properties`
|
|
/// property of `EncodingProfile`.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```rust
|
|
/// # use gstreamer_pbutils::ElementProperties;
|
|
/// # gst::init().unwrap();
|
|
/// ElementProperties::builder_general()
|
|
/// .field("threads", 16)
|
|
/// .build();
|
|
/// ```
|
|
///
|
|
/// ```rust
|
|
/// # use gstreamer_pbutils::{ElementProperties, ElementPropertiesMapItem};
|
|
/// # gst::init().unwrap();
|
|
/// ElementProperties::builder_map()
|
|
/// .item(
|
|
/// ElementPropertiesMapItem::builder("vp8enc")
|
|
/// .field("max-quantizer", 17)
|
|
/// .field("buffer-size", 20000)
|
|
/// .field("threads", 16)
|
|
/// .build(),
|
|
/// )
|
|
/// .build();
|
|
/// ```
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct ElementProperties(pub(crate) gst::Structure);
|
|
|
|
impl Default for ElementProperties {
|
|
fn default() -> Self {
|
|
Self::builder_general().build()
|
|
}
|
|
}
|
|
|
|
impl Deref for ElementProperties {
|
|
type Target = gst::StructureRef;
|
|
|
|
#[inline]
|
|
fn deref(&self) -> &Self::Target {
|
|
self.0.as_ref()
|
|
}
|
|
}
|
|
|
|
impl From<ElementProperties> for gst::Structure {
|
|
#[inline]
|
|
fn from(e: ElementProperties) -> Self {
|
|
skip_assert_initialized!();
|
|
|
|
e.into_inner()
|
|
}
|
|
}
|
|
|
|
impl ElementProperties {
|
|
// rustdoc-stripper-ignore-next
|
|
/// Creates an `ElementProperties` builder that build into
|
|
/// something similar to the following:
|
|
///
|
|
/// [element-properties, boolean-prop=true, string-prop="hi"]
|
|
pub fn builder_general() -> ElementPropertiesGeneralBuilder {
|
|
assert_initialized_main_thread!();
|
|
|
|
ElementPropertiesGeneralBuilder {
|
|
structure: gst::Structure::new_empty("element-properties"),
|
|
}
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Creates an `ElementProperties` builder that build into
|
|
/// something similar to the following:
|
|
///
|
|
/// element-properties-map, map = {
|
|
/// [openh264enc, gop-size=32, ],
|
|
/// [x264enc, key-int-max=32, tune=zerolatency],
|
|
/// }
|
|
pub fn builder_map() -> ElementPropertiesMapBuilder {
|
|
assert_initialized_main_thread!();
|
|
|
|
ElementPropertiesMapBuilder { map: Vec::new() }
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns true if self is built with `ElementPropertiesGeneralBuilder`.
|
|
pub fn is_general(&self) -> bool {
|
|
let structure_name = self.0.name();
|
|
|
|
if structure_name != "element-properties" {
|
|
debug_assert_eq!(structure_name, "element-properties-map");
|
|
return false;
|
|
}
|
|
|
|
true
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns true if self is built with `ElementPropertiesMapBuilder`.
|
|
pub fn is_map(&self) -> bool {
|
|
!self.is_general()
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Returns the inner vec of `ElementPropertiesMapItem` if self is_map()
|
|
/// or `None` if self is_general().
|
|
pub fn map(&self) -> Option<Vec<ElementPropertiesMapItem>> {
|
|
if !self.is_map() {
|
|
return None;
|
|
}
|
|
|
|
Some(
|
|
self.0
|
|
.get::<gst::List>("map")
|
|
.unwrap()
|
|
.as_slice()
|
|
.iter()
|
|
.map(|props_map| {
|
|
ElementPropertiesMapItem(props_map.get::<gst::Structure>().unwrap())
|
|
})
|
|
.collect::<Vec<_>>(),
|
|
)
|
|
}
|
|
|
|
#[inline]
|
|
pub fn into_inner(self) -> gst::Structure {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
#[must_use = "The builder must be built to be used"]
|
|
#[derive(Debug, Clone)]
|
|
pub struct ElementPropertiesGeneralBuilder {
|
|
structure: gst::Structure,
|
|
}
|
|
|
|
impl ElementPropertiesGeneralBuilder {
|
|
// rustdoc-stripper-ignore-next
|
|
/// Sets property `property_name` to the given value `value`.
|
|
///
|
|
/// Overrides any default or previously defined value for `property_name`.
|
|
pub fn field(
|
|
mut self,
|
|
property_name: impl glib::IntoGStr,
|
|
value: impl Into<glib::Value> + Send,
|
|
) -> Self {
|
|
self.structure.set(property_name, value);
|
|
self
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Sets property `property_name` to the given value `value`.
|
|
///
|
|
/// Overrides any default or previously defined value for `property_name`.
|
|
pub fn field_with_static(
|
|
mut self,
|
|
property_name: impl AsRef<glib::GStr> + 'static,
|
|
value: impl Into<glib::Value> + Send,
|
|
) -> Self {
|
|
self.structure.set_with_static(property_name, value);
|
|
self
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Sets property `property_name` to the given value `value`.
|
|
///
|
|
/// Overrides any default or previously defined value for `property_name`.
|
|
pub fn field_with_id(
|
|
mut self,
|
|
property_name: impl AsRef<IdStr>,
|
|
value: impl Into<glib::Value> + Send,
|
|
) -> Self {
|
|
self.structure.set_with_id(property_name, value);
|
|
self
|
|
}
|
|
|
|
gst::impl_builder_gvalue_extra_setters!(field);
|
|
|
|
pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self {
|
|
self.structure.set_value(property_name, value);
|
|
self
|
|
}
|
|
|
|
pub fn field_value_with_static(
|
|
mut self,
|
|
property_name: impl AsRef<glib::GStr> + 'static,
|
|
value: glib::SendValue,
|
|
) -> Self {
|
|
self.structure.set_value_with_static(property_name, value);
|
|
self
|
|
}
|
|
|
|
pub fn field_value_with_id(
|
|
mut self,
|
|
property_name: impl AsRef<IdStr>,
|
|
value: glib::SendValue,
|
|
) -> Self {
|
|
self.structure.set_value_with_id(property_name, value);
|
|
self
|
|
}
|
|
|
|
pub fn field_value_if_some(self, property_name: &str, value: Option<glib::SendValue>) -> Self {
|
|
if let Some(value) = value {
|
|
self.field_value(property_name, value)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn field_value_with_static_if_some(
|
|
self,
|
|
property_name: impl AsRef<glib::GStr> + 'static,
|
|
value: Option<glib::SendValue>,
|
|
) -> Self {
|
|
if let Some(value) = value {
|
|
self.field_value_with_static(property_name, value)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn field_value_with_id_if_some(
|
|
self,
|
|
property_name: impl AsRef<IdStr>,
|
|
value: Option<glib::SendValue>,
|
|
) -> Self {
|
|
if let Some(value) = value {
|
|
self.field_value_with_id(property_name, value)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn build(self) -> ElementProperties {
|
|
ElementProperties(self.structure)
|
|
}
|
|
}
|
|
|
|
#[must_use = "The builder must be built to be used"]
|
|
#[derive(Debug, Clone)]
|
|
pub struct ElementPropertiesMapBuilder {
|
|
map: Vec<glib::SendValue>,
|
|
}
|
|
|
|
impl ElementPropertiesMapBuilder {
|
|
pub fn item(mut self, item: ElementPropertiesMapItem) -> Self {
|
|
self.map.push(item.into_inner().to_send_value());
|
|
self
|
|
}
|
|
|
|
pub fn item_if(self, item: ElementPropertiesMapItem, predicate: bool) -> Self {
|
|
if predicate {
|
|
self.item(item)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn item_if_some(self, item: Option<ElementPropertiesMapItem>) -> Self {
|
|
if let Some(item) = item {
|
|
self.item(item)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn build(self) -> ElementProperties {
|
|
ElementProperties(
|
|
gst::Structure::builder("element-properties-map")
|
|
.field("map", gst::List::new(self.map))
|
|
.build(),
|
|
)
|
|
}
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Wrapper around `gst::Structure` for `element-properties-map` map item.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```rust
|
|
/// # use gstreamer_pbutils::{ElementProperties, ElementPropertiesMapItem};
|
|
/// # gst::init().unwrap();
|
|
/// ElementProperties::builder_map()
|
|
/// .item(
|
|
/// ElementPropertiesMapItem::builder("vp8enc")
|
|
/// .field("max-quantizer", 17)
|
|
/// .field("buffer-size", 20000)
|
|
/// .field("threads", 16)
|
|
/// .build(),
|
|
/// )
|
|
/// .build();
|
|
/// ```
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct ElementPropertiesMapItem(gst::Structure);
|
|
|
|
impl Deref for ElementPropertiesMapItem {
|
|
type Target = gst::StructureRef;
|
|
|
|
#[inline]
|
|
fn deref(&self) -> &Self::Target {
|
|
self.0.as_ref()
|
|
}
|
|
}
|
|
|
|
impl DerefMut for ElementPropertiesMapItem {
|
|
#[inline]
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
self.0.deref_mut()
|
|
}
|
|
}
|
|
|
|
impl From<ElementPropertiesMapItem> for gst::Structure {
|
|
#[inline]
|
|
fn from(e: ElementPropertiesMapItem) -> Self {
|
|
skip_assert_initialized!();
|
|
|
|
e.into_inner()
|
|
}
|
|
}
|
|
|
|
impl ElementPropertiesMapItem {
|
|
pub fn builder(factory_name: &str) -> ElementPropertiesMapItemBuilder {
|
|
assert_initialized_main_thread!();
|
|
|
|
ElementPropertiesMapItemBuilder {
|
|
structure: gst::Structure::new_empty(factory_name),
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn into_inner(self) -> gst::Structure {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
#[must_use = "The builder must be built to be used"]
|
|
#[derive(Debug, Clone)]
|
|
pub struct ElementPropertiesMapItemBuilder {
|
|
structure: gst::Structure,
|
|
}
|
|
|
|
impl ElementPropertiesMapItemBuilder {
|
|
// rustdoc-stripper-ignore-next
|
|
/// Sets property `property_name` to the given value `value`.
|
|
///
|
|
/// Overrides any default or previously defined value for `property_name`.
|
|
pub fn field(
|
|
mut self,
|
|
property_name: impl glib::IntoGStr,
|
|
value: impl Into<glib::Value> + Send,
|
|
) -> Self {
|
|
self.structure.set(property_name, value);
|
|
self
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Sets property `property_name` to the given value `value`.
|
|
///
|
|
/// Overrides any default or previously defined value for `property_name`.
|
|
pub fn field_with_static(
|
|
mut self,
|
|
property_name: impl AsRef<glib::GStr> + 'static,
|
|
value: impl Into<glib::Value> + Send,
|
|
) -> Self {
|
|
self.structure.set_with_static(property_name, value);
|
|
self
|
|
}
|
|
|
|
// rustdoc-stripper-ignore-next
|
|
/// Sets property `property_name` to the given value `value`.
|
|
///
|
|
/// Overrides any default or previously defined value for `property_name`.
|
|
pub fn field_with_id(
|
|
mut self,
|
|
property_name: impl AsRef<IdStr>,
|
|
value: impl Into<glib::Value> + Send,
|
|
) -> Self {
|
|
self.structure.set_with_id(property_name, value);
|
|
self
|
|
}
|
|
|
|
gst::impl_builder_gvalue_extra_setters!(field);
|
|
|
|
pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self {
|
|
self.structure.set_value(property_name, value);
|
|
self
|
|
}
|
|
|
|
pub fn field_value_with_static(
|
|
mut self,
|
|
property_name: impl AsRef<glib::GStr> + 'static,
|
|
value: glib::SendValue,
|
|
) -> Self {
|
|
self.structure.set_value_with_static(property_name, value);
|
|
self
|
|
}
|
|
|
|
pub fn field_value_with_id(
|
|
mut self,
|
|
property_name: impl AsRef<IdStr>,
|
|
value: glib::SendValue,
|
|
) -> Self {
|
|
self.structure.set_value_with_id(property_name, value);
|
|
self
|
|
}
|
|
|
|
pub fn field_value_if_some(self, property_name: &str, value: Option<glib::SendValue>) -> Self {
|
|
if let Some(value) = value {
|
|
self.field_value(property_name, value)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn field_value_with_static_if_some(
|
|
self,
|
|
property_name: impl AsRef<glib::GStr> + 'static,
|
|
value: Option<glib::SendValue>,
|
|
) -> Self {
|
|
if let Some(value) = value {
|
|
self.field_value_with_static(property_name, value)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn field_value_with_id_if_some(
|
|
self,
|
|
property_name: impl AsRef<IdStr>,
|
|
value: Option<glib::SendValue>,
|
|
) -> Self {
|
|
if let Some(value) = value {
|
|
self.field_value_with_id(property_name, value)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub fn build(self) -> ElementPropertiesMapItem {
|
|
ElementPropertiesMapItem(self.structure)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
use gst::idstr;
|
|
|
|
#[test]
|
|
fn element_properties_getters() {
|
|
gst::init().unwrap();
|
|
|
|
let elem_props_general = ElementProperties::builder_general()
|
|
.field("string-prop", "hi")
|
|
.field("boolean-prop", true)
|
|
.build();
|
|
assert!(elem_props_general.is_general());
|
|
assert!(!elem_props_general.is_map());
|
|
assert_eq!(elem_props_general.map(), None);
|
|
|
|
let elem_factory_props_map = ElementPropertiesMapItem::builder("vp8enc")
|
|
.field_with_id(idstr!("cq-level"), 13)
|
|
.field("resize-allowed", false)
|
|
.build();
|
|
let elem_props_map = ElementProperties::builder_map()
|
|
.item(elem_factory_props_map.clone())
|
|
.build();
|
|
assert!(elem_props_map.is_map());
|
|
assert!(!elem_props_map.is_general());
|
|
assert_eq!(elem_props_map.map(), Some(vec![elem_factory_props_map]));
|
|
}
|
|
|
|
#[test]
|
|
fn element_properties_general_builder() {
|
|
gst::init().unwrap();
|
|
|
|
let elem_props = ElementProperties::builder_general()
|
|
.field("string-prop", "hi")
|
|
.field("boolean-prop", true)
|
|
.build();
|
|
assert_eq!(elem_props.n_fields(), 2);
|
|
assert_eq!(elem_props.name(), "element-properties");
|
|
assert_eq!(elem_props.get::<String>("string-prop").unwrap(), "hi");
|
|
assert!(elem_props.get::<bool>("boolean-prop").unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn element_properties_map_builder() {
|
|
gst::init().unwrap();
|
|
|
|
let props_map = ElementPropertiesMapItem::builder("vp8enc")
|
|
.field("cq-level", 13)
|
|
.field("resize-allowed", false)
|
|
.build();
|
|
assert_eq!(props_map.n_fields(), 2);
|
|
assert_eq!(props_map.name(), "vp8enc");
|
|
assert_eq!(props_map.get::<i32>("cq-level").unwrap(), 13);
|
|
assert!(!props_map.get::<bool>("resize-allowed").unwrap());
|
|
|
|
let elem_props = ElementProperties::builder_map()
|
|
.item(props_map.clone())
|
|
.build();
|
|
assert_eq!(elem_props.n_fields(), 1);
|
|
|
|
let list = elem_props.map().unwrap();
|
|
assert_eq!(list.len(), 1);
|
|
assert_eq!(list.first().unwrap(), &props_map);
|
|
}
|
|
}
|