1use std::error;
2use std::ffi::CStr;
3use std::fmt;
4use std::io;
5use std::str::from_utf8_unchecked;
6
7use ffi::{
8 av_strerror, AVERROR, AVERROR_BSF_NOT_FOUND, AVERROR_BUFFER_TOO_SMALL, AVERROR_BUG,
9 AVERROR_BUG2, AVERROR_DECODER_NOT_FOUND, AVERROR_DEMUXER_NOT_FOUND, AVERROR_ENCODER_NOT_FOUND,
10 AVERROR_EOF, AVERROR_EXIT, AVERROR_EXPERIMENTAL, AVERROR_EXTERNAL, AVERROR_FILTER_NOT_FOUND,
11 AVERROR_HTTP_BAD_REQUEST, AVERROR_HTTP_FORBIDDEN, AVERROR_HTTP_NOT_FOUND,
12 AVERROR_HTTP_OTHER_4XX, AVERROR_HTTP_SERVER_ERROR, AVERROR_HTTP_UNAUTHORIZED,
13 AVERROR_INPUT_CHANGED, AVERROR_INVALIDDATA, AVERROR_MUXER_NOT_FOUND, AVERROR_OPTION_NOT_FOUND,
14 AVERROR_OUTPUT_CHANGED, AVERROR_PATCHWELCOME, AVERROR_PROTOCOL_NOT_FOUND,
15 AVERROR_STREAM_NOT_FOUND, AVERROR_UNKNOWN, AVUNERROR, AV_ERROR_MAX_STRING_SIZE,
16};
17use libc::{c_char, c_int};
18
19// Export POSIX error codes so that users can do something like
20//
21// if error == (Error::Other { errno: EAGAIN }) {
22// ...
23// }
24pub use libc::{
25 E2BIG, EACCES, EADDRINUSE, EADDRNOTAVAIL, EAFNOSUPPORT, EAGAIN, EALREADY, EBADF, EBADMSG,
26 EBUSY, ECANCELED, ECHILD, ECONNABORTED, ECONNREFUSED, ECONNRESET, EDEADLK, EDESTADDRREQ, EDOM,
27 EEXIST, EFAULT, EFBIG, EHOSTUNREACH, EIDRM, EILSEQ, EINPROGRESS, EINTR, EINVAL, EIO, EISCONN,
28 EISDIR, ELOOP, EMFILE, EMLINK, EMSGSIZE, ENAMETOOLONG, ENETDOWN, ENETRESET, ENETUNREACH,
29 ENFILE, ENOBUFS, ENODEV, ENOENT, ENOEXEC, ENOLCK, ENOLINK, ENOMEM, ENOMSG, ENOPROTOOPT, ENOSPC,
30 ENOSYS, ENOTCONN, ENOTDIR, ENOTEMPTY, ENOTRECOVERABLE, ENOTSOCK, ENOTSUP, ENOTTY, ENXIO,
31 EOPNOTSUPP, EOVERFLOW, EOWNERDEAD, EPERM, EPIPE, EPROTO, EPROTONOSUPPORT, EPROTOTYPE, ERANGE,
32 EROFS, ESPIPE, ESRCH, ETIMEDOUT, ETXTBSY, EWOULDBLOCK, EXDEV,
33};
34#[cfg(not(any(target_os = "freebsd", target_os = "wasi")))]
35pub use libc::{ENODATA, ENOSR, ENOSTR, ETIME};
36
37#[derive(Copy, Clone, PartialEq, Eq)]
38pub enum Error {
39 Bug,
40 Bug2,
41 Unknown,
42 Experimental,
43 BufferTooSmall,
44 Eof,
45 Exit,
46 External,
47 InvalidData,
48 PatchWelcome,
49
50 InputChanged,
51 OutputChanged,
52
53 BsfNotFound,
54 DecoderNotFound,
55 DemuxerNotFound,
56 EncoderNotFound,
57 OptionNotFound,
58 MuxerNotFound,
59 FilterNotFound,
60 ProtocolNotFound,
61 StreamNotFound,
62
63 HttpBadRequest,
64 HttpUnauthorized,
65 HttpForbidden,
66 HttpNotFound,
67 HttpOther4xx,
68 HttpServerError,
69
70 /// For AVERROR(e) wrapping POSIX error codes, e.g. AVERROR(EAGAIN).
71 Other {
72 errno: c_int,
73 },
74}
75
76impl From<c_int> for Error {
77 fn from(value: c_int) -> Error {
78 match value {
79 AVERROR_BSF_NOT_FOUND => Error::BsfNotFound,
80 AVERROR_BUG => Error::Bug,
81 AVERROR_BUFFER_TOO_SMALL => Error::BufferTooSmall,
82 AVERROR_DECODER_NOT_FOUND => Error::DecoderNotFound,
83 AVERROR_DEMUXER_NOT_FOUND => Error::DemuxerNotFound,
84 AVERROR_ENCODER_NOT_FOUND => Error::EncoderNotFound,
85 AVERROR_EOF => Error::Eof,
86 AVERROR_EXIT => Error::Exit,
87 AVERROR_EXTERNAL => Error::External,
88 AVERROR_FILTER_NOT_FOUND => Error::FilterNotFound,
89 AVERROR_INVALIDDATA => Error::InvalidData,
90 AVERROR_MUXER_NOT_FOUND => Error::MuxerNotFound,
91 AVERROR_OPTION_NOT_FOUND => Error::OptionNotFound,
92 AVERROR_PATCHWELCOME => Error::PatchWelcome,
93 AVERROR_PROTOCOL_NOT_FOUND => Error::ProtocolNotFound,
94 AVERROR_STREAM_NOT_FOUND => Error::StreamNotFound,
95 AVERROR_BUG2 => Error::Bug2,
96 AVERROR_UNKNOWN => Error::Unknown,
97 AVERROR_EXPERIMENTAL => Error::Experimental,
98 AVERROR_INPUT_CHANGED => Error::InputChanged,
99 AVERROR_OUTPUT_CHANGED => Error::OutputChanged,
100 AVERROR_HTTP_BAD_REQUEST => Error::HttpBadRequest,
101 AVERROR_HTTP_UNAUTHORIZED => Error::HttpUnauthorized,
102 AVERROR_HTTP_FORBIDDEN => Error::HttpForbidden,
103 AVERROR_HTTP_NOT_FOUND => Error::HttpNotFound,
104 AVERROR_HTTP_OTHER_4XX => Error::HttpOther4xx,
105 AVERROR_HTTP_SERVER_ERROR => Error::HttpServerError,
106 e => Error::Other {
107 errno: AVUNERROR(e),
108 },
109 }
110 }
111}
112
113impl From<Error> for c_int {
114 fn from(value: Error) -> c_int {
115 match value {
116 Error::BsfNotFound => AVERROR_BSF_NOT_FOUND,
117 Error::Bug => AVERROR_BUG,
118 Error::BufferTooSmall => AVERROR_BUFFER_TOO_SMALL,
119 Error::DecoderNotFound => AVERROR_DECODER_NOT_FOUND,
120 Error::DemuxerNotFound => AVERROR_DEMUXER_NOT_FOUND,
121 Error::EncoderNotFound => AVERROR_ENCODER_NOT_FOUND,
122 Error::Eof => AVERROR_EOF,
123 Error::Exit => AVERROR_EXIT,
124 Error::External => AVERROR_EXTERNAL,
125 Error::FilterNotFound => AVERROR_FILTER_NOT_FOUND,
126 Error::InvalidData => AVERROR_INVALIDDATA,
127 Error::MuxerNotFound => AVERROR_MUXER_NOT_FOUND,
128 Error::OptionNotFound => AVERROR_OPTION_NOT_FOUND,
129 Error::PatchWelcome => AVERROR_PATCHWELCOME,
130 Error::ProtocolNotFound => AVERROR_PROTOCOL_NOT_FOUND,
131 Error::StreamNotFound => AVERROR_STREAM_NOT_FOUND,
132 Error::Bug2 => AVERROR_BUG2,
133 Error::Unknown => AVERROR_UNKNOWN,
134 Error::Experimental => AVERROR_EXPERIMENTAL,
135 Error::InputChanged => AVERROR_INPUT_CHANGED,
136 Error::OutputChanged => AVERROR_OUTPUT_CHANGED,
137 Error::HttpBadRequest => AVERROR_HTTP_BAD_REQUEST,
138 Error::HttpUnauthorized => AVERROR_HTTP_UNAUTHORIZED,
139 Error::HttpForbidden => AVERROR_HTTP_FORBIDDEN,
140 Error::HttpNotFound => AVERROR_HTTP_NOT_FOUND,
141 Error::HttpOther4xx => AVERROR_HTTP_OTHER_4XX,
142 Error::HttpServerError => AVERROR_HTTP_SERVER_ERROR,
143 Error::Other { errno } => AVERROR(errno),
144 }
145 }
146}
147
148impl error::Error for Error {}
149
150impl From<Error> for io::Error {
151 fn from(value: Error) -> io::Error {
152 io::Error::new(kind:io::ErrorKind::Other, error:value)
153 }
154}
155
156impl fmt::Display for Error {
157 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
158 f.write_str(data:unsafe {
159 from_utf8_unchecked(
160 CStr&CStr::from_ptr(match *self {
161 Error::Other { errno: i32 } => libc::strerror(errno),
162 _ => STRINGS[index(self)].as_ptr(),
163 })
164 .to_bytes(),
165 )
166 })
167 }
168}
169
170impl fmt::Debug for Error {
171 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
172 f.write_str(data:"ffmpeg::Error(")?;
173 f.write_str(&format!("{}: ", AVUNERROR((*self).into())))?;
174 fmt::Display::fmt(self, f)?;
175 f.write_str(data:")")
176 }
177}
178
179#[inline(always)]
180fn index(error: &Error) -> usize {
181 match *error {
182 Error::BsfNotFound => 0,
183 Error::Bug => 1,
184 Error::BufferTooSmall => 2,
185 Error::DecoderNotFound => 3,
186 Error::DemuxerNotFound => 4,
187 Error::EncoderNotFound => 5,
188 Error::Eof => 6,
189 Error::Exit => 7,
190 Error::External => 8,
191 Error::FilterNotFound => 9,
192 Error::InvalidData => 10,
193 Error::MuxerNotFound => 11,
194 Error::OptionNotFound => 12,
195 Error::PatchWelcome => 13,
196 Error::ProtocolNotFound => 14,
197 Error::StreamNotFound => 15,
198 Error::Bug2 => 16,
199 Error::Unknown => 17,
200 Error::Experimental => 18,
201 Error::InputChanged => 19,
202 Error::OutputChanged => 20,
203 Error::HttpBadRequest => 21,
204 Error::HttpUnauthorized => 22,
205 Error::HttpForbidden => 23,
206 Error::HttpNotFound => 24,
207 Error::HttpOther4xx => 25,
208 Error::HttpServerError => 26,
209 Error::Other { errno: _ } => (-1isize) as usize,
210 }
211}
212
213// XXX: the length has to be synced with the number of errors
214static mut STRINGS: [[c_char; AV_ERROR_MAX_STRING_SIZE]; 27] = [[0; AV_ERROR_MAX_STRING_SIZE]; 27];
215
216pub fn register_all() {
217 unsafe {
218 av_strerror(
219 Error::Bug.into(),
220 STRINGS[index(&Error::Bug)].as_mut_ptr(),
221 AV_ERROR_MAX_STRING_SIZE,
222 );
223 av_strerror(
224 Error::Bug2.into(),
225 STRINGS[index(&Error::Bug2)].as_mut_ptr(),
226 AV_ERROR_MAX_STRING_SIZE,
227 );
228 av_strerror(
229 Error::Unknown.into(),
230 STRINGS[index(&Error::Unknown)].as_mut_ptr(),
231 AV_ERROR_MAX_STRING_SIZE,
232 );
233 av_strerror(
234 Error::Experimental.into(),
235 STRINGS[index(&Error::Experimental)].as_mut_ptr(),
236 AV_ERROR_MAX_STRING_SIZE,
237 );
238 av_strerror(
239 Error::BufferTooSmall.into(),
240 STRINGS[index(&Error::BufferTooSmall)].as_mut_ptr(),
241 AV_ERROR_MAX_STRING_SIZE,
242 );
243 av_strerror(
244 Error::Eof.into(),
245 STRINGS[index(&Error::Eof)].as_mut_ptr(),
246 AV_ERROR_MAX_STRING_SIZE,
247 );
248 av_strerror(
249 Error::Exit.into(),
250 STRINGS[index(&Error::Exit)].as_mut_ptr(),
251 AV_ERROR_MAX_STRING_SIZE,
252 );
253 av_strerror(
254 Error::External.into(),
255 STRINGS[index(&Error::External)].as_mut_ptr(),
256 AV_ERROR_MAX_STRING_SIZE,
257 );
258 av_strerror(
259 Error::InvalidData.into(),
260 STRINGS[index(&Error::InvalidData)].as_mut_ptr(),
261 AV_ERROR_MAX_STRING_SIZE,
262 );
263 av_strerror(
264 Error::PatchWelcome.into(),
265 STRINGS[index(&Error::PatchWelcome)].as_mut_ptr(),
266 AV_ERROR_MAX_STRING_SIZE,
267 );
268
269 av_strerror(
270 Error::InputChanged.into(),
271 STRINGS[index(&Error::InputChanged)].as_mut_ptr(),
272 AV_ERROR_MAX_STRING_SIZE,
273 );
274 av_strerror(
275 Error::OutputChanged.into(),
276 STRINGS[index(&Error::OutputChanged)].as_mut_ptr(),
277 AV_ERROR_MAX_STRING_SIZE,
278 );
279
280 av_strerror(
281 Error::BsfNotFound.into(),
282 STRINGS[index(&Error::BsfNotFound)].as_mut_ptr(),
283 AV_ERROR_MAX_STRING_SIZE,
284 );
285 av_strerror(
286 Error::DecoderNotFound.into(),
287 STRINGS[index(&Error::DecoderNotFound)].as_mut_ptr(),
288 AV_ERROR_MAX_STRING_SIZE,
289 );
290 av_strerror(
291 Error::DemuxerNotFound.into(),
292 STRINGS[index(&Error::DemuxerNotFound)].as_mut_ptr(),
293 AV_ERROR_MAX_STRING_SIZE,
294 );
295 av_strerror(
296 Error::EncoderNotFound.into(),
297 STRINGS[index(&Error::EncoderNotFound)].as_mut_ptr(),
298 AV_ERROR_MAX_STRING_SIZE,
299 );
300 av_strerror(
301 Error::OptionNotFound.into(),
302 STRINGS[index(&Error::OptionNotFound)].as_mut_ptr(),
303 AV_ERROR_MAX_STRING_SIZE,
304 );
305 av_strerror(
306 Error::MuxerNotFound.into(),
307 STRINGS[index(&Error::MuxerNotFound)].as_mut_ptr(),
308 AV_ERROR_MAX_STRING_SIZE,
309 );
310 av_strerror(
311 Error::FilterNotFound.into(),
312 STRINGS[index(&Error::FilterNotFound)].as_mut_ptr(),
313 AV_ERROR_MAX_STRING_SIZE,
314 );
315 av_strerror(
316 Error::ProtocolNotFound.into(),
317 STRINGS[index(&Error::ProtocolNotFound)].as_mut_ptr(),
318 AV_ERROR_MAX_STRING_SIZE,
319 );
320 av_strerror(
321 Error::StreamNotFound.into(),
322 STRINGS[index(&Error::StreamNotFound)].as_mut_ptr(),
323 AV_ERROR_MAX_STRING_SIZE,
324 );
325
326 av_strerror(
327 Error::HttpBadRequest.into(),
328 STRINGS[index(&Error::HttpBadRequest)].as_mut_ptr(),
329 AV_ERROR_MAX_STRING_SIZE,
330 );
331 av_strerror(
332 Error::HttpUnauthorized.into(),
333 STRINGS[index(&Error::HttpUnauthorized)].as_mut_ptr(),
334 AV_ERROR_MAX_STRING_SIZE,
335 );
336 av_strerror(
337 Error::HttpForbidden.into(),
338 STRINGS[index(&Error::HttpForbidden)].as_mut_ptr(),
339 AV_ERROR_MAX_STRING_SIZE,
340 );
341 av_strerror(
342 Error::HttpNotFound.into(),
343 STRINGS[index(&Error::HttpNotFound)].as_mut_ptr(),
344 AV_ERROR_MAX_STRING_SIZE,
345 );
346 av_strerror(
347 Error::HttpOther4xx.into(),
348 STRINGS[index(&Error::HttpOther4xx)].as_mut_ptr(),
349 AV_ERROR_MAX_STRING_SIZE,
350 );
351 av_strerror(
352 Error::HttpServerError.into(),
353 STRINGS[index(&Error::HttpServerError)].as_mut_ptr(),
354 AV_ERROR_MAX_STRING_SIZE,
355 );
356 }
357}
358
359#[cfg(test)]
360mod tests {
361 use super::*;
362
363 #[test]
364 fn test_error_roundtrip() {
365 assert_eq!(Into::<c_int>::into(Error::from(AVERROR_EOF)), AVERROR_EOF);
366 assert_eq!(
367 Into::<c_int>::into(Error::from(AVERROR(EAGAIN))),
368 AVERROR(EAGAIN)
369 );
370 assert_eq!(Error::from(AVERROR(EAGAIN)), Error::Other { errno: EAGAIN });
371 }
372
373 #[cfg(any(target_os = "linux", target_os = "macos"))]
374 #[test]
375 fn test_posix_error_string() {
376 assert_eq!(
377 Error::from(AVERROR(EAGAIN)).to_string(),
378 "Resource temporarily unavailable"
379 )
380 }
381}
382

Provided by KDAB

Privacy Policy