format: split input and output formats

This commit is contained in:
meh 2015-09-04 16:30:19 +02:00
parent fbf5cd94eb
commit 1f80007e5e
9 changed files with 672 additions and 558 deletions

View File

@ -123,7 +123,7 @@ impl Packet {
SideDataIter::new(&self.0) SideDataIter::new(&self.0)
} }
pub fn read(&mut self, format: &mut format::Context) -> Result<(), Error> { pub fn read(&mut self, format: &mut format::context::Input) -> Result<(), Error> {
unsafe { unsafe {
match av_read_frame(format.as_mut_ptr(), self.as_mut_ptr()) { match av_read_frame(format.as_mut_ptr(), self.as_mut_ptr()) {
0 => Ok(()), 0 => Ok(()),
@ -132,7 +132,7 @@ impl Packet {
} }
} }
pub fn write(&self, format: &mut format::Context) -> Result<bool, Error> { pub fn write(&self, format: &mut format::context::Output) -> Result<bool, Error> {
unsafe { unsafe {
match av_write_frame(format.as_mut_ptr(), self.as_ptr()) { match av_write_frame(format.as_mut_ptr(), self.as_ptr()) {
1 => Ok(true), 1 => Ok(true),
@ -142,7 +142,7 @@ impl Packet {
} }
} }
pub fn write_interleaved(&self, format: &mut format::Context) -> Result<bool, Error> { pub fn write_interleaved(&self, format: &mut format::context::Output) -> Result<bool, Error> {
unsafe { unsafe {
match av_interleaved_write_frame(format.as_mut_ptr(), self.as_ptr()) { match av_interleaved_write_frame(format.as_mut_ptr(), self.as_ptr()) {
1 => Ok(true), 1 => Ok(true),

View File

@ -3,7 +3,7 @@ use std::marker::PhantomData;
use ffi::*; use ffi::*;
use ::Error; use ::Error;
use ::format::Context; use ::format::context::common::Context;
use ::device; use ::device;
use libc::c_int; use libc::c_int;

View File

@ -1,419 +0,0 @@
use std::marker::PhantomData;
use std::ptr;
use libc::{c_int, c_uint};
use ffi::*;
use ::{Error, Codec, Stream, StreamMut, Packet, Dictionary, media};
pub struct Context {
ptr: *mut AVFormatContext,
_input: bool,
}
unsafe impl Send for Context { }
impl Context {
pub unsafe fn input(ptr: *mut AVFormatContext) -> Self {
Context {
ptr: ptr,
_input: true,
}
}
pub unsafe fn output(ptr: *mut AVFormatContext) -> Self {
Context {
ptr: ptr,
_input: false,
}
}
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
self.ptr as *const _
}
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
self.ptr
}
}
impl Context {
pub fn new() -> Self {
unsafe {
Context {
ptr: avformat_alloc_context(),
_input: false,
}
}
}
pub fn is_input(&self) -> bool {
self._input
}
pub fn is_output(&self) -> bool {
!self._input
}
pub fn write_header(&mut self) -> Result<(), Error> {
unsafe {
match avformat_write_header(self.as_mut_ptr(), ptr::null_mut()) {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn write_header_with(&mut self, options: Dictionary) -> Result<(), Error> {
unsafe {
let mut opts = options.take();
let status = avformat_write_header(self.as_mut_ptr(), &mut opts);
Dictionary::own(opts);
match status {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn write_trailer(&mut self) -> Result<(), Error> {
unsafe {
match av_write_trailer(self.as_mut_ptr()) {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn stream(&self, index: usize) -> Option<Stream> {
unsafe {
if index >= (*self.as_ptr()).nb_streams as usize {
None
}
else {
Some(Stream::wrap(*(*self.ptr).streams.offset(index as isize)))
}
}
}
pub fn stream_mut(&mut self, index: usize) -> Option<StreamMut> {
unsafe {
if index >= (*self.as_ptr()).nb_streams as usize {
None
}
else {
Some(StreamMut::wrap(*(*self.ptr).streams.offset(index as isize)))
}
}
}
pub fn streams(&self) -> StreamIter {
unsafe {
StreamIter::new(self.as_ptr())
}
}
pub fn streams_mut(&mut self) -> StreamIterMut {
unsafe {
StreamIterMut::new(self.as_mut_ptr())
}
}
pub fn new_stream(&mut self, codec: &Codec) -> Option<StreamMut> {
unsafe {
let ptr = avformat_new_stream(self.as_mut_ptr(), codec.as_ptr());
if ptr.is_null() {
None
}
else {
Some(StreamMut::wrap(ptr))
}
}
}
pub fn metadata(&self) -> Dictionary {
unsafe {
Dictionary::wrap((*self.as_ptr()).metadata)
}
}
pub fn probe_score(&self) -> i32 {
unsafe {
av_format_get_probe_score(self.as_ptr())
}
}
pub fn video_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_video_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_video_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_video_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn audio_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_audio_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_audio_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_audio_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn subtitle_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_subtitle_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_subtitle_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_subtitle_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn data_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_data_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_data_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_data_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn packets(&mut self) -> PacketIter {
PacketIter::new(self)
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
if self._input {
avformat_close_input(&mut self.as_mut_ptr());
}
else {
avformat_free_context(self.as_mut_ptr());
}
}
}
}
pub struct Best<'a> {
ptr: *const AVFormatContext,
wanted: i32,
related: i32,
_marker: PhantomData<&'a ()>,
}
impl<'a> Best<'a> {
pub unsafe fn new<'b>(ptr: *const AVFormatContext) -> Best<'b> {
Best {
ptr: ptr,
wanted: -1,
related: -1,
_marker: PhantomData,
}
}
pub fn wanted<'b: 'a>(mut self, stream: &'b Stream) -> Best<'a> {
self.wanted = stream.index() as i32;
self
}
pub fn related<'b: 'a>(mut self, stream: &'b Stream) -> Best<'a> {
self.related = stream.index() as i32;
self
}
pub fn best(self, kind: media::Type) -> Option<Stream<'a>> {
unsafe {
let mut decoder = ptr::null_mut();
let index = av_find_best_stream(self.ptr,
kind.into(), self.wanted as c_int, self.related as c_int,
&mut decoder, 0);
if index >= 0 && !decoder.is_null() {
Some(Stream::wrap(*(*self.ptr).streams.offset(index as isize)))
}
else {
None
}
}
}
}
pub struct StreamIter<'a> {
ptr: *const AVFormatContext,
cur: c_uint,
_marker: PhantomData<&'a Context>,
}
impl<'a> StreamIter<'a> {
pub fn new(ptr: *const AVFormatContext) -> Self {
StreamIter { ptr: ptr, cur: 0, _marker: PhantomData }
}
}
impl<'a> StreamIter<'a> {
pub fn wanted<'b: 'a>(&'a self, stream: &'b Stream) -> Best<'a> {
unsafe {
Best::new(self.ptr).wanted(stream)
}
}
pub fn related<'b: 'a>(&'a self, stream: &'b Stream) -> Best<'a> {
unsafe {
Best::new(self.ptr).related(stream)
}
}
pub fn best(&'a self, kind: media::Type) -> Option<Stream<'a>> {
unsafe {
Best::new(self.ptr).best(kind)
}
}
}
impl<'a> Iterator for StreamIter<'a> {
type Item = Stream<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if self.cur >= (*self.ptr).nb_streams {
None
}
else {
self.cur += 1;
Some(Stream::wrap(*(*self.ptr).streams.offset((self.cur - 1) as isize)))
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
unsafe {
((*self.ptr).nb_streams as usize, Some((*self.ptr).nb_streams as usize))
}
}
}
impl<'a> ExactSizeIterator for StreamIter<'a> { }
pub struct StreamIterMut<'a> {
ptr: *const AVFormatContext,
cur: c_uint,
_marker: PhantomData<&'a Context>,
}
impl<'a> StreamIterMut<'a> {
pub fn new(ptr: *mut AVFormatContext) -> Self {
StreamIterMut { ptr: ptr, cur: 0, _marker: PhantomData }
}
}
impl<'a> Iterator for StreamIterMut<'a> {
type Item = StreamMut<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if self.cur >= (*self.ptr).nb_streams {
None
}
else {
self.cur += 1;
Some(StreamMut::wrap(*(*self.ptr).streams.offset((self.cur - 1) as isize)))
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
unsafe {
((*self.ptr).nb_streams as usize, Some((*self.ptr).nb_streams as usize))
}
}
}
impl<'a> ExactSizeIterator for StreamIterMut<'a> { }
pub struct PacketIter<'a> {
context: &'a mut Context,
}
impl<'a> PacketIter<'a> {
pub fn new(context: &mut Context) -> PacketIter {
PacketIter { context: context }
}
}
impl<'a> Iterator for PacketIter<'a> {
type Item = (Stream<'a>, Packet);
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
let mut packet = Packet::empty();
loop {
match packet.read(self.context) {
Ok(..) =>
return Some((unsafe {
Stream::wrap(*(*self.context.as_ptr()).streams.offset(packet.stream() as isize))
}, packet)),
Err(Error::Eof) =>
return None,
Err(..) =>
()
}
}
}
}

View File

@ -0,0 +1,210 @@
use std::marker::PhantomData;
use std::ptr;
use ffi::*;
use libc::{c_int, c_uint};
use ::{media, Stream, StreamMut, Dictionary};
pub struct Context {
ptr: *mut AVFormatContext,
}
unsafe impl Send for Context { }
impl Context {
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
Context { ptr: ptr }
}
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
self.ptr as *const _
}
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
self.ptr
}
}
impl Context {
pub fn stream<'a, 'b>(&'a self, index: usize) -> Option<Stream<'b>> where 'a: 'b {
unsafe {
if index >= (*self.as_ptr()).nb_streams as usize {
None
}
else {
Some(Stream::wrap(*(*self.as_ptr()).streams.offset(index as isize)))
}
}
}
pub fn stream_mut<'a, 'b>(&'a mut self, index: usize) -> Option<StreamMut<'b>> where 'a: 'b {
unsafe {
if index >= (*self.as_ptr()).nb_streams as usize {
None
}
else {
Some(StreamMut::wrap(*(*self.as_mut_ptr()).streams.offset(index as isize)))
}
}
}
pub fn streams(&self) -> StreamIter {
unsafe {
StreamIter::new(self.as_ptr())
}
}
pub fn streams_mut(&mut self) -> StreamIterMut {
unsafe {
StreamIterMut::new(self.as_mut_ptr())
}
}
pub fn metadata(&self) -> Dictionary {
unsafe {
Dictionary::wrap((*self.as_ptr()).metadata)
}
}
}
pub struct Best<'a> {
ptr: *const AVFormatContext,
wanted: i32,
related: i32,
_marker: PhantomData<&'a ()>,
}
impl<'a> Best<'a> {
pub unsafe fn new<'b>(ptr: *const AVFormatContext) -> Best<'b> {
Best {
ptr: ptr,
wanted: -1,
related: -1,
_marker: PhantomData,
}
}
pub fn wanted<'b>(mut self, stream: &'b Stream) -> Best<'a> where 'a: 'b {
self.wanted = stream.index() as i32;
self
}
pub fn related<'b>(mut self, stream: &'b Stream) -> Best<'a> where 'a: 'b {
self.related = stream.index() as i32;
self
}
pub fn best<'b>(self, kind: media::Type) -> Option<Stream<'b>> where 'a: 'b {
unsafe {
let mut decoder = ptr::null_mut();
let index = av_find_best_stream(self.ptr,
kind.into(), self.wanted as c_int, self.related as c_int,
&mut decoder, 0);
if index >= 0 && !decoder.is_null() {
Some(Stream::wrap(*(*self.ptr).streams.offset(index as isize)))
}
else {
None
}
}
}
}
pub struct StreamIter<'a> {
ptr: *const AVFormatContext,
cur: c_uint,
_marker: PhantomData<&'a ()>,
}
impl<'a> StreamIter<'a> {
pub fn new(ptr: *const AVFormatContext) -> Self {
StreamIter { ptr: ptr, cur: 0, _marker: PhantomData }
}
}
impl<'a> StreamIter<'a> {
pub fn wanted<'b: 'a, 'c: 'a>(&'a self, stream: &'b Stream) -> Best<'a> {
unsafe {
Best::new(self.ptr).wanted(stream)
}
}
pub fn related<'b: 'a>(&'a self, stream: &'b Stream) -> Best<'a> {
unsafe {
Best::new(self.ptr).related(stream)
}
}
pub fn best<'b: 'a>(&'a self, kind: media::Type) -> Option<Stream<'b>> {
unsafe {
Best::new(self.ptr).best(kind)
}
}
}
impl<'a> Iterator for StreamIter<'a> {
type Item = Stream<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if self.cur >= (*self.ptr).nb_streams {
None
}
else {
self.cur += 1;
Some(Stream::wrap(*(*self.ptr).streams.offset((self.cur - 1) as isize)))
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
unsafe {
((*self.ptr).nb_streams as usize, Some((*self.ptr).nb_streams as usize))
}
}
}
impl<'a> ExactSizeIterator for StreamIter<'a> { }
pub struct StreamIterMut<'a> {
ptr: *const AVFormatContext,
cur: c_uint,
_marker: PhantomData<&'a ()>,
}
impl<'a> StreamIterMut<'a> {
pub fn new(ptr: *mut AVFormatContext) -> Self {
StreamIterMut { ptr: ptr, cur: 0, _marker: PhantomData }
}
}
impl<'a> Iterator for StreamIterMut<'a> {
type Item = StreamMut<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if self.cur >= (*self.ptr).nb_streams {
None
}
else {
self.cur += 1;
Some(StreamMut::wrap(*(*self.ptr).streams.offset((self.cur - 1) as isize)))
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
unsafe {
((*self.ptr).nb_streams as usize, Some((*self.ptr).nb_streams as usize))
}
}
}
impl<'a> ExactSizeIterator for StreamIterMut<'a> { }

180
src/format/context/input.rs Normal file
View File

@ -0,0 +1,180 @@
use std::ops::{Deref, DerefMut};
use std::ptr;
use std::ffi::CString;
use ffi::*;
use ::{Error, Codec, Stream, Packet};
use super::common::Context;
pub struct Input {
ptr: *mut AVFormatContext,
ctx: Context,
}
unsafe impl Send for Input { }
impl Input {
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
Input { ptr: ptr, ctx: Context::wrap(ptr) }
}
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
self.ptr as *const _
}
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
self.ptr
}
}
impl Input {
pub fn video_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_video_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_video_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_video_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn audio_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_audio_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_audio_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_audio_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn subtitle_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_subtitle_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_subtitle_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_subtitle_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn data_codec(&self) -> Option<Codec> {
unsafe {
let ptr = av_format_get_data_codec(self.as_ptr());
if ptr.is_null() {
None
}
else {
Some(Codec::wrap(ptr))
}
}
}
pub fn set_data_codec(&mut self, mut value: Codec) {
unsafe {
av_format_set_data_codec(self.as_mut_ptr(), value.as_mut_ptr());
}
}
pub fn probe_score(&self) -> i32 {
unsafe {
av_format_get_probe_score(self.as_ptr())
}
}
pub fn packets(&mut self) -> PacketIter {
PacketIter::new(self)
}
}
impl Deref for Input {
type Target = Context;
fn deref(&self) -> &Self::Target {
&self.ctx
}
}
impl DerefMut for Input {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.ctx
}
}
impl Drop for Input {
fn drop(&mut self) {
unsafe {
avformat_close_input(&mut self.as_mut_ptr());
}
}
}
pub struct PacketIter<'a> {
context: &'a mut Input,
}
impl<'a> PacketIter<'a> {
pub fn new(context: &mut Input) -> PacketIter {
PacketIter { context: context }
}
}
impl<'a> Iterator for PacketIter<'a> {
type Item = (Stream<'a>, Packet);
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
let mut packet = Packet::empty();
loop {
match packet.read(self.context) {
Ok(..) =>
return Some((unsafe {
Stream::wrap(*(*self.context.as_ptr()).streams.offset(packet.stream() as isize))
}, packet)),
Err(Error::Eof) =>
return None,
Err(..) =>
()
}
}
}
}
pub fn dump(ctx: &Input, index: i32, url: Option<&str>) {
let url = url.map(|u| CString::new(u).unwrap());
unsafe {
av_dump_format(ctx.as_ptr(), index,
url.map(|u| u.as_ptr()).unwrap_or(ptr::null()), 0);
}
}

