audio: implement Iterator on AudioFormat

Also add AUDIO_FORMATS_ALL as public API.
This commit is contained in:
Guillaume Desmottes 2020-05-28 12:57:35 +02:00 committed by Sebastian Dröge
parent 3ceb870790
commit d5cab61c93
3 changed files with 199 additions and 0 deletions

View file

@ -24,6 +24,7 @@ glib = { git = "https://github.com/gtk-rs/glib" }
gstreamer = { path = "../gstreamer" }
gstreamer-base = { path = "../gstreamer-base" }
array-init = "0.1"
once_cell = "1.0"
[build-dependencies]
rustdoc-stripper = { version = "0.1", optional = true }

View file

@ -13,6 +13,55 @@ use std::fmt;
use std::str;
use glib::translate::{from_glib, FromGlib, ToGlib, ToGlibPtr};
use once_cell::sync::Lazy;
#[cfg(feature = "v1_18")]
pub static AUDIO_FORMATS_ALL: Lazy<Box<[::AudioFormat]>> = Lazy::new(|| unsafe {
let mut len: u32 = 0;
let mut res = Vec::with_capacity(len as usize);
let formats = gst_audio_sys::gst_audio_formats_raw(&mut len);
for i in 0..len {
let format = formats.offset(i as isize);
res.push(from_glib(*format));
}
res.into_boxed_slice()
});
#[cfg(not(feature = "v1_18"))]
pub static AUDIO_FORMATS_ALL: Lazy<Box<[::AudioFormat]>> = Lazy::new(|| {
Box::new([
::AudioFormat::S8,
::AudioFormat::U8,
::AudioFormat::S16le,
::AudioFormat::S16be,
::AudioFormat::U16le,
::AudioFormat::U16be,
::AudioFormat::S2432le,
::AudioFormat::S2432be,
::AudioFormat::U2432le,
::AudioFormat::U2432be,
::AudioFormat::S32le,
::AudioFormat::S32be,
::AudioFormat::U32le,
::AudioFormat::U32be,
::AudioFormat::S24le,
::AudioFormat::S24be,
::AudioFormat::U24le,
::AudioFormat::U24be,
::AudioFormat::S20le,
::AudioFormat::S20be,
::AudioFormat::U20le,
::AudioFormat::U20be,
::AudioFormat::S18le,
::AudioFormat::S18be,
::AudioFormat::U18le,
::AudioFormat::U18be,
::AudioFormat::F32le,
::AudioFormat::F32be,
::AudioFormat::F64le,
::AudioFormat::F64be,
])
});
impl ::AudioFormat {
pub fn build_integer(
@ -44,6 +93,10 @@ impl ::AudioFormat {
.unwrap()
}
}
pub fn iter_raw() -> AudioFormatIterator {
AudioFormatIterator::default()
}
}
impl str::FromStr for ::AudioFormat {
@ -134,6 +187,99 @@ pub const AUDIO_FORMAT_F32: ::AudioFormat = ::AudioFormat::F32le;
#[cfg(target_endian = "little")]
pub const AUDIO_FORMAT_F64: ::AudioFormat = ::AudioFormat::F64le;
pub struct AudioFormatIterator {
idx: usize,
len: usize,
}
impl Default for AudioFormatIterator {
fn default() -> Self {
Self {
idx: 0,
len: AUDIO_FORMATS_ALL.len(),
}
}
}
impl Iterator for AudioFormatIterator {
type Item = ::AudioFormat;
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.len {
None
} else {
let fmt = AUDIO_FORMATS_ALL[self.idx];
self.idx += 1;
Some(fmt)
}
}
}
impl ExactSizeIterator for AudioFormatIterator {
fn len(&self) -> usize {
self.len
}
}
impl DoubleEndedIterator for AudioFormatIterator {
fn next_back(&mut self) -> Option<Self::Item> {
if self.idx >= self.len {
None
} else {
let fmt = AUDIO_FORMATS_ALL[self.len - 1];
self.len -= 1;
Some(fmt)
}
}
}
pub trait AudioFormatIteratorExt {
fn into_audio_caps(
self,
layout: ::AudioLayout,
) -> Option<gst::caps::Builder<gst::caps::NoFeature>>;
}
impl<T> AudioFormatIteratorExt for T
where
T: Iterator<Item = ::AudioFormat>,
{
fn into_audio_caps(
self,
layout: ::AudioLayout,
) -> Option<gst::caps::Builder<gst::caps::NoFeature>> {
let formats: Vec<::AudioFormat> = self.collect();
if !formats.is_empty() {
Some(::functions::audio_make_raw_caps(&formats, layout))
} else {
None
}
}
}
pub trait AudioFormatIteratorExtRef {
fn into_audio_caps(
self,
layout: ::AudioLayout,
) -> Option<gst::caps::Builder<gst::caps::NoFeature>>;
}
impl<'a, T> AudioFormatIteratorExtRef for T
where
T: Iterator<Item = &'a ::AudioFormat>,
{
fn into_audio_caps(
self,
layout: ::AudioLayout,
) -> Option<gst::caps::Builder<gst::caps::NoFeature>> {
let formats: Vec<::AudioFormat> = self.copied().collect();
if !formats.is_empty() {
Some(::functions::audio_make_raw_caps(&formats, layout))
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use gst;
@ -144,4 +290,55 @@ mod tests {
format!("{}", ::AudioFormat::S16be);
}
#[test]
fn iter() {
use super::*;
gst::init().unwrap();
assert!(::AudioFormat::iter_raw().count() > 0);
assert_eq!(
::AudioFormat::iter_raw().count(),
::AudioFormat::iter_raw().len()
);
let mut i = ::AudioFormat::iter_raw();
let mut count = 0;
loop {
if i.next().is_none() {
break;
}
count += 1;
if i.next_back().is_none() {
break;
}
count += 1;
}
assert_eq!(count, ::AudioFormat::iter_raw().len());
assert!(::AudioFormat::iter_raw().any(|f| f == ::AudioFormat::F64be));
assert!(::AudioFormat::iter_raw()
.find(|f| *f == ::AudioFormat::Encoded)
.is_none());
let caps = ::AudioFormat::iter_raw().into_audio_caps(::AudioLayout::Interleaved);
assert!(caps.is_some());
let caps = ::AudioFormat::iter_raw()
.filter(|f| ::AudioFormatInfo::from_format(*f).is_little_endian())
.into_audio_caps(::AudioLayout::Interleaved);
assert!(caps.is_some());
let caps = ::AudioFormat::iter_raw()
.skip(1000)
.into_audio_caps(::AudioLayout::Interleaved);
assert!(caps.is_none());
let caps = [::AudioFormat::S16le, ::AudioFormat::S16be]
.iter()
.into_audio_caps(::AudioLayout::Interleaved)
.unwrap()
.build();
assert_eq!(caps.to_string(), "audio/x-raw, format=(string){ S16LE, S16BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved");
}
}

View file

@ -9,6 +9,7 @@
extern crate array_init;
#[macro_use]
extern crate bitflags;
extern crate once_cell;
#[macro_use]
extern crate glib;