ffmpeg_rs/format/context/
input.rs1use 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}