1 // Copyright 2025 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::marker::PhantomData; 6 7 use v4l2r::bindings::v4l2_ctrl_av1_film_grain; 8 use v4l2r::bindings::v4l2_ctrl_av1_frame; 9 use v4l2r::bindings::v4l2_ctrl_av1_sequence; 10 use v4l2r::bindings::v4l2_ctrl_av1_tile_group_entry; 11 use v4l2r::bindings::v4l2_ext_control; 12 use v4l2r::bindings::v4l2_ext_control__bindgen_ty_1; 13 use v4l2r::bindings::V4L2_AV1_AR_COEFFS_SIZE; 14 use v4l2r::bindings::V4L2_AV1_CDEF_MAX; 15 use v4l2r::bindings::V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN; 16 use v4l2r::bindings::V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA; 17 use v4l2r::bindings::V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE; 18 use v4l2r::bindings::V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP; 19 use v4l2r::bindings::V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN; 20 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV; 21 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC; 22 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS; 23 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION; 24 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT; 25 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE; 26 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF; 27 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE; 28 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV; 29 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING; 30 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE; 31 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE; 32 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET; 33 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT; 34 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME; 35 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_SHOW_FRAME; 36 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED; 37 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT; 38 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS; 39 use v4l2r::bindings::V4L2_AV1_FRAME_FLAG_USE_SUPERRES; 40 use v4l2r::bindings::V4L2_AV1_GLOBAL_MOTION_FLAG_IS_GLOBAL; 41 use v4l2r::bindings::V4L2_AV1_GLOBAL_MOTION_FLAG_IS_ROT_ZOOM; 42 use v4l2r::bindings::V4L2_AV1_GLOBAL_MOTION_FLAG_IS_TRANSLATION; 43 use v4l2r::bindings::V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED; 44 use v4l2r::bindings::V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI; 45 use v4l2r::bindings::V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT; 46 use v4l2r::bindings::V4L2_AV1_LOOP_FILTER_FLAG_DELTA_UPDATE; 47 use v4l2r::bindings::V4L2_AV1_LOOP_RESTORATION_FLAG_USES_CHROMA_LR; 48 use v4l2r::bindings::V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR; 49 use v4l2r::bindings::V4L2_AV1_MAX_NUM_CB_POINTS; 50 use v4l2r::bindings::V4L2_AV1_MAX_NUM_CR_POINTS; 51 use v4l2r::bindings::V4L2_AV1_MAX_NUM_Y_POINTS; 52 use v4l2r::bindings::V4L2_AV1_MAX_OPERATING_POINTS; 53 use v4l2r::bindings::V4L2_AV1_MAX_SEGMENTS; 54 use v4l2r::bindings::V4L2_AV1_MAX_TILE_COLS; 55 use v4l2r::bindings::V4L2_AV1_MAX_TILE_ROWS; 56 use v4l2r::bindings::V4L2_AV1_NUM_PLANES_MAX; 57 use v4l2r::bindings::V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT; 58 use v4l2r::bindings::V4L2_AV1_QUANTIZATION_FLAG_DIFF_UV_DELTA; 59 use v4l2r::bindings::V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX; 60 use v4l2r::bindings::V4L2_AV1_REFS_PER_FRAME; 61 use v4l2r::bindings::V4L2_AV1_SEGMENTATION_FLAG_ENABLED; 62 use v4l2r::bindings::V4L2_AV1_SEGMENTATION_FLAG_SEG_ID_PRE_SKIP; 63 use v4l2r::bindings::V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE; 64 use v4l2r::bindings::V4L2_AV1_SEGMENTATION_FLAG_UPDATE_DATA; 65 use v4l2r::bindings::V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP; 66 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE; 67 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF; 68 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER; 69 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA; 70 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND; 71 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER; 72 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP; 73 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND; 74 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT; 75 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS; 76 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION; 77 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES; 78 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION; 79 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT; 80 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME; 81 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q; 82 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE; 83 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X; 84 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y; 85 use v4l2r::bindings::V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK; 86 use v4l2r::bindings::V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING; 87 use v4l2r::bindings::V4L2_AV1_TOTAL_REFS_PER_FRAME; 88 use v4l2r::bindings::V4L2_CID_STATELESS_AV1_FILM_GRAIN; 89 use v4l2r::bindings::V4L2_CID_STATELESS_AV1_FRAME; 90 use v4l2r::bindings::V4L2_CID_STATELESS_AV1_SEQUENCE; 91 use v4l2r::bindings::V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY; 92 use v4l2r::controls::AsV4l2ControlSlice; 93 94 use crate::codec::av1::parser::BitDepth; 95 use crate::codec::av1::parser::CdefParams; 96 use crate::codec::av1::parser::FrameHeaderObu; 97 use crate::codec::av1::parser::FrameRestorationType; 98 use crate::codec::av1::parser::GlobalMotionParams; 99 use crate::codec::av1::parser::LoopFilterParams; 100 use crate::codec::av1::parser::LoopRestorationParams; 101 use crate::codec::av1::parser::QuantizationParams; 102 use crate::codec::av1::parser::SegmentationParams; 103 use crate::codec::av1::parser::SequenceHeaderObu; 104 use crate::codec::av1::parser::Tile; 105 use crate::codec::av1::parser::WarpModelType; 106 107 // v4l2r does not have V4L2_AV1_SEG_LVL_MAX 108 //use v4l2r::bindings::V4L2_AV1_SEG_LVL_MAX; 109 const V4L2_AV1_SEG_LVL_MAX: u32 = 8; 110 111 #[derive(Default)] 112 pub struct V4l2CtrlAv1FilmGrainParams { 113 handle: v4l2_ctrl_av1_film_grain, 114 } 115 116 impl V4l2CtrlAv1FilmGrainParams { new() -> Self117 pub fn new() -> Self { 118 Default::default() 119 } 120 set_film_grain_params(&mut self, hdr: &FrameHeaderObu) -> &mut Self121 pub fn set_film_grain_params(&mut self, hdr: &FrameHeaderObu) -> &mut Self { 122 let fg = &hdr.film_grain_params; 123 124 if fg.apply_grain { 125 log::warn!("Film grain is not officially supported yet.") 126 } 127 128 self.handle.flags = 0; 129 if fg.apply_grain { 130 self.handle.flags |= V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN as u8; 131 } 132 133 if fg.update_grain { 134 self.handle.flags |= V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN as u8; 135 } 136 137 if fg.chroma_scaling_from_luma { 138 self.handle.flags |= V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA as u8; 139 } 140 141 if fg.overlap_flag { 142 self.handle.flags |= V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP as u8; 143 } 144 145 if fg.clip_to_restricted_range { 146 self.handle.flags |= V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE as u8; 147 } 148 149 self.handle.cr_mult = fg.cr_mult; 150 self.handle.grain_seed = fg.grain_seed; 151 self.handle.film_grain_params_ref_idx = fg.film_grain_params_ref_idx; 152 self.handle.num_y_points = fg.num_y_points; 153 self.handle 154 .point_y_value 155 .copy_from_slice(&fg.point_y_scaling[0..V4L2_AV1_MAX_NUM_Y_POINTS as usize]); 156 self.handle 157 .point_y_scaling 158 .copy_from_slice(&fg.point_y_scaling[0..V4L2_AV1_MAX_NUM_Y_POINTS as usize]); 159 self.handle.num_cb_points = fg.num_cb_points; 160 self.handle 161 .point_cb_value 162 .copy_from_slice(&fg.point_cb_value[0..V4L2_AV1_MAX_NUM_CB_POINTS as usize]); 163 self.handle 164 .point_cb_scaling 165 .copy_from_slice(&fg.point_cb_scaling[0..V4L2_AV1_MAX_NUM_CB_POINTS as usize]); 166 self.handle.num_cr_points = fg.num_cr_points; 167 self.handle 168 .point_cr_value 169 .copy_from_slice(&fg.point_cr_value[0..V4L2_AV1_MAX_NUM_CR_POINTS as usize]); 170 self.handle 171 .point_cr_scaling 172 .copy_from_slice(&fg.point_cr_scaling[0..V4L2_AV1_MAX_NUM_CR_POINTS as usize]); 173 self.handle.grain_scaling_minus_8 = fg.grain_scaling_minus_8; 174 self.handle.ar_coeff_lag = fg.ar_coeff_lag as u8; 175 self.handle 176 .ar_coeffs_y_plus_128 177 .copy_from_slice(&fg.ar_coeffs_y_plus_128[0..V4L2_AV1_AR_COEFFS_SIZE as usize]); 178 self.handle 179 .ar_coeffs_cb_plus_128 180 .copy_from_slice(&fg.ar_coeffs_cb_plus_128[0..V4L2_AV1_AR_COEFFS_SIZE as usize]); 181 self.handle 182 .ar_coeffs_cr_plus_128 183 .copy_from_slice(&fg.ar_coeffs_cr_plus_128[0..V4L2_AV1_AR_COEFFS_SIZE as usize]); 184 self.handle.ar_coeff_shift_minus_6 = fg.ar_coeff_shift_minus_6; 185 self.handle.grain_scale_shift = fg.grain_scale_shift; 186 self.handle.cb_mult = fg.cb_mult; 187 self.handle.cb_luma_mult = fg.cb_luma_mult; 188 self.handle.cr_luma_mult = fg.cr_luma_mult; 189 self.handle.cb_offset = fg.cb_offset; 190 self.handle.cr_offset = fg.cr_offset; 191 self 192 } 193 } 194 195 #[derive(Default)] 196 pub struct V4l2CtrlAv1FrameParams { 197 handle: v4l2_ctrl_av1_frame, 198 } 199 200 impl V4l2CtrlAv1FrameParams { new() -> Self201 pub fn new() -> Self { 202 Default::default() 203 } 204 set_reference_frame_ts( &mut self, reference_ts: [u64; V4L2_AV1_TOTAL_REFS_PER_FRAME as usize], ) -> &mut Self205 pub fn set_reference_frame_ts( 206 &mut self, 207 reference_ts: [u64; V4L2_AV1_TOTAL_REFS_PER_FRAME as usize], 208 ) -> &mut Self { 209 for i in 0..V4L2_AV1_TOTAL_REFS_PER_FRAME as usize { 210 self.handle.reference_frame_ts[i] = reference_ts[i] * 1000; 211 } 212 self 213 } 214 set_tile_info_params(&mut self, hdr: &FrameHeaderObu) -> &mut Self215 pub fn set_tile_info_params(&mut self, hdr: &FrameHeaderObu) -> &mut Self { 216 let tile_info = &hdr.tile_info; 217 if tile_info.uniform_tile_spacing_flag { 218 self.handle.tile_info.flags |= V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING as u8; 219 } 220 self.handle.tile_info.context_update_tile_id = tile_info.context_update_tile_id as u8; 221 self.handle.tile_info.tile_cols = tile_info.tile_cols as u8; 222 self.handle.tile_info.tile_rows = tile_info.tile_rows as u8; 223 self.handle 224 .tile_info 225 .mi_col_starts 226 .copy_from_slice(&tile_info.mi_col_starts[0..(V4L2_AV1_MAX_TILE_COLS + 1) as usize]); 227 self.handle 228 .tile_info 229 .mi_col_starts 230 .copy_from_slice(&tile_info.mi_col_starts[0..(V4L2_AV1_MAX_TILE_COLS + 1) as usize]); 231 self.handle 232 .tile_info 233 .mi_row_starts 234 .copy_from_slice(&tile_info.mi_row_starts[0..(V4L2_AV1_MAX_TILE_ROWS + 1) as usize]); 235 self.handle 236 .tile_info 237 .width_in_sbs_minus_1 238 .copy_from_slice(&tile_info.width_in_sbs_minus_1[0..V4L2_AV1_MAX_TILE_COLS as usize]); 239 self.handle 240 .tile_info 241 .height_in_sbs_minus_1 242 .copy_from_slice(&tile_info.height_in_sbs_minus_1[0..V4L2_AV1_MAX_TILE_ROWS as usize]); 243 self.handle.tile_info.tile_size_bytes = tile_info.tile_size_bytes as u8; 244 self 245 } 246 set_quantization_params(&mut self, quant: &QuantizationParams) -> &mut Self247 pub fn set_quantization_params(&mut self, quant: &QuantizationParams) -> &mut Self { 248 if quant.diff_uv_delta { 249 self.handle.quantization.flags |= V4L2_AV1_QUANTIZATION_FLAG_DIFF_UV_DELTA as u8; 250 } 251 if quant.using_qmatrix { 252 self.handle.quantization.flags |= V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX as u8; 253 } 254 if quant.delta_q_present { 255 self.handle.quantization.flags |= V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT as u8; 256 } 257 self.handle.quantization.base_q_idx = quant.base_q_idx as u8; 258 self.handle.quantization.delta_q_y_dc = quant.delta_q_y_dc as i8; 259 self.handle.quantization.delta_q_u_dc = quant.delta_q_u_dc as i8; 260 self.handle.quantization.delta_q_v_dc = quant.delta_q_v_dc as i8; 261 self.handle.quantization.delta_q_u_ac = quant.delta_q_u_ac as i8; 262 self.handle.quantization.delta_q_v_ac = quant.delta_q_v_ac as i8; 263 self.handle.quantization.qm_y = quant.qm_y as u8; 264 self.handle.quantization.qm_u = quant.qm_u as u8; 265 self.handle.quantization.qm_v = quant.qm_v as u8; 266 self.handle.quantization.delta_q_res = quant.delta_q_res as u8; 267 self 268 } 269 set_segmentation_params(&mut self, seg: &SegmentationParams) -> &mut Self270 pub fn set_segmentation_params(&mut self, seg: &SegmentationParams) -> &mut Self { 271 self.handle.segmentation.last_active_seg_id = seg.last_active_seg_id; 272 for i in 0..V4L2_AV1_MAX_SEGMENTS as usize { 273 for j in 0..V4L2_AV1_SEG_LVL_MAX as usize { 274 self.handle.segmentation.feature_enabled[i] |= 275 (seg.feature_enabled[i][j] as u8) << j; 276 self.handle.segmentation.feature_data[i][j] |= seg.feature_data[i][j]; 277 } 278 } 279 if seg.segmentation_enabled { 280 self.handle.segmentation.flags |= V4L2_AV1_SEGMENTATION_FLAG_ENABLED as u8; 281 } 282 if seg.segmentation_update_map { 283 self.handle.segmentation.flags |= V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP as u8; 284 } 285 if seg.segmentation_temporal_update { 286 self.handle.segmentation.flags |= V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE as u8; 287 } 288 if seg.segmentation_update_data { 289 self.handle.segmentation.flags |= V4L2_AV1_SEGMENTATION_FLAG_UPDATE_DATA as u8; 290 } 291 if seg.seg_id_pre_skip { 292 self.handle.segmentation.flags |= V4L2_AV1_SEGMENTATION_FLAG_SEG_ID_PRE_SKIP as u8; 293 } 294 self 295 } 296 set_loop_filter_params(&mut self, loop_filter: &LoopFilterParams) -> &mut Self297 pub fn set_loop_filter_params(&mut self, loop_filter: &LoopFilterParams) -> &mut Self { 298 if loop_filter.loop_filter_delta_enabled { 299 self.handle.loop_filter.flags |= V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED as u8; 300 } 301 if loop_filter.loop_filter_delta_update { 302 self.handle.loop_filter.flags |= V4L2_AV1_LOOP_FILTER_FLAG_DELTA_UPDATE as u8; 303 } 304 if loop_filter.delta_lf_present { 305 self.handle.loop_filter.flags |= V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT as u8; 306 } 307 if loop_filter.delta_lf_multi { 308 self.handle.loop_filter.flags |= V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI as u8; 309 } 310 self.handle.loop_filter.level.copy_from_slice(&loop_filter.loop_filter_level[0..4]); 311 self.handle.loop_filter.sharpness = loop_filter.loop_filter_sharpness; 312 self.handle.loop_filter.ref_deltas.copy_from_slice( 313 &loop_filter.loop_filter_ref_deltas[0..V4L2_AV1_TOTAL_REFS_PER_FRAME as usize], 314 ); 315 self.handle 316 .loop_filter 317 .mode_deltas 318 .copy_from_slice(&loop_filter.loop_filter_mode_deltas[0..2]); 319 self.handle.loop_filter.delta_lf_res = loop_filter.delta_lf_res; 320 self 321 } 322 set_cdef_params(&mut self, cdef: &CdefParams) -> &mut Self323 pub fn set_cdef_params(&mut self, cdef: &CdefParams) -> &mut Self { 324 self.handle.cdef.damping_minus_3 = (cdef.cdef_damping - 3) as u8; 325 self.handle.cdef.bits = cdef.cdef_bits as u8; 326 for i in 0..V4L2_AV1_CDEF_MAX as usize { 327 self.handle.cdef.y_pri_strength[i] = cdef.cdef_y_pri_strength[i] as u8; 328 self.handle.cdef.y_sec_strength[i] = cdef.cdef_y_sec_strength[i] as u8; 329 self.handle.cdef.uv_pri_strength[i] = cdef.cdef_uv_pri_strength[i] as u8; 330 self.handle.cdef.uv_sec_strength[i] = cdef.cdef_uv_sec_strength[i] as u8; 331 } 332 self 333 } 334 set_loop_restoration_params( &mut self, loop_restoration: &LoopRestorationParams, ) -> &mut Self335 pub fn set_loop_restoration_params( 336 &mut self, 337 loop_restoration: &LoopRestorationParams, 338 ) -> &mut Self { 339 if loop_restoration.uses_lr { 340 self.handle.loop_restoration.flags |= V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR as u8; 341 } 342 if loop_restoration.uses_chroma_lr { 343 self.handle.loop_restoration.flags |= 344 V4L2_AV1_LOOP_RESTORATION_FLAG_USES_CHROMA_LR as u8; 345 } 346 self.handle.loop_restoration.lr_unit_shift = loop_restoration.lr_unit_shift; 347 self.handle.loop_restoration.lr_uv_shift = loop_restoration.lr_uv_shift; 348 for i in 0..V4L2_AV1_NUM_PLANES_MAX as usize { 349 self.handle.loop_restoration.frame_restoration_type[i] = 350 match loop_restoration.frame_restoration_type[i] { 351 FrameRestorationType::None => 0, 352 FrameRestorationType::Wiener => 1, 353 FrameRestorationType::Sgrproj => 2, 354 FrameRestorationType::Switchable => 3, 355 }; 356 self.handle.loop_restoration.loop_restoration_size[i] = 357 loop_restoration.loop_restoration_size[i] as u32; 358 } 359 self 360 } 361 set_global_motion_params(&mut self, global_motion: &GlobalMotionParams) -> &mut Self362 pub fn set_global_motion_params(&mut self, global_motion: &GlobalMotionParams) -> &mut Self { 363 for i in 0..V4L2_AV1_TOTAL_REFS_PER_FRAME as usize { 364 if global_motion.is_global[i] { 365 self.handle.global_motion.flags[i] |= V4L2_AV1_GLOBAL_MOTION_FLAG_IS_GLOBAL as u8; 366 } 367 if global_motion.is_rot_zoom[i] { 368 self.handle.global_motion.flags[i] |= V4L2_AV1_GLOBAL_MOTION_FLAG_IS_ROT_ZOOM as u8; 369 } 370 if global_motion.is_translation[i] { 371 self.handle.global_motion.flags[i] |= 372 V4L2_AV1_GLOBAL_MOTION_FLAG_IS_TRANSLATION as u8; 373 } 374 self.handle.global_motion.type_[i] = match global_motion.gm_type[i] { 375 WarpModelType::Identity => 0, 376 WarpModelType::Translation => 1, 377 WarpModelType::RotZoom => 2, 378 WarpModelType::Affine => 3, 379 }; 380 self.handle.global_motion.params[i].copy_from_slice(&global_motion.gm_params[i][0..6]); 381 if !global_motion.warp_valid[i] { 382 self.handle.global_motion.invalid |= 1 << i; 383 } 384 } 385 self 386 } 387 set_frame_params(&mut self, hdr: &FrameHeaderObu) -> &mut Self388 pub fn set_frame_params(&mut self, hdr: &FrameHeaderObu) -> &mut Self { 389 self.handle.superres_denom = hdr.superres_denom as u8; 390 for i in 0..2 as usize { 391 self.handle.skip_mode_frame[i] = hdr.skip_mode_frame[i] as u8; 392 } 393 self.handle.primary_ref_frame = hdr.primary_ref_frame as u8; 394 if hdr.show_frame { 395 self.handle.flags |= V4L2_AV1_FRAME_FLAG_SHOW_FRAME; 396 } 397 if hdr.showable_frame { 398 self.handle.flags |= V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME; 399 } 400 if hdr.error_resilient_mode { 401 self.handle.flags |= V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE; 402 } 403 if hdr.disable_cdf_update { 404 self.handle.flags |= V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE; 405 } 406 if hdr.allow_screen_content_tools != 0 { 407 self.handle.flags |= V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS; 408 } 409 if hdr.force_integer_mv != 0 { 410 self.handle.flags |= V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV; 411 } 412 if hdr.allow_intrabc { 413 self.handle.flags |= V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC; 414 } 415 if hdr.use_superres { 416 self.handle.flags |= V4L2_AV1_FRAME_FLAG_USE_SUPERRES; 417 } 418 if hdr.allow_high_precision_mv { 419 self.handle.flags |= V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV; 420 } 421 if hdr.is_motion_mode_switchable { 422 self.handle.flags |= V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE; 423 } 424 if hdr.use_ref_frame_mvs { 425 self.handle.flags |= V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS; 426 } 427 if hdr.disable_frame_end_update_cdf { 428 self.handle.flags |= V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF; 429 } 430 if hdr.allow_warped_motion { 431 self.handle.flags |= V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION; 432 } 433 if hdr.reference_select { 434 self.handle.flags |= V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT; 435 } 436 if hdr.reduced_tx_set { 437 self.handle.flags |= V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET; 438 } 439 if hdr.skip_mode_frame[0] > 0 { 440 self.handle.flags |= V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED; 441 } 442 if hdr.skip_mode_present { 443 self.handle.flags |= V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT; 444 } 445 if hdr.frame_size_override_flag { 446 self.handle.flags |= V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE; 447 } 448 if hdr.buffer_removal_time_present_flag { 449 self.handle.flags |= V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT; 450 self.handle.buffer_removal_time.copy_from_slice( 451 &hdr.buffer_removal_time[0..V4L2_AV1_MAX_OPERATING_POINTS as usize], 452 ); 453 } 454 if hdr.frame_refs_short_signaling { 455 self.handle.flags |= V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING; 456 } 457 self.handle.frame_type = hdr.frame_type as u32; 458 self.handle.order_hint = hdr.order_hint; 459 self.handle.upscaled_width = hdr.upscaled_width; 460 self.handle.interpolation_filter = hdr.interpolation_filter as u32; 461 self.handle.tx_mode = hdr.tx_mode as u32; 462 self.handle.frame_width_minus_1 = hdr.frame_width - 1; 463 self.handle.frame_height_minus_1 = hdr.frame_height - 1; 464 self.handle.render_width_minus_1 = hdr.render_width as u16 - 1; 465 self.handle.render_height_minus_1 = hdr.render_height as u16 - 1; 466 self.handle.current_frame_id = hdr.current_frame_id; 467 self.handle 468 .order_hints 469 .copy_from_slice(&hdr.order_hints[0..V4L2_AV1_TOTAL_REFS_PER_FRAME as usize]); 470 for i in 0..V4L2_AV1_REFS_PER_FRAME as usize { 471 self.handle.ref_frame_idx[i] = hdr.ref_frame_idx[i] as i8; 472 } 473 self.handle.refresh_frame_flags = hdr.refresh_frame_flags as u8; 474 self 475 } 476 } 477 478 #[derive(Default)] 479 pub struct V4l2CtrlAv1SequenceParams { 480 #[allow(dead_code)] 481 handle: v4l2_ctrl_av1_sequence, 482 } 483 484 impl V4l2CtrlAv1SequenceParams { new() -> Self485 pub fn new() -> Self { 486 Default::default() 487 } set_ctrl_sequence(&mut self, hdr: &SequenceHeaderObu) -> &mut Self488 pub fn set_ctrl_sequence(&mut self, hdr: &SequenceHeaderObu) -> &mut Self { 489 if hdr.still_picture { 490 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE; 491 } 492 if hdr.use_128x128_superblock { 493 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK; 494 } 495 if hdr.enable_filter_intra { 496 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA; 497 } 498 if hdr.enable_intra_edge_filter { 499 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER; 500 } 501 if hdr.enable_interintra_compound { 502 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND; 503 } 504 if hdr.enable_masked_compound { 505 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND; 506 } 507 if hdr.enable_warped_motion { 508 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION; 509 } 510 if hdr.enable_dual_filter { 511 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER; 512 } 513 if hdr.enable_order_hint { 514 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT; 515 } 516 if hdr.enable_jnt_comp { 517 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP; 518 } 519 if hdr.enable_ref_frame_mvs { 520 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS; 521 } 522 if hdr.enable_superres { 523 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES; 524 } 525 if hdr.enable_cdef { 526 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF; 527 } 528 if hdr.enable_restoration { 529 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION; 530 } 531 if hdr.color_config.mono_chrome { 532 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME; 533 } 534 if hdr.color_config.color_range { 535 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE; 536 } 537 if hdr.color_config.subsampling_x { 538 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X; 539 } 540 if hdr.color_config.subsampling_y { 541 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y; 542 } 543 if hdr.film_grain_params_present { 544 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT; 545 } 546 if hdr.color_config.separate_uv_delta_q { 547 self.handle.flags |= V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q; 548 } 549 self.handle.seq_profile = hdr.seq_profile as u8; 550 self.handle.order_hint_bits = hdr.order_hint_bits as u8; 551 self.handle.bit_depth = match hdr.bit_depth { 552 BitDepth::Depth8 => 8, 553 BitDepth::Depth10 => 10, 554 BitDepth::Depth12 => 12, 555 }; 556 self.handle.max_frame_width_minus_1 = hdr.max_frame_width_minus_1; 557 self.handle.max_frame_height_minus_1 = hdr.max_frame_height_minus_1; 558 self 559 } 560 } 561 562 #[derive(Default)] 563 pub struct V4l2CtrlAv1TileGroupEntryParams { 564 #[allow(dead_code)] 565 handle: v4l2_ctrl_av1_tile_group_entry, 566 } 567 568 impl V4l2CtrlAv1TileGroupEntryParams { new() -> Self569 pub fn new() -> Self { 570 Default::default() 571 } set_tile_group_entry(&mut self, tg: &Tile) -> &mut Self572 pub fn set_tile_group_entry(&mut self, tg: &Tile) -> &mut Self { 573 self.handle.tile_offset = tg.tile_offset; 574 self.handle.tile_size = tg.tile_size; 575 self.handle.tile_row = tg.tile_row; 576 self.handle.tile_col = tg.tile_col; 577 self 578 } 579 } 580 581 // Cargo-culted from v4l2r's control.rs file. v4l2r does not currently support 582 // VP9 controls, so we work around the issue by making our own "control" struct 583 // and just implementing the AsV4l2ControlSlice trait. 584 585 pub struct Av1V4l2FilmGrainCtrl(v4l2_ext_control, PhantomData<v4l2_ctrl_av1_film_grain>); 586 587 impl From<&V4l2CtrlAv1FilmGrainParams> for Av1V4l2FilmGrainCtrl { from(decode_params: &V4l2CtrlAv1FilmGrainParams) -> Self588 fn from(decode_params: &V4l2CtrlAv1FilmGrainParams) -> Self { 589 let payload = Box::new(decode_params.handle); 590 591 Self( 592 v4l2_ext_control { 593 id: V4L2_CID_STATELESS_AV1_FILM_GRAIN, 594 size: std::mem::size_of::<v4l2_ctrl_av1_film_grain>() as u32, 595 __bindgen_anon_1: v4l2_ext_control__bindgen_ty_1 { 596 p_av1_film_grain: Box::into_raw(payload), 597 }, 598 ..Default::default() 599 }, 600 PhantomData, 601 ) 602 } 603 } 604 605 impl AsV4l2ControlSlice for &mut Av1V4l2FilmGrainCtrl { as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control]606 fn as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control] { 607 std::slice::from_mut(&mut self.0) 608 } 609 } 610 611 impl Drop for Av1V4l2FilmGrainCtrl { drop(&mut self)612 fn drop(&mut self) { 613 // SAFETY: p_av1_film_grain contains a pointer to a non-NULL 614 // v4l2_ctrl_av1_film_grain object. 615 unsafe { 616 let _ = Box::from_raw(self.0.__bindgen_anon_1.p_av1_film_grain); 617 } 618 } 619 } 620 621 pub struct Av1V4l2FrameCtrl(v4l2_ext_control, PhantomData<v4l2_ctrl_av1_frame>); 622 623 impl From<&V4l2CtrlAv1FrameParams> for Av1V4l2FrameCtrl { from(decode_params: &V4l2CtrlAv1FrameParams) -> Self624 fn from(decode_params: &V4l2CtrlAv1FrameParams) -> Self { 625 let payload = Box::new(decode_params.handle); 626 627 Self( 628 v4l2_ext_control { 629 id: V4L2_CID_STATELESS_AV1_FRAME, 630 size: std::mem::size_of::<v4l2_ctrl_av1_frame>() as u32, 631 __bindgen_anon_1: v4l2_ext_control__bindgen_ty_1 { 632 p_av1_frame: Box::into_raw(payload), 633 }, 634 ..Default::default() 635 }, 636 PhantomData, 637 ) 638 } 639 } 640 641 impl AsV4l2ControlSlice for &mut Av1V4l2FrameCtrl { as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control]642 fn as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control] { 643 std::slice::from_mut(&mut self.0) 644 } 645 } 646 647 impl Drop for Av1V4l2FrameCtrl { drop(&mut self)648 fn drop(&mut self) { 649 // SAFETY: p_av1_frame contains a pointer to a non-NULL v4l2_ctrl_av1_frame object. 650 unsafe { 651 let _ = Box::from_raw(self.0.__bindgen_anon_1.p_av1_frame); 652 } 653 } 654 } 655 656 pub struct Av1V4l2SequenceCtrl(v4l2_ext_control, PhantomData<v4l2_ctrl_av1_sequence>); 657 658 impl From<&V4l2CtrlAv1SequenceParams> for Av1V4l2SequenceCtrl { from(decode_params: &V4l2CtrlAv1SequenceParams) -> Self659 fn from(decode_params: &V4l2CtrlAv1SequenceParams) -> Self { 660 let payload = Box::new(decode_params.handle); 661 662 Self( 663 v4l2_ext_control { 664 id: V4L2_CID_STATELESS_AV1_SEQUENCE, 665 size: std::mem::size_of::<v4l2_ctrl_av1_sequence>() as u32, 666 __bindgen_anon_1: v4l2_ext_control__bindgen_ty_1 { 667 p_av1_sequence: Box::into_raw(payload), 668 }, 669 ..Default::default() 670 }, 671 PhantomData, 672 ) 673 } 674 } 675 676 impl AsV4l2ControlSlice for &mut Av1V4l2SequenceCtrl { as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control]677 fn as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control] { 678 std::slice::from_mut(&mut self.0) 679 } 680 } 681 682 impl Drop for Av1V4l2SequenceCtrl { drop(&mut self)683 fn drop(&mut self) { 684 // SAFETY: p_av1_sequence contains a pointer to a non-NULL v4l2_ctrl_av1_sequence object. 685 unsafe { 686 let _ = Box::from_raw(self.0.__bindgen_anon_1.p_av1_sequence); 687 } 688 } 689 } 690 691 pub struct Av1V4l2TileGroupEntryCtrl(v4l2_ext_control, PhantomData<v4l2_ctrl_av1_tile_group_entry>); 692 693 impl From<&V4l2CtrlAv1TileGroupEntryParams> for Av1V4l2TileGroupEntryCtrl { from(decode_params: &V4l2CtrlAv1TileGroupEntryParams) -> Self694 fn from(decode_params: &V4l2CtrlAv1TileGroupEntryParams) -> Self { 695 let payload = Box::new(decode_params.handle); 696 697 Self( 698 v4l2_ext_control { 699 id: V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY, 700 size: std::mem::size_of::<v4l2_ctrl_av1_tile_group_entry>() as u32, 701 __bindgen_anon_1: v4l2_ext_control__bindgen_ty_1 { 702 p_av1_tile_group_entry: Box::into_raw(payload), 703 }, 704 ..Default::default() 705 }, 706 PhantomData, 707 ) 708 } 709 } 710 711 impl AsV4l2ControlSlice for &mut Av1V4l2TileGroupEntryCtrl { as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control]712 fn as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control] { 713 std::slice::from_mut(&mut self.0) 714 } 715 } 716 717 impl Drop for Av1V4l2TileGroupEntryCtrl { drop(&mut self)718 fn drop(&mut self) { 719 // SAFETY: p_av1_tile_group_entry contains a pointer to a non-NULL 720 // v4l2_ctrl_tile_group_entry object. 721 unsafe { 722 let _ = Box::from_raw(self.0.__bindgen_anon_1.p_av1_tile_group_entry); 723 } 724 } 725 } 726