From 72895052e6c6b501540b84b1da6d440fb3fcfafc Mon Sep 17 00:00:00 2001 From: meh Date: Mon, 1 Jun 2015 16:52:19 +0200 Subject: [PATCH] util/frame/audio: add samples accessor --- src/lib.rs | 3 +- src/util/format/sample.rs | 4 ++ src/util/frame/audio.rs | 17 +++-- src/util/mod.rs | 1 + src/util/samples.rs | 130 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 src/util/samples.rs diff --git a/src/lib.rs b/src/lib.rs index fc3e71d..65f0a72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(convert)] +#![feature(convert, core)] #![allow(raw_pointer_derive, non_camel_case_types)] extern crate libc; @@ -15,6 +15,7 @@ pub use util::color; pub use util::chroma; pub use util::time; pub use util::frame::{self, Frame}; +pub use util::samples::Samples; #[cfg(feature = "format")] pub mod format; diff --git a/src/util/format/sample.rs b/src/util/format/sample.rs index 1e04fc9..cdc0c2f 100644 --- a/src/util/format/sample.rs +++ b/src/util/format/sample.rs @@ -49,6 +49,10 @@ impl Sample { } } + pub fn is_packed(&self) -> bool { + !self.is_planar() + } + pub fn bytes(&self) -> usize { unsafe { av_get_bytes_per_sample((*self).into()) as usize diff --git a/src/util/frame/audio.rs b/src/util/frame/audio.rs index dca5d30..dea03b5 100644 --- a/src/util/frame/audio.rs +++ b/src/util/frame/audio.rs @@ -3,6 +3,7 @@ use std::mem; use std::ops::{Deref, DerefMut}; use ffi::*; +use ::Samples; use ::util::format; use super::Frame; @@ -21,7 +22,7 @@ impl Audio { let mut frame = Audio::empty(); frame.set_format(format); - frame.set_samples(samples); + frame.set_sample_number(samples); frame.set_channel_layout(layout); av_frame_get_buffer(frame.ptr, 1); @@ -83,17 +84,25 @@ impl Audio { } } - pub fn samples(&self) -> usize { + pub fn sample_number(&self) -> usize { unsafe { (*self.ptr).nb_samples as usize } } - pub fn set_samples(&mut self, value: usize) { + pub fn set_sample_number(&mut self, value: usize) { unsafe { (*self.ptr).nb_samples = value as c_int; } } + + pub fn samples(&self) -> Samples { + Samples::wrap(self.ptr as *mut AVPicture, self.format(), self.sample_number(), self.channels()) + } + + pub fn samples_mut(&mut self) -> Samples { + Samples::wrap(self.ptr as *mut AVPicture, self.format(), self.sample_number(), self.channels()) + } } unsafe impl Send for Audio { } @@ -114,7 +123,7 @@ impl DerefMut for Audio { impl Clone for Audio { fn clone(&self) -> Self { - let mut cloned = Audio::new(self.format(), self.samples(), self.channel_layout()); + let mut cloned = Audio::new(self.format(), self.sample_number(), self.channel_layout()); cloned.clone_from(self); cloned diff --git a/src/util/mod.rs b/src/util/mod.rs index 67c3ca8..57b979a 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -8,6 +8,7 @@ pub mod format; pub mod frame; pub mod chroma; pub mod time; +pub mod samples; use std::ffi::CStr; use std::str::from_utf8_unchecked; diff --git a/src/util/samples.rs b/src/util/samples.rs new file mode 100644 index 0000000..373c991 --- /dev/null +++ b/src/util/samples.rs @@ -0,0 +1,130 @@ +use std::slice; +use std::mem; +use std::any::TypeId; +use std::marker::{Reflect, PhantomData}; + +use ffi::*; +use ::util::format::Sample; +use ::Error; + +pub struct Samples<'a> { + pub ptr: *mut AVPicture, + + format: Sample, + number: usize, + channels: u16, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Samples<'a> { + pub fn wrap(ptr: *mut AVPicture, format: Sample, number: usize, channels: u16) -> Self { + Samples { + ptr: ptr, + + format: format, + number: number, + channels: channels, + + _marker: PhantomData, + } + } + + pub fn format(&self) -> Sample { + self.format + } + + pub fn number(&self) -> usize { + self.number + } + + pub fn channels(&self) -> u16 { + self.channels + } + + pub fn is_planar(&self) -> bool { + self.format.is_planar() + } + + pub fn is_packed(&self) -> bool { + self.format.is_planar() + } + + pub fn data(&self) -> Result, Error> { + if !valid::(self.format) { + return Err(Error::InvalidData) + } + + let mut result = Vec::new(); + + unsafe { + let size = (*self.ptr).linesize[0]; + + if self.is_planar() { + for i in 0 .. self.channels { + result.push(slice::from_raw_parts( + mem::transmute((*self.ptr).data[i as usize]), + size as usize / mem::size_of::())); + } + } + else { + result.push(slice::from_raw_parts( + mem::transmute((*self.ptr).data[0]), + size as usize / mem::size_of::())); + } + } + + Ok(result) + } + + pub fn data_mut(&mut self) -> Result, Error> { + if !valid::(self.format) { + return Err(Error::InvalidData) + } + + let mut result = Vec::new(); + + unsafe { + let size = (*self.ptr).linesize[0]; + + if self.is_planar() { + for i in 0 .. self.channels { + result.push(slice::from_raw_parts_mut( + mem::transmute((*self.ptr).data[i as usize]), + size as usize / mem::size_of::())); + } + } + else { + result.push(slice::from_raw_parts_mut( + mem::transmute((*self.ptr).data[0]), + size as usize / mem::size_of::())); + } + } + + Ok(result) + } +} + +pub fn valid(format: Sample) -> bool { + match format { + Sample::None => + false, + + Sample::U8 | Sample::U8P if TypeId::of::() != TypeId::of::() => + false, + + Sample::S16 | Sample::S16P if TypeId::of::() != TypeId::of::() => + false, + + Sample::S32 | Sample::S32P if TypeId::of::() != TypeId::of::() => + false, + + Sample::FLT | Sample::FLTP if TypeId::of::() != TypeId::of::() => + false, + + Sample::DBL | Sample::DBLP if TypeId::of::() != TypeId::of::() => + false, + + _ => true + } +}