// Copyright 2024 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. use std::rc::Rc; use crate::codec::vp9::parser::Header; use crate::encoder::stateless::vp9::predictor::LowDelayVP9; use crate::encoder::stateless::BitstreamPromise; use crate::encoder::stateless::Predictor; use crate::encoder::stateless::StatelessBackendResult; use crate::encoder::stateless::StatelessCodec; use crate::encoder::stateless::StatelessEncoderExecute; use crate::encoder::stateless::StatelessVideoEncoderBackend; use crate::encoder::vp9::EncoderConfig; use crate::encoder::vp9::VP9; use crate::encoder::EncodeResult; use crate::encoder::FrameMetadata; use crate::encoder::PredictionStructure; use crate::encoder::Tunings; use crate::BlockingMode; mod predictor; #[cfg(feature = "vaapi")] pub mod vaapi; /// Determines how reference frame shall be used pub enum ReferenceUse { /// The frame will be used for single prediction Single, /// The frame will be used for compound prediction Compound, /// The frame will be used for both single and compound prediction Hybrid, } pub struct BackendRequest { header: Header, /// Input frame to be encoded input: P, /// Input frame metadata input_meta: FrameMetadata, /// Reference frames last_frame_ref: Option<(Rc, ReferenceUse)>, golden_frame_ref: Option<(Rc, ReferenceUse)>, altref_frame_ref: Option<(Rc, ReferenceUse)>, /// [`Tunings`] for the frame tunings: Tunings, /// Container for the request output. [`StatelessVP9EncoderBackend`] impl shall move it and /// append the slice data to it. This prevents unnecessary copying of bitstream around. coded_output: Vec, } impl StatelessCodec for VP9 where Backend: StatelessVideoEncoderBackend, { type Reference = Backend::Reconstructed; type Request = BackendRequest; type CodedPromise = BitstreamPromise; type ReferencePromise = Backend::ReconPromise; } pub trait StatelessVP9EncoderBackend: StatelessVideoEncoderBackend { fn encode_frame( &mut self, request: BackendRequest, ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>; } pub type StatelessEncoder = crate::encoder::stateless::StatelessEncoder; impl StatelessEncoderExecute for StatelessEncoder where Backend: StatelessVP9EncoderBackend, { fn execute( &mut self, request: BackendRequest, ) -> EncodeResult<()> { let meta = request.input_meta.clone(); // The [`BackendRequest`] has a frame from predictor. Decresing internal counter. self.predictor_frame_count -= 1; log::trace!("submitting new request"); let (recon, bitstream) = self.backend.encode_frame(request)?; // Wrap promise from backend with headers and metadata let slice_promise = BitstreamPromise { bitstream, meta }; self.output_queue.add_promise(slice_promise); self.recon_queue.add_promise(recon); Ok(()) } } impl StatelessEncoder where Backend: StatelessVP9EncoderBackend, { fn new_vp9(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult { let predictor: Box> = match config.pred_structure { PredictionStructure::LowDelay { limit } => Box::new(LowDelayVP9::new(config, limit)), }; Self::new(backend, mode, predictor) } }