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_h264_decode_params; 6 use v4l2r::bindings::v4l2_ctrl_h264_pps; 7 use v4l2r::bindings::v4l2_ctrl_h264_scaling_matrix; 8 use v4l2r::bindings::v4l2_ctrl_h264_sps; 9 use v4l2r::bindings::v4l2_h264_dpb_entry; 10 use v4l2r::bindings::v4l2_stateless_h264_decode_mode_V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED as V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED; 11 use v4l2r::bindings::v4l2_stateless_h264_decode_mode_V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED as V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED; 12 use v4l2r::bindings::v4l2_stateless_h264_start_code_V4L2_STATELESS_H264_START_CODE_ANNEX_B as V4L2_STATELESS_H264_START_CODE_ANNEX_B; 13 use v4l2r::bindings::v4l2_stateless_h264_start_code_V4L2_STATELESS_H264_START_CODE_NONE as V4L2_STATELESS_H264_START_CODE_NONE; 14 use v4l2r::bindings::V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD; 15 use v4l2r::bindings::V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC; 16 use v4l2r::bindings::V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC; 17 use v4l2r::bindings::V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; 18 use v4l2r::bindings::V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; 19 use v4l2r::bindings::V4L2_H264_DPB_ENTRY_FLAG_VALID; 20 use v4l2r::bindings::V4L2_H264_FRAME_REF; 21 use v4l2r::bindings::V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT; 22 use v4l2r::bindings::V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED; 23 use v4l2r::bindings::V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT; 24 use v4l2r::bindings::V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE; 25 use v4l2r::bindings::V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT; 26 use v4l2r::bindings::V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT; 27 use v4l2r::bindings::V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE; 28 use v4l2r::bindings::V4L2_H264_PPS_FLAG_WEIGHTED_PRED; 29 use v4l2r::bindings::V4L2_H264_SPS_CONSTRAINT_SET0_FLAG; 30 use v4l2r::bindings::V4L2_H264_SPS_CONSTRAINT_SET1_FLAG; 31 use v4l2r::bindings::V4L2_H264_SPS_CONSTRAINT_SET2_FLAG; 32 use v4l2r::bindings::V4L2_H264_SPS_CONSTRAINT_SET3_FLAG; 33 use v4l2r::bindings::V4L2_H264_SPS_CONSTRAINT_SET4_FLAG; 34 use v4l2r::bindings::V4L2_H264_SPS_CONSTRAINT_SET5_FLAG; 35 use v4l2r::bindings::V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO; 36 use v4l2r::bindings::V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE; 37 use v4l2r::bindings::V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY; 38 use v4l2r::bindings::V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED; 39 use v4l2r::bindings::V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD; 40 use v4l2r::bindings::V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS; 41 use v4l2r::bindings::V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE; 42 use v4l2r::controls::codec::H264DecodeMode; 43 use v4l2r::controls::codec::H264DecodeParams; 44 use v4l2r::controls::codec::H264StartCode; 45 use v4l2r::controls::SafeExtControl; 46 47 use crate::codec::h264::parser::Pps; 48 use crate::codec::h264::parser::SliceHeader; 49 use crate::codec::h264::parser::Sps; 50 use crate::codec::h264::picture::Field; 51 use crate::codec::h264::picture::IsIdr; 52 use crate::codec::h264::picture::PictureData; 53 use crate::codec::h264::picture::RcPictureData; 54 use crate::codec::h264::picture::Reference; 55 use crate::decoder::stateless::h264::get_raster_from_zigzag_4x4; 56 use crate::decoder::stateless::h264::get_raster_from_zigzag_8x8; 57 58 impl From<&Sps> for v4l2_ctrl_h264_sps { from(sps: &Sps) -> Self59 fn from(sps: &Sps) -> Self { 60 let mut constraint_set_flags: u32 = 0; 61 if sps.constraint_set0_flag { 62 constraint_set_flags |= V4L2_H264_SPS_CONSTRAINT_SET0_FLAG; 63 } 64 if sps.constraint_set1_flag { 65 constraint_set_flags |= V4L2_H264_SPS_CONSTRAINT_SET1_FLAG; 66 } 67 if sps.constraint_set2_flag { 68 constraint_set_flags |= V4L2_H264_SPS_CONSTRAINT_SET2_FLAG; 69 } 70 if sps.constraint_set3_flag { 71 constraint_set_flags |= V4L2_H264_SPS_CONSTRAINT_SET3_FLAG; 72 } 73 if sps.constraint_set4_flag { 74 constraint_set_flags |= V4L2_H264_SPS_CONSTRAINT_SET4_FLAG; 75 } 76 if sps.constraint_set5_flag { 77 constraint_set_flags |= V4L2_H264_SPS_CONSTRAINT_SET5_FLAG; 78 } 79 let mut flags: u32 = 0; 80 if sps.separate_colour_plane_flag { 81 flags |= V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE; 82 } 83 if sps.qpprime_y_zero_transform_bypass_flag { 84 flags |= V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS; 85 } 86 if sps.delta_pic_order_always_zero_flag { 87 flags |= V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO; 88 } 89 if sps.gaps_in_frame_num_value_allowed_flag { 90 flags |= V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED; 91 } 92 if sps.frame_mbs_only_flag { 93 flags |= V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY; 94 } 95 if sps.mb_adaptive_frame_field_flag { 96 flags |= V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD; 97 } 98 if sps.direct_8x8_inference_flag { 99 flags |= V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE; 100 } 101 Self { 102 profile_idc: sps.profile_idc, 103 constraint_set_flags: constraint_set_flags as u8, 104 level_idc: sps.level_idc as u8, 105 seq_parameter_set_id: sps.seq_parameter_set_id, 106 chroma_format_idc: sps.chroma_format_idc, 107 bit_depth_luma_minus8: sps.bit_depth_luma_minus8, 108 bit_depth_chroma_minus8: sps.bit_depth_chroma_minus8, 109 log2_max_frame_num_minus4: sps.log2_max_frame_num_minus4, 110 pic_order_cnt_type: sps.pic_order_cnt_type, 111 log2_max_pic_order_cnt_lsb_minus4: sps.log2_max_pic_order_cnt_lsb_minus4, 112 max_num_ref_frames: sps.max_num_ref_frames as u8, 113 num_ref_frames_in_pic_order_cnt_cycle: sps.num_ref_frames_in_pic_order_cnt_cycle, 114 offset_for_ref_frame: sps.offset_for_ref_frame, 115 offset_for_non_ref_pic: sps.offset_for_non_ref_pic, 116 offset_for_top_to_bottom_field: sps.offset_for_top_to_bottom_field, 117 pic_width_in_mbs_minus1: sps.pic_width_in_mbs_minus1 as u16, 118 pic_height_in_map_units_minus1: sps.pic_height_in_map_units_minus1 as u16, 119 flags, 120 ..Default::default() 121 } 122 } 123 } 124 125 impl From<&Pps> for v4l2_ctrl_h264_pps { from(pps: &Pps) -> Self126 fn from(pps: &Pps) -> Self { 127 let mut flags: u32 = 0; 128 if pps.entropy_coding_mode_flag { 129 flags |= V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE; 130 } 131 if pps.bottom_field_pic_order_in_frame_present_flag { 132 flags |= V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT; 133 } 134 if pps.weighted_pred_flag { 135 flags |= V4L2_H264_PPS_FLAG_WEIGHTED_PRED; 136 } 137 if pps.deblocking_filter_control_present_flag { 138 flags |= V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT; 139 } 140 if pps.constrained_intra_pred_flag { 141 flags |= V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED; 142 } 143 if pps.redundant_pic_cnt_present_flag { 144 flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT; 145 } 146 if pps.transform_8x8_mode_flag { 147 flags |= V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE; 148 } 149 if pps.pic_scaling_matrix_present_flag { 150 flags |= V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT; 151 } 152 Self { 153 pic_parameter_set_id: pps.pic_parameter_set_id, 154 seq_parameter_set_id: pps.seq_parameter_set_id, 155 num_slice_groups_minus1: pps.num_slice_groups_minus1 as u8, 156 num_ref_idx_l0_default_active_minus1: pps.num_ref_idx_l0_default_active_minus1, 157 num_ref_idx_l1_default_active_minus1: pps.num_ref_idx_l1_default_active_minus1, 158 weighted_bipred_idc: pps.weighted_bipred_idc, 159 pic_init_qp_minus26: pps.pic_init_qp_minus26, 160 pic_init_qs_minus26: pps.pic_init_qs_minus26, 161 chroma_qp_index_offset: pps.chroma_qp_index_offset, 162 second_chroma_qp_index_offset: pps.second_chroma_qp_index_offset, 163 flags: flags as u16, 164 ..Default::default() 165 } 166 } 167 } 168 169 impl From<&Pps> for v4l2_ctrl_h264_scaling_matrix { from(pps: &Pps) -> Self170 fn from(pps: &Pps) -> Self { 171 let mut scaling_list_4x4 = [[0; 16]; 6]; 172 let mut scaling_list_8x8 = [[0; 64]; 6]; 173 174 (0..6).for_each(|i| { 175 get_raster_from_zigzag_4x4(pps.scaling_lists_4x4[i], &mut scaling_list_4x4[i]); 176 }); 177 178 (0..2).for_each(|i| { 179 get_raster_from_zigzag_8x8(pps.scaling_lists_8x8[i], &mut scaling_list_8x8[i]); 180 }); 181 182 Self { scaling_list_4x4, scaling_list_8x8 } 183 } 184 } 185 186 pub struct V4l2CtrlH264DpbEntry { 187 pub timestamp: u64, 188 pub pic: RcPictureData, 189 } 190 191 impl From<&V4l2CtrlH264DpbEntry> for v4l2_h264_dpb_entry { from(dpb: &V4l2CtrlH264DpbEntry) -> Self192 fn from(dpb: &V4l2CtrlH264DpbEntry) -> Self { 193 let pic: &PictureData = &dpb.pic.borrow(); 194 // TODO DCHECK_EQ(pic->field, H264Picture::FIELD_NONE) 195 // TODO << "Interlacing not supported"; 196 197 let (frame_num, pic_num): (u16, u32) = match pic.reference() { 198 Reference::LongTerm => (pic.long_term_pic_num as u16, pic.long_term_frame_idx), 199 _ => (pic.frame_num as u16, pic.pic_num as u32), 200 }; 201 202 let mut flags: u32 = V4L2_H264_DPB_ENTRY_FLAG_VALID; 203 if matches!(pic.reference(), Reference::LongTerm | Reference::ShortTerm) { 204 flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; 205 } 206 if matches!(pic.reference(), Reference::LongTerm) { 207 flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; 208 } 209 210 Self { 211 reference_ts: dpb.timestamp * 1000, // usec to nsec 212 frame_num, 213 pic_num, 214 fields: V4L2_H264_FRAME_REF as u8, 215 top_field_order_cnt: pic.top_field_order_cnt, 216 bottom_field_order_cnt: pic.bottom_field_order_cnt, 217 flags, 218 ..Default::default() 219 } 220 } 221 } 222 223 #[derive(Default)] 224 pub struct V4l2CtrlH264DecodeParams { 225 handle: v4l2_ctrl_h264_decode_params, 226 } 227 228 impl V4l2CtrlH264DecodeParams { new() -> Self229 pub fn new() -> Self { 230 Default::default() 231 } set_picture_data(&mut self, pic: &PictureData) -> &mut Self232 pub fn set_picture_data(&mut self, pic: &PictureData) -> &mut Self { 233 self.handle.top_field_order_cnt = pic.top_field_order_cnt; 234 self.handle.bottom_field_order_cnt = pic.bottom_field_order_cnt; 235 self.handle.flags |= match pic.field { 236 Field::Top => V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC, 237 Field::Bottom => { 238 V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC | V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 239 } 240 _ => 0, 241 }; 242 self.handle.flags |= match pic.is_idr { 243 IsIdr::Yes { idr_pic_id: _ } => V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC, 244 _ => 0, 245 }; 246 self.handle.nal_ref_idc = pic.nal_ref_idc as u16; 247 self 248 } set_dpb_entries(&mut self, dpb: Vec<V4l2CtrlH264DpbEntry>) -> &mut Self249 pub fn set_dpb_entries(&mut self, dpb: Vec<V4l2CtrlH264DpbEntry>) -> &mut Self { 250 for i in 0..dpb.len() { 251 self.handle.dpb[i] = v4l2_h264_dpb_entry::from(&dpb[i]); 252 } 253 self 254 } set_slice_header(&mut self, slice_header: &SliceHeader) -> &mut Self255 pub fn set_slice_header(&mut self, slice_header: &SliceHeader) -> &mut Self { 256 self.handle.frame_num = slice_header.frame_num; 257 self.handle.idr_pic_id = slice_header.idr_pic_id; 258 self.handle.pic_order_cnt_lsb = slice_header.pic_order_cnt_lsb; 259 self.handle.delta_pic_order_cnt_bottom = slice_header.delta_pic_order_cnt_bottom; 260 self.handle.delta_pic_order_cnt0 = slice_header.delta_pic_order_cnt[0]; 261 self.handle.delta_pic_order_cnt1 = slice_header.delta_pic_order_cnt[1]; 262 self.handle.dec_ref_pic_marking_bit_size = slice_header.dec_ref_pic_marking_bit_size as u32; 263 self.handle.pic_order_cnt_bit_size = slice_header.pic_order_cnt_bit_size as u32; 264 self 265 } 266 } 267 268 impl From<&V4l2CtrlH264DecodeParams> for SafeExtControl<H264DecodeParams> { from(decode_params: &V4l2CtrlH264DecodeParams) -> Self269 fn from(decode_params: &V4l2CtrlH264DecodeParams) -> Self { 270 SafeExtControl::<H264DecodeParams>::from(decode_params.handle) 271 } 272 } 273 274 pub enum V4l2CtrlH264DecodeMode { 275 SliceBased = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED as isize, 276 FrameBased = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED as isize, 277 } 278 279 impl From<V4l2CtrlH264DecodeMode> for SafeExtControl<H264DecodeMode> { from(decode_mode: V4l2CtrlH264DecodeMode) -> Self280 fn from(decode_mode: V4l2CtrlH264DecodeMode) -> Self { 281 SafeExtControl::<H264DecodeMode>::from_value(decode_mode as i32) 282 } 283 } 284 285 impl From<V4l2CtrlH264StartCode> for SafeExtControl<H264StartCode> { from(decode_mode: V4l2CtrlH264StartCode) -> Self286 fn from(decode_mode: V4l2CtrlH264StartCode) -> Self { 287 SafeExtControl::<H264StartCode>::from_value(decode_mode as i32) 288 } 289 } 290 291 pub enum V4l2CtrlH264StartCode { 292 None = V4L2_STATELESS_H264_START_CODE_NONE as isize, 293 AnnexB = V4L2_STATELESS_H264_START_CODE_ANNEX_B as isize, 294 } 295