From bd4cfd56dcf25f40c891e7b0c232b90544629c7c Mon Sep 17 00:00:00 2001 From: meh Date: Tue, 12 May 2015 18:19:30 +0200 Subject: [PATCH] codec/picture: add Picture --- src/codec/mod.rs | 2 + src/codec/picture.rs | 120 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 123 insertions(+) create mode 100644 src/codec/picture.rs diff --git a/src/codec/mod.rs b/src/codec/mod.rs index d9d146a..c7ffdbd 100644 --- a/src/codec/mod.rs +++ b/src/codec/mod.rs @@ -5,6 +5,8 @@ pub mod packet; pub mod subtitle; +pub mod picture; + pub mod discard; pub mod context; diff --git a/src/codec/picture.rs b/src/codec/picture.rs new file mode 100644 index 0000000..020ed63 --- /dev/null +++ b/src/codec/picture.rs @@ -0,0 +1,120 @@ +use std::mem; +use std::marker::PhantomData; + +use libc::{c_int, size_t}; +use ffi::*; +use ::format; +use ::Error; + +pub struct Picture<'a> { + pub ptr: *mut AVPicture, + + pub format: format::Pixel, + pub width: usize, + pub height: usize, + + _own: bool, + _marker: PhantomData<&'a ()>, +} + +impl<'a> Picture<'a> { + pub fn size(format: format::Pixel, width: usize, height: usize) -> Result { + unsafe { + match avpicture_get_size(format.into(), width as c_int, height as c_int) { + v if v >= 0 => Ok(v as usize), + e => Err(Error::new(e)) + } + } + } + + pub fn new(format: format::Pixel, width: usize, height: usize) -> Result { + unsafe { + let ptr = av_malloc(mem::size_of::() as size_t) as *mut AVPicture; + + match avpicture_alloc(ptr, format.into(), width as c_int, height as c_int) { + 0 => Ok(Picture { + ptr: ptr, + + format: format, + width: width, + height: height, + + _own: true, + _marker: PhantomData + }), + + e => Err(Error::new(e)) + } + } + } + + pub fn wrap(ptr: *mut AVPicture, format: format::Pixel, width: usize, height: usize) -> Self { + Picture { + ptr: ptr, + + format: format, + width: width, + height: height, + + _own: false, + _marker: PhantomData + } + } + + pub fn layout(&self, out: &mut [u8]) -> Result { + unsafe { + match avpicture_layout(self.ptr, self.format.into(), self.width as c_int, self.height as c_int, out.as_mut_ptr(), out.len() as c_int) { + s if s >= 0 => Ok(s as usize), + e => Err(Error::new(e)) + } + } + } + + pub fn layout_as(&self, format: format::Pixel, width: usize, height: usize, out: &mut [u8]) -> Result { + unsafe { + match avpicture_layout(self.ptr, format.into(), width as c_int, height as c_int, out.as_mut_ptr(), out.len() as c_int) { + s if s >= 0 => Ok(s as usize), + e => Err(Error::new(e)) + } + } + } + + + pub fn crop(&mut self, source: &Picture, top: usize, left: usize) -> Result<(), Error> { + if self.format != source.format { + return Err(Error::new(AVERROR_BUG)); + } + + unsafe { + match av_picture_crop(self.ptr, source.ptr, self.format.into(), top as c_int, left as c_int) { + 0 => Ok(()), + e => Err(Error::new(e)) + } + } + } +} + +impl<'a> Clone for Picture<'a> { + fn clone(&self) -> Self { + let mut pic = Picture::new(self.format, self.width, self.height).unwrap(); + pic.clone_from(self); + + pic + } + + fn clone_from(&mut self, source: &Self) { + unsafe { + av_picture_copy(self.ptr, source.ptr, source.format.into(), source.width as c_int, source.height as c_int); + } + } +} + +impl<'a> Drop for Picture<'a> { + fn drop(&mut self) { + if self._own { + unsafe { + av_free(mem::transmute(self.ptr)); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 10a0a64..bedf191 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,7 @@ pub use format::stream::Stream; pub mod codec; pub use codec::packet::{self, Packet}; pub use codec::subtitle::Subtitle; +pub use codec::picture::Picture; pub use codec::discard::Discard; pub use codec::codec::Codec; pub use codec::encoder::{self, Encode};