ffmpeg_next/format/context/
common.rs

1use std::fmt;
2use std::mem;
3use std::ptr;
4use std::rc::Rc;
5
6use super::destructor::{self, Destructor};
7use ffi::*;
8use libc::{c_int, c_uint};
9use {media, Chapter, ChapterMut, DictionaryRef, Stream, StreamMut};
10
11pub struct Context {
12    ptr: *mut AVFormatContext,
13    dtor: Rc<Destructor>,
14}
15
16unsafe impl Send for Context {}
17
18impl Context {
19    pub unsafe fn wrap(ptr: *mut AVFormatContext, mode: destructor::Mode) -> Self {
20        Context {
21            ptr,
22            dtor: Rc::new(Destructor::new(ptr, mode)),
23        }
24    }
25
26    pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
27        self.ptr as *const _
28    }
29
30    pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
31        self.ptr
32    }
33
34    pub unsafe fn destructor(&self) -> Rc<Destructor> {
35        Rc::clone(&self.dtor)
36    }
37}
38
39impl Context {
40    #[inline]
41    pub fn nb_streams(&self) -> u32 {
42        unsafe { (*self.as_ptr()).nb_streams }
43    }
44
45    pub fn stream<'a, 'b>(&'a self, index: usize) -> Option<Stream<'b>>
46    where
47        'a: 'b,
48    {
49        unsafe {
50            if index >= self.nb_streams() as usize {
51                None
52            } else {
53                Some(Stream::wrap(self, index))
54            }
55        }
56    }
57
58    pub fn stream_mut<'a, 'b>(&'a mut self, index: usize) -> Option<StreamMut<'b>>
59    where
60        'a: 'b,
61    {
62        unsafe {
63            if index >= self.nb_streams() as usize {
64                None
65            } else {
66                Some(StreamMut::wrap(self, index))
67            }
68        }
69    }
70
71    pub fn streams(&self) -> StreamIter {
72        StreamIter::new(self)
73    }
74
75    pub fn streams_mut(&mut self) -> StreamIterMut {
76        StreamIterMut::new(self)
77    }
78
79    pub fn bit_rate(&self) -> i64 {
80        unsafe { (*self.as_ptr()).bit_rate }
81    }
82
83    pub fn duration(&self) -> i64 {
84        unsafe { (*self.as_ptr()).duration }
85    }
86
87    #[inline]
88    pub fn nb_chapters(&self) -> u32 {
89        unsafe { (*self.as_ptr()).nb_chapters }
90    }
91
92    pub fn chapter<'a, 'b>(&'a self, index: usize) -> Option<Chapter<'b>>
93    where
94        'a: 'b,
95    {
96        unsafe {
97            if index >= self.nb_chapters() as usize {
98                None
99            } else {
100                Some(Chapter::wrap(self, index))
101            }
102        }
103    }
104
105    pub fn chapter_mut<'a, 'b>(&'a mut self, index: usize) -> Option<ChapterMut<'b>>
106    where
107        'a: 'b,
108    {
109        unsafe {
110            if index >= self.nb_chapters() as usize {
111                None
112            } else {
113                Some(ChapterMut::wrap(self, index))
114            }
115        }
116    }
117
118    pub fn chapters(&self) -> ChapterIter {
119        ChapterIter::new(self)
120    }
121
122    pub fn chapters_mut(&mut self) -> ChapterIterMut {
123        ChapterIterMut::new(self)
124    }
125
126    pub fn metadata(&self) -> DictionaryRef {
127        unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
128    }
129}
130
131pub struct Best<'a> {
132    context: &'a Context,
133
134    wanted: i32,
135    related: i32,
136}
137
138impl<'a> Best<'a> {
139    pub unsafe fn new<'b, 'c: 'b>(context: &'c Context) -> Best<'b> {
140        Best {
141            context,
142
143            wanted: -1,
144            related: -1,
145        }
146    }
147
148    pub fn wanted<'b>(mut self, stream: &'b Stream) -> Best<'a>
149    where
150        'a: 'b,
151    {
152        self.wanted = stream.index() as i32;
153        self
154    }
155
156    pub fn related<'b>(mut self, stream: &'b Stream) -> Best<'a>
157    where
158        'a: 'b,
159    {
160        self.related = stream.index() as i32;
161        self
162    }
163
164    pub fn best<'b>(self, kind: media::Type) -> Option<Stream<'b>>
165    where
166        'a: 'b,
167    {
168        unsafe {
169            let decoder = ptr::null_mut();
170            let index = av_find_best_stream(
171                self.context.ptr,
172                kind.into(),
173                self.wanted as c_int,
174                self.related as c_int,
175                decoder,
176                0,
177            );
178
179            if index >= 0 {
180                Some(Stream::wrap(self.context, index as usize))
181            } else {
182                None
183            }
184        }
185    }
186}
187
188pub struct StreamIter<'a> {
189    context: &'a Context,
190    current: c_uint,
191}
192
193impl<'a> StreamIter<'a> {
194    pub fn new<'s, 'c: 's>(context: &'c Context) -> StreamIter<'s> {
195        StreamIter {
196            context,
197            current: 0,
198        }
199    }
200}
201
202impl<'a> StreamIter<'a> {
203    pub fn wanted<'b, 'c>(&self, stream: &'b Stream) -> Best<'c>
204    where
205        'a: 'b,
206        'a: 'c,
207    {
208        unsafe { Best::new(self.context).wanted(stream) }
209    }
210
211    pub fn related<'b, 'c>(&self, stream: &'b Stream) -> Best<'c>
212    where
213        'a: 'b,
214        'a: 'c,
215    {
216        unsafe { Best::new(self.context).related(stream) }
217    }
218
219    pub fn best<'b>(&self, kind: media::Type) -> Option<Stream<'b>>
220    where
221        'a: 'b,
222    {
223        unsafe { Best::new(self.context).best(kind) }
224    }
225}
226
227impl<'a> Iterator for StreamIter<'a> {
228    type Item = Stream<'a>;
229
230    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
231        unsafe {
232            if self.current >= self.context.nb_streams() {
233                return None;
234            }
235
236            self.current += 1;
237
238            Some(Stream::wrap(self.context, (self.current - 1) as usize))
239        }
240    }
241
242    fn size_hint(&self) -> (usize, Option<usize>) {
243        let length = self.context.nb_streams() as usize;
244
245        (
246            length - self.current as usize,
247            Some(length - self.current as usize),
248        )
249    }
250}
251
252impl<'a> ExactSizeIterator for StreamIter<'a> {}
253
254pub struct StreamIterMut<'a> {
255    context: &'a mut Context,
256    current: c_uint,
257}
258
259impl<'a> StreamIterMut<'a> {
260    pub fn new<'s, 'c: 's>(context: &'c mut Context) -> StreamIterMut<'s> {
261        StreamIterMut {
262            context,
263            current: 0,
264        }
265    }
266}
267
268impl<'a> Iterator for StreamIterMut<'a> {
269    type Item = StreamMut<'a>;
270
271    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
272        if self.current >= self.context.nb_streams() {
273            return None;
274        }
275        self.current += 1;
276
277        unsafe {
278            Some(StreamMut::wrap(
279                mem::transmute_copy(&self.context),
280                (self.current - 1) as usize,
281            ))
282        }
283    }
284
285    fn size_hint(&self) -> (usize, Option<usize>) {
286        let length = self.context.nb_streams() as usize;
287
288        (
289            length - self.current as usize,
290            Some(length - self.current as usize),
291        )
292    }
293}
294
295impl<'a> ExactSizeIterator for StreamIterMut<'a> {}
296
297pub struct ChapterIter<'a> {
298    context: &'a Context,
299    current: c_uint,
300}
301
302impl<'a> ChapterIter<'a> {
303    pub fn new<'s, 'c: 's>(context: &'c Context) -> ChapterIter<'s> {
304        ChapterIter {
305            context,
306            current: 0,
307        }
308    }
309}
310
311impl<'a> Iterator for ChapterIter<'a> {
312    type Item = Chapter<'a>;
313
314    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
315        unsafe {
316            if self.current >= (*self.context.as_ptr()).nb_chapters {
317                return None;
318            }
319
320            self.current += 1;
321
322            Some(Chapter::wrap(self.context, (self.current - 1) as usize))
323        }
324    }
325
326    fn size_hint(&self) -> (usize, Option<usize>) {
327        unsafe {
328            let length = (*self.context.as_ptr()).nb_chapters as usize;
329
330            (
331                length - self.current as usize,
332                Some(length - self.current as usize),
333            )
334        }
335    }
336}
337
338impl<'a> ExactSizeIterator for ChapterIter<'a> {}
339
340pub struct ChapterIterMut<'a> {
341    context: &'a mut Context,
342    current: c_uint,
343}
344
345impl<'a> ChapterIterMut<'a> {
346    pub fn new<'s, 'c: 's>(context: &'c mut Context) -> ChapterIterMut<'s> {
347        ChapterIterMut {
348            context,
349            current: 0,
350        }
351    }
352}
353
354impl<'a> Iterator for ChapterIterMut<'a> {
355    type Item = ChapterMut<'a>;
356
357    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
358        unsafe {
359            if self.current >= (*self.context.as_ptr()).nb_chapters {
360                return None;
361            }
362
363            self.current += 1;
364
365            Some(ChapterMut::wrap(
366                mem::transmute_copy(&self.context),
367                (self.current - 1) as usize,
368            ))
369        }
370    }
371
372    fn size_hint(&self) -> (usize, Option<usize>) {
373        unsafe {
374            let length = (*self.context.as_ptr()).nb_chapters as usize;
375
376            (
377                length - self.current as usize,
378                Some(length - self.current as usize),
379            )
380        }
381    }
382}
383
384impl<'a> ExactSizeIterator for ChapterIterMut<'a> {}
385
386impl fmt::Debug for Context {
387    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
388        let mut s = fmt.debug_struct("AVFormatContext");
389        s.field("bit_rate", &self.bit_rate());
390        s.field("duration", &self.duration());
391        s.field("nb_chapters", &self.nb_chapters());
392        s.field("nb_streams", &self.nb_streams());
393        s.finish()
394    }
395}