mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-25 05:03:05 +00:00
media: cros-codecs: move methods from StatelessDecoderBackend to VideoDecoderBackend
Move some methods that are common for all codecs from the `HandleType` type from StatelessDecoderBackend to VideoDecoderBackend. This makes the `StatelessDecoderBackend` traits implement the codec-specific part of the backend (which requires a custom interface), while the `VideoDecoderBackend` trait implements the shared behavior of the backend, regardless of the underlying codec. This separation will also allow us to factorize the implementations of these methods further down this series. BUG=b:214478588 TEST=cargo test --features vaapi -p cros-codecs Change-Id: Id9f6874a1a57531ff092975f3692b10f7c1afcae Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4123654 Commit-Queue: Alexandre Courbot <acourbot@chromium.org> Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.corp-partner.google.com>
This commit is contained in:
parent
e010e848d5
commit
80b9fa53d7
11 changed files with 296 additions and 360 deletions
|
@ -5,6 +5,7 @@
|
|||
use std::cell::Ref;
|
||||
use std::cell::RefCell;
|
||||
use std::cell::RefMut;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
use thiserror::Error;
|
||||
|
@ -40,7 +41,15 @@ pub enum StatelessBackendError {
|
|||
Other(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
pub type StatelessBackendResult<T> = std::result::Result<T, StatelessBackendError>;
|
||||
|
||||
pub(crate) trait VideoDecoderBackend {
|
||||
/// The type that the backend returns as a result of a decode operation.
|
||||
/// This will usually be some backend-specific type with a resource and a
|
||||
/// resource pool so that said buffer can be reused for another decode
|
||||
/// operation when it goes out of scope.
|
||||
type Handle: DecodedHandle;
|
||||
|
||||
/// Returns the current coded resolution of the bitstream being processed.
|
||||
/// This may be None if we have not read the stream parameters yet.
|
||||
fn coded_resolution(&self) -> Option<Resolution>;
|
||||
|
@ -62,6 +71,17 @@ pub(crate) trait VideoDecoderBackend {
|
|||
|
||||
/// Try altering the decoded format.
|
||||
fn try_format(&mut self, format: DecodedFormat) -> Result<()>;
|
||||
|
||||
/// Poll for any ready pictures. `block` dictates whether this call should
|
||||
/// block on the operation or return immediately.
|
||||
fn poll(&mut self, blocking_mode: BlockingMode) -> Result<VecDeque<Self::Handle>>;
|
||||
|
||||
/// Whether the handle is ready for presentation. The decoder will check
|
||||
/// this before returning the handle to clients.
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool;
|
||||
|
||||
/// Block on handle `handle`.
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()>;
|
||||
}
|
||||
|
||||
pub trait VideoDecoder {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::decoders::h264::dpb::Dpb;
|
||||
|
@ -11,11 +10,10 @@ use crate::decoders::h264::parser::Pps;
|
|||
use crate::decoders::h264::parser::Slice;
|
||||
use crate::decoders::h264::parser::Sps;
|
||||
use crate::decoders::h264::picture::H264Picture;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::VideoDecoderBackend;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, crate::decoders::StatelessBackendError>;
|
||||
pub type Result<T> = crate::decoders::StatelessBackendResult<T>;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod dummy;
|
||||
|
@ -38,12 +36,6 @@ pub type AsBackendHandle<Handle> = <Handle as DecodedHandle>::BackendHandle;
|
|||
/// mode, where it should return immediately with any previously decoded frames
|
||||
/// that happen to be ready.
|
||||
pub(crate) trait StatelessDecoderBackend: VideoDecoderBackend {
|
||||
/// The type that the backend returns as a result of a decode operation.
|
||||
/// This will usually be some backend-specific type with a resource and a
|
||||
/// resource pool so that said buffer can be reused for another decode
|
||||
/// operation when it goes out of scope.
|
||||
type Handle: DecodedHandle;
|
||||
|
||||
/// Called when a new SPS is parsed.
|
||||
fn new_sequence(&mut self, sps: &Sps, dpb_size: usize) -> Result<()>;
|
||||
|
||||
|
@ -109,10 +101,6 @@ pub(crate) trait StatelessDecoderBackend: VideoDecoderBackend {
|
|||
block: bool,
|
||||
) -> Result<Self::Handle>;
|
||||
|
||||
/// Poll for any ready pictures. `block` dictates whether this call should
|
||||
/// block on the operation or return immediately.
|
||||
fn poll(&mut self, blocking_mode: BlockingMode) -> Result<VecDeque<Self::Handle>>;
|
||||
|
||||
/// Indicates that the decoder has split a picture and that a new Handle
|
||||
/// must be obtained.
|
||||
fn new_handle(
|
||||
|
@ -120,13 +108,6 @@ pub(crate) trait StatelessDecoderBackend: VideoDecoderBackend {
|
|||
picture: ContainedPicture<AsBackendHandle<Self::Handle>>,
|
||||
) -> Result<Self::Handle>;
|
||||
|
||||
/// Whether the handle is ready for presentation. The decoder will check
|
||||
/// this before returning the handle to clients.
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool;
|
||||
|
||||
/// Block on handle `handle`.
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> Result<()>;
|
||||
|
||||
/// Get the test parameters for the backend. The caller is reponsible for
|
||||
/// downcasting them to the correct type, which is backend-dependent.
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -6,11 +6,9 @@
|
|||
//! run so we can test it in isolation.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::decoders::h264::backends::AsBackendHandle;
|
||||
use crate::decoders::h264::backends::BlockingMode;
|
||||
use crate::decoders::h264::backends::ContainedPicture;
|
||||
use crate::decoders::h264::backends::Result as StatelessBackendResult;
|
||||
use crate::decoders::h264::backends::StatelessDecoderBackend;
|
||||
|
@ -20,11 +18,10 @@ use crate::decoders::h264::parser::Pps;
|
|||
use crate::decoders::h264::parser::Slice;
|
||||
use crate::decoders::h264::parser::Sps;
|
||||
use crate::decoders::h264::picture::H264Picture;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::utils::dummy::*;
|
||||
|
||||
impl StatelessDecoderBackend for Backend {
|
||||
type Handle = Handle<H264Picture<BackendHandle>>;
|
||||
|
||||
impl StatelessDecoderBackend for Backend<H264Picture<BackendHandle>> {
|
||||
fn new_sequence(&mut self, _: &Sps, _: usize) -> StatelessBackendResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -72,10 +69,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
})
|
||||
}
|
||||
|
||||
fn poll(&mut self, _: BlockingMode) -> StatelessBackendResult<VecDeque<Self::Handle>> {
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn new_handle(
|
||||
&mut self,
|
||||
picture: ContainedPicture<AsBackendHandle<Self::Handle>>,
|
||||
|
@ -99,14 +92,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, _: &Self::Handle) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, _: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_test_params(&self) -> &dyn std::any::Any {
|
||||
// There are no test parameters for the dummy backend.
|
||||
|
@ -117,6 +102,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
impl Decoder<Handle<H264Picture<BackendHandle>>> {
|
||||
// Creates a new instance of the decoder using the dummy backend.
|
||||
pub fn new_dummy(blocking_mode: BlockingMode) -> anyhow::Result<Self> {
|
||||
Self::new(Box::new(Backend), blocking_mode)
|
||||
Self::new(Box::new(Backend::new()), blocking_mode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,7 @@ use libva::SliceParameter;
|
|||
use libva::UsageHint;
|
||||
use log::debug;
|
||||
|
||||
use crate::decoders::h264::backends::BlockingMode;
|
||||
use crate::decoders::h264::backends::ContainedPicture;
|
||||
use crate::decoders::h264::backends::DecodedHandle;
|
||||
use crate::decoders::h264::backends::Result as StatelessBackendResult;
|
||||
use crate::decoders::h264::backends::StatelessDecoderBackend;
|
||||
use crate::decoders::h264::decoder::Decoder;
|
||||
|
@ -35,6 +33,8 @@ use crate::decoders::h264::parser::Sps;
|
|||
use crate::decoders::h264::picture::Field;
|
||||
use crate::decoders::h264::picture::H264Picture;
|
||||
use crate::decoders::h264::picture::Reference;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::Error as DecoderError;
|
||||
use crate::decoders::Result as DecoderResult;
|
||||
use crate::decoders::StatelessBackendError;
|
||||
|
@ -51,7 +51,7 @@ use crate::DecodedFormat;
|
|||
use crate::Resolution;
|
||||
|
||||
/// Resolves to the type used as Handle by the backend.
|
||||
type AssociatedHandle = <Backend as StatelessDecoderBackend>::Handle;
|
||||
type AssociatedHandle = <Backend as VideoDecoderBackend>::Handle;
|
||||
|
||||
#[cfg(test)]
|
||||
#[derive(Default)]
|
||||
|
@ -609,6 +609,8 @@ impl Backend {
|
|||
}
|
||||
|
||||
impl VideoDecoderBackend for Backend {
|
||||
type Handle = VADecodedHandle<H264Picture<GenericBackendHandle>>;
|
||||
|
||||
fn num_resources_total(&self) -> usize {
|
||||
self.num_allocated_surfaces
|
||||
}
|
||||
|
@ -667,11 +669,81 @@ impl VideoDecoderBackend for Backend {
|
|||
fn display_resolution(&self) -> Option<Resolution> {
|
||||
self.metadata_state.display_resolution().ok()
|
||||
}
|
||||
|
||||
fn poll(&mut self, blocking_mode: BlockingMode) -> DecoderResult<VecDeque<Self::Handle>> {
|
||||
let mut completed = VecDeque::new();
|
||||
let candidates = self.pending_jobs.drain(..).collect::<VecDeque<_>>();
|
||||
|
||||
for job in candidates {
|
||||
if matches!(blocking_mode, BlockingMode::NonBlocking) {
|
||||
let status = job.va_picture.query_status()?;
|
||||
if status != libva::VASurfaceStatus::VASurfaceReady {
|
||||
self.pending_jobs.push_back(job);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
completed.push_back(job.codec_picture);
|
||||
}
|
||||
|
||||
let completed = completed.into_iter().map(|picture| {
|
||||
self.build_va_decoded_handle(&picture)
|
||||
.map_err(|e| DecoderError::from(StatelessBackendError::Other(anyhow!(e))))
|
||||
});
|
||||
|
||||
completed.collect::<Result<VecDeque<_>, _>>()
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool {
|
||||
match &handle.picture().backend_handle {
|
||||
Some(backend_handle) => backend_handle.is_ready(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
for i in 0..self.pending_jobs.len() {
|
||||
// Remove from the queue in order.
|
||||
let job = &self.pending_jobs[i];
|
||||
|
||||
if H264Picture::same(&job.codec_picture, handle.picture_container()) {
|
||||
let job = self.pending_jobs.remove(i).unwrap();
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(StatelessBackendError::Other(anyhow!(
|
||||
"Asked to block on a pending job that doesn't exist"
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl StatelessDecoderBackend for Backend {
|
||||
type Handle = VADecodedHandle<H264Picture<GenericBackendHandle>>;
|
||||
|
||||
fn new_sequence(&mut self, sps: &Sps, dpb_size: usize) -> StatelessBackendResult<()> {
|
||||
self.open(sps, dpb_size, None)?;
|
||||
self.negotiation_status = NegotiationStatus::Possible(Box::new((sps.clone(), dpb_size)));
|
||||
|
@ -802,45 +874,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
.map_err(|e| StatelessBackendError::Other(anyhow!(e)))
|
||||
}
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
blocking_mode: BlockingMode,
|
||||
) -> StatelessBackendResult<VecDeque<Self::Handle>> {
|
||||
let mut completed = VecDeque::new();
|
||||
let candidates = self.pending_jobs.drain(..).collect::<VecDeque<_>>();
|
||||
|
||||
for job in candidates {
|
||||
if matches!(blocking_mode, BlockingMode::NonBlocking) {
|
||||
let status = job.va_picture.query_status()?;
|
||||
if status != libva::VASurfaceStatus::VASurfaceReady {
|
||||
self.pending_jobs.push_back(job);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
completed.push_back(job.codec_picture);
|
||||
}
|
||||
|
||||
let completed = completed.into_iter().map(|picture| {
|
||||
self.build_va_decoded_handle(&picture)
|
||||
.map_err(|e| StatelessBackendError::Other(anyhow!(e)))
|
||||
});
|
||||
|
||||
completed.collect::<Result<VecDeque<_>, StatelessBackendError>>()
|
||||
}
|
||||
|
||||
fn new_handle(
|
||||
&mut self,
|
||||
picture: ContainedPicture<GenericBackendHandle>,
|
||||
|
@ -906,42 +939,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool {
|
||||
match &handle.picture().backend_handle {
|
||||
Some(backend_handle) => backend_handle.is_ready(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
for i in 0..self.pending_jobs.len() {
|
||||
// Remove from the queue in order.
|
||||
let job = &self.pending_jobs[i];
|
||||
|
||||
if H264Picture::same(&job.codec_picture, handle.picture_container()) {
|
||||
let job = self.pending_jobs.remove(i).unwrap();
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(StatelessBackendError::Other(anyhow!(
|
||||
"Asked to block on a pending job that doesn't exist"
|
||||
)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_test_params(&self) -> &dyn std::any::Any {
|
||||
&self.test_params
|
||||
|
@ -963,12 +960,12 @@ mod tests {
|
|||
|
||||
use crate::decoders::h264::backends::vaapi::AssociatedHandle;
|
||||
use crate::decoders::h264::backends::vaapi::TestParams;
|
||||
use crate::decoders::h264::backends::BlockingMode;
|
||||
use crate::decoders::h264::backends::DecodedHandle;
|
||||
use crate::decoders::h264::backends::StatelessDecoderBackend;
|
||||
use crate::decoders::h264::decoder::tests::process_ready_frames;
|
||||
use crate::decoders::h264::decoder::tests::run_decoding_loop;
|
||||
use crate::decoders::h264::decoder::Decoder;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::DynPicture;
|
||||
|
||||
fn get_test_params(
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::decoders::vp8::parser::Header;
|
||||
use crate::decoders::vp8::parser::Parser;
|
||||
use crate::decoders::vp8::picture::Vp8Picture;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::VideoDecoderBackend;
|
||||
|
||||
|
@ -18,7 +16,7 @@ pub mod dummy;
|
|||
#[cfg(feature = "vaapi")]
|
||||
pub mod vaapi;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, crate::decoders::StatelessBackendError>;
|
||||
pub type Result<T> = crate::decoders::StatelessBackendResult<T>;
|
||||
|
||||
/// The container type for the picture. Pictures must offer interior mutability
|
||||
/// as they may be shared.
|
||||
|
@ -35,12 +33,6 @@ pub type AsBackendHandle<Handle> = <Handle as DecodedHandle>::BackendHandle;
|
|||
/// mode, where it should return immediately with any previously decoded frames
|
||||
/// that happen to be ready.
|
||||
pub(crate) trait StatelessDecoderBackend: VideoDecoderBackend {
|
||||
/// The type that the backend returns as a result of a decode operation.
|
||||
/// This will usually be some backend-specific type with a resource and a
|
||||
/// resource pool so that said buffer can be reused for another decode
|
||||
/// operation when it goes out of scope.
|
||||
type Handle: DecodedHandle;
|
||||
|
||||
/// Called when new stream parameters are found.
|
||||
fn new_sequence(&mut self, header: &Header) -> Result<()>;
|
||||
|
||||
|
@ -63,17 +55,6 @@ pub(crate) trait StatelessDecoderBackend: VideoDecoderBackend {
|
|||
block: bool,
|
||||
) -> Result<Self::Handle>;
|
||||
|
||||
/// Poll for any ready pictures. `block` dictates whether this call should
|
||||
/// block on the operation or return immediately.
|
||||
fn poll(&mut self, blocking_mode: BlockingMode) -> Result<VecDeque<Self::Handle>>;
|
||||
|
||||
/// Whether the handle is ready for presentation. The decoder will check
|
||||
/// this before returning the handle to clients.
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool;
|
||||
|
||||
/// Block on handle `handle`.
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> Result<()>;
|
||||
|
||||
/// Get the test parameters for the backend. The caller is reponsible for
|
||||
/// downcasting them to the correct type, which is backend-dependent.
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
// run so we can test it in isolation.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::decoders::vp8::backends::StatelessDecoderBackend;
|
||||
|
@ -15,9 +14,7 @@ use crate::decoders::vp8::decoder::Decoder;
|
|||
use crate::decoders::BlockingMode;
|
||||
use crate::utils::dummy::*;
|
||||
|
||||
impl StatelessDecoderBackend for Backend {
|
||||
type Handle = Handle<Vp8Picture<BackendHandle>>;
|
||||
|
||||
impl StatelessDecoderBackend for Backend<Vp8Picture<BackendHandle>> {
|
||||
fn new_sequence(&mut self, _: &crate::decoders::vp8::parser::Header) -> super::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -38,18 +35,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
})
|
||||
}
|
||||
|
||||
fn poll(&mut self, _: super::BlockingMode) -> super::Result<VecDeque<Self::Handle>> {
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, _: &Self::Handle) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, _: &Self::Handle) -> super::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_test_params(&self) -> &dyn std::any::Any {
|
||||
// There are no test parameters for the dummy backend.
|
||||
|
@ -60,6 +45,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
impl Decoder<Handle<Vp8Picture<BackendHandle>>> {
|
||||
// Creates a new instance of the decoder using the dummy backend.
|
||||
pub fn new_dummy(blocking_mode: BlockingMode) -> anyhow::Result<Self> {
|
||||
Self::new(Box::new(Backend), blocking_mode)
|
||||
Self::new(Box::new(Backend::new()), blocking_mode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,7 @@ use libva::UsageHint;
|
|||
|
||||
use crate::decoders::h264::backends::Result as StatelessBackendResult;
|
||||
use crate::decoders::vp8::backends::AsBackendHandle;
|
||||
use crate::decoders::vp8::backends::BlockingMode;
|
||||
use crate::decoders::vp8::backends::ContainedPicture;
|
||||
use crate::decoders::vp8::backends::DecodedHandle;
|
||||
use crate::decoders::vp8::backends::StatelessDecoderBackend;
|
||||
use crate::decoders::vp8::backends::Vp8Picture;
|
||||
use crate::decoders::vp8::decoder::Decoder;
|
||||
|
@ -31,6 +29,8 @@ use crate::decoders::vp8::parser::Header;
|
|||
use crate::decoders::vp8::parser::MbLfAdjustments;
|
||||
use crate::decoders::vp8::parser::Parser;
|
||||
use crate::decoders::vp8::parser::Segmentation;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::Error as DecoderError;
|
||||
use crate::decoders::Result as DecoderResult;
|
||||
use crate::decoders::StatelessBackendError;
|
||||
|
@ -47,7 +47,7 @@ use crate::DecodedFormat;
|
|||
use crate::Resolution;
|
||||
|
||||
/// Resolves to the type used as Handle by the backend.
|
||||
type AssociatedHandle = <Backend as StatelessDecoderBackend>::Handle;
|
||||
type AssociatedHandle = <Backend as VideoDecoderBackend>::Handle;
|
||||
|
||||
/// The number of surfaces to allocate for this codec. Same as GStreamer's vavp8dec.
|
||||
const NUM_SURFACES: usize = 7;
|
||||
|
@ -371,8 +371,6 @@ impl Backend {
|
|||
}
|
||||
|
||||
impl StatelessDecoderBackend for Backend {
|
||||
type Handle = VADecodedHandle<Vp8Picture<GenericBackendHandle>>;
|
||||
|
||||
fn new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()> {
|
||||
self.open(header, None)?;
|
||||
self.negotiation_status = NegotiationStatus::Possible(Box::new(header.clone()));
|
||||
|
@ -487,81 +485,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
.map_err(|e| StatelessBackendError::Other(anyhow!(e)))
|
||||
}
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
blocking_mode: super::BlockingMode,
|
||||
) -> StatelessBackendResult<VecDeque<Self::Handle>> {
|
||||
let mut completed = VecDeque::new();
|
||||
let candidates = self.pending_jobs.drain(..).collect::<VecDeque<_>>();
|
||||
|
||||
for job in candidates {
|
||||
if matches!(blocking_mode, BlockingMode::NonBlocking) {
|
||||
let status = job.va_picture.query_status()?;
|
||||
if status != libva::VASurfaceStatus::VASurfaceReady {
|
||||
self.pending_jobs.push_back(job);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
completed.push_back(job.codec_picture);
|
||||
}
|
||||
|
||||
let completed = completed.into_iter().map(|picture| {
|
||||
self.build_va_decoded_handle(&picture)
|
||||
.map_err(|e| StatelessBackendError::Other(anyhow!(e)))
|
||||
});
|
||||
|
||||
completed.collect::<Result<VecDeque<_>, StatelessBackendError>>()
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool {
|
||||
match &handle.picture().backend_handle {
|
||||
Some(backend_handle) => backend_handle.is_ready(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
for i in 0..self.pending_jobs.len() {
|
||||
// Remove from the queue in order.
|
||||
let job = &self.pending_jobs[i];
|
||||
|
||||
if Vp8Picture::same(&job.codec_picture, handle.picture_container()) {
|
||||
let job = self.pending_jobs.remove(i).unwrap();
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(StatelessBackendError::Other(anyhow!(
|
||||
"Asked to block on a pending job that doesn't exist"
|
||||
)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_test_params(&self) -> &dyn Any {
|
||||
&self.test_params
|
||||
|
@ -569,6 +492,8 @@ impl StatelessDecoderBackend for Backend {
|
|||
}
|
||||
|
||||
impl VideoDecoderBackend for Backend {
|
||||
type Handle = VADecodedHandle<Vp8Picture<GenericBackendHandle>>;
|
||||
|
||||
fn coded_resolution(&self) -> Option<Resolution> {
|
||||
self.metadata_state.coded_resolution().ok()
|
||||
}
|
||||
|
@ -626,6 +551,78 @@ impl VideoDecoderBackend for Backend {
|
|||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn poll(&mut self, blocking_mode: BlockingMode) -> DecoderResult<VecDeque<Self::Handle>> {
|
||||
let mut completed = VecDeque::new();
|
||||
let candidates = self.pending_jobs.drain(..).collect::<VecDeque<_>>();
|
||||
|
||||
for job in candidates {
|
||||
if matches!(blocking_mode, BlockingMode::NonBlocking) {
|
||||
let status = job.va_picture.query_status()?;
|
||||
if status != libva::VASurfaceStatus::VASurfaceReady {
|
||||
self.pending_jobs.push_back(job);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
completed.push_back(job.codec_picture);
|
||||
}
|
||||
|
||||
let completed = completed.into_iter().map(|picture| {
|
||||
self.build_va_decoded_handle(&picture)
|
||||
.map_err(|e| DecoderError::from(StatelessBackendError::Other(anyhow!(e))))
|
||||
});
|
||||
|
||||
completed.collect::<Result<VecDeque<_>, _>>()
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool {
|
||||
match &handle.picture().backend_handle {
|
||||
Some(backend_handle) => backend_handle.is_ready(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
for i in 0..self.pending_jobs.len() {
|
||||
// Remove from the queue in order.
|
||||
let job = &self.pending_jobs[i];
|
||||
|
||||
if Vp8Picture::same(&job.codec_picture, handle.picture_container()) {
|
||||
let job = self.pending_jobs.remove(i).unwrap();
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(StatelessBackendError::Other(anyhow!(
|
||||
"Asked to block on a pending job that doesn't exist"
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Decoder<VADecodedHandle<Vp8Picture<GenericBackendHandle>>> {
|
||||
|
@ -647,12 +644,12 @@ mod tests {
|
|||
|
||||
use crate::decoders::vp8::backends::vaapi::AssociatedHandle;
|
||||
use crate::decoders::vp8::backends::vaapi::TestParams;
|
||||
use crate::decoders::vp8::backends::BlockingMode;
|
||||
use crate::decoders::vp8::backends::DecodedHandle;
|
||||
use crate::decoders::vp8::backends::StatelessDecoderBackend;
|
||||
use crate::decoders::vp8::decoder::tests::process_ready_frames;
|
||||
use crate::decoders::vp8::decoder::tests::run_decoding_loop;
|
||||
use crate::decoders::vp8::decoder::Decoder;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::DynPicture;
|
||||
|
||||
fn get_test_params(
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::decoders::vp9::parser::Header;
|
||||
use crate::decoders::vp9::parser::NUM_REF_FRAMES;
|
||||
use crate::decoders::vp9::picture::Vp9Picture;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::VideoDecoderBackend;
|
||||
|
||||
|
@ -18,7 +16,7 @@ pub mod dummy;
|
|||
#[cfg(feature = "vaapi")]
|
||||
pub mod vaapi;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, crate::decoders::StatelessBackendError>;
|
||||
pub type Result<T> = crate::decoders::StatelessBackendResult<T>;
|
||||
|
||||
/// The container type for the picture. Pictures must offer interior mutability
|
||||
/// as they may be shared.
|
||||
|
@ -35,12 +33,6 @@ pub type AsBackendHandle<Handle> = <Handle as DecodedHandle>::BackendHandle;
|
|||
/// mode, where it should return immediately with any previously decoded frames
|
||||
/// that happen to be ready.
|
||||
pub(crate) trait StatelessDecoderBackend: VideoDecoderBackend {
|
||||
/// The type that the backend returns as a result of a decode operation.
|
||||
/// This will usually be some backend-specific type with a resource and a
|
||||
/// resource pool so that said buffer can be reused for another decode
|
||||
/// operation when it goes out of scope.
|
||||
type Handle: DecodedHandle;
|
||||
|
||||
/// Called when new stream parameters are found.
|
||||
fn new_sequence(&mut self, header: &Header) -> Result<()>;
|
||||
|
||||
|
@ -60,17 +52,6 @@ pub(crate) trait StatelessDecoderBackend: VideoDecoderBackend {
|
|||
block: bool,
|
||||
) -> Result<Self::Handle>;
|
||||
|
||||
/// Poll for any ready pictures. `block` dictates whether this call should
|
||||
/// block on the operation or return immediately.
|
||||
fn poll(&mut self, blocking_mode: BlockingMode) -> Result<VecDeque<Self::Handle>>;
|
||||
|
||||
/// Whether the handle is ready for presentation. The decoder will check
|
||||
/// this before returning the handle to clients.
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool;
|
||||
|
||||
/// Block on handle `handle`.
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> Result<()>;
|
||||
|
||||
/// Get the test parameters for the backend. The caller is reponsible for
|
||||
/// downcasting them to the correct type, which is backend-dependent.
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
//! run so we can test it in isolation.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::decoders::vp9::backends::StatelessDecoderBackend;
|
||||
|
@ -16,9 +15,7 @@ use crate::decoders::vp9::parser::NUM_REF_FRAMES;
|
|||
use crate::decoders::BlockingMode;
|
||||
use crate::utils::dummy::*;
|
||||
|
||||
impl StatelessDecoderBackend for Backend {
|
||||
type Handle = Handle<Vp9Picture<BackendHandle>>;
|
||||
|
||||
impl StatelessDecoderBackend for Backend<Vp9Picture<BackendHandle>> {
|
||||
fn new_sequence(&mut self, _: &crate::decoders::vp9::parser::Header) -> super::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -36,18 +33,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
})
|
||||
}
|
||||
|
||||
fn poll(&mut self, _: super::BlockingMode) -> super::Result<VecDeque<Self::Handle>> {
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, _: &Self::Handle) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, _: &Self::Handle) -> super::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_test_params(&self) -> &dyn std::any::Any {
|
||||
// There are no test parameters for the dummy backend.
|
||||
|
@ -58,6 +43,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
impl Decoder<Handle<Vp9Picture<BackendHandle>>> {
|
||||
// Creates a new instance of the decoder using the dummy backend.
|
||||
pub fn new_dummy(blocking_mode: BlockingMode) -> anyhow::Result<Self> {
|
||||
Self::new(Box::new(Backend), blocking_mode)
|
||||
Self::new(Box::new(Backend::new()), blocking_mode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,7 @@ use libva::SegmentParameterVP9;
|
|||
use libva::UsageHint;
|
||||
|
||||
use crate::decoders::vp9::backends::AsBackendHandle;
|
||||
use crate::decoders::vp9::backends::BlockingMode;
|
||||
use crate::decoders::vp9::backends::ContainedPicture;
|
||||
use crate::decoders::vp9::backends::DecodedHandle;
|
||||
use crate::decoders::vp9::backends::Result as StatelessBackendResult;
|
||||
use crate::decoders::vp9::backends::StatelessDecoderBackend;
|
||||
use crate::decoders::vp9::backends::Vp9Picture;
|
||||
|
@ -44,6 +42,8 @@ use crate::decoders::vp9::parser::NUM_REF_FRAMES;
|
|||
use crate::decoders::vp9::parser::SEG_LVL_ALT_L;
|
||||
use crate::decoders::vp9::parser::SEG_LVL_REF_FRAME;
|
||||
use crate::decoders::vp9::parser::SEG_LVL_SKIP;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::Error as DecoderError;
|
||||
use crate::decoders::Result as DecoderResult;
|
||||
use crate::decoders::StatelessBackendError;
|
||||
|
@ -60,7 +60,7 @@ use crate::DecodedFormat;
|
|||
use crate::Resolution;
|
||||
|
||||
/// Resolves to the type used as Handle by the backend.
|
||||
type AssociatedHandle = <Backend as StatelessDecoderBackend>::Handle;
|
||||
type AssociatedHandle = <Backend as VideoDecoderBackend>::Handle;
|
||||
|
||||
/// The number of surfaces to allocate for this codec.
|
||||
const NUM_SURFACES: usize = 12;
|
||||
|
@ -582,8 +582,6 @@ impl Backend {
|
|||
}
|
||||
|
||||
impl StatelessDecoderBackend for Backend {
|
||||
type Handle = VADecodedHandle<Vp9Picture<GenericBackendHandle>>;
|
||||
|
||||
fn new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()> {
|
||||
self.open(header, None)?;
|
||||
self.negotiation_status = NegotiationStatus::Possible(Box::new(header.clone()));
|
||||
|
@ -674,81 +672,6 @@ impl StatelessDecoderBackend for Backend {
|
|||
.map_err(|e| StatelessBackendError::Other(anyhow!(e)))
|
||||
}
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
blocking_mode: super::BlockingMode,
|
||||
) -> StatelessBackendResult<VecDeque<Self::Handle>> {
|
||||
let mut completed = VecDeque::new();
|
||||
let candidates = self.pending_jobs.drain(..).collect::<VecDeque<_>>();
|
||||
|
||||
for job in candidates {
|
||||
if matches!(blocking_mode, BlockingMode::NonBlocking) {
|
||||
let status = job.va_picture.query_status()?;
|
||||
if status != libva::VASurfaceStatus::VASurfaceReady {
|
||||
self.pending_jobs.push_back(job);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
completed.push_back(job.codec_picture);
|
||||
}
|
||||
|
||||
let completed = completed.into_iter().map(|picture| {
|
||||
self.build_va_decoded_handle(&picture)
|
||||
.map_err(|e| StatelessBackendError::Other(anyhow!(e)))
|
||||
});
|
||||
|
||||
completed.collect::<Result<VecDeque<_>, StatelessBackendError>>()
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool {
|
||||
match &handle.picture().backend_handle {
|
||||
Some(backend_handle) => backend_handle.is_ready(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
for i in 0..self.pending_jobs.len() {
|
||||
// Remove from the queue in order.
|
||||
let job = &self.pending_jobs[i];
|
||||
|
||||
if Vp9Picture::same(&job.codec_picture, handle.picture_container()) {
|
||||
let job = self.pending_jobs.remove(i).unwrap();
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(StatelessBackendError::Other(anyhow!(
|
||||
"Asked to block on a pending job that doesn't exist"
|
||||
)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_test_params(&self) -> &dyn std::any::Any {
|
||||
&self.test_params
|
||||
|
@ -756,6 +679,8 @@ impl StatelessDecoderBackend for Backend {
|
|||
}
|
||||
|
||||
impl VideoDecoderBackend for Backend {
|
||||
type Handle = VADecodedHandle<Vp9Picture<GenericBackendHandle>>;
|
||||
|
||||
fn coded_resolution(&self) -> Option<Resolution> {
|
||||
self.metadata_state.coded_resolution().ok()
|
||||
}
|
||||
|
@ -813,6 +738,78 @@ impl VideoDecoderBackend for Backend {
|
|||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn poll(&mut self, blocking_mode: BlockingMode) -> DecoderResult<VecDeque<Self::Handle>> {
|
||||
let mut completed = VecDeque::new();
|
||||
let candidates = self.pending_jobs.drain(..).collect::<VecDeque<_>>();
|
||||
|
||||
for job in candidates {
|
||||
if matches!(blocking_mode, BlockingMode::NonBlocking) {
|
||||
let status = job.va_picture.query_status()?;
|
||||
if status != libva::VASurfaceStatus::VASurfaceReady {
|
||||
self.pending_jobs.push_back(job);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
completed.push_back(job.codec_picture);
|
||||
}
|
||||
|
||||
let completed = completed.into_iter().map(|picture| {
|
||||
self.build_va_decoded_handle(&picture)
|
||||
.map_err(|e| DecoderError::from(StatelessBackendError::Other(anyhow!(e))))
|
||||
});
|
||||
|
||||
completed.collect::<Result<VecDeque<_>, _>>()
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, handle: &Self::Handle) -> bool {
|
||||
match &handle.picture().backend_handle {
|
||||
Some(backend_handle) => backend_handle.is_ready(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, handle: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
for i in 0..self.pending_jobs.len() {
|
||||
// Remove from the queue in order.
|
||||
let job = &self.pending_jobs[i];
|
||||
|
||||
if Vp9Picture::same(&job.codec_picture, handle.picture_container()) {
|
||||
let job = self.pending_jobs.remove(i).unwrap();
|
||||
|
||||
let current_picture = job.va_picture.sync()?;
|
||||
|
||||
let map_format = self.metadata_state.map_format()?;
|
||||
|
||||
let backend_handle = GenericBackendHandle::new_ready(
|
||||
current_picture,
|
||||
Rc::clone(map_format),
|
||||
self.metadata_state.display_resolution()?,
|
||||
);
|
||||
|
||||
job.codec_picture.borrow_mut().backend_handle = Some(backend_handle);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(StatelessBackendError::Other(anyhow!(
|
||||
"Asked to block on a pending job that doesn't exist"
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Decoder<VADecodedHandle<Vp9Picture<GenericBackendHandle>>> {
|
||||
|
@ -832,13 +829,13 @@ mod tests {
|
|||
|
||||
use crate::decoders::vp9::backends::vaapi::AssociatedHandle;
|
||||
use crate::decoders::vp9::backends::vaapi::TestParams;
|
||||
use crate::decoders::vp9::backends::BlockingMode;
|
||||
use crate::decoders::vp9::backends::DecodedHandle;
|
||||
use crate::decoders::vp9::backends::StatelessDecoderBackend;
|
||||
use crate::decoders::vp9::decoder::tests::process_ready_frames;
|
||||
use crate::decoders::vp9::decoder::tests::run_decoding_loop;
|
||||
use crate::decoders::vp9::decoder::Decoder;
|
||||
use crate::decoders::vp9::parser::NUM_REF_FRAMES;
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::DynPicture;
|
||||
|
||||
fn get_test_params(
|
||||
|
|
|
@ -6,14 +6,18 @@
|
|||
//! run so we can test it in isolation.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::decoders::BlockingMode;
|
||||
use crate::decoders::DecodedHandle;
|
||||
use crate::decoders::DynPicture;
|
||||
use crate::decoders::FrameInfo;
|
||||
use crate::decoders::MappableHandle;
|
||||
use crate::decoders::Picture;
|
||||
use crate::decoders::Result;
|
||||
use crate::decoders::StatelessBackendResult;
|
||||
use crate::decoders::VideoDecoderBackend;
|
||||
use crate::DecodedFormat;
|
||||
use crate::Resolution;
|
||||
|
@ -68,9 +72,20 @@ impl<T: FrameInfo> DecodedHandle for Handle<Picture<T, BackendHandle>> {
|
|||
}
|
||||
|
||||
/// Dummy backend that can be used for any codec.
|
||||
pub(crate) struct Backend;
|
||||
pub(crate) struct Backend<H>(PhantomData<H>);
|
||||
|
||||
impl<H> Backend<H> {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<H> VideoDecoderBackend for Backend<H>
|
||||
where
|
||||
Handle<H>: DecodedHandle,
|
||||
{
|
||||
type Handle = Handle<H>;
|
||||
|
||||
impl VideoDecoderBackend for Backend {
|
||||
fn num_resources_total(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
@ -94,4 +109,16 @@ impl VideoDecoderBackend for Backend {
|
|||
fn display_resolution(&self) -> Option<Resolution> {
|
||||
None
|
||||
}
|
||||
|
||||
fn poll(&mut self, _: BlockingMode) -> crate::decoders::Result<VecDeque<Self::Handle>> {
|
||||
Ok(VecDeque::new())
|
||||
}
|
||||
|
||||
fn handle_is_ready(&self, _: &Self::Handle) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn block_on_handle(&mut self, _: &Self::Handle) -> StatelessBackendResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue