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 crate::codec::av1::parser::BitDepth; 6 use crate::codec::av1::parser::CdefParams; 7 use crate::codec::av1::parser::ColorConfig; 8 use crate::codec::av1::parser::FrameHeaderObu; 9 use crate::codec::av1::parser::FrameType; 10 use crate::codec::av1::parser::ObuHeader; 11 use crate::codec::av1::parser::ObuType; 12 use crate::codec::av1::parser::OperatingPoint; 13 use crate::codec::av1::parser::Profile; 14 use crate::codec::av1::parser::QuantizationParams; 15 use crate::codec::av1::parser::ReferenceFrameType; 16 use crate::codec::av1::parser::SequenceHeaderObu; 17 use crate::codec::av1::parser::TemporalDelimiterObu; 18 use crate::codec::av1::parser::TileInfo; 19 use crate::codec::av1::parser::TxMode; 20 use crate::codec::av1::parser::MAX_NUM_OPERATING_POINTS; 21 use crate::codec::av1::parser::MAX_TILE_COLS; 22 use crate::codec::av1::parser::MAX_TILE_ROWS; 23 use crate::codec::av1::parser::PRIMARY_REF_NONE; 24 use crate::codec::av1::parser::REFS_PER_FRAME; 25 use crate::codec::av1::parser::SELECT_INTEGER_MV; 26 use crate::codec::av1::parser::SUPERRES_NUM; 27 use crate::codec::av1::synthesizer::Synthesizer; 28 use crate::encoder::stateless::av1::BackendRequest; 29 use crate::encoder::stateless::av1::EncoderConfig; 30 use crate::encoder::stateless::predictor::LowDelay; 31 use crate::encoder::stateless::predictor::LowDelayDelegate; 32 use crate::encoder::EncodeError; 33 use crate::encoder::EncodeResult; 34 use crate::encoder::FrameMetadata; 35 use crate::encoder::RateControl; 36 use crate::encoder::Tunings; 37 38 // AV1 Spec. Dc_Qlookup max indices 39 pub(crate) const MIN_BASE_QINDEX: u32 = 0; 40 pub(crate) const MAX_BASE_QINDEX: u32 = 255; 41 42 pub(crate) struct LowDelayAV1Delegate { 43 /// Current sequence header obu 44 sequence: SequenceHeaderObu, 45 46 /// Encoder config 47 config: EncoderConfig, 48 } 49 50 pub(crate) type LowDelayAV1<Picture, Reference> = 51 LowDelay<Picture, Reference, LowDelayAV1Delegate, BackendRequest<Picture, Reference>>; 52 53 impl<Picture, Reference> LowDelayAV1<Picture, Reference> { new(config: EncoderConfig, limit: u16) -> Self54 pub fn new(config: EncoderConfig, limit: u16) -> Self { 55 Self { 56 queue: Default::default(), 57 references: Default::default(), 58 counter: 0, 59 limit, 60 tunings: config.initial_tunings.clone(), 61 delegate: LowDelayAV1Delegate { 62 sequence: Self::create_sequence_header(&config), 63 config, 64 }, 65 tunings_queue: Default::default(), 66 _phantom: Default::default(), 67 } 68 } 69 create_sequence_header(config: &EncoderConfig) -> SequenceHeaderObu70 fn create_sequence_header(config: &EncoderConfig) -> SequenceHeaderObu { 71 let width = config.resolution.width; 72 let height = config.resolution.height; 73 74 SequenceHeaderObu { 75 obu_header: ObuHeader { 76 obu_type: ObuType::SequenceHeader, 77 extension_flag: false, 78 has_size_field: true, 79 temporal_id: 0, 80 spatial_id: 0, 81 }, 82 83 seq_profile: Profile::Profile0, 84 num_planes: 3, 85 86 enable_order_hint: true, 87 order_hint_bits: 8, 88 order_hint_bits_minus_1: 8 - 1, 89 90 // Use maximum size (16 bits) 91 frame_width_bits_minus_1: (1 << 4) - 1, 92 frame_height_bits_minus_1: (1 << 4) - 1, 93 94 // Current resolution is the maximum resolution 95 max_frame_width_minus_1: (width - 1) as u16, 96 max_frame_height_minus_1: (height - 1) as u16, 97 98 seq_force_integer_mv: SELECT_INTEGER_MV as u32, 99 100 operating_points: { 101 let mut ops: [OperatingPoint; MAX_NUM_OPERATING_POINTS] = Default::default(); 102 ops[0].idc = 0; 103 // Use highest level 23 for now. 104 // TODO(bgrzesik): approximate level base on resolution and framerate 105 ops[0].seq_level_idx = 23; 106 ops 107 }, 108 109 bit_depth: config.bit_depth, 110 color_config: ColorConfig { 111 // YUV 4:2:0 8-bit or 10-bit 112 high_bitdepth: config.bit_depth == BitDepth::Depth10, 113 mono_chrome: false, 114 subsampling_x: true, 115 subsampling_y: true, 116 ..Default::default() 117 }, 118 119 ..Default::default() 120 } 121 } 122 create_temporal_delimiter() -> TemporalDelimiterObu123 fn create_temporal_delimiter() -> TemporalDelimiterObu { 124 TemporalDelimiterObu { 125 obu_header: ObuHeader { 126 obu_type: ObuType::TemporalDelimiter, 127 extension_flag: false, 128 has_size_field: true, 129 temporal_id: 0, 130 spatial_id: 0, 131 }, 132 } 133 } 134 create_frame_header(&self, frame_type: FrameType) -> EncodeResult<FrameHeaderObu>135 fn create_frame_header(&self, frame_type: FrameType) -> EncodeResult<FrameHeaderObu> { 136 let width = self.delegate.config.resolution.width; 137 let height = self.delegate.config.resolution.height; 138 139 // Superblock size 140 let sb_size = if self.delegate.sequence.use_128x128_superblock { 128 } else { 64 }; 141 142 // Use frame counter for order hinting 143 let order_hint_mask = (1 << self.delegate.sequence.order_hint_bits) - 1; 144 let order_hint = (self.counter & order_hint_mask) as u32; 145 146 let RateControl::ConstantQuality(base_q_idx) = self.tunings.rate_control else { 147 return Err(EncodeError::Unsupported); 148 }; 149 150 // Clamp tunings's quaility range to correct range 151 let min_q_idx = self.tunings.min_quality.max(MIN_BASE_QINDEX); 152 let max_q_idx = self.tunings.max_quality.min(MAX_BASE_QINDEX); 153 154 // Clamp Q index 155 let base_q_idx = base_q_idx.clamp(min_q_idx, max_q_idx); 156 157 // Set the frame size in superblocks for the only tile 158 let mut width_in_sbs_minus_1 = [0u32; MAX_TILE_COLS]; 159 width_in_sbs_minus_1[0] = ((width + sb_size - 1) / sb_size) - 1; 160 161 let mut height_in_sbs_minus_1 = [0u32; MAX_TILE_ROWS]; 162 height_in_sbs_minus_1[0] = ((height + sb_size - 1) / sb_size) - 1; 163 164 Ok(FrameHeaderObu { 165 obu_header: ObuHeader { 166 obu_type: ObuType::FrameHeader, 167 extension_flag: false, 168 has_size_field: true, 169 temporal_id: 0, 170 spatial_id: 0, 171 }, 172 show_frame: true, 173 showable_frame: !matches!(frame_type, FrameType::KeyFrame), 174 frame_type, 175 frame_is_intra: matches!(frame_type, FrameType::KeyFrame | FrameType::IntraOnlyFrame), 176 primary_ref_frame: PRIMARY_REF_NONE, 177 refresh_frame_flags: if matches!(frame_type, FrameType::KeyFrame) { 178 0xff 179 } else { 180 0x01 181 }, 182 183 // Use error resilient mode, and provide the order hints for referencing frame ie. just 184 // previous frame 185 error_resilient_mode: true, 186 order_hint, 187 ref_order_hint: [0, 0, 0, 0, 0, 0, 0, 0], 188 189 reduced_tx_set: true, 190 tx_mode_select: 1, 191 tx_mode: TxMode::Select, 192 193 // Provide the Q index from config 194 quantization_params: QuantizationParams { base_q_idx, ..Default::default() }, 195 196 // Use single tile for now 197 tile_info: TileInfo { 198 uniform_tile_spacing_flag: true, 199 tile_cols: 1, 200 tile_rows: 1, 201 tile_cols_log2: 0, 202 tile_rows_log2: 0, 203 width_in_sbs_minus_1, 204 height_in_sbs_minus_1, 205 ..Default::default() 206 }, 207 208 // CDEF is not used currently, use default value to keep Synthesizer happy 209 cdef_params: CdefParams { cdef_damping: 3, ..Default::default() }, 210 211 // No superres 212 superres_denom: SUPERRES_NUM as u32, 213 upscaled_width: width, 214 frame_width: width, 215 frame_height: height, 216 render_width: width, 217 render_height: height, 218 219 ..Default::default() 220 }) 221 } 222 } 223 224 impl<Picture, Reference> LowDelayDelegate<Picture, Reference, BackendRequest<Picture, Reference>> 225 for LowDelayAV1<Picture, Reference> 226 { request_keyframe( &mut self, input: Picture, input_meta: FrameMetadata, idr: bool, ) -> EncodeResult<BackendRequest<Picture, Reference>>227 fn request_keyframe( 228 &mut self, 229 input: Picture, 230 input_meta: FrameMetadata, 231 idr: bool, 232 ) -> EncodeResult<BackendRequest<Picture, Reference>> { 233 log::trace!("Requested keyframe timestamp={}", input_meta.timestamp); 234 235 let temporal_delim = Self::create_temporal_delimiter(); 236 let sequence = self.delegate.sequence.clone(); 237 let frame = self.create_frame_header(FrameType::KeyFrame)?; 238 239 // This is intra frame, so there is no references 240 let references = [None, None, None, None, None, None, None]; 241 let ref_frame_ctrl_l0 = [ReferenceFrameType::Intra; REFS_PER_FRAME]; 242 let ref_frame_ctrl_l1 = [ReferenceFrameType::Intra; REFS_PER_FRAME]; 243 244 let mut coded_output = Vec::new(); 245 246 // Output Temporal Delimiter, Sequence Header and Frame Header OBUs to bitstream 247 Synthesizer::<'_, TemporalDelimiterObu, _>::synthesize(&temporal_delim, &mut coded_output)?; 248 if idr { 249 Synthesizer::<'_, SequenceHeaderObu, _>::synthesize(&sequence, &mut coded_output)?; 250 } 251 Synthesizer::<'_, FrameHeaderObu, _>::synthesize(&frame, &sequence, &mut coded_output)?; 252 253 let request = BackendRequest { 254 sequence, 255 frame, 256 input, 257 input_meta, 258 references, 259 ref_frame_ctrl_l0, 260 ref_frame_ctrl_l1, 261 intra_period: self.limit as u32, 262 ip_period: 1, 263 tunings: self.tunings.clone(), 264 coded_output, 265 }; 266 267 Ok(request) 268 } 269 request_interframe( &mut self, input: Picture, input_meta: FrameMetadata, ) -> EncodeResult<BackendRequest<Picture, Reference>>270 fn request_interframe( 271 &mut self, 272 input: Picture, 273 input_meta: FrameMetadata, 274 ) -> EncodeResult<BackendRequest<Picture, Reference>> { 275 log::trace!("Requested interframe timestamp={}", input_meta.timestamp); 276 277 let temporal_delim = Self::create_temporal_delimiter(); 278 let sequence = self.delegate.sequence.clone(); 279 let mut frame = self.create_frame_header(FrameType::InterFrame)?; 280 281 // Use previous frame as last frame reference 282 let references = [self.references.front().cloned(), None, None, None, None, None, None]; 283 284 let order_hint_mask = (1 << self.delegate.sequence.order_hint_bits) - 1; 285 let mut ref_frame_ctrl_l0 = [ReferenceFrameType::Intra; REFS_PER_FRAME]; 286 let ref_frame_ctrl_l1 = [ReferenceFrameType::Intra; REFS_PER_FRAME]; 287 288 // Enable previous frame as reference 289 ref_frame_ctrl_l0[0] = ReferenceFrameType::Last; 290 frame.ref_frame_idx[0] = 0; 291 frame.last_frame_idx = 0; 292 frame.ref_order_hint[0] = ((self.counter - 1) & order_hint_mask) as u32; 293 294 let mut coded_output = Vec::new(); 295 296 // Output Temporal Delimiter and Frame Header OBUs to bitstream, marking next frame 297 Synthesizer::<'_, TemporalDelimiterObu, _>::synthesize(&temporal_delim, &mut coded_output)?; 298 Synthesizer::<'_, FrameHeaderObu, _>::synthesize(&frame, &sequence, &mut coded_output)?; 299 300 let request = BackendRequest { 301 sequence, 302 frame, 303 input, 304 input_meta, 305 references, 306 ref_frame_ctrl_l0, 307 ref_frame_ctrl_l1, 308 intra_period: self.limit as u32, 309 ip_period: 1, 310 tunings: self.tunings.clone(), 311 coded_output, 312 }; 313 314 self.references.clear(); 315 316 Ok(request) 317 } 318 try_tunings(&self, _tunings: &Tunings) -> EncodeResult<()>319 fn try_tunings(&self, _tunings: &Tunings) -> EncodeResult<()> { 320 Ok(()) 321 } 322 apply_tunings(&mut self, _tunings: &Tunings) -> EncodeResult<()>323 fn apply_tunings(&mut self, _tunings: &Tunings) -> EncodeResult<()> { 324 Ok(()) 325 } 326 } 327