• 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 std::cell::RefCell;
6 use std::os::fd::AsRawFd;
7 use std::rc::{Rc, Weak};
8 
9 use v4l2r::controls::ExtControlTrait;
10 use v4l2r::controls::SafeExtControl;
11 use v4l2r::ioctl;
12 
13 use crate::backend::v4l2::decoder::stateless::V4l2Picture;
14 use crate::decoder::stateless::StatelessBackendError;
15 use crate::decoder::stateless::StatelessBackendResult;
16 use crate::device::v4l2::stateless::device::V4l2Device;
17 use crate::device::v4l2::stateless::queue::V4l2CaptureBuffer;
18 use crate::device::v4l2::stateless::queue::V4l2OutputBuffer;
19 use crate::video_frame::VideoFrame;
20 
21 struct InitRequestHandle<V: VideoFrame> {
22     device: V4l2Device<V>,
23     timestamp: u64,
24     handle: ioctl::Request,
25     output_buffer: V4l2OutputBuffer,
26     picture: Weak<RefCell<V4l2Picture<V>>>,
27     frame: V,
28 }
29 
30 impl<V: VideoFrame> InitRequestHandle<V> {
new( device: V4l2Device<V>, timestamp: u64, handle: ioctl::Request, output_buffer: V4l2OutputBuffer, frame: V, ) -> Self31     fn new(
32         device: V4l2Device<V>,
33         timestamp: u64,
34         handle: ioctl::Request,
35         output_buffer: V4l2OutputBuffer,
36         frame: V,
37     ) -> Self {
38         Self { device, timestamp, handle, output_buffer, picture: Weak::new(), frame }
39     }
which(&self) -> ioctl::CtrlWhich40     fn which(&self) -> ioctl::CtrlWhich {
41         ioctl::CtrlWhich::Request(self.handle.as_raw_fd())
42     }
ioctl<C, T>(&mut self, ctrl: C) -> StatelessBackendResult<&mut Self> where C: Into<SafeExtControl<T>>, T: ExtControlTrait,43     fn ioctl<C, T>(&mut self, ctrl: C) -> StatelessBackendResult<&mut Self>
44     where
45         C: Into<SafeExtControl<T>>,
46         T: ExtControlTrait,
47     {
48         let mut ctrl: SafeExtControl<T> = ctrl.into();
49         ioctl::s_ext_ctrls(&self.device, self.which(), &mut ctrl)
50             .map_err(|e| StatelessBackendError::Other(anyhow::anyhow!(e)))?;
51         Ok(self)
52     }
write(&mut self, data: &[u8]) -> &mut Self53     fn write(&mut self, data: &[u8]) -> &mut Self {
54         self.output_buffer.write(data);
55         self
56     }
submit(self) -> StatelessBackendResult<PendingRequestHandle<V>>57     fn submit(self) -> StatelessBackendResult<PendingRequestHandle<V>> {
58         self.device
59             .queue_capture_buffer(self.frame)
60             .map_err(|e| StatelessBackendError::Other(anyhow::anyhow!(e)))?;
61         self.output_buffer
62             .submit(self.timestamp, self.handle.as_raw_fd())
63             .map_err(|e| StatelessBackendError::Other(anyhow::anyhow!(e)))?;
64         self.handle.queue().map_err(|e| StatelessBackendError::Other(anyhow::anyhow!(e)))?;
65         Ok(PendingRequestHandle {
66             device: self.device.clone(),
67             timestamp: self.timestamp,
68             picture: self.picture,
69         })
70     }
set_picture_ref(&mut self, picture: Weak<RefCell<V4l2Picture<V>>>)71     fn set_picture_ref(&mut self, picture: Weak<RefCell<V4l2Picture<V>>>) {
72         self.picture = picture;
73     }
74 }
75 
76 struct PendingRequestHandle<V: VideoFrame> {
77     device: V4l2Device<V>,
78     timestamp: u64,
79     picture: Weak<RefCell<V4l2Picture<V>>>,
80 }
81 
82 impl<V: VideoFrame> PendingRequestHandle<V> {
sync(self) -> DoneRequestHandle<V>83     fn sync(self) -> DoneRequestHandle<V> {
84         DoneRequestHandle {
85             capture_buffer: Rc::new(RefCell::new(self.device.sync(self.timestamp))),
86         }
87     }
associate_dequeued_buffer( &mut self, capture_buffer: V4l2CaptureBuffer<V>, ) -> DoneRequestHandle<V>88     fn associate_dequeued_buffer(
89         &mut self,
90         capture_buffer: V4l2CaptureBuffer<V>,
91     ) -> DoneRequestHandle<V> {
92         self.picture.upgrade().unwrap().as_ref().try_borrow_mut().unwrap().drop_references();
93         DoneRequestHandle { capture_buffer: Rc::new(RefCell::new(capture_buffer)) }
94     }
95 }
96 
97 struct DoneRequestHandle<V: VideoFrame> {
98     capture_buffer: Rc<RefCell<V4l2CaptureBuffer<V>>>,
99 }
100 
101 impl<V: VideoFrame> DoneRequestHandle<V> {
result(&self) -> V4l2Result<V>102     fn result(&self) -> V4l2Result<V> {
103         V4l2Result { capture_buffer: self.capture_buffer.clone() }
104     }
105 }
106 
107 #[derive(Default)]
108 enum RequestHandle<V: VideoFrame> {
109     Init(InitRequestHandle<V>),
110     Pending(PendingRequestHandle<V>),
111     Done(DoneRequestHandle<V>),
112     #[default]
113     Unknown,
114 }
115 
116 impl<V: VideoFrame> RequestHandle<V> {
new( device: V4l2Device<V>, timestamp: u64, handle: ioctl::Request, output_buffer: V4l2OutputBuffer, frame: V, ) -> Self117     fn new(
118         device: V4l2Device<V>,
119         timestamp: u64,
120         handle: ioctl::Request,
121         output_buffer: V4l2OutputBuffer,
122         frame: V,
123     ) -> Self {
124         Self::Init(InitRequestHandle::new(device, timestamp, handle, output_buffer, frame))
125     }
timestamp(&self) -> u64126     fn timestamp(&self) -> u64 {
127         match self {
128             Self::Init(handle) => handle.timestamp,
129             Self::Pending(handle) => handle.timestamp,
130             Self::Done(handle) => handle.capture_buffer.borrow().timestamp(),
131             _ => panic!("ERROR"),
132         }
133     }
which(&self) -> ioctl::CtrlWhich134     fn which(&self) -> ioctl::CtrlWhich {
135         match self {
136             Self::Init(handle) => handle.which(),
137             _ => panic!("ERROR"),
138         }
139     }
ioctl<C, T>(&mut self, ctrl: C) -> StatelessBackendResult<&mut Self> where C: Into<SafeExtControl<T>>, T: ExtControlTrait,140     fn ioctl<C, T>(&mut self, ctrl: C) -> StatelessBackendResult<&mut Self>
141     where
142         C: Into<SafeExtControl<T>>,
143         T: ExtControlTrait,
144     {
145         match self {
146             Self::Init(handle) => handle.ioctl(ctrl)?,
147             _ => {
148                 return Err(StatelessBackendError::Other(anyhow::anyhow!(
149                     "incorrect request state"
150                 )))
151             }
152         };
153         Ok(self)
154     }
write(&mut self, data: &[u8]) -> &mut Self155     fn write(&mut self, data: &[u8]) -> &mut Self {
156         match self {
157             Self::Init(handle) => handle.write(data),
158             _ => panic!("ERROR"),
159         };
160         self
161     }
162 
163     // This method can modify in-place instead of returning a new value. This removes the need for
164     // a RefCell in V4l2Request.
submit(&mut self) -> StatelessBackendResult<()>165     fn submit(&mut self) -> StatelessBackendResult<()> {
166         match std::mem::take(self) {
167             Self::Init(handle) => Ok(*self = Self::Pending(handle.submit()?)),
168             _ => Err(StatelessBackendError::Other(anyhow::anyhow!("incorrect request state"))),
169         }
170     }
sync(&mut self)171     fn sync(&mut self) {
172         match std::mem::take(self) {
173             Self::Pending(handle) => *self = Self::Done(handle.sync()),
174             s @ Self::Done(_) => *self = s,
175             _ => panic!("ERROR"),
176         }
177     }
result(&self) -> V4l2Result<V>178     fn result(&self) -> V4l2Result<V> {
179         match self {
180             Self::Done(handle) => handle.result(),
181             _ => panic!("ERROR"),
182         }
183     }
set_picture_ref(&mut self, picture: Weak<RefCell<V4l2Picture<V>>>)184     fn set_picture_ref(&mut self, picture: Weak<RefCell<V4l2Picture<V>>>) {
185         match self {
186             Self::Init(handle) => handle.set_picture_ref(picture),
187             _ => panic!("ERROR"),
188         }
189     }
associate_dequeued_buffer(&mut self, capture_buffer: V4l2CaptureBuffer<V>)190     fn associate_dequeued_buffer(&mut self, capture_buffer: V4l2CaptureBuffer<V>) {
191         match self {
192             Self::Pending(handle) => {
193                 *self = Self::Done(handle.associate_dequeued_buffer(capture_buffer))
194             }
195             _ => panic!("ERROR"),
196         }
197     }
198 }
199 
200 pub struct V4l2Request<V: VideoFrame>(RequestHandle<V>);
201 
202 impl<V: VideoFrame> V4l2Request<V> {
new( device: V4l2Device<V>, timestamp: u64, handle: ioctl::Request, output_buffer: V4l2OutputBuffer, frame: V, ) -> Self203     pub fn new(
204         device: V4l2Device<V>,
205         timestamp: u64,
206         handle: ioctl::Request,
207         output_buffer: V4l2OutputBuffer,
208         frame: V,
209     ) -> Self {
210         Self(RequestHandle::new(device, timestamp, handle, output_buffer, frame))
211     }
timestamp(&self) -> u64212     pub fn timestamp(&self) -> u64 {
213         self.0.timestamp()
214     }
which(&self) -> ioctl::CtrlWhich215     pub fn which(&self) -> ioctl::CtrlWhich {
216         self.0.which()
217     }
ioctl<C, T>(&mut self, ctrl: C) -> StatelessBackendResult<&mut Self> where C: Into<SafeExtControl<T>>, T: ExtControlTrait,218     pub fn ioctl<C, T>(&mut self, ctrl: C) -> StatelessBackendResult<&mut Self>
219     where
220         C: Into<SafeExtControl<T>>,
221         T: ExtControlTrait,
222     {
223         self.0.ioctl(ctrl)?;
224         Ok(self)
225     }
write(&mut self, data: &[u8]) -> &mut Self226     pub fn write(&mut self, data: &[u8]) -> &mut Self {
227         self.0.write(data);
228         self
229     }
submit(&mut self) -> StatelessBackendResult<()>230     pub fn submit(&mut self) -> StatelessBackendResult<()> {
231         self.0.submit()
232     }
sync(&mut self)233     pub fn sync(&mut self) {
234         self.0.sync();
235     }
result(&self) -> V4l2Result<V>236     pub fn result(&self) -> V4l2Result<V> {
237         self.0.result()
238     }
set_picture_ref(&mut self, picture: Weak<RefCell<V4l2Picture<V>>>)239     pub fn set_picture_ref(&mut self, picture: Weak<RefCell<V4l2Picture<V>>>) {
240         self.0.set_picture_ref(picture);
241     }
associate_dequeued_buffer(&mut self, capture_buffer: V4l2CaptureBuffer<V>)242     pub fn associate_dequeued_buffer(&mut self, capture_buffer: V4l2CaptureBuffer<V>) {
243         self.0.associate_dequeued_buffer(capture_buffer)
244     }
245 }
246 
247 pub struct V4l2Result<V: VideoFrame> {
248     pub capture_buffer: Rc<RefCell<V4l2CaptureBuffer<V>>>,
249 }
250