use std::fmt; use std::mem; use std::ptr; use std::rc::Rc; use super::destructor::{self, Destructor}; use ffi::*; use libc::{c_int, c_uint}; use {media, Chapter, ChapterMut, DictionaryRef, Stream, StreamMut}; pub struct Context { ptr: *mut AVFormatContext, dtor: Rc, } unsafe impl Send for Context {} impl Context { pub unsafe fn wrap(ptr: *mut AVFormatContext, mode: destructor::Mode) -> Self { Context { ptr, dtor: Rc::new(Destructor::new(ptr, mode)), } } pub unsafe fn as_ptr(&self) -> *const AVFormatContext { self.ptr as *const _ } pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext { self.ptr } pub unsafe fn destructor(&self) -> Rc { Rc::clone(&self.dtor) } } impl Context { #[inline] pub fn nb_streams(&self) -> u32 { unsafe { (*self.as_ptr()).nb_streams } } pub fn stream<'a, 'b>(&'a self, index: usize) -> Option> where 'a: 'b, { unsafe { if index >= self.nb_streams() as usize { None } else { Some(Stream::wrap(self, index)) } } } pub fn stream_mut<'a, 'b>(&'a mut self, index: usize) -> Option> where 'a: 'b, { unsafe { if index >= self.nb_streams() as usize { None } else { Some(StreamMut::wrap(self, index)) } } } pub fn streams(&self) -> StreamIter { StreamIter::new(self) } pub fn streams_mut(&mut self) -> StreamIterMut { StreamIterMut::new(self) } pub fn bit_rate(&self) -> i64 { unsafe { (*self.as_ptr()).bit_rate } } pub fn duration(&self) -> i64 { unsafe { (*self.as_ptr()).duration } } #[inline] pub fn nb_chapters(&self) -> u32 { unsafe { (*self.as_ptr()).nb_chapters } } pub fn chapter<'a, 'b>(&'a self, index: usize) -> Option> where 'a: 'b, { unsafe { if index >= self.nb_chapters() as usize { None } else { Some(Chapter::wrap(self, index)) } } } pub fn chapter_mut<'a, 'b>(&'a mut self, index: usize) -> Option> where 'a: 'b, { unsafe { if index >= self.nb_chapters() as usize { None } else { Some(ChapterMut::wrap(self, index)) } } } pub fn chapters(&self) -> ChapterIter { ChapterIter::new(self) } pub fn chapters_mut(&mut self) -> ChapterIterMut { ChapterIterMut::new(self) } pub fn metadata(&self) -> DictionaryRef { unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) } } } pub struct Best<'a> { context: &'a Context, wanted: i32, related: i32, } impl<'a> Best<'a> { pub unsafe fn new<'b, 'c: 'b>(context: &'c Context) -> Best<'b> { Best { context, wanted: -1, related: -1, } } 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> where 'a: 'b, { unsafe { let mut decoder = ptr::null_mut(); let index = av_find_best_stream( self.context.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.context, index as usize)) } else { None } } } } pub struct StreamIter<'a> { context: &'a Context, current: c_uint, } impl<'a> StreamIter<'a> { pub fn new<'s, 'c: 's>(context: &'c Context) -> StreamIter<'s> { StreamIter { context, current: 0, } } } impl<'a> StreamIter<'a> { pub fn wanted<'b, 'c>(&self, stream: &'b Stream) -> Best<'c> where 'a: 'b, 'a: 'c, { unsafe { Best::new(self.context).wanted(stream) } } pub fn related<'b, 'c>(&self, stream: &'b Stream) -> Best<'c> where 'a: 'b, 'a: 'c, { unsafe { Best::new(self.context).related(stream) } } pub fn best<'b>(&self, kind: media::Type) -> Option> where 'a: 'b, { unsafe { Best::new(self.context).best(kind) } } } impl<'a> Iterator for StreamIter<'a> { type Item = Stream<'a>; fn next(&mut self) -> Option<::Item> { unsafe { if self.current >= self.context.nb_streams() { return None; } self.current += 1; Some(Stream::wrap(self.context, (self.current - 1) as usize)) } } fn size_hint(&self) -> (usize, Option) { let length = self.context.nb_streams() as usize; ( length - self.current as usize, Some(length - self.current as usize), ) } } impl<'a> ExactSizeIterator for StreamIter<'a> {} pub struct StreamIterMut<'a> { context: &'a mut Context, current: c_uint, } impl<'a> StreamIterMut<'a> { pub fn new<'s, 'c: 's>(context: &'c mut Context) -> StreamIterMut<'s> { StreamIterMut { context, current: 0, } } } impl<'a> Iterator for StreamIterMut<'a> { type Item = StreamMut<'a>; fn next(&mut self) -> Option<::Item> { if self.current >= self.context.nb_streams() { return None; } self.current += 1; unsafe { Some(StreamMut::wrap( mem::transmute_copy(&self.context), (self.current - 1) as usize, )) } } fn size_hint(&self) -> (usize, Option) { let length = self.context.nb_streams() as usize; ( length - self.current as usize, Some(length - self.current as usize), ) } } impl<'a> ExactSizeIterator for StreamIterMut<'a> {} pub struct ChapterIter<'a> { context: &'a Context, current: c_uint, } impl<'a> ChapterIter<'a> { pub fn new<'s, 'c: 's>(context: &'c Context) -> ChapterIter<'s> { ChapterIter { context, current: 0, } } } impl<'a> Iterator for ChapterIter<'a> { type Item = Chapter<'a>; fn next(&mut self) -> Option<::Item> { unsafe { if self.current >= (*self.context.as_ptr()).nb_chapters { return None; } self.current += 1; Some(Chapter::wrap(self.context, (self.current - 1) as usize)) } } fn size_hint(&self) -> (usize, Option) { unsafe { let length = (*self.context.as_ptr()).nb_chapters as usize; ( length - self.current as usize, Some(length - self.current as usize), ) } } } impl<'a> ExactSizeIterator for ChapterIter<'a> {} pub struct ChapterIterMut<'a> { context: &'a mut Context, current: c_uint, } impl<'a> ChapterIterMut<'a> { pub fn new<'s, 'c: 's>(context: &'c mut Context) -> ChapterIterMut<'s> { ChapterIterMut { context, current: 0, } } } impl<'a> Iterator for ChapterIterMut<'a> { type Item = ChapterMut<'a>; fn next(&mut self) -> Option<::Item> { unsafe { if self.current >= (*self.context.as_ptr()).nb_chapters { return None; } self.current += 1; Some(ChapterMut::wrap( mem::transmute_copy(&self.context), (self.current - 1) as usize, )) } } fn size_hint(&self) -> (usize, Option) { unsafe { let length = (*self.context.as_ptr()).nb_chapters as usize; ( length - self.current as usize, Some(length - self.current as usize), ) } } } impl<'a> ExactSizeIterator for ChapterIterMut<'a> {} impl fmt::Debug for Context { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut s = fmt.debug_struct("AVFormatContext"); s.field("bit_rate", &self.bit_rate()); s.field("duration", &self.duration()); s.field("nb_chapters", &self.nb_chapters()); s.field("nb_streams", &self.nb_streams()); s.finish() } }