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)
}
pub fn read(&mut self, format: &mut format::Context) -> Result<(), Error> {
pub fn read(&mut self, format: &mut format::context::Input) -> Result<(), Error> {
unsafe {
match av_read_frame(format.as_mut_ptr(), self.as_mut_ptr()) {
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 {
match av_write_frame(format.as_mut_ptr(), self.as_ptr()) {
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 {
match av_interleaved_write_frame(format.as_mut_ptr(), self.as_ptr()) {
1 => Ok(true),

View File

@ -3,7 +3,7 @@ use std::marker::PhantomData;
use ffi::*;
use ::Error;
use ::format::Context;
use ::format::context::common::Context;
use ::device;
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 {
input: *mut AVInputFormat,
output: *mut AVOutputFormat,
step: usize,
step: Step,
}
enum Step {
Input,
Output,
Done,
}
impl FormatIter {
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> {
unsafe {
match self.step {
0 => {
Step::Input => {
let ptr = av_iformat_next(self.input);
if ptr.is_null() && !self.input.is_null() {
self.step = 1;
self.step = Step::Output;
self.next()
}
@ -190,13 +196,13 @@ impl Iterator for FormatIter {
Some(Format::Input(Input::wrap(ptr)))
}
},
}
1 => {
Step::Output => {
let ptr = av_oformat_next(self.output);
if ptr.is_null() && !self.output.is_null() {
self.step = 2;
self.step = Step::Done;
self.next()
}
@ -205,9 +211,10 @@ impl Iterator for FormatIter {
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
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()
}
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 {
let mut ps = ptr::null_mut();
let path = from_path(path);
let status = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut());
let mut ps = ptr::null_mut();
let path = from_path(path);
match status {
0 => {
let ctx = Context::input(ps);
match format {
&Format::Input(ref format) => {
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))
}
},
}
&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))
}
}
}
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 {
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(), ptr::null_mut(), &mut opts);
let mut ps = ptr::null_mut();
let path = from_path(path);
let mut opts = options.take();
Dictionary::own(opts);
match status {
match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts) {
0 => {
let ctx = Context::input(ps);
Dictionary::own(opts);
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))
}
}
}
pub fn open_input_as<T: AsRef<Path>>(path: &T, format: &Format) -> Result<Context, 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> {
pub fn output<P: AsRef<Path>>(path: &P) -> Result<context::Output, Error> {
unsafe {
let mut ps = ptr::null_mut();
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 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(Context::output(ps)),
e => Err(Error::from(e)),
0 => Ok(context::Output::wrap(ps)),
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> {
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> {
pub fn output_as<P: AsRef<Path>>(path: &P, format: &str) -> Result<context::Output, Error> {
unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
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 {
0 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(Context::output(ps)),
e => Err(Error::from(e)),
}
},
match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), format.as_ptr(), path.as_ptr()) {
0 => {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(context::Output::wrap(ps)),
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 });
}
}