virtio: video: decoder: add SyncEventQueue

So far we were using EventQueue in a very simple and controlled manner ;
but efficient decoding patterns are more complex than that and we are
soon going to need to keep references to the queue from remote corners
of the code and post events from there, which requires mutable access.

To help with this, add a SyncEventQueue type that is essentially an
EventQueue wrapped into a Mutex, which allows us to make its methods
non-mut.

BUG=b:169295147
TEST=v4l2r's simple_decoder can decode a H.264 stream.

Change-Id: Ife94629ab2382eb0aac5786ba24373c66b80efc7
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3782035
Tested-by: Alexandre Courbot <acourbot@chromium.org>
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
This commit is contained in:
Alexandre Courbot 2022-07-19 12:11:48 +09:00 committed by crosvm LUCI
parent 03b55369d4
commit 91ff1282b4

View file

@ -12,6 +12,7 @@ use std::time::Duration;
use base::AsRawDescriptor;
use base::Event;
use sync::Mutex;
use thiserror::Error as ThisError;
#[cfg(feature = "ffmpeg")]
@ -94,6 +95,46 @@ impl<T> AsRawDescriptor for EventQueue<T> {
}
}
/// An `EventQueue` that is `Sync`, `Send`, and non-mut - i.e. that can easily be passed across
/// threads and wrapped into a `Rc` or `Arc`.
pub struct SyncEventQueue<T>(Mutex<EventQueue<T>>);
impl<T> From<EventQueue<T>> for SyncEventQueue<T> {
fn from(queue: EventQueue<T>) -> Self {
Self(Mutex::new(queue))
}
}
impl<T> SyncEventQueue<T> {
/// Add `event` to the queue.
pub fn queue_event(&self, event: T) -> base::Result<()> {
self.0.lock().queue_event(event)
}
/// Read the next event, blocking until an event becomes available.
pub fn dequeue_event(&self) -> base::Result<T> {
self.0.lock().dequeue_event()
}
/// Remove all the posted events for which `predicate` returns `false`.
pub fn retain<P: FnMut(&T) -> bool>(&self, predicate: P) {
self.0.lock().retain(predicate)
}
/// Returns the number of events currently pending on this queue, i.e. the number of times
/// `dequeue_event` can be called without blocking.
#[cfg(test)]
pub fn len(&self) -> usize {
self.0.lock().len()
}
}
impl<T> AsRawDescriptor for SyncEventQueue<T> {
fn as_raw_descriptor(&self) -> base::RawDescriptor {
self.0.lock().as_raw_descriptor()
}
}
#[cfg(feature = "ffmpeg")]
impl ffmpeg::swscale::SwConverterTarget for GuestResource {
fn stride(&self) -> Option<usize> {