1 // Copyright 2022 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 use std::cell::Ref; 6 use std::cell::RefCell; 7 use std::cell::RefMut; 8 use std::collections::VecDeque; 9 use std::rc::Rc; 10 11 use thiserror::Error; 12 13 use crate::DecodedFormat; 14 use crate::Resolution; 15 16 pub mod h264; 17 pub mod vp8; 18 pub mod vp9; 19 20 pub type Result<T> = std::result::Result<T, Error>; 21 22 #[derive(Error, Debug)] 23 pub enum Error { 24 #[error(transparent)] 25 StatelessBackendError(#[from] StatelessBackendError), 26 #[error(transparent)] 27 Other(#[from] anyhow::Error), 28 } 29 30 #[derive(Error, Debug)] 31 pub enum StatelessBackendError { 32 #[error("not enough resources to proceed with the operation now")] 33 OutOfResources, 34 #[error("this resource is not ready")] 35 ResourceNotReady, 36 #[error("this format is not supported")] 37 UnsupportedFormat, 38 #[error("negotiation failed")] 39 NegotiationFailed(anyhow::Error), 40 #[error(transparent)] 41 Other(#[from] anyhow::Error), 42 } 43 44 pub type StatelessBackendResult<T> = std::result::Result<T, StatelessBackendError>; 45 46 pub(crate) trait VideoDecoderBackend { 47 /// The type that the backend returns as a result of a decode operation. 48 /// This will usually be some backend-specific type with a resource and a 49 /// resource pool so that said buffer can be reused for another decode 50 /// operation when it goes out of scope. 51 type Handle: DecodedHandle; 52 53 /// Returns the current coded resolution of the bitstream being processed. 54 /// This may be None if we have not read the stream parameters yet. coded_resolution(&self) -> Option<Resolution>55 fn coded_resolution(&self) -> Option<Resolution>; 56 57 /// Returns the current display resolution of the bitstream being processed. 58 /// This may be None if we have not read the stream parameters yet. display_resolution(&self) -> Option<Resolution>59 fn display_resolution(&self) -> Option<Resolution>; 60 61 /// Gets the number of output resources allocated by the backend. num_resources_total(&self) -> usize62 fn num_resources_total(&self) -> usize; 63 64 /// Gets the number of output resources left in the backend. num_resources_left(&self) -> usize65 fn num_resources_left(&self) -> usize; 66 67 /// Gets the chosen format. This is set to a default after the decoder reads 68 /// enough stream metadata from the bitstream. Some buffers need to be 69 /// processed first before the default format can be set. format(&self) -> Option<DecodedFormat>70 fn format(&self) -> Option<DecodedFormat>; 71 72 /// Try altering the decoded format. try_format(&mut self, format: DecodedFormat) -> Result<()>73 fn try_format(&mut self, format: DecodedFormat) -> Result<()>; 74 75 /// Poll for any ready pictures. `block` dictates whether this call should 76 /// block on the operation or return immediately. poll(&mut self, blocking_mode: BlockingMode) -> Result<VecDeque<Self::Handle>>77 fn poll(&mut self, blocking_mode: BlockingMode) -> Result<VecDeque<Self::Handle>>; 78 79 /// Whether the handle is ready for presentation. The decoder will check 80 /// this before returning the handle to clients. handle_is_ready(&self, handle: &Self::Handle) -> bool81 fn handle_is_ready(&self, handle: &Self::Handle) -> bool; 82 83 /// Block on handle `handle`. block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()>84 fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()>; 85 } 86 87 pub trait VideoDecoder { 88 /// Decode the `bitstream` represented by `timestamp`. Returns zero or more 89 /// decoded handles representing the decoded data. decode( &mut self, timestamp: u64, bitstream: &[u8], ) -> Result<Vec<Box<dyn DynDecodedHandle>>>90 fn decode( 91 &mut self, 92 timestamp: u64, 93 bitstream: &[u8], 94 ) -> Result<Vec<Box<dyn DynDecodedHandle>>>; 95 96 /// Flush the decoder i.e. finish processing all queued decode requests and 97 /// emit frames for them. flush(&mut self) -> Result<Vec<Box<dyn DynDecodedHandle>>>98 fn flush(&mut self) -> Result<Vec<Box<dyn DynDecodedHandle>>>; 99 100 /// Whether negotiation of the decoded format is possible. In particular, a 101 /// decoder will indicate that negotiation is possible after enough metadata 102 /// is collected from parsing the bitstream through calls to the `decode()` 103 /// method. 104 /// 105 /// The negotiation process will start as soon as `negotiation_possible()` 106 /// returns true. At this moment, the client and the backend can settle on a 107 /// format by using the `supported_formats_for_stream()`, `format()` and 108 /// `try_format()` methods. 109 /// 110 /// When `negotiation_possible()` returns true, the client may also query 111 /// the backend for new values for the coded resolution, display resolution 112 /// and/or to the number of resources allocated. 113 /// 114 /// The negotiation process ends as soon as another call to `decode()` is 115 /// made, at which point any queued data will be processed first in order to 116 /// generate any frames that might have been pending while the negotiation 117 /// process was under way and `negotiation_possible()` will from then on 118 /// return false. 119 /// 120 /// If no action is undertaken by the client in the window of time where 121 /// `negotiation_possible()` returns true, it is assumed that the default 122 /// format chosen by the backend is acceptable. 123 /// 124 /// The negotiation process can happen more than once if new stream metadata 125 /// indicate a change of the stream parameters such that the current decoded 126 /// format becomes incompatible with the stream. In this case, 127 /// `negotiation_possible()` will once again return true and the same 128 /// process described above will take place. negotiation_possible(&self) -> bool129 fn negotiation_possible(&self) -> bool; 130 131 /// Gets the number of output resources left in the backend after accounting 132 /// for any buffers that might be queued in the decoder. num_resources_left(&self) -> Option<usize>133 fn num_resources_left(&self) -> Option<usize>; 134 135 /// Gets the number of output resources allocated by the backend. num_resources_total(&self) -> usize136 fn num_resources_total(&self) -> usize; 137 /// 138 /// Returns the current coded resolution of the bitstream being processed. 139 /// This may be None if we have not read the stream parameters yet. coded_resolution(&self) -> Option<Resolution>140 fn coded_resolution(&self) -> Option<Resolution>; 141 142 /// Polls the decoder, emitting frames for all queued decode requests. This 143 /// is similar to flush, but it does not change the state of the decoded 144 /// picture buffer nor does it reset any internal state. poll(&mut self, blocking_mode: BlockingMode) -> Result<Vec<Box<dyn DynDecodedHandle>>>145 fn poll(&mut self, blocking_mode: BlockingMode) -> Result<Vec<Box<dyn DynDecodedHandle>>>; 146 } 147 148 pub trait DynDecodedHandle { dyn_picture_mut(&self) -> RefMut<dyn DynHandle>149 fn dyn_picture_mut(&self) -> RefMut<dyn DynHandle>; timestamp(&self) -> u64150 fn timestamp(&self) -> u64; display_resolution(&self) -> Resolution151 fn display_resolution(&self) -> Resolution; display_order(&self) -> Option<u64>152 fn display_order(&self) -> Option<u64>; 153 } 154 155 impl<T> DynDecodedHandle for T 156 where 157 T: DecodedHandle, 158 T::BackendHandle: DynHandle, 159 { dyn_picture_mut(&self) -> RefMut<dyn DynHandle>160 fn dyn_picture_mut(&self) -> RefMut<dyn DynHandle> { 161 DecodedHandle::handle_mut(self) 162 } 163 timestamp(&self) -> u64164 fn timestamp(&self) -> u64 { 165 DecodedHandle::timestamp(self) 166 } 167 display_resolution(&self) -> Resolution168 fn display_resolution(&self) -> Resolution { 169 DecodedHandle::display_resolution(self) 170 } 171 display_order(&self) -> Option<u64>172 fn display_order(&self) -> Option<u64> { 173 DecodedHandle::display_order(self) 174 } 175 } 176 177 pub trait DynHandle { 178 /// Gets an exclusive reference to the backend handle of this picture. 179 /// Assumes that this picture is backed by a handle and panics if not the case. dyn_mappable_handle_mut<'a>(&'a mut self) -> Box<dyn MappableHandle + 'a>180 fn dyn_mappable_handle_mut<'a>(&'a mut self) -> Box<dyn MappableHandle + 'a>; 181 } 182 183 /// A trait for types that can be mapped into the client's address space. 184 pub trait MappableHandle { 185 /// Read the contents of `self` into `buffer`. 186 /// 187 /// The size of `buffer` must be equal to `image_size()`, or an error will be returned. read(&mut self, buffer: &mut [u8]) -> Result<()>188 fn read(&mut self, buffer: &mut [u8]) -> Result<()>; 189 190 /// Returns the size of the `buffer` argument required to call `read` on this handle. image_size(&mut self) -> usize191 fn image_size(&mut self) -> usize; 192 } 193 194 /// Instructs the decoder on whether it should block on the decode operations. 195 /// Nonblocking mode is conditional on backend support. 196 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 197 pub enum BlockingMode { 198 Blocking, 199 NonBlocking, 200 } 201 202 impl Default for BlockingMode { default() -> Self203 fn default() -> Self { 204 Self::Blocking 205 } 206 } 207 208 /// Codec-specific information for a single frame. 209 pub trait FrameInfo { 210 /// Returns the display resolution of this frame. display_resolution(&self) -> Resolution211 fn display_resolution(&self) -> Resolution; 212 } 213 214 /// The handle type used by the stateless decoder backend. The only requirement 215 /// from implementors is that they give access to the underlying handle and 216 /// that they can be (cheaply) cloned. 217 pub trait DecodedHandle: Clone { 218 /// The type of the handle used by the backend. 219 type BackendHandle; 220 221 /// Returns a reference to the container of the backend handle. handle_rc(&self) -> &Rc<RefCell<Self::BackendHandle>>222 fn handle_rc(&self) -> &Rc<RefCell<Self::BackendHandle>>; 223 /// Returns a shared reference to the backend handle. handle(&self) -> Ref<Self::BackendHandle>224 fn handle(&self) -> Ref<Self::BackendHandle> { 225 self.handle_rc().borrow() 226 } 227 /// Returns a mutable reference to the backend handle. handle_mut(&self) -> RefMut<Self::BackendHandle>228 fn handle_mut(&self) -> RefMut<Self::BackendHandle> { 229 self.handle_rc().borrow_mut() 230 } 231 232 /// Returns the display order for the picture backed by this handle, if set by the decoder. display_order(&self) -> Option<u64>233 fn display_order(&self) -> Option<u64>; 234 /// Sets the display order for the picture backend by this handle set_display_order(&mut self, display_order: u64)235 fn set_display_order(&mut self, display_order: u64); 236 237 /// Returns the timestamp of the picture. timestamp(&self) -> u64238 fn timestamp(&self) -> u64; 239 240 /// Returns the display resolution at the time this handle was decoded. display_resolution(&self) -> Resolution241 fn display_resolution(&self) -> Resolution; 242 } 243