• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use anyhow::anyhow;
6 use std::cell::RefCell;
7 use std::convert::Infallible;
8 use std::rc::Rc;
9 use std::sync::Arc;
10 use thiserror::Error;
11 
12 use v4l2r::bindings::v4l2_format;
13 use v4l2r::device::queue::direction;
14 use v4l2r::device::queue::direction::Capture;
15 use v4l2r::device::queue::direction::Output;
16 use v4l2r::device::queue::dqbuf::DqBuffer;
17 use v4l2r::device::queue::qbuf::QBuffer;
18 use v4l2r::device::queue::BuffersAllocated;
19 use v4l2r::device::queue::CaptureQueueable;
20 use v4l2r::device::queue::CreateQueueError;
21 use v4l2r::device::queue::GetFreeBufferError;
22 use v4l2r::device::queue::GetFreeCaptureBuffer;
23 use v4l2r::device::queue::GetFreeOutputBuffer;
24 use v4l2r::device::queue::Queue;
25 use v4l2r::device::queue::QueueInit;
26 use v4l2r::device::queue::RequestBuffersError;
27 use v4l2r::device::AllocatedQueue;
28 use v4l2r::device::Device;
29 use v4l2r::device::Stream;
30 use v4l2r::device::TryDequeue;
31 use v4l2r::ioctl::GFmtError;
32 use v4l2r::ioctl::IoctlConvertError;
33 use v4l2r::ioctl::QBufIoctlError;
34 use v4l2r::ioctl::SFmtError;
35 use v4l2r::ioctl::StreamOnError;
36 use v4l2r::memory::BufferHandles;
37 use v4l2r::memory::Memory;
38 use v4l2r::memory::MemoryType;
39 use v4l2r::memory::MmapHandle;
40 use v4l2r::memory::PlaneHandle;
41 use v4l2r::nix::sys::time::TimeVal;
42 use v4l2r::Format;
43 use v4l2r::PlaneLayout;
44 
45 use crate::decoder::stateless::DecodeError;
46 use crate::decoder::stateless::NewStatelessDecoderError;
47 use crate::decoder::stateless::StatelessBackendError;
48 use crate::utils::buffer_size_for_area;
49 use crate::video_frame::V4l2VideoFrame;
50 use crate::video_frame::VideoFrame;
51 use crate::Fourcc;
52 use crate::Resolution;
53 
54 //TODO: handle memory backends other than mmap
55 //TODO: handle video formats other than h264
56 //TODO: handle synced buffers in Streaming state
57 #[derive(Default)]
58 enum V4l2OutputQueueHandle<T: v4l2r::device::queue::direction::Direction> {
59     Init(Queue<T, QueueInit>),
60     Streaming(Rc<Queue<T, BuffersAllocated<Vec<MmapHandle>>>>),
61     #[default]
62     Unknown,
63 }
64 
65 #[derive(Default)]
66 enum V4l2CaptureQueueHandle<T: v4l2r::device::queue::direction::Direction, V: VideoFrame> {
67     Init(Queue<T, QueueInit>),
68     Streaming(Rc<Queue<T, BuffersAllocated<V4l2VideoFrame<V>>>>),
69     #[default]
70     Unknown,
71 }
72 
73 #[derive(Debug, Error)]
74 pub enum QueueError {
75     #[error("unable to create queue.")]
76     Creation,
77     #[error("failed to get format for queue.")]
78     FormatGet,
79     #[error("failed to set format for queue.")]
80     FormatSet,
81     #[error("failed requesting buffers.")]
82     RequestBuffers,
83     #[error("unable to stream on.")]
84     StreamOn,
85     #[error("driver does not support {0}.")]
86     UnsupportedPixelFormat(Fourcc),
87     #[error("operation can not be performed in this state.")]
88     State,
89     #[error("no buffer to dequeue.")]
90     BufferDequeue,
91     #[error("failed to queue buffer.")]
92     BufferQueue,
93     #[error("requested {0} buffers, only {1} allocated")]
94     NotEnoughRequestedBuffers(usize, usize),
95     #[error("failed to stream off.")]
96     StreamOff,
97     #[error("failed to get queue handle.")]
98     QueueHandle,
99     #[error("failed to free buffers.")]
100     FreeBuffer,
101     #[error("failed to reset OUTPUT queue.")]
102     ResetOutputQueue,
103     #[error("failed to reset CAPTURE queue.")]
104     ResetCaptureQueue,
105 }
106 
107 impl From<QueueError> for DecodeError {
from(err: QueueError) -> Self108     fn from(err: QueueError) -> Self {
109         DecodeError::BackendError(StatelessBackendError::Other(anyhow::anyhow!(err)))
110     }
111 }
112 
113 impl<B: BufferHandles> From<v4l2r::device::queue::qbuf::QueueError<B>> for QueueError {
from(_err: v4l2r::device::queue::qbuf::QueueError<B>) -> Self114     fn from(_err: v4l2r::device::queue::qbuf::QueueError<B>) -> Self {
115         QueueError::BufferQueue
116     }
117 }
118 
119 impl From<CreateQueueError> for QueueError {
from(_err: CreateQueueError) -> Self120     fn from(_err: CreateQueueError) -> Self {
121         QueueError::Creation
122     }
123 }
124 
125 impl From<GFmtError> for QueueError {
from(_err: GFmtError) -> Self126     fn from(_err: GFmtError) -> Self {
127         QueueError::FormatGet
128     }
129 }
130 
131 impl From<SFmtError> for QueueError {
from(_err: SFmtError) -> Self132     fn from(_err: SFmtError) -> Self {
133         QueueError::FormatSet
134     }
135 }
136 
137 impl From<RequestBuffersError> for QueueError {
from(_err: RequestBuffersError) -> Self138     fn from(_err: RequestBuffersError) -> Self {
139         QueueError::RequestBuffers
140     }
141 }
142 
143 impl From<StreamOnError> for QueueError {
from(_err: StreamOnError) -> Self144     fn from(_err: StreamOnError) -> Self {
145         QueueError::StreamOn
146     }
147 }
148 
149 impl From<GetFreeBufferError> for QueueError {
from(_err: GetFreeBufferError) -> Self150     fn from(_err: GetFreeBufferError) -> Self {
151         QueueError::BufferDequeue
152     }
153 }
154 
155 impl From<IoctlConvertError<QBufIoctlError, Infallible>> for QueueError {
from(_err: IoctlConvertError<QBufIoctlError, Infallible>) -> Self156     fn from(_err: IoctlConvertError<QBufIoctlError, Infallible>) -> Self {
157         QueueError::BufferQueue
158     }
159 }
160 
check_requested_buffer_count(requested: u32, received: usize) -> Result<(), QueueError>161 fn check_requested_buffer_count(requested: u32, received: usize) -> Result<(), QueueError> {
162     if received < requested as usize {
163         return Err(QueueError::NotEnoughRequestedBuffers(requested as usize, received));
164     }
165     Ok(())
166 }
167 
168 //TODO: handle memory backends other than mmap
169 pub struct V4l2OutputBuffer {
170     queue: V4l2OutputQueue,
171     handle: QBuffer<
172         Output,
173         Vec<MmapHandle>,
174         Vec<MmapHandle>,
175         Rc<Queue<Output, BuffersAllocated<Vec<MmapHandle>>>>,
176     >,
177     length: usize,
178 }
179 
180 impl V4l2OutputBuffer {
new( queue: V4l2OutputQueue, handle: QBuffer< Output, Vec<MmapHandle>, Vec<MmapHandle>, Rc<Queue<Output, BuffersAllocated<Vec<MmapHandle>>>>, >, ) -> Self181     fn new(
182         queue: V4l2OutputQueue,
183         handle: QBuffer<
184             Output,
185             Vec<MmapHandle>,
186             Vec<MmapHandle>,
187             Rc<Queue<Output, BuffersAllocated<Vec<MmapHandle>>>>,
188         >,
189     ) -> Self {
190         Self { queue, handle, length: 0 }
191     }
index(&self) -> usize192     pub fn index(&self) -> usize {
193         self.handle.index()
194     }
length(&self) -> usize195     pub fn length(&self) -> usize {
196         self.length
197     }
write(&mut self, data: &[u8]) -> &mut Self198     pub fn write(&mut self, data: &[u8]) -> &mut Self {
199         let mut mapping = self.handle.get_plane_mapping(0).expect("Failed to mmap output buffer");
200 
201         mapping.as_mut()[self.length..self.length + data.len()].copy_from_slice(data);
202         self.length += data.len();
203 
204         drop(mapping);
205         self
206     }
submit(self, timestamp: u64, request_fd: i32) -> Result<(), QueueError>207     pub fn submit(self, timestamp: u64, request_fd: i32) -> Result<(), QueueError> {
208         let handle = &*self.queue.handle.borrow();
209         match handle {
210             V4l2OutputQueueHandle::Streaming(_) => {
211                 self.handle
212                     .set_timestamp(TimeVal::new(/* FIXME: sec */ 0, timestamp as i64))
213                     .set_request(request_fd)
214                     .queue(&[self.length])?;
215                 Ok(())
216             }
217             _ => Err(QueueError::State),
218         }
219     }
220 }
221 
222 #[derive(Clone)]
223 pub struct V4l2OutputQueue {
224     handle: Rc<RefCell<V4l2OutputQueueHandle<direction::Output>>>,
225 }
226 
227 const NUM_OUTPUT_BUFFERS: u32 = 2;
228 impl V4l2OutputQueue {
new(device: Arc<Device>) -> Result<Self, NewStatelessDecoderError>229     pub fn new(device: Arc<Device>) -> Result<Self, NewStatelessDecoderError> {
230         let handle = Queue::get_output_mplane_queue(device)
231             .map_err(|_| NewStatelessDecoderError::DriverInitialization)?;
232         log::debug!("output queue created");
233         let handle = Rc::new(RefCell::new(V4l2OutputQueueHandle::Init(handle)));
234         Ok(Self { handle })
235     }
236 
reset(&mut self, device: Arc<Device>) -> Result<(), QueueError>237     pub fn reset(&mut self, device: Arc<Device>) -> Result<(), QueueError> {
238         let handle = self.handle.take();
239         let (ret, handle) = match handle {
240             V4l2OutputQueueHandle::Streaming(handle) => {
241                 handle.stream_off().map_err(|_| QueueError::StreamOff)?;
242                 (Rc::into_inner(handle).ok_or(QueueError::QueueHandle)?)
243                     .free_buffers()
244                     .map_err(|_| QueueError::FreeBuffer)?;
245 
246                 let queue_handle = Queue::get_output_mplane_queue(device.clone())
247                     .map_err(|_| QueueError::QueueHandle);
248 
249                 (Ok(()), V4l2OutputQueueHandle::Init(queue_handle?))
250             }
251             _ => (Err(QueueError::State), handle),
252         };
253         self.handle.replace(handle);
254         ret
255     }
256 
initialize( &mut self, fourcc: Fourcc, resolution: Resolution, ) -> Result<&mut Self, QueueError>257     pub fn initialize(
258         &mut self,
259         fourcc: Fourcc,
260         resolution: Resolution,
261     ) -> Result<&mut Self, QueueError> {
262         self.handle.replace(match self.handle.take() {
263             V4l2OutputQueueHandle::Init(mut handle) => {
264                 let (width, height) = resolution.into();
265                 handle
266                     .change_format()?
267                     .set_size(width as usize, height as usize)
268                     .set_pixelformat(fourcc)
269                     .set_planes_layout(vec![PlaneLayout {
270                         sizeimage: buffer_size_for_area(width, height),
271                         ..Default::default()
272                     }])
273                     .apply::<v4l2_format>()?;
274 
275                 let format: Format = handle.get_format()?;
276                 if format.pixelformat != fourcc.into() {
277                     return Err(QueueError::UnsupportedPixelFormat(fourcc));
278                 }
279 
280                 let handle = handle.request_buffers_generic::<Vec<MmapHandle>>(
281                     MemoryType::Mmap,
282                     NUM_OUTPUT_BUFFERS,
283                 )?;
284 
285                 check_requested_buffer_count(NUM_OUTPUT_BUFFERS, handle.num_free_buffers())?;
286 
287                 handle.stream_on()?;
288 
289                 V4l2OutputQueueHandle::Streaming(handle.into())
290             }
291             _ => return Err(QueueError::State),
292         });
293         Ok(self)
294     }
295 
num_free_buffers(&self) -> usize296     pub fn num_free_buffers(&self) -> usize {
297         let handle = &*self.handle.borrow();
298         match handle {
299             V4l2OutputQueueHandle::Streaming(handle) => handle.num_free_buffers(),
300             _ => 0,
301         }
302     }
alloc_buffer(&self) -> Result<V4l2OutputBuffer, DecodeError>303     pub fn alloc_buffer(&self) -> Result<V4l2OutputBuffer, DecodeError> {
304         let handle = &*self.handle.borrow();
305         match handle {
306             V4l2OutputQueueHandle::Streaming(handle) => match handle.try_get_free_buffer() {
307                 Ok(buffer) => Ok(V4l2OutputBuffer::new(self.clone(), buffer)),
308                 Err(_) => Err(DecodeError::NotEnoughOutputBuffers(1)),
309             },
310             _ => Err(DecodeError::DecoderError(anyhow!("Invalid hardware handle"))),
311         }
312     }
dequeue_buffer(&self) -> Result<(), QueueError>313     pub fn dequeue_buffer(&self) -> Result<(), QueueError> {
314         let handle = &*self.handle.borrow();
315         match handle {
316             V4l2OutputQueueHandle::Streaming(handle) => {
317                 handle.try_dequeue().map_err(|_| QueueError::BufferDequeue)?;
318                 Ok(())
319             }
320             _ => Err(QueueError::State),
321         }
322     }
323 }
324 
325 pub struct V4l2CaptureBuffer<V: VideoFrame> {
326     pub frame: Arc<V>,
327     handle: DqBuffer<Capture, V4l2VideoFrame<V>>,
328 }
329 
330 impl<V: VideoFrame> V4l2CaptureBuffer<V> {
new(frame: Arc<V>, handle: DqBuffer<Capture, V4l2VideoFrame<V>>) -> Self331     fn new(frame: Arc<V>, handle: DqBuffer<Capture, V4l2VideoFrame<V>>) -> Self {
332         Self { frame, handle }
333     }
timestamp(&self) -> u64334     pub fn timestamp(&self) -> u64 {
335         self.handle.data.timestamp().tv_usec as u64
336     }
337     // TODO enable once upstream v4l2r has rolled
338     //    pub fn has_error(&self) -> bool {
339     //        self.handle.data.has_error() as u64
340     //    }
341 }
342 
343 pub struct V4l2CaptureQueue<V: VideoFrame> {
344     format: Format,
345     handle: RefCell<V4l2CaptureQueueHandle<direction::Capture, V>>,
346     num_buffers: u32,
347     device: Arc<Device>,
348 }
349 
350 impl<V: VideoFrame> V4l2CaptureQueue<V> {
new(device: Arc<Device>) -> Result<Self, NewStatelessDecoderError>351     pub fn new(device: Arc<Device>) -> Result<Self, NewStatelessDecoderError> {
352         let handle = Queue::get_capture_mplane_queue(device.clone())
353             .map_err(|_| NewStatelessDecoderError::DriverInitialization)?;
354         log::debug!("capture queue created");
355         let handle = RefCell::new(V4l2CaptureQueueHandle::Init(handle));
356         Ok(Self { handle, num_buffers: 0, format: Default::default(), device: device })
357     }
358 
reset(&mut self, device: Arc<Device>) -> Result<(), QueueError>359     pub fn reset(&mut self, device: Arc<Device>) -> Result<(), QueueError> {
360         let handle = self.handle.take();
361         let (ret, handle) = match handle {
362             V4l2CaptureQueueHandle::Streaming(handle) => {
363                 handle.stream_off().map_err(|_| QueueError::StreamOff)?;
364                 (Rc::into_inner(handle).ok_or(QueueError::QueueHandle)?)
365                     .free_buffers()
366                     .map_err(|_| QueueError::FreeBuffer)?;
367 
368                 let queue_handle = Queue::get_capture_mplane_queue(device.clone())
369                     .map_err(|_| QueueError::QueueHandle);
370 
371                 (Ok(()), V4l2CaptureQueueHandle::Init(queue_handle?))
372             }
373             _ => (Err(QueueError::State), handle),
374         };
375         self.handle.replace(handle);
376         ret
377     }
378 
initialize(&mut self, requested_num_buffers: u32) -> Result<&mut Self, QueueError>379     pub fn initialize(&mut self, requested_num_buffers: u32) -> Result<&mut Self, QueueError> {
380         // +2 due to HCMP1_HHI_A.h264 needing more
381         let requested_num_buffers = requested_num_buffers + 2;
382 
383         self.handle.replace(match self.handle.take() {
384             V4l2CaptureQueueHandle::Init(handle) => {
385                 // TODO: check if decoded format is supported.
386                 self.format = handle.get_format()?;
387                 // TODO: handle 10 bit format negotiation.
388                 let handle = handle.request_buffers_generic::<V4l2VideoFrame<V>>(
389                     <V::NativeHandle as PlaneHandle>::Memory::MEMORY_TYPE,
390                     requested_num_buffers,
391                 )?;
392 
393                 check_requested_buffer_count(requested_num_buffers, handle.num_free_buffers())?;
394 
395                 self.num_buffers = requested_num_buffers;
396 
397                 handle.stream_on()?;
398 
399                 V4l2CaptureQueueHandle::Streaming(handle.into())
400             }
401             _ => return Err(QueueError::State),
402         });
403 
404         Ok(self)
405     }
406 
dequeue_buffer(&self) -> Result<Option<V4l2CaptureBuffer<V>>, QueueError>407     pub fn dequeue_buffer(&self) -> Result<Option<V4l2CaptureBuffer<V>>, QueueError> {
408         let handle = &*self.handle.borrow();
409         match handle {
410             V4l2CaptureQueueHandle::Streaming(handle) => match handle.try_dequeue() {
411                 Ok(mut buffer) => {
412                     log::debug!("capture buffer {} dequeued", buffer.data.index());
413                     // TODO handle buffer dequeuing successfully, but having an error
414                     // buffer.data.has_error();
415                     let mut frame = buffer.take_handles().expect("Missing handle on dequeue!").0;
416                     frame.process_dqbuf(self.device.clone(), &self.format, &buffer.data);
417                     Ok(Some(V4l2CaptureBuffer::new(Arc::new(frame), buffer)))
418                 }
419                 _ => Ok(None),
420             },
421             _ => Err(QueueError::State),
422         }
423     }
424 
425     // TODO: Plumb in VideoFrames from external Gralloc frame pool instead of reallocating every
426     // frame every time.
queue_buffer(&self, frame: V) -> Result<(), QueueError>427     pub fn queue_buffer(&self, frame: V) -> Result<(), QueueError> {
428         let handle = &*self.handle.borrow();
429         match handle {
430             V4l2CaptureQueueHandle::Streaming(handle) => {
431                 let buffer = handle.try_get_free_buffer()?;
432                 log::debug!("capture buffer {} queued", buffer.index());
433                 buffer.queue_with_handles(frame.into())?;
434             }
435             _ => return Err(QueueError::State),
436         }
437         Ok(())
438     }
439 
num_free_buffers(&self) -> usize440     pub fn num_free_buffers(&self) -> usize {
441         let handle = &*self.handle.borrow();
442         match handle {
443             V4l2CaptureQueueHandle::Streaming(handle) => handle.num_free_buffers(),
444             _ => 0,
445         }
446     }
447 }
448