1use crate::types::PixelFormat;
12
13#[derive(Debug, thiserror::Error)]
15pub enum EngineError {
16 #[error("CUDA driver error: {0}")]
18 Cuda(#[from] cudarc::driver::DriverError),
19
20 #[error("CUDA kernel compilation error: {0}")]
21 NvrtcCompile(#[from] cudarc::nvrtc::CompileError),
22
23 #[error("ORT inference error: {0}")]
25 Inference(#[from] ort::Error),
26
27 #[error("Model metadata error: {0}")]
28 ModelMetadata(String),
29
30 #[error("Backend not initialized — call initialize() first")]
31 NotInitialized,
32
33 #[error("NVDEC decode error: {0}")]
35 Decode(String),
36
37 #[error("NVENC encode error: {0}")]
38 Encode(String),
39
40 #[error("Demux error: {0}")]
41 Demux(String),
42
43 #[error("Mux error: {0}")]
44 Mux(String),
45
46 #[error("Bitstream filter error: {0}")]
47 BitstreamFilter(String),
48
49 #[error("Probe error: {0}")]
50 Probe(String),
51
52 #[error("Pipeline error: {0}")]
54 Pipeline(String),
55
56 #[error("Pipeline channel closed unexpectedly")]
57 ChannelClosed,
58
59 #[error("Pipeline shutdown signal received")]
60 Shutdown,
61
62 #[error("Pixel format mismatch: expected {expected:?}, got {actual:?}")]
64 FormatMismatch {
65 expected: PixelFormat,
66 actual: PixelFormat,
67 },
68
69 #[error("Dimension mismatch: {0}")]
70 DimensionMismatch(String),
71
72 #[error("Buffer too small: need {need} bytes, have {have}")]
73 BufferTooSmall { need: usize, have: usize },
74
75 #[error("Invariant violation: {0}")]
77 InvariantViolation(String),
78
79 #[error("Panic recovered in {stage}: {message}")]
81 PanicRecovered {
82 stage: &'static str,
83 message: String,
84 },
85
86 #[error(
87 "VRAM limit exceeded: limit={limit_bytes}B current={current_bytes}B \
88 requested={requested_bytes}B would_be={would_be_bytes}B"
89 )]
90 VramLimitExceeded {
91 limit_bytes: usize,
92 current_bytes: usize,
93 requested_bytes: usize,
94 would_be_bytes: usize,
95 },
96
97 #[error("Backpressure timeout: {stage} blocked for {elapsed_ms} ms")]
98 BackpressureTimeout {
99 stage: &'static str,
100 elapsed_ms: u64,
101 },
102
103 #[error("Drop order violation: {0}")]
104 DropOrderViolation(String),
105}
106
107impl EngineError {
108 pub fn error_code(&self) -> u32 {
119 match self {
120 Self::Cuda(_) => 100,
121 Self::NvrtcCompile(_) => 101,
122 Self::Inference(_) => 200,
123 Self::ModelMetadata(_) => 201,
124 Self::NotInitialized => 202,
125 Self::Decode(_) => 300,
126 Self::Encode(_) => 301,
127 Self::Demux(_) => 302,
128 Self::Mux(_) => 303,
129 Self::BitstreamFilter(_) => 304,
130 Self::Probe(_) => 305,
131 Self::ChannelClosed => 400,
132 Self::Shutdown => 401,
133 Self::Pipeline(_) => 402,
134 Self::FormatMismatch { .. } => 500,
135 Self::DimensionMismatch(_) => 501,
136 Self::BufferTooSmall { .. } => 502,
137 Self::InvariantViolation(_) => 600,
138 Self::PanicRecovered { .. } => 700,
139 Self::VramLimitExceeded { .. } => 701,
140 Self::BackpressureTimeout { .. } => 702,
141 Self::DropOrderViolation(_) => 703,
142 }
143 }
144
145 pub fn is_recoverable(&self) -> bool {
147 matches!(
148 self,
149 Self::BackpressureTimeout { .. } | Self::PanicRecovered { .. }
150 )
151 }
152}
153
154pub type Result<T> = std::result::Result<T, EngineError>;