• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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