1use std::path::PathBuf;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
8pub enum EncodeError {
9 #[error("Cannot create output file: {path}")]
11 CannotCreateFile {
12 path: PathBuf,
14 },
15
16 #[error("Unsupported codec: {codec}")]
18 UnsupportedCodec {
19 codec: String,
21 },
22
23 #[error("No suitable encoder found for {codec} (tried: {tried:?})")]
25 NoSuitableEncoder {
26 codec: String,
28 tried: Vec<String>,
30 },
31
32 #[error("Encoding failed at frame {frame}: {reason}")]
34 EncodingFailed {
35 frame: u64,
37 reason: String,
39 },
40
41 #[error("Invalid configuration: {reason}")]
43 InvalidConfig {
44 reason: String,
46 },
47
48 #[error("Hardware encoder unavailable: {encoder}")]
50 HwEncoderUnavailable {
51 encoder: String,
53 },
54
55 #[error("Muxing failed: {reason}")]
57 MuxingFailed {
58 reason: String,
60 },
61
62 #[error("ffmpeg error: {message} (code={code})")]
64 Ffmpeg {
65 code: i32,
67 message: String,
69 },
70
71 #[error("IO error: {0}")]
73 Io(#[from] std::io::Error),
74
75 #[error("Encoding cancelled by user")]
77 Cancelled,
78}
79
80impl EncodeError {
81 pub(crate) fn from_ffmpeg_error(errnum: i32) -> Self {
87 EncodeError::Ffmpeg {
88 code: errnum,
89 message: ff_sys::av_error_string(errnum),
90 }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::EncodeError;
97
98 #[test]
99 fn from_ffmpeg_error_should_return_ffmpeg_variant() {
100 let err = EncodeError::from_ffmpeg_error(ff_sys::error_codes::EINVAL);
101 assert!(matches!(err, EncodeError::Ffmpeg { .. }));
102 }
103
104 #[test]
105 fn from_ffmpeg_error_should_carry_numeric_code() {
106 let err = EncodeError::from_ffmpeg_error(ff_sys::error_codes::EINVAL);
107 match err {
108 EncodeError::Ffmpeg { code, .. } => assert_eq!(code, ff_sys::error_codes::EINVAL),
109 _ => panic!("expected Ffmpeg variant"),
110 }
111 }
112
113 #[test]
114 fn from_ffmpeg_error_should_format_with_code_in_display() {
115 let err = EncodeError::from_ffmpeg_error(ff_sys::error_codes::EINVAL);
116 let msg = err.to_string();
117 assert!(msg.contains("code=-22"), "expected 'code=-22' in '{msg}'");
118 }
119
120 #[test]
121 fn from_ffmpeg_error_message_should_be_nonempty() {
122 let err = EncodeError::from_ffmpeg_error(ff_sys::error_codes::ENOMEM);
123 assert!(!err.to_string().is_empty());
124 }
125
126 #[test]
127 fn from_ffmpeg_error_eof_should_be_constructible() {
128 let err = EncodeError::from_ffmpeg_error(ff_sys::error_codes::EOF);
129 assert!(matches!(err, EncodeError::Ffmpeg { .. }));
130 assert!(!err.to_string().is_empty());
131 }
132}