1 | pub use util::format::{pixel, Pixel}; |
2 | pub use util::format::{sample, Sample}; |
3 | use util::interrupt; |
4 | |
5 | pub mod stream; |
6 | |
7 | pub mod chapter; |
8 | |
9 | pub mod context; |
10 | pub use self::context::Context; |
11 | |
12 | pub mod format; |
13 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
14 | pub use self::format::list; |
15 | pub use self::format::{flag, Flags}; |
16 | pub use self::format::{Input, Output}; |
17 | |
18 | pub mod network; |
19 | |
20 | use std::ffi::{CStr, CString}; |
21 | use std::path::Path; |
22 | use std::ptr; |
23 | use std::str::from_utf8_unchecked; |
24 | |
25 | use ffi::*; |
26 | use {Dictionary, Error, Format}; |
27 | |
28 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
29 | pub fn register_all() { |
30 | unsafe { |
31 | av_register_all(); |
32 | } |
33 | } |
34 | |
35 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
36 | pub fn register(format: &Format) { |
37 | match *format { |
38 | Format::Input(ref format: &Input) => unsafe { |
39 | av_register_input_format(format.as_ptr() as *mut _); |
40 | }, |
41 | |
42 | Format::Output(ref format: &Output) => unsafe { |
43 | av_register_output_format(format.as_ptr() as *mut _); |
44 | }, |
45 | } |
46 | } |
47 | |
48 | pub fn version() -> u32 { |
49 | unsafe { avformat_version() } |
50 | } |
51 | |
52 | pub fn configuration() -> &'static str { |
53 | unsafe { from_utf8_unchecked(CStr::from_ptr(avformat_configuration()).to_bytes()) } |
54 | } |
55 | |
56 | pub fn license() -> &'static str { |
57 | unsafe { from_utf8_unchecked(CStr::from_ptr(avformat_license()).to_bytes()) } |
58 | } |
59 | |
60 | // XXX: use to_cstring when stable |
61 | fn from_path<P: AsRef<Path>>(path: &P) -> CString { |
62 | CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap() |
63 | } |
64 | |
65 | // NOTE: this will be better with specialization or anonymous return types |
66 | pub fn open<P: AsRef<Path>>(path: &P, format: &Format) -> Result<Context, Error> { |
67 | unsafe { |
68 | let mut ps = ptr::null_mut(); |
69 | let path = from_path(path); |
70 | |
71 | match *format { |
72 | Format::Input(ref format) => match avformat_open_input( |
73 | &mut ps, |
74 | path.as_ptr(), |
75 | format.as_ptr() as *mut _, |
76 | ptr::null_mut(), |
77 | ) { |
78 | 0 => match avformat_find_stream_info(ps, ptr::null_mut()) { |
79 | r if r >= 0 => Ok(Context::Input(context::Input::wrap(ps))), |
80 | e => Err(Error::from(e)), |
81 | }, |
82 | |
83 | e => Err(Error::from(e)), |
84 | }, |
85 | |
86 | Format::Output(ref format) => match avformat_alloc_output_context2( |
87 | &mut ps, |
88 | format.as_ptr() as *mut _, |
89 | ptr::null(), |
90 | path.as_ptr(), |
91 | ) { |
92 | 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { |
93 | 0 => Ok(Context::Output(context::Output::wrap(ps))), |
94 | e => Err(Error::from(e)), |
95 | }, |
96 | |
97 | e => Err(Error::from(e)), |
98 | }, |
99 | } |
100 | } |
101 | } |
102 | |
103 | pub fn open_with<P: AsRef<Path>>( |
104 | path: &P, |
105 | format: &Format, |
106 | options: Dictionary, |
107 | ) -> Result<Context, Error> { |
108 | unsafe { |
109 | let mut ps = ptr::null_mut(); |
110 | let path = from_path(path); |
111 | let mut opts = options.disown(); |
112 | |
113 | match *format { |
114 | Format::Input(ref format) => { |
115 | let res = avformat_open_input( |
116 | &mut ps, |
117 | path.as_ptr(), |
118 | format.as_ptr() as *mut _, |
119 | &mut opts, |
120 | ); |
121 | |
122 | Dictionary::own(opts); |
123 | |
124 | match res { |
125 | 0 => match avformat_find_stream_info(ps, ptr::null_mut()) { |
126 | r if r >= 0 => Ok(Context::Input(context::Input::wrap(ps))), |
127 | e => Err(Error::from(e)), |
128 | }, |
129 | |
130 | e => Err(Error::from(e)), |
131 | } |
132 | } |
133 | |
134 | Format::Output(ref format) => match avformat_alloc_output_context2( |
135 | &mut ps, |
136 | format.as_ptr() as *mut _, |
137 | ptr::null(), |
138 | path.as_ptr(), |
139 | ) { |
140 | 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { |
141 | 0 => Ok(Context::Output(context::Output::wrap(ps))), |
142 | e => Err(Error::from(e)), |
143 | }, |
144 | |
145 | e => Err(Error::from(e)), |
146 | }, |
147 | } |
148 | } |
149 | } |
150 | |
151 | pub fn input<P: AsRef<Path>>(path: &P) -> Result<context::Input, Error> { |
152 | unsafe { |
153 | let mut ps: *mut {unknown} = ptr::null_mut(); |
154 | let path: CString = from_path(path); |
155 | |
156 | match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) { |
157 | 0 => match avformat_find_stream_info(ps, ptr::null_mut()) { |
158 | r if r >= 0 => Ok(context::Input::wrap(ptr:ps)), |
159 | e => { |
160 | avformat_close_input(&mut ps); |
161 | Err(Error::from(e)) |
162 | } |
163 | }, |
164 | |
165 | e: i32 => Err(Error::from(e)), |
166 | } |
167 | } |
168 | } |
169 | |
170 | pub fn input_with_dictionary<P: AsRef<Path>>( |
171 | path: &P, |
172 | options: Dictionary, |
173 | ) -> Result<context::Input, Error> { |
174 | unsafe { |
175 | let mut ps: *mut {unknown} = ptr::null_mut(); |
176 | let path: CString = from_path(path); |
177 | let mut opts: *mut {unknown} = options.disown(); |
178 | let res: i32 = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts); |
179 | |
180 | Dictionary::own(ptr:opts); |
181 | |
182 | match res { |
183 | 0 => match avformat_find_stream_info(ps, ptr::null_mut()) { |
184 | r if r >= 0 => Ok(context::Input::wrap(ptr:ps)), |
185 | e => { |
186 | avformat_close_input(&mut ps); |
187 | Err(Error::from(e)) |
188 | } |
189 | }, |
190 | |
191 | e: i32 => Err(Error::from(e)), |
192 | } |
193 | } |
194 | } |
195 | |
196 | pub fn input_with_interrupt<P: AsRef<Path>, F>( |
197 | path: &P, |
198 | closure: F, |
199 | ) -> Result<context::Input, Error> |
200 | where |
201 | F: FnMut() -> bool, |
202 | { |
203 | unsafe { |
204 | let mut ps: *mut {unknown} = avformat_alloc_context(); |
205 | let path: CString = from_path(path); |
206 | (*ps).interrupt_callback = interrupt::new(opaque:Box::new(closure)).interrupt; |
207 | |
208 | match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) { |
209 | 0 => match avformat_find_stream_info(ps, ptr::null_mut()) { |
210 | r if r >= 0 => Ok(context::Input::wrap(ptr:ps)), |
211 | e => { |
212 | avformat_close_input(&mut ps); |
213 | Err(Error::from(e)) |
214 | } |
215 | }, |
216 | |
217 | e: i32 => Err(Error::from(e)), |
218 | } |
219 | } |
220 | } |
221 | |
222 | pub fn output<P: AsRef<Path>>(path: &P) -> Result<context::Output, Error> { |
223 | unsafe { |
224 | let mut ps: *mut {unknown} = ptr::null_mut(); |
225 | let path: CString = from_path(path); |
226 | |
227 | match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr()) { |
228 | 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { |
229 | 0 => Ok(context::Output::wrap(ptr:ps)), |
230 | e: i32 => Err(Error::from(e)), |
231 | }, |
232 | |
233 | e: i32 => Err(Error::from(e)), |
234 | } |
235 | } |
236 | } |
237 | |
238 | pub fn output_with<P: AsRef<Path>>( |
239 | path: &P, |
240 | options: Dictionary, |
241 | ) -> Result<context::Output, Error> { |
242 | unsafe { |
243 | let mut ps = ptr::null_mut(); |
244 | let path = from_path(path); |
245 | let mut opts = options.disown(); |
246 | |
247 | match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr()) { |
248 | 0 => { |
249 | let res = avio_open2( |
250 | &mut (*ps).pb, |
251 | path.as_ptr(), |
252 | AVIO_FLAG_WRITE, |
253 | ptr::null(), |
254 | &mut opts, |
255 | ); |
256 | |
257 | Dictionary::own(opts); |
258 | |
259 | match res { |
260 | 0 => Ok(context::Output::wrap(ps)), |
261 | e => Err(Error::from(e)), |
262 | } |
263 | } |
264 | |
265 | e => Err(Error::from(e)), |
266 | } |
267 | } |
268 | } |
269 | |
270 | pub fn output_as<P: AsRef<Path>>(path: &P, format: &str) -> Result<context::Output, Error> { |
271 | unsafe { |
272 | let mut ps: *mut {unknown} = ptr::null_mut(); |
273 | let path: CString = from_path(path); |
274 | let format: CString = CString::new(format).unwrap(); |
275 | |
276 | match avformat_alloc_output_context2( |
277 | &mut ps, |
278 | ptr::null_mut(), |
279 | format.as_ptr(), |
280 | path.as_ptr(), |
281 | ) { |
282 | 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { |
283 | 0 => Ok(context::Output::wrap(ptr:ps)), |
284 | e: i32 => Err(Error::from(e)), |
285 | }, |
286 | |
287 | e: i32 => Err(Error::from(e)), |
288 | } |
289 | } |
290 | } |
291 | |
292 | pub fn output_as_with<P: AsRef<Path>>( |
293 | path: &P, |
294 | format: &str, |
295 | options: Dictionary, |
296 | ) -> Result<context::Output, Error> { |
297 | unsafe { |
298 | let mut ps = ptr::null_mut(); |
299 | let path = from_path(path); |
300 | let format = CString::new(format).unwrap(); |
301 | let mut opts = options.disown(); |
302 | |
303 | match avformat_alloc_output_context2( |
304 | &mut ps, |
305 | ptr::null_mut(), |
306 | format.as_ptr(), |
307 | path.as_ptr(), |
308 | ) { |
309 | 0 => { |
310 | let res = avio_open2( |
311 | &mut (*ps).pb, |
312 | path.as_ptr(), |
313 | AVIO_FLAG_WRITE, |
314 | ptr::null(), |
315 | &mut opts, |
316 | ); |
317 | |
318 | Dictionary::own(opts); |
319 | |
320 | match res { |
321 | 0 => Ok(context::Output::wrap(ps)), |
322 | e => Err(Error::from(e)), |
323 | } |
324 | } |
325 | |
326 | e => Err(Error::from(e)), |
327 | } |
328 | } |
329 | } |
330 | |