1use std::error;
2use std::ffi::CStr;
3use std::fmt;
4use std::io;
5use std::str::from_utf8_unchecked;
6
7use crate::ffi::*;
8use libc::{c_char, c_int};
9#[cfg(feature = "serialize")]
10use serde::{Deserialize, Serialize};
11
12#[derive(Copy, Clone, PartialEq, Eq)]
13#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
14pub enum Error {
15 Bug,
16 Bug2,
17 Unknown,
18 Experimental,
19 BufferTooSmall,
20 Eof,
21 Exit,
22 External,
23 InvalidData,
24 PatchWelcome,
25
26 InputChanged,
27 OutputChanged,
28
29 BsfNotFound,
30 DecoderNotFound,
31 DemuxerNotFound,
32 EncoderNotFound,
33 OptionNotFound,
34 MuxerNotFound,
35 FilterNotFound,
36 ProtocolNotFound,
37 StreamNotFound,
38
39 HttpBadRequest,
40 HttpUnauthorized,
41 HttpForbidden,
42 HttpNotFound,
43 HttpOther4xx,
44 HttpServerError,
45
46 Other {
48 errno: c_int,
49 },
50}
51
52impl From<c_int> for Error {
53 fn from(value: c_int) -> Error {
54 match value {
55 AVERROR_BSF_NOT_FOUND => Error::BsfNotFound,
56 AVERROR_BUG => Error::Bug,
57 AVERROR_BUFFER_TOO_SMALL => Error::BufferTooSmall,
58 AVERROR_DECODER_NOT_FOUND => Error::DecoderNotFound,
59 AVERROR_DEMUXER_NOT_FOUND => Error::DemuxerNotFound,
60 AVERROR_ENCODER_NOT_FOUND => Error::EncoderNotFound,
61 AVERROR_EOF => Error::Eof,
62 AVERROR_EXIT => Error::Exit,
63 AVERROR_EXTERNAL => Error::External,
64 AVERROR_FILTER_NOT_FOUND => Error::FilterNotFound,
65 AVERROR_INVALIDDATA => Error::InvalidData,
66 AVERROR_MUXER_NOT_FOUND => Error::MuxerNotFound,
67 AVERROR_OPTION_NOT_FOUND => Error::OptionNotFound,
68 AVERROR_PATCHWELCOME => Error::PatchWelcome,
69 AVERROR_PROTOCOL_NOT_FOUND => Error::ProtocolNotFound,
70 AVERROR_STREAM_NOT_FOUND => Error::StreamNotFound,
71 AVERROR_BUG2 => Error::Bug2,
72 AVERROR_UNKNOWN => Error::Unknown,
73 AVERROR_EXPERIMENTAL => Error::Experimental,
74 AVERROR_INPUT_CHANGED => Error::InputChanged,
75 AVERROR_OUTPUT_CHANGED => Error::OutputChanged,
76 AVERROR_HTTP_BAD_REQUEST => Error::HttpBadRequest,
77 AVERROR_HTTP_UNAUTHORIZED => Error::HttpUnauthorized,
78 AVERROR_HTTP_FORBIDDEN => Error::HttpForbidden,
79 AVERROR_HTTP_NOT_FOUND => Error::HttpNotFound,
80 AVERROR_HTTP_OTHER_4XX => Error::HttpOther4xx,
81 AVERROR_HTTP_SERVER_ERROR => Error::HttpServerError,
82 e => Error::Other {
83 errno: AVUNERROR(e),
84 },
85 }
86 }
87}
88
89impl From<Error> for c_int {
90 fn from(value: Error) -> c_int {
91 match value {
92 Error::BsfNotFound => AVERROR_BSF_NOT_FOUND,
93 Error::Bug => AVERROR_BUG,
94 Error::BufferTooSmall => AVERROR_BUFFER_TOO_SMALL,
95 Error::DecoderNotFound => AVERROR_DECODER_NOT_FOUND,
96 Error::DemuxerNotFound => AVERROR_DEMUXER_NOT_FOUND,
97 Error::EncoderNotFound => AVERROR_ENCODER_NOT_FOUND,
98 Error::Eof => AVERROR_EOF,
99 Error::Exit => AVERROR_EXIT,
100 Error::External => AVERROR_EXTERNAL,
101 Error::FilterNotFound => AVERROR_FILTER_NOT_FOUND,
102 Error::InvalidData => AVERROR_INVALIDDATA,
103 Error::MuxerNotFound => AVERROR_MUXER_NOT_FOUND,
104 Error::OptionNotFound => AVERROR_OPTION_NOT_FOUND,
105 Error::PatchWelcome => AVERROR_PATCHWELCOME,
106 Error::ProtocolNotFound => AVERROR_PROTOCOL_NOT_FOUND,
107 Error::StreamNotFound => AVERROR_STREAM_NOT_FOUND,
108 Error::Bug2 => AVERROR_BUG2,
109 Error::Unknown => AVERROR_UNKNOWN,
110 Error::Experimental => AVERROR_EXPERIMENTAL,
111 Error::InputChanged => AVERROR_INPUT_CHANGED,
112 Error::OutputChanged => AVERROR_OUTPUT_CHANGED,
113 Error::HttpBadRequest => AVERROR_HTTP_BAD_REQUEST,
114 Error::HttpUnauthorized => AVERROR_HTTP_UNAUTHORIZED,
115 Error::HttpForbidden => AVERROR_HTTP_FORBIDDEN,
116 Error::HttpNotFound => AVERROR_HTTP_NOT_FOUND,
117 Error::HttpOther4xx => AVERROR_HTTP_OTHER_4XX,
118 Error::HttpServerError => AVERROR_HTTP_SERVER_ERROR,
119 Error::Other { errno } => AVERROR(errno),
120 }
121 }
122}
123
124impl error::Error for Error {}
125
126impl From<Error> for io::Error {
127 fn from(value: Error) -> io::Error {
128 io::Error::new(io::ErrorKind::Other, value)
129 }
130}
131
132impl fmt::Display for Error {
133 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
134 f.write_str(unsafe {
135 from_utf8_unchecked(
136 CStr::from_ptr(match *self {
137 Error::Other { errno } => libc::strerror(errno),
138 _ => STRINGS[index(self)].as_ptr(),
139 })
140 .to_bytes(),
141 )
142 })
143 }
144}
145
146impl fmt::Debug for Error {
147 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
148 f.write_str("ffmpeg::Error(")?;
149 f.write_str(&format!("{}: ", AVUNERROR((*self).into())))?;
150 fmt::Display::fmt(self, f)?;
151 f.write_str(")")
152 }
153}
154
155#[inline(always)]
156fn index(error: &Error) -> usize {
157 match *error {
158 Error::BsfNotFound => 0,
159 Error::Bug => 1,
160 Error::BufferTooSmall => 2,
161 Error::DecoderNotFound => 3,
162 Error::DemuxerNotFound => 4,
163 Error::EncoderNotFound => 5,
164 Error::Eof => 6,
165 Error::Exit => 7,
166 Error::External => 8,
167 Error::FilterNotFound => 9,
168 Error::InvalidData => 10,
169 Error::MuxerNotFound => 11,
170 Error::OptionNotFound => 12,
171 Error::PatchWelcome => 13,
172 Error::ProtocolNotFound => 14,
173 Error::StreamNotFound => 15,
174 Error::Bug2 => 16,
175 Error::Unknown => 17,
176 Error::Experimental => 18,
177 Error::InputChanged => 19,
178 Error::OutputChanged => 20,
179 Error::HttpBadRequest => 21,
180 Error::HttpUnauthorized => 22,
181 Error::HttpForbidden => 23,
182 Error::HttpNotFound => 24,
183 Error::HttpOther4xx => 25,
184 Error::HttpServerError => 26,
185 Error::Other { errno: _ } => (-1isize) as usize,
186 }
187}
188
189static mut STRINGS: [[c_char; AV_ERROR_MAX_STRING_SIZE]; 27] = [[0; AV_ERROR_MAX_STRING_SIZE]; 27];
191
192pub fn register_all() {
193 unsafe {
194 av_strerror(
195 Error::Bug.into(),
196 STRINGS[index(&Error::Bug)].as_mut_ptr(),
197 AV_ERROR_MAX_STRING_SIZE,
198 );
199 av_strerror(
200 Error::Bug2.into(),
201 STRINGS[index(&Error::Bug2)].as_mut_ptr(),
202 AV_ERROR_MAX_STRING_SIZE,
203 );
204 av_strerror(
205 Error::Unknown.into(),
206 STRINGS[index(&Error::Unknown)].as_mut_ptr(),
207 AV_ERROR_MAX_STRING_SIZE,
208 );
209 av_strerror(
210 Error::Experimental.into(),
211 STRINGS[index(&Error::Experimental)].as_mut_ptr(),
212 AV_ERROR_MAX_STRING_SIZE,
213 );
214 av_strerror(
215 Error::BufferTooSmall.into(),
216 STRINGS[index(&Error::BufferTooSmall)].as_mut_ptr(),
217 AV_ERROR_MAX_STRING_SIZE,
218 );
219 av_strerror(
220 Error::Eof.into(),
221 STRINGS[index(&Error::Eof)].as_mut_ptr(),
222 AV_ERROR_MAX_STRING_SIZE,
223 );
224 av_strerror(
225 Error::Exit.into(),
226 STRINGS[index(&Error::Exit)].as_mut_ptr(),
227 AV_ERROR_MAX_STRING_SIZE,
228 );
229 av_strerror(
230 Error::External.into(),
231 STRINGS[index(&Error::External)].as_mut_ptr(),
232 AV_ERROR_MAX_STRING_SIZE,
233 );
234 av_strerror(
235 Error::InvalidData.into(),
236 STRINGS[index(&Error::InvalidData)].as_mut_ptr(),
237 AV_ERROR_MAX_STRING_SIZE,
238 );
239 av_strerror(
240 Error::PatchWelcome.into(),
241 STRINGS[index(&Error::PatchWelcome)].as_mut_ptr(),
242 AV_ERROR_MAX_STRING_SIZE,
243 );
244
245 av_strerror(
246 Error::InputChanged.into(),
247 STRINGS[index(&Error::InputChanged)].as_mut_ptr(),
248 AV_ERROR_MAX_STRING_SIZE,
249 );
250 av_strerror(
251 Error::OutputChanged.into(),
252 STRINGS[index(&Error::OutputChanged)].as_mut_ptr(),
253 AV_ERROR_MAX_STRING_SIZE,
254 );
255
256 av_strerror(
257 Error::BsfNotFound.into(),
258 STRINGS[index(&Error::BsfNotFound)].as_mut_ptr(),
259 AV_ERROR_MAX_STRING_SIZE,
260 );
261 av_strerror(
262 Error::DecoderNotFound.into(),
263 STRINGS[index(&Error::DecoderNotFound)].as_mut_ptr(),
264 AV_ERROR_MAX_STRING_SIZE,
265 );
266 av_strerror(
267 Error::DemuxerNotFound.into(),
268 STRINGS[index(&Error::DemuxerNotFound)].as_mut_ptr(),
269 AV_ERROR_MAX_STRING_SIZE,
270 );
271 av_strerror(
272 Error::EncoderNotFound.into(),
273 STRINGS[index(&Error::EncoderNotFound)].as_mut_ptr(),
274 AV_ERROR_MAX_STRING_SIZE,
275 );
276 av_strerror(
277 Error::OptionNotFound.into(),
278 STRINGS[index(&Error::OptionNotFound)].as_mut_ptr(),
279 AV_ERROR_MAX_STRING_SIZE,
280 );
281 av_strerror(
282 Error::MuxerNotFound.into(),
283 STRINGS[index(&Error::MuxerNotFound)].as_mut_ptr(),
284 AV_ERROR_MAX_STRING_SIZE,
285 );
286 av_strerror(
287 Error::FilterNotFound.into(),
288 STRINGS[index(&Error::FilterNotFound)].as_mut_ptr(),
289 AV_ERROR_MAX_STRING_SIZE,
290 );
291 av_strerror(
292 Error::ProtocolNotFound.into(),
293 STRINGS[index(&Error::ProtocolNotFound)].as_mut_ptr(),
294 AV_ERROR_MAX_STRING_SIZE,
295 );
296 av_strerror(
297 Error::StreamNotFound.into(),
298 STRINGS[index(&Error::StreamNotFound)].as_mut_ptr(),
299 AV_ERROR_MAX_STRING_SIZE,
300 );
301
302 av_strerror(
303 Error::HttpBadRequest.into(),
304 STRINGS[index(&Error::HttpBadRequest)].as_mut_ptr(),
305 AV_ERROR_MAX_STRING_SIZE,
306 );
307 av_strerror(
308 Error::HttpUnauthorized.into(),
309 STRINGS[index(&Error::HttpUnauthorized)].as_mut_ptr(),
310 AV_ERROR_MAX_STRING_SIZE,
311 );
312 av_strerror(
313 Error::HttpForbidden.into(),
314 STRINGS[index(&Error::HttpForbidden)].as_mut_ptr(),
315 AV_ERROR_MAX_STRING_SIZE,
316 );
317 av_strerror(
318 Error::HttpNotFound.into(),
319 STRINGS[index(&Error::HttpNotFound)].as_mut_ptr(),
320 AV_ERROR_MAX_STRING_SIZE,
321 );
322 av_strerror(
323 Error::HttpOther4xx.into(),
324 STRINGS[index(&Error::HttpOther4xx)].as_mut_ptr(),
325 AV_ERROR_MAX_STRING_SIZE,
326 );
327 av_strerror(
328 Error::HttpServerError.into(),
329 STRINGS[index(&Error::HttpServerError)].as_mut_ptr(),
330 AV_ERROR_MAX_STRING_SIZE,
331 );
332 }
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338 use libc::EAGAIN;
339
340 #[test]
341 fn test_error_roundtrip() {
342 assert_eq!(Into::<c_int>::into(Error::from(AVERROR_EOF)), AVERROR_EOF);
343 assert_eq!(
344 Into::<c_int>::into(Error::from(AVERROR(EAGAIN))),
345 AVERROR(EAGAIN)
346 );
347 assert_eq!(Error::from(AVERROR(EAGAIN)), Error::Other { errno: EAGAIN });
348 }
349
350 #[cfg(any(target_os = "linux", target_os = "macos"))]
351 #[test]
352 fn test_posix_error_string() {
353 assert_eq!(
354 Error::from(AVERROR(EAGAIN)).to_string(),
355 "Resource temporarily unavailable"
356 )
357 }
358}