use std::{ collections::VecDeque, fmt::Debug, sync::{Arc, Mutex, Weak}, task::Wake, }; use log::error; use crate::device::queue::{ GetCaptureBufferByIndex, GetFreeBufferError, GetFreeCaptureBuffer, TryGetBufferError, }; use crate::{ bindings, device::poller::Waker, memory::{BufferHandles, MmapHandle, PrimitiveBufferHandles}, Format, }; use thiserror::Error; #[derive(Debug, Error)] pub enum GetSuitableBufferError { #[error("error while calling try_get_free_buffer(): {0}")] TryGetFree(#[from] GetFreeBufferError), #[error("error while calling try_get_buffer(): {0}")] TryGetIndexed(#[from] TryGetBufferError), } pub trait HandlesProvider: Send + 'static { type HandleType: BufferHandles; /// Request a set of handles. Returns `None` if no handle is currently /// available. If that is the case, `waker` will be signaled when handles /// are available again. fn get_handles(&self, waker: &Arc) -> Option; fn get_suitable_buffer_for<'a, Q>( &self, _handles: &Self::HandleType, queue: &'a Q, ) -> Result where Q: GetCaptureBufferByIndex<'a, Self::HandleType> + GetFreeCaptureBuffer<'a, Self::HandleType>, { Ok(queue.try_get_free_buffer()?) } } /// `HandleProvider`s on the heap are `HandleProvider`s too. impl HandlesProvider for Box

{ type HandleType = P::HandleType; fn get_handles(&self, waker: &Arc) -> Option { self.as_ref().get_handles(waker) } fn get_suitable_buffer_for<'a, Q>( &self, handles: &Self::HandleType, queue: &'a Q, ) -> Result where Q: GetCaptureBufferByIndex<'a, Self::HandleType> + GetFreeCaptureBuffer<'a, Self::HandleType>, { self.as_ref().get_suitable_buffer_for(handles, queue) } } impl HandlesProvider for Arc

{ type HandleType = P::HandleType; fn get_handles(&self, waker: &Arc) -> Option { self.as_ref().get_handles(waker) } fn get_suitable_buffer_for<'a, Q>( &self, handles: &Self::HandleType, queue: &'a Q, ) -> Result where Q: GetCaptureBufferByIndex<'a, Self::HandleType> + GetFreeCaptureBuffer<'a, Self::HandleType>, { self.as_ref().get_suitable_buffer_for(handles, queue) } } pub struct MmapProvider(Vec); impl MmapProvider { pub fn new(format: &Format) -> Self { Self(vec![Default::default(); format.plane_fmt.len()]) } } impl HandlesProvider for MmapProvider { type HandleType = Vec; fn get_handles(&self, _waker: &Arc) -> Option { Some(self.0.clone()) } } /// Internals of `PooledHandlesProvider`, which acts just as a protected wrapper /// around this structure. struct PooledHandlesProviderInternal { buffers: VecDeque, waker: Option>, } unsafe impl Send for PooledHandlesProviderInternal {} /// A handles provider that recycles buffers from a fixed set in a pool. /// Provided `PooledHandles` will not be recycled for as long as the instance is /// alive. Once it is dropped, it the underlying buffer returns into the pool to /// be reused later. pub struct PooledHandlesProvider { d: Arc>>, } impl PooledHandlesProvider { /// Create a new `PooledMemoryProvider`, using the set in `buffers`. pub fn new>(buffers: B) -> Self { Self { d: Arc::new(Mutex::new(PooledHandlesProviderInternal { buffers: buffers.into_iter().collect(), waker: None, })), } } } impl HandlesProvider for PooledHandlesProvider { type HandleType = PooledHandles; fn get_handles(&self, waker: &Arc) -> Option> { let mut d = self.d.lock().unwrap(); match d.buffers.pop_front() { Some(handles) => Some(PooledHandles::new(&self.d, handles)), None => { d.waker = Some(Arc::clone(waker)); None } } } } /// A set of buffer handles provided by `PooledHandlesProvider`. The handles /// will remain out of the pool as long as this instance is alive, i.e. the /// handles will be recycled when it is dropped. pub struct PooledHandles { // Use of Option is necessary here because of Drop implementation, but the // Option will always be Some() handles: Option, provider: Weak>>, } impl PooledHandles { fn new(provider: &Arc>>, handles: H) -> Self { Self { handles: Some(handles), provider: Arc::downgrade(provider), } } pub fn handles(&self) -> &H { self.handles.as_ref().unwrap() } } impl Debug for PooledHandles { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.handles.fmt(f) } } impl Drop for PooledHandles { /// Return the handles to the pool if it still exists, otherwise the handles /// themselves are destroyed. fn drop(&mut self) { match self.provider.upgrade() { None => (), Some(provider) => { let mut provider = provider.lock().unwrap(); provider.buffers.push_back(self.handles.take().unwrap()); if let Some(waker) = provider.waker.take() { waker.wake(); } } } } } impl BufferHandles for PooledHandles { type SupportedMemoryType = H::SupportedMemoryType; fn len(&self) -> usize { self.handles.as_ref().unwrap().len() } fn fill_v4l2_plane(&self, index: usize, plane: &mut bindings::v4l2_plane) { self.handles.as_ref().unwrap().fill_v4l2_plane(index, plane); } } impl PrimitiveBufferHandles for PooledHandles { type HandleType = H::HandleType; const MEMORY_TYPE: Self::SupportedMemoryType = H::MEMORY_TYPE; }