Skip to main content

ffmpeg_the_third/format/
mod.rs

1#[cfg(feature = "ffmpeg_8_1")]
2pub use crate::util::format::AlphaMode;
3pub use crate::util::format::{pixel, Pixel};
4pub use crate::util::format::{sample, Sample};
5
6use crate::util::interrupt;
7
8pub mod stream;
9
10pub mod chapter;
11
12pub mod context;
13pub use self::context::Context;
14
15pub mod format;
16pub use self::format::{flag, Flags};
17pub use self::format::{Input, Output};
18
19pub mod network;
20
21use std::ffi::{CString, OsStr};
22use std::ptr;
23
24use crate::ffi::*;
25use crate::utils;
26use crate::{AsMutPtr, Error};
27
28pub fn version() -> u32 {
29    unsafe { avformat_version() }
30}
31
32pub fn configuration() -> &'static str {
33    unsafe { utils::str_from_c_ptr(avformat_configuration()) }
34}
35
36pub fn license() -> &'static str {
37    unsafe { utils::str_from_c_ptr(avformat_license()) }
38}
39
40pub fn input<P: AsRef<OsStr>>(path_or_url: P) -> Result<context::Input, Error> {
41    unsafe {
42        let mut ps = ptr::null_mut();
43        let path = from_os_str(path_or_url);
44
45        match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) {
46            0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
47                r if r >= 0 => Ok(context::Input::wrap(ps)),
48                e => {
49                    avformat_close_input(&mut ps);
50                    Err(Error::from(e))
51                }
52            },
53
54            e => Err(Error::from(e)),
55        }
56    }
57}
58
59pub fn input_with_dictionary<P, Dict>(
60    path_or_url: P,
61    mut options: Dict,
62) -> Result<context::Input, Error>
63where
64    Dict: AsMutPtr<*mut AVDictionary>,
65    P: AsRef<OsStr>,
66{
67    unsafe {
68        let mut ps = ptr::null_mut();
69        let path = from_os_str(path_or_url);
70        let res = avformat_open_input(
71            &mut ps,
72            path.as_ptr(),
73            ptr::null_mut(),
74            options.as_mut_ptr(),
75        );
76
77        match res {
78            0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
79                r if r >= 0 => Ok(context::Input::wrap(ps)),
80                e => {
81                    avformat_close_input(&mut ps);
82                    Err(Error::from(e))
83                }
84            },
85
86            e => Err(Error::from(e)),
87        }
88    }
89}
90
91pub fn input_with_interrupt<P, F>(path_or_url: P, closure: F) -> Result<context::Input, Error>
92where
93    P: AsRef<OsStr>,
94    F: FnMut() -> bool,
95{
96    unsafe {
97        let mut ps = avformat_alloc_context();
98        let path = from_os_str(path_or_url);
99        (*ps).interrupt_callback = interrupt::new(Box::new(closure)).interrupt;
100
101        match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) {
102            0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
103                r if r >= 0 => Ok(context::Input::wrap(ps)),
104                e => {
105                    avformat_close_input(&mut ps);
106                    Err(Error::from(e))
107                }
108            },
109
110            e => Err(Error::from(e)),
111        }
112    }
113}
114
115fn from_os_str(path_or_url: impl AsRef<OsStr>) -> CString {
116    CString::new(path_or_url.as_ref().as_encoded_bytes()).unwrap()
117}
118
119fn alloc_context(
120    format_name: *const libc::c_char,
121    filename: *const libc::c_char,
122) -> Result<context::Output, Error> {
123    let mut ps = ptr::null_mut();
124
125    unsafe {
126        let res = avformat_alloc_output_context2(&mut ps, ptr::null(), format_name, filename);
127        if res >= 0 {
128            Ok(context::Output::wrap(ps))
129        } else {
130            Err(Error::from(res))
131        }
132    }
133}
134
135fn open_context_write(
136    ctx: &mut context::Output,
137    filename: *const libc::c_char,
138    opts: *mut *mut AVDictionary,
139) -> Result<(), Error> {
140    let res = unsafe {
141        avio_open2(
142            &mut (*ctx.as_mut_ptr()).pb,
143            filename,
144            AVIO_FLAG_WRITE,
145            ptr::null(),
146            opts,
147        )
148    };
149
150    if res >= 0 {
151        Ok(())
152    } else {
153        Err(Error::from(res))
154    }
155}
156
157pub fn output<P: AsRef<OsStr>>(path_or_url: P) -> Result<context::Output, Error> {
158    let filename = from_os_str(path_or_url);
159    let mut ctx = alloc_context(ptr::null(), filename.as_ptr())?;
160
161    if !ctx.format().flags().contains(Flags::NO_FILE) {
162        open_context_write(&mut ctx, filename.as_ptr(), ptr::null_mut())?;
163    }
164
165    Ok(ctx)
166}
167
168pub fn output_with<P, Dict>(path_or_url: P, mut options: Dict) -> Result<context::Output, Error>
169where
170    P: AsRef<OsStr>,
171    Dict: AsMutPtr<*mut AVDictionary>,
172{
173    let path = from_os_str(path_or_url);
174    let mut ctx = alloc_context(ptr::null(), path.as_ptr())?;
175
176    if !ctx.format().flags().contains(Flags::NO_FILE) {
177        open_context_write(&mut ctx, path.as_ptr(), options.as_mut_ptr())?;
178    }
179
180    Ok(ctx)
181}
182
183pub fn output_as<P: AsRef<OsStr>>(path_or_url: P, format: &str) -> Result<context::Output, Error> {
184    let path = from_os_str(path_or_url);
185    let format = CString::new(format).unwrap();
186    let mut ctx = alloc_context(format.as_ptr(), path.as_ptr())?;
187
188    if !ctx.format().flags().contains(Flags::NO_FILE) {
189        open_context_write(&mut ctx, path.as_ptr(), ptr::null_mut())?;
190    }
191
192    Ok(ctx)
193}
194
195pub fn output_as_with<P, Dict>(
196    path_or_url: P,
197    format: &str,
198    mut options: Dict,
199) -> Result<context::Output, Error>
200where
201    P: AsRef<OsStr>,
202    Dict: AsMutPtr<*mut AVDictionary>,
203{
204    let path = from_os_str(path_or_url);
205    let format = CString::new(format).unwrap();
206    let mut ctx = alloc_context(format.as_ptr(), path.as_ptr())?;
207
208    if !ctx.format().flags().contains(Flags::NO_FILE) {
209        open_context_write(&mut ctx, path.as_ptr(), options.as_mut_ptr())?;
210    }
211
212    Ok(ctx)
213}