1 pub mod buffer; 2 pub mod direction; 3 pub mod dqbuf; 4 pub mod generic; 5 pub mod handles_provider; 6 pub mod qbuf; 7 8 use self::qbuf::{get_free::GetFreeOutputBuffer, get_indexed::GetOutputBufferByIndex}; 9 10 use super::{AllocatedQueue, Device, FreeBuffersResult, Stream, TryDequeue}; 11 use crate::ioctl::{DqBufResult, QueryBufError, V4l2BufferFromError}; 12 use crate::{bindings, memory::*}; 13 use crate::{ 14 ioctl::{ 15 self, GFmtError, QueryBuffer, ReqbufsError, SFmtError, SelectionTarget, SelectionType, 16 StreamOffError, StreamOnError, TryFmtError, 17 }, 18 PlaneLayout, Rect, 19 }; 20 use crate::{Format, PixelFormat, QueueType}; 21 use buffer::*; 22 use direction::*; 23 use dqbuf::*; 24 use generic::{GenericBufferHandles, GenericQBuffer, GenericSupportedMemoryType}; 25 use log::debug; 26 use qbuf::{ 27 get_free::{GetFreeBufferError, GetFreeCaptureBuffer}, 28 get_indexed::{GetCaptureBufferByIndex, TryGetBufferError}, 29 *, 30 }; 31 32 use std::convert::{Infallible, TryFrom}; 33 use std::os::unix::io::{AsRawFd, RawFd}; 34 use std::sync::{Arc, Weak}; 35 use thiserror::Error; 36 37 /// Base values of a queue, that are always value no matter the state the queue 38 /// is in. This base object remains alive as long as the queue is borrowed from 39 /// the `Device`. 40 pub struct QueueBase { 41 // Reference to the device, so we can perform operations on its `fd` and to let us mark the 42 // queue as free again upon destruction. 43 device: Arc<Device>, 44 type_: QueueType, 45 capabilities: ioctl::BufferCapabilities, 46 } 47 48 impl AsRawFd for QueueBase { as_raw_fd(&self) -> RawFd49 fn as_raw_fd(&self) -> RawFd { 50 self.device.as_raw_fd() 51 } 52 } 53 54 impl Drop for QueueBase { 55 /// Make the queue available again. drop(&mut self)56 fn drop(&mut self) { 57 assert!(self.device.used_queues.lock().unwrap().remove(&self.type_)); 58 } 59 } 60 61 /// Trait for the different states a queue can be in. This allows us to limit 62 /// the available queue methods to the one that make sense at a given point of 63 /// the queue's lifecycle. 64 pub trait QueueState {} 65 66 /// V4L2 queue object. Specialized according to its configuration state so that 67 /// only valid methods can be called from a given point. 68 pub struct Queue<D, S> 69 where 70 D: Direction, 71 S: QueueState, 72 { 73 inner: QueueBase, 74 _d: std::marker::PhantomData<D>, 75 state: S, 76 } 77 78 /// Methods of `Queue` that are available no matter the state. 79 impl<D, S> Queue<D, S> 80 where 81 D: Direction, 82 S: QueueState, 83 { get_capabilities(&self) -> ioctl::BufferCapabilities84 pub fn get_capabilities(&self) -> ioctl::BufferCapabilities { 85 self.inner.capabilities 86 } 87 get_type(&self) -> QueueType88 pub fn get_type(&self) -> QueueType { 89 self.inner.type_ 90 } 91 get_format<T: TryFrom<bindings::v4l2_format>>(&self) -> Result<T, GFmtError>92 pub fn get_format<T: TryFrom<bindings::v4l2_format>>(&self) -> Result<T, GFmtError> { 93 ioctl::g_fmt(&self.inner, self.inner.type_) 94 } 95 96 /// This method can invalidate any current format iterator, hence it requires 97 /// the queue to be mutable. This way of doing is not perfect though, as setting 98 /// the format on one queue can change the options available on another. set_format(&mut self, format: Format) -> Result<Format, SFmtError>99 pub fn set_format(&mut self, format: Format) -> Result<Format, SFmtError> { 100 let type_ = self.inner.type_; 101 ioctl::s_fmt(&mut self.inner, (type_, &format)) 102 } 103 104 /// Performs exactly as `set_format`, but does not actually apply `format`. 105 /// Useful to check what modifications need to be done to a format before it 106 /// can be used. try_format(&self, format: Format) -> Result<Format, TryFmtError>107 pub fn try_format(&self, format: Format) -> Result<Format, TryFmtError> { 108 ioctl::try_fmt(&self.inner, (self.inner.type_, &format)) 109 } 110 111 /// Returns a `FormatBuilder` which is set to the currently active format 112 /// and can be modified and eventually applied. The `FormatBuilder` holds 113 /// a mutable reference to this `Queue`. change_format(&mut self) -> Result<FormatBuilder, GFmtError>114 pub fn change_format(&mut self) -> Result<FormatBuilder, GFmtError> { 115 FormatBuilder::new(&mut self.inner) 116 } 117 118 /// Returns an iterator over all the formats currently supported by this queue. format_iter(&self) -> ioctl::FormatIterator<QueueBase>119 pub fn format_iter(&self) -> ioctl::FormatIterator<QueueBase> { 120 ioctl::FormatIterator::new(&self.inner, self.inner.type_) 121 } 122 get_selection(&self, target: SelectionTarget) -> Result<Rect, ioctl::GSelectionError>123 pub fn get_selection(&self, target: SelectionTarget) -> Result<Rect, ioctl::GSelectionError> { 124 let selection = match self.get_type() { 125 QueueType::VideoCapture | QueueType::VideoCaptureMplane => SelectionType::Capture, 126 QueueType::VideoOutput | QueueType::VideoOutputMplane => SelectionType::Output, 127 _ => return Err(ioctl::GSelectionError::Invalid), 128 }; 129 130 ioctl::g_selection(&self.inner, selection, target) 131 } 132 } 133 134 /// Builder for a V4L2 format. This takes a mutable reference on the queue, so 135 /// it is supposed to be short-lived: get one, adjust the format, and apply. 136 pub struct FormatBuilder<'a> { 137 queue: &'a mut QueueBase, 138 format: Format, 139 } 140 141 impl<'a> FormatBuilder<'a> { new(queue: &'a mut QueueBase) -> Result<Self, GFmtError>142 fn new(queue: &'a mut QueueBase) -> Result<Self, GFmtError> { 143 let format = ioctl::g_fmt(queue, queue.type_)?; 144 Ok(Self { queue, format }) 145 } 146 147 /// Get a reference to the format built so far. Useful for checking the 148 /// currently set format after getting a builder, or the actual settings 149 /// that will be applied by the kernel after a `try_apply()`. format(&self) -> &Format150 pub fn format(&self) -> &Format { 151 &self.format 152 } 153 set_size(mut self, width: usize, height: usize) -> Self154 pub fn set_size(mut self, width: usize, height: usize) -> Self { 155 self.format.width = width as u32; 156 self.format.height = height as u32; 157 self 158 } 159 set_pixelformat(mut self, pixel_format: impl Into<PixelFormat>) -> Self160 pub fn set_pixelformat(mut self, pixel_format: impl Into<PixelFormat>) -> Self { 161 self.format.pixelformat = pixel_format.into(); 162 self 163 } 164 set_planes_layout<P: IntoIterator<Item = PlaneLayout>>(mut self, planes: P) -> Self165 pub fn set_planes_layout<P: IntoIterator<Item = PlaneLayout>>(mut self, planes: P) -> Self { 166 self.format.plane_fmt = planes.into_iter().collect(); 167 self 168 } 169 170 /// Apply the format built so far. The kernel will adjust the format to fit 171 /// the driver's capabilities if needed, and the format actually applied will 172 /// be returned. apply<O: TryFrom<bindings::v4l2_format>>(self) -> Result<O, SFmtError>173 pub fn apply<O: TryFrom<bindings::v4l2_format>>(self) -> Result<O, SFmtError> { 174 ioctl::s_fmt(self.queue, (self.queue.type_, &self.format)) 175 } 176 177 /// Try to apply the format built so far. The kernel will adjust the format 178 /// to fit the driver's capabilities if needed, so make sure to check important 179 /// parameters upon return. 180 /// 181 /// Calling `apply()` right after this method is guaranteed to successfully 182 /// apply the format without further change. try_apply(&mut self) -> Result<(), TryFmtError>183 pub fn try_apply(&mut self) -> Result<(), TryFmtError> { 184 let new_format = ioctl::try_fmt(self.queue, (self.queue.type_, &self.format))?; 185 186 self.format = new_format; 187 Ok(()) 188 } 189 } 190 191 /// Initial state of the queue when created. Streaming and queuing are not 192 /// supported since buffers have not been allocated yet. 193 /// Allocating buffers makes the queue switch to the `BuffersAllocated` state. 194 pub struct QueueInit; 195 impl QueueState for QueueInit {} 196 197 #[derive(Debug, Error)] 198 pub enum CreateQueueError { 199 #[error("queue is already in use")] 200 AlreadyBorrowed, 201 #[error("error while querying queue capabilities")] 202 ReqbufsError(#[from] ioctl::ReqbufsError), 203 } 204 205 #[derive(Debug, Error)] 206 pub enum RequestBuffersError { 207 #[error("error while requesting buffers")] 208 ReqbufsError(#[from] ioctl::ReqbufsError), 209 #[error("error while querying buffer")] 210 QueryBufferError(#[from] QueryBufError<Infallible>), 211 } 212 213 impl<D: Direction> Queue<D, QueueInit> { 214 /// Create a queue for type `queue_type` on `device`. A queue of a specific type 215 /// can be requested only once. 216 /// 217 /// Not all devices support all kinds of queue. To test whether the queue is supported, 218 /// a REQBUFS(0) is issued on the device. If it is not successful, the device is 219 /// deemed to not support this kind of queue and this method will fail. create( device: Arc<Device>, queue_type: QueueType, ) -> Result<Queue<D, QueueInit>, CreateQueueError>220 fn create( 221 device: Arc<Device>, 222 queue_type: QueueType, 223 ) -> Result<Queue<D, QueueInit>, CreateQueueError> { 224 let mut used_queues = device.used_queues.lock().unwrap(); 225 226 if used_queues.contains(&queue_type) { 227 return Err(CreateQueueError::AlreadyBorrowed); 228 } 229 230 // Check that the queue is valid for this device by doing a dummy REQBUFS. 231 // Obtain its capacities while we are at it. 232 let capabilities: ioctl::BufferCapabilities = 233 ioctl::reqbufs(&*device, queue_type, MemoryType::Mmap, 0) 234 // In the unlikely case that MMAP buffers are not supported, try DMABUF. 235 .or_else(|e| match e { 236 ReqbufsError::InvalidBufferType(_, _) => { 237 ioctl::reqbufs(&*device, queue_type, MemoryType::DmaBuf, 0) 238 } 239 _ => Err(e), 240 })?; 241 242 used_queues.insert(queue_type); 243 244 drop(used_queues); 245 246 Ok(Queue::<D, QueueInit> { 247 inner: QueueBase { 248 device, 249 type_: queue_type, 250 capabilities, 251 }, 252 _d: std::marker::PhantomData, 253 state: QueueInit {}, 254 }) 255 } 256 request_buffers_generic<P: BufferHandles>( self, memory_type: P::SupportedMemoryType, count: u32, ) -> Result<Queue<D, BuffersAllocated<P>>, RequestBuffersError>257 pub fn request_buffers_generic<P: BufferHandles>( 258 self, 259 memory_type: P::SupportedMemoryType, 260 count: u32, 261 ) -> Result<Queue<D, BuffersAllocated<P>>, RequestBuffersError> { 262 let type_ = self.inner.type_; 263 let num_buffers: usize = ioctl::reqbufs(&self.inner, type_, memory_type.into(), count)?; 264 265 debug!( 266 "Requested {} buffers on {} queue, obtained {}", 267 count, type_, num_buffers 268 ); 269 270 // The buffers have been allocated, now let's get their features. 271 // We cannot use functional programming here because we need to return 272 // the error from ioctl::querybuf(), if any. 273 let mut buffer_features = Vec::new(); 274 for i in 0..num_buffers { 275 buffer_features.push(ioctl::querybuf(&self.inner, self.inner.type_, i)?); 276 } 277 278 let buffer_stats = Arc::new(BufferStats::new()); 279 280 let buffer_info = buffer_features 281 .into_iter() 282 .map(|features: QueryBuffer| { 283 Arc::new(BufferInfo::new(features, Arc::clone(&buffer_stats))) 284 }) 285 .collect(); 286 287 Ok(Queue { 288 inner: self.inner, 289 _d: std::marker::PhantomData, 290 state: BuffersAllocated { 291 memory_type, 292 buffer_info, 293 buffer_stats, 294 }, 295 }) 296 } 297 298 /// Allocate `count` buffers for this queue and make it transition to the 299 /// `BuffersAllocated` state. request_buffers<P: PrimitiveBufferHandles>( self, count: u32, ) -> Result<Queue<D, BuffersAllocated<P>>, RequestBuffersError>300 pub fn request_buffers<P: PrimitiveBufferHandles>( 301 self, 302 count: u32, 303 ) -> Result<Queue<D, BuffersAllocated<P>>, RequestBuffersError> { 304 self.request_buffers_generic(P::MEMORY_TYPE, count) 305 } 306 } 307 308 impl Queue<Output, QueueInit> { 309 /// Acquires the OUTPUT queue from `device`. 310 /// 311 /// This method will fail if the queue has already been obtained and has not 312 /// yet been released. get_output_queue(device: Arc<Device>) -> Result<Self, CreateQueueError>313 pub fn get_output_queue(device: Arc<Device>) -> Result<Self, CreateQueueError> { 314 Queue::<Output, QueueInit>::create(device, QueueType::VideoOutput) 315 } 316 317 /// Acquires the OUTPUT_MPLANE queue from `device`. 318 /// 319 /// This method will fail if the queue has already been obtained and has not 320 /// yet been released. get_output_mplane_queue(device: Arc<Device>) -> Result<Self, CreateQueueError>321 pub fn get_output_mplane_queue(device: Arc<Device>) -> Result<Self, CreateQueueError> { 322 Queue::<Output, QueueInit>::create(device, QueueType::VideoOutputMplane) 323 } 324 } 325 326 impl Queue<Capture, QueueInit> { 327 /// Acquires the CAPTURE queue from `device`. 328 /// 329 /// This method will fail if the queue has already been obtained and has not 330 /// yet been released. get_capture_queue(device: Arc<Device>) -> Result<Self, CreateQueueError>331 pub fn get_capture_queue(device: Arc<Device>) -> Result<Self, CreateQueueError> { 332 Queue::<Capture, QueueInit>::create(device, QueueType::VideoCapture) 333 } 334 335 /// Acquires the CAPTURE_MPLANE queue from `device`. 336 /// 337 /// This method will fail if the queue has already been obtained and has not 338 /// yet been released. get_capture_mplane_queue(device: Arc<Device>) -> Result<Self, CreateQueueError>339 pub fn get_capture_mplane_queue(device: Arc<Device>) -> Result<Self, CreateQueueError> { 340 Queue::<Capture, QueueInit>::create(device, QueueType::VideoCaptureMplane) 341 } 342 } 343 344 /// Allocated state for a queue. A queue with its buffers allocated can be 345 /// streamed on and off, and buffers can be queued and dequeued. 346 pub struct BuffersAllocated<P: BufferHandles> { 347 memory_type: P::SupportedMemoryType, 348 /// Keep one `Arc` per buffer. This allows us to invalidate this buffer only in case it gets 349 /// deallocated alone (V4L2 currently does not allow this, but might in the future). 350 buffer_info: Vec<Arc<BufferInfo<P>>>, 351 buffer_stats: Arc<BufferStats>, 352 } 353 impl<P: BufferHandles> QueueState for BuffersAllocated<P> {} 354 355 impl<D: Direction, P: BufferHandles> Queue<D, BuffersAllocated<P>> { 356 /// Return all the currently queued buffers as CanceledBuffers. This can 357 /// be called after a explicit or implicit streamoff to inform the client 358 /// of which buffers have been canceled and return their handles. cancel_queued_buffers(&self) -> Vec<CanceledBuffer<P>>359 fn cancel_queued_buffers(&self) -> Vec<CanceledBuffer<P>> { 360 let canceled_buffers: Vec<_> = self 361 .state 362 .buffer_info 363 .iter() 364 .filter_map(|buffer_info| { 365 // Take the handles of queued entries and make them free again. 366 // Skip entries in any other state. 367 let plane_handles = buffer_info.update_state(|state| { 368 match *state { 369 // Set queued entry to `Free` state and steal its handles. 370 BufferState::Queued(_) => { 371 // We just matched the state but need to do it again in order to take 372 // the handles since `state` is a reference... 373 match std::mem::replace(state, BufferState::Free) { 374 BufferState::Queued(handles) => Some(handles), 375 _ => unreachable!(), 376 } 377 } 378 // Filter out entries not in queued state. 379 _ => None, 380 } 381 })?; 382 383 Some(CanceledBuffer { 384 index: buffer_info.features.index as u32, 385 plane_handles, 386 }) 387 }) 388 .collect(); 389 390 debug!( 391 "{} buffers canceled on {} queue", 392 canceled_buffers.len(), 393 self.get_type() 394 ); 395 396 assert_eq!(self.state.buffer_stats.num_queued(), 0); 397 398 canceled_buffers 399 } 400 401 /// Try to obtain a buffer to pass to userspace so it can be queued. `index` must be the index 402 /// of a buffer in the `Free` state, otherwise an `AlreadyUsed` error is returned. try_obtain_buffer(&self, index: usize) -> Result<&Arc<BufferInfo<P>>, TryGetBufferError>403 fn try_obtain_buffer(&self, index: usize) -> Result<&Arc<BufferInfo<P>>, TryGetBufferError> { 404 let buffer_info = self 405 .state 406 .buffer_info 407 .get(index) 408 .ok_or(TryGetBufferError::InvalidIndex(index))?; 409 410 buffer_info.update_state(|state| match *state { 411 BufferState::Free => { 412 *state = BufferState::PreQueue; 413 Ok(()) 414 } 415 _ => Err(TryGetBufferError::AlreadyUsed), 416 })?; 417 418 Ok(buffer_info) 419 } 420 } 421 422 impl<'a, D: Direction, P: BufferHandles + 'a> AllocatedQueue<'a, D> 423 for Queue<D, BuffersAllocated<P>> 424 { num_buffers(&self) -> usize425 fn num_buffers(&self) -> usize { 426 self.state.buffer_info.len() 427 } 428 num_queued_buffers(&self) -> usize429 fn num_queued_buffers(&self) -> usize { 430 self.state.buffer_stats.num_queued() 431 } 432 num_free_buffers(&self) -> usize433 fn num_free_buffers(&self) -> usize { 434 self.state.buffer_stats.num_free() 435 } 436 free_buffers(self) -> Result<FreeBuffersResult<D, Self>, ioctl::ReqbufsError>437 fn free_buffers(self) -> Result<FreeBuffersResult<D, Self>, ioctl::ReqbufsError> { 438 let type_ = self.inner.type_; 439 ioctl::reqbufs::<()>(&self.inner, type_, self.state.memory_type.into(), 0)?; 440 441 debug!("Freed all buffers on {} queue", type_); 442 443 // reqbufs also performs an implicit streamoff, so return the cancelled 444 // buffers. 445 let canceled_buffers = self.cancel_queued_buffers(); 446 447 Ok(FreeBuffersResult { 448 queue: Queue { 449 inner: self.inner, 450 _d: std::marker::PhantomData, 451 state: QueueInit {}, 452 }, 453 canceled_buffers, 454 }) 455 } 456 } 457 458 /// Represents a queued buffer which has not been processed due to `streamoff` 459 /// being called on a queue. 460 pub struct CanceledBuffer<P: BufferHandles> { 461 /// Index of the buffer, 462 pub index: u32, 463 /// Plane handles that were passed when the buffer has been queued. 464 pub plane_handles: P, 465 } 466 467 impl<D: Direction, P: BufferHandles> Stream for Queue<D, BuffersAllocated<P>> { 468 type Canceled = CanceledBuffer<P>; 469 stream_on(&self) -> Result<(), StreamOnError>470 fn stream_on(&self) -> Result<(), StreamOnError> { 471 debug!("{} queue streaming on", self.get_type()); 472 let type_ = self.inner.type_; 473 ioctl::streamon(&self.inner, type_) 474 } 475 stream_off(&self) -> Result<Vec<Self::Canceled>, StreamOffError>476 fn stream_off(&self) -> Result<Vec<Self::Canceled>, StreamOffError> { 477 debug!("{} queue streaming off", self.get_type()); 478 let type_ = self.inner.type_; 479 ioctl::streamoff(&self.inner, type_)?; 480 481 Ok(self.cancel_queued_buffers()) 482 } 483 } 484 485 impl<D: Direction, P: BufferHandles> TryDequeue for Queue<D, BuffersAllocated<P>> { 486 type Dequeued = DqBuffer<D, P>; 487 try_dequeue(&self) -> DqBufResult<Self::Dequeued, V4l2BufferFromError>488 fn try_dequeue(&self) -> DqBufResult<Self::Dequeued, V4l2BufferFromError> { 489 let dqbuf: ioctl::V4l2Buffer = ioctl::dqbuf(&self.inner, self.inner.type_)?; 490 491 let id = dqbuf.index() as usize; 492 493 let buffer_info = self 494 .state 495 .buffer_info 496 .get(id) 497 .expect("Inconsistent buffer state!"); 498 499 let plane_handles = buffer_info.update_state(|state| match *state { 500 BufferState::Queued(_) => { 501 // We just matched the state but need to do it again in order to take the handles 502 // since `state` is a reference... 503 match std::mem::replace(state, BufferState::Dequeued) { 504 BufferState::Queued(handles) => handles, 505 _ => unreachable!(), 506 } 507 } 508 _ => unreachable!("Inconsistent buffer state!"), 509 }); 510 511 let fuse = BufferStateFuse::new(Arc::downgrade(buffer_info)); 512 513 let dqbuffer = DqBuffer::new(self, buffer_info, plane_handles, dqbuf, fuse); 514 515 Ok(dqbuffer) 516 } 517 } 518 519 mod private { 520 use super::*; 521 522 /// Private trait for providing a Queuable regardless of the queue's 523 /// direction. Avoids duplicating the same code in 524 /// Capture/OutputQueueableProvider's implementations. 525 pub trait GetBufferByIndex<'a> { 526 type Queueable: 'a; 527 try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError>528 fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError>; 529 } 530 531 /// Same as `GetBufferByIndex` but for providing any free buffer. 532 pub trait GetFreeBuffer<'a, ErrorType = GetFreeBufferError>: GetBufferByIndex<'a> { try_get_free_buffer(&'a self) -> Result<Self::Queueable, ErrorType>533 fn try_get_free_buffer(&'a self) -> Result<Self::Queueable, ErrorType>; 534 } 535 536 impl<'a, D: Direction, P: PrimitiveBufferHandles> GetBufferByIndex<'a> 537 for Queue<D, BuffersAllocated<P>> 538 { 539 type Queueable = QBuffer<'a, D, P, P>; 540 541 // Take buffer `id` in order to prepare it for queueing, provided it is available. try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError>542 fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> { 543 Ok(QBuffer::new(self, self.try_obtain_buffer(index)?)) 544 } 545 } 546 547 impl<'a, D: Direction> GetBufferByIndex<'a> for Queue<D, BuffersAllocated<GenericBufferHandles>> { 548 type Queueable = GenericQBuffer<'a, D>; 549 try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError>550 fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> { 551 let buffer_info = self.try_obtain_buffer(index)?; 552 553 Ok(match self.state.memory_type { 554 GenericSupportedMemoryType::Mmap => { 555 GenericQBuffer::Mmap(QBuffer::new(self, buffer_info)) 556 } 557 GenericSupportedMemoryType::UserPtr => { 558 GenericQBuffer::User(QBuffer::new(self, buffer_info)) 559 } 560 GenericSupportedMemoryType::DmaBuf => { 561 GenericQBuffer::DmaBuf(QBuffer::new(self, buffer_info)) 562 } 563 }) 564 } 565 } 566 567 impl<'a, D, P> GetFreeBuffer<'a> for Queue<D, BuffersAllocated<P>> 568 where 569 D: Direction, 570 P: BufferHandles, 571 Self: GetBufferByIndex<'a>, 572 { try_get_free_buffer(&'a self) -> Result<Self::Queueable, GetFreeBufferError>573 fn try_get_free_buffer(&'a self) -> Result<Self::Queueable, GetFreeBufferError> { 574 let res = self 575 .state 576 .buffer_info 577 .iter() 578 .enumerate() 579 .find(|(_, s)| s.do_with_state(|s| matches!(s, BufferState::Free))); 580 581 match res { 582 None => Err(GetFreeBufferError::NoFreeBuffer), 583 Some((i, _)) => Ok(self.try_get_buffer(i).unwrap()), 584 } 585 } 586 } 587 } 588 589 impl<'a, P: PrimitiveBufferHandles> CaptureQueueableProvider<'a, P> 590 for Queue<Capture, BuffersAllocated<P>> 591 where 592 Self: private::GetBufferByIndex<'a>, 593 <Self as private::GetBufferByIndex<'a>>::Queueable: CaptureQueueable<P>, 594 { 595 type Queueable = <Self as private::GetBufferByIndex<'a>>::Queueable; 596 } 597 598 impl<'a, P: PrimitiveBufferHandles> OutputQueueableProvider<'a, P> 599 for Queue<Output, BuffersAllocated<P>> 600 where 601 Self: private::GetBufferByIndex<'a>, 602 <Self as private::GetBufferByIndex<'a>>::Queueable: OutputQueueable<P>, 603 { 604 type Queueable = <Self as private::GetBufferByIndex<'a>>::Queueable; 605 } 606 607 impl<'a, P: BufferHandles, R> GetOutputBufferByIndex<'a, P> for Queue<Output, BuffersAllocated<P>> 608 where 609 Self: private::GetBufferByIndex<'a, Queueable = R>, 610 Self: OutputQueueableProvider<'a, P, Queueable = R>, 611 { 612 // Take buffer `id` in order to prepare it for queueing, provided it is available. try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError>613 fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> { 614 <Self as private::GetBufferByIndex<'a>>::try_get_buffer(self, index) 615 } 616 } 617 618 impl<'a, P: BufferHandles, R> GetCaptureBufferByIndex<'a, P> for Queue<Capture, BuffersAllocated<P>> 619 where 620 Self: private::GetBufferByIndex<'a, Queueable = R>, 621 Self: CaptureQueueableProvider<'a, P, Queueable = R>, 622 { 623 // Take buffer `id` in order to prepare it for queueing, provided it is available. try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError>624 fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> { 625 <Self as private::GetBufferByIndex<'a>>::try_get_buffer(self, index) 626 } 627 } 628 629 impl<'a, P: BufferHandles, R> GetFreeOutputBuffer<'a, P> for Queue<Output, BuffersAllocated<P>> 630 where 631 Self: private::GetFreeBuffer<'a, Queueable = R>, 632 Self: OutputQueueableProvider<'a, P, Queueable = R>, 633 { try_get_free_buffer(&'a self) -> Result<Self::Queueable, GetFreeBufferError>634 fn try_get_free_buffer(&'a self) -> Result<Self::Queueable, GetFreeBufferError> { 635 <Self as private::GetFreeBuffer<'a>>::try_get_free_buffer(self) 636 } 637 } 638 639 impl<'a, P: BufferHandles, R> GetFreeCaptureBuffer<'a, P> for Queue<Capture, BuffersAllocated<P>> 640 where 641 Self: private::GetFreeBuffer<'a, Queueable = R>, 642 Self: CaptureQueueableProvider<'a, P, Queueable = R>, 643 { try_get_free_buffer(&'a self) -> Result<Self::Queueable, GetFreeBufferError>644 fn try_get_free_buffer(&'a self) -> Result<Self::Queueable, GetFreeBufferError> { 645 <Self as private::GetFreeBuffer<'a>>::try_get_free_buffer(self) 646 } 647 } 648 649 /// A fuse that will return the buffer to the Free state when destroyed, unless 650 /// it has been disarmed. 651 struct BufferStateFuse<P: BufferHandles> { 652 buffer_info: Weak<BufferInfo<P>>, 653 } 654 655 impl<P: BufferHandles> BufferStateFuse<P> { 656 /// Create a new fuse that will set `state` to `BufferState::Free` if 657 /// destroyed before `disarm()` has been called. new(buffer_info: Weak<BufferInfo<P>>) -> Self658 fn new(buffer_info: Weak<BufferInfo<P>>) -> Self { 659 BufferStateFuse { buffer_info } 660 } 661 662 /// Disarm this fuse, e.g. the monitored state will be left untouched when 663 /// the fuse is destroyed. disarm(&mut self)664 fn disarm(&mut self) { 665 // Drop our weak reference. 666 self.buffer_info = Weak::new(); 667 } 668 669 /// Trigger the fuse, i.e. make the buffer return to the Free state, unless the fuse has been 670 /// `disarm`ed or the buffer freed. This method should only be called when the reference to the 671 /// buffer is being dropped, otherwise inconsistent state may ensue. The fuse will be disarmed 672 /// after this call. trigger(&mut self)673 fn trigger(&mut self) { 674 match self.buffer_info.upgrade() { 675 None => (), 676 Some(buffer_info) => { 677 buffer_info.update_state(|state| *state = BufferState::Free); 678 self.disarm(); 679 } 680 }; 681 } 682 } 683 684 impl<P: BufferHandles> Drop for BufferStateFuse<P> { drop(&mut self)685 fn drop(&mut self) { 686 self.trigger(); 687 } 688 } 689