diff --git a/src/format/context/input.rs b/src/format/context/input.rs index a8bd7b4..f87a69e 100644 --- a/src/format/context/input.rs +++ b/src/format/context/input.rs @@ -3,7 +3,7 @@ use std::ptr; use std::ffi::CString; use ffi::*; -use ::{Error, Codec, Stream, Packet}; +use ::{Error, Codec, Stream, Packet, format}; use super::common::Context; pub struct Input { @@ -28,6 +28,12 @@ impl Input { } impl Input { + pub fn format(&self) -> format::Input { + unsafe { + format::Input::wrap((*self.as_ptr()).iformat) + } + } + pub fn video_codec(&self) -> Option { unsafe { let ptr = av_format_get_video_codec(self.as_ptr()); diff --git a/src/format/context/output.rs b/src/format/context/output.rs index 080c057..b1f90ec 100644 --- a/src/format/context/output.rs +++ b/src/format/context/output.rs @@ -3,7 +3,7 @@ use std::ptr; use std::ffi::CString; use ffi::*; -use ::{Error, Codec, StreamMut, Dictionary}; +use ::{Error, Codec, StreamMut, Dictionary, format}; use super::common::Context; pub struct Output { @@ -28,6 +28,12 @@ impl Output { } impl Output { + pub fn format(&self) -> format::Output { + unsafe { + format::Output::wrap((*self.as_ptr()).oformat) + } + } + pub fn write_header(&mut self) -> Result<(), Error> { unsafe { match avformat_write_header(self.as_mut_ptr(), ptr::null_mut()) { @@ -74,7 +80,7 @@ impl Output { pub fn set_metadata(&mut self, dictionary: Dictionary) { unsafe { - (*self.as_mut_ptr()).metadata = dictionary.take(); + (*self.as_mut_ptr()).metadata = dictionary.disown(); } } } diff --git a/src/format/format.rs b/src/format/format.rs deleted file mode 100644 index ceca921..0000000 --- a/src/format/format.rs +++ /dev/null @@ -1,221 +0,0 @@ -use std::ptr; -use std::ffi::CStr; -use std::str::from_utf8_unchecked; - -use ffi::*; - -pub enum Format { - Input(Input), - Output(Output), -} - -impl Format { - pub fn name(&self) -> &str { - match self { - &Format::Input(ref f) => f.name(), - &Format::Output(ref f) => f.name() - } - } - - pub fn description(&self) -> &str { - match self { - &Format::Input(ref f) => f.description(), - &Format::Output(ref f) => f.description() - } - } - - pub fn extensions(&self) -> Vec<&str> { - match self { - &Format::Input(ref f) => f.extensions(), - &Format::Output(ref f) => f.extensions() - } - } - - pub fn mime_types(&self) -> Vec<&str> { - match self { - &Format::Input(ref f) => f.mime_types(), - &Format::Output(ref f) => f.mime_types() - } - } -} - -pub struct Input { - ptr: *mut AVInputFormat, -} - -impl Input { - pub unsafe fn wrap(ptr: *mut AVInputFormat) -> Self { - Input { ptr: ptr } - } - - pub unsafe fn as_ptr(&self) -> *const AVInputFormat { - self.ptr as *const _ - } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVInputFormat { - self.ptr - } -} - -impl Input { - pub fn name(&self) -> &str { - unsafe { - from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) - } - } - - pub fn description(&self) -> &str { - unsafe { - from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) - } - } - - pub fn extensions(&self) -> Vec<&str> { - unsafe { - let ptr = (*self.as_ptr()).extensions; - - if ptr.is_null() { - Vec::new() - } - else { - from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() - } - } - } - - pub fn mime_types(&self) -> Vec<&str> { - unsafe { - let ptr = (*self.as_ptr()).mime_type; - - if ptr.is_null() { - Vec::new() - } - else { - from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() - } - } - } -} - -pub struct Output { - ptr: *mut AVOutputFormat, -} - -impl Output { - pub unsafe fn wrap(ptr: *mut AVOutputFormat) -> Self { - Output { ptr: ptr } - } - - pub unsafe fn as_ptr(&self) -> *const AVOutputFormat { - self.ptr as *const _ - } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVOutputFormat { - self.ptr - } -} - -impl Output { - pub fn name(&self) -> &str { - unsafe { - from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) - } - } - - pub fn description(&self) -> &str { - unsafe { - from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) - } - } - - pub fn extensions(&self) -> Vec<&str> { - unsafe { - let ptr = (*self.as_ptr()).extensions; - - if ptr.is_null() { - Vec::new() - } - else { - from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() - } - } - } - - pub fn mime_types(&self) -> Vec<&str> { - unsafe { - let ptr = (*self.as_ptr()).mime_type; - - if ptr.is_null() { - Vec::new() - } - else { - from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() - } - } - } -} - -pub fn list() -> FormatIter { - FormatIter::new() -} - -pub struct FormatIter { - input: *mut AVInputFormat, - output: *mut AVOutputFormat, - step: Step, -} - -enum Step { - Input, - Output, - Done, -} - -impl FormatIter { - pub fn new() -> Self { - FormatIter { input: ptr::null_mut(), output: ptr::null_mut(), step: Step::Input } - } -} - -impl Iterator for FormatIter { - type Item = Format; - - fn next(&mut self) -> Option<::Item> { - unsafe { - match self.step { - Step::Input => { - let ptr = av_iformat_next(self.input); - - if ptr.is_null() && !self.input.is_null() { - self.step = Step::Output; - - self.next() - } - else { - self.input = ptr; - - Some(Format::Input(Input::wrap(ptr))) - } - } - - Step::Output => { - let ptr = av_oformat_next(self.output); - - if ptr.is_null() && !self.output.is_null() { - self.step = Step::Done; - - self.next() - } - else { - self.output = ptr; - - Some(Format::Output(Output::wrap(ptr))) - } - } - - Step::Done => - None - } - } - } -} diff --git a/src/format/format/input.rs b/src/format/format/input.rs new file mode 100644 index 0000000..e7e760b --- /dev/null +++ b/src/format/format/input.rs @@ -0,0 +1,62 @@ +use std::ffi::CStr; +use std::str::from_utf8_unchecked; + +use ffi::*; + +pub struct Input { + ptr: *mut AVInputFormat, +} + +impl Input { + pub unsafe fn wrap(ptr: *mut AVInputFormat) -> Self { + Input { ptr: ptr } + } + + pub unsafe fn as_ptr(&self) -> *const AVInputFormat { + self.ptr as *const _ + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVInputFormat { + self.ptr + } +} + +impl Input { + pub fn name(&self) -> &str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) + } + } + + pub fn description(&self) -> &str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) + } + } + + pub fn extensions(&self) -> Vec<&str> { + unsafe { + let ptr = (*self.as_ptr()).extensions; + + if ptr.is_null() { + Vec::new() + } + else { + from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() + } + } + } + + pub fn mime_types(&self) -> Vec<&str> { + unsafe { + let ptr = (*self.as_ptr()).mime_type; + + if ptr.is_null() { + Vec::new() + } + else { + from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() + } + } + } +} diff --git a/src/format/format/iter.rs b/src/format/format/iter.rs new file mode 100644 index 0000000..a0c3afc --- /dev/null +++ b/src/format/format/iter.rs @@ -0,0 +1,65 @@ +use std::ptr; + +use ffi::*; +use super::{Format, Input, Output}; + +pub struct Iter { + input: *mut AVInputFormat, + output: *mut AVOutputFormat, + step: Step, +} + +enum Step { + Input, + Output, + Done, +} + +impl Iter { + pub fn new() -> Self { + Iter { input: ptr::null_mut(), output: ptr::null_mut(), step: Step::Input } + } +} + +impl Iterator for Iter { + type Item = Format; + + fn next(&mut self) -> Option<::Item> { + unsafe { + match self.step { + Step::Input => { + let ptr = av_iformat_next(self.input); + + if ptr.is_null() && !self.input.is_null() { + self.step = Step::Output; + + self.next() + } + else { + self.input = ptr; + + Some(Format::Input(Input::wrap(ptr))) + } + } + + Step::Output => { + let ptr = av_oformat_next(self.output); + + if ptr.is_null() && !self.output.is_null() { + self.step = Step::Done; + + self.next() + } + else { + self.output = ptr; + + Some(Format::Output(Output::wrap(ptr))) + } + } + + Step::Done => + None + } + } + } +} diff --git a/src/format/format/mod.rs b/src/format/format/mod.rs new file mode 100644 index 0000000..9cb12a6 --- /dev/null +++ b/src/format/format/mod.rs @@ -0,0 +1,47 @@ +mod input; +pub use self::input::Input; + +mod output; +pub use self::output::Output; + +mod iter; +pub use self::iter::Iter; + +pub enum Format { + Input(Input), + Output(Output), +} + +impl Format { + pub fn name(&self) -> &str { + match self { + &Format::Input(ref f) => f.name(), + &Format::Output(ref f) => f.name() + } + } + + pub fn description(&self) -> &str { + match self { + &Format::Input(ref f) => f.description(), + &Format::Output(ref f) => f.description() + } + } + + pub fn extensions(&self) -> Vec<&str> { + match self { + &Format::Input(ref f) => f.extensions(), + &Format::Output(ref f) => f.extensions() + } + } + + pub fn mime_types(&self) -> Vec<&str> { + match self { + &Format::Input(ref f) => f.mime_types(), + &Format::Output(ref f) => f.mime_types() + } + } +} + +pub fn list() -> Iter { + Iter::new() +} diff --git a/src/format/format/output.rs b/src/format/format/output.rs new file mode 100644 index 0000000..a3012e9 --- /dev/null +++ b/src/format/format/output.rs @@ -0,0 +1,75 @@ +use std::path::Path; + +use std::ptr; +use std::ffi::{CStr, CString}; +use std::str::from_utf8_unchecked; + +use ffi::*; +use {codec, media}; + +pub struct Output { + ptr: *mut AVOutputFormat, +} + +impl Output { + pub unsafe fn wrap(ptr: *mut AVOutputFormat) -> Self { + Output { ptr: ptr } + } + + pub unsafe fn as_ptr(&self) -> *const AVOutputFormat { + self.ptr as *const _ + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVOutputFormat { + self.ptr + } +} + +impl Output { + pub fn name(&self) -> &str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) + } + } + + pub fn description(&self) -> &str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) + } + } + + pub fn extensions(&self) -> Vec<&str> { + unsafe { + let ptr = (*self.as_ptr()).extensions; + + if ptr.is_null() { + Vec::new() + } + else { + from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() + } + } + } + + pub fn mime_types(&self) -> Vec<&str> { + unsafe { + let ptr = (*self.as_ptr()).mime_type; + + if ptr.is_null() { + Vec::new() + } + else { + from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() + } + } + } + + pub fn codec>(&self, path: &P, kind: media::Type) -> codec::Id { + // XXX: use to_cstring when stable + let path = CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap(); + + unsafe { + codec::Id::from(av_guess_codec(self.as_ptr(), ptr::null(), path.as_ptr(), ptr::null(), kind.into())) + } + } +}