use NAPacketiser::attach_stream() where appropriate
[nihav-player.git] / nihed-cros-libva / src / picture.rs
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::marker::PhantomData;
9 use std::rc::Rc;
10
11 use crate::bindings;
12 use crate::buffer::Buffer;
13 use crate::context::Context;
14 use crate::display::Display;
15 use crate::status::*;
16 use crate::surface::Surface;
17
18 // Use the sealed trait pattern to make sure that new states are not created in caller code. More
19 // information about the sealed trait pattern can be found at
20 // <https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed>
21 mod private {
22 pub trait Sealed {}
23 }
24
25 /// A `Picture` will only have valid YUV data after a sequence of operations are performed in a
26 /// particular order. This order correspond to the following VA-API calls: `vaBeginPicture`,
27 /// `vaRenderPicture`, `vaEndPicture` and `vaSyncSurface`. This trait enforces this ordering by
28 /// implementing the Typestate pattern to constrain what operations are available in what particular
29 /// states.
30 ///
31 /// The states for the state machine are:
32 ///
33 /// * PictureNew -> PictureBegin
34 /// * PictureBegin -> PictureRender
35 /// * PictureRender ->PictureEnd
36 /// * PictureEnd -> PictureSync
37 ///
38 /// Where the surface can be reclaimed in both `PictureNew` and `PictureSync`, as either no
39 /// operation took place (as in `PictureNew`), or it is guaranteed that the operation has already
40 /// completed (as in `PictureSync`).
41 ///
42 /// More information about the Typestate pattern can be found at
43 /// <http://cliffle.com/blog/rust-typestate/>
44 pub trait PictureState: private::Sealed {}
45
46 /// Represents a `Picture` that has just been created.
47 pub enum PictureNew {}
48 impl PictureState for PictureNew {}
49 impl private::Sealed for PictureNew {}
50
51 /// Represents a `Picture` after `vaBeginPicture` has been called.
52 pub enum PictureBegin {}
53 impl PictureState for PictureBegin {}
54 impl private::Sealed for PictureBegin {}
55
56 /// Represents a `Picture` after `vaRenderPicture` has been called.
57 pub enum PictureRender {}
58 impl PictureState for PictureRender {}
59 impl private::Sealed for PictureRender {}
60
61 /// Represents a `Picture` after `vaEndPicture` has been called.
62 pub enum PictureEnd {}
63 impl PictureState for PictureEnd {}
64 impl private::Sealed for PictureEnd {}
65
66 /// Represents a `Picture` after `vaSyncSurface` has been called on the underlying surface.
67 pub enum PictureSync {}
68 impl PictureState for PictureSync {}
69 impl private::Sealed for PictureSync {}
70
71 /// Represents a state where one can reclaim the underlying `Surface` for this `Picture`. This is
72 /// true when either no decoding has been initiated or, alternatively, when the decoding operation
73 /// has completed for the underlying `vaSurface`
74 pub trait PictureReclaimableSurface: PictureState + private::Sealed {}
75 impl PictureReclaimableSurface for PictureNew {}
76 impl PictureReclaimableSurface for PictureSync {}
77
78 struct PictureInner {
79 /// Timestamp of the picture.
80 timestamp: u64,
81 /// A context associated with this picture.
82 context: Rc<Context>,
83 /// Contains the buffers used to decode the data.
84 buffers: Vec<Buffer>,
85 /// Contains the actual decoded data. Note that the surface may be shared in
86 /// interlaced decoding.
87 surface: Rc<RefCell<Surface>>,
88 }
89
90 /// A `Surface` that is being rendered into.
91 ///
92 /// This struct abstracts the decoding flow using `vaBeginPicture`, `vaRenderPicture`,
93 /// `vaEndPicture` and `vaSyncSurface` in a type-safe way.
94 ///
95 /// The surface will have valid picture data after all the stages of decoding are called.
96 pub struct Picture<S: PictureState> {
97 inner: Box<PictureInner>,
98 phantom: std::marker::PhantomData<S>,
99 }
100
101 impl Picture<PictureNew> {
102 /// Creates a new Picture with a given `timestamp`. `surface` is the underlying surface that
103 /// libva will render to.
104 pub fn new(timestamp: u64, context: Rc<Context>, surface: Surface) -> Self {
105 Self {
106 inner: Box::new(PictureInner {
107 timestamp,
108 context,
109 buffers: Default::default(),
110 surface: Rc::new(RefCell::new(surface)),
111 }),
112
113 phantom: PhantomData,
114 }
115 }
116
117 /// Creates a new Picture with a given `frame_number` to identify it,
118 /// reusing the Surface from `picture`. This is useful for interlaced
119 /// decoding as one can render both fields to the same underlying surface.
120 pub fn new_from_same_surface<T: PictureReclaimableSurface, S: PictureReclaimableSurface>(
121 timestamp: u64,
122 picture: &Picture<S>,
123 ) -> Picture<T> {
124 let context = Rc::clone(&picture.inner.context);
125 Picture {
126 inner: Box::new(PictureInner {
127 timestamp,
128 context,
129 buffers: Default::default(),
130 surface: Rc::clone(&picture.inner.surface),
131 }),
132
133 phantom: PhantomData,
134 }
135 }
136
137 /// Add `buffer` to the picture.
138 pub fn add_buffer(&mut self, buffer: Buffer) {
139 self.inner.buffers.push(buffer);
140 }
141
142 /// Wrapper around `vaBeginPicture`.
143 pub fn begin(self) -> VAResult<Picture<PictureBegin>> {
144 // Safe because `self.inner.context` represents a valid VAContext and
145 // `self.inner.surface` represents a valid VASurface.
146 (unsafe {
147 bindings::vaBeginPicture(
148 self.inner.context.display().handle(),
149 self.inner.context.id(),
150 self.inner.surface.borrow().id(),
151 )
152 })
153 .check()?;
154
155 Ok(Picture {
156 inner: self.inner,
157 phantom: PhantomData,
158 })
159 }
160 }
161
162 impl Picture<PictureBegin> {
163 /// Wrapper around `vaRenderPicture`.
164 pub fn render(self) -> VAResult<Picture<PictureRender>> {
165 // Safe because `self.inner.context` represents a valid `VAContext` and `self.inner.surface`
166 // represents a valid `VASurface`. `buffers` point to a Rust struct and the vector length is
167 // passed to the C function, so it is impossible to write past the end of the vector's
168 // storage by mistake.
169 (unsafe {
170 bindings::vaRenderPicture(
171 self.inner.context.display().handle(),
172 self.inner.context.id(),
173 Buffer::as_id_vec(&self.inner.buffers).as_mut_ptr(),
174 self.inner.buffers.len() as i32,
175 )
176 })
177 .check()?;
178
179 Ok(Picture {
180 inner: self.inner,
181 phantom: PhantomData,
182 })
183 }
184 }
185
186 impl Picture<PictureRender> {
187 /// Wrapper around `vaEndPicture`.
188 pub fn end(self) -> VAResult<Picture<PictureEnd>> {
189 // Safe because `self.inner.context` represents a valid `VAContext`.
190 (unsafe {
191 bindings::vaEndPicture(
192 self.inner.context.display().handle(),
193 self.inner.context.id(),
194 )
195 })
196 .check()?;
197 Ok(Picture {
198 inner: self.inner,
199 phantom: PhantomData,
200 })
201 }
202 }
203
204 impl Picture<PictureEnd> {
205 /// Syncs the picture, ensuring that all pending operations are complete when this call returns.
206 pub fn sync(self) -> std::result::Result<Picture<PictureSync>, (VAError, Self)> {
207 let res = self.inner.surface.borrow().sync();
208
209 match res {
210 Ok(()) => Ok(Picture {
211 inner: self.inner,
212 phantom: PhantomData,
213 }),
214 Err(e) => Err((e, self)),
215 }
216 }
217
218 /// Queries the status of the underlying surface.
219 ///
220 /// This call can be used to implement a non-blocking path, wherein a decoder queries the status
221 /// of the surface after each decode operation instead of blocking on it.
222 pub fn query_status(&self) -> VAResult<VASurfaceStatus> {
223 self.inner.surface.borrow_mut().query_status()
224 }
225 }
226
227 impl<S: PictureState> Picture<S> {
228 /// Returns the timestamp of this picture.
229 pub fn timestamp(&self) -> u64 {
230 self.inner.timestamp
231 }
232
233 /// Returns the ID of the underlying surface.
234 pub fn surface_id(&self) -> bindings::VASurfaceID {
235 self.inner.surface.borrow().id()
236 }
237
238 /// Returns a reference to the display owning this `Picture`.
239 pub(crate) fn display(&self) -> &Rc<Display> {
240 self.inner.context.display()
241 }
242
243 /// Returns the size of the surface being rendered to by this `Picture`.
244 pub fn surface_size(&self) -> (u32, u32) {
245 self.inner.surface.borrow().size()
246 }
247 }
248
249 impl<S: PictureReclaimableSurface> Picture<S> {
250 /// Reclaim ownership of the Surface this picture has been created from, consuming the picture
251 /// in the process. Useful if the Surface is part of a pool.
252 pub fn take_surface(self) -> VAResult<Surface> {
253 match Rc::try_unwrap(self.inner.surface) {
254 Ok(surface) => Ok(surface.into_inner()),
255 Err(_) => Err(VAError::SurfaceBusy),
256 }
257 }
258
259 /// Returns a reference to the underlying `Surface` for this `Picture`
260 pub fn surface(&self) -> Ref<Surface> {
261 self.inner.surface.borrow()
262 }
263
264 /// Returns a mutable reference to the underlying `Surface` for this `Picture`
265 pub fn surface_mut(&mut self) -> RefMut<Surface> {
266 self.inner.surface.borrow_mut()
267 }
268 }