util/frame: add Frame, frame::Video and frame::Audio

This commit is contained in:
meh 2015-05-12 03:25:29 +02:00
parent 1a9ca7a4a0
commit 2ff14a2043
4 changed files with 372 additions and 2 deletions

View File

@ -12,5 +12,4 @@ pub use util::rational::Rational;
pub use util::color_space::ColorSpace; pub use util::color_space::ColorSpace;
pub use util::color_range::ColorRange; pub use util::color_range::ColorRange;
pub use util::media; pub use util::media;
pub use util::sample_format::SampleFormat; pub use util::frame::{self, Frame};
pub use util::pixel_format::PixelFormat;

273
src/util/frame/mod.rs Normal file
View File

@ -0,0 +1,273 @@
pub mod side_data;
pub use self::side_data::SideData;
use libc::c_int;
use std::ptr;
use std::mem;
use std::ops::Deref;
use ffi::*;
use ::{Dictionary, ColorSpace, ColorRange};
use ::util::pixel_format::PixelFormat;
use ::util::sample_format::SampleFormat;
pub struct Packet {
pub duration: isize,
pub position: isize,
pub size: usize,
}
pub struct Frame {
pub ptr: *mut AVFrame,
}
impl Frame {
pub fn new() -> Self {
unsafe {
Frame { ptr: av_frame_alloc() }
}
}
pub fn make_unique(&mut self) -> &mut Self {
unsafe {
av_frame_make_writable(self.ptr);
}
self
}
pub fn is_unique(&self) -> bool {
unsafe {
av_frame_is_writable(self.ptr) == 0
}
}
pub fn is_key(&self) -> bool {
unsafe {
(*self.ptr).key_frame == 1
}
}
pub fn packet(&self) -> Packet {
unsafe {
Packet {
duration: av_frame_get_pkt_duration(self.ptr) as isize,
position: av_frame_get_pkt_pos(self.ptr) as isize,
size: av_frame_get_pkt_size(self.ptr) as usize,
}
}
}
pub fn best_effort_timestamp(&self) -> isize {
unsafe {
av_frame_get_best_effort_timestamp(self.ptr) as isize
}
}
pub fn metadata<'a>(&'a self) -> Dictionary<'a> {
unsafe {
Dictionary::wrap(av_frame_get_metadata(self.ptr))
}
}
pub fn set_metadata(&mut self, mut value: Dictionary) {
unsafe {
av_frame_set_metadata(self.ptr, value.take());
}
}
pub fn side_data<'a>(&'a self, kind: side_data::Type) -> Option<SideData<'a>> {
unsafe {
let ptr = av_frame_get_side_data(self.ptr, kind.into());
if ptr == ptr::null_mut() {
None
}
else {
Some(SideData::wrap(ptr))
}
}
}
pub fn new_side_data<'a>(&'a mut self, kind: side_data::Type, size: usize) -> Option<SideData<'a>> {
unsafe {
let ptr = av_frame_new_side_data(self.ptr, kind.into(), size as c_int);
if ptr == ptr::null_mut() {
None
}
else {
Some(SideData::wrap(ptr))
}
}
}
pub fn remove_side_data(&mut self, kind: side_data::Type) {
unsafe {
av_frame_remove_side_data(self.ptr, kind.into());
}
}
}
impl Clone for Frame {
fn clone(&self) -> Self {
unsafe {
Frame { ptr: av_frame_clone(self.ptr) }
}
}
fn clone_from(&mut self, source: &Self) {
unsafe {
av_frame_copy(self.ptr, source.ptr);
av_frame_copy_props(self.ptr, source.ptr);
}
}
}
impl Drop for Frame {
fn drop(&mut self) {
unsafe {
av_frame_free(&mut self.ptr);
}
}
}
pub struct Audio(Frame);
impl Audio {
pub fn new() -> Self {
Audio(Frame::new())
}
pub fn format(&self) -> SampleFormat {
unsafe {
SampleFormat::from(mem::transmute::<_, AVSampleFormat>(((*self.ptr).format)))
}
}
pub fn channel_layout(&self) -> i64 {
unsafe {
av_frame_get_channel_layout(self.0.ptr)
}
}
pub fn set_channel_layout(&mut self, value: i64) {
unsafe {
av_frame_set_channel_layout(self.0.ptr, value);
}
}
pub fn channels(&self) -> usize {
unsafe {
av_frame_get_channels(self.0.ptr) as usize
}
}
pub fn set_channels(&mut self, value: usize) {
unsafe {
av_frame_set_channels(self.0.ptr, value as c_int);
}
}
pub fn sample_rate(&self) -> i32 {
unsafe {
av_frame_get_sample_rate(self.0.ptr)
}
}
pub fn set_sample_rate(&mut self, value: i32) {
unsafe {
av_frame_set_sample_rate(self.0.ptr, value);
}
}
}
impl Deref for Audio {
type Target = Frame;
fn deref(&self) -> &Frame {
&self.0
}
}
impl Into<Frame> for Audio {
fn into(self) -> Frame {
self.0
}
}
impl Into<Audio> for Frame {
fn into(self) -> Audio {
Audio(self)
}
}
pub struct Video(Frame);
impl Deref for Video {
type Target = Frame;
fn deref(&self) -> &Frame {
&self.0
}
}
impl Video {
pub fn new() -> Self {
Video(Frame::new())
}
pub fn format(&self) -> PixelFormat {
unsafe {
PixelFormat::from(mem::transmute::<_, AVPixelFormat>(((*self.ptr).format)))
}
}
pub fn width(&self) -> usize {
unsafe {
(*self.0.ptr).width as usize
}
}
pub fn height(&self) -> usize {
unsafe {
(*self.0.ptr).height as usize
}
}
pub fn color_space(&self) -> ColorSpace {
unsafe {
ColorSpace::from(av_frame_get_colorspace(self.0.ptr))
}
}
pub fn set_color_space(&mut self, value: ColorSpace) {
unsafe {
av_frame_set_colorspace(self.0.ptr, value.into());
}
}
pub fn color_range(&self) -> ColorRange {
unsafe {
ColorRange::from(av_frame_get_color_range(self.0.ptr))
}
}
pub fn set_color_range(&mut self, value: ColorRange) {
unsafe {
av_frame_set_color_range(self.0.ptr, value.into());
}
}
}
impl Into<Video> for Frame {
fn into(self) -> Video {
Video(self)
}
}
impl Into<Frame> for Video {
fn into(self) -> Frame {
self.0
}
}

