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::rc::Rc; 6 7 use crate::codec::vp9::parser::Header; 8 use crate::encoder::stateless::vp9::predictor::LowDelayVP9; 9 use crate::encoder::stateless::BitstreamPromise; 10 use crate::encoder::stateless::Predictor; 11 use crate::encoder::stateless::StatelessBackendResult; 12 use crate::encoder::stateless::StatelessCodec; 13 use crate::encoder::stateless::StatelessEncoderExecute; 14 use crate::encoder::stateless::StatelessVideoEncoderBackend; 15 use crate::encoder::vp9::EncoderConfig; 16 use crate::encoder::vp9::VP9; 17 use crate::encoder::EncodeResult; 18 use crate::encoder::FrameMetadata; 19 use crate::encoder::PredictionStructure; 20 use crate::encoder::Tunings; 21 use crate::BlockingMode; 22 23 mod predictor; 24 25 #[cfg(feature = "vaapi")] 26 pub mod vaapi; 27 28 /// Determines how reference frame shall be used 29 pub enum ReferenceUse { 30 /// The frame will be used for single prediction 31 Single, 32 /// The frame will be used for compound prediction 33 Compound, 34 /// The frame will be used for both single and compound prediction 35 Hybrid, 36 } 37 38 pub struct BackendRequest<P, R> { 39 header: Header, 40 41 /// Input frame to be encoded 42 input: P, 43 44 /// Input frame metadata 45 input_meta: FrameMetadata, 46 47 /// Reference frames 48 last_frame_ref: Option<(Rc<R>, ReferenceUse)>, 49 golden_frame_ref: Option<(Rc<R>, ReferenceUse)>, 50 altref_frame_ref: Option<(Rc<R>, ReferenceUse)>, 51 52 /// [`Tunings`] for the frame 53 tunings: Tunings, 54 55 /// Container for the request output. [`StatelessVP9EncoderBackend`] impl shall move it and 56 /// append the slice data to it. This prevents unnecessary copying of bitstream around. 57 coded_output: Vec<u8>, 58 } 59 60 impl<Backend> StatelessCodec<Backend> for VP9 61 where 62 Backend: StatelessVideoEncoderBackend<VP9>, 63 { 64 type Reference = Backend::Reconstructed; 65 66 type Request = BackendRequest<Backend::Picture, Backend::Reconstructed>; 67 68 type CodedPromise = BitstreamPromise<Backend::CodedPromise>; 69 70 type ReferencePromise = Backend::ReconPromise; 71 } 72 73 pub trait StatelessVP9EncoderBackend: StatelessVideoEncoderBackend<VP9> { encode_frame( &mut self, request: BackendRequest<Self::Picture, Self::Reconstructed>, ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>74 fn encode_frame( 75 &mut self, 76 request: BackendRequest<Self::Picture, Self::Reconstructed>, 77 ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>; 78 } 79 80 pub type StatelessEncoder<Handle, Backend> = 81 crate::encoder::stateless::StatelessEncoder<VP9, Handle, Backend>; 82 83 impl<Handle, Backend> StatelessEncoderExecute<VP9, Handle, Backend> 84 for StatelessEncoder<Handle, Backend> 85 where 86 Backend: StatelessVP9EncoderBackend, 87 { execute( &mut self, request: BackendRequest<Backend::Picture, Backend::Reconstructed>, ) -> EncodeResult<()>88 fn execute( 89 &mut self, 90 request: BackendRequest<Backend::Picture, Backend::Reconstructed>, 91 ) -> EncodeResult<()> { 92 let meta = request.input_meta.clone(); 93 94 // The [`BackendRequest`] has a frame from predictor. Decresing internal counter. 95 self.predictor_frame_count -= 1; 96 97 log::trace!("submitting new request"); 98 let (recon, bitstream) = self.backend.encode_frame(request)?; 99 100 // Wrap promise from backend with headers and metadata 101 let slice_promise = BitstreamPromise { bitstream, meta }; 102 103 self.output_queue.add_promise(slice_promise); 104 105 self.recon_queue.add_promise(recon); 106 107 Ok(()) 108 } 109 } 110 111 impl<Handle, Backend> StatelessEncoder<Handle, Backend> 112 where 113 Backend: StatelessVP9EncoderBackend, 114 { new_vp9(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self>115 fn new_vp9(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self> { 116 let predictor: Box<dyn Predictor<_, _, _>> = match config.pred_structure { 117 PredictionStructure::LowDelay { limit } => Box::new(LowDelayVP9::new(config, limit)), 118 }; 119 120 Self::new(backend, mode, predictor) 121 } 122 } 123