From 67a2c60a3304481e3bcc16ae786c511315dfba1b Mon Sep 17 00:00:00 2001 From: meh Date: Fri, 4 Sep 2015 16:34:02 +0200 Subject: [PATCH] util/option: add some basic options handling --- src/lib.rs | 1 + src/util/mod.rs | 1 + src/util/option/mod.rs | 76 +++++++++++++++++++++++++ src/util/option/traits.rs | 114 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 src/util/option/mod.rs create mode 100644 src/util/option/traits.rs diff --git a/src/lib.rs b/src/lib.rs index b8688d6..9a34395 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ pub use util::chroma; pub use util::time; pub use util::frame::{self, Frame}; pub use util::channel_layout::{self, ChannelLayout}; +pub use util::option; #[cfg(feature = "format")] pub mod format; diff --git a/src/util/mod.rs b/src/util/mod.rs index e6666ff..fbfc70f 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -9,6 +9,7 @@ pub mod frame; pub mod chroma; pub mod time; pub mod channel_layout; +pub mod option; use std::ffi::CStr; use std::str::from_utf8_unchecked; diff --git a/src/util/option/mod.rs b/src/util/option/mod.rs new file mode 100644 index 0000000..266017c --- /dev/null +++ b/src/util/option/mod.rs @@ -0,0 +1,76 @@ +mod traits; +pub use self::traits::{Target, Settable, Gettable, Iterable}; + +use ffi::*; + +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum Type { + Flags, + Int, + Int64, + Double, + Float, + String, + Rational, + Binary, + Dictionary, + Constant, + + ImageSize, + PixelFormat, + SampleFormat, + VideoRate, + Duration, + Color, + ChannelLayout, +} + +impl From for Type { + fn from(value: AVOptionType) -> Self { + match value { + AV_OPT_TYPE_FLAGS => Type::Flags, + AV_OPT_TYPE_INT => Type::Int, + AV_OPT_TYPE_INT64 => Type::Int64, + AV_OPT_TYPE_DOUBLE => Type::Double, + AV_OPT_TYPE_FLOAT => Type::Float, + AV_OPT_TYPE_STRING => Type::String, + AV_OPT_TYPE_RATIONAL => Type::Rational, + AV_OPT_TYPE_BINARY => Type::Binary, + AV_OPT_TYPE_DICT => Type::Dictionary, + AV_OPT_TYPE_CONST => Type::Constant, + + AV_OPT_TYPE_IMAGE_SIZE => Type::ImageSize, + AV_OPT_TYPE_PIXEL_FMT => Type::PixelFormat, + AV_OPT_TYPE_SAMPLE_FMT => Type::SampleFormat, + AV_OPT_TYPE_VIDEO_RATE => Type::VideoRate, + AV_OPT_TYPE_DURATION => Type::Duration, + AV_OPT_TYPE_COLOR => Type::Color, + AV_OPT_TYPE_CHANNEL_LAYOUT => Type::ChannelLayout, + } + } +} + +impl Into for Type { + fn into(self) -> AVOptionType { + match self { + Type::Flags => AV_OPT_TYPE_FLAGS, + Type::Int => AV_OPT_TYPE_INT, + Type::Int64 => AV_OPT_TYPE_INT64, + Type::Double => AV_OPT_TYPE_DOUBLE, + Type::Float => AV_OPT_TYPE_FLOAT, + Type::String => AV_OPT_TYPE_STRING, + Type::Rational => AV_OPT_TYPE_RATIONAL, + Type::Binary => AV_OPT_TYPE_BINARY, + Type::Dictionary => AV_OPT_TYPE_DICT, + Type::Constant => AV_OPT_TYPE_CONST, + + Type::ImageSize => AV_OPT_TYPE_IMAGE_SIZE, + Type::PixelFormat => AV_OPT_TYPE_PIXEL_FMT, + Type::SampleFormat => AV_OPT_TYPE_SAMPLE_FMT, + Type::VideoRate => AV_OPT_TYPE_VIDEO_RATE, + Type::Duration => AV_OPT_TYPE_DURATION, + Type::Color => AV_OPT_TYPE_COLOR, + Type::ChannelLayout => AV_OPT_TYPE_CHANNEL_LAYOUT, + } + } +} diff --git a/src/util/option/traits.rs b/src/util/option/traits.rs new file mode 100644 index 0000000..6e4f195 --- /dev/null +++ b/src/util/option/traits.rs @@ -0,0 +1,114 @@ +//! NOTE: this will be much better once specialization comes + +use std::mem; +use std::ffi::CString; + +use ffi::*; +use libc::{c_void, c_int, int64_t}; +use ::{Error, Rational, ChannelLayout}; +use util::format; + +macro_rules! check { + ($expr:expr) => ( + match $expr { + 0 => Ok(()), + e => Err(Error::from(e)), + } + ) +} + +pub unsafe trait Target { + fn as_ptr(&self) -> *const c_void; + fn as_mut_ptr(&mut self) -> *mut c_void; +} + +pub trait Settable: Target { + fn set(&mut self, name: &str, value: &T) -> Result<(), Error> { + unsafe { + check!(av_opt_set_bin(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + value as *const _ as *const _, mem::size_of::() as c_int, + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_str(&mut self, name: &str, value: &str) -> Result<(), Error> { + unsafe { + check!(av_opt_set(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + CString::new(value).unwrap().as_ptr(), + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_int(&mut self, name: &str, value: i64) -> Result<(), Error> { + unsafe { + check!(av_opt_set_int(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + value as int64_t, + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_double(&mut self, name: &str, value: f64) -> Result<(), Error> { + unsafe { + check!(av_opt_set_double(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + value, + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_rational>(&mut self, name: &str, value: T) -> Result<(), Error> { + unsafe { + check!(av_opt_set_q(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + value.into().into(), + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_image_size(&mut self, name: &str, w: u32, h: u32) -> Result<(), Error> { + unsafe { + check!(av_opt_set_image_size(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + w as c_int, h as c_int, + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_pixel_format(&mut self, name: &str, format: format::Pixel) -> Result<(), Error> { + unsafe { + check!(av_opt_set_pixel_fmt(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + format.into(), + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_sample_format(&mut self, name: &str, format: format::Sample) -> Result<(), Error> { + unsafe { + check!(av_opt_set_sample_fmt(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + format.into(), + AV_OPT_SEARCH_CHILDREN)) + } + } + + fn set_channel_layout(&mut self, name: &str, layout: ChannelLayout) -> Result<(), Error> { + unsafe { + check!(av_opt_set_channel_layout(self.as_mut_ptr(), + CString::new(name).unwrap().as_ptr(), + layout.bits() as int64_t, + AV_OPT_SEARCH_CHILDREN)) + } + } +} + +pub trait Gettable: Target { + +} + +pub trait Iterable: Target { + +}