xref: /linux/drivers/media/platform/allegro-dvt/nal-h264.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1d74d4e23SMichael Tretter // SPDX-License-Identifier: GPL-2.0
2d74d4e23SMichael Tretter /*
3d74d4e23SMichael Tretter  * Copyright (C) 2019 Pengutronix, Michael Tretter <kernel@pengutronix.de>
4d74d4e23SMichael Tretter  *
5d74d4e23SMichael Tretter  * Convert NAL units between raw byte sequence payloads (RBSP) and C structs
6d74d4e23SMichael Tretter  *
7d74d4e23SMichael Tretter  * The conversion is defined in "ITU-T Rec. H.264 (04/2017) Advanced video
8d74d4e23SMichael Tretter  * coding for generic audiovisual services". Decoder drivers may use the
9d74d4e23SMichael Tretter  * parser to parse RBSP from encoded streams and configure the hardware, if
10d74d4e23SMichael Tretter  * the hardware is not able to parse RBSP itself.  Encoder drivers may use the
11d74d4e23SMichael Tretter  * generator to generate the RBSP for SPS/PPS nal units and add them to the
12d74d4e23SMichael Tretter  * encoded stream if the hardware does not generate the units.
13d74d4e23SMichael Tretter  */
14d74d4e23SMichael Tretter 
15d74d4e23SMichael Tretter #include <linux/kernel.h>
16d74d4e23SMichael Tretter #include <linux/types.h>
17d74d4e23SMichael Tretter #include <linux/string.h>
18d74d4e23SMichael Tretter #include <linux/v4l2-controls.h>
19d74d4e23SMichael Tretter 
20d74d4e23SMichael Tretter #include <linux/device.h>
21d74d4e23SMichael Tretter #include <linux/export.h>
22d74d4e23SMichael Tretter #include <linux/log2.h>
23d74d4e23SMichael Tretter 
24d74d4e23SMichael Tretter #include "nal-h264.h"
2525644288SMichael Tretter #include "nal-rbsp.h"
26d74d4e23SMichael Tretter 
27d74d4e23SMichael Tretter /*
28*a4c3793eSMauro Carvalho Chehab  * See Rec. ITU-T H.264 (04/2017) Table 7-1 - NAL unit type codes, syntax
29d74d4e23SMichael Tretter  * element categories, and NAL unit type classes
30d74d4e23SMichael Tretter  */
31d74d4e23SMichael Tretter enum nal_unit_type {
32d74d4e23SMichael Tretter 	SEQUENCE_PARAMETER_SET = 7,
33d74d4e23SMichael Tretter 	PICTURE_PARAMETER_SET = 8,
34d74d4e23SMichael Tretter 	FILLER_DATA = 12,
35d74d4e23SMichael Tretter };
36d74d4e23SMichael Tretter 
nal_h264_write_start_code_prefix(struct rbsp * rbsp)37d74d4e23SMichael Tretter static void nal_h264_write_start_code_prefix(struct rbsp *rbsp)
38d74d4e23SMichael Tretter {
39d74d4e23SMichael Tretter 	u8 *p = rbsp->data + DIV_ROUND_UP(rbsp->pos, 8);
40d74d4e23SMichael Tretter 	int i = 4;
41d74d4e23SMichael Tretter 
42d74d4e23SMichael Tretter 	if (DIV_ROUND_UP(rbsp->pos, 8) + i > rbsp->size) {
43d74d4e23SMichael Tretter 		rbsp->error = -EINVAL;
44d74d4e23SMichael Tretter 		return;
45d74d4e23SMichael Tretter 	}
46d74d4e23SMichael Tretter 
47d74d4e23SMichael Tretter 	p[0] = 0x00;
48d74d4e23SMichael Tretter 	p[1] = 0x00;
49d74d4e23SMichael Tretter 	p[2] = 0x00;
50d74d4e23SMichael Tretter 	p[3] = 0x01;
51d74d4e23SMichael Tretter 
52d74d4e23SMichael Tretter 	rbsp->pos += i * 8;
53d74d4e23SMichael Tretter }
54d74d4e23SMichael Tretter 
nal_h264_read_start_code_prefix(struct rbsp * rbsp)55d74d4e23SMichael Tretter static void nal_h264_read_start_code_prefix(struct rbsp *rbsp)
56d74d4e23SMichael Tretter {
57d74d4e23SMichael Tretter 	u8 *p = rbsp->data + DIV_ROUND_UP(rbsp->pos, 8);
58d74d4e23SMichael Tretter 	int i = 4;
59d74d4e23SMichael Tretter 
60d74d4e23SMichael Tretter 	if (DIV_ROUND_UP(rbsp->pos, 8) + i > rbsp->size) {
61d74d4e23SMichael Tretter 		rbsp->error = -EINVAL;
62d74d4e23SMichael Tretter 		return;
63d74d4e23SMichael Tretter 	}
64d74d4e23SMichael Tretter 
65d74d4e23SMichael Tretter 	if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x01) {
66d74d4e23SMichael Tretter 		rbsp->error = -EINVAL;
67d74d4e23SMichael Tretter 		return;
68d74d4e23SMichael Tretter 	}
69d74d4e23SMichael Tretter 
70d74d4e23SMichael Tretter 	rbsp->pos += i * 8;
71d74d4e23SMichael Tretter }
72d74d4e23SMichael Tretter 
nal_h264_write_filler_data(struct rbsp * rbsp)73d74d4e23SMichael Tretter static void nal_h264_write_filler_data(struct rbsp *rbsp)
74d74d4e23SMichael Tretter {
75d74d4e23SMichael Tretter 	u8 *p = rbsp->data + DIV_ROUND_UP(rbsp->pos, 8);
76d74d4e23SMichael Tretter 	int i;
77d74d4e23SMichael Tretter 
78d74d4e23SMichael Tretter 	/* Keep 1 byte extra for terminating the NAL unit */
79d74d4e23SMichael Tretter 	i = rbsp->size - DIV_ROUND_UP(rbsp->pos, 8) - 1;
80d74d4e23SMichael Tretter 	memset(p, 0xff, i);
81d74d4e23SMichael Tretter 	rbsp->pos += i * 8;
82d74d4e23SMichael Tretter }
83d74d4e23SMichael Tretter 
nal_h264_read_filler_data(struct rbsp * rbsp)84d74d4e23SMichael Tretter static void nal_h264_read_filler_data(struct rbsp *rbsp)
85d74d4e23SMichael Tretter {
86d74d4e23SMichael Tretter 	u8 *p = rbsp->data + DIV_ROUND_UP(rbsp->pos, 8);
87d74d4e23SMichael Tretter 
88d74d4e23SMichael Tretter 	while (*p == 0xff) {
89d74d4e23SMichael Tretter 		if (DIV_ROUND_UP(rbsp->pos, 8) > rbsp->size) {
90d74d4e23SMichael Tretter 			rbsp->error = -EINVAL;
91d74d4e23SMichael Tretter 			return;
92d74d4e23SMichael Tretter 		}
93d74d4e23SMichael Tretter 
94d74d4e23SMichael Tretter 		p++;
95d74d4e23SMichael Tretter 		rbsp->pos += 8;
96d74d4e23SMichael Tretter 	}
97d74d4e23SMichael Tretter }
98d74d4e23SMichael Tretter 
nal_h264_rbsp_hrd_parameters(struct rbsp * rbsp,struct nal_h264_hrd_parameters * hrd)99d74d4e23SMichael Tretter static void nal_h264_rbsp_hrd_parameters(struct rbsp *rbsp,
100d74d4e23SMichael Tretter 					 struct nal_h264_hrd_parameters *hrd)
101d74d4e23SMichael Tretter {
102d74d4e23SMichael Tretter 	unsigned int i;
103d74d4e23SMichael Tretter 
104d74d4e23SMichael Tretter 	if (!hrd) {
105d74d4e23SMichael Tretter 		rbsp->error = -EINVAL;
106d74d4e23SMichael Tretter 		return;
107d74d4e23SMichael Tretter 	}
108d74d4e23SMichael Tretter 
109d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &hrd->cpb_cnt_minus1);
110d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 4, &hrd->bit_rate_scale);
111d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 4, &hrd->cpb_size_scale);
112d74d4e23SMichael Tretter 
113d74d4e23SMichael Tretter 	for (i = 0; i <= hrd->cpb_cnt_minus1; i++) {
114d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &hrd->bit_rate_value_minus1[i]);
115d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &hrd->cpb_size_value_minus1[i]);
116d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &hrd->cbr_flag[i]);
117d74d4e23SMichael Tretter 	}
118d74d4e23SMichael Tretter 
119d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 5, &hrd->initial_cpb_removal_delay_length_minus1);
120d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 5, &hrd->cpb_removal_delay_length_minus1);
121d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 5, &hrd->dpb_output_delay_length_minus1);
122d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 5, &hrd->time_offset_length);
123d74d4e23SMichael Tretter }
124d74d4e23SMichael Tretter 
nal_h264_rbsp_vui_parameters(struct rbsp * rbsp,struct nal_h264_vui_parameters * vui)125d74d4e23SMichael Tretter static void nal_h264_rbsp_vui_parameters(struct rbsp *rbsp,
126d74d4e23SMichael Tretter 					 struct nal_h264_vui_parameters *vui)
127d74d4e23SMichael Tretter {
128d74d4e23SMichael Tretter 	if (!vui) {
129d74d4e23SMichael Tretter 		rbsp->error = -EINVAL;
130d74d4e23SMichael Tretter 		return;
131d74d4e23SMichael Tretter 	}
132d74d4e23SMichael Tretter 
133d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->aspect_ratio_info_present_flag);
134d74d4e23SMichael Tretter 	if (vui->aspect_ratio_info_present_flag) {
135d74d4e23SMichael Tretter 		rbsp_bits(rbsp, 8, &vui->aspect_ratio_idc);
136d74d4e23SMichael Tretter 		if (vui->aspect_ratio_idc == 255) {
137d74d4e23SMichael Tretter 			rbsp_bits(rbsp, 16, &vui->sar_width);
138d74d4e23SMichael Tretter 			rbsp_bits(rbsp, 16, &vui->sar_height);
139d74d4e23SMichael Tretter 		}
140d74d4e23SMichael Tretter 	}
141d74d4e23SMichael Tretter 
142d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->overscan_info_present_flag);
143d74d4e23SMichael Tretter 	if (vui->overscan_info_present_flag)
144d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &vui->overscan_appropriate_flag);
145d74d4e23SMichael Tretter 
146d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->video_signal_type_present_flag);
147d74d4e23SMichael Tretter 	if (vui->video_signal_type_present_flag) {
148d74d4e23SMichael Tretter 		rbsp_bits(rbsp, 3, &vui->video_format);
149d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &vui->video_full_range_flag);
150d74d4e23SMichael Tretter 
151d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &vui->colour_description_present_flag);
152d74d4e23SMichael Tretter 		if (vui->colour_description_present_flag) {
153d74d4e23SMichael Tretter 			rbsp_bits(rbsp, 8, &vui->colour_primaries);
154d74d4e23SMichael Tretter 			rbsp_bits(rbsp, 8, &vui->transfer_characteristics);
155d74d4e23SMichael Tretter 			rbsp_bits(rbsp, 8, &vui->matrix_coefficients);
156d74d4e23SMichael Tretter 		}
157d74d4e23SMichael Tretter 	}
158d74d4e23SMichael Tretter 
159d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->chroma_loc_info_present_flag);
160d74d4e23SMichael Tretter 	if (vui->chroma_loc_info_present_flag) {
161d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->chroma_sample_loc_type_top_field);
162d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->chroma_sample_loc_type_bottom_field);
163d74d4e23SMichael Tretter 	}
164d74d4e23SMichael Tretter 
165d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->timing_info_present_flag);
166d74d4e23SMichael Tretter 	if (vui->timing_info_present_flag) {
167d74d4e23SMichael Tretter 		rbsp_bits(rbsp, 32, &vui->num_units_in_tick);
168d74d4e23SMichael Tretter 		rbsp_bits(rbsp, 32, &vui->time_scale);
169d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &vui->fixed_frame_rate_flag);
170d74d4e23SMichael Tretter 	}
171d74d4e23SMichael Tretter 
172d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->nal_hrd_parameters_present_flag);
173d74d4e23SMichael Tretter 	if (vui->nal_hrd_parameters_present_flag)
174d74d4e23SMichael Tretter 		nal_h264_rbsp_hrd_parameters(rbsp, &vui->nal_hrd_parameters);
175d74d4e23SMichael Tretter 
176d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->vcl_hrd_parameters_present_flag);
177d74d4e23SMichael Tretter 	if (vui->vcl_hrd_parameters_present_flag)
178d74d4e23SMichael Tretter 		nal_h264_rbsp_hrd_parameters(rbsp, &vui->vcl_hrd_parameters);
179d74d4e23SMichael Tretter 
180d74d4e23SMichael Tretter 	if (vui->nal_hrd_parameters_present_flag ||
181d74d4e23SMichael Tretter 	    vui->vcl_hrd_parameters_present_flag)
182d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &vui->low_delay_hrd_flag);
183d74d4e23SMichael Tretter 
184d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->pic_struct_present_flag);
185d74d4e23SMichael Tretter 
186d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &vui->bitstream_restriction_flag);
187d74d4e23SMichael Tretter 	if (vui->bitstream_restriction_flag) {
188d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &vui->motion_vectors_over_pic_boundaries_flag);
189d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->max_bytes_per_pic_denom);
190d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->max_bits_per_mb_denom);
191d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->log2_max_mv_length_horizontal);
192d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->log21_max_mv_length_vertical);
193d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->max_num_reorder_frames);
194d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &vui->max_dec_frame_buffering);
195d74d4e23SMichael Tretter 	}
196d74d4e23SMichael Tretter }
197d74d4e23SMichael Tretter 
nal_h264_rbsp_sps(struct rbsp * rbsp,struct nal_h264_sps * sps)198d74d4e23SMichael Tretter static void nal_h264_rbsp_sps(struct rbsp *rbsp, struct nal_h264_sps *sps)
199d74d4e23SMichael Tretter {
200d74d4e23SMichael Tretter 	unsigned int i;
201d74d4e23SMichael Tretter 
202d74d4e23SMichael Tretter 	if (!sps) {
203d74d4e23SMichael Tretter 		rbsp->error = -EINVAL;
204d74d4e23SMichael Tretter 		return;
205d74d4e23SMichael Tretter 	}
206d74d4e23SMichael Tretter 
207d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 8, &sps->profile_idc);
208d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->constraint_set0_flag);
209d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->constraint_set1_flag);
210d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->constraint_set2_flag);
211d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->constraint_set3_flag);
212d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->constraint_set4_flag);
213d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->constraint_set5_flag);
214d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 2, &sps->reserved_zero_2bits);
215d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 8, &sps->level_idc);
216d74d4e23SMichael Tretter 
217d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &sps->seq_parameter_set_id);
218d74d4e23SMichael Tretter 
219d74d4e23SMichael Tretter 	if (sps->profile_idc == 100 || sps->profile_idc == 110 ||
220d74d4e23SMichael Tretter 	    sps->profile_idc == 122 || sps->profile_idc == 244 ||
221d74d4e23SMichael Tretter 	    sps->profile_idc == 44 || sps->profile_idc == 83 ||
222d74d4e23SMichael Tretter 	    sps->profile_idc == 86 || sps->profile_idc == 118 ||
223d74d4e23SMichael Tretter 	    sps->profile_idc == 128 || sps->profile_idc == 138 ||
224d74d4e23SMichael Tretter 	    sps->profile_idc == 139 || sps->profile_idc == 134 ||
225d74d4e23SMichael Tretter 	    sps->profile_idc == 135) {
226d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->chroma_format_idc);
227d74d4e23SMichael Tretter 
228d74d4e23SMichael Tretter 		if (sps->chroma_format_idc == 3)
229d74d4e23SMichael Tretter 			rbsp_bit(rbsp, &sps->separate_colour_plane_flag);
230d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->bit_depth_luma_minus8);
231d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->bit_depth_chroma_minus8);
232d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &sps->qpprime_y_zero_transform_bypass_flag);
233d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &sps->seq_scaling_matrix_present_flag);
234d74d4e23SMichael Tretter 		if (sps->seq_scaling_matrix_present_flag)
235d74d4e23SMichael Tretter 			rbsp->error = -EINVAL;
236d74d4e23SMichael Tretter 	}
237d74d4e23SMichael Tretter 
238d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &sps->log2_max_frame_num_minus4);
239d74d4e23SMichael Tretter 
240d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &sps->pic_order_cnt_type);
241d74d4e23SMichael Tretter 	switch (sps->pic_order_cnt_type) {
242d74d4e23SMichael Tretter 	case 0:
243d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->log2_max_pic_order_cnt_lsb_minus4);
244d74d4e23SMichael Tretter 		break;
245d74d4e23SMichael Tretter 	case 1:
246d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &sps->delta_pic_order_always_zero_flag);
247d74d4e23SMichael Tretter 		rbsp_sev(rbsp, &sps->offset_for_non_ref_pic);
248d74d4e23SMichael Tretter 		rbsp_sev(rbsp, &sps->offset_for_top_to_bottom_field);
249d74d4e23SMichael Tretter 
250d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->num_ref_frames_in_pic_order_cnt_cycle);
251d74d4e23SMichael Tretter 		for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
252d74d4e23SMichael Tretter 			rbsp_sev(rbsp, &sps->offset_for_ref_frame[i]);
253d74d4e23SMichael Tretter 		break;
254d74d4e23SMichael Tretter 	default:
255d74d4e23SMichael Tretter 		rbsp->error = -EINVAL;
256d74d4e23SMichael Tretter 		break;
257d74d4e23SMichael Tretter 	}
258d74d4e23SMichael Tretter 
259d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &sps->max_num_ref_frames);
260d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->gaps_in_frame_num_value_allowed_flag);
261d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &sps->pic_width_in_mbs_minus1);
262d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &sps->pic_height_in_map_units_minus1);
263d74d4e23SMichael Tretter 
264d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->frame_mbs_only_flag);
265d74d4e23SMichael Tretter 	if (!sps->frame_mbs_only_flag)
266d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &sps->mb_adaptive_frame_field_flag);
267d74d4e23SMichael Tretter 
268d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->direct_8x8_inference_flag);
269d74d4e23SMichael Tretter 
270d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->frame_cropping_flag);
271d74d4e23SMichael Tretter 	if (sps->frame_cropping_flag) {
272d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->crop_left);
273d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->crop_right);
274d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->crop_top);
275d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &sps->crop_bottom);
276d74d4e23SMichael Tretter 	}
277d74d4e23SMichael Tretter 
278d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &sps->vui_parameters_present_flag);
279d74d4e23SMichael Tretter 	if (sps->vui_parameters_present_flag)
280d74d4e23SMichael Tretter 		nal_h264_rbsp_vui_parameters(rbsp, &sps->vui);
281d74d4e23SMichael Tretter }
282d74d4e23SMichael Tretter 
nal_h264_rbsp_pps(struct rbsp * rbsp,struct nal_h264_pps * pps)283d74d4e23SMichael Tretter static void nal_h264_rbsp_pps(struct rbsp *rbsp, struct nal_h264_pps *pps)
284d74d4e23SMichael Tretter {
285d74d4e23SMichael Tretter 	int i;
286d74d4e23SMichael Tretter 
287d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &pps->pic_parameter_set_id);
288d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &pps->seq_parameter_set_id);
289d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &pps->entropy_coding_mode_flag);
290d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &pps->bottom_field_pic_order_in_frame_present_flag);
291d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &pps->num_slice_groups_minus1);
292d74d4e23SMichael Tretter 	if (pps->num_slice_groups_minus1 > 0) {
293d74d4e23SMichael Tretter 		rbsp_uev(rbsp, &pps->slice_group_map_type);
294d74d4e23SMichael Tretter 		switch (pps->slice_group_map_type) {
295d74d4e23SMichael Tretter 		case 0:
296d74d4e23SMichael Tretter 			for (i = 0; i < pps->num_slice_groups_minus1; i++)
297d74d4e23SMichael Tretter 				rbsp_uev(rbsp, &pps->run_length_minus1[i]);
298d74d4e23SMichael Tretter 			break;
299d74d4e23SMichael Tretter 		case 2:
300d74d4e23SMichael Tretter 			for (i = 0; i < pps->num_slice_groups_minus1; i++) {
301d74d4e23SMichael Tretter 				rbsp_uev(rbsp, &pps->top_left[i]);
302d74d4e23SMichael Tretter 				rbsp_uev(rbsp, &pps->bottom_right[i]);
303d74d4e23SMichael Tretter 			}
304d74d4e23SMichael Tretter 			break;
305d74d4e23SMichael Tretter 		case 3: case 4: case 5:
306d74d4e23SMichael Tretter 			rbsp_bit(rbsp, &pps->slice_group_change_direction_flag);
307d74d4e23SMichael Tretter 			rbsp_uev(rbsp, &pps->slice_group_change_rate_minus1);
308d74d4e23SMichael Tretter 			break;
309d74d4e23SMichael Tretter 		case 6:
310d74d4e23SMichael Tretter 			rbsp_uev(rbsp, &pps->pic_size_in_map_units_minus1);
311d74d4e23SMichael Tretter 			for (i = 0; i < pps->pic_size_in_map_units_minus1; i++)
312d74d4e23SMichael Tretter 				rbsp_bits(rbsp,
313d74d4e23SMichael Tretter 					  order_base_2(pps->num_slice_groups_minus1 + 1),
314d74d4e23SMichael Tretter 					  &pps->slice_group_id[i]);
315d74d4e23SMichael Tretter 			break;
316d74d4e23SMichael Tretter 		default:
317d74d4e23SMichael Tretter 			break;
318d74d4e23SMichael Tretter 		}
319d74d4e23SMichael Tretter 	}
320d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &pps->num_ref_idx_l0_default_active_minus1);
321d74d4e23SMichael Tretter 	rbsp_uev(rbsp, &pps->num_ref_idx_l1_default_active_minus1);
322d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &pps->weighted_pred_flag);
323d74d4e23SMichael Tretter 	rbsp_bits(rbsp, 2, &pps->weighted_bipred_idc);
324d74d4e23SMichael Tretter 	rbsp_sev(rbsp, &pps->pic_init_qp_minus26);
325d74d4e23SMichael Tretter 	rbsp_sev(rbsp, &pps->pic_init_qs_minus26);
326d74d4e23SMichael Tretter 	rbsp_sev(rbsp, &pps->chroma_qp_index_offset);
327d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &pps->deblocking_filter_control_present_flag);
328d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &pps->constrained_intra_pred_flag);
329d74d4e23SMichael Tretter 	rbsp_bit(rbsp, &pps->redundant_pic_cnt_present_flag);
330d74d4e23SMichael Tretter 	if (/* more_rbsp_data() */ false) {
331d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &pps->transform_8x8_mode_flag);
332d74d4e23SMichael Tretter 		rbsp_bit(rbsp, &pps->pic_scaling_matrix_present_flag);
333d74d4e23SMichael Tretter 		if (pps->pic_scaling_matrix_present_flag)
334d74d4e23SMichael Tretter 			rbsp->error = -EINVAL;
335d74d4e23SMichael Tretter 		rbsp_sev(rbsp, &pps->second_chroma_qp_index_offset);
336d74d4e23SMichael Tretter 	}
337d74d4e23SMichael Tretter }
338d74d4e23SMichael Tretter 
339d74d4e23SMichael Tretter /**
340d74d4e23SMichael Tretter  * nal_h264_write_sps() - Write SPS NAL unit into RBSP format
341d74d4e23SMichael Tretter  * @dev: device pointer
342d74d4e23SMichael Tretter  * @dest: the buffer that is filled with RBSP data
343d74d4e23SMichael Tretter  * @n: maximum size of @dest in bytes
344d74d4e23SMichael Tretter  * @sps: &struct nal_h264_sps to convert to RBSP
345d74d4e23SMichael Tretter  *
346d74d4e23SMichael Tretter  * Convert @sps to RBSP data and write it into @dest.
347d74d4e23SMichael Tretter  *
348d74d4e23SMichael Tretter  * The size of the SPS NAL unit is not known in advance and this function will
349d74d4e23SMichael Tretter  * fail, if @dest does not hold sufficient space for the SPS NAL unit.
350d74d4e23SMichael Tretter  *
351d74d4e23SMichael Tretter  * Return: number of bytes written to @dest or negative error code
352d74d4e23SMichael Tretter  */
nal_h264_write_sps(const struct device * dev,void * dest,size_t n,struct nal_h264_sps * sps)353d74d4e23SMichael Tretter ssize_t nal_h264_write_sps(const struct device *dev,
354d74d4e23SMichael Tretter 			   void *dest, size_t n, struct nal_h264_sps *sps)
355d74d4e23SMichael Tretter {
356d74d4e23SMichael Tretter 	struct rbsp rbsp;
357d74d4e23SMichael Tretter 	unsigned int forbidden_zero_bit = 0;
358d74d4e23SMichael Tretter 	unsigned int nal_ref_idc = 0;
359d74d4e23SMichael Tretter 	unsigned int nal_unit_type = SEQUENCE_PARAMETER_SET;
360d74d4e23SMichael Tretter 
361d74d4e23SMichael Tretter 	if (!dest)
362d74d4e23SMichael Tretter 		return -EINVAL;
363d74d4e23SMichael Tretter 
364d74d4e23SMichael Tretter 	rbsp_init(&rbsp, dest, n, &write);
365d74d4e23SMichael Tretter 
366d74d4e23SMichael Tretter 	nal_h264_write_start_code_prefix(&rbsp);
367d74d4e23SMichael Tretter 
368d74d4e23SMichael Tretter 	rbsp_bit(&rbsp, &forbidden_zero_bit);
369d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 2, &nal_ref_idc);
370d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 5, &nal_unit_type);
371d74d4e23SMichael Tretter 
372d74d4e23SMichael Tretter 	nal_h264_rbsp_sps(&rbsp, sps);
373d74d4e23SMichael Tretter 
37425644288SMichael Tretter 	rbsp_trailing_bits(&rbsp);
375d74d4e23SMichael Tretter 
376d74d4e23SMichael Tretter 	if (rbsp.error)
377d74d4e23SMichael Tretter 		return rbsp.error;
378d74d4e23SMichael Tretter 
379d74d4e23SMichael Tretter 	return DIV_ROUND_UP(rbsp.pos, 8);
380d74d4e23SMichael Tretter }
381d74d4e23SMichael Tretter EXPORT_SYMBOL_GPL(nal_h264_write_sps);
382d74d4e23SMichael Tretter 
383d74d4e23SMichael Tretter /**
384d74d4e23SMichael Tretter  * nal_h264_read_sps() - Read SPS NAL unit from RBSP format
385d74d4e23SMichael Tretter  * @dev: device pointer
386d74d4e23SMichael Tretter  * @sps: the &struct nal_h264_sps to fill from the RBSP data
387d74d4e23SMichael Tretter  * @src: the buffer that contains the RBSP data
388d74d4e23SMichael Tretter  * @n: size of @src in bytes
389d74d4e23SMichael Tretter  *
390d74d4e23SMichael Tretter  * Read RBSP data from @src and use it to fill @sps.
391d74d4e23SMichael Tretter  *
392d74d4e23SMichael Tretter  * Return: number of bytes read from @src or negative error code
393d74d4e23SMichael Tretter  */
nal_h264_read_sps(const struct device * dev,struct nal_h264_sps * sps,void * src,size_t n)394d74d4e23SMichael Tretter ssize_t nal_h264_read_sps(const struct device *dev,
395d74d4e23SMichael Tretter 			  struct nal_h264_sps *sps, void *src, size_t n)
396d74d4e23SMichael Tretter {
397d74d4e23SMichael Tretter 	struct rbsp rbsp;
398d74d4e23SMichael Tretter 	unsigned int forbidden_zero_bit;
399d74d4e23SMichael Tretter 	unsigned int nal_ref_idc;
400d74d4e23SMichael Tretter 	unsigned int nal_unit_type;
401d74d4e23SMichael Tretter 
402d74d4e23SMichael Tretter 	if (!src)
403d74d4e23SMichael Tretter 		return -EINVAL;
404d74d4e23SMichael Tretter 
405d74d4e23SMichael Tretter 	rbsp_init(&rbsp, src, n, &read);
406d74d4e23SMichael Tretter 
407d74d4e23SMichael Tretter 	nal_h264_read_start_code_prefix(&rbsp);
408d74d4e23SMichael Tretter 
409d74d4e23SMichael Tretter 	rbsp_bit(&rbsp, &forbidden_zero_bit);
410d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 2, &nal_ref_idc);
411d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 5, &nal_unit_type);
412d74d4e23SMichael Tretter 
413d74d4e23SMichael Tretter 	if (rbsp.error ||
414d74d4e23SMichael Tretter 	    forbidden_zero_bit != 0 ||
415d74d4e23SMichael Tretter 	    nal_ref_idc != 0 ||
416d74d4e23SMichael Tretter 	    nal_unit_type != SEQUENCE_PARAMETER_SET)
417d74d4e23SMichael Tretter 		return -EINVAL;
418d74d4e23SMichael Tretter 
419d74d4e23SMichael Tretter 	nal_h264_rbsp_sps(&rbsp, sps);
420d74d4e23SMichael Tretter 
42125644288SMichael Tretter 	rbsp_trailing_bits(&rbsp);
422d74d4e23SMichael Tretter 
423d74d4e23SMichael Tretter 	if (rbsp.error)
424d74d4e23SMichael Tretter 		return rbsp.error;
425d74d4e23SMichael Tretter 
426d74d4e23SMichael Tretter 	return DIV_ROUND_UP(rbsp.pos, 8);
427d74d4e23SMichael Tretter }
428d74d4e23SMichael Tretter EXPORT_SYMBOL_GPL(nal_h264_read_sps);
429d74d4e23SMichael Tretter 
430d74d4e23SMichael Tretter /**
431d74d4e23SMichael Tretter  * nal_h264_write_pps() - Write PPS NAL unit into RBSP format
432d74d4e23SMichael Tretter  * @dev: device pointer
433d74d4e23SMichael Tretter  * @dest: the buffer that is filled with RBSP data
434d74d4e23SMichael Tretter  * @n: maximum size of @dest in bytes
435d74d4e23SMichael Tretter  * @pps: &struct nal_h264_pps to convert to RBSP
436d74d4e23SMichael Tretter  *
437d74d4e23SMichael Tretter  * Convert @pps to RBSP data and write it into @dest.
438d74d4e23SMichael Tretter  *
439d74d4e23SMichael Tretter  * The size of the PPS NAL unit is not known in advance and this function will
440d74d4e23SMichael Tretter  * fail, if @dest does not hold sufficient space for the PPS NAL unit.
441d74d4e23SMichael Tretter  *
442d74d4e23SMichael Tretter  * Return: number of bytes written to @dest or negative error code
443d74d4e23SMichael Tretter  */
nal_h264_write_pps(const struct device * dev,void * dest,size_t n,struct nal_h264_pps * pps)444d74d4e23SMichael Tretter ssize_t nal_h264_write_pps(const struct device *dev,
445d74d4e23SMichael Tretter 			   void *dest, size_t n, struct nal_h264_pps *pps)
446d74d4e23SMichael Tretter {
447d74d4e23SMichael Tretter 	struct rbsp rbsp;
448d74d4e23SMichael Tretter 	unsigned int forbidden_zero_bit = 0;
449d74d4e23SMichael Tretter 	unsigned int nal_ref_idc = 0;
450d74d4e23SMichael Tretter 	unsigned int nal_unit_type = PICTURE_PARAMETER_SET;
451d74d4e23SMichael Tretter 
452d74d4e23SMichael Tretter 	if (!dest)
453d74d4e23SMichael Tretter 		return -EINVAL;
454d74d4e23SMichael Tretter 
455d74d4e23SMichael Tretter 	rbsp_init(&rbsp, dest, n, &write);
456d74d4e23SMichael Tretter 
457d74d4e23SMichael Tretter 	nal_h264_write_start_code_prefix(&rbsp);
458d74d4e23SMichael Tretter 
459d74d4e23SMichael Tretter 	/* NAL unit header */
460d74d4e23SMichael Tretter 	rbsp_bit(&rbsp, &forbidden_zero_bit);
461d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 2, &nal_ref_idc);
462d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 5, &nal_unit_type);
463d74d4e23SMichael Tretter 
464d74d4e23SMichael Tretter 	nal_h264_rbsp_pps(&rbsp, pps);
465d74d4e23SMichael Tretter 
46625644288SMichael Tretter 	rbsp_trailing_bits(&rbsp);
467d74d4e23SMichael Tretter 
468d74d4e23SMichael Tretter 	if (rbsp.error)
469d74d4e23SMichael Tretter 		return rbsp.error;
470d74d4e23SMichael Tretter 
471d74d4e23SMichael Tretter 	return DIV_ROUND_UP(rbsp.pos, 8);
472d74d4e23SMichael Tretter }
473d74d4e23SMichael Tretter EXPORT_SYMBOL_GPL(nal_h264_write_pps);
474d74d4e23SMichael Tretter 
475d74d4e23SMichael Tretter /**
476d74d4e23SMichael Tretter  * nal_h264_read_pps() - Read PPS NAL unit from RBSP format
477d74d4e23SMichael Tretter  * @dev: device pointer
478d74d4e23SMichael Tretter  * @pps: the &struct nal_h264_pps to fill from the RBSP data
479d74d4e23SMichael Tretter  * @src: the buffer that contains the RBSP data
480d74d4e23SMichael Tretter  * @n: size of @src in bytes
481d74d4e23SMichael Tretter  *
482d74d4e23SMichael Tretter  * Read RBSP data from @src and use it to fill @pps.
483d74d4e23SMichael Tretter  *
484d74d4e23SMichael Tretter  * Return: number of bytes read from @src or negative error code
485d74d4e23SMichael Tretter  */
nal_h264_read_pps(const struct device * dev,struct nal_h264_pps * pps,void * src,size_t n)486d74d4e23SMichael Tretter ssize_t nal_h264_read_pps(const struct device *dev,
487d74d4e23SMichael Tretter 			  struct nal_h264_pps *pps, void *src, size_t n)
488d74d4e23SMichael Tretter {
489d74d4e23SMichael Tretter 	struct rbsp rbsp;
490d74d4e23SMichael Tretter 
491d74d4e23SMichael Tretter 	if (!src)
492d74d4e23SMichael Tretter 		return -EINVAL;
493d74d4e23SMichael Tretter 
494d74d4e23SMichael Tretter 	rbsp_init(&rbsp, src, n, &read);
495d74d4e23SMichael Tretter 
496d74d4e23SMichael Tretter 	nal_h264_read_start_code_prefix(&rbsp);
497d74d4e23SMichael Tretter 
498d74d4e23SMichael Tretter 	/* NAL unit header */
499d74d4e23SMichael Tretter 	rbsp.pos += 8;
500d74d4e23SMichael Tretter 
501d74d4e23SMichael Tretter 	nal_h264_rbsp_pps(&rbsp, pps);
502d74d4e23SMichael Tretter 
50325644288SMichael Tretter 	rbsp_trailing_bits(&rbsp);
504d74d4e23SMichael Tretter 
505d74d4e23SMichael Tretter 	if (rbsp.error)
506d74d4e23SMichael Tretter 		return rbsp.error;
507d74d4e23SMichael Tretter 
508d74d4e23SMichael Tretter 	return DIV_ROUND_UP(rbsp.pos, 8);
509d74d4e23SMichael Tretter }
510d74d4e23SMichael Tretter EXPORT_SYMBOL_GPL(nal_h264_read_pps);
511d74d4e23SMichael Tretter 
512d74d4e23SMichael Tretter /**
513d74d4e23SMichael Tretter  * nal_h264_write_filler() - Write filler data RBSP
514d74d4e23SMichael Tretter  * @dev: device pointer
515d74d4e23SMichael Tretter  * @dest: buffer to fill with filler data
516d74d4e23SMichael Tretter  * @n: size of the buffer to fill with filler data
517d74d4e23SMichael Tretter  *
518d74d4e23SMichael Tretter  * Write a filler data RBSP to @dest with a size of @n bytes and return the
519d74d4e23SMichael Tretter  * number of written filler data bytes.
520d74d4e23SMichael Tretter  *
521d74d4e23SMichael Tretter  * Use this function to generate dummy data in an RBSP data stream that can be
522d74d4e23SMichael Tretter  * safely ignored by h264 decoders.
523d74d4e23SMichael Tretter  *
524d74d4e23SMichael Tretter  * The RBSP format of the filler data is specified in Rec. ITU-T H.264
525d74d4e23SMichael Tretter  * (04/2017) 7.3.2.7 Filler data RBSP syntax.
526d74d4e23SMichael Tretter  *
527d74d4e23SMichael Tretter  * Return: number of filler data bytes (including marker) or negative error
528d74d4e23SMichael Tretter  */
nal_h264_write_filler(const struct device * dev,void * dest,size_t n)529d74d4e23SMichael Tretter ssize_t nal_h264_write_filler(const struct device *dev, void *dest, size_t n)
530d74d4e23SMichael Tretter {
531d74d4e23SMichael Tretter 	struct rbsp rbsp;
532d74d4e23SMichael Tretter 	unsigned int forbidden_zero_bit = 0;
533d74d4e23SMichael Tretter 	unsigned int nal_ref_idc = 0;
534d74d4e23SMichael Tretter 	unsigned int nal_unit_type = FILLER_DATA;
535d74d4e23SMichael Tretter 
536d74d4e23SMichael Tretter 	if (!dest)
537d74d4e23SMichael Tretter 		return -EINVAL;
538d74d4e23SMichael Tretter 
539d74d4e23SMichael Tretter 	rbsp_init(&rbsp, dest, n, &write);
540d74d4e23SMichael Tretter 
541d74d4e23SMichael Tretter 	nal_h264_write_start_code_prefix(&rbsp);
542d74d4e23SMichael Tretter 
543d74d4e23SMichael Tretter 	rbsp_bit(&rbsp, &forbidden_zero_bit);
544d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 2, &nal_ref_idc);
545d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 5, &nal_unit_type);
546d74d4e23SMichael Tretter 
547d74d4e23SMichael Tretter 	nal_h264_write_filler_data(&rbsp);
548d74d4e23SMichael Tretter 
54925644288SMichael Tretter 	rbsp_trailing_bits(&rbsp);
550d74d4e23SMichael Tretter 
551d74d4e23SMichael Tretter 	return DIV_ROUND_UP(rbsp.pos, 8);
552d74d4e23SMichael Tretter }
553d74d4e23SMichael Tretter EXPORT_SYMBOL_GPL(nal_h264_write_filler);
554d74d4e23SMichael Tretter 
555d74d4e23SMichael Tretter /**
556d74d4e23SMichael Tretter  * nal_h264_read_filler() - Read filler data RBSP
557d74d4e23SMichael Tretter  * @dev: device pointer
558d74d4e23SMichael Tretter  * @src: buffer with RBSP data that is read
559d74d4e23SMichael Tretter  * @n: maximum size of src that shall be read
560d74d4e23SMichael Tretter  *
561d74d4e23SMichael Tretter  * Read a filler data RBSP from @src up to a maximum size of @n bytes and
562d74d4e23SMichael Tretter  * return the size of the filler data in bytes including the marker.
563d74d4e23SMichael Tretter  *
564d74d4e23SMichael Tretter  * This function is used to parse filler data and skip the respective bytes in
565d74d4e23SMichael Tretter  * the RBSP data.
566d74d4e23SMichael Tretter  *
567d74d4e23SMichael Tretter  * The RBSP format of the filler data is specified in Rec. ITU-T H.264
568d74d4e23SMichael Tretter  * (04/2017) 7.3.2.7 Filler data RBSP syntax.
569d74d4e23SMichael Tretter  *
570d74d4e23SMichael Tretter  * Return: number of filler data bytes (including marker) or negative error
571d74d4e23SMichael Tretter  */
nal_h264_read_filler(const struct device * dev,void * src,size_t n)572d74d4e23SMichael Tretter ssize_t nal_h264_read_filler(const struct device *dev, void *src, size_t n)
573d74d4e23SMichael Tretter {
574d74d4e23SMichael Tretter 	struct rbsp rbsp;
575d74d4e23SMichael Tretter 	unsigned int forbidden_zero_bit;
576d74d4e23SMichael Tretter 	unsigned int nal_ref_idc;
577d74d4e23SMichael Tretter 	unsigned int nal_unit_type;
578d74d4e23SMichael Tretter 
579d74d4e23SMichael Tretter 	if (!src)
580d74d4e23SMichael Tretter 		return -EINVAL;
581d74d4e23SMichael Tretter 
582d74d4e23SMichael Tretter 	rbsp_init(&rbsp, src, n, &read);
583d74d4e23SMichael Tretter 
584d74d4e23SMichael Tretter 	nal_h264_read_start_code_prefix(&rbsp);
585d74d4e23SMichael Tretter 
586d74d4e23SMichael Tretter 	rbsp_bit(&rbsp, &forbidden_zero_bit);
587d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 2, &nal_ref_idc);
588d74d4e23SMichael Tretter 	rbsp_bits(&rbsp, 5, &nal_unit_type);
589d74d4e23SMichael Tretter 
590d74d4e23SMichael Tretter 	if (rbsp.error)
591d74d4e23SMichael Tretter 		return rbsp.error;
592d74d4e23SMichael Tretter 	if (forbidden_zero_bit != 0 ||
593d74d4e23SMichael Tretter 	    nal_ref_idc != 0 ||
594d74d4e23SMichael Tretter 	    nal_unit_type != FILLER_DATA)
595d74d4e23SMichael Tretter 		return -EINVAL;
596d74d4e23SMichael Tretter 
597d74d4e23SMichael Tretter 	nal_h264_read_filler_data(&rbsp);
59825644288SMichael Tretter 	rbsp_trailing_bits(&rbsp);
599d74d4e23SMichael Tretter 
600d74d4e23SMichael Tretter 	if (rbsp.error)
601d74d4e23SMichael Tretter 		return rbsp.error;
602d74d4e23SMichael Tretter 
603d74d4e23SMichael Tretter 	return DIV_ROUND_UP(rbsp.pos, 8);
604d74d4e23SMichael Tretter }
605d74d4e23SMichael Tretter EXPORT_SYMBOL_GPL(nal_h264_read_filler);
606