Skip to main content

media_pp/
error.rs

1//! The crate-wide error type.
2//!
3//! [`enum@Error`] is the aggregate an element's own error converts into with `?`,
4//! so that a pipeline built from unrelated elements still has one return type.
5//! Each variant wraps a component error — `thiserror` enums that stay actionable
6//! on their own, documented next to the element that produces them.
7//!
8//! Backend variants are behind the same Cargo features as the elements that
9//! raise them, so this enum is exactly as wide as the build it belongs to.
10
11use std::io;
12
13use thiserror::Error;
14
15#[cfg(all(target_os = "windows", feature = "dxgi-capture"))]
16use crate::elements::DxgiCaptureSourceError;
17#[cfg(feature = "ort")]
18use crate::elements::OrtDetectorError;
19#[cfg(all(target_os = "linux", feature = "pipewire-audio-capture"))]
20use crate::elements::PipeWireAudioCaptureSourceError;
21#[cfg(all(target_os = "linux", feature = "pipewire-audio-renderer"))]
22use crate::elements::PipeWireAudioRendererError;
23#[cfg(all(target_os = "linux", feature = "pipewire-screen-capture"))]
24use crate::elements::PipeWireScreenCaptureSourceError;
25use crate::elements::RtspSinkError;
26#[cfg(all(target_os = "windows", feature = "wasapi-capture"))]
27use crate::elements::WasapiCaptureSourceError;
28#[cfg(all(target_os = "windows", feature = "wasapi-renderer"))]
29use crate::elements::WasapiRendererError;
30#[cfg(feature = "webrtc")]
31use crate::elements::WebRtcError;
32#[cfg(feature = "cuda")]
33use crate::elements::{
34    CudaConverterError, CudaDecoderError, CudaDownloadError, CudaEncoderError, CudaRendererError,
35    CudaScalerError, CudaUploadError, CudaVideoCompositorError,
36};
37#[cfg(all(target_os = "windows", feature = "d3d11"))]
38use crate::elements::{
39    D3d11ChromaKeyError, D3d11DecoderError, D3d11DownloadError, D3d11NvencEncoderError,
40    D3d11RendererError, D3d11ScalerError, D3d11TextLayerError, D3d11UploadError,
41    D3d11VideoCompositorError,
42};
43#[cfg(all(target_os = "windows", feature = "d3d12"))]
44use crate::elements::{
45    D3d12DecoderError, D3d12DownloadError, D3d12RendererError, D3d12ScalerError, D3d12UploadError,
46};
47use crate::{
48    elements::{
49        AppSourceError, AudioMixerError, AudioResamplerError, AudioVolumeError, FileDemuxError,
50        HlsMuxerError, Mp4MuxerError, PacerError, RtspSourceError, SwAudioEncoderError,
51        SwChromaKeyError, SwDecoderError, SwEncoderError, SwScalerError, SwVideoCompositorError,
52        TestAudioSourceError, TestVideoSourceError, VideoSynchronizerError,
53    },
54    graph::GraphError,
55    log::LogInitError,
56    queue::QueueError,
57};
58
59/// Failure to create one of the background threads owned by this crate.
60///
61/// The operation that requested the thread returns this error before claiming
62/// that it started successfully. The `thread` field identifies the worker so
63/// callers can distinguish pipeline, queue, and standalone-driver failures.
64#[derive(Debug, Error)]
65#[error("failed to spawn {thread} thread: {source}")]
66pub struct ThreadSpawnError {
67    thread: String,
68    #[source]
69    source: io::Error,
70}
71
72impl ThreadSpawnError {
73    pub(crate) fn new(thread: impl Into<String>, source: io::Error) -> Self {
74        Self {
75            thread: thread.into(),
76            source,
77        }
78    }
79
80    /// Name of the worker that could not be created.
81    pub fn thread(&self) -> &str {
82        &self.thread
83    }
84}
85
86/// FFmpeg could not allocate the reference-counted buffer that owns a D3D11
87/// texture attached to an `AVFrame`.
88#[cfg(all(target_os = "windows", feature = "d3d11"))]
89#[derive(Debug, Error)]
90#[error("FFmpeg could not allocate a D3D11 texture buffer wrapper")]
91pub struct D3d11FrameWrapError;
92
93/// Crate-wide error. Each element defines its own `{Element}Error` (see
94/// [`FileDemuxError`], [`SwDecoderError`], [`QueueError`]) for its own
95/// domain-specific failures; this enum just aggregates them so trait
96/// methods (`Sink::consume`, `SourceElement::run`, ...) — which have to
97/// return one common error type to stay object-safe across arbitrary
98/// `Box<dyn Sink>` — can report any of them. `?` chains through
99/// automatically: an element's own function returns its own error type,
100/// and the moment that gets used with `?` inside a function returning
101/// this top-level `Result`, it's converted here via `#[from]`.
102#[derive(Debug, Error)]
103pub enum Error {
104    /// A pipeline, queue, or driver worker thread could not be created.
105    #[error(transparent)]
106    ThreadSpawnError(#[from] ThreadSpawnError),
107
108    /// FFmpeg could not allocate a D3D11 frame buffer wrapper.
109    #[cfg(all(target_os = "windows", feature = "d3d11"))]
110    #[error(transparent)]
111    D3d11FrameWrapError(#[from] D3d11FrameWrapError),
112
113    /// A file demuxer operation failed.
114    #[error(transparent)]
115    FileDemuxError(#[from] FileDemuxError),
116
117    /// An application source channel is closed.
118    #[error(transparent)]
119    AppSourceError(#[from] AppSourceError),
120
121    /// An RTSP source operation failed.
122    #[error(transparent)]
123    RtspSourceError(#[from] RtspSourceError),
124
125    /// A synthetic video source rejected an operation.
126    #[error(transparent)]
127    TestVideoSourceError(#[from] TestVideoSourceError),
128
129    /// A synthetic audio source rejected an operation.
130    #[error(transparent)]
131    TestAudioSourceError(#[from] TestAudioSourceError),
132
133    /// A software decoder operation failed.
134    #[error(transparent)]
135    SwDecoderError(#[from] SwDecoderError),
136
137    /// A CUDA decoder operation failed.
138    #[cfg(feature = "cuda")]
139    #[error(transparent)]
140    CudaDecoderError(#[from] CudaDecoderError),
141
142    /// A CUDA renderer operation failed.
143    #[cfg(feature = "cuda")]
144    #[error(transparent)]
145    CudaRendererError(#[from] CudaRendererError),
146
147    /// Uploading a frame to CUDA failed.
148    #[cfg(feature = "cuda")]
149    #[error(transparent)]
150    CudaUploadError(#[from] CudaUploadError),
151
152    /// Downloading a frame from CUDA failed.
153    #[cfg(feature = "cuda")]
154    #[error(transparent)]
155    CudaDownloadError(#[from] CudaDownloadError),
156
157    /// A CUDA scaling operation failed.
158    #[cfg(feature = "cuda")]
159    #[error(transparent)]
160    CudaScalerError(#[from] CudaScalerError),
161
162    /// A CUDA pixel-format conversion failed.
163    #[cfg(feature = "cuda")]
164    #[error(transparent)]
165    CudaConverterError(#[from] CudaConverterError),
166
167    /// A CUDA compositor operation failed.
168    #[cfg(feature = "cuda")]
169    #[error(transparent)]
170    CudaVideoCompositorError(#[from] CudaVideoCompositorError),
171
172    /// A CUDA encoder operation failed.
173    #[cfg(feature = "cuda")]
174    #[error(transparent)]
175    CudaEncoderError(#[from] CudaEncoderError),
176
177    /// A software video encoder operation failed.
178    #[error(transparent)]
179    SwEncoderError(#[from] SwEncoderError),
180
181    /// A pacer could not schedule an input timestamp.
182    #[error(transparent)]
183    PacerError(#[from] PacerError),
184
185    /// A video synchronizer could not schedule an input frame.
186    #[error(transparent)]
187    VideoSynchronizerError(#[from] VideoSynchronizerError),
188
189    /// A software audio encoder operation failed.
190    #[error(transparent)]
191    SwAudioEncoderError(#[from] SwAudioEncoderError),
192
193    /// An audio resampling operation failed.
194    #[error(transparent)]
195    AudioResamplerError(#[from] AudioResamplerError),
196
197    /// An audio gain operation failed.
198    #[error(transparent)]
199    AudioVolumeError(#[from] AudioVolumeError),
200
201    /// A software scaling operation failed.
202    #[error(transparent)]
203    SwScalerError(#[from] SwScalerError),
204
205    /// A software chroma-key operation failed.
206    #[error(transparent)]
207    SwChromaKeyError(#[from] SwChromaKeyError),
208
209    /// A queue worker or capacity policy failed.
210    #[error(transparent)]
211    QueueError(#[from] QueueError),
212
213    /// A pipeline graph mutation violated a topology invariant.
214    #[error(transparent)]
215    GraphError(#[from] GraphError),
216
217    /// Private file logging could not be initialized.
218    #[error(transparent)]
219    LogInitError(#[from] LogInitError),
220
221    /// An audio mixer operation failed.
222    #[error(transparent)]
223    AudioMixerError(#[from] AudioMixerError),
224
225    /// A software video compositor operation failed.
226    #[error(transparent)]
227    SwVideoCompositorError(#[from] SwVideoCompositorError),
228
229    /// MP4 muxing failed.
230    #[error(transparent)]
231    Mp4MuxerError(#[from] Mp4MuxerError),
232
233    /// HLS muxing or option validation failed.
234    #[error(transparent)]
235    HlsMuxerError(#[from] HlsMuxerError),
236
237    /// Sending a stream to an RTSP endpoint failed.
238    #[error(transparent)]
239    RtspSinkError(#[from] RtspSinkError),
240
241    /// A D3D12 renderer operation failed.
242    #[cfg(all(target_os = "windows", feature = "d3d12"))]
243    #[error(transparent)]
244    D3d12RendererError(#[from] D3d12RendererError),
245
246    /// A D3D12 decoder operation failed.
247    #[cfg(all(target_os = "windows", feature = "d3d12"))]
248    #[error(transparent)]
249    D3d12DecoderError(#[from] D3d12DecoderError),
250
251    /// Uploading a frame to D3D12 failed.
252    #[cfg(all(target_os = "windows", feature = "d3d12"))]
253    #[error(transparent)]
254    D3d12UploadError(#[from] D3d12UploadError),
255
256    /// Downloading a frame from D3D12 failed.
257    #[cfg(all(target_os = "windows", feature = "d3d12"))]
258    #[error(transparent)]
259    D3d12DownloadError(#[from] D3d12DownloadError),
260
261    /// A D3D12 scaling operation failed.
262    #[cfg(all(target_os = "windows", feature = "d3d12"))]
263    #[error(transparent)]
264    D3d12ScalerError(#[from] D3d12ScalerError),
265
266    /// A D3D11 decoder operation failed.
267    #[cfg(all(target_os = "windows", feature = "d3d11"))]
268    #[error(transparent)]
269    D3d11DecoderError(#[from] D3d11DecoderError),
270
271    /// Uploading a frame to D3D11 failed.
272    #[cfg(all(target_os = "windows", feature = "d3d11"))]
273    #[error(transparent)]
274    D3d11UploadError(#[from] D3d11UploadError),
275
276    /// Downloading a frame from D3D11 failed.
277    #[cfg(all(target_os = "windows", feature = "d3d11"))]
278    #[error(transparent)]
279    D3d11DownloadError(#[from] D3d11DownloadError),
280
281    /// A D3D11 scaling operation failed.
282    #[cfg(all(target_os = "windows", feature = "d3d11"))]
283    #[error(transparent)]
284    D3d11ScalerError(#[from] D3d11ScalerError),
285
286    /// A D3D11 chroma-key operation failed.
287    #[cfg(all(target_os = "windows", feature = "d3d11"))]
288    #[error(transparent)]
289    D3d11ChromaKeyError(#[from] D3d11ChromaKeyError),
290
291    /// A D3D11-backed NVENC operation failed.
292    #[cfg(all(target_os = "windows", feature = "d3d11"))]
293    #[error(transparent)]
294    D3d11NvencEncoderError(#[from] D3d11NvencEncoderError),
295
296    /// A D3D11 renderer operation failed.
297    #[cfg(all(target_os = "windows", feature = "d3d11"))]
298    #[error(transparent)]
299    D3d11RendererError(#[from] D3d11RendererError),
300
301    /// A D3D11 compositor operation failed.
302    #[cfg(all(target_os = "windows", feature = "d3d11"))]
303    #[error(transparent)]
304    D3d11VideoCompositorError(#[from] D3d11VideoCompositorError),
305
306    /// A D3D11 text-layer operation failed.
307    #[cfg(all(target_os = "windows", feature = "d3d11"))]
308    #[error(transparent)]
309    D3d11TextLayerError(#[from] D3d11TextLayerError),
310
311    /// Desktop duplication capture failed.
312    #[cfg(all(target_os = "windows", feature = "dxgi-capture"))]
313    #[error(transparent)]
314    DxgiCaptureSourceError(#[from] DxgiCaptureSourceError),
315
316    /// PipeWire audio capture failed.
317    #[cfg(all(target_os = "linux", feature = "pipewire-audio-capture"))]
318    #[error(transparent)]
319    PipeWireAudioCaptureSourceError(#[from] PipeWireAudioCaptureSourceError),
320
321    /// PipeWire audio rendering failed.
322    #[cfg(all(target_os = "linux", feature = "pipewire-audio-renderer"))]
323    #[error(transparent)]
324    PipeWireAudioRendererError(#[from] PipeWireAudioRendererError),
325
326    /// PipeWire screen capture failed.
327    #[cfg(all(target_os = "linux", feature = "pipewire-screen-capture"))]
328    #[error(transparent)]
329    PipeWireScreenCaptureSourceError(#[from] PipeWireScreenCaptureSourceError),
330
331    /// WASAPI audio capture failed.
332    #[cfg(all(target_os = "windows", feature = "wasapi-capture"))]
333    #[error(transparent)]
334    WasapiCaptureSourceError(#[from] WasapiCaptureSourceError),
335
336    /// WASAPI audio rendering failed.
337    #[cfg(all(target_os = "windows", feature = "wasapi-renderer"))]
338    #[error(transparent)]
339    WasapiRendererError(#[from] WasapiRendererError),
340
341    /// ONNX Runtime inference or detector processing failed.
342    #[cfg(feature = "ort")]
343    #[error(transparent)]
344    OrtDetectorError(#[from] OrtDetectorError),
345
346    /// A WebRTC peer operation failed.
347    #[cfg(feature = "webrtc")]
348    #[error(transparent)]
349    WebRtcError(#[from] WebRtcError),
350
351    /// An FFmpeg error not assigned to a more specific element error.
352    #[error("ffmpeg error: {0}")]
353    Ffmpeg(#[from] ffmpeg_next::Error),
354
355    /// An application-defined error message without a more specific category.
356    #[error("{0}")]
357    Other(String),
358}
359
360/// The crate's `Result`, with [`enum@Error`] as the error type.
361pub type Result<T> = std::result::Result<T, Error>;