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::marker::PhantomData; 6 7 use v4l2r::bindings::v4l2_ctrl_vp9_frame; 8 use v4l2r::bindings::v4l2_ext_control; 9 use v4l2r::bindings::v4l2_ext_control__bindgen_ty_1; 10 use v4l2r::bindings::V4L2_CID_STATELESS_VP9_FRAME; 11 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV; 12 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING; 13 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT; 14 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY; 15 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME; 16 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE; 17 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX; 18 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_SHOW_FRAME; 19 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING; 20 use v4l2r::bindings::V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING; 21 use v4l2r::bindings::V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED; 22 use v4l2r::bindings::V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE; 23 use v4l2r::bindings::V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE; 24 use v4l2r::bindings::V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE; 25 use v4l2r::bindings::V4L2_VP9_SEGMENTATION_FLAG_ENABLED; 26 use v4l2r::bindings::V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE; 27 use v4l2r::bindings::V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA; 28 use v4l2r::bindings::V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP; 29 use v4l2r::controls::AsV4l2ControlSlice; 30 31 use crate::codec::vp9::parser::ColorRange; 32 use crate::codec::vp9::parser::FrameType; 33 use crate::codec::vp9::parser::Header; 34 use crate::codec::vp9::parser::LAST_FRAME; 35 use crate::codec::vp9::parser::MAX_REF_FRAMES; 36 use crate::codec::vp9::parser::MAX_SEGMENTS; 37 use crate::codec::vp9::parser::SEG_LVL_MAX; 38 39 #[derive(Default)] 40 pub struct V4l2CtrlVp9FrameParams { 41 handle: v4l2_ctrl_vp9_frame, 42 } 43 44 impl V4l2CtrlVp9FrameParams { new() -> Self45 pub fn new() -> Self { 46 Default::default() 47 } 48 set_loop_filter_params(&mut self, hdr: &Header) -> &mut Self49 pub fn set_loop_filter_params(&mut self, hdr: &Header) -> &mut Self { 50 self.handle.lf.level = hdr.lf.level; 51 self.handle.lf.sharpness = hdr.lf.sharpness; 52 self.handle.lf.flags = 0; 53 54 if hdr.lf.delta_enabled { 55 self.handle.lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED as u8; 56 } 57 if hdr.lf.delta_update { 58 self.handle.lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE as u8; 59 } 60 61 self.handle.lf.ref_deltas.clone_from_slice(&hdr.lf.ref_deltas); 62 self.handle.lf.mode_deltas.clone_from_slice(&hdr.lf.mode_deltas); 63 64 self 65 } 66 set_quantization_params(&mut self, hdr: &Header) -> &mut Self67 pub fn set_quantization_params(&mut self, hdr: &Header) -> &mut Self { 68 self.handle.quant.base_q_idx = hdr.quant.base_q_idx; 69 self.handle.quant.delta_q_y_dc = hdr.quant.delta_q_y_dc; 70 self.handle.quant.delta_q_uv_dc = hdr.quant.delta_q_uv_dc; 71 self.handle.quant.delta_q_uv_ac = hdr.quant.delta_q_uv_ac; 72 self 73 } 74 set_segmentation_params(&mut self, hdr: &Header) -> &mut Self75 pub fn set_segmentation_params(&mut self, hdr: &Header) -> &mut Self { 76 if hdr.seg.enabled { 77 self.handle.seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ENABLED as u8; 78 } 79 if hdr.seg.update_map { 80 self.handle.seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP as u8; 81 } 82 if hdr.seg.temporal_update { 83 self.handle.seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE as u8; 84 } 85 if hdr.seg.update_data { 86 self.handle.seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA as u8; 87 } 88 if hdr.seg.abs_or_delta_update { 89 self.handle.seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE as u8; 90 } 91 92 for i in 0..MAX_SEGMENTS { 93 self.handle.seg.feature_data[i].clone_from_slice(&hdr.seg.feature_data[i]); 94 let mut feature_enabled = 0u8; 95 for j in 0..SEG_LVL_MAX { 96 feature_enabled |= (hdr.seg.feature_enabled[i][j] as u8) << j; 97 } 98 self.handle.seg.feature_enabled[i] = feature_enabled; 99 } 100 101 self.handle.seg.tree_probs.clone_from_slice(&hdr.seg.tree_probs); 102 self.handle.seg.pred_probs.clone_from_slice(&hdr.seg.pred_probs); 103 104 self 105 } 106 set_frame_params( &mut self, hdr: &Header, last_frame_ts: u64, golden_frame_ts: u64, alt_frame_ts: u64, ) -> &mut Self107 pub fn set_frame_params( 108 &mut self, 109 hdr: &Header, 110 last_frame_ts: u64, 111 golden_frame_ts: u64, 112 alt_frame_ts: u64, 113 ) -> &mut Self { 114 self.handle.compressed_header_size = hdr.header_size_in_bytes; 115 self.handle.uncompressed_header_size = hdr.uncompressed_header_size_in_bytes; 116 self.handle.frame_width_minus_1 = (hdr.width - 1) as u16; 117 self.handle.frame_height_minus_1 = (hdr.height - 1) as u16; 118 self.handle.render_width_minus_1 = (hdr.render_width - 1) as u16; 119 self.handle.render_height_minus_1 = (hdr.render_height - 1) as u16; 120 self.handle.reset_frame_context = hdr.reset_frame_context; 121 self.handle.frame_context_idx = hdr.frame_context_idx; 122 self.handle.profile = hdr.profile as u8; 123 self.handle.bit_depth = hdr.bit_depth as u8; 124 self.handle.interpolation_filter = hdr.interpolation_filter as u8; 125 self.handle.tile_cols_log2 = hdr.tile_cols_log2; 126 self.handle.tile_rows_log2 = hdr.tile_rows_log2; 127 128 // The MTK V4L2 stateless driver ignores the reference_mode field current. 129 // TODO: Implement this properly for future drivers? 130 self.handle.reference_mode = V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE as u8; 131 132 for i in 0..(MAX_REF_FRAMES - LAST_FRAME) { 133 self.handle.ref_frame_sign_bias |= 134 ((hdr.ref_frame_sign_bias[i + LAST_FRAME] != 0) as u8) << i; 135 } 136 137 if hdr.frame_type == FrameType::KeyFrame { 138 self.handle.flags |= V4L2_VP9_FRAME_FLAG_KEY_FRAME; 139 } 140 if hdr.show_frame { 141 self.handle.flags |= V4L2_VP9_FRAME_FLAG_SHOW_FRAME; 142 } 143 if hdr.error_resilient_mode { 144 self.handle.flags |= V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT; 145 } 146 if hdr.intra_only { 147 self.handle.flags |= V4L2_VP9_FRAME_FLAG_INTRA_ONLY; 148 } 149 if hdr.allow_high_precision_mv { 150 self.handle.flags |= V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV; 151 } 152 if hdr.refresh_frame_context { 153 self.handle.flags |= V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX; 154 } 155 if hdr.frame_parallel_decoding_mode { 156 self.handle.flags |= V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE; 157 } 158 if hdr.subsampling_x { 159 self.handle.flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING; 160 } 161 if hdr.subsampling_y { 162 self.handle.flags |= V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING; 163 } 164 if hdr.color_range == ColorRange::FullSwing { 165 self.handle.flags |= V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING; 166 } 167 168 self.handle.last_frame_ts = last_frame_ts * 1000; 169 self.handle.golden_frame_ts = golden_frame_ts * 1000; 170 self.handle.alt_frame_ts = alt_frame_ts * 1000; 171 172 self 173 } 174 } 175 176 // Cargo-culted from v4l2r's control.rs file. v4l2r does not currently support 177 // VP9 controls, so we work around the issue by making our own "control" struct 178 // and just implementing the AsV4l2ControlSlice trait. 179 pub struct Vp9V4l2Control(v4l2_ext_control, PhantomData<v4l2_ctrl_vp9_frame>); 180 181 impl From<&V4l2CtrlVp9FrameParams> for Vp9V4l2Control { from(decode_params: &V4l2CtrlVp9FrameParams) -> Self182 fn from(decode_params: &V4l2CtrlVp9FrameParams) -> Self { 183 let payload = Box::new(decode_params.handle); 184 185 Self( 186 v4l2_ext_control { 187 id: V4L2_CID_STATELESS_VP9_FRAME, 188 size: std::mem::size_of::<v4l2_ctrl_vp9_frame>() as u32, 189 __bindgen_anon_1: v4l2_ext_control__bindgen_ty_1 { 190 p_vp9_frame: Box::into_raw(payload), 191 }, 192 ..Default::default() 193 }, 194 PhantomData, 195 ) 196 } 197 } 198 199 impl AsV4l2ControlSlice for &mut Vp9V4l2Control { as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control]200 fn as_v4l2_control_slice(&mut self) -> &mut [v4l2_ext_control] { 201 std::slice::from_mut(&mut self.0) 202 } 203 } 204 205 impl Drop for Vp9V4l2Control { drop(&mut self)206 fn drop(&mut self) { 207 // SAFETY: p_vp9_frame contains a pointer to a non-NULL v4l2_ctrl_vp9_frame object. 208 unsafe { 209 let _ = Box::from_raw(self.0.__bindgen_anon_1.p_vp9_frame); 210 } 211 } 212 } 213