diff --git a/src/format/context.rs b/src/format/context.rs index 9c7cc08..d5b24ef 100644 --- a/src/format/context.rs +++ b/src/format/context.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use libc::c_uint; use ffi::*; -use ::{Error, Codec, Stream, Packet, Dictionary}; +use ::{Error, Codec, Stream, StreamMut, Packet, Dictionary}; pub struct Context { ptr: *mut AVFormatContext, @@ -49,12 +49,40 @@ impl Context { !self._input } + pub fn stream(&self, index: usize) -> Option { + 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 { + 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 metadata(&self) -> Dictionary { unsafe { Dictionary::wrap((*self.as_ptr()).metadata) @@ -190,6 +218,35 @@ impl<'a> Iterator 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<::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))) + } + } + } +} + pub struct PacketIter<'a> { context: &'a mut Context, } diff --git a/src/format/stream/mod.rs b/src/format/stream/mod.rs index 3d71994..e23afec 100644 --- a/src/format/stream/mod.rs +++ b/src/format/stream/mod.rs @@ -1,128 +1,8 @@ pub mod disposition; pub use self::disposition::Disposition; -use std::marker::PhantomData; +mod stream; +pub use self::stream::Stream; -use libc::c_int; -use ffi::*; -use ::format; -use ::codec::{self, packet}; -use ::{Rational, Discard}; - -#[derive(Eq, PartialEq)] -pub struct Stream<'a> { - ptr: *mut AVStream, - - _marker: PhantomData<&'a format::Context>, -} - -impl<'a> Stream<'a> { - pub unsafe fn wrap(ptr: *mut AVStream) -> Self { - Stream { ptr: ptr, _marker: PhantomData } - } - - pub unsafe fn as_ptr(&self) -> *const AVStream { - self.ptr as *const _ - } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVStream { - self.ptr - } -} - -impl<'a> Stream<'a> { - pub fn codec(&self) -> codec::Context { - unsafe { - codec::Context::wrap((*self.as_ptr()).codec) - } - } - - pub fn index(&self) -> usize { - unsafe { - (*self.as_ptr()).index as usize - } - } - - pub fn time_base(&self) -> Rational { - unsafe { - Rational::from((*self.as_ptr()).time_base) - } - } - - pub fn start_time(&self) -> i64 { - unsafe { - (*self.as_ptr()).start_time - } - } - - pub fn duration(&self) -> i64 { - unsafe { - (*self.as_ptr()).duration - } - } - - pub fn frames(&self) -> i64 { - unsafe { - (*self.as_ptr()).nb_frames - } - } - - pub fn disposition(&self) -> Disposition { - unsafe { - Disposition::from_bits_truncate((*self.as_ptr()).disposition) - } - } - - pub fn discard(&self) -> Discard { - unsafe { - Discard::from((*self.as_ptr()).discard) - } - } - - pub fn side_data(&self) -> SideDataIter { - unsafe { - SideDataIter::new(self.as_ptr()) - } - } - - pub fn frame_rate(&self) -> Rational { - unsafe { - Rational::from(av_stream_get_r_frame_rate(self.as_ptr())) - } - } - - pub fn set_frame_rate(&mut self, value: Rational) { - unsafe { - av_stream_set_r_frame_rate(self.as_mut_ptr(), value.into()); - } - } -} - -pub struct SideDataIter<'a> { - ptr: *const AVStream, - cur: c_int, - - _marker: PhantomData<&'a Stream<'a>>, -} - -impl<'a> SideDataIter<'a> { - pub fn new(ptr: *const AVStream) -> Self { - SideDataIter { ptr: ptr, cur: 0, _marker: PhantomData } - } -} - -impl<'a> Iterator for SideDataIter<'a> { - type Item = packet::SideData<'a>; - - fn next(&mut self) -> Option<::Item> { - unsafe { - if self.cur >= (*self.ptr).nb_side_data { - None - } - else { - self.cur += 1; - Some(packet::SideData::wrap((*self.ptr).side_data.offset((self.cur - 1) as isize))) - } - } - } -} +mod stream_mut; +pub use self::stream_mut::StreamMut; diff --git a/src/format/stream/stream.rs b/src/format/stream/stream.rs new file mode 100644 index 0000000..efc04ad --- /dev/null +++ b/src/format/stream/stream.rs @@ -0,0 +1,116 @@ +use std::marker::PhantomData; + +use libc::c_int; +use ffi::*; +use ::format; +use ::codec::{self, packet}; +use ::{Rational, Discard}; +use super::Disposition; + +#[derive(Eq, PartialEq)] +pub struct Stream<'a> { + ptr: *mut AVStream, + + _marker: PhantomData<&'a format::Context>, +} + +impl<'a> Stream<'a> { + pub unsafe fn wrap(ptr: *mut AVStream) -> Self { + Stream { ptr: ptr, _marker: PhantomData } + } + + pub unsafe fn as_ptr(&self) -> *const AVStream { + self.ptr as *const _ + } +} + +impl<'a> Stream<'a> { + pub fn codec(&self) -> codec::Context { + unsafe { + codec::Context::wrap((*self.as_ptr()).codec) + } + } + + pub fn index(&self) -> usize { + unsafe { + (*self.as_ptr()).index as usize + } + } + + pub fn time_base(&self) -> Rational { + unsafe { + Rational::from((*self.as_ptr()).time_base) + } + } + + pub fn start_time(&self) -> i64 { + unsafe { + (*self.as_ptr()).start_time + } + } + + pub fn duration(&self) -> i64 { + unsafe { + (*self.as_ptr()).duration + } + } + + pub fn frames(&self) -> i64 { + unsafe { + (*self.as_ptr()).nb_frames + } + } + + pub fn disposition(&self) -> Disposition { + unsafe { + Disposition::from_bits_truncate((*self.as_ptr()).disposition) + } + } + + pub fn discard(&self) -> Discard { + unsafe { + Discard::from((*self.as_ptr()).discard) + } + } + + pub fn side_data(&self) -> SideDataIter { + unsafe { + SideDataIter::new(self.as_ptr()) + } + } + + pub fn frame_rate(&self) -> Rational { + unsafe { + Rational::from(av_stream_get_r_frame_rate(self.as_ptr())) + } + } +} + +pub struct SideDataIter<'a> { + ptr: *const AVStream, + cur: c_int, + + _marker: PhantomData<&'a Stream<'a>>, +} + +impl<'a> SideDataIter<'a> { + pub fn new(ptr: *const AVStream) -> Self { + SideDataIter { ptr: ptr, cur: 0, _marker: PhantomData } + } +} + +impl<'a> Iterator for SideDataIter<'a> { + type Item = packet::SideData<'a>; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if self.cur >= (*self.ptr).nb_side_data { + None + } + else { + self.cur += 1; + Some(packet::SideData::wrap((*self.ptr).side_data.offset((self.cur - 1) as isize))) + } + } + } +} diff --git a/src/format/stream/stream_mut.rs b/src/format/stream/stream_mut.rs new file mode 100644 index 0000000..63fd3bb --- /dev/null +++ b/src/format/stream/stream_mut.rs @@ -0,0 +1,41 @@ +use std::ops::Deref; + +use ffi::*; +use ::Rational; +use super::Stream; + +#[derive(Eq, PartialEq)] +pub struct StreamMut<'a> { + ptr: *mut AVStream, + imm: Stream<'a>, +} + +impl<'a> StreamMut<'a> { + pub unsafe fn wrap(ptr: *mut AVStream) -> Self { + StreamMut { ptr: ptr, imm: Stream::wrap(ptr) } + } + + pub unsafe fn as_ptr(&self) -> *const AVStream { + self.ptr as *const _ + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVStream { + self.ptr + } +} + +impl<'a> StreamMut<'a> { + pub fn set_frame_rate(&mut self, value: Rational) { + unsafe { + av_stream_set_r_frame_rate(self.as_mut_ptr(), value.into()); + } + } +} + +impl<'a> Deref for StreamMut<'a> { + type Target = Stream<'a>; + + fn deref(&self) -> &Self::Target { + &self.imm + } +} diff --git a/src/lib.rs b/src/lib.rs index f39b40b..b8688d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ pub mod format; #[cfg(feature = "format")] pub use format::format::Format; #[cfg(feature = "format")] -pub use format::stream::Stream; +pub use format::stream::{Stream, StreamMut}; #[cfg(feature = "codec")] pub mod codec;