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::av1::parser::FrameHeaderObu; 8 use crate::codec::av1::parser::ReferenceFrameType; 9 use crate::codec::av1::parser::SequenceHeaderObu; 10 use crate::codec::av1::parser::REFS_PER_FRAME; 11 use crate::encoder::av1::EncoderConfig; 12 use crate::encoder::av1::AV1; 13 use crate::encoder::stateless::av1::predictor::LowDelayAV1; 14 use crate::encoder::stateless::BitstreamPromise; 15 use crate::encoder::stateless::Predictor; 16 use crate::encoder::stateless::StatelessBackendResult; 17 use crate::encoder::stateless::StatelessCodec; 18 use crate::encoder::stateless::StatelessEncoderExecute; 19 use crate::encoder::stateless::StatelessVideoEncoderBackend; 20 use crate::encoder::EncodeResult; 21 use crate::encoder::FrameMetadata; 22 use crate::encoder::PredictionStructure; 23 use crate::encoder::Tunings; 24 use crate::BlockingMode; 25 26 mod predictor; 27 28 #[cfg(feature = "vaapi")] 29 pub mod vaapi; 30 31 pub struct BackendRequest<P, R> { 32 /// Current sequence's header OBU 33 sequence: SequenceHeaderObu, 34 35 /// Current frame OBU contains 36 frame: FrameHeaderObu, 37 38 /// Input frame to be encoded 39 input: P, 40 41 /// Input frame metadata 42 input_meta: FrameMetadata, 43 44 /// References for the frame to be encoded 45 /// Use `ReferenceFrameType::Golden - ReferenceFrameType::Last` for indexing 46 references: [Option<Rc<R>>; REFS_PER_FRAME], 47 48 /// The reference frame search priority list. From highest to lowest 49 /// Use [`ReferenceFrameType::Intra`] for invalid 50 ref_frame_ctrl_l0: [ReferenceFrameType; REFS_PER_FRAME], 51 ref_frame_ctrl_l1: [ReferenceFrameType; REFS_PER_FRAME], 52 53 /// Period between intra frames 54 intra_period: u32, 55 56 /// Period between intra frame and P frame 57 ip_period: u32, 58 59 /// [`Tunings`] for the frame 60 tunings: Tunings, 61 62 /// Container for the request output. [`StatelessAV1EncoderBackend`] impl shall move it and 63 /// append the slice data to it. This prevents unnecessary copying of bitstream around. 64 coded_output: Vec<u8>, 65 } 66 67 impl<Backend> StatelessCodec<Backend> for AV1 68 where 69 Backend: StatelessVideoEncoderBackend<AV1>, 70 { 71 type Reference = Backend::Reconstructed; 72 73 type Request = BackendRequest<Backend::Picture, Backend::Reconstructed>; 74 75 type CodedPromise = BitstreamPromise<Backend::CodedPromise>; 76 77 type ReferencePromise = Backend::ReconPromise; 78 } 79 80 /// Trait for stateless encoder backend for H.264 81 pub trait StatelessAV1EncoderBackend: StatelessVideoEncoderBackend<AV1> { 82 /// Submit a [`BackendRequest`] to the backend. This operation returns both a 83 /// [`StatelessVideoEncoderBackend::ReconPromise`] and a 84 /// [`StatelessVideoEncoderBackend::CodedPromise`] with resulting slice data. encode_tile_group( &mut self, request: BackendRequest<Self::Picture, Self::Reconstructed>, ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>85 fn encode_tile_group( 86 &mut self, 87 request: BackendRequest<Self::Picture, Self::Reconstructed>, 88 ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>; 89 } 90 91 pub type StatelessEncoder<Handle, Backend> = 92 crate::encoder::stateless::StatelessEncoder<AV1, Handle, Backend>; 93 94 impl<Handle, Backend> StatelessEncoderExecute<AV1, Handle, Backend> 95 for StatelessEncoder<Handle, Backend> 96 where 97 Backend: StatelessAV1EncoderBackend, 98 { execute( &mut self, request: BackendRequest<Backend::Picture, Backend::Reconstructed>, ) -> EncodeResult<()>99 fn execute( 100 &mut self, 101 request: BackendRequest<Backend::Picture, Backend::Reconstructed>, 102 ) -> EncodeResult<()> { 103 let meta = request.input_meta.clone(); 104 105 // The [`BackendRequest`] has a frame from predictor. Decresing internal counter. 106 self.predictor_frame_count -= 1; 107 108 log::trace!("submitting new request"); 109 let (recon, bitstream) = self.backend.encode_tile_group(request)?; 110 111 // Wrap promise from backend with headers and metadata 112 let tilegroup_promise = BitstreamPromise { bitstream, meta }; 113 114 self.output_queue.add_promise(tilegroup_promise); 115 116 self.recon_queue.add_promise(recon); 117 118 Ok(()) 119 } 120 } 121 122 impl<Handle, Backend> StatelessEncoder<Handle, Backend> 123 where 124 Backend: StatelessAV1EncoderBackend, 125 { new_av1(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self>126 fn new_av1(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self> { 127 let predictor: Box<dyn Predictor<_, _, _>> = match config.pred_structure { 128 PredictionStructure::LowDelay { limit } => Box::new(LowDelayAV1::new(config, limit)), 129 }; 130 131 Self::new(backend, mode, predictor) 132 } 133 } 134