From 59b1eead16438348b5bb2f1ae80d01f5ee6b0b9d Mon Sep 17 00:00:00 2001 From: lummax Date: Fri, 28 Aug 2015 15:36:29 +0200 Subject: [PATCH] codec: add several getters --- src/codec/audio.rs | 136 +++++++++++++++++++++++++++++++++++++ src/codec/codec.rs | 37 +++++++++- src/codec/decoder/video.rs | 1 + src/codec/mod.rs | 6 ++ src/codec/video.rs | 99 +++++++++++++++++++++++++++ 5 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 src/codec/audio.rs create mode 100644 src/codec/video.rs diff --git a/src/codec/audio.rs b/src/codec/audio.rs new file mode 100644 index 0000000..b04e535 --- /dev/null +++ b/src/codec/audio.rs @@ -0,0 +1,136 @@ +use std::ops::Deref; +use std::marker::PhantomData; + +use {ChannelLayout, format}; +use super::codec::Codec; +use ffi::*; + +pub struct Audio<'a> { + codec: &'a Codec<'a>, +} + +impl<'a> Audio<'a> { + pub unsafe fn new<'b>(codec: &'b Codec) -> Audio<'b> { + Audio { + codec: codec, + } + } +} + +impl<'a> Audio<'a> { + pub fn rates(&self) -> RateIter { + unsafe { + RateIter::new((*self.codec.as_ptr()).supported_samplerates) + } + } + + pub fn formats(&self) -> FormatIter { + unsafe { + FormatIter::new((*self.codec.as_ptr()).sample_fmts) + } + } + + pub fn channel_layouts(&self) -> ChannelLayoutIter { + unsafe { + ChannelLayoutIter::new((*self.codec.as_ptr()).channel_layouts) + } + } +} + +impl<'a> Deref for Audio<'a> { + type Target = Codec<'a>; + + fn deref(&self) -> &Self::Target { + self.codec + } +} + +pub struct RateIter<'a> { + ptr: *const i32, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> RateIter<'a> { + pub fn new(ptr: *const i32) -> Self { + RateIter { ptr: ptr, _marker: PhantomData } + } +} + +impl<'a> Iterator for RateIter<'a> { + type Item = i32; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if !self.ptr.is_null() && (*self.ptr) != 0 { + let element = self.ptr; + self.ptr = self.ptr.offset(1); + + Some((*element)) + } + else { + None + } + } + } +} + +pub struct FormatIter<'a> { + ptr: *const AVSampleFormat, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> FormatIter<'a> { + pub fn new(ptr: *const AVSampleFormat) -> Self { + FormatIter { ptr: ptr, _marker: PhantomData } + } +} + +impl<'a> Iterator for FormatIter<'a> { + type Item = format::Sample; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if !self.ptr.is_null() && (*self.ptr) != AVSampleFormat::AV_SAMPLE_FMT_NONE { + let element = self.ptr; + self.ptr = self.ptr.offset(1); + + Some((*element).into()) + } + else { + None + } + } + } +} + +pub struct ChannelLayoutIter<'a> { + ptr: *const u64, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> ChannelLayoutIter<'a> { + pub fn new(ptr: *const u64) -> Self { + ChannelLayoutIter { ptr: ptr, _marker: PhantomData } + } +} + +impl<'a> Iterator for ChannelLayoutIter<'a> { + type Item = ChannelLayout; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if !self.ptr.is_null() && (*self.ptr) != 0 { + let element = self.ptr; + self.ptr = self.ptr.offset(1); + + Some(ChannelLayout::from_bits_truncate(*element)) + } + else { + None + } + } + } +} diff --git a/src/codec/codec.rs b/src/codec/codec.rs index a5b46b7..7c294fd 100644 --- a/src/codec/codec.rs +++ b/src/codec/codec.rs @@ -3,9 +3,8 @@ use std::ffi::CStr; use std::str::from_utf8_unchecked; use ffi::*; -use super::{Id, Context}; -use ::media; -use ::Error; +use super::{Id, Context, Video, Audio}; +use ::{Error, media}; use ::codec::context::Opened; pub struct Codec<'a> { @@ -68,4 +67,36 @@ impl<'a> Codec<'a> { Id::from((*self.as_ptr()).id) } } + + pub fn video(&self) -> Result { + unsafe { + if self.medium() == media::Type::Video { + Ok(Video::new(self)) + } + else { + Err(Error::InvalidData) + } + } + } + + pub fn audio(&self) -> Result { + unsafe { + if self.medium() == media::Type::Audio { + Ok(Audio::new(self)) + } + else { + Err(Error::InvalidData) + } + } + } + + // capabilities + + pub fn max_lowres(&self) -> i32 { + unsafe { + av_codec_get_max_lowres(self.as_ptr()) + } + } + + // profiles } diff --git a/src/codec/decoder/video.rs b/src/codec/decoder/video.rs index d2b3868..8b722fa 100644 --- a/src/codec/decoder/video.rs +++ b/src/codec/decoder/video.rs @@ -149,3 +149,4 @@ impl DerefMut for Video { &mut self.0 } } + diff --git a/src/codec/mod.rs b/src/codec/mod.rs index a699ba3..c67abe5 100644 --- a/src/codec/mod.rs +++ b/src/codec/mod.rs @@ -14,6 +14,12 @@ pub use self::context::Context; pub mod codec; +pub mod video; +pub use self::video::Video; + +pub mod audio; +pub use self::audio::Audio; + pub mod field_order; pub mod audio_service; diff --git a/src/codec/video.rs b/src/codec/video.rs new file mode 100644 index 0000000..8802b2e --- /dev/null +++ b/src/codec/video.rs @@ -0,0 +1,99 @@ +use std::marker::PhantomData; +use std::ops::Deref; + +use {Rational, format}; +use super::codec::Codec; +use ffi::*; + +pub struct Video<'a> { + codec: &'a Codec<'a>, +} + +impl<'a> Video<'a> { + pub unsafe fn new<'b>(codec: &'b Codec) -> Video<'b> { + Video { + codec: codec, + } + } +} + +impl<'a> Video<'a> { + pub fn rates(&self) -> RateIter { + unsafe { + RateIter::new((*self.codec.as_ptr()).supported_framerates) + } + } + + pub fn formats(&self) -> FormatIter { + unsafe { + FormatIter::new((*self.codec.as_ptr()).pix_fmts) + } + } +} + +impl<'a> Deref for Video<'a> { + type Target = Codec<'a>; + + fn deref(&self) -> &Self::Target { + self.codec + } +} + +pub struct RateIter<'a> { + ptr: *const AVRational, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> RateIter<'a> { + pub fn new(ptr: *const AVRational) -> Self { + RateIter { ptr: ptr, _marker: PhantomData } + } +} + +impl<'a> Iterator for RateIter<'a> { + type Item = Rational; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if !self.ptr.is_null() && (*self.ptr) != (AVRational { num: 0, den: 0 }) { + let element = self.ptr; + self.ptr = self.ptr.offset(1); + + Some(Rational::from(*element)) + } else { + None + } + } + } +} + +pub struct FormatIter<'a> { + ptr: *const AVPixelFormat, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> FormatIter<'a> { + pub fn new(ptr: *const AVPixelFormat) -> Self { + FormatIter { ptr: ptr, _marker: PhantomData } + } +} + +impl<'a> Iterator for FormatIter<'a> { + type Item = format::Pixel; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if !self.ptr.is_null() && (*self.ptr) != AVPixelFormat::AV_PIX_FMT_NONE { + let element = self.ptr; + self.ptr = self.ptr.offset(1); + + Some((*element).into()) + } + else { + None + } + } + } +}