• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::{
2     collections::VecDeque,
3     fmt::Debug,
4     sync::{Arc, Mutex, Weak},
5     task::Wake,
6 };
7 
8 use log::error;
9 
10 use crate::device::queue::{
11     GetCaptureBufferByIndex, GetFreeBufferError, GetFreeCaptureBuffer, TryGetBufferError,
12 };
13 use crate::{
14     bindings,
15     device::poller::Waker,
16     memory::{BufferHandles, MmapHandle, PrimitiveBufferHandles},
17     Format,
18 };
19 
20 use thiserror::Error;
21 
22 #[derive(Debug, Error)]
23 pub enum GetSuitableBufferError {
24     #[error("error while calling try_get_free_buffer(): {0}")]
25     TryGetFree(#[from] GetFreeBufferError),
26     #[error("error while calling try_get_buffer(): {0}")]
27     TryGetIndexed(#[from] TryGetBufferError),
28 }
29 
30 pub trait HandlesProvider: Send + 'static {
31     type HandleType: BufferHandles;
32 
33     /// Request a set of handles. Returns `None` if no handle is currently
34     /// available. If that is the case, `waker` will be signaled when handles
35     /// are available again.
get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType>36     fn get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType>;
37 
get_suitable_buffer_for<'a, Q>( &self, _handles: &Self::HandleType, queue: &'a Q, ) -> Result<Q::Queueable, GetSuitableBufferError> where Q: GetCaptureBufferByIndex<'a, Self::HandleType> + GetFreeCaptureBuffer<'a, Self::HandleType>,38     fn get_suitable_buffer_for<'a, Q>(
39         &self,
40         _handles: &Self::HandleType,
41         queue: &'a Q,
42     ) -> Result<Q::Queueable, GetSuitableBufferError>
43     where
44         Q: GetCaptureBufferByIndex<'a, Self::HandleType>
45             + GetFreeCaptureBuffer<'a, Self::HandleType>,
46     {
47         Ok(queue.try_get_free_buffer()?)
48     }
49 }
50 
51 /// `HandleProvider`s on the heap are `HandleProvider`s too.
52 impl<P: HandlesProvider> HandlesProvider for Box<P> {
53     type HandleType = P::HandleType;
54 
get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType>55     fn get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType> {
56         self.as_ref().get_handles(waker)
57     }
58 
get_suitable_buffer_for<'a, Q>( &self, handles: &Self::HandleType, queue: &'a Q, ) -> Result<Q::Queueable, GetSuitableBufferError> where Q: GetCaptureBufferByIndex<'a, Self::HandleType> + GetFreeCaptureBuffer<'a, Self::HandleType>,59     fn get_suitable_buffer_for<'a, Q>(
60         &self,
61         handles: &Self::HandleType,
62         queue: &'a Q,
63     ) -> Result<Q::Queueable, GetSuitableBufferError>
64     where
65         Q: GetCaptureBufferByIndex<'a, Self::HandleType>
66             + GetFreeCaptureBuffer<'a, Self::HandleType>,
67     {
68         self.as_ref().get_suitable_buffer_for(handles, queue)
69     }
70 }
71 
72 impl<P: HandlesProvider + Sync> HandlesProvider for Arc<P> {
73     type HandleType = P::HandleType;
74 
get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType>75     fn get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType> {
76         self.as_ref().get_handles(waker)
77     }
78 
get_suitable_buffer_for<'a, Q>( &self, handles: &Self::HandleType, queue: &'a Q, ) -> Result<Q::Queueable, GetSuitableBufferError> where Q: GetCaptureBufferByIndex<'a, Self::HandleType> + GetFreeCaptureBuffer<'a, Self::HandleType>,79     fn get_suitable_buffer_for<'a, Q>(
80         &self,
81         handles: &Self::HandleType,
82         queue: &'a Q,
83     ) -> Result<Q::Queueable, GetSuitableBufferError>
84     where
85         Q: GetCaptureBufferByIndex<'a, Self::HandleType>
86             + GetFreeCaptureBuffer<'a, Self::HandleType>,
87     {
88         self.as_ref().get_suitable_buffer_for(handles, queue)
89     }
90 }
91 
92 pub struct MmapProvider(Vec<MmapHandle>);
93 
94 impl MmapProvider {
new(format: &Format) -> Self95     pub fn new(format: &Format) -> Self {
96         Self(vec![Default::default(); format.plane_fmt.len()])
97     }
98 }
99 
100 impl HandlesProvider for MmapProvider {
101     type HandleType = Vec<MmapHandle>;
102 
get_handles(&self, _waker: &Arc<Waker>) -> Option<Self::HandleType>103     fn get_handles(&self, _waker: &Arc<Waker>) -> Option<Self::HandleType> {
104         Some(self.0.clone())
105     }
106 }
107 
108 /// Internals of `PooledHandlesProvider`, which acts just as a protected wrapper
109 /// around this structure.
110 struct PooledHandlesProviderInternal<H: BufferHandles> {
111     buffers: VecDeque<H>,
112     waker: Option<Arc<Waker>>,
113 }
114 
115 unsafe impl<H: BufferHandles> Send for PooledHandlesProviderInternal<H> {}
116 
117 /// A handles provider that recycles buffers from a fixed set in a pool.
118 /// Provided `PooledHandles` will not be recycled for as long as the instance is
119 /// alive. Once it is dropped, it the underlying buffer returns into the pool to
120 /// be reused later.
121 pub struct PooledHandlesProvider<H: BufferHandles> {
122     d: Arc<Mutex<PooledHandlesProviderInternal<H>>>,
123 }
124 
125 impl<H: BufferHandles> PooledHandlesProvider<H> {
126     /// Create a new `PooledMemoryProvider`, using the set in `buffers`.
new<B: IntoIterator<Item = H>>(buffers: B) -> Self127     pub fn new<B: IntoIterator<Item = H>>(buffers: B) -> Self {
128         Self {
129             d: Arc::new(Mutex::new(PooledHandlesProviderInternal {
130                 buffers: buffers.into_iter().collect(),
131                 waker: None,
132             })),
133         }
134     }
135 }
136 
137 impl<H: BufferHandles> HandlesProvider for PooledHandlesProvider<H> {
138     type HandleType = PooledHandles<H>;
139 
get_handles(&self, waker: &Arc<Waker>) -> Option<PooledHandles<H>>140     fn get_handles(&self, waker: &Arc<Waker>) -> Option<PooledHandles<H>> {
141         let mut d = self.d.lock().unwrap();
142         match d.buffers.pop_front() {
143             Some(handles) => Some(PooledHandles::new(&self.d, handles)),
144             None => {
145                 d.waker = Some(Arc::clone(waker));
146                 None
147             }
148         }
149     }
150 }
151 
152 /// A set of buffer handles provided by `PooledHandlesProvider`. The handles
153 /// will remain out of the pool as long as this instance is alive, i.e. the
154 /// handles will be recycled when it is dropped.
155 pub struct PooledHandles<H: BufferHandles> {
156     // Use of Option is necessary here because of Drop implementation, but the
157     // Option will always be Some()
158     handles: Option<H>,
159     provider: Weak<Mutex<PooledHandlesProviderInternal<H>>>,
160 }
161 
162 impl<H: BufferHandles> PooledHandles<H> {
new(provider: &Arc<Mutex<PooledHandlesProviderInternal<H>>>, handles: H) -> Self163     fn new(provider: &Arc<Mutex<PooledHandlesProviderInternal<H>>>, handles: H) -> Self {
164         Self {
165             handles: Some(handles),
166             provider: Arc::downgrade(provider),
167         }
168     }
169 
handles(&self) -> &H170     pub fn handles(&self) -> &H {
171         self.handles.as_ref().unwrap()
172     }
173 }
174 
175 impl<H: BufferHandles + Debug> Debug for PooledHandles<H> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result176     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177         self.handles.fmt(f)
178     }
179 }
180 
181 impl<H: BufferHandles> Drop for PooledHandles<H> {
182     /// Return the handles to the pool if it still exists, otherwise the handles
183     /// themselves are destroyed.
drop(&mut self)184     fn drop(&mut self) {
185         match self.provider.upgrade() {
186             None => (),
187             Some(provider) => {
188                 let mut provider = provider.lock().unwrap();
189                 provider.buffers.push_back(self.handles.take().unwrap());
190                 if let Some(waker) = provider.waker.take() {
191                     waker.wake();
192                 }
193             }
194         }
195     }
196 }
197 
198 impl<H: BufferHandles> BufferHandles for PooledHandles<H> {
199     type SupportedMemoryType = H::SupportedMemoryType;
200 
len(&self) -> usize201     fn len(&self) -> usize {
202         self.handles.as_ref().unwrap().len()
203     }
204 
fill_v4l2_plane(&self, index: usize, plane: &mut bindings::v4l2_plane)205     fn fill_v4l2_plane(&self, index: usize, plane: &mut bindings::v4l2_plane) {
206         self.handles.as_ref().unwrap().fill_v4l2_plane(index, plane);
207     }
208 }
209 
210 impl<H: PrimitiveBufferHandles> PrimitiveBufferHandles for PooledHandles<H> {
211     type HandleType = H::HandleType;
212     const MEMORY_TYPE: Self::SupportedMemoryType = H::MEMORY_TYPE;
213 }
214