Add bindings for various audio channel position functions

This commit is contained in:
Sebastian Dröge 2017-08-10 14:39:57 +03:00
parent 8215770076
commit e1538b6ca5
6 changed files with 364 additions and 37 deletions

25
Cargo.lock generated
View file

@ -2,6 +2,7 @@
name = "gstreamer-audio" name = "gstreamer-audio"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"array-init 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.1.3 (git+https://github.com/gtk-rs/glib)", "glib 0.1.3 (git+https://github.com/gtk-rs/glib)",
"glib-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", "glib-sys 0.3.4 (git+https://github.com/gtk-rs/sys)",
@ -13,6 +14,14 @@ dependencies = [
"rustdoc-stripper 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustdoc-stripper 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "array-init"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "atk-sys" name = "atk-sys"
version = "0.3.4" version = "0.3.4"
@ -465,6 +474,14 @@ dependencies = [
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "nodrop"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.35" version = "0.1.35"
@ -487,6 +504,11 @@ name = "num-traits"
version = "0.1.40" version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "odds"
version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "pango" name = "pango"
version = "0.1.3" version = "0.1.3"
@ -582,6 +604,7 @@ dependencies = [
] ]
[metadata] [metadata]
"checksum array-init 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3b508d35216892b50a135fb52c9bb90f04a97b7782230805dff1a156ad5469"
"checksum atk-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "<none>" "checksum atk-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "<none>"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
@ -621,9 +644,11 @@ dependencies = [
"checksum mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "dbd91d3bfbceb13897065e97b2ef177a09a438cb33612b2d371bf568819a9313" "checksum mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "dbd91d3bfbceb13897065e97b2ef177a09a438cb33612b2d371bf568819a9313"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "94101fd932816f97eb9a5116f6c1a11511a1fed7db21c5ccd823b2dc11abf566" "checksum net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "94101fd932816f97eb9a5116f6c1a11511a1fed7db21c5ccd823b2dc11abf566"
"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2"
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
"checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790" "checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790"
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba"
"checksum pango 0.1.3 (git+https://github.com/gtk-rs/pango)" = "<none>" "checksum pango 0.1.3 (git+https://github.com/gtk-rs/pango)" = "<none>"
"checksum pango-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "<none>" "checksum pango-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "<none>"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"

View file

@ -19,6 +19,7 @@ gstreamer-sys = { version = "0.1.1", git = "https://github.com/sdroege/gstreamer
gstreamer-audio-sys = { version = "0.1.1", git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] } gstreamer-audio-sys = { version = "0.1.1", git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] }
glib = { version = "0.1.3", git = "https://github.com/gtk-rs/glib" } glib = { version = "0.1.3", git = "https://github.com/gtk-rs/glib" }
gstreamer = { version = "0.1.0", path = "../gstreamer" } gstreamer = { version = "0.1.0", path = "../gstreamer" }
array-init = "0.0"
[build-dependencies.rustdoc-stripper] [build-dependencies.rustdoc-stripper]
version = "0.1" version = "0.1"

View file

@ -0,0 +1,288 @@
// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ffi;
use AudioChannelPosition;
use std::mem;
use gst;
use gst::MiniObject;
use glib;
use glib::translate::{from_glib, ToGlib};
use array_init;
impl AudioChannelPosition {
pub fn to_mask(&self) -> u64 {
unsafe {
let val = mem::transmute::<ffi::GstAudioChannelPosition, u32>(self.to_glib());
1 << val
}
}
pub fn positions_to_mask(positions: &[AudioChannelPosition], force_order: bool) -> Option<u64> {
let len = positions.len();
if len > 64 {
return None;
}
let positions_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
positions[i].to_glib()
});
unsafe {
let mut mask = mem::uninitialized();
let valid: bool = from_glib(ffi::gst_audio_channel_positions_to_mask(
positions_raw.as_ptr() as *mut _,
len as i32,
force_order.to_glib(),
&mut mask,
));
if valid {
Some(mask)
} else {
None
}
}
}
pub fn positions_from_mask(
mask: u64,
positions: &mut [AudioChannelPosition],
) -> Result<(), glib::BoolError> {
if positions.len() > 64 {
return Err(glib::BoolError("Invalid number of channels"));
}
let len = positions.len();
let mut positions_raw: [ffi::GstAudioChannelPosition; 64] =
[ffi::GstAudioChannelPosition::Invalid; 64];
let valid: bool = unsafe {
from_glib(ffi::gst_audio_channel_positions_from_mask(
len as i32,
mask,
positions_raw.as_mut_ptr(),
))
};
if valid {
for (d, s) in positions.iter_mut().zip(positions_raw.iter()) {
*d = from_glib(*s);
}
Ok(())
} else {
Err(glib::BoolError(
"Couldn't convert channel positions to mask",
))
}
}
pub fn positions_to_valid_order(
positions: &mut [AudioChannelPosition],
) -> Result<(), glib::BoolError> {
if positions.len() > 64 {
return Err(glib::BoolError("Invalid number of channels"));
}
let len = positions.len();
let mut positions_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
positions[i].to_glib()
});
let valid: bool = unsafe {
from_glib(ffi::gst_audio_channel_positions_to_valid_order(
positions_raw.as_mut_ptr(),
len as i32,
))
};
if valid {
for (d, s) in positions.iter_mut().zip(positions_raw.iter()) {
*d = from_glib(*s);
}
Ok(())
} else {
Err(glib::BoolError(
"Couldn't convert channel positions to mask",
))
}
}
pub fn get_fallback_mask(channels: u32) -> u64 {
unsafe { ffi::gst_audio_channel_get_fallback_mask(channels as i32) }
}
pub fn check_valid_channel_positions(
positions: &[::AudioChannelPosition],
force_order: bool,
) -> bool {
if positions.len() > 64 {
return false;
}
let len = positions.len();
let positions_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
positions[i].to_glib()
});
unsafe {
from_glib(ffi::gst_audio_check_valid_channel_positions(
positions_raw.as_ptr() as *mut _,
len as i32,
force_order.to_glib(),
))
}
}
}
pub fn buffer_reorder_channels(
buffer: &mut gst::BufferRef,
format: ::AudioFormat,
channels: u32,
from: &[AudioChannelPosition],
to: &[AudioChannelPosition],
) -> Result<(), glib::BoolError> {
if from.len() != to.len() || from.len() > 64 {
return Err(glib::BoolError("Invalid number of channels"));
}
let from_len = from.len();
let to_len = to.len();
let from_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= from_len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
from[i].to_glib()
});
let to_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= to_len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
to[i].to_glib()
});
let valid: bool = unsafe {
from_glib(ffi::gst_audio_buffer_reorder_channels(
buffer.as_mut_ptr(),
format.to_glib(),
channels as i32,
from_raw.as_ptr() as *mut _,
to_raw.as_ptr() as *mut _,
))
};
if valid {
Ok(())
} else {
Err(glib::BoolError("Failed to reorder channels"))
}
}
pub fn reorder_channels(
data: &mut [u8],
format: ::AudioFormat,
channels: u32,
from: &[AudioChannelPosition],
to: &[AudioChannelPosition],
) -> Result<(), glib::BoolError> {
if from.len() != to.len() || from.len() > 64 {
return Err(glib::BoolError("Invalid number of channels"));
}
let from_len = from.len();
let to_len = to.len();
let from_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= from_len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
from[i].to_glib()
});
let to_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= to_len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
to[i].to_glib()
});
let valid: bool = unsafe {
from_glib(ffi::gst_audio_reorder_channels(
data.as_mut_ptr() as *mut _,
data.len(),
format.to_glib(),
channels as i32,
from_raw.as_ptr() as *mut _,
to_raw.as_ptr() as *mut _,
))
};
if valid {
Ok(())
} else {
Err(glib::BoolError("Failed to reorder channels"))
}
}
pub fn get_channel_reorder_map(
from: &[AudioChannelPosition],
to: &[AudioChannelPosition],
reorder_map: &mut [usize],
) -> Result<(), glib::BoolError> {
if from.len() != to.len() || from.len() != reorder_map.len() || from.len() > 64 {
return Err(glib::BoolError("Invalid number of channels"));
}
let from_len = from.len();
let to_len = to.len();
let from_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= from_len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
from[i].to_glib()
});
let to_raw: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= to_len as usize {
ffi::GstAudioChannelPosition::Invalid
} else {
to[i].to_glib()
});
let mut reorder_map_raw = [0i32, 64];
let valid: bool = unsafe {
from_glib(ffi::gst_audio_get_channel_reorder_map(
from_len as i32,
from_raw.as_ptr() as *mut _,
to_raw.as_ptr() as *mut _,
reorder_map_raw.as_mut_ptr(),
))
};
if valid {
for (d, s) in reorder_map.iter_mut().zip(reorder_map_raw.iter()) {
*d = *s as usize;
}
Ok(())
} else {
Err(glib::BoolError("Failed to reorder channels"))
}
}