View File

@ -0,0 +1,97 @@
use std::marker::PhantomData;
use std::slice;
use std::ffi::CStr;
use std::str::from_utf8_unchecked;
use ffi::*;
use super::Frame;
use ::Dictionary;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Type {
PanScan,
A53CC,
Stereo3D,
MatrixEncoding,
DownMixInfo,
ReplayGain,
DisplayMatrix,
AFD,
MotionVectors,
SkipSamples,
AudioServiceType,
}
impl Type {
pub fn name(&self) -> &'static str {
unsafe {
from_utf8_unchecked(CStr::from_ptr(av_frame_side_data_name((*self).into())).to_bytes())
}
}
}
impl From<AVFrameSideDataType> for Type {
fn from(value: AVFrameSideDataType) -> Self {
match value {
AV_FRAME_DATA_PANSCAN => Type::PanScan,
AV_FRAME_DATA_A53_CC => Type::A53CC,
AV_FRAME_DATA_STEREO3D => Type::Stereo3D,
AV_FRAME_DATA_MATRIXENCODING => Type::MatrixEncoding,
AV_FRAME_DATA_DOWNMIX_INFO => Type::DownMixInfo,
AV_FRAME_DATA_REPLAYGAIN => Type::ReplayGain,
AV_FRAME_DATA_DISPLAYMATRIX => Type::DisplayMatrix,
AV_FRAME_DATA_AFD => Type::AFD,
AV_FRAME_DATA_MOTION_VECTORS => Type::MotionVectors,
AV_FRAME_DATA_SKIP_SAMPLES => Type::SkipSamples,
AV_FRAME_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType
}
}
}
impl Into<AVFrameSideDataType> for Type {
fn into(self) -> AVFrameSideDataType {
match self {
Type::PanScan => AV_FRAME_DATA_PANSCAN,
Type::A53CC => AV_FRAME_DATA_A53_CC,
Type::Stereo3D => AV_FRAME_DATA_STEREO3D,
Type::MatrixEncoding => AV_FRAME_DATA_MATRIXENCODING,
Type::DownMixInfo => AV_FRAME_DATA_DOWNMIX_INFO,
Type::ReplayGain => AV_FRAME_DATA_REPLAYGAIN,
Type::DisplayMatrix => AV_FRAME_DATA_DISPLAYMATRIX,
Type::AFD => AV_FRAME_DATA_AFD,
Type::MotionVectors => AV_FRAME_DATA_MOTION_VECTORS,
Type::SkipSamples => AV_FRAME_DATA_SKIP_SAMPLES,
Type::AudioServiceType => AV_FRAME_DATA_AUDIO_SERVICE_TYPE
}
}
}
pub struct SideData<'a> {
pub ptr: *mut AVFrameSideData,
_marker: PhantomData<&'a Frame>,
}
impl<'a> SideData<'a> {
pub fn wrap(ptr: *mut AVFrameSideData) -> Self {
SideData { ptr: ptr, _marker: PhantomData }
}
pub fn kind(&self) -> Type {
unsafe {
Type::from((*self.ptr).kind)
}
}
pub fn data(&'a self) -> &'a [u8] {
unsafe {
slice::from_raw_parts((*self.ptr).data, (*self.ptr).size as usize)
}
}
pub fn metadata(&'a self) -> Dictionary<'a> {
unsafe {
Dictionary::wrap((*self.ptr).metadata)
}
}
}

View File

@ -6,6 +6,7 @@ pub mod color_space;
pub mod color_range; pub mod color_range;
pub mod sample_format; pub mod sample_format;
pub mod pixel_format; pub mod pixel_format;
pub mod frame;
use std::ffi::CStr; use std::ffi::CStr;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;