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