cros_codecs/encoder/stateless/
h264.rs1use std::rc::Rc;
6
7use crate::codec::h264::parser::Pps;
8use crate::codec::h264::parser::SliceHeader;
9use crate::codec::h264::parser::Sps;
10use crate::encoder::h264::EncoderConfig;
11use crate::encoder::h264::H264;
12use crate::encoder::stateless::h264::predictor::LowDelayH264;
13use crate::encoder::stateless::BackendPromise;
14use crate::encoder::stateless::BitstreamPromise;
15use crate::encoder::stateless::FrameMetadata;
16use crate::encoder::stateless::Predictor;
17use crate::encoder::stateless::StatelessBackendResult;
18use crate::encoder::stateless::StatelessCodec;
19use crate::encoder::stateless::StatelessEncoderBackendImport;
20use crate::encoder::stateless::StatelessEncoderExecute;
21use crate::encoder::stateless::StatelessVideoEncoderBackend;
22use crate::encoder::EncodeResult;
23use crate::encoder::PredictionStructure;
24use crate::encoder::Tunings;
25use crate::BlockingMode;
26
27mod predictor;
28
29#[cfg(feature = "vaapi")]
30pub mod vaapi;
31
32#[derive(Copy, Clone, PartialEq, Eq, Debug)]
33pub enum IsReference {
34 No,
35 ShortTerm,
36 LongTerm,
37}
38
39#[derive(Clone, Debug)]
40pub struct DpbEntryMeta {
41 poc: u16,
43 frame_num: u32,
44 is_reference: IsReference,
45}
46
47pub struct DpbEntry<R> {
50 recon_pic: R,
52 meta: DpbEntryMeta,
54}
55
56pub struct BackendRequest<P, R> {
58 sps: Rc<Sps>,
59 pps: Rc<Pps>,
60 header: SliceHeader,
61
62 input: P,
64
65 input_meta: FrameMetadata,
67
68 dpb_meta: DpbEntryMeta,
70
71 ref_list_0: Vec<Rc<DpbEntry<R>>>,
73 ref_list_1: Vec<Rc<DpbEntry<R>>>,
74
75 intra_period: u32,
77
78 ip_period: u32,
80
81 num_macroblocks: usize,
83
84 is_idr: bool,
86
87 tunings: Tunings,
89
90 coded_output: Vec<u8>,
93}
94
95pub struct ReferencePromise<P>
98where
99 P: BackendPromise,
100{
101 recon: P,
103
104 dpb_meta: DpbEntryMeta,
106}
107
108impl<P> BackendPromise for ReferencePromise<P>
109where
110 P: BackendPromise,
111{
112 type Output = DpbEntry<P::Output>;
113
114 fn is_ready(&self) -> bool {
115 self.recon.is_ready()
116 }
117
118 fn sync(self) -> StatelessBackendResult<Self::Output> {
119 let recon_pic = self.recon.sync()?;
120
121 log::trace!("synced recon picture frame_num={}", self.dpb_meta.frame_num);
122
123 Ok(DpbEntry {
124 recon_pic,
125 meta: self.dpb_meta,
126 })
127 }
128}
129
130impl<Backend> StatelessCodec<Backend> for H264
131where
132 Backend: StatelessVideoEncoderBackend<H264>,
133{
134 type Reference = DpbEntry<Backend::Reconstructed>;
135
136 type Request = BackendRequest<Backend::Picture, Backend::Reconstructed>;
137
138 type CodedPromise = BitstreamPromise<Backend::CodedPromise>;
139
140 type ReferencePromise = ReferencePromise<Backend::ReconPromise>;
141}
142
143pub trait StatelessH264EncoderBackend: StatelessVideoEncoderBackend<H264> {
145 fn encode_slice(
149 &mut self,
150 request: BackendRequest<Self::Picture, Self::Reconstructed>,
151 ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>;
152}
153
154pub type StatelessEncoder<Handle, Backend> =
155 crate::encoder::stateless::StatelessEncoder<H264, Handle, Backend>;
156
157impl<Handle, Backend> StatelessEncoderExecute<H264, Handle, Backend>
158 for StatelessEncoder<Handle, Backend>
159where
160 Backend: StatelessH264EncoderBackend,
161{
162 fn execute(
163 &mut self,
164 request: BackendRequest<Backend::Picture, Backend::Reconstructed>,
165 ) -> EncodeResult<()> {
166 let meta = request.input_meta.clone();
167 let dpb_meta = request.dpb_meta.clone();
168
169 self.predictor_frame_count -= 1;
171
172 log::trace!("submitting new request");
173 let (recon, bitstream) = self.backend.encode_slice(request)?;
174
175 let slice_promise = BitstreamPromise { bitstream, meta };
177
178 self.output_queue.add_promise(slice_promise);
179
180 let ref_promise = ReferencePromise { recon, dpb_meta };
181
182 self.recon_queue.add_promise(ref_promise);
183
184 Ok(())
185 }
186}
187
188impl<Handle, Backend> StatelessEncoder<Handle, Backend>
189where
190 Backend: StatelessH264EncoderBackend,
191 Backend: StatelessEncoderBackendImport<Handle, Backend::Picture>,
192{
193 fn new_h264(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self> {
194 let predictor: Box<dyn Predictor<_, _, _>> = match config.pred_structure {
195 PredictionStructure::LowDelay { limit } => Box::new(LowDelayH264::new(config, limit)),
196 };
197
198 Self::new(backend, mode, predictor)
199 }
200}