diff --git a/src/codec/codec.rs b/src/codec/codec.rs index 3fa2248..da49104 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, Video, Audio, Capabilities, Profile}; +use super::{Id, Video, Audio, Capabilities, Profile}; use ::{Error, media}; -use ::codec::context::Opened; pub struct Codec<'a> { ptr: *mut AVCodec, @@ -28,10 +27,6 @@ impl<'a> Codec<'a> { } impl<'a> Codec<'a> { - pub fn open(&self) -> Result { - Context::new().open(self) - } - pub fn is_encoder(&self) -> bool { unsafe { av_codec_is_encoder(self.as_ptr()) != 0 diff --git a/src/codec/context.rs b/src/codec/context.rs index 75abcae..760d37b 100644 --- a/src/codec/context.rs +++ b/src/codec/context.rs @@ -1,10 +1,9 @@ -use std::ops::{Deref, DerefMut}; use std::ptr; use libc::c_int; use ffi::*; use ::media; -use ::{Error, Codec, Dictionary}; +use ::Codec; use super::{Id, Debug, Compliance, threading}; use super::decoder::Decoder; use super::encoder::Encoder; @@ -38,40 +37,12 @@ impl Context { } } - pub fn open(mut self, codec: &Codec) -> Result { - unsafe { - match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) { - 0 => Ok(Opened(self)), - e => Err(Error::from(e)) - } - } + pub fn decoder(self) -> Decoder { + Decoder(self) } - pub fn open_with(mut self, codec: &Codec, options: Dictionary) -> Result { - unsafe { - match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut options.take()) { - 0 => Ok(Opened(self)), - e => Err(Error::from(e)) - } - } - } - - pub fn decoder(&self) -> Result { - if let Some(ref codec) = super::decoder::find(self.id()) { - self.clone().open(codec).and_then(|c| c.decoder()) - } - else { - Err(Error::DecoderNotFound) - } - } - - pub fn encoder(&self) -> Result { - if let Some(ref codec) = super::encoder::find(self.id()) { - self.clone().open(codec).and_then(|c| c.encoder()) - } - else { - Err(Error::EncoderNotFound) - } + pub fn encoder(self) -> Encoder { + Encoder(self) } pub fn codec(&self) -> Option { @@ -164,59 +135,3 @@ impl Clone for Context { } } } - -pub struct Opened(pub Context); - -impl Opened { - pub fn decoder(self) -> Result { - let mut valid = false; - - if let Some(codec) = self.codec() { - valid = codec.is_decoder(); - } - - if valid { - Ok(Decoder(self)) - } - else { - Err(Error::InvalidData) - } - } - - pub fn encoder(self) -> Result { - let mut valid = false; - - if let Some(codec) = self.codec() { - valid = codec.is_encoder(); - } - - if valid { - Ok(Encoder(self)) - } - else { - Err(Error::InvalidData) - } - } -} - -impl Drop for Opened { - fn drop(&mut self) { - unsafe { - avcodec_close(self.as_mut_ptr()); - } - } -} - -impl Deref for Opened { - type Target = Context; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -impl DerefMut for Opened { - fn deref_mut(&mut self) -> &mut::Target { - &mut self.0 - } -} diff --git a/src/codec/decoder/audio.rs b/src/codec/decoder/audio.rs index 7b0eb2d..120ead1 100644 --- a/src/codec/decoder/audio.rs +++ b/src/codec/decoder/audio.rs @@ -3,12 +3,12 @@ use std::ops::{Deref, DerefMut}; use libc::c_int; use ffi::*; -use super::Decoder; +use super::Opened; use ::{Packet, Error, AudioService, ChannelLayout}; use ::frame; use ::util::format; -pub struct Audio(pub Decoder); +pub struct Audio(pub Opened); impl Audio { pub fn decode(&mut self, packet: &Packet, out: &mut frame::Audio) -> Result { @@ -99,7 +99,7 @@ impl Audio { } impl Deref for Audio { - type Target = Decoder; + type Target = Opened; fn deref(&self) -> &::Target { &self.0 diff --git a/src/codec/decoder/mod.rs b/src/codec/decoder/mod.rs index a3ed368..f02e78f 100644 --- a/src/codec/decoder/mod.rs +++ b/src/codec/decoder/mod.rs @@ -15,110 +15,78 @@ pub use self::conceal::Conceal; pub mod check; pub use self::check::Check; +pub mod opened; +pub use self::opened::Opened; + +use std::ptr; use std::ffi::CString; -use std::slice::from_raw_parts; use std::ops::{Deref, DerefMut}; use ffi::*; -use super::{Id, Profile}; -use super::context::Opened; -use ::{Codec, Error, Discard, Rational}; -use ::media; +use super::{Id, Context}; +use ::{Codec, Error, Dictionary}; -pub struct Decoder(pub Opened); +pub struct Decoder(pub Context); impl Decoder { + pub fn open(mut self, codec: &Codec) -> Result { + unsafe { + if codec.is_decoder() { + match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) { + 0 => Ok(Opened(self)), + e => Err(Error::from(e)) + } + } + else { + Err(Error::InvalidData) + } + } + } + + pub fn open_with(mut self, codec: &Codec, options: Dictionary) -> Result { + unsafe { + if codec.is_decoder() { + match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut options.take()) { + 0 => Ok(Opened(self)), + e => Err(Error::from(e)) + } + } + else { + Err(Error::InvalidData) + } + } + } + pub fn video(self) -> Result { - if self.medium() == media::Type::Video { - Ok(Video(self)) + if let Some(ref codec) = find(self.id()) { + self.open(codec).and_then(|o| o.video()) } else { - Err(Error::InvalidData) + Err(Error::DecoderNotFound) } } pub fn audio(self) -> Result { - if self.medium() == media::Type::Audio { - Ok(Audio(self)) + if let Some(ref codec) = find(self.id()) { + self.open(codec).and_then(|o| o.audio()) } else { - Err(Error::InvalidData) + Err(Error::DecoderNotFound) } } pub fn subtitle(self) -> Result { - if self.medium() == media::Type::Subtitle { - Ok(Subtitle(self)) + if let Some(ref codec) = find(self.id()) { + self.open(codec).and_then(|o| o.subtitle()) } else { - Err(Error::InvalidData) - } - } - - pub fn conceal(&mut self, value: Conceal) { - unsafe { - (*self.as_mut_ptr()).error_concealment = value.bits(); - } - } - - pub fn check(&mut self, value: Check) { - unsafe { - (*self.as_mut_ptr()).err_recognition = value.bits(); - } - } - - pub fn profile(&self) -> Profile { - unsafe { - Profile::from((self.id(), (*self.as_ptr()).profile)) - } - } - - pub fn skip_loop_filter(&mut self, value: Discard) { - unsafe { - (*self.as_mut_ptr()).skip_loop_filter = value.into(); - } - } - - pub fn skip_idct(&mut self, value: Discard) { - unsafe { - (*self.as_mut_ptr()).skip_idct = value.into(); - } - } - - pub fn skip_frame(&mut self, value: Discard) { - unsafe { - (*self.as_mut_ptr()).skip_frame = value.into(); - } - } - - pub fn subtitle_header(&self) -> &[u8] { - unsafe { - from_raw_parts((*self.as_ptr()).subtitle_header, (*self.as_ptr()).subtitle_header_size as usize) - } - } - - pub fn frame_rate(&self) -> Option { - unsafe { - let value = (*self.as_ptr()).framerate; - - if value == (AVRational { num: 0, den: 1 }) { - None - } - else { - Some(Rational::from(value)) - } - } - } - - pub fn time_base(&self) -> Rational { - unsafe { - Rational::from((*self.as_ptr()).time_base) + Err(Error::DecoderNotFound) } } } impl Deref for Decoder { - type Target = Opened; + type Target = Context; fn deref(&self) -> &::Target { &self.0 diff --git a/src/codec/decoder/opened.rs b/src/codec/decoder/opened.rs new file mode 100644 index 0000000..4228331 --- /dev/null +++ b/src/codec/decoder/opened.rs @@ -0,0 +1,122 @@ +use std::ops::{Deref, DerefMut}; +use std::slice::from_raw_parts; + +use ffi::*; +use super::{Conceal, Check, Video, Audio, Subtitle, Decoder}; +use ::codec::Profile; +use ::{Error, Discard, Rational}; +use ::media; + +pub struct Opened(pub Decoder); + +impl Opened { + pub fn video(self) -> Result { + if self.medium() == media::Type::Video { + Ok(Video(self)) + } + else { + Err(Error::InvalidData) + } + } + + pub fn audio(self) -> Result { + if self.medium() == media::Type::Audio { + Ok(Audio(self)) + } + else { + Err(Error::InvalidData) + } + } + + pub fn subtitle(self) -> Result { + if self.medium() == media::Type::Subtitle { + Ok(Subtitle(self)) + } + else { + Err(Error::InvalidData) + } + } + + pub fn conceal(&mut self, value: Conceal) { + unsafe { + (*self.as_mut_ptr()).error_concealment = value.bits(); + } + } + + pub fn check(&mut self, value: Check) { + unsafe { + (*self.as_mut_ptr()).err_recognition = value.bits(); + } + } + + pub fn profile(&self) -> Profile { + unsafe { + Profile::from((self.id(), (*self.as_ptr()).profile)) + } + } + + pub fn skip_loop_filter(&mut self, value: Discard) { + unsafe { + (*self.as_mut_ptr()).skip_loop_filter = value.into(); + } + } + + pub fn skip_idct(&mut self, value: Discard) { + unsafe { + (*self.as_mut_ptr()).skip_idct = value.into(); + } + } + + pub fn skip_frame(&mut self, value: Discard) { + unsafe { + (*self.as_mut_ptr()).skip_frame = value.into(); + } + } + + pub fn subtitle_header(&self) -> &[u8] { + unsafe { + from_raw_parts((*self.as_ptr()).subtitle_header, (*self.as_ptr()).subtitle_header_size as usize) + } + } + + pub fn frame_rate(&self) -> Option { + unsafe { + let value = (*self.as_ptr()).framerate; + + if value == (AVRational { num: 0, den: 1 }) { + None + } + else { + Some(Rational::from(value)) + } + } + } + + pub fn time_base(&self) -> Rational { + unsafe { + Rational::from((*self.as_ptr()).time_base) + } + } +} + +impl Drop for Opened { + fn drop(&mut self) { + unsafe { + avcodec_close(self.as_mut_ptr()); + } + } +} + +impl Deref for Opened { + type Target = Decoder; + + fn deref(&self) -> &::Target { + &self.0 + } +} + +impl DerefMut for Opened { + fn deref_mut(&mut self) -> &mut::Target { + &mut self.0 + } +} diff --git a/src/codec/decoder/subtitle.rs b/src/codec/decoder/subtitle.rs index b6bc0c5..db378d9 100644 --- a/src/codec/decoder/subtitle.rs +++ b/src/codec/decoder/subtitle.rs @@ -3,10 +3,10 @@ use std::ops::{Deref, DerefMut}; use libc::c_int; use ffi::*; -use super::Decoder; +use super::Opened; use ::{Packet, Error}; -pub struct Subtitle(pub Decoder); +pub struct Subtitle(pub Opened); impl Subtitle { pub fn decode(&mut self, packet: &Packet, out: &mut ::Subtitle) -> Result { @@ -22,7 +22,7 @@ impl Subtitle { } impl Deref for Subtitle { - type Target = Decoder; + type Target = Opened; fn deref(&self) -> &::Target { &self.0 diff --git a/src/codec/decoder/video.rs b/src/codec/decoder/video.rs index 8b722fa..47d1cf5 100644 --- a/src/codec/decoder/video.rs +++ b/src/codec/decoder/video.rs @@ -3,14 +3,14 @@ use std::ops::{Deref, DerefMut}; use libc::c_int; use ffi::*; -use super::{Decoder, slice}; +use super::{Opened, slice}; use ::{Packet, Error, Rational, FieldOrder}; use ::frame; use ::util::format; use ::util::chroma; use ::color; -pub struct Video(pub Decoder); +pub struct Video(pub Opened); impl Video { pub fn decode(&mut self, packet: &Packet, out: &mut frame::Video) -> Result { @@ -137,7 +137,7 @@ impl Video { } impl Deref for Video { - type Target = Decoder; + type Target = Opened; fn deref(&self) -> &::Target { &self.0 diff --git a/src/codec/encoder/mod.rs b/src/codec/encoder/mod.rs index e964f63..17148eb 100644 --- a/src/codec/encoder/mod.rs +++ b/src/codec/encoder/mod.rs @@ -24,12 +24,11 @@ use std::ops::{Deref, DerefMut}; use libc::c_int; use ffi::*; -use super::Id; -use super::context::Opened; +use super::{Id, Context}; use ::{Codec, Error, Rational}; use ::media; -pub struct Encoder(pub Opened); +pub struct Encoder(pub Context); impl Encoder { pub fn video(self) -> Result { @@ -108,7 +107,7 @@ impl Encoder { } impl Deref for Encoder { - type Target = Opened; + type Target = Context; fn deref(&self) -> &::Target { &self.0