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::collections::HashMap; 7 use std::os::fd::{AsRawFd, RawFd}; 8 use std::rc::{Rc, Weak}; 9 use std::sync::Arc; 10 use std::thread::sleep; 11 use std::time::Duration; 12 13 use v4l2r::device::Device as VideoDevice; 14 use v4l2r::device::DeviceConfig; 15 use v4l2r::ioctl; 16 use v4l2r::nix::fcntl::open; 17 use v4l2r::nix::fcntl::OFlag; 18 use v4l2r::nix::sys::stat::Mode; 19 20 use crate::decoder::stateless::DecodeError; 21 use crate::decoder::stateless::NewStatelessDecoderError; 22 use crate::device::v4l2::stateless::queue::QueueError; 23 use crate::device::v4l2::stateless::queue::V4l2CaptureBuffer; 24 use crate::device::v4l2::stateless::queue::V4l2CaptureQueue; 25 use crate::device::v4l2::stateless::queue::V4l2OutputQueue; 26 use crate::device::v4l2::stateless::request::V4l2Request; 27 use crate::device::v4l2::utils::enumerate_devices; 28 use crate::video_frame::VideoFrame; 29 use crate::Fourcc; 30 use crate::Resolution; 31 32 //TODO: handle other memory backends for OUTPUT queue 33 //TODO: handle video formats other than h264 34 //TODO: handle queue start/stop at runtime 35 //TODO: handle DRC at runtime 36 struct DeviceHandle<V: VideoFrame> { 37 video_device: Arc<VideoDevice>, 38 media_device: RawFd, 39 output_queue: V4l2OutputQueue, 40 capture_queue: V4l2CaptureQueue<V>, 41 requests: HashMap<u64, Weak<RefCell<V4l2Request<V>>>>, 42 } 43 44 impl<V: VideoFrame> DeviceHandle<V> { new() -> Result<Self, NewStatelessDecoderError>45 fn new() -> Result<Self, NewStatelessDecoderError> { 46 let devices = enumerate_devices(); 47 let (video_device_path, media_device_path) = match devices { 48 Some(paths) => paths, 49 None => return Err(NewStatelessDecoderError::DriverInitialization), 50 }; 51 52 let video_device_config = DeviceConfig::new().non_blocking_dqbuf(); 53 let video_device = Arc::new( 54 VideoDevice::open(&video_device_path, video_device_config) 55 .map_err(|_| NewStatelessDecoderError::DriverInitialization)?, 56 ); 57 58 let media_device = 59 open(&media_device_path, OFlag::O_RDWR | OFlag::O_CLOEXEC, Mode::empty()) 60 .map_err(|_| NewStatelessDecoderError::DriverInitialization)?; 61 let output_queue = V4l2OutputQueue::new(video_device.clone())?; 62 let capture_queue = V4l2CaptureQueue::new(video_device.clone())?; 63 Ok(Self { 64 video_device, 65 media_device, 66 output_queue, 67 capture_queue, 68 requests: HashMap::<u64, Weak<RefCell<V4l2Request<V>>>>::new(), 69 }) 70 } 71 reset_queues(&mut self) -> Result<(), QueueError>72 pub fn reset_queues(&mut self) -> Result<(), QueueError> { 73 self.output_queue 74 .reset(self.video_device.clone()) 75 .map_err(|_| QueueError::ResetOutputQueue)?; 76 self.capture_queue 77 .reset(self.video_device.clone()) 78 .map_err(|_| QueueError::ResetCaptureQueue) 79 } 80 alloc_request(&self) -> ioctl::Request81 fn alloc_request(&self) -> ioctl::Request { 82 ioctl::Request::alloc(&self.media_device).expect("Failed to alloc request handle") 83 } dequeue_output_buffer(&self)84 fn dequeue_output_buffer(&self) { 85 let mut back_off_duration = Duration::from_millis(1); 86 loop { 87 match self.output_queue.dequeue_buffer() { 88 Ok(_) => { 89 break; 90 } 91 Err(QueueError::BufferDequeue) => { 92 sleep(back_off_duration); 93 back_off_duration = back_off_duration + back_off_duration; 94 continue; 95 } 96 Err(_) => panic!("handle this better"), 97 } 98 } 99 } insert_request_into_hash(&mut self, request: Weak<RefCell<V4l2Request<V>>>)100 fn insert_request_into_hash(&mut self, request: Weak<RefCell<V4l2Request<V>>>) { 101 let timestamp = request.upgrade().unwrap().as_ref().borrow().timestamp(); 102 self.requests.insert(timestamp, request); 103 } try_dequeue_capture_buffers(&mut self)104 fn try_dequeue_capture_buffers(&mut self) { 105 loop { 106 match self.capture_queue.dequeue_buffer() { 107 Ok(Some(buffer)) => { 108 let timestamp = buffer.timestamp(); 109 let request = self.requests.remove(×tamp).unwrap(); 110 match request.upgrade().unwrap().as_ref().try_borrow_mut() { 111 Ok(mut request) => { 112 request.associate_dequeued_buffer(buffer); 113 } 114 _ => (), 115 } 116 continue; 117 } 118 _ => break, 119 } 120 } 121 } sync(&mut self, timestamp: u64) -> V4l2CaptureBuffer<V>122 fn sync(&mut self, timestamp: u64) -> V4l2CaptureBuffer<V> { 123 let mut back_off_duration = Duration::from_millis(1); 124 let time_out = Duration::from_millis(120); 125 loop { 126 match self.capture_queue.dequeue_buffer() { 127 Ok(Some(buffer)) => { 128 let dequeued_timestamp = buffer.timestamp(); 129 let request = self.requests.remove(&dequeued_timestamp).unwrap(); 130 if dequeued_timestamp == timestamp { 131 return buffer; 132 } else { 133 match request.upgrade().unwrap().as_ref().try_borrow_mut() { 134 Ok(mut request) => { 135 request.associate_dequeued_buffer(buffer); 136 } 137 _ => (), 138 } 139 } 140 } 141 _ => (), 142 } 143 back_off_duration = back_off_duration + back_off_duration; 144 if back_off_duration > time_out { 145 panic!("there should not be a scenario where a queued frame is not returned."); 146 } 147 sleep(back_off_duration); 148 } 149 } 150 } 151 152 pub struct V4l2Device<V: VideoFrame> { 153 handle: Rc<RefCell<DeviceHandle<V>>>, 154 } 155 156 impl<V: VideoFrame> V4l2Device<V> { new() -> Result<Self, NewStatelessDecoderError>157 pub fn new() -> Result<Self, NewStatelessDecoderError> { 158 Ok(Self { handle: Rc::new(RefCell::new(DeviceHandle::new()?)) }) 159 } 160 reset_queues(&mut self) -> Result<(), QueueError>161 pub fn reset_queues(&mut self) -> Result<(), QueueError> { 162 self.handle.borrow_mut().reset_queues() 163 } 164 initialize_queues( &mut self, format: Fourcc, coded_size: Resolution, num_buffers: u32, ) -> Result<(), anyhow::Error>165 pub fn initialize_queues( 166 &mut self, 167 format: Fourcc, 168 coded_size: Resolution, 169 num_buffers: u32, 170 ) -> Result<(), anyhow::Error> { 171 self.handle.borrow_mut().output_queue.initialize(format, coded_size)?; 172 self.handle.borrow_mut().capture_queue.initialize(num_buffers)?; 173 Ok(()) 174 } alloc_request( &self, timestamp: u64, frame: V, ) -> Result<Rc<RefCell<V4l2Request<V>>>, DecodeError>175 pub fn alloc_request( 176 &self, 177 timestamp: u64, 178 frame: V, 179 ) -> Result<Rc<RefCell<V4l2Request<V>>>, DecodeError> { 180 if self.handle.borrow().capture_queue.num_free_buffers() == 0 { 181 return Err(DecodeError::NotEnoughOutputBuffers(0)); 182 } 183 184 let output_buffer = self.handle.borrow().output_queue.alloc_buffer(); 185 186 let output_buffer = match output_buffer { 187 Ok(buffer) => buffer, 188 Err(DecodeError::NotEnoughOutputBuffers(_)) => { 189 self.handle.borrow_mut().dequeue_output_buffer(); 190 match self.handle.borrow().output_queue.alloc_buffer() { 191 Ok(buffer) => buffer, 192 Err(e) => return Err(e), 193 } 194 } 195 Err(error) => return Err(error), 196 }; 197 self.handle.borrow_mut().try_dequeue_capture_buffers(); 198 199 let request = Rc::new(RefCell::new(V4l2Request::new( 200 self.clone(), 201 timestamp, 202 self.handle.borrow().alloc_request(), 203 output_buffer, 204 frame, 205 ))); 206 self.handle.borrow_mut().insert_request_into_hash(Rc::downgrade(&request.clone())); 207 Ok(request) 208 } sync(&self, timestamp: u64) -> V4l2CaptureBuffer<V>209 pub fn sync(&self, timestamp: u64) -> V4l2CaptureBuffer<V> { 210 self.handle.borrow_mut().sync(timestamp) 211 } queue_capture_buffer(&self, frame: V) -> Result<(), QueueError>212 pub fn queue_capture_buffer(&self, frame: V) -> Result<(), QueueError> { 213 self.handle.borrow().capture_queue.queue_buffer(frame) 214 } 215 } 216 217 impl<V: VideoFrame> Clone for V4l2Device<V> { clone(&self) -> Self218 fn clone(&self) -> Self { 219 Self { handle: self.handle.clone() } 220 } 221 } 222 223 impl<V: VideoFrame> AsRawFd for V4l2Device<V> { as_raw_fd(&self) -> i32224 fn as_raw_fd(&self) -> i32 { 225 self.handle.borrow().video_device.as_raw_fd() 226 } 227 } 228