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