• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Stateless decoders.
6 //!
7 //! Stateless here refers to the backend API targeted by these decoders. The decoders themselves do
8 //! hold the decoding state so the backend doesn't need to.
9 //!
10 //! The [`StatelessDecoder`] struct is the basis of all stateless decoders. It is created by
11 //! combining a codec codec to a [backend](crate::backend), after which bitstream units can be
12 //! submitted through the [`StatelessDecoder::decode`] method.
13 
14 pub mod av1;
15 pub mod h264;
16 pub mod h265;
17 pub mod vp8;
18 pub mod vp9;
19 
20 use std::os::fd::AsFd;
21 use std::os::fd::AsRawFd;
22 use std::os::fd::BorrowedFd;
23 use std::time::Duration;
24 
25 use nix::errno::Errno;
26 use nix::sys::epoll::Epoll;
27 use nix::sys::epoll::EpollCreateFlags;
28 use nix::sys::epoll::EpollEvent;
29 use nix::sys::epoll::EpollFlags;
30 use nix::sys::eventfd::EventFd;
31 use thiserror::Error;
32 
33 use crate::decoder::BlockingMode;
34 use crate::decoder::DecodedHandle;
35 use crate::decoder::DecoderEvent;
36 use crate::decoder::DynDecodedHandle;
37 use crate::decoder::ReadyFramesQueue;
38 use crate::decoder::StreamInfo;
39 use crate::Resolution;
40 
41 /// Error returned by `new_picture` methods of the backend, usually to indicate which kind of
42 /// resource is needed before the picture can be successfully created.
43 #[derive(Error, Debug)]
44 pub enum NewPictureError {
45     /// Indicates that the backend needs one output buffer to be returned to the pool before it can
46     /// proceed.
47     #[error("need one output buffer to be returned before operation can proceed")]
48     OutOfOutputBuffers,
49     /// An unrecoverable backend error has occured.
50     #[error(transparent)]
51     BackendError(#[from] anyhow::Error),
52 }
53 
54 pub type NewPictureResult<T> = Result<T, NewPictureError>;
55 
56 /// Error returned by stateless backend methods.
57 #[derive(Error, Debug)]
58 pub enum StatelessBackendError {
59     #[error(transparent)]
60     Other(#[from] anyhow::Error),
61 }
62 
63 /// Result type returned by stateless backend methods.
64 pub type StatelessBackendResult<T> = Result<T, StatelessBackendError>;
65 
66 /// Decoder implementations can use this struct to represent their decoding state.
67 ///
68 /// `F` is a type containing the parsed stream format, that the decoder will use for format
69 /// negotiation with the client.
70 #[derive(Clone, Default)]
71 enum DecodingState<F> {
72     /// Decoder will ignore all input until format and resolution information passes by.
73     #[default]
74     AwaitingStreamInfo,
75     /// Decoder is stopped until the client has confirmed the output format.
76     AwaitingFormat(F),
77     /// Decoder is currently decoding input.
78     Decoding,
79     /// Decoder has been reset after a flush, and can resume with the current parameters after
80     /// seeing a key frame.
81     Reset,
82     // Decoder has recently seen a DRC frame and is flushing and waiting for all frames to be
83     // output before performing the DRC operation.
84     FlushingForDRC,
85 }
86 
87 /// Error returned by the [`StatelessVideoDecoder::decode`] method.
88 #[derive(Debug, Error)]
89 pub enum DecodeError {
90     #[error("not enough output buffers available to continue, need {0} more")]
91     NotEnoughOutputBuffers(usize),
92     #[error("cannot accept more input until pending events are processed")]
93     CheckEvents,
94     #[error("error while parsing frame: {0}")]
95     ParseFrameError(String),
96     #[error(transparent)]
97     DecoderError(#[from] anyhow::Error),
98     #[error(transparent)]
99     BackendError(#[from] StatelessBackendError),
100 }
101 
102 /// Convenience conversion for codecs that process a single frame per decode call.
103 impl From<NewPictureError> for DecodeError {
from(err: NewPictureError) -> Self104     fn from(err: NewPictureError) -> Self {
105         match err {
106             NewPictureError::OutOfOutputBuffers => DecodeError::NotEnoughOutputBuffers(1),
107             NewPictureError::BackendError(e) => {
108                 DecodeError::BackendError(StatelessBackendError::Other(e))
109             }
110         }
111     }
112 }
113 
114 /// Error returned by the [`StatelessVideoDecoder::wait_for_next_event`] method.
115 #[derive(Debug, Error)]
116 pub enum WaitNextEventError {
117     #[error("timed out while waiting for next decoder event")]
118     TimedOut,
119 }
120 
121 /// Specifies the type of picture that a backend will create for a given codec.
122 ///
123 /// The picture type is state that is preserved from the start of a given frame to its submission
124 /// to the backend. Some codecs don't need it, in this case they can just set `Picture` to `()`.
125 pub trait StatelessDecoderBackendPicture<Codec: StatelessCodec> {
126     /// Backend-specific type representing a frame being decoded. Useful for decoders that need
127     /// to render a frame in several steps and to preserve its state in between.
128     ///
129     /// Backends that don't use this can simply set it to `()`.
130     type Picture;
131 }
132 
133 /// Common trait shared by all stateless video decoder backends, providing codec-independent
134 /// methods.
135 pub trait StatelessDecoderBackend {
136     /// The type that the backend returns as a result of a decode operation.
137     /// This will usually be some backend-specific type with a resource and a
138     /// resource pool so that said buffer can be reused for another decode
139     /// operation when it goes out of scope.
140     type Handle: DecodedHandle;
141 
142     /// Returns the current decoding parameters, as parsed from the stream.
stream_info(&self) -> Option<&StreamInfo>143     fn stream_info(&self) -> Option<&StreamInfo>;
144 
145     // Resets the backend decoder to accommodate for a format change event.
reset_backend(&mut self) -> anyhow::Result<()>146     fn reset_backend(&mut self) -> anyhow::Result<()>;
147 }
148 
149 /// Stateless video decoder interface.
150 ///
151 /// A stateless decoder differs from a stateful one in that its input and output queues are not
152 /// operating independently: a new decode unit can only be processed if there is already an output
153 /// resource available to receive its decoded content.
154 ///
155 /// Therefore [`decode`] can refuse work if there is no output resource
156 /// available at the time of calling, in which case the caller is responsible for calling
157 /// [`decode`] again with the same parameters after processing at least one
158 /// pending output frame and returning it to the decoder.
159 ///
160 /// The `M` generic parameter is the type of the memory descriptor backing the output frames.
161 ///
162 /// [`decode`]: StatelessVideoDecoder::decode
163 pub trait StatelessVideoDecoder {
164     /// Type of the [`DecodedHandle`]s that decoded frames are returned into.
165     type Handle: DecodedHandle;
166 
167     /// Attempts to decode `bitstream` if the current conditions allow it.
168     ///
169     /// This method will return [`DecodeError::CheckEvents`] if processing cannot take place until
170     /// pending events are handled. This could either be because a change of output format has
171     /// been detected that the client should acknowledge, or because there are no available output
172     /// resources and dequeueing and returning pending frames will fix that. After the cause has
173     /// been addressed, the client is responsible for calling this method again with the same data.
174     ///
175     /// The return value is the number of bytes in `bitstream` that have been processed. Usually
176     /// this will be equal to the length of `bitstream`, but some codecs may only do partial
177     /// processing if e.g. several units are sent at the same time. It is the responsibility of the
178     /// caller to check that all submitted input has been processed, and to resubmit the
179     /// unprocessed part if it hasn't. See the documentation of each codec for their expectations.
decode( &mut self, timestamp: u64, bitstream: &[u8], alloc_cb: &mut dyn FnMut() -> Option<<Self::Handle as DecodedHandle>::Frame>, ) -> Result<usize, DecodeError>180     fn decode(
181         &mut self,
182         timestamp: u64,
183         bitstream: &[u8],
184         alloc_cb: &mut dyn FnMut() -> Option<<Self::Handle as DecodedHandle>::Frame>,
185     ) -> Result<usize, DecodeError>;
186 
187     /// Flush the decoder i.e. finish processing all pending decode requests and make sure the
188     /// resulting frames are ready to be retrieved via [`next_event`].
189     ///
190     /// Note that after flushing, a key frame must be submitted before decoding can resume.
191     ///
192     /// [`next_event`]: StatelessVideoDecoder::next_event
flush(&mut self) -> Result<(), DecodeError>193     fn flush(&mut self) -> Result<(), DecodeError>;
194 
stream_info(&self) -> Option<&StreamInfo>195     fn stream_info(&self) -> Option<&StreamInfo>;
196 
197     /// Returns the next event, if there is any pending.
next_event(&mut self) -> Option<DecoderEvent<Self::Handle>>198     fn next_event(&mut self) -> Option<DecoderEvent<Self::Handle>>;
199 
200     /// Blocks until [`StatelessVideoDecoder::next_event`] is expected to return `Some` or
201     /// `timeout` has elapsed.
202     ///
203     /// Wait for the next event and return it, or return `None` if `timeout` has been reached while
204     /// waiting.
wait_for_next_event(&mut self, timeout: Duration) -> Result<(), WaitNextEventError>205     fn wait_for_next_event(&mut self, timeout: Duration) -> Result<(), WaitNextEventError> {
206         // Wait until the next event is available.
207         let mut fd = nix::libc::pollfd {
208             fd: self.poll_fd().as_raw_fd(),
209             events: nix::libc::POLLIN,
210             revents: 0,
211         };
212         // SAFETY: `fd` is a valid reference to a properly-filled `pollfd`.
213         match unsafe { nix::libc::poll(&mut fd, 1, timeout.as_millis() as i32) } {
214             0 => Err(WaitNextEventError::TimedOut),
215             _ => Ok(()),
216         }
217     }
218 
219     /// Returns a file descriptor that signals `POLLIN` whenever an event is pending on this
220     /// decoder.
poll_fd(&self) -> BorrowedFd221     fn poll_fd(&self) -> BorrowedFd;
222 
223     /// Transforms the decoder into a [`StatelessVideoDecoder`] trait object.
224     ///
225     /// All decoders going through this method present the same virtual interface when they return.
226     /// This is useful in order avoid monomorphization of application code that can control
227     /// decoders using various codecs or backends.
into_trait_object(self) -> DynStatelessVideoDecoder<<Self::Handle as DecodedHandle>::Frame> where Self: Sized + 'static, Self::Handle: 'static,228     fn into_trait_object(self) -> DynStatelessVideoDecoder<<Self::Handle as DecodedHandle>::Frame>
229     where
230         Self: Sized + 'static,
231         Self::Handle: 'static,
232     {
233         Box::new(DynStatelessVideoDecoderWrapper(self))
234     }
235 }
236 
237 /// Wrapper type for a `StatelessVideoDecoder` that can be turned into a trait object with a common
238 /// interface.
239 struct DynStatelessVideoDecoderWrapper<D: StatelessVideoDecoder>(D);
240 
241 impl<D> StatelessVideoDecoder for DynStatelessVideoDecoderWrapper<D>
242 where
243     D: StatelessVideoDecoder,
244     <D as StatelessVideoDecoder>::Handle: 'static,
245 {
246     type Handle = DynDecodedHandle<<D::Handle as DecodedHandle>::Frame>;
247 
decode( &mut self, timestamp: u64, bitstream: &[u8], alloc_cb: &mut dyn FnMut() -> Option<<Self::Handle as DecodedHandle>::Frame>, ) -> Result<usize, DecodeError>248     fn decode(
249         &mut self,
250         timestamp: u64,
251         bitstream: &[u8],
252         alloc_cb: &mut dyn FnMut() -> Option<<Self::Handle as DecodedHandle>::Frame>,
253     ) -> Result<usize, DecodeError> {
254         self.0.decode(timestamp, bitstream, alloc_cb)
255     }
256 
flush(&mut self) -> Result<(), DecodeError>257     fn flush(&mut self) -> Result<(), DecodeError> {
258         self.0.flush()
259     }
260 
stream_info(&self) -> Option<&StreamInfo>261     fn stream_info(&self) -> Option<&StreamInfo> {
262         self.0.stream_info()
263     }
264 
next_event(&mut self) -> Option<DecoderEvent<Self::Handle>>265     fn next_event(&mut self) -> Option<DecoderEvent<Self::Handle>> {
266         self.0.next_event().map(|e| match e {
267             DecoderEvent::FrameReady(h) => {
268                 DecoderEvent::FrameReady(Box::new(h) as DynDecodedHandle<_>)
269             }
270             DecoderEvent::FormatChanged => DecoderEvent::FormatChanged,
271         })
272     }
273 
poll_fd(&self) -> BorrowedFd274     fn poll_fd(&self) -> BorrowedFd {
275         self.0.poll_fd()
276     }
277 }
278 
279 pub type DynStatelessVideoDecoder<D> = Box<dyn StatelessVideoDecoder<Handle = DynDecodedHandle<D>>>;
280 
281 pub trait StatelessCodec {
282     /// Type providing current format information for the codec: resolution, color format, etc.
283     ///
284     /// For H.264 this would be the Sps, for VP8 or VP9 the frame header.
285     type FormatInfo;
286     /// State that needs to be kept during a decoding operation, typed by backend.
287     type DecoderState<H: DecodedHandle, P>;
288 }
289 
290 /// A struct that serves as a basis to implement a stateless decoder.
291 ///
292 /// A stateless decoder is defined by three generic parameters:
293 ///
294 /// * A codec, represented by a type that implements [`StatelessCodec`]. This type defines the
295 /// codec-specific decoder state and other codec properties.
296 /// * A backend, i.e. an interface to talk to the hardware that accelerates decoding. An example is
297 /// the VAAPI backend that uses VAAPI for acceleration. The backend will typically itself be typed
298 /// against a memory decriptor, defining how memory is provided for decoded frames.
299 ///
300 /// So for instance, a decoder for the H264 codec, using VAAPI for acceleration with self-managed
301 /// memory, will have the following type:
302 ///
303 /// ```text
304 /// let decoder: StatelessDecoder<H264, VaapiBackend<()>>;
305 /// ```
306 ///
307 /// This struct just manages the high-level decoder state as well as the queue of decoded frames.
308 /// All the rest is left to codec-specific code.
309 pub struct StatelessDecoder<C, B>
310 where
311     C: StatelessCodec,
312     B: StatelessDecoderBackend + StatelessDecoderBackendPicture<C>,
313 {
314     /// The current coded resolution
315     coded_resolution: Resolution,
316 
317     /// Whether the decoder should block on decode operations.
318     blocking_mode: BlockingMode,
319 
320     ready_queue: ReadyFramesQueue<B::Handle>,
321 
322     decoding_state: DecodingState<C::FormatInfo>,
323 
324     /// The backend used for hardware acceleration.
325     backend: B,
326 
327     /// Codec-specific state.
328     codec: C::DecoderState<B::Handle, B::Picture>,
329 
330     /// Signaled whenever the decoder is in `AwaitingFormat` state.
331     awaiting_format_event: EventFd,
332 
333     /// Union of `awaiting_format_event` and `ready_queue` to signal whenever there is an event
334     /// (frame ready or format change) pending.
335     epoll_fd: Epoll,
336 }
337 
338 #[derive(Debug, Error)]
339 pub enum NewStatelessDecoderError {
340     #[error("failed to create EventFd for ready frames queue: {0}")]
341     ReadyFramesQueue(Errno),
342     #[error("failed to create EventFd for awaiting format event: {0}")]
343     AwaitingFormatEventFd(Errno),
344     #[error("failed to create Epoll for decoder: {0}")]
345     Epoll(Errno),
346     #[error("failed to add poll FDs to decoder Epoll: {0}")]
347     EpollAdd(Errno),
348     #[error("failed to initialize the driver")]
349     DriverInitialization,
350 }
351 
352 impl<C, B> StatelessDecoder<C, B>
353 where
354     C: StatelessCodec,
355     B: StatelessDecoderBackend + StatelessDecoderBackendPicture<C>,
356     C::DecoderState<B::Handle, B::Picture>: Default,
357 {
new(backend: B, blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError>358     pub fn new(backend: B, blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError> {
359         let ready_queue =
360             ReadyFramesQueue::new().map_err(NewStatelessDecoderError::ReadyFramesQueue)?;
361         let awaiting_format_event =
362             EventFd::new().map_err(NewStatelessDecoderError::AwaitingFormatEventFd)?;
363         let epoll_fd =
364             Epoll::new(EpollCreateFlags::empty()).map_err(NewStatelessDecoderError::Epoll)?;
365         epoll_fd
366             .add(ready_queue.poll_fd(), EpollEvent::new(EpollFlags::EPOLLIN, 1))
367             .map_err(NewStatelessDecoderError::EpollAdd)?;
368         epoll_fd
369             .add(awaiting_format_event.as_fd(), EpollEvent::new(EpollFlags::EPOLLIN, 2))
370             .map_err(NewStatelessDecoderError::EpollAdd)?;
371 
372         Ok(Self {
373             backend,
374             blocking_mode,
375             coded_resolution: Default::default(),
376             decoding_state: Default::default(),
377             ready_queue,
378             codec: Default::default(),
379             awaiting_format_event,
380             epoll_fd,
381         })
382     }
383 
384     /// Switch the decoder into `AwaitingFormat` state, making it refuse any input until the
385     /// `FormatChanged` event is processed.
await_format_change(&mut self, format_info: C::FormatInfo)386     fn await_format_change(&mut self, format_info: C::FormatInfo) {
387         self.decoding_state = DecodingState::AwaitingFormat(format_info);
388         self.awaiting_format_event.write(1).unwrap();
389     }
390 
391     // If the decoder is in a flushing state, the decoder will wait until the ready_queue is
392     // empty. Once the ready_queue is empty, the decoder will reset the backend.
wait_for_drc_flush(&mut self) -> Result<(), DecodeError>393     fn wait_for_drc_flush(&mut self) -> Result<(), DecodeError> {
394         if matches!(self.decoding_state, DecodingState::FlushingForDRC) {
395             if self.ready_queue.queue.is_empty() {
396                 // We can start the DRC operation since the ready queue is empty.
397                 self.backend.reset_backend()?;
398                 self.decoding_state = DecodingState::Reset;
399             } else {
400                 // Since the ready queue is not empty yet, we can't start the DRC.
401                 // Clear the awaiting format event as we cannot process this yet.
402                 self.awaiting_format_event.read().unwrap();
403                 return Err(DecodeError::CheckEvents);
404             }
405         }
406         Ok(())
407     }
408 
409     /// Returns the next pending event, if any, using `on_format_changed` as the format change
410     /// callback of the [`StatelessDecoderFormatNegotiator`] if there is a resolution change event
411     /// pending.
query_next_event<F>(&mut self, on_format_changed: F) -> Option<DecoderEvent<B::Handle>> where Self: StatelessVideoDecoder<Handle = B::Handle>, C::FormatInfo: Clone, F: Fn(&mut Self, &C::FormatInfo) + 'static,412     fn query_next_event<F>(&mut self, on_format_changed: F) -> Option<DecoderEvent<B::Handle>>
413     where
414         Self: StatelessVideoDecoder<Handle = B::Handle>,
415         C::FormatInfo: Clone,
416         F: Fn(&mut Self, &C::FormatInfo) + 'static,
417     {
418         // The next event is either the next frame, or, if we are awaiting negotiation, the format
419         // change event that will allow us to keep going.
420         self.ready_queue.next().map(DecoderEvent::FrameReady).or_else(|| {
421             if let DecodingState::AwaitingFormat(format_info) = self.decoding_state.clone() {
422                 on_format_changed(self, &format_info);
423                 self.decoding_state = DecodingState::Reset;
424                 self.awaiting_format_event.read().unwrap();
425                 Some(DecoderEvent::FormatChanged)
426             } else {
427                 None
428             }
429         })
430     }
431 }
432 
433 #[cfg(test)]
434 pub(crate) mod tests {
435     use crate::decoder::stateless::StatelessVideoDecoder;
436     use crate::decoder::DecodedHandle;
437 
438     /// Stream that can be used in tests, along with the CRC32 of all of its frames.
439     pub struct TestStream {
440         /// Bytestream to decode.
441         pub stream: &'static [u8],
442         /// Expected CRC for each frame, one per line.
443         pub crcs: &'static str,
444     }
445 
446     /// Run the codec-specific `decoding_loop` on a `decoder` with a given `test`, linearly
447     /// decoding the stream until its end.
448     ///
449     /// If `check_crcs` is `true`, then the expected CRCs of the decoded images are compared
450     /// against the existing result. We may want to set this to false when using a decoder backend
451     /// that does not produce actual frames.
452     ///
453     /// `dump_yuv` will dump all the decoded frames into `/tmp/framexxx.yuv`. Set this to true in
454     /// order to debug the output of the test.
test_decode_stream<D, H, FP, L>( decoding_loop: L, mut decoder: D, test: &TestStream, check_crcs: bool, dump_yuv: bool, ) where H: DecodedHandle, D: StatelessVideoDecoder<Handle = H>, L: Fn(&mut D, &[u8], &mut dyn FnMut(H)) -> anyhow::Result<()>,455     pub fn test_decode_stream<D, H, FP, L>(
456         decoding_loop: L,
457         mut decoder: D,
458         test: &TestStream,
459         check_crcs: bool,
460         dump_yuv: bool,
461     ) where
462         H: DecodedHandle,
463         D: StatelessVideoDecoder<Handle = H>,
464         L: Fn(&mut D, &[u8], &mut dyn FnMut(H)) -> anyhow::Result<()>,
465     {
466         let mut crcs = test.crcs.lines().enumerate();
467 
468         decoding_loop(&mut decoder, test.stream, &mut |handle| {
469             let (frame_num, expected_crc) = crcs.next().expect("decoded more frames than expected");
470 
471             if check_crcs || dump_yuv {
472                 handle.sync().unwrap();
473                 let picture = handle.dyn_picture();
474                 let mut backend_handle = picture.dyn_mappable_handle().unwrap();
475 
476                 let buffer_size = backend_handle.image_size();
477                 let mut nv12 = vec![0; buffer_size];
478 
479                 backend_handle.read(&mut nv12).unwrap();
480 
481                 if dump_yuv {
482                     std::fs::write(format!("/tmp/frame{:03}.yuv", frame_num), &nv12).unwrap();
483                 }
484 
485                 if check_crcs {
486                     let frame_crc = format!("{:08x}", crc32fast::hash(&nv12));
487                     assert_eq!(frame_crc, expected_crc, "at frame {}", frame_num);
488                 }
489             }
490         })
491         .unwrap();
492 
493         assert_eq!(crcs.next(), None, "decoded less frames than expected");
494     }
495 }
496