ffmpeg_rs/format/context/
input.rs

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