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
59fn from_path<P: AsRef<Path> + ?Sized>(path: &P) -> CString {
61 CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap()
62}
63
64pub 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}