diff --git a/gstreamer-audio/src/functions.rs b/gstreamer-audio/src/functions.rs new file mode 100644 index 000000000..2cd43dfef --- /dev/null +++ b/gstreamer-audio/src/functions.rs @@ -0,0 +1,105 @@ +// Copyright (C) 2020 Guillaume Desmottes +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use glib; +use glib::ToSendValue; +use gst; + +use std::i32; + +pub fn audio_make_raw_caps( + formats: &[::AudioFormat], + layout: ::AudioLayout, +) -> gst::caps::Builder { + assert_initialized_main_thread!(); + + let formats: Vec = formats + .iter() + .map(|f| match f { + ::AudioFormat::Encoded => panic!("Invalid encoded format"), + ::AudioFormat::Unknown => panic!("Invalid unknown format"), + _ => f.to_string().to_send_value(), + }) + .collect(); + + let builder = gst::caps::Caps::builder("audio/x-raw") + .field("format", &gst::List::from_owned(formats)) + .field("rate", &gst::IntRange::::new(1, i32::MAX)) + .field("channels", &gst::IntRange::::new(1, i32::MAX)); + + match layout { + ::AudioLayout::Interleaved => builder.field("layout", &"interleaved"), + ::AudioLayout::NonInterleaved => builder.field("layout", &"non-interleaved"), + ::AudioLayout::__Unknown(_) => builder, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use gst; + + #[test] + fn audio_caps() { + gst::init().unwrap(); + + let caps = audio_make_raw_caps( + &[::AudioFormat::S16be, ::AudioFormat::S16le], + ::AudioLayout::Interleaved, + ) + .build(); + assert_eq!(caps.to_string(), "audio/x-raw, format=(string){ S16BE, S16LE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved"); + + #[cfg(feature = "v1_18")] + { + use glib::translate::{from_glib_full, ToGlib}; + + /* audio_make_raw_caps() is a re-implementation so ensure it returns the same caps as the C API */ + let c_caps = unsafe { + let formats: Vec = + [::AudioFormat::S16be, ::AudioFormat::S16le] + .iter() + .map(|f| f.to_glib()) + .collect(); + let caps = gst_audio_sys::gst_audio_make_raw_caps( + formats.as_ptr(), + formats.len() as u32, + gst_audio_sys::GST_AUDIO_LAYOUT_INTERLEAVED, + ); + from_glib_full(caps) + }; + assert_eq!(caps, c_caps); + } + + let caps = audio_make_raw_caps( + &[::AudioFormat::S16be, ::AudioFormat::S16le], + ::AudioLayout::NonInterleaved, + ) + .field("rate", &16000) + .field("channels", &2) + .build(); + assert_eq!( + caps.to_string(), + "audio/x-raw, format=(string){ S16BE, S16LE }, rate=(int)16000, channels=(int)2, layout=(string)non-interleaved" + ); + } + + #[test] + #[should_panic(expected = "Invalid encoded format")] + fn audio_caps_encoded() { + gst::init().unwrap(); + audio_make_raw_caps(&[::AudioFormat::Encoded], ::AudioLayout::Interleaved); + } + + #[test] + #[should_panic(expected = "Invalid unknown format")] + fn audio_caps_unknown() { + gst::init().unwrap(); + audio_make_raw_caps(&[::AudioFormat::Unknown], ::AudioLayout::Interleaved); + } +} diff --git a/gstreamer-audio/src/lib.rs b/gstreamer-audio/src/lib.rs index f102b99e6..357460162 100644 --- a/gstreamer-audio/src/lib.rs +++ b/gstreamer-audio/src/lib.rs @@ -53,6 +53,8 @@ mod audio_channel_position; pub use audio_channel_position::*; #[cfg(any(feature = "v1_14", feature = "dox"))] mod audio_stream_align; +mod functions; +pub use functions::*; mod audio_decoder; pub use audio_decoder::AudioDecoderExtManual;