• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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