From 757088f46c5eef08ada9706c25b94b2d091c9d72 Mon Sep 17 00:00:00 2001 From: meh Date: Sat, 16 May 2015 17:28:25 +0200 Subject: [PATCH] codec: refactor decoder and encoder --- src/codec/decoder.rs | 145 ---------------------------------- src/codec/decoder/audio.rs | 107 +++++++++++++++++++++++++ src/codec/decoder/conceal.rs | 10 +++ src/codec/decoder/mod.rs | 94 ++++++++++++++++++++++ src/codec/decoder/slice.rs | 10 +++ src/codec/decoder/subtitle.rs | 30 +++++++ src/codec/decoder/video.rs | 141 +++++++++++++++++++++++++++++++++ src/codec/encoder.rs | 143 --------------------------------- src/codec/encoder/audio.rs | 31 ++++++++ src/codec/encoder/mod.rs | 83 +++++++++++++++++++ src/codec/encoder/subtitle.rs | 28 +++++++ src/codec/encoder/video.rs | 31 ++++++++ src/lib.rs | 2 + 13 files changed, 567 insertions(+), 288 deletions(-) delete mode 100644 src/codec/decoder.rs create mode 100644 src/codec/decoder/audio.rs create mode 100644 src/codec/decoder/conceal.rs create mode 100644 src/codec/decoder/mod.rs create mode 100644 src/codec/decoder/slice.rs create mode 100644 src/codec/decoder/subtitle.rs create mode 100644 src/codec/decoder/video.rs delete mode 100644 src/codec/encoder.rs create mode 100644 src/codec/encoder/audio.rs create mode 100644 src/codec/encoder/mod.rs create mode 100644 src/codec/encoder/subtitle.rs create mode 100644 src/codec/encoder/video.rs diff --git a/src/codec/decoder.rs b/src/codec/decoder.rs deleted file mode 100644 index fc9bed0..0000000 --- a/src/codec/decoder.rs +++ /dev/null @@ -1,145 +0,0 @@ -use std::ffi::CString; -use std::ptr; -use std::ops::Deref; - -use libc::c_int; -use ffi::*; -use super::Id; -use super::context::Opened; -use ::{Codec, Packet, Error}; -use ::frame; -use ::media; - -pub struct Decoder(pub Opened); - -impl Decoder { - pub fn video(self) -> Result { - if self.medium() == media::Type::Video { - Ok(Video(self)) - } - else { - Err(Error::from(AVERROR_INVALIDDATA)) - } - } - - pub fn audio(self) -> Result { - if self.medium() == media::Type::Audio { - Ok(Audio(self)) - } - else { - Err(Error::from(AVERROR_INVALIDDATA)) - } - } - - pub fn subtitle(self) -> Result { - if self.medium() == media::Type::Subtitle { - Ok(Subtitle(self)) - } - else { - Err(Error::from(AVERROR_INVALIDDATA)) - } - } -} - -impl Deref for Decoder { - type Target = Opened; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub struct Video(pub Decoder); - -impl Video { - pub fn decode(&self, packet: &Packet, out: &mut frame::Video) -> Result { - unsafe { - let mut got: c_int = 0; - - match avcodec_decode_video2(self.ptr, out.ptr, &mut got, &packet.val) { - e if e < 0 => Err(Error::new(e)), - _ => Ok(got != 0) - } - } - } -} - -impl Deref for Video { - type Target = Decoder; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub struct Audio(pub Decoder); - -impl Audio { - pub fn decode(&self, packet: &Packet, out: &mut frame::Audio) -> Result { - unsafe { - let mut got: c_int = 0; - - match avcodec_decode_audio4(self.ptr, out.ptr, &mut got, &packet.val) { - e if e < 0 => Err(Error::new(e)), - _ => Ok(got != 0) - } - } - } -} - -impl Deref for Audio { - type Target = Decoder; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub struct Subtitle(pub Decoder); - -impl Subtitle { - pub fn decode(&self, packet: &Packet, out: &mut ::Subtitle) -> Result { - unsafe { - let mut got: c_int = 0; - - match avcodec_decode_subtitle2(self.ptr, &mut out.val, &mut got, &packet.val) { - e if e < 0 => Err(Error::new(e)), - _ => Ok(got != 0) - } - } - } -} - -impl Deref for Subtitle { - type Target = Decoder; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub fn find(id: Id) -> Option> { - unsafe { - let ptr = avcodec_find_decoder(id.into()); - - if ptr == ptr::null_mut() { - None - } - else { - Some(Codec::wrap(ptr)) - } - } -} - -pub fn find_by_name(name: &str) -> Option> { - unsafe { - let ptr = avcodec_find_decoder_by_name(CString::new(name).unwrap().as_ptr()); - - if ptr == ptr::null_mut() { - None - } - else { - Some(Codec::wrap(ptr)) - } - } -} diff --git a/src/codec/decoder/audio.rs b/src/codec/decoder/audio.rs new file mode 100644 index 0000000..b1dbb90 --- /dev/null +++ b/src/codec/decoder/audio.rs @@ -0,0 +1,107 @@ +use std::ops::Deref; + +use libc::c_int; +use ffi::*; + +use super::Decoder; +use ::{Packet, Error, AudioService}; +use ::frame; +use ::util::format; + +pub struct Audio(pub Decoder); + +impl Audio { + pub fn decode(&mut self, packet: &Packet, out: &mut frame::Audio) -> Result { + unsafe { + let mut got: c_int = 0; + + match avcodec_decode_audio4(self.ptr, out.ptr, &mut got, &packet.val) { + e if e < 0 => Err(Error::new(e)), + _ => Ok(got != 0) + } + } + } + + pub fn rate(&self) -> i32 { + unsafe { + (*self.ptr).sample_rate as i32 + } + } + + pub fn channels(&self) -> usize { + unsafe { + (*self.ptr).channels as usize + } + } + + pub fn format(&self) -> format::Sample { + unsafe { + format::Sample::from((*self.ptr).sample_fmt) + } + } + + pub fn request_format(&mut self, value: format::Sample) { + unsafe { + (*self.ptr).request_sample_fmt = value.into(); + } + } + + pub fn frames(&self) -> usize { + unsafe { + (*self.ptr).frame_number as usize + } + } + + pub fn align(&self) -> usize { + unsafe { + (*self.ptr).block_align as usize + } + } + + pub fn channel_layout(&self) -> u64 { + unsafe { + (*self.ptr).channel_layout + } + } + + pub fn set_channel_layout(&mut self, value: u64) { + unsafe { + (*self.ptr).channel_layout = value; + } + } + + pub fn request_channel_layout(&mut self, value: u64) { + unsafe { + (*self.ptr).request_channel_layout = value; + } + } + + pub fn audio_service(&mut self) -> AudioService { + unsafe { + AudioService::from((*self.ptr).audio_service_type) + } + } + + pub fn max_rate(&self) -> usize { + unsafe { + (*self.ptr).rc_max_rate as usize + } + } + + pub fn frame_start(&self) -> Option { + unsafe { + match (*self.ptr).timecode_frame_start { + -1 => None, + n => Some(n as usize) + } + } + } +} + +impl Deref for Audio { + type Target = Decoder; + + fn deref(&self) -> &::Target { + &self.0 + } +} diff --git a/src/codec/decoder/conceal.rs b/src/codec/decoder/conceal.rs new file mode 100644 index 0000000..d7c97ce --- /dev/null +++ b/src/codec/decoder/conceal.rs @@ -0,0 +1,10 @@ +use libc::c_int; +use ffi::*; + +bitflags! { + flags Conceal: c_int { + const CONCEAL_GUESS_MVS = FF_EC_GUESS_MVS, + const CONCEAL_DEBLOCK = FF_EC_DEBLOCK, + const CONCEAL_FAVOR_INTER = FF_EC_FAVOR_INTER, + } +} diff --git a/src/codec/decoder/mod.rs b/src/codec/decoder/mod.rs new file mode 100644 index 0000000..8eaa006 --- /dev/null +++ b/src/codec/decoder/mod.rs @@ -0,0 +1,94 @@ +pub mod video; +pub use self::video::Video; + +pub mod audio; +pub use self::audio::Audio; + +pub mod subtitle; +pub use self::subtitle::Subtitle; + +pub mod slice; + +pub mod conceal; +pub use self::conceal::*; + +use std::ffi::CString; +use std::ptr; +use std::ops::Deref; + +use ffi::*; +use super::Id; +use super::context::Opened; +use ::{Codec, Error}; +use ::media; + +pub struct Decoder(pub Opened); + +impl Decoder { + pub fn video(self) -> Result { + if self.medium() == media::Type::Video { + Ok(Video(self)) + } + else { + Err(Error::from(AVERROR_INVALIDDATA)) + } + } + + pub fn audio(self) -> Result { + if self.medium() == media::Type::Audio { + Ok(Audio(self)) + } + else { + Err(Error::from(AVERROR_INVALIDDATA)) + } + } + + pub fn subtitle(self) -> Result { + if self.medium() == media::Type::Subtitle { + Ok(Subtitle(self)) + } + else { + Err(Error::from(AVERROR_INVALIDDATA)) + } + } + + pub fn conceal(&mut self, value: Conceal) { + unsafe { + (*self.ptr).error_concealment = value.bits(); + } + } +} + +impl Deref for Decoder { + type Target = Opened; + + fn deref(&self) -> &::Target { + &self.0 + } +} + +pub fn find(id: Id) -> Option> { + unsafe { + let ptr = avcodec_find_decoder(id.into()); + + if ptr == ptr::null_mut() { + None + } + else { + Some(Codec::wrap(ptr)) + } + } +} + +pub fn find_by_name(name: &str) -> Option> { + unsafe { + let ptr = avcodec_find_decoder_by_name(CString::new(name).unwrap().as_ptr()); + + if ptr == ptr::null_mut() { + None + } + else { + Some(Codec::wrap(ptr)) + } + } +} diff --git a/src/codec/decoder/slice.rs b/src/codec/decoder/slice.rs new file mode 100644 index 0000000..0274f3d --- /dev/null +++ b/src/codec/decoder/slice.rs @@ -0,0 +1,10 @@ +use libc::c_int; +use ffi::*; + +bitflags! { + flags Flags: c_int { + const FLAG_CODED_ORDER = SLICE_FLAG_CODED_ORDER, + const FLAG_ALLOW_FIELD = SLICE_FLAG_ALLOW_FIELD, + const FLAG_ALLOW_PLANE = SLICE_FLAG_ALLOW_PLANE, + } +} diff --git a/src/codec/decoder/subtitle.rs b/src/codec/decoder/subtitle.rs new file mode 100644 index 0000000..88a5190 --- /dev/null +++ b/src/codec/decoder/subtitle.rs @@ -0,0 +1,30 @@ +use std::ops::Deref; + +use libc::c_int; +use ffi::*; + +use super::Decoder; +use ::{Packet, Error}; + +pub struct Subtitle(pub Decoder); + +impl Subtitle { + pub fn decode(&mut self, packet: &Packet, out: &mut ::Subtitle) -> Result { + unsafe { + let mut got: c_int = 0; + + match avcodec_decode_subtitle2(self.ptr, &mut out.val, &mut got, &packet.val) { + e if e < 0 => Err(Error::new(e)), + _ => Ok(got != 0) + } + } + } +} + +impl Deref for Subtitle { + type Target = Decoder; + + fn deref(&self) -> &::Target { + &self.0 + } +} diff --git a/src/codec/decoder/video.rs b/src/codec/decoder/video.rs new file mode 100644 index 0000000..bf36ca3 --- /dev/null +++ b/src/codec/decoder/video.rs @@ -0,0 +1,141 @@ +use std::ops::Deref; + +use libc::c_int; +use ffi::*; + +use super::{Decoder, slice}; +use ::{Packet, Error, Rational, FieldOrder}; +use ::frame; +use ::util::format; +use ::util::chroma; +use ::color; + +pub struct Video(pub Decoder); + +impl Video { + pub fn decode(&mut self, packet: &Packet, out: &mut frame::Video) -> Result { + unsafe { + let mut got: c_int = 0; + + match avcodec_decode_video2(self.ptr, out.ptr, &mut got, &packet.val) { + e if e < 0 => Err(Error::new(e)), + _ => Ok(got != 0) + } + } + } + + pub fn width(&self) -> usize { + unsafe { + (*self.ptr).width as usize + } + } + + pub fn height(&self) -> usize { + unsafe { + (*self.ptr).height as usize + } + } + + pub fn format(&self) -> format::Pixel { + unsafe { + format::Pixel::from((*self.ptr).pix_fmt) + } + } + + pub fn set_format(&mut self, value: format::Pixel) { + unsafe { + (*self.ptr).pix_fmt = value.into(); + } + } + + pub fn has_b_frames(&self) -> bool { + unsafe { + (*self.ptr).has_b_frames != 0 + } + } + + pub fn aspect_ratio(&self) -> Rational { + unsafe { + Rational((*self.ptr).sample_aspect_ratio) + } + } + + pub fn color_space(&self) -> color::Space { + unsafe { + color::Space::from((*self.ptr).colorspace) + } + } + + pub fn color_range(&self) -> color::Range { + unsafe { + color::Range::from((*self.ptr).color_range) + } + } + + pub fn color_primaries(&self) -> color::Primaries { + unsafe { + color::Primaries::from((*self.ptr).color_primaries) + } + } + + pub fn color_transfer_characteristic(&self) -> color::TransferCharacteristic { + unsafe { + color::TransferCharacteristic::from((*self.ptr).color_trc) + } + } + + pub fn chroma_location(&self) -> chroma::Location { + unsafe { + chroma::Location::from((*self.ptr).chroma_sample_location) + } + } + + pub fn set_slice_count(&mut self, value: usize) { + unsafe { + (*self.ptr).slice_count = value as c_int; + } + } + + pub fn set_slice_flags(&mut self, value: slice::Flags) { + unsafe { + (*self.ptr).slice_flags = value.bits(); + } + } + + pub fn skip_top(&mut self, value: usize) { + unsafe { + (*self.ptr).skip_top = value as c_int; + } + } + + pub fn skip_bottom(&mut self, value: usize) { + unsafe { + (*self.ptr).skip_bottom = value as c_int; + } + } + + pub fn references(&self) -> usize { + unsafe { + (*self.ptr).refs as usize + } + } + + pub fn set_field_order(&mut self, value: FieldOrder) { + unsafe { + (*self.ptr).field_order = value.into(); + } + } + + // intra_matrix + // inter_matrix +} + +impl Deref for Video { + type Target = Decoder; + + fn deref(&self) -> &::Target { + &self.0 + } +} + + diff --git a/src/codec/encoder.rs b/src/codec/encoder.rs deleted file mode 100644 index 8bab6bf..0000000 --- a/src/codec/encoder.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::ffi::CString; -use std::ptr; -use std::ops::Deref; - -use libc::c_int; -use ffi::*; -use super::Id; -use super::context::Opened; -use ::{Codec, Packet, Error}; -use ::frame; -use ::media; - -pub struct Encoder(pub Opened); - -impl Encoder { - pub fn video(self) -> Result { - if self.medium() == media::Type::Video { - Ok(Video(self)) - } - else { - Err(Error::from(AVERROR_INVALIDDATA)) - } - } - - pub fn audio(self) -> Result { - if self.medium() == media::Type::Audio { - Ok(Audio(self)) - } - else { - Err(Error::from(AVERROR_INVALIDDATA)) - } - } - - pub fn subtitle(self) -> Result { - if self.medium() == media::Type::Subtitle { - Ok(Subtitle(self)) - } - else { - Err(Error::from(AVERROR_INVALIDDATA)) - } - } -} - -impl Deref for Encoder { - type Target = Opened; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub struct Video(pub Encoder); - -impl Video { - pub fn encode(&self, frame: &frame::Video, out: &mut Packet) -> Result { - unsafe { - let mut got: c_int = 0; - - match avcodec_encode_video2(self.ptr, &mut out.val, frame.ptr, &mut got) { - e if e < 0 => Err(Error::new(e)), - _ => Ok(got != 0) - } - } - } -} - -impl Deref for Video { - type Target = Encoder; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub struct Audio(pub Encoder); - -impl Audio { - pub fn encode(&self, frame: &frame::Audio, out: &mut Packet) -> Result { - unsafe { - let mut got: c_int = 0; - - match avcodec_encode_audio2(self.ptr, &mut out.val, frame.ptr, &mut got) { - e if e < 0 => Err(Error::new(e)), - _ => Ok(got != 0) - } - } - } -} - -impl Deref for Audio { - type Target = Encoder; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub struct Subtitle(pub Encoder); - -impl Subtitle { - pub fn encode(&self, subtitle: &::Subtitle, out: &mut [u8]) -> Result { - unsafe { - match avcodec_encode_subtitle(self.ptr, out.as_mut_ptr(), out.len() as c_int, &subtitle.val) { - e if e < 0 => Err(Error::new(e)), - _ => Ok(true) - } - } - } -} - -impl Deref for Subtitle { - type Target = Encoder; - - fn deref(&self) -> &::Target { - &self.0 - } -} - -pub fn find(id: Id) -> Option> { - unsafe { - let ptr = avcodec_find_encoder(id.into()); - - if ptr == ptr::null_mut() { - None - } - else { - Some(Codec::wrap(ptr)) - } - } -} - -pub fn find_by_name(name: &str) -> Option> { - unsafe { - let ptr = avcodec_find_encoder_by_name(CString::new(name).unwrap().as_ptr()); - - if ptr == ptr::null_mut() { - None - } - else { - Some(Codec::wrap(ptr)) - } - } -} diff --git a/src/codec/encoder/audio.rs b/src/codec/encoder/audio.rs new file mode 100644 index 0000000..8960b3d --- /dev/null +++ b/src/codec/encoder/audio.rs @@ -0,0 +1,31 @@ +use std::ops::Deref; + +use libc::c_int; +use ffi::*; + +use super::Encoder; +use ::{Packet, Error}; +use ::frame; + +pub struct Audio(pub Encoder); + +impl Audio { + pub fn encode(&self, frame: &frame::Audio, out: &mut Packet) -> Result { + unsafe { + let mut got: c_int = 0; + + match avcodec_encode_audio2(self.ptr, &mut out.val, frame.ptr, &mut got) { + e if e < 0 => Err(Error::new(e)), + _ => Ok(got != 0) + } + } + } +} + +impl Deref for Audio { + type Target = Encoder; + + fn deref(&self) -> &::Target { + &self.0 + } +} diff --git a/src/codec/encoder/mod.rs b/src/codec/encoder/mod.rs new file mode 100644 index 0000000..e298383 --- /dev/null +++ b/src/codec/encoder/mod.rs @@ -0,0 +1,83 @@ +pub mod video; +pub use self::video::Video; + +pub mod audio; +pub use self::audio::Audio; + +pub mod subtitle; +pub use self::subtitle::Subtitle; + +use std::ffi::CString; +use std::ptr; +use std::ops::Deref; + +use ffi::*; +use super::Id; +use super::context::Opened; +use ::{Codec, Error}; +use ::media; + +pub struct Encoder(pub Opened); + +impl Encoder { + pub fn video(self) -> Result { + if self.medium() == media::Type::Video { + Ok(Video(self)) + } + else { + Err(Error::from(AVERROR_INVALIDDATA)) + } + } + + pub fn audio(self) -> Result { + if self.medium() == media::Type::Audio { + Ok(Audio(self)) + } + else { + Err(Error::from(AVERROR_INVALIDDATA)) + } + } + + pub fn subtitle(self) -> Result { + if self.medium() == media::Type::Subtitle { + Ok(Subtitle(self)) + } + else { + Err(Error::from(AVERROR_INVALIDDATA)) + } + } +} + +impl Deref for Encoder { + type Target = Opened; + + fn deref(&self) -> &::Target { + &self.0 + } +} + +pub fn find(id: Id) -> Option> { + unsafe { + let ptr = avcodec_find_encoder(id.into()); + + if ptr == ptr::null_mut() { + None + } + else { + Some(Codec::wrap(ptr)) + } + } +} + +pub fn find_by_name(name: &str) -> Option> { + unsafe { + let ptr = avcodec_find_encoder_by_name(CString::new(name).unwrap().as_ptr()); + + if ptr == ptr::null_mut() { + None + } + else { + Some(Codec::wrap(ptr)) + } + } +} diff --git a/src/codec/encoder/subtitle.rs b/src/codec/encoder/subtitle.rs new file mode 100644 index 0000000..fb0cec0 --- /dev/null +++ b/src/codec/encoder/subtitle.rs @@ -0,0 +1,28 @@ +use std::ops::Deref; + +use libc::c_int; +use ffi::*; + +use super::Encoder; +use ::Error; + +pub struct Subtitle(pub Encoder); + +impl Subtitle { + pub fn encode(&self, subtitle: &::Subtitle, out: &mut [u8]) -> Result { + unsafe { + match avcodec_encode_subtitle(self.ptr, out.as_mut_ptr(), out.len() as c_int, &subtitle.val) { + e if e < 0 => Err(Error::new(e)), + _ => Ok(true) + } + } + } +} + +impl Deref for Subtitle { + type Target = Encoder; + + fn deref(&self) -> &::Target { + &self.0 + } +} diff --git a/src/codec/encoder/video.rs b/src/codec/encoder/video.rs new file mode 100644 index 0000000..861ab97 --- /dev/null +++ b/src/codec/encoder/video.rs @@ -0,0 +1,31 @@ +use std::ops::Deref; + +use libc::c_int; +use ffi::*; + +use super::Encoder; +use ::{Packet, Error}; +use ::frame; + +pub struct Video(pub Encoder); + +impl Video { + pub fn encode(&self, frame: &frame::Video, out: &mut Packet) -> Result { + unsafe { + let mut got: c_int = 0; + + match avcodec_encode_video2(self.ptr, &mut out.val, frame.ptr, &mut got) { + e if e < 0 => Err(Error::new(e)), + _ => Ok(got != 0) + } + } + } +} + +impl Deref for Video { + type Target = Encoder; + + fn deref(&self) -> &::Target { + &self.0 + } +} diff --git a/src/lib.rs b/src/lib.rs index def6a28..113bf83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,8 @@ pub use codec::discard::Discard; #[cfg(feature = "codec")] pub use codec::codec::Codec; #[cfg(feature = "codec")] +pub use codec::{decoder, encoder}; +#[cfg(feature = "codec")] pub use codec::field_order::FieldOrder; #[cfg(feature = "codec")] pub use codec::audio_service::AudioService;