1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker // Not all video backends make use of the tools in this module. 6*bb4ee6a4SAndroid Build Coastguard Worker #![allow(dead_code)] 7*bb4ee6a4SAndroid Build Coastguard Worker 8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::btree_map::Entry; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap; 10*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::VecDeque; 11*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration; 12*bb4ee6a4SAndroid Build Coastguard Worker 13*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor; 14*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 15*bb4ee6a4SAndroid Build Coastguard Worker use base::EventExt; 16*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex; 17*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError; 18*bb4ee6a4SAndroid Build Coastguard Worker 19*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::resource::GuestResource; 20*bb4ee6a4SAndroid Build Coastguard Worker 21*bb4ee6a4SAndroid Build Coastguard Worker /// Manages a pollable queue of events to be sent to the decoder or encoder. 22*bb4ee6a4SAndroid Build Coastguard Worker pub struct EventQueue<T> { 23*bb4ee6a4SAndroid Build Coastguard Worker /// Pipe used to signal available events. 24*bb4ee6a4SAndroid Build Coastguard Worker event: Event, 25*bb4ee6a4SAndroid Build Coastguard Worker /// FIFO of all pending events. 26*bb4ee6a4SAndroid Build Coastguard Worker pending_events: VecDeque<T>, 27*bb4ee6a4SAndroid Build Coastguard Worker } 28*bb4ee6a4SAndroid Build Coastguard Worker 29*bb4ee6a4SAndroid Build Coastguard Worker impl<T> EventQueue<T> { 30*bb4ee6a4SAndroid Build Coastguard Worker /// Create a new event queue. new() -> base::Result<Self>31*bb4ee6a4SAndroid Build Coastguard Worker pub fn new() -> base::Result<Self> { 32*bb4ee6a4SAndroid Build Coastguard Worker Ok(Self { 33*bb4ee6a4SAndroid Build Coastguard Worker // Use semaphore semantics so `eventfd` can be `read` as many times as it has been 34*bb4ee6a4SAndroid Build Coastguard Worker // `write`n to without blocking. 35*bb4ee6a4SAndroid Build Coastguard Worker event: Event::new()?, 36*bb4ee6a4SAndroid Build Coastguard Worker pending_events: Default::default(), 37*bb4ee6a4SAndroid Build Coastguard Worker }) 38*bb4ee6a4SAndroid Build Coastguard Worker } 39*bb4ee6a4SAndroid Build Coastguard Worker 40*bb4ee6a4SAndroid Build Coastguard Worker /// Add `event` to the queue. queue_event(&mut self, event: T) -> base::Result<()>41*bb4ee6a4SAndroid Build Coastguard Worker pub fn queue_event(&mut self, event: T) -> base::Result<()> { 42*bb4ee6a4SAndroid Build Coastguard Worker self.pending_events.push_back(event); 43*bb4ee6a4SAndroid Build Coastguard Worker self.event.write_count(1)?; 44*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 45*bb4ee6a4SAndroid Build Coastguard Worker } 46*bb4ee6a4SAndroid Build Coastguard Worker 47*bb4ee6a4SAndroid Build Coastguard Worker /// Read the next event, blocking until an event becomes available. dequeue_event(&mut self) -> base::Result<T>48*bb4ee6a4SAndroid Build Coastguard Worker pub fn dequeue_event(&mut self) -> base::Result<T> { 49*bb4ee6a4SAndroid Build Coastguard Worker // Wait until at least one event is written, if necessary. 50*bb4ee6a4SAndroid Build Coastguard Worker let cpt = self.event.read_count()?; 51*bb4ee6a4SAndroid Build Coastguard Worker let event = match self.pending_events.pop_front() { 52*bb4ee6a4SAndroid Build Coastguard Worker Some(event) => event, 53*bb4ee6a4SAndroid Build Coastguard Worker None => panic!("event signaled but no pending event - this is a bug."), 54*bb4ee6a4SAndroid Build Coastguard Worker }; 55*bb4ee6a4SAndroid Build Coastguard Worker // If we have more than one event pending, write the remainder back into the event so it 56*bb4ee6a4SAndroid Build Coastguard Worker // keeps signalling. 57*bb4ee6a4SAndroid Build Coastguard Worker if cpt > 1 { 58*bb4ee6a4SAndroid Build Coastguard Worker self.event.write_count(cpt - 1)?; 59*bb4ee6a4SAndroid Build Coastguard Worker } 60*bb4ee6a4SAndroid Build Coastguard Worker 61*bb4ee6a4SAndroid Build Coastguard Worker Ok(event) 62*bb4ee6a4SAndroid Build Coastguard Worker } 63*bb4ee6a4SAndroid Build Coastguard Worker 64*bb4ee6a4SAndroid Build Coastguard Worker /// Remove all the posted events for which `predicate` returns `false`. retain<P: FnMut(&T) -> bool>(&mut self, predicate: P)65*bb4ee6a4SAndroid Build Coastguard Worker pub fn retain<P: FnMut(&T) -> bool>(&mut self, predicate: P) { 66*bb4ee6a4SAndroid Build Coastguard Worker if !self.pending_events.is_empty() { 67*bb4ee6a4SAndroid Build Coastguard Worker let _ = self 68*bb4ee6a4SAndroid Build Coastguard Worker .event 69*bb4ee6a4SAndroid Build Coastguard Worker .wait_timeout(Duration::from_millis(0)) 70*bb4ee6a4SAndroid Build Coastguard Worker .expect("wait_timeout failure"); 71*bb4ee6a4SAndroid Build Coastguard Worker } 72*bb4ee6a4SAndroid Build Coastguard Worker 73*bb4ee6a4SAndroid Build Coastguard Worker self.pending_events.retain(predicate); 74*bb4ee6a4SAndroid Build Coastguard Worker 75*bb4ee6a4SAndroid Build Coastguard Worker let num_pending_events = self.pending_events.len(); 76*bb4ee6a4SAndroid Build Coastguard Worker if num_pending_events > 0 { 77*bb4ee6a4SAndroid Build Coastguard Worker self.event 78*bb4ee6a4SAndroid Build Coastguard Worker .write_count(num_pending_events as u64) 79*bb4ee6a4SAndroid Build Coastguard Worker .expect("write failure"); 80*bb4ee6a4SAndroid Build Coastguard Worker } 81*bb4ee6a4SAndroid Build Coastguard Worker } 82*bb4ee6a4SAndroid Build Coastguard Worker 83*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the number of events currently pending on this queue, i.e. the number of times 84*bb4ee6a4SAndroid Build Coastguard Worker /// `dequeue_event` can be called without blocking. 85*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] len(&self) -> usize86*bb4ee6a4SAndroid Build Coastguard Worker pub fn len(&self) -> usize { 87*bb4ee6a4SAndroid Build Coastguard Worker self.pending_events.len() 88*bb4ee6a4SAndroid Build Coastguard Worker } 89*bb4ee6a4SAndroid Build Coastguard Worker } 90*bb4ee6a4SAndroid Build Coastguard Worker 91*bb4ee6a4SAndroid Build Coastguard Worker impl<T> AsRawDescriptor for EventQueue<T> { as_raw_descriptor(&self) -> base::RawDescriptor92*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> base::RawDescriptor { 93*bb4ee6a4SAndroid Build Coastguard Worker self.event.as_raw_descriptor() 94*bb4ee6a4SAndroid Build Coastguard Worker } 95*bb4ee6a4SAndroid Build Coastguard Worker } 96*bb4ee6a4SAndroid Build Coastguard Worker 97*bb4ee6a4SAndroid Build Coastguard Worker /// An `EventQueue` that is `Sync`, `Send`, and non-mut - i.e. that can easily be passed across 98*bb4ee6a4SAndroid Build Coastguard Worker /// threads and wrapped into a `Rc` or `Arc`. 99*bb4ee6a4SAndroid Build Coastguard Worker pub struct SyncEventQueue<T>(Mutex<EventQueue<T>>); 100*bb4ee6a4SAndroid Build Coastguard Worker 101*bb4ee6a4SAndroid Build Coastguard Worker impl<T> From<EventQueue<T>> for SyncEventQueue<T> { from(queue: EventQueue<T>) -> Self102*bb4ee6a4SAndroid Build Coastguard Worker fn from(queue: EventQueue<T>) -> Self { 103*bb4ee6a4SAndroid Build Coastguard Worker Self(Mutex::new(queue)) 104*bb4ee6a4SAndroid Build Coastguard Worker } 105*bb4ee6a4SAndroid Build Coastguard Worker } 106*bb4ee6a4SAndroid Build Coastguard Worker 107*bb4ee6a4SAndroid Build Coastguard Worker impl<T> SyncEventQueue<T> { 108*bb4ee6a4SAndroid Build Coastguard Worker /// Add `event` to the queue. queue_event(&self, event: T) -> base::Result<()>109*bb4ee6a4SAndroid Build Coastguard Worker pub fn queue_event(&self, event: T) -> base::Result<()> { 110*bb4ee6a4SAndroid Build Coastguard Worker self.0.lock().queue_event(event) 111*bb4ee6a4SAndroid Build Coastguard Worker } 112*bb4ee6a4SAndroid Build Coastguard Worker 113*bb4ee6a4SAndroid Build Coastguard Worker /// Read the next event, blocking until an event becomes available. dequeue_event(&self) -> base::Result<T>114*bb4ee6a4SAndroid Build Coastguard Worker pub fn dequeue_event(&self) -> base::Result<T> { 115*bb4ee6a4SAndroid Build Coastguard Worker self.0.lock().dequeue_event() 116*bb4ee6a4SAndroid Build Coastguard Worker } 117*bb4ee6a4SAndroid Build Coastguard Worker 118*bb4ee6a4SAndroid Build Coastguard Worker /// Remove all the posted events for which `predicate` returns `false`. retain<P: FnMut(&T) -> bool>(&self, predicate: P)119*bb4ee6a4SAndroid Build Coastguard Worker pub fn retain<P: FnMut(&T) -> bool>(&self, predicate: P) { 120*bb4ee6a4SAndroid Build Coastguard Worker self.0.lock().retain(predicate) 121*bb4ee6a4SAndroid Build Coastguard Worker } 122*bb4ee6a4SAndroid Build Coastguard Worker 123*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the number of events currently pending on this queue, i.e. the number of times 124*bb4ee6a4SAndroid Build Coastguard Worker /// `dequeue_event` can be called without blocking. 125*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] len(&self) -> usize126*bb4ee6a4SAndroid Build Coastguard Worker pub fn len(&self) -> usize { 127*bb4ee6a4SAndroid Build Coastguard Worker self.0.lock().len() 128*bb4ee6a4SAndroid Build Coastguard Worker } 129*bb4ee6a4SAndroid Build Coastguard Worker } 130*bb4ee6a4SAndroid Build Coastguard Worker 131*bb4ee6a4SAndroid Build Coastguard Worker impl<T> AsRawDescriptor for SyncEventQueue<T> { as_raw_descriptor(&self) -> base::RawDescriptor132*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> base::RawDescriptor { 133*bb4ee6a4SAndroid Build Coastguard Worker self.0.lock().as_raw_descriptor() 134*bb4ee6a4SAndroid Build Coastguard Worker } 135*bb4ee6a4SAndroid Build Coastguard Worker } 136*bb4ee6a4SAndroid Build Coastguard Worker 137*bb4ee6a4SAndroid Build Coastguard Worker /// Queue of all the output buffers provided by crosvm. 138*bb4ee6a4SAndroid Build Coastguard Worker pub struct OutputQueue { 139*bb4ee6a4SAndroid Build Coastguard Worker // Max number of output buffers that can be imported into this queue. 140*bb4ee6a4SAndroid Build Coastguard Worker num_buffers: usize, 141*bb4ee6a4SAndroid Build Coastguard Worker // Maps picture IDs to the corresponding guest resource. 142*bb4ee6a4SAndroid Build Coastguard Worker buffers: BTreeMap<u32, GuestResource>, 143*bb4ee6a4SAndroid Build Coastguard Worker // Picture IDs of output buffers we can write into. 144*bb4ee6a4SAndroid Build Coastguard Worker ready_buffers: VecDeque<u32>, 145*bb4ee6a4SAndroid Build Coastguard Worker } 146*bb4ee6a4SAndroid Build Coastguard Worker 147*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, ThisError)] 148*bb4ee6a4SAndroid Build Coastguard Worker pub enum OutputBufferImportError { 149*bb4ee6a4SAndroid Build Coastguard Worker #[error("maximum number of imported buffers ({0}) already reached")] 150*bb4ee6a4SAndroid Build Coastguard Worker MaxBuffersReached(usize), 151*bb4ee6a4SAndroid Build Coastguard Worker #[error("a buffer with picture ID {0} is already imported")] 152*bb4ee6a4SAndroid Build Coastguard Worker AlreadyImported(u32), 153*bb4ee6a4SAndroid Build Coastguard Worker } 154*bb4ee6a4SAndroid Build Coastguard Worker 155*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, ThisError)] 156*bb4ee6a4SAndroid Build Coastguard Worker pub enum OutputBufferReuseError { 157*bb4ee6a4SAndroid Build Coastguard Worker #[error("no buffer with picture ID {0} is imported at the moment")] 158*bb4ee6a4SAndroid Build Coastguard Worker NotYetImported(u32), 159*bb4ee6a4SAndroid Build Coastguard Worker #[error("buffer with picture ID {0} is already ready for use")] 160*bb4ee6a4SAndroid Build Coastguard Worker AlreadyUsed(u32), 161*bb4ee6a4SAndroid Build Coastguard Worker } 162*bb4ee6a4SAndroid Build Coastguard Worker 163*bb4ee6a4SAndroid Build Coastguard Worker impl OutputQueue { 164*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new output queue capable of containing `num_buffers` buffers. new(num_buffers: usize) -> Self165*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(num_buffers: usize) -> Self { 166*bb4ee6a4SAndroid Build Coastguard Worker Self { 167*bb4ee6a4SAndroid Build Coastguard Worker num_buffers, 168*bb4ee6a4SAndroid Build Coastguard Worker buffers: Default::default(), 169*bb4ee6a4SAndroid Build Coastguard Worker ready_buffers: Default::default(), 170*bb4ee6a4SAndroid Build Coastguard Worker } 171*bb4ee6a4SAndroid Build Coastguard Worker } 172*bb4ee6a4SAndroid Build Coastguard Worker 173*bb4ee6a4SAndroid Build Coastguard Worker /// Import a buffer, i.e. associate the buffer's `resource` to a given `picture_buffer_id`, and 174*bb4ee6a4SAndroid Build Coastguard Worker /// make the buffer ready for use. 175*bb4ee6a4SAndroid Build Coastguard Worker /// 176*bb4ee6a4SAndroid Build Coastguard Worker /// A buffer with a given `picture_buffer_id` can only be imported once. import_buffer( &mut self, picture_buffer_id: u32, resource: GuestResource, ) -> Result<(), OutputBufferImportError>177*bb4ee6a4SAndroid Build Coastguard Worker pub fn import_buffer( 178*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 179*bb4ee6a4SAndroid Build Coastguard Worker picture_buffer_id: u32, 180*bb4ee6a4SAndroid Build Coastguard Worker resource: GuestResource, 181*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), OutputBufferImportError> { 182*bb4ee6a4SAndroid Build Coastguard Worker if self.buffers.len() >= self.num_buffers { 183*bb4ee6a4SAndroid Build Coastguard Worker return Err(OutputBufferImportError::MaxBuffersReached(self.num_buffers)); 184*bb4ee6a4SAndroid Build Coastguard Worker } 185*bb4ee6a4SAndroid Build Coastguard Worker 186*bb4ee6a4SAndroid Build Coastguard Worker match self.buffers.entry(picture_buffer_id) { 187*bb4ee6a4SAndroid Build Coastguard Worker Entry::Vacant(o) => { 188*bb4ee6a4SAndroid Build Coastguard Worker o.insert(resource); 189*bb4ee6a4SAndroid Build Coastguard Worker } 190*bb4ee6a4SAndroid Build Coastguard Worker Entry::Occupied(_) => { 191*bb4ee6a4SAndroid Build Coastguard Worker return Err(OutputBufferImportError::AlreadyImported(picture_buffer_id)); 192*bb4ee6a4SAndroid Build Coastguard Worker } 193*bb4ee6a4SAndroid Build Coastguard Worker } 194*bb4ee6a4SAndroid Build Coastguard Worker 195*bb4ee6a4SAndroid Build Coastguard Worker self.ready_buffers.push_back(picture_buffer_id); 196*bb4ee6a4SAndroid Build Coastguard Worker 197*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 198*bb4ee6a4SAndroid Build Coastguard Worker } 199*bb4ee6a4SAndroid Build Coastguard Worker 200*bb4ee6a4SAndroid Build Coastguard Worker /// Mark the previously-imported buffer with ID `picture_buffer_id` as ready for being used. reuse_buffer(&mut self, picture_buffer_id: u32) -> Result<(), OutputBufferReuseError>201*bb4ee6a4SAndroid Build Coastguard Worker pub fn reuse_buffer(&mut self, picture_buffer_id: u32) -> Result<(), OutputBufferReuseError> { 202*bb4ee6a4SAndroid Build Coastguard Worker if !self.buffers.contains_key(&picture_buffer_id) { 203*bb4ee6a4SAndroid Build Coastguard Worker return Err(OutputBufferReuseError::NotYetImported(picture_buffer_id)); 204*bb4ee6a4SAndroid Build Coastguard Worker } 205*bb4ee6a4SAndroid Build Coastguard Worker 206*bb4ee6a4SAndroid Build Coastguard Worker if self.ready_buffers.contains(&picture_buffer_id) { 207*bb4ee6a4SAndroid Build Coastguard Worker return Err(OutputBufferReuseError::AlreadyUsed(picture_buffer_id)); 208*bb4ee6a4SAndroid Build Coastguard Worker } 209*bb4ee6a4SAndroid Build Coastguard Worker 210*bb4ee6a4SAndroid Build Coastguard Worker self.ready_buffers.push_back(picture_buffer_id); 211*bb4ee6a4SAndroid Build Coastguard Worker 212*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 213*bb4ee6a4SAndroid Build Coastguard Worker } 214*bb4ee6a4SAndroid Build Coastguard Worker 215*bb4ee6a4SAndroid Build Coastguard Worker /// Get a buffer ready to be decoded into, if any is available. try_get_ready_buffer(&mut self) -> Option<(u32, &mut GuestResource)>216*bb4ee6a4SAndroid Build Coastguard Worker pub fn try_get_ready_buffer(&mut self) -> Option<(u32, &mut GuestResource)> { 217*bb4ee6a4SAndroid Build Coastguard Worker let picture_buffer_id = self.ready_buffers.pop_front()?; 218*bb4ee6a4SAndroid Build Coastguard Worker // Unwrapping is safe here because our interface guarantees that ids in `ready_buffers` are 219*bb4ee6a4SAndroid Build Coastguard Worker // valid keys for `buffers`. 220*bb4ee6a4SAndroid Build Coastguard Worker Some(( 221*bb4ee6a4SAndroid Build Coastguard Worker picture_buffer_id, 222*bb4ee6a4SAndroid Build Coastguard Worker self.buffers 223*bb4ee6a4SAndroid Build Coastguard Worker .get_mut(&picture_buffer_id) 224*bb4ee6a4SAndroid Build Coastguard Worker .expect("expected buffer not present in queue"), 225*bb4ee6a4SAndroid Build Coastguard Worker )) 226*bb4ee6a4SAndroid Build Coastguard Worker } 227*bb4ee6a4SAndroid Build Coastguard Worker clear_ready_buffers(&mut self)228*bb4ee6a4SAndroid Build Coastguard Worker pub fn clear_ready_buffers(&mut self) { 229*bb4ee6a4SAndroid Build Coastguard Worker self.ready_buffers.clear(); 230*bb4ee6a4SAndroid Build Coastguard Worker } 231*bb4ee6a4SAndroid Build Coastguard Worker } 232*bb4ee6a4SAndroid Build Coastguard Worker 233*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 234*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 235*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration; 236*bb4ee6a4SAndroid Build Coastguard Worker 237*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken; 238*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext; 239*bb4ee6a4SAndroid Build Coastguard Worker 240*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 241*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::error::VideoError; 242*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::error::VideoResult; 243*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::format::Rect; 244*bb4ee6a4SAndroid Build Coastguard Worker 245*bb4ee6a4SAndroid Build Coastguard Worker /// This is the same as DecoderEvent but copied here so that the test can be compiled 246*bb4ee6a4SAndroid Build Coastguard Worker /// without depending on the "video-decoder" feature. 247*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)] 248*bb4ee6a4SAndroid Build Coastguard Worker pub enum TestEvent { 249*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 250*bb4ee6a4SAndroid Build Coastguard Worker ProvidePictureBuffers { 251*bb4ee6a4SAndroid Build Coastguard Worker min_num_buffers: u32, 252*bb4ee6a4SAndroid Build Coastguard Worker width: i32, 253*bb4ee6a4SAndroid Build Coastguard Worker height: i32, 254*bb4ee6a4SAndroid Build Coastguard Worker visible_rect: Rect, 255*bb4ee6a4SAndroid Build Coastguard Worker }, 256*bb4ee6a4SAndroid Build Coastguard Worker PictureReady { 257*bb4ee6a4SAndroid Build Coastguard Worker picture_buffer_id: i32, 258*bb4ee6a4SAndroid Build Coastguard Worker timestamp: u64, 259*bb4ee6a4SAndroid Build Coastguard Worker visible_rect: Rect, 260*bb4ee6a4SAndroid Build Coastguard Worker }, 261*bb4ee6a4SAndroid Build Coastguard Worker NotifyEndOfBitstreamBuffer(u32), 262*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 263*bb4ee6a4SAndroid Build Coastguard Worker NotifyError(VideoError), 264*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 265*bb4ee6a4SAndroid Build Coastguard Worker FlushCompleted(VideoResult<()>), 266*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 267*bb4ee6a4SAndroid Build Coastguard Worker ResetCompleted(VideoResult<()>), 268*bb4ee6a4SAndroid Build Coastguard Worker } 269*bb4ee6a4SAndroid Build Coastguard Worker 270*bb4ee6a4SAndroid Build Coastguard Worker /// Test basic queue/dequeue functionality of `EventQueue`. 271*bb4ee6a4SAndroid Build Coastguard Worker #[test] event_queue()272*bb4ee6a4SAndroid Build Coastguard Worker fn event_queue() { 273*bb4ee6a4SAndroid Build Coastguard Worker let mut event_queue = EventQueue::new().unwrap(); 274*bb4ee6a4SAndroid Build Coastguard Worker 275*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 276*bb4ee6a4SAndroid Build Coastguard Worker event_queue.queue_event(TestEvent::NotifyEndOfBitstreamBuffer(1)), 277*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 278*bb4ee6a4SAndroid Build Coastguard Worker ); 279*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(event_queue.len(), 1); 280*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 281*bb4ee6a4SAndroid Build Coastguard Worker event_queue.queue_event(TestEvent::PictureReady { 282*bb4ee6a4SAndroid Build Coastguard Worker picture_buffer_id: 0, 283*bb4ee6a4SAndroid Build Coastguard Worker timestamp: 42, 284*bb4ee6a4SAndroid Build Coastguard Worker visible_rect: Rect { 285*bb4ee6a4SAndroid Build Coastguard Worker left: 0, 286*bb4ee6a4SAndroid Build Coastguard Worker top: 0, 287*bb4ee6a4SAndroid Build Coastguard Worker right: 320, 288*bb4ee6a4SAndroid Build Coastguard Worker bottom: 240, 289*bb4ee6a4SAndroid Build Coastguard Worker }, 290*bb4ee6a4SAndroid Build Coastguard Worker }), 291*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 292*bb4ee6a4SAndroid Build Coastguard Worker ); 293*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(event_queue.len(), 2); 294*bb4ee6a4SAndroid Build Coastguard Worker 295*bb4ee6a4SAndroid Build Coastguard Worker assert!(matches!( 296*bb4ee6a4SAndroid Build Coastguard Worker event_queue.dequeue_event(), 297*bb4ee6a4SAndroid Build Coastguard Worker Ok(TestEvent::NotifyEndOfBitstreamBuffer(1)) 298*bb4ee6a4SAndroid Build Coastguard Worker )); 299*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(event_queue.len(), 1); 300*bb4ee6a4SAndroid Build Coastguard Worker assert!(matches!( 301*bb4ee6a4SAndroid Build Coastguard Worker event_queue.dequeue_event(), 302*bb4ee6a4SAndroid Build Coastguard Worker Ok(TestEvent::PictureReady { 303*bb4ee6a4SAndroid Build Coastguard Worker picture_buffer_id: 0, 304*bb4ee6a4SAndroid Build Coastguard Worker timestamp: 42, 305*bb4ee6a4SAndroid Build Coastguard Worker visible_rect: Rect { 306*bb4ee6a4SAndroid Build Coastguard Worker left: 0, 307*bb4ee6a4SAndroid Build Coastguard Worker top: 0, 308*bb4ee6a4SAndroid Build Coastguard Worker right: 320, 309*bb4ee6a4SAndroid Build Coastguard Worker bottom: 240, 310*bb4ee6a4SAndroid Build Coastguard Worker } 311*bb4ee6a4SAndroid Build Coastguard Worker }) 312*bb4ee6a4SAndroid Build Coastguard Worker )); 313*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(event_queue.len(), 0); 314*bb4ee6a4SAndroid Build Coastguard Worker } 315*bb4ee6a4SAndroid Build Coastguard Worker 316*bb4ee6a4SAndroid Build Coastguard Worker /// Test polling of `TestEventQueue`'s `event_pipe`. 317*bb4ee6a4SAndroid Build Coastguard Worker #[test] decoder_event_queue_polling()318*bb4ee6a4SAndroid Build Coastguard Worker fn decoder_event_queue_polling() { 319*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken)] 320*bb4ee6a4SAndroid Build Coastguard Worker enum Token { 321*bb4ee6a4SAndroid Build Coastguard Worker Event, 322*bb4ee6a4SAndroid Build Coastguard Worker } 323*bb4ee6a4SAndroid Build Coastguard Worker 324*bb4ee6a4SAndroid Build Coastguard Worker let mut event_queue = EventQueue::new().unwrap(); 325*bb4ee6a4SAndroid Build Coastguard Worker let wait_context = WaitContext::build_with(&[(&event_queue, Token::Event)]).unwrap(); 326*bb4ee6a4SAndroid Build Coastguard Worker 327*bb4ee6a4SAndroid Build Coastguard Worker // The queue is empty, so `event_pipe` should not signal. 328*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 0); 329*bb4ee6a4SAndroid Build Coastguard Worker 330*bb4ee6a4SAndroid Build Coastguard Worker // `event_pipe` should signal as long as the queue is not empty. 331*bb4ee6a4SAndroid Build Coastguard Worker event_queue 332*bb4ee6a4SAndroid Build Coastguard Worker .queue_event(TestEvent::NotifyEndOfBitstreamBuffer(1)) 333*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 334*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1); 335*bb4ee6a4SAndroid Build Coastguard Worker event_queue 336*bb4ee6a4SAndroid Build Coastguard Worker .queue_event(TestEvent::NotifyEndOfBitstreamBuffer(2)) 337*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 338*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1); 339*bb4ee6a4SAndroid Build Coastguard Worker event_queue 340*bb4ee6a4SAndroid Build Coastguard Worker .queue_event(TestEvent::NotifyEndOfBitstreamBuffer(3)) 341*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 342*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1); 343*bb4ee6a4SAndroid Build Coastguard Worker 344*bb4ee6a4SAndroid Build Coastguard Worker event_queue.dequeue_event().unwrap(); 345*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1); 346*bb4ee6a4SAndroid Build Coastguard Worker event_queue.dequeue_event().unwrap(); 347*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1); 348*bb4ee6a4SAndroid Build Coastguard Worker event_queue.dequeue_event().unwrap(); 349*bb4ee6a4SAndroid Build Coastguard Worker 350*bb4ee6a4SAndroid Build Coastguard Worker // The queue is empty again, so `event_pipe` should not signal. 351*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 0); 352*bb4ee6a4SAndroid Build Coastguard Worker } 353*bb4ee6a4SAndroid Build Coastguard Worker } 354