ffmpeg_next/format/context/
input.rs

1use std::ffi::CString;
2use std::mem;
3use std::ops::{Deref, DerefMut};
4
5use super::common::Context;
6use super::destructor;
7use ffi::*;
8use util::range::Range;
9#[cfg(not(feature = "ffmpeg_5_0"))]
10use Codec;
11use {format, Error, Packet, Stream};
12
13pub struct Input {
14    ptr: *mut AVFormatContext,
15    ctx: Context,
16}
17
18unsafe impl Send for Input {}
19
20impl Input {
21    pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
22        Input {
23            ptr,
24            ctx: Context::wrap(ptr, destructor::Mode::Input),
25        }
26    }
27
28    pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
29        self.ptr as *const _
30    }
31
32    pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
33        self.ptr
34    }
35}
36
37impl Input {
38    pub fn format(&self) -> format::Input {
39        // We get a clippy warning in 4.4 but not in 5.0 and newer, so we allow that cast to not complicate the code
40        #[allow(clippy::unnecessary_cast)]
41        unsafe {
42            format::Input::wrap((*self.as_ptr()).iformat as *mut AVInputFormat)
43        }
44    }
45
46    #[cfg(not(feature = "ffmpeg_5_0"))]
47    pub fn video_codec(&self) -> Option<Codec> {
48        unsafe {
49            let ptr = (*self.as_ptr()).video_codec;
50
51            if ptr.is_null() {
52                None
53            } else {
54                Some(Codec::wrap(ptr))
55            }
56        }
57    }
58
59    #[cfg(not(feature = "ffmpeg_5_0"))]
60    pub fn audio_codec(&self) -> Option<Codec> {
61        unsafe {
62            let ptr = (*self.as_ptr()).audio_codec;
63
64            if ptr.is_null() {
65                None
66            } else {
67                Some(Codec::wrap(ptr))
68            }
69        }
70    }
71
72    #[cfg(not(feature = "ffmpeg_5_0"))]
73    pub fn subtitle_codec(&self) -> Option<Codec> {
74        unsafe {
75            let ptr = (*self.as_ptr()).subtitle_codec;
76
77            if ptr.is_null() {
78                None
79            } else {
80                Some(Codec::wrap(ptr))
81            }
82        }
83    }
84
85    #[cfg(not(feature = "ffmpeg_5_0"))]
86    pub fn data_codec(&self) -> Option<Codec> {
87        unsafe {
88            let ptr = (*self.as_ptr()).data_codec;
89
90            if ptr.is_null() {
91                None
92            } else {
93                Some(Codec::wrap(ptr))
94            }
95        }
96    }
97
98    pub fn probe_score(&self) -> i32 {
99        unsafe { (*self.as_ptr()).probe_score }
100    }
101
102    pub fn packets(&mut self) -> PacketIter<'_> {
103        PacketIter::new(self)
104    }
105
106    pub fn pause(&mut self) -> Result<(), Error> {
107        unsafe {
108            match av_read_pause(self.as_mut_ptr()) {
109                0 => Ok(()),
110                e => Err(Error::from(e)),
111            }
112        }
113    }
114
115    pub fn play(&mut self) -> Result<(), Error> {
116        unsafe {
117            match av_read_play(self.as_mut_ptr()) {
118                0 => Ok(()),
119                e => Err(Error::from(e)),
120            }
121        }
122    }
123
124    pub fn seek<R: Range<i64>>(&mut self, ts: i64, range: R) -> Result<(), Error> {
125        unsafe {
126            match avformat_seek_file(
127                self.as_mut_ptr(),
128                -1,
129                range.start().cloned().unwrap_or(i64::MIN),
130                ts,
131                range.end().cloned().unwrap_or(i64::MAX),
132                0,
133            ) {
134                s if s >= 0 => Ok(()),
135                e => Err(Error::from(e)),
136            }
137        }
138    }
139}
140
141impl Deref for Input {
142    type Target = Context;
143
144    fn deref(&self) -> &Self::Target {
145        &self.ctx
146    }
147}
148
149impl DerefMut for Input {
150    fn deref_mut(&mut self) -> &mut Self::Target {
151        &mut self.ctx
152    }
153}
154
155pub struct PacketIter<'a> {
156    context: &'a mut Input,
157}
158
159impl<'a> PacketIter<'a> {
160    pub fn new(context: &mut Input) -> PacketIter<'_> {
161        PacketIter { context }
162    }
163}
164
165impl<'a> Iterator for PacketIter<'a> {
166    type Item = (Stream<'a>, Packet);
167
168    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
169        let mut packet = Packet::empty();
170
171        loop {
172            match packet.read(self.context) {
173                Ok(..) => unsafe {
174                    return Some((
175                        Stream::wrap(mem::transmute_copy(&self.context), packet.stream()),
176                        packet,
177                    ));
178                },
179
180                Err(Error::Eof) => return None,
181
182                Err(..) => (),
183            }
184        }
185    }
186}
187
188pub fn dump(ctx: &Input, index: i32, url: Option<&str>) {
189    let url = url.map(|u| CString::new(u).unwrap());
190
191    unsafe {
192        av_dump_format(
193            ctx.as_ptr() as *mut _,
194            index,
195            url.unwrap_or_else(|| CString::new("").unwrap()).as_ptr(),
196            0,
197        );
198    }
199}