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 v4l2r::bindings::v4l2_ctrl_vp8_frame; 6 use v4l2r::bindings::V4L2_VP8_FRAME_FLAG_KEY_FRAME; 7 use v4l2r::bindings::V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF; 8 use v4l2r::bindings::V4L2_VP8_FRAME_FLAG_SHOW_FRAME; 9 use v4l2r::bindings::V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT; 10 use v4l2r::bindings::V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN; 11 use v4l2r::bindings::V4L2_VP8_LF_ADJ_ENABLE; 12 use v4l2r::bindings::V4L2_VP8_LF_DELTA_UPDATE; 13 use v4l2r::bindings::V4L2_VP8_LF_FILTER_TYPE_SIMPLE; 14 use v4l2r::bindings::V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE; 15 use v4l2r::bindings::V4L2_VP8_SEGMENT_FLAG_ENABLED; 16 use v4l2r::bindings::V4L2_VP8_SEGMENT_FLAG_UPDATE_FEATURE_DATA; 17 use v4l2r::bindings::V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP; 18 use v4l2r::controls::codec::Vp8Frame; 19 use v4l2r::controls::SafeExtControl; 20 21 use crate::codec::vp8::parser::Header; 22 use crate::codec::vp8::parser::MbLfAdjustments; 23 use crate::codec::vp8::parser::Segmentation; 24 25 #[derive(Default)] 26 pub struct V4l2CtrlVp8FrameParams { 27 handle: v4l2_ctrl_vp8_frame, 28 } 29 30 impl V4l2CtrlVp8FrameParams { new() -> Self31 pub fn new() -> Self { 32 Default::default() 33 } 34 set_loop_filter_params( &mut self, hdr: &Header, mb_lf_adjust: &MbLfAdjustments, ) -> &mut Self35 pub fn set_loop_filter_params( 36 &mut self, 37 hdr: &Header, 38 mb_lf_adjust: &MbLfAdjustments, 39 ) -> &mut Self { 40 for i in 0..4 { 41 self.handle.lf.ref_frm_delta[i] = mb_lf_adjust.ref_frame_delta[i]; 42 self.handle.lf.mb_mode_delta[i] = mb_lf_adjust.mb_mode_delta[i]; 43 } 44 45 self.handle.lf.sharpness_level = hdr.sharpness_level; 46 self.handle.lf.level = hdr.loop_filter_level; 47 self.handle.lf.padding = 0; 48 49 let mut flags: u32 = 0; 50 if hdr.filter_type { 51 flags |= V4L2_VP8_LF_FILTER_TYPE_SIMPLE; 52 } 53 if mb_lf_adjust.loop_filter_adj_enable { 54 flags |= V4L2_VP8_LF_ADJ_ENABLE; 55 } 56 if mb_lf_adjust.mode_ref_lf_delta_update { 57 flags |= V4L2_VP8_LF_DELTA_UPDATE; 58 } 59 self.handle.lf.flags = flags; 60 self 61 } 62 set_quantization_params(&mut self, hdr: &Header) -> &mut Self63 pub fn set_quantization_params(&mut self, hdr: &Header) -> &mut Self { 64 self.handle.quant.y_ac_qi = 65 u8::try_from(hdr.quant_indices.y_ac_qi).expect("Value out of range for u8"); 66 self.handle.quant.y_dc_delta = 67 i8::try_from(hdr.quant_indices.y_dc_delta).expect("Value out of range for u8"); 68 self.handle.quant.y2_dc_delta = 69 i8::try_from(hdr.quant_indices.y2_dc_delta).expect("Value out of range for u8"); 70 self.handle.quant.y2_ac_delta = 71 i8::try_from(hdr.quant_indices.y2_ac_delta).expect("Value out of range for u8"); 72 self.handle.quant.uv_dc_delta = 73 i8::try_from(hdr.quant_indices.uv_dc_delta).expect("Value out of range for u8"); 74 self.handle.quant.uv_ac_delta = 75 i8::try_from(hdr.quant_indices.uv_ac_delta).expect("Value out of range for u8"); 76 77 self.handle.quant.padding = 0; 78 self 79 } 80 set_segmentation_params(&mut self, segmentation: &Segmentation) -> &mut Self81 pub fn set_segmentation_params(&mut self, segmentation: &Segmentation) -> &mut Self { 82 for i in 0..4 { 83 self.handle.segment.quant_update[i] = segmentation.quantizer_update_value[i]; 84 self.handle.segment.lf_update[i] = segmentation.lf_update_value[i]; 85 } 86 87 for i in 0..3 { 88 self.handle.segment.segment_probs[i] = segmentation.segment_prob[i]; 89 } 90 91 self.handle.segment.padding = 0; 92 93 let mut flags: u32 = 0; 94 if segmentation.segmentation_enabled { 95 flags |= V4L2_VP8_SEGMENT_FLAG_ENABLED; 96 } 97 if segmentation.update_mb_segmentation_map { 98 flags |= V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP; 99 } 100 if segmentation.update_segment_feature_data { 101 flags |= V4L2_VP8_SEGMENT_FLAG_UPDATE_FEATURE_DATA; 102 } 103 if segmentation.segment_feature_mode == false { 104 flags |= V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE; 105 } 106 self.handle.segment.flags = flags; 107 self 108 } 109 set_entropy_params(&mut self, hdr: &Header) -> &mut Self110 pub fn set_entropy_params(&mut self, hdr: &Header) -> &mut Self { 111 self.handle.entropy.coeff_probs = hdr.coeff_prob; 112 self.handle.entropy.y_mode_probs = hdr.mode_probs.intra_16x16_prob; 113 self.handle.entropy.uv_mode_probs = hdr.mode_probs.intra_chroma_prob; 114 self.handle.entropy.mv_probs = hdr.mv_prob; 115 self 116 } 117 set_bool_ctx(&mut self, hdr: &Header) -> &mut Self118 pub fn set_bool_ctx(&mut self, hdr: &Header) -> &mut Self { 119 self.handle.coder_state.range = hdr.bd_range as u8; 120 self.handle.coder_state.value = hdr.bd_value as u8; 121 self.handle.coder_state.bit_count = hdr.bd_count as u8; 122 self.handle.coder_state.padding = 0; 123 self 124 } 125 set_frame_params( &mut self, hdr: &Header, last_frame_ts: u64, golden_frame_ts: u64, alt_frame_ts: u64, ) -> &mut Self126 pub fn set_frame_params( 127 &mut self, 128 hdr: &Header, 129 last_frame_ts: u64, 130 golden_frame_ts: u64, 131 alt_frame_ts: u64, 132 ) -> &mut Self { 133 self.handle.width = hdr.width; 134 self.handle.height = hdr.height; 135 self.handle.horizontal_scale = hdr.horiz_scale_code; 136 self.handle.vertical_scale = hdr.vert_scale_code; 137 138 self.handle.version = hdr.version; 139 self.handle.prob_skip_false = hdr.prob_skip_false; 140 self.handle.prob_intra = hdr.prob_intra; 141 self.handle.prob_last = hdr.prob_last; 142 self.handle.prob_gf = hdr.prob_golden; 143 self.handle.num_dct_parts = hdr.num_dct_partitions() as u8; 144 145 self.handle.first_part_size = hdr.first_part_size; 146 self.handle.first_part_header_bits = hdr.header_size; 147 148 for i in 0..hdr.num_dct_partitions() { 149 self.handle.dct_part_sizes[i] = hdr.partition_size[i]; 150 } 151 152 self.handle.last_frame_ts = last_frame_ts * 1000; 153 self.handle.golden_frame_ts = golden_frame_ts * 1000; 154 self.handle.alt_frame_ts = alt_frame_ts * 1000; 155 156 let mut flags: u32 = 0; 157 if hdr.key_frame { 158 flags |= V4L2_VP8_FRAME_FLAG_KEY_FRAME; 159 } 160 if hdr.show_frame { 161 flags |= V4L2_VP8_FRAME_FLAG_SHOW_FRAME; 162 } 163 if hdr.mb_no_coeff_skip { 164 flags |= V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF; 165 } 166 if hdr.sign_bias_golden { 167 flags |= V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN; 168 } 169 if hdr.sign_bias_alternate { 170 flags |= V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT; 171 } 172 173 self.handle.flags = flags as u64; 174 175 self 176 } 177 } 178 179 impl From<&V4l2CtrlVp8FrameParams> for SafeExtControl<Vp8Frame> { from(decode_params: &V4l2CtrlVp8FrameParams) -> Self180 fn from(decode_params: &V4l2CtrlVp8FrameParams) -> Self { 181 SafeExtControl::<Vp8Frame>::from(decode_params.handle) 182 } 183 } 184