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::collections::VecDeque; 6 use std::rc::Rc; 7 8 use crate::encoder::stateless::Predictor; 9 use crate::encoder::EncodeError; 10 use crate::encoder::EncodeResult; 11 use crate::encoder::FrameMetadata; 12 use crate::encoder::RateControl; 13 use crate::encoder::Tunings; 14 15 /// Implementation of [`LowDelay`] prediction structure. See [`LowDelay`] for details. 16 /// 17 /// [`LowDelay`]: crate::encoder::PredictionStructure::LowDelay 18 pub(crate) struct LowDelay<Picture, Reference, Delegate, Request> { 19 /// Pending frames for encoding 20 pub(super) queue: VecDeque<(Picture, FrameMetadata)>, 21 22 /// Availabe frames for references 23 pub(super) references: VecDeque<Rc<Reference>>, 24 25 /// Current frame counter 26 pub(super) counter: usize, 27 28 /// The number of frames between intra frames 29 pub(super) limit: u16, 30 31 /// Codec specific delegate. Holds codec specific state. Is also used to differentiate 32 /// [`LowDelay`] implementations between codecs. 33 pub(super) delegate: Delegate, 34 35 /// Currently set tunings for the stream 36 pub(super) tunings: Tunings, 37 38 /// Pending [`Tunings`] to be applied with `counter` value when to set them. 39 /// In this way we ensure that the requested frames prior tuning request are encoded using 40 /// previous tunings. This is especially important for bitrate, this way we ensure the bitrate 41 /// changes when requested. 42 pub(super) tunings_queue: VecDeque<(usize, Tunings)>, 43 44 pub(super) _phantom: std::marker::PhantomData<Request>, 45 } 46 47 /// Helper trait enabling forcing [`LowDelay`] to implement codec specific functions. 48 pub(crate) trait LowDelayDelegate<Picture, Reference, Request> { 49 /// Creates keyframe or IDR request for the codec backend request_keyframe( &mut self, input: Picture, input_meta: FrameMetadata, idr: bool, ) -> EncodeResult<Request>50 fn request_keyframe( 51 &mut self, 52 input: Picture, 53 input_meta: FrameMetadata, 54 idr: bool, 55 ) -> EncodeResult<Request>; 56 57 /// Creates interframe request for the codec backend request_interframe( &mut self, input: Picture, input_meta: FrameMetadata, ) -> EncodeResult<Request>58 fn request_interframe( 59 &mut self, 60 input: Picture, 61 input_meta: FrameMetadata, 62 ) -> EncodeResult<Request>; 63 64 /// Checks if the `_tunings` can be applied try_tunings(&self, _tunings: &Tunings) -> EncodeResult<()>65 fn try_tunings(&self, _tunings: &Tunings) -> EncodeResult<()> { 66 Err(EncodeError::Unsupported) 67 } 68 69 /// Applies `_tunings` apply_tunings(&mut self, _tunings: &Tunings) -> EncodeResult<()>70 fn apply_tunings(&mut self, _tunings: &Tunings) -> EncodeResult<()> { 71 Err(EncodeError::Unsupported) 72 } 73 } 74 75 impl<Picture, Reference, Delegate, Request> LowDelay<Picture, Reference, Delegate, Request> 76 where 77 Self: LowDelayDelegate<Picture, Reference, Request>, 78 { pop_tunings(&mut self) -> EncodeResult<()>79 fn pop_tunings(&mut self) -> EncodeResult<()> { 80 while let Some((when_counter, _)) = self.tunings_queue.front() { 81 if self.counter < *when_counter { 82 log::trace!( 83 "Pending tuning skipped counter={} scheduled={}", 84 self.counter, 85 when_counter 86 ); 87 break; 88 } 89 90 // SAFETY: checked in loop condition 91 let (_, tunings) = self.tunings_queue.pop_front().unwrap(); 92 log::info!("Applying tuning {tunings:?}"); 93 self.apply_tunings(&tunings)?; 94 self.tunings = tunings; 95 } 96 97 Ok(()) 98 } 99 next_request(&mut self) -> EncodeResult<Vec<Request>>100 fn next_request(&mut self) -> EncodeResult<Vec<Request>> { 101 log::trace!("Pending frames in the queue: {}", self.queue.len()); 102 103 let mut requests = Vec::new(); 104 while let Some((input, meta)) = self.queue.pop_front() { 105 self.pop_tunings()?; 106 107 if self.counter == 0 || meta.force_keyframe { 108 log::trace!("Requesting keyframe/IDR for timestamp={}", meta.timestamp); 109 // If first frame in the sequence or forced IDR then clear references and create 110 // keyframe request. 111 // TODO: Maybe don't clear references on just keyframe (!= IDR) 112 self.references.clear(); 113 114 let request = self.request_keyframe(input, meta, self.counter == 0)?; 115 116 requests.push(request); 117 self.counter = self.counter.wrapping_add(1) % (self.limit as usize); 118 } else if self.references.is_empty() { 119 log::trace!("Awaiting more reconstructed frames"); 120 // There is no enough frames reconstructed 121 self.queue.push_front((input, meta)); 122 break; 123 } else { 124 log::trace!("Requesting interframe for timestamp={}", meta.timestamp); 125 let request = self.request_interframe(input, meta)?; 126 127 requests.push(request); 128 self.counter = self.counter.wrapping_add(1) % (self.limit as usize); 129 130 break; 131 } 132 } 133 134 Ok(requests) 135 } 136 } 137 138 impl<Picture, Reference, Delegate, Request> Predictor<Picture, Reference, Request> 139 for LowDelay<Picture, Reference, Delegate, Request> 140 where 141 Self: LowDelayDelegate<Picture, Reference, Request>, 142 { new_frame( &mut self, input: Picture, frame_metadata: FrameMetadata, ) -> EncodeResult<Vec<Request>>143 fn new_frame( 144 &mut self, 145 input: Picture, 146 frame_metadata: FrameMetadata, 147 ) -> EncodeResult<Vec<Request>> { 148 log::trace!("New frame added to queue timestamp={}", frame_metadata.timestamp); 149 // Add new frame in the request queue and request new encoding if possible 150 self.queue.push_back((input, frame_metadata)); 151 self.next_request() 152 } 153 reconstructed(&mut self, reference: Reference) -> EncodeResult<Vec<Request>>154 fn reconstructed(&mut self, reference: Reference) -> EncodeResult<Vec<Request>> { 155 log::trace!("A frame was reconstructed"); 156 // Add new reconstructed surface and request next encoding if possible 157 self.references.push_back(Rc::new(reference)); 158 self.next_request() 159 } 160 tune(&mut self, tunings: Tunings) -> EncodeResult<()>161 fn tune(&mut self, tunings: Tunings) -> EncodeResult<()> { 162 log::trace!("Tuning requested with {tunings:?}"); 163 if !RateControl::is_same_variant(&self.tunings.rate_control, &tunings.rate_control) { 164 // TODO(bgrzesik): consider enabling switching between RateControl variants 165 log::error!("Changing RateControl variant is not supported at the moment"); 166 return Err(EncodeError::Unsupported); 167 } 168 169 // Check if the tunings are or will be the same, in such case we skip. 170 let skip = match self.tunings_queue.front() { 171 Some((_, preceeding_tunnings)) if preceeding_tunnings == &tunings => true, 172 None if self.tunings == tunings => true, 173 _ => false, 174 }; 175 176 if skip { 177 log::debug!("Tuning skipped, the requested values are the same."); 178 return Ok(()); 179 } 180 181 // Check if applying tunings will succeed. 182 self.try_tunings(&tunings)?; 183 184 let when_counter = self.counter + self.queue.len(); 185 self.tunings_queue.push_back((when_counter, tunings)); 186 187 Ok(()) 188 } 189 drain(&mut self) -> EncodeResult<Vec<Request>>190 fn drain(&mut self) -> EncodeResult<Vec<Request>> { 191 // [`LowDelay`] will not hold any frames, therefore the drain function shall never be called. 192 Err(EncodeError::InvalidInternalState) 193 } 194 } 195 196 #[cfg(test)] 197 mod tests { 198 use crate::Fourcc; 199 200 use super::*; 201 202 #[derive(Debug, PartialEq, Eq)] 203 enum MockRequest { 204 KeyFrameRequest(u32, Tunings), 205 InterframerRequest(u32, Tunings), 206 } 207 208 struct MockDelegate; 209 210 impl LowDelayDelegate<u32, u32, MockRequest> for LowDelay<u32, u32, MockDelegate, MockRequest> { request_interframe( &mut self, input: u32, _input_meta: FrameMetadata, ) -> EncodeResult<MockRequest>211 fn request_interframe( 212 &mut self, 213 input: u32, 214 _input_meta: FrameMetadata, 215 ) -> EncodeResult<MockRequest> { 216 Ok(MockRequest::InterframerRequest(input, self.tunings.clone())) 217 } 218 request_keyframe( &mut self, input: u32, _input_meta: FrameMetadata, _idr: bool, ) -> EncodeResult<MockRequest>219 fn request_keyframe( 220 &mut self, 221 input: u32, 222 _input_meta: FrameMetadata, 223 _idr: bool, 224 ) -> EncodeResult<MockRequest> { 225 Ok(MockRequest::KeyFrameRequest(input, self.tunings.clone())) 226 } 227 try_tunings(&self, _tunings: &Tunings) -> EncodeResult<()>228 fn try_tunings(&self, _tunings: &Tunings) -> EncodeResult<()> { 229 Ok(()) 230 } 231 apply_tunings(&mut self, _tunings: &Tunings) -> EncodeResult<()>232 fn apply_tunings(&mut self, _tunings: &Tunings) -> EncodeResult<()> { 233 Ok(()) 234 } 235 } 236 dummy_frame_meta(timestamp: u64, force_keyframe: bool) -> FrameMetadata237 fn dummy_frame_meta(timestamp: u64, force_keyframe: bool) -> FrameMetadata { 238 FrameMetadata { 239 timestamp, 240 layout: crate::FrameLayout { 241 format: (Fourcc::from(b"NV12"), 0), 242 size: crate::Resolution { width: 0, height: 0 }, 243 planes: vec![], 244 }, 245 force_keyframe, 246 } 247 } 248 249 /// This test ensures that Tunings change applies to only frames following the change 250 #[test] test_tuning_delay()251 fn test_tuning_delay() { 252 let _ = env_logger::try_init(); 253 254 let tunings_prev = Tunings { framerate: 1, ..Default::default() }; 255 256 let mut predictor: LowDelay<u32, u32, MockDelegate, MockRequest> = LowDelay { 257 queue: Default::default(), 258 references: Default::default(), 259 counter: 0, 260 limit: 1028, 261 delegate: MockDelegate, 262 tunings: tunings_prev.clone(), 263 tunings_queue: Default::default(), 264 _phantom: Default::default(), 265 }; 266 267 let mut requests = Vec::new(); 268 269 requests.extend(predictor.new_frame(0, dummy_frame_meta(0, false)).unwrap()); 270 requests.extend(predictor.new_frame(1, dummy_frame_meta(1, false)).unwrap()); 271 requests.extend(predictor.new_frame(2, dummy_frame_meta(2, false)).unwrap()); 272 requests.extend(predictor.new_frame(3, dummy_frame_meta(3, false)).unwrap()); 273 274 let tunings_next = Tunings { framerate: 2, ..Default::default() }; 275 276 predictor.tune(tunings_next.clone()).unwrap(); 277 278 assert_eq!(predictor.tunings, tunings_prev); 279 280 requests.extend(predictor.new_frame(4, dummy_frame_meta(4, false)).unwrap()); 281 282 requests.extend(predictor.reconstructed(0).unwrap()); 283 requests.extend(predictor.reconstructed(1).unwrap()); 284 requests.extend(predictor.reconstructed(2).unwrap()); 285 286 assert_eq!(predictor.tunings, tunings_prev); 287 requests.extend(predictor.reconstructed(3).unwrap()); 288 289 assert_eq!(predictor.tunings, tunings_next); 290 requests.extend(predictor.reconstructed(4).unwrap()); 291 292 assert_eq!( 293 requests, 294 vec![ 295 MockRequest::KeyFrameRequest(0, tunings_prev.clone()), 296 MockRequest::InterframerRequest(1, tunings_prev.clone()), 297 MockRequest::InterframerRequest(2, tunings_prev.clone()), 298 MockRequest::InterframerRequest(3, tunings_prev.clone()), 299 MockRequest::InterframerRequest(4, tunings_next.clone()), 300 ] 301 ); 302 } 303 304 #[test] test_keyframes()305 fn test_keyframes() { 306 const FRAME_COUNT: u32 = 1028; 307 const IDR_PERIOD: u16 = 37; 308 const KEYFRAME_REQUEST_PERIOD: u32 = 31; 309 310 let _ = env_logger::try_init(); 311 312 let tunings = Tunings::default(); 313 let mut predictor: LowDelay<u32, u32, MockDelegate, MockRequest> = LowDelay { 314 queue: Default::default(), 315 references: Default::default(), 316 counter: 0, 317 limit: IDR_PERIOD, 318 delegate: MockDelegate, 319 tunings: tunings.clone(), 320 tunings_queue: Default::default(), 321 _phantom: Default::default(), 322 }; 323 324 let mut requests = Vec::new(); 325 326 for i in 0..FRAME_COUNT { 327 let keyframe = i % KEYFRAME_REQUEST_PERIOD == 0; 328 requests.extend(predictor.new_frame(i, dummy_frame_meta(i as u64, keyframe)).unwrap()); 329 } 330 331 for i in 0..FRAME_COUNT { 332 requests.extend(predictor.reconstructed(i).unwrap()); 333 } 334 335 let mut expected = Vec::new(); 336 for i in 0..FRAME_COUNT { 337 if (i % IDR_PERIOD as u32 == 0) || (i % KEYFRAME_REQUEST_PERIOD) == 0 { 338 expected.push(MockRequest::KeyFrameRequest(i, tunings.clone())); 339 } else { 340 expected.push(MockRequest::InterframerRequest(i, tunings.clone())); 341 } 342 } 343 344 assert_eq!(requests, expected); 345 } 346 } 347