1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * TW5864 driver - H.264 headers generation functions
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016 Bluecherry, LLC <maintainers@bluecherrydvr.com>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/log2.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "tw5864.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun static u8 marker[] = { 0x00, 0x00, 0x00, 0x01 };
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun /*
15*4882a593Smuzhiyun * Exponential-Golomb coding functions
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * These functions are used for generation of H.264 bitstream headers.
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * This code is derived from tw5864 reference driver by manufacturers, which
20*4882a593Smuzhiyun * itself apparently was derived from x264 project.
21*4882a593Smuzhiyun */
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /* Bitstream writing context */
24*4882a593Smuzhiyun struct bs {
25*4882a593Smuzhiyun u8 *buf; /* pointer to buffer beginning */
26*4882a593Smuzhiyun u8 *buf_end; /* pointer to buffer end */
27*4882a593Smuzhiyun u8 *ptr; /* pointer to current byte in buffer */
28*4882a593Smuzhiyun unsigned int bits_left; /* number of available bits in current byte */
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun
bs_init(struct bs * s,void * buf,int size)31*4882a593Smuzhiyun static void bs_init(struct bs *s, void *buf, int size)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun s->buf = buf;
34*4882a593Smuzhiyun s->ptr = buf;
35*4882a593Smuzhiyun s->buf_end = s->ptr + size;
36*4882a593Smuzhiyun s->bits_left = 8;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
bs_len(struct bs * s)39*4882a593Smuzhiyun static int bs_len(struct bs *s)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun return s->ptr - s->buf;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
bs_write(struct bs * s,int count,u32 bits)44*4882a593Smuzhiyun static void bs_write(struct bs *s, int count, u32 bits)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun if (s->ptr >= s->buf_end - 4)
47*4882a593Smuzhiyun return;
48*4882a593Smuzhiyun while (count > 0) {
49*4882a593Smuzhiyun if (count < 32)
50*4882a593Smuzhiyun bits &= (1 << count) - 1;
51*4882a593Smuzhiyun if (count < s->bits_left) {
52*4882a593Smuzhiyun *s->ptr = (*s->ptr << count) | bits;
53*4882a593Smuzhiyun s->bits_left -= count;
54*4882a593Smuzhiyun break;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun *s->ptr = (*s->ptr << s->bits_left) |
57*4882a593Smuzhiyun (bits >> (count - s->bits_left));
58*4882a593Smuzhiyun count -= s->bits_left;
59*4882a593Smuzhiyun s->ptr++;
60*4882a593Smuzhiyun s->bits_left = 8;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
bs_write1(struct bs * s,u32 bit)64*4882a593Smuzhiyun static void bs_write1(struct bs *s, u32 bit)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun if (s->ptr < s->buf_end) {
67*4882a593Smuzhiyun *s->ptr <<= 1;
68*4882a593Smuzhiyun *s->ptr |= bit;
69*4882a593Smuzhiyun s->bits_left--;
70*4882a593Smuzhiyun if (s->bits_left == 0) {
71*4882a593Smuzhiyun s->ptr++;
72*4882a593Smuzhiyun s->bits_left = 8;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
bs_write_ue(struct bs * s,u32 val)77*4882a593Smuzhiyun static void bs_write_ue(struct bs *s, u32 val)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun if (val == 0) {
80*4882a593Smuzhiyun bs_write1(s, 1);
81*4882a593Smuzhiyun } else {
82*4882a593Smuzhiyun val++;
83*4882a593Smuzhiyun bs_write(s, 2 * fls(val) - 1, val);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
bs_write_se(struct bs * s,int val)87*4882a593Smuzhiyun static void bs_write_se(struct bs *s, int val)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun bs_write_ue(s, val <= 0 ? -val * 2 : val * 2 - 1);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
bs_rbsp_trailing(struct bs * s)92*4882a593Smuzhiyun static void bs_rbsp_trailing(struct bs *s)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun bs_write1(s, 1);
95*4882a593Smuzhiyun if (s->bits_left != 8)
96*4882a593Smuzhiyun bs_write(s, s->bits_left, 0x00);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* H.264 headers generation functions */
100*4882a593Smuzhiyun
tw5864_h264_gen_sps_rbsp(u8 * buf,size_t size,int width,int height)101*4882a593Smuzhiyun static int tw5864_h264_gen_sps_rbsp(u8 *buf, size_t size, int width, int height)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun struct bs bs, *s;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun s = &bs;
106*4882a593Smuzhiyun bs_init(s, buf, size);
107*4882a593Smuzhiyun bs_write(s, 8, 0x42); /* profile_idc, baseline */
108*4882a593Smuzhiyun bs_write(s, 1, 1); /* constraint_set0_flag */
109*4882a593Smuzhiyun bs_write(s, 1, 1); /* constraint_set1_flag */
110*4882a593Smuzhiyun bs_write(s, 1, 0); /* constraint_set2_flag */
111*4882a593Smuzhiyun bs_write(s, 5, 0); /* reserved_zero_5bits */
112*4882a593Smuzhiyun bs_write(s, 8, 0x1e); /* level_idc */
113*4882a593Smuzhiyun bs_write_ue(s, 0); /* seq_parameter_set_id */
114*4882a593Smuzhiyun bs_write_ue(s, ilog2(MAX_GOP_SIZE) - 4); /* log2_max_frame_num_minus4 */
115*4882a593Smuzhiyun bs_write_ue(s, 0); /* pic_order_cnt_type */
116*4882a593Smuzhiyun /* log2_max_pic_order_cnt_lsb_minus4 */
117*4882a593Smuzhiyun bs_write_ue(s, ilog2(MAX_GOP_SIZE) - 4);
118*4882a593Smuzhiyun bs_write_ue(s, 1); /* num_ref_frames */
119*4882a593Smuzhiyun bs_write(s, 1, 0); /* gaps_in_frame_num_value_allowed_flag */
120*4882a593Smuzhiyun bs_write_ue(s, width / 16 - 1); /* pic_width_in_mbs_minus1 */
121*4882a593Smuzhiyun bs_write_ue(s, height / 16 - 1); /* pic_height_in_map_units_minus1 */
122*4882a593Smuzhiyun bs_write(s, 1, 1); /* frame_mbs_only_flag */
123*4882a593Smuzhiyun bs_write(s, 1, 0); /* direct_8x8_inference_flag */
124*4882a593Smuzhiyun bs_write(s, 1, 0); /* frame_cropping_flag */
125*4882a593Smuzhiyun bs_write(s, 1, 0); /* vui_parameters_present_flag */
126*4882a593Smuzhiyun bs_rbsp_trailing(s);
127*4882a593Smuzhiyun return bs_len(s);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
tw5864_h264_gen_pps_rbsp(u8 * buf,size_t size,int qp)130*4882a593Smuzhiyun static int tw5864_h264_gen_pps_rbsp(u8 *buf, size_t size, int qp)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun struct bs bs, *s;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun s = &bs;
135*4882a593Smuzhiyun bs_init(s, buf, size);
136*4882a593Smuzhiyun bs_write_ue(s, 0); /* pic_parameter_set_id */
137*4882a593Smuzhiyun bs_write_ue(s, 0); /* seq_parameter_set_id */
138*4882a593Smuzhiyun bs_write(s, 1, 0); /* entropy_coding_mode_flag */
139*4882a593Smuzhiyun bs_write(s, 1, 0); /* pic_order_present_flag */
140*4882a593Smuzhiyun bs_write_ue(s, 0); /* num_slice_groups_minus1 */
141*4882a593Smuzhiyun bs_write_ue(s, 0); /* i_num_ref_idx_l0_active_minus1 */
142*4882a593Smuzhiyun bs_write_ue(s, 0); /* i_num_ref_idx_l1_active_minus1 */
143*4882a593Smuzhiyun bs_write(s, 1, 0); /* weighted_pred_flag */
144*4882a593Smuzhiyun bs_write(s, 2, 0); /* weighted_bipred_idc */
145*4882a593Smuzhiyun bs_write_se(s, qp - 26); /* pic_init_qp_minus26 */
146*4882a593Smuzhiyun bs_write_se(s, qp - 26); /* pic_init_qs_minus26 */
147*4882a593Smuzhiyun bs_write_se(s, 0); /* chroma_qp_index_offset */
148*4882a593Smuzhiyun bs_write(s, 1, 0); /* deblocking_filter_control_present_flag */
149*4882a593Smuzhiyun bs_write(s, 1, 0); /* constrained_intra_pred_flag */
150*4882a593Smuzhiyun bs_write(s, 1, 0); /* redundant_pic_cnt_present_flag */
151*4882a593Smuzhiyun bs_rbsp_trailing(s);
152*4882a593Smuzhiyun return bs_len(s);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
tw5864_h264_gen_slice_head(u8 * buf,size_t size,unsigned int idr_pic_id,unsigned int frame_gop_seqno,int * tail_nb_bits,u8 * tail)155*4882a593Smuzhiyun static int tw5864_h264_gen_slice_head(u8 *buf, size_t size,
156*4882a593Smuzhiyun unsigned int idr_pic_id,
157*4882a593Smuzhiyun unsigned int frame_gop_seqno,
158*4882a593Smuzhiyun int *tail_nb_bits, u8 *tail)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun struct bs bs, *s;
161*4882a593Smuzhiyun int is_i_frame = frame_gop_seqno == 0;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun s = &bs;
164*4882a593Smuzhiyun bs_init(s, buf, size);
165*4882a593Smuzhiyun bs_write_ue(s, 0); /* first_mb_in_slice */
166*4882a593Smuzhiyun bs_write_ue(s, is_i_frame ? 2 : 5); /* slice_type - I or P */
167*4882a593Smuzhiyun bs_write_ue(s, 0); /* pic_parameter_set_id */
168*4882a593Smuzhiyun bs_write(s, ilog2(MAX_GOP_SIZE), frame_gop_seqno); /* frame_num */
169*4882a593Smuzhiyun if (is_i_frame)
170*4882a593Smuzhiyun bs_write_ue(s, idr_pic_id);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun /* pic_order_cnt_lsb */
173*4882a593Smuzhiyun bs_write(s, ilog2(MAX_GOP_SIZE), frame_gop_seqno);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun if (is_i_frame) {
176*4882a593Smuzhiyun bs_write1(s, 0); /* no_output_of_prior_pics_flag */
177*4882a593Smuzhiyun bs_write1(s, 0); /* long_term_reference_flag */
178*4882a593Smuzhiyun } else {
179*4882a593Smuzhiyun bs_write1(s, 0); /* num_ref_idx_active_override_flag */
180*4882a593Smuzhiyun bs_write1(s, 0); /* ref_pic_list_reordering_flag_l0 */
181*4882a593Smuzhiyun bs_write1(s, 0); /* adaptive_ref_pic_marking_mode_flag */
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun bs_write_se(s, 0); /* slice_qp_delta */
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun if (s->bits_left != 8) {
187*4882a593Smuzhiyun *tail = ((s->ptr[0]) << s->bits_left);
188*4882a593Smuzhiyun *tail_nb_bits = 8 - s->bits_left;
189*4882a593Smuzhiyun } else {
190*4882a593Smuzhiyun *tail = 0;
191*4882a593Smuzhiyun *tail_nb_bits = 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun return bs_len(s);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
tw5864_h264_put_stream_header(u8 ** buf,size_t * space_left,int qp,int width,int height)197*4882a593Smuzhiyun void tw5864_h264_put_stream_header(u8 **buf, size_t *space_left, int qp,
198*4882a593Smuzhiyun int width, int height)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun int nal_len;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* SPS */
203*4882a593Smuzhiyun memcpy(*buf, marker, sizeof(marker));
204*4882a593Smuzhiyun *buf += 4;
205*4882a593Smuzhiyun *space_left -= 4;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun **buf = 0x67; /* SPS NAL header */
208*4882a593Smuzhiyun *buf += 1;
209*4882a593Smuzhiyun *space_left -= 1;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun nal_len = tw5864_h264_gen_sps_rbsp(*buf, *space_left, width, height);
212*4882a593Smuzhiyun *buf += nal_len;
213*4882a593Smuzhiyun *space_left -= nal_len;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* PPS */
216*4882a593Smuzhiyun memcpy(*buf, marker, sizeof(marker));
217*4882a593Smuzhiyun *buf += 4;
218*4882a593Smuzhiyun *space_left -= 4;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun **buf = 0x68; /* PPS NAL header */
221*4882a593Smuzhiyun *buf += 1;
222*4882a593Smuzhiyun *space_left -= 1;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun nal_len = tw5864_h264_gen_pps_rbsp(*buf, *space_left, qp);
225*4882a593Smuzhiyun *buf += nal_len;
226*4882a593Smuzhiyun *space_left -= nal_len;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
tw5864_h264_put_slice_header(u8 ** buf,size_t * space_left,unsigned int idr_pic_id,unsigned int frame_gop_seqno,int * tail_nb_bits,u8 * tail)229*4882a593Smuzhiyun void tw5864_h264_put_slice_header(u8 **buf, size_t *space_left,
230*4882a593Smuzhiyun unsigned int idr_pic_id,
231*4882a593Smuzhiyun unsigned int frame_gop_seqno,
232*4882a593Smuzhiyun int *tail_nb_bits, u8 *tail)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun int nal_len;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun memcpy(*buf, marker, sizeof(marker));
237*4882a593Smuzhiyun *buf += 4;
238*4882a593Smuzhiyun *space_left -= 4;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /* Frame NAL header */
241*4882a593Smuzhiyun **buf = (frame_gop_seqno == 0) ? 0x25 : 0x21;
242*4882a593Smuzhiyun *buf += 1;
243*4882a593Smuzhiyun *space_left -= 1;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun nal_len = tw5864_h264_gen_slice_head(*buf, *space_left, idr_pic_id,
246*4882a593Smuzhiyun frame_gop_seqno, tail_nb_bits,
247*4882a593Smuzhiyun tail);
248*4882a593Smuzhiyun *buf += nal_len;
249*4882a593Smuzhiyun *space_left -= nal_len;
250*4882a593Smuzhiyun }
251