View file

@ -19,7 +19,9 @@ use glib::translate::{from_glib, from_glib_full, from_glib_none, FromGlibPtrNone
use std::mem; use std::mem;
use std::ptr; use std::ptr;
pub struct AudioInfo(ffi::GstAudioInfo); use array_init;
pub struct AudioInfo(ffi::GstAudioInfo, [::AudioChannelPosition; 64]);
pub struct AudioInfoBuilder<'a> { pub struct AudioInfoBuilder<'a> {
format: ::AudioFormat, format: ::AudioFormat,
@ -34,21 +36,21 @@ impl<'a> AudioInfoBuilder<'a> {
pub fn build(self) -> Option<AudioInfo> { pub fn build(self) -> Option<AudioInfo> {
unsafe { unsafe {
let mut info = mem::uninitialized(); let mut info = mem::uninitialized();
let mut positions_raw = Vec::new();
let positions_ptr = match self.positions { let positions = if let Some(p) = self.positions {
Some(p) => { if p.len() != self.channels as usize || p.len() > 64 {
if p.len() != self.channels as usize {
return None; return None;
} }
positions_raw.reserve(self.channels as usize); let positions: [ffi::GstAudioChannelPosition; 64] =
for i in p { array_init::array_init_copy(|i| if i >= self.channels as usize {
positions_raw.push(i.to_glib()); ffi::GstAudioChannelPosition::Invalid
} } else {
p[i].to_glib()
});
let valid: bool = from_glib(ffi::gst_audio_check_valid_channel_positions( let valid: bool = from_glib(ffi::gst_audio_check_valid_channel_positions(
positions_raw.as_mut_ptr(), positions.as_ptr() as *mut _,
self.channels as i32, self.channels as i32,
true.to_glib(), true.to_glib(),
)); ));
@ -56,11 +58,15 @@ impl<'a> AudioInfoBuilder<'a> {
return None; return None;
} }
positions_raw.as_ptr() Some(positions)
} } else {
None => ptr::null(), None
}; };
let positions_ptr = positions
.as_ref()
.map(|p| p.as_ptr())
.unwrap_or(ptr::null());
ffi::gst_audio_info_set_format( ffi::gst_audio_info_set_format(
&mut info, &mut info,
@ -82,7 +88,8 @@ impl<'a> AudioInfoBuilder<'a> {
info.layout = layout.to_glib(); info.layout = layout.to_glib();
} }
Some(AudioInfo(info)) let positions = array_init::array_init_copy(|i| from_glib(info.position[i]));
Some(AudioInfo(info, positions))
} }
} }
@ -124,7 +131,8 @@ impl AudioInfo {
unsafe { unsafe {
let mut info = mem::uninitialized(); let mut info = mem::uninitialized();
if from_glib(ffi::gst_audio_info_from_caps(&mut info, caps.as_ptr())) { if from_glib(ffi::gst_audio_info_from_caps(&mut info, caps.as_ptr())) {
Some(AudioInfo(info)) let positions = array_init::array_init_copy(|i| from_glib(info.position[i]));
Some(AudioInfo(info, positions))
} else { } else {
None None
} }
@ -228,13 +236,12 @@ impl AudioInfo {
self.format_info().is_signed() self.format_info().is_signed()
} }
pub fn positions(&self) -> Vec<::AudioChannelPosition> { pub fn positions(&self) -> Option<&[::AudioChannelPosition]> {
let mut v = Vec::with_capacity(self.0.channels as usize); if self.0.channels > 64 || self.is_unpositioned() {
for i in 0..(self.0.channels as usize) { return None;
v.push(from_glib(self.0.position[i]));
} }
v Some(&self.1[0..(self.0.channels as usize)])
} }
pub fn is_unpositioned(&self) -> bool { pub fn is_unpositioned(&self) -> bool {
@ -244,7 +251,7 @@ impl AudioInfo {
impl Clone for AudioInfo { impl Clone for AudioInfo {
fn clone(&self) -> Self { fn clone(&self) -> Self {
unsafe { AudioInfo(ptr::read(&self.0)) } unsafe { AudioInfo(ptr::read(&self.0), self.1) }
} }
} }
@ -322,7 +329,10 @@ impl<'a> glib::translate::ToGlibPtr<'a, *const ffi::GstAudioInfo> for AudioInfo
impl glib::translate::FromGlibPtrNone<*mut ffi::GstAudioInfo> for AudioInfo { impl glib::translate::FromGlibPtrNone<*mut ffi::GstAudioInfo> for AudioInfo {
#[inline] #[inline]
unsafe fn from_glib_none(ptr: *mut ffi::GstAudioInfo) -> Self { unsafe fn from_glib_none(ptr: *mut ffi::GstAudioInfo) -> Self {
AudioInfo(ptr::read(ptr)) AudioInfo(
ptr::read(ptr),
array_init::array_init_copy(|i| from_glib((*ptr).position[i])),
)
} }
} }
@ -352,7 +362,7 @@ mod tests {
assert_eq!(info.rate(), 48000); assert_eq!(info.rate(), 48000);
assert_eq!(info.channels(), 2); assert_eq!(info.channels(), 2);
assert_eq!( assert_eq!(
&info.positions(), &info.positions().unwrap(),
&[ &[
::AudioChannelPosition::FrontLeft, ::AudioChannelPosition::FrontLeft,
::AudioChannelPosition::FrontRight ::AudioChannelPosition::FrontRight
@ -371,7 +381,7 @@ mod tests {
assert_eq!(info.rate(), 48000); assert_eq!(info.rate(), 48000);
assert_eq!(info.channels(), 2); assert_eq!(info.channels(), 2);
assert_eq!( assert_eq!(
&info.positions(), &info.positions().unwrap(),
&[ &[
::AudioChannelPosition::RearLeft, ::AudioChannelPosition::RearLeft,
::AudioChannelPosition::RearRight ::AudioChannelPosition::RearRight
@ -398,7 +408,7 @@ mod tests {
assert_eq!(info.rate(), 48000); assert_eq!(info.rate(), 48000);
assert_eq!(info.channels(), 2); assert_eq!(info.channels(), 2);
assert_eq!( assert_eq!(
&info.positions(), &info.positions().unwrap(),
&[ &[
::AudioChannelPosition::FrontLeft, ::AudioChannelPosition::FrontLeft,
::AudioChannelPosition::FrontRight ::AudioChannelPosition::FrontRight

View file

@ -9,6 +9,7 @@
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
extern crate libc; extern crate libc;
extern crate array_init;
extern crate glib_sys as glib_ffi; extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi; extern crate gobject_sys as gobject_ffi;
@ -46,3 +47,5 @@ mod audio_format_info;
pub use audio_format_info::*; pub use audio_format_info::*;
mod audio_info; mod audio_info;
pub use audio_info::*; pub use audio_info::*;
mod audio_channel_position;
pub use audio_channel_position::*;

View file

@ -53,7 +53,7 @@ pub use auto::traits::*;
pub use auto::functions::{parse_bin_from_description, parse_launch}; pub use auto::functions::{parse_bin_from_description, parse_launch};
pub mod miniobject; pub mod miniobject;
pub use miniobject::GstRc; pub use miniobject::{GstRc, MiniObject};
pub mod message; pub mod message;
pub use message::{Message, MessageRef, MessageView}; pub use message::{Message, MessageRef, MessageView};
pub mod structure; pub mod structure;