Skip to main content

ffmpeg_the_third/format/context/
input.rs

1use std::ffi::CString;
2use std::mem;
3use std::ops::{Bound, Deref, DerefMut, RangeBounds};
4
5use super::common::Context;
6use super::destructor;
7use crate::ffi::*;
8use crate::{format, Error, Packet, Stream};
9
10pub struct Input {
11    ptr: *mut AVFormatContext,
12    ctx: Context,
13}
14
15unsafe impl Send for Input {}
16
17impl Input {
18    pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
19        Input {
20            ptr,
21            ctx: Context::wrap(ptr, destructor::Mode::Input),
22        }
23    }
24
25    pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
26        self.ptr as *const _
27    }
28
29    pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
30        self.ptr
31    }
32}
33
34impl Input {
35    pub fn format(&self) -> format::Input {
36        unsafe { format::Input::from_raw((*self.as_ptr()).iformat).expect("iformat is non-null") }
37    }
38
39    pub fn probe_score(&self) -> i32 {
40        unsafe { (*self.as_ptr()).probe_score }
41    }
42
43    pub fn packets(&mut self) -> PacketIter<'_> {
44        PacketIter::new(self)
45    }
46
47    pub fn pause(&mut self) -> Result<(), Error> {
48        unsafe {
49            match av_read_pause(self.as_mut_ptr()) {
50                0 => Ok(()),
51                e => Err(Error::from(e)),
52            }
53        }
54    }
55
56    pub fn play(&mut self) -> Result<(), Error> {
57        unsafe {
58            match av_read_play(self.as_mut_ptr()) {
59                0 => Ok(()),
60                e => Err(Error::from(e)),
61            }
62        }
63    }
64
65    pub fn seek<R: RangeBounds<i64>>(&mut self, ts: i64, range: R) -> Result<(), Error> {
66        unsafe {
67            let start = match range.start_bound().cloned() {
68                Bound::Included(i) => i,
69                Bound::Excluded(i) => i.saturating_add(1),
70                Bound::Unbounded => i64::MIN,
71            };
72
73            let end = match range.end_bound().cloned() {
74                Bound::Included(i) => i,
75                Bound::Excluded(i) => i.saturating_sub(1),
76                Bound::Unbounded => i64::MAX,
77            };
78
79            match avformat_seek_file(self.as_mut_ptr(), -1, start, ts, end, 0) {
80                s if s >= 0 => Ok(()),
81                e => Err(Error::from(e)),
82            }
83        }
84    }
85}
86
87impl Deref for Input {
88    type Target = Context;
89
90    fn deref(&self) -> &Self::Target {
91        &self.ctx
92    }
93}
94
95impl DerefMut for Input {
96    fn deref_mut(&mut self) -> &mut Self::Target {
97        &mut self.ctx
98    }
99}
100
101pub struct PacketIter<'a> {
102    context: &'a mut Input,
103}
104
105impl<'a> PacketIter<'a> {
106    pub fn new(context: &mut Input) -> PacketIter<'_> {
107        PacketIter { context }
108    }
109}
110
111impl<'a> Iterator for PacketIter<'a> {
112    type Item = Result<(Stream<'a>, Packet), Error>;
113
114    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
115        let mut packet = Packet::empty();
116
117        match packet.read(self.context) {
118            Ok(..) => unsafe {
119                Some(Ok((
120                    Stream::wrap(mem::transmute_copy(&self.context), packet.stream()),
121                    packet,
122                )))
123            },
124
125            Err(Error::Eof) => None,
126
127            Err(e) => Some(Err(e)),
128        }
129    }
130}
131
132pub fn dump(ctx: &Input, index: i32, url: Option<&str>) {
133    let url = url.map(|u| CString::new(u).unwrap());
134
135    unsafe {
136        av_dump_format(
137            ctx.as_ptr() as *mut _,
138            index,
139            url.unwrap_or_else(|| CString::new("").unwrap()).as_ptr(),
140            0,
141        );
142    }
143}