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