ffmpeg_rs/format/
mod.rs

1pub use util::format::{pixel, Pixel};
2pub use util::format::{sample, Sample};
3use util::interrupt;
4
5pub mod stream;
6
7pub mod chapter;
8
9pub mod context;
10pub use self::context::Context;
11
12pub mod format;
13#[cfg(not(feature = "ffmpeg_5_0"))]
14pub use self::format::list;
15pub use self::format::{flag, Flags, SeekFlags};
16pub use self::format::{Input, Output};
17
18pub mod network;
19
20use std::ffi::{CStr, CString};
21use std::path::Path;
22use std::ptr;
23use std::str::from_utf8_unchecked;
24
25use ffi::*;
26use {Dictionary, Error, Format};
27
28#[cfg(not(feature = "ffmpeg_5_0"))]
29pub fn register_all() {
30    unsafe {
31        av_register_all();
32    }
33}
34
35#[cfg(not(feature = "ffmpeg_5_0"))]
36pub fn register(format: &Format) {
37    match *format {
38        Format::Input(ref format) => unsafe {
39            av_register_input_format(format.as_ptr() as *mut _);
40        },
41
42        Format::Output(ref format) => unsafe {
43            av_register_output_format(format.as_ptr() as *mut _);
44        },
45    }
46}
47
48pub fn version() -> u32 {
49    unsafe { avformat_version() }
50}
51
52pub fn configuration() -> &'static str {
53    unsafe { from_utf8_unchecked(CStr::from_ptr(avformat_configuration()).to_bytes()) }
54}
55
56pub 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
61fn 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
66pub 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
103pub 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
151pub fn input<P: AsRef<Path>>(path: &P) -> Result<context::Input, Error> {
152    unsafe {
153        let mut ps = ptr::null_mut();
154        let path = 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(ps)),
159                e => {
160                    avformat_close_input(&mut ps);
161                    Err(Error::from(e))
162                }
163            },
164
165            e => Err(Error::from(e)),
166        }
167    }
168}
169
170pub fn input_with_dictionary<P: AsRef<Path>>(
171    path: &P,
172    options: Dictionary,
173) -> Result<context::Input, Error> {
174    unsafe {
175        let mut ps = ptr::null_mut();
176        let path = from_path(path);
177        let mut opts = options.disown();
178        let res = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts);
179
180        Dictionary::own(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(ps)),
185                e => {
186                    avformat_close_input(&mut ps);
187                    Err(Error::from(e))
188                }
189            },
190
191            e => Err(Error::from(e)),
192        }
193    }
194}
195
196pub fn input_with_interrupt<P: AsRef<Path>, F>(
197    path: &P,
198    closure: F,
199) -> Result<context::Input, Error>
200where
201    F: FnMut() -> bool,
202{
203    unsafe {
204        let mut ps = avformat_alloc_context();
205        let path = from_path(path);
206        (*ps).interrupt_callback = interrupt::new(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(ps)),
211                e => {
212                    avformat_close_input(&mut ps);
213                    Err(Error::from(e))
214                }
215            },
216
217            e => Err(Error::from(e)),
218        }
219    }
220}
221
222pub fn output<P: AsRef<Path>>(path: &P) -> Result<context::Output, Error> {
223    unsafe {
224        let mut ps = ptr::null_mut();
225        let path = 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(ps)),
230                e => Err(Error::from(e)),
231            },
232
233            e => Err(Error::from(e)),
234        }
235    }
236}
237
238pub 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
270pub fn output_as<P: AsRef<Path>>(path: &P, format: &str) -> Result<context::Output, Error> {
271    unsafe {
272        let mut ps = ptr::null_mut();
273        let path = from_path(path);
274        let format = 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(ps)),
284                e => Err(Error::from(e)),
285            },
286
287            e => Err(Error::from(e)),
288        }
289    }
290}
291
292pub 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}