playa_ffmpeg/format/
mod.rs

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