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