• 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 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