51
src/format/context/mod.rs Normal file
View File

@ -0,0 +1,51 @@
pub mod input;
pub use self::input::Input;
pub mod output;
pub use self::output::Output;
#[doc(hidden)]
pub mod common;
pub enum Context {
Input(Input),
Output(Output),
}
unsafe impl Send for Context { }
impl Context {
pub fn is_input(&self) -> bool {
if let &Context::Input(..) = self {
true
}
else {
false
}
}
pub fn input(self) -> Input {
if let Context::Input(context) = self {
return context;
}
unreachable!();
}
pub fn is_output(&self) -> bool {
if let &Context::Output(..) = self {
true
}
else {
false
}
}
pub fn output(self) -> Output {
if let Context::Output(context) = self {
return context;
}
unreachable!();
}
}

View File

@ -0,0 +1,105 @@
use std::ops::{Deref, DerefMut};
use std::ptr;
use std::ffi::CString;
use ffi::*;
use ::{Error, Codec, StreamMut, Dictionary};
use super::common::Context;
pub struct Output {
ptr: *mut AVFormatContext,
ctx: Context,
}
unsafe impl Send for Output { }
impl Output {
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
Output { ptr: ptr, ctx: Context::wrap(ptr) }
}
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
self.ptr as *const _
}
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
self.ptr
}
}
impl Output {
pub fn write_header(&mut self) -> Result<(), Error> {
unsafe {
match avformat_write_header(self.as_mut_ptr(), ptr::null_mut()) {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn write_header_with(&mut self, options: Dictionary) -> Result<(), Error> {
unsafe {
let mut opts = options.take();
let status = avformat_write_header(self.as_mut_ptr(), &mut opts);
Dictionary::own(opts);
match status {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn write_trailer(&mut self) -> Result<(), Error> {
unsafe {
match av_write_trailer(self.as_mut_ptr()) {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn add_stream(&mut self, codec: &Codec) -> StreamMut {
unsafe {
let ptr = avformat_new_stream(self.as_mut_ptr(), codec.as_ptr());
if ptr.is_null() {
panic!("out of memory");
}
StreamMut::wrap(ptr)
}
}
}
impl Deref for Output {
type Target = Context;
fn deref(&self) -> &Self::Target {
&self.ctx
}
}
impl DerefMut for Output {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.ctx
}
}
impl Drop for Output {
fn drop(&mut self) {
unsafe {
avformat_free_context(self.as_mut_ptr());
}
}
}
pub fn dump(ctx: &Output, index: i32, url: Option<&str>) {
let url = url.map(|u| CString::new(u).unwrap());
unsafe {
av_dump_format(ctx.as_ptr(), index,
url.map(|u| u.as_ptr()).unwrap_or(ptr::null()), 1);
}
}

View File

@ -162,12 +162,18 @@ pub fn list() -> FormatIter {
pub struct FormatIter { pub struct FormatIter {
input: *mut AVInputFormat, input: *mut AVInputFormat,
output: *mut AVOutputFormat, output: *mut AVOutputFormat,
step: usize, step: Step,
}
enum Step {
Input,
Output,
Done,
} }
impl FormatIter { impl FormatIter {
pub fn new() -> Self { pub fn new() -> Self {
FormatIter { input: ptr::null_mut(), output: ptr::null_mut(), step: 0 } FormatIter { input: ptr::null_mut(), output: ptr::null_mut(), step: Step::Input }
} }
} }
@ -177,11 +183,11 @@ impl Iterator for FormatIter {
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
match self.step { match self.step {
0 => { Step::Input => {
let ptr = av_iformat_next(self.input); let ptr = av_iformat_next(self.input);
if ptr.is_null() && !self.input.is_null() { if ptr.is_null() && !self.input.is_null() {
self.step = 1; self.step = Step::Output;
self.next() self.next()
} }
@ -190,13 +196,13 @@ impl Iterator for FormatIter {
Some(Format::Input(Input::wrap(ptr))) Some(Format::Input(Input::wrap(ptr)))
} }
}, }
1 => { Step::Output => {
let ptr = av_oformat_next(self.output); let ptr = av_oformat_next(self.output);
if ptr.is_null() && !self.output.is_null() { if ptr.is_null() && !self.output.is_null() {
self.step = 2; self.step = Step::Done;
self.next() self.next()
} }
@ -205,9 +211,10 @@ impl Iterator for FormatIter {
Some(Format::Output(Output::wrap(ptr))) Some(Format::Output(Output::wrap(ptr)))
} }
}, }
_ => None Step::Done =>
None
} }
} }
} }

View File

@ -56,176 +56,156 @@ pub fn license() -> &'static str {
} }
// XXX: use to_cstring when stable // XXX: use to_cstring when stable
fn from_path<T: AsRef<Path>>(path: &T) -> CString { fn from_path<P: AsRef<Path>>(path: &P) -> CString {
CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap() CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap()
} }
pub fn open_input<T: AsRef<Path>>(path: &T) -> Result<Context, Error> { // NOTE: this will be better with specialization or anonymous return types
pub fn open<P: AsRef<Path>>(path: &P, format: &Format) -> Result<Context, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
let status = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut());
match status { match format {
0 => { &Format::Input(ref format) => {
let ctx = Context::input(ps); match avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr(), ptr::null_mut()) {
0 => {
match avformat_find_stream_info(ps, ptr::null_mut()) {
0 => Ok(Context::Input(context::Input::wrap(ps))),
e => Err(Error::from(e)),
}
}
match avformat_find_stream_info(ps, ptr::null_mut()) {
0 => Ok(ctx),
e => Err(Error::from(e)) e => Err(Error::from(e))
} }
}, }
&Format::Output(ref format) => {
match avformat_alloc_output_context2(&mut ps, format.as_ptr(), ptr::null(), path.as_ptr()) {
0 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(Context::Output(context::Output::wrap(ps))),
e => Err(Error::from(e)),
}
}
e => Err(Error::from(e))
}
}
}
}
}
pub fn open_with<P: AsRef<Path>>(path: &P, format: &Format, options: Dictionary) -> Result<Context, Error> {
unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
let mut opts = options.take();
match format {
&Format::Input(ref format) => {
match avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr(), &mut opts) {
0 => {
Dictionary::own(opts);
match avformat_find_stream_info(ps, ptr::null_mut()) {
0 => Ok(Context::Input(context::Input::wrap(ps))),
e => Err(Error::from(e)),
}
}
e => Err(Error::from(e))
}
}
&Format::Output(ref format) => {
match avformat_alloc_output_context2(&mut ps, format.as_ptr(), ptr::null(), path.as_ptr()) {
0 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(Context::Output(context::Output::wrap(ps))),
e => Err(Error::from(e)),
}
}
e => Err(Error::from(e))
}
}
}
}
}
pub fn input<P: AsRef<Path>>(path: &P) -> Result<context::Input, Error> {
unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) {
0 => {
match avformat_find_stream_info(ps, ptr::null_mut()) {
0 => Ok(context::Input::wrap(ps)),
e => Err(Error::from(e))
}
}
e => Err(Error::from(e)) e => Err(Error::from(e))
} }
} }
} }
pub fn open_input_with<T: AsRef<Path>>(path: &T, options: Dictionary) -> Result<Context, Error> { pub fn input_with<P: AsRef<Path>>(path: &P, options: Dictionary) -> Result<context::Input, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
let mut opts = options.take(); let mut opts = options.take();
let status = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts);
Dictionary::own(opts); match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts) {
match status {
0 => { 0 => {
let ctx = Context::input(ps); Dictionary::own(opts);
match avformat_find_stream_info(ps, ptr::null_mut()) { match avformat_find_stream_info(ps, ptr::null_mut()) {
0 => Ok(ctx), 0 => Ok(context::Input::wrap(ps)),
e => Err(Error::from(e)) e => Err(Error::from(e))
} }
}, }
e => Err(Error::from(e)) e => Err(Error::from(e))
} }
} }
} }
pub fn open_input_as<T: AsRef<Path>>(path: &T, format: &Format) -> Result<Context, Error> { pub fn output<P: AsRef<Path>>(path: &P) -> Result<context::Output, Error> {
if let &Format::Input(ref format) = format {
unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
let status = avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr(), ptr::null_mut());
match status {
0 => {
let ctx = Context::input(ps);
match avformat_find_stream_info(ps, ptr::null_mut()) {
0 => Ok(ctx),
e => Err(Error::from(e))
}
},
e => Err(Error::from(e))
}
}
}
else {
Err(Error::Bug)
}
}
pub fn open_input_as_with<T: AsRef<Path>>(path: &T, format: &Format, options: Dictionary) -> Result<Context, Error> {
if let &Format::Input(ref format) = format {
unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
let mut opts = options.take();
let status = avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr(), &mut opts);
Dictionary::own(opts);
match status {
0 => {
let ctx = Context::input(ps);
match avformat_find_stream_info(ps, ptr::null_mut()) {
0 => Ok(ctx),
e => Err(Error::from(e))
}
},
e => Err(Error::from(e))
}
}
}
else {
Err(Error::Bug)
}
}
pub fn open_output<T: AsRef<Path>>(path: &T) -> Result<Context, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
let status = avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr());
match status { match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr()) {
0 => { 0 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(Context::output(ps)), 0 => Ok(context::Output::wrap(ps)),
e => Err(Error::from(e)), e => Err(Error::from(e))
} }
}, }
e => Err(Error::from(e)) e => Err(Error::from(e))
} }
} }
} }
pub fn open_output_as<T: AsRef<Path>>(path: &T, format: &Format) -> Result<Context, Error> { pub fn output_as<P: AsRef<Path>>(path: &P, format: &str) -> Result<context::Output, Error> {
if let &Format::Output(ref format) = format {
unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
let status = avformat_alloc_output_context2(&mut ps, format.as_ptr(), ptr::null(), path.as_ptr());
match status {
0 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(Context::output(ps)),
e => Err(Error::from(e)),
}
},
e => Err(Error::from(e))
}
}
}
else {
Err(Error::Bug)
}
}
pub fn open_output_as_string<T: AsRef<Path>>(path: &T, format: &str) -> Result<Context, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
let format = CString::new(format).unwrap(); let format = CString::new(format).unwrap();
let status = avformat_alloc_output_context2(&mut ps, ptr::null_mut(), format.as_ptr(), path.as_ptr());
match status { match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), format.as_ptr(), path.as_ptr()) {
0 => { 0 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(Context::output(ps)), 0 => Ok(context::Output::wrap(ps)),
e => Err(Error::from(e)), e => Err(Error::from(e))
} }
}, }
e => Err(Error::from(e)) e => Err(Error::from(e))
} }
} }
} }
pub fn dump(ctx: &Context, index: i32, url: Option<&str>) {
let url = url.map(|u| CString::new(u).unwrap());
unsafe {
av_dump_format(ctx.as_ptr(), index,
url.map(|u| u.as_ptr()).unwrap_or(ptr::null()),
if ctx.is_input() { 0 } else { 1 });
}
}