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