cros_codecs/backend/vaapi/
surface_pool.rs1use std::borrow::Borrow;
6use std::cell::RefCell;
7use std::collections::BTreeMap;
8use std::collections::VecDeque;
9use std::rc::Rc;
10use std::rc::Weak;
11
12use libva::Display;
13use libva::Surface;
14use libva::SurfaceMemoryDescriptor;
15use libva::VASurfaceID;
16
17use crate::decoder::FramePool;
18use crate::Resolution;
19
20pub struct PooledVaSurface<M: SurfaceMemoryDescriptor> {
25 surface: Option<Surface<M>>,
26 pool: Weak<RefCell<VaSurfacePoolInner<M>>>,
27}
28
29impl<M: SurfaceMemoryDescriptor> PooledVaSurface<M> {
30 fn new(surface: Surface<M>, pool: &Rc<RefCell<VaSurfacePoolInner<M>>>) -> Self {
31 Self {
32 surface: Some(surface),
33 pool: Rc::downgrade(pool),
34 }
35 }
36
37 pub fn detach_from_pool(mut self) -> Surface<M> {
40 let surface = self.surface.take().unwrap();
42
43 if let Some(pool) = self.pool.upgrade() {
44 (*pool).borrow_mut().managed_surfaces.remove(&surface.id());
45 }
46
47 surface
48 }
49}
50
51impl<M: SurfaceMemoryDescriptor> Borrow<Surface<M>> for PooledVaSurface<M> {
52 fn borrow(&self) -> &Surface<M> {
53 self.surface.as_ref().unwrap()
55 }
56}
57
58impl<M: SurfaceMemoryDescriptor> AsRef<M> for PooledVaSurface<M> {
59 fn as_ref(&self) -> &M {
60 <Self as Borrow<Surface<M>>>::borrow(self).as_ref()
61 }
62}
63
64impl<M: SurfaceMemoryDescriptor> Drop for PooledVaSurface<M> {
65 fn drop(&mut self) {
66 if let Some(surface) = self.surface.take() {
68 if let Some(pool) = self.pool.upgrade() {
70 let mut pool_borrowed = (*pool).borrow_mut();
71 if pool_borrowed.managed_surfaces.contains_key(&surface.id()) {
73 pool_borrowed.surfaces.push_back(surface);
74 return;
75 }
76 }
77
78 log::debug!(
80 "Dropping stale surface: {}, ({:?})",
81 surface.id(),
82 surface.size()
83 )
84 }
85 }
86}
87
88struct VaSurfacePoolInner<M: SurfaceMemoryDescriptor> {
89 display: Rc<Display>,
90 rt_format: u32,
91 usage_hint: Option<libva::UsageHint>,
92 coded_resolution: Resolution,
93 surfaces: VecDeque<Surface<M>>,
94 managed_surfaces: BTreeMap<VASurfaceID, Resolution>,
98}
99
100pub struct VaSurfacePool<M: SurfaceMemoryDescriptor> {
110 inner: Rc<RefCell<VaSurfacePoolInner<M>>>,
111}
112
113impl<M: SurfaceMemoryDescriptor> VaSurfacePool<M> {
114 #[allow(dead_code)]
122 fn add_surface(&mut self, surface: Surface<M>) -> Result<(), Surface<M>> {
123 let mut inner = (*self.inner).borrow_mut();
124
125 if Resolution::from(surface.size()).can_contain(inner.coded_resolution) {
126 inner
127 .managed_surfaces
128 .insert(surface.id(), surface.size().into());
129 inner.surfaces.push_back(surface);
130 Ok(())
131 } else {
132 Err(surface)
133 }
134 }
135
136 pub fn new(
145 display: Rc<Display>,
146 rt_format: u32,
147 usage_hint: Option<libva::UsageHint>,
148 coded_resolution: Resolution,
149 ) -> Self {
150 Self {
151 inner: Rc::new(RefCell::new(VaSurfacePoolInner {
152 display,
153 rt_format,
154 usage_hint,
155 coded_resolution,
156 surfaces: VecDeque::new(),
157 managed_surfaces: Default::default(),
158 })),
159 }
160 }
161
162 pub fn get_surface(&mut self) -> Option<PooledVaSurface<M>> {
164 let mut inner = (*self.inner).borrow_mut();
165 let surface = inner.surfaces.pop_front();
166
167 debug_assert!({
170 match surface.as_ref() {
171 Some(s) => Resolution::from(s.size()).can_contain(inner.coded_resolution),
172 None => true,
173 }
174 });
175
176 surface.map(|s| PooledVaSurface::new(s, &self.inner))
177 }
178}
179
180impl<M: SurfaceMemoryDescriptor> FramePool for VaSurfacePool<M> {
181 type Descriptor = M;
182
183 fn coded_resolution(&self) -> Resolution {
184 (*self.inner).borrow().coded_resolution
185 }
186
187 fn set_coded_resolution(&mut self, resolution: Resolution) {
188 let mut inner = (*self.inner).borrow_mut();
189
190 inner.coded_resolution = resolution;
191 inner
192 .managed_surfaces
193 .retain(|_, res| res.can_contain(resolution));
194 inner
195 .surfaces
196 .retain(|s| Resolution::from(s.size()).can_contain(resolution));
197 }
198
199 fn add_frames(&mut self, descriptors: Vec<Self::Descriptor>) -> Result<(), anyhow::Error> {
200 let mut inner = (*self.inner).borrow_mut();
201
202 let surfaces = inner
203 .display
204 .create_surfaces(
205 inner.rt_format,
206 None,
209 inner.coded_resolution.width,
210 inner.coded_resolution.height,
211 inner.usage_hint,
212 descriptors,
213 )
214 .map_err(|e| anyhow::anyhow!(e))?;
215
216 for surface in &surfaces {
217 inner
218 .managed_surfaces
219 .insert(surface.id(), surface.size().into());
220 }
221 inner.surfaces.extend(surfaces);
222
223 Ok(())
224 }
225
226 fn num_free_frames(&self) -> usize {
227 (*self.inner).borrow().surfaces.len()
228 }
229
230 fn num_managed_frames(&self) -> usize {
231 (*self.inner).borrow().managed_surfaces.len()
232 }
233
234 fn clear(&mut self) {
235 let mut pool = (*self.inner).borrow_mut();
236
237 pool.surfaces.clear();
238 pool.managed_surfaces.clear();
239 }
240}