2 * TW5864 driver - H.264 headers generation functions
4 * Copyright (C) 2016 Bluecherry, LLC <maintainers@bluecherrydvr.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/log2.h>
21 static u8 marker
[] = { 0x00, 0x00, 0x00, 0x01 };
24 * Exponential-Golomb coding functions
26 * These functions are used for generation of H.264 bitstream headers.
28 * This code is derived from tw5864 reference driver by manufacturers, which
29 * itself apparently was derived from x264 project.
32 /* Bitstream writing context */
34 u8
*buf
; /* pointer to buffer beginning */
35 u8
*buf_end
; /* pointer to buffer end */
36 u8
*ptr
; /* pointer to current byte in buffer */
37 unsigned int bits_left
; /* number of available bits in current byte */
40 static void bs_init(struct bs
*s
, void *buf
, int size
)
44 s
->buf_end
= s
->ptr
+ size
;
48 static int bs_len(struct bs
*s
)
50 return s
->ptr
- s
->buf
;
53 static void bs_write(struct bs
*s
, int count
, u32 bits
)
55 if (s
->ptr
>= s
->buf_end
- 4)
59 bits
&= (1 << count
) - 1;
60 if (count
< s
->bits_left
) {
61 *s
->ptr
= (*s
->ptr
<< count
) | bits
;
62 s
->bits_left
-= count
;
65 *s
->ptr
= (*s
->ptr
<< s
->bits_left
) |
66 (bits
>> (count
- s
->bits_left
));
67 count
-= s
->bits_left
;
73 static void bs_write1(struct bs
*s
, u32 bit
)
75 if (s
->ptr
< s
->buf_end
) {
79 if (s
->bits_left
== 0) {
86 static void bs_write_ue(struct bs
*s
, u32 val
)
92 bs_write(s
, 2 * fls(val
) - 1, val
);
96 static void bs_write_se(struct bs
*s
, int val
)
98 bs_write_ue(s
, val
<= 0 ? -val
* 2 : val
* 2 - 1);
101 static void bs_rbsp_trailing(struct bs
*s
)
104 if (s
->bits_left
!= 8)
105 bs_write(s
, s
->bits_left
, 0x00);
108 /* H.264 headers generation functions */
110 static int tw5864_h264_gen_sps_rbsp(u8
*buf
, size_t size
, int width
, int height
)
115 bs_init(s
, buf
, size
);
116 bs_write(s
, 8, 0x42); /* profile_idc, baseline */
117 bs_write(s
, 1, 1); /* constraint_set0_flag */
118 bs_write(s
, 1, 1); /* constraint_set1_flag */
119 bs_write(s
, 1, 0); /* constraint_set2_flag */
120 bs_write(s
, 5, 0); /* reserved_zero_5bits */
121 bs_write(s
, 8, 0x1e); /* level_idc */
122 bs_write_ue(s
, 0); /* seq_parameter_set_id */
123 bs_write_ue(s
, ilog2(MAX_GOP_SIZE
) - 4); /* log2_max_frame_num_minus4 */
124 bs_write_ue(s
, 0); /* pic_order_cnt_type */
125 /* log2_max_pic_order_cnt_lsb_minus4 */
126 bs_write_ue(s
, ilog2(MAX_GOP_SIZE
) - 4);
127 bs_write_ue(s
, 1); /* num_ref_frames */
128 bs_write(s
, 1, 0); /* gaps_in_frame_num_value_allowed_flag */
129 bs_write_ue(s
, width
/ 16 - 1); /* pic_width_in_mbs_minus1 */
130 bs_write_ue(s
, height
/ 16 - 1); /* pic_height_in_map_units_minus1 */
131 bs_write(s
, 1, 1); /* frame_mbs_only_flag */
132 bs_write(s
, 1, 0); /* direct_8x8_inference_flag */
133 bs_write(s
, 1, 0); /* frame_cropping_flag */
134 bs_write(s
, 1, 0); /* vui_parameters_present_flag */
139 static int tw5864_h264_gen_pps_rbsp(u8
*buf
, size_t size
, int qp
)
144 bs_init(s
, buf
, size
);
145 bs_write_ue(s
, 0); /* pic_parameter_set_id */
146 bs_write_ue(s
, 0); /* seq_parameter_set_id */
147 bs_write(s
, 1, 0); /* entropy_coding_mode_flag */
148 bs_write(s
, 1, 0); /* pic_order_present_flag */
149 bs_write_ue(s
, 0); /* num_slice_groups_minus1 */
150 bs_write_ue(s
, 0); /* i_num_ref_idx_l0_active_minus1 */
151 bs_write_ue(s
, 0); /* i_num_ref_idx_l1_active_minus1 */
152 bs_write(s
, 1, 0); /* weighted_pred_flag */
153 bs_write(s
, 2, 0); /* weighted_bipred_idc */
154 bs_write_se(s
, qp
- 26); /* pic_init_qp_minus26 */
155 bs_write_se(s
, qp
- 26); /* pic_init_qs_minus26 */
156 bs_write_se(s
, 0); /* chroma_qp_index_offset */
157 bs_write(s
, 1, 0); /* deblocking_filter_control_present_flag */
158 bs_write(s
, 1, 0); /* constrained_intra_pred_flag */
159 bs_write(s
, 1, 0); /* redundant_pic_cnt_present_flag */
164 static int tw5864_h264_gen_slice_head(u8
*buf
, size_t size
,
165 unsigned int idr_pic_id
,
166 unsigned int frame_gop_seqno
,
167 int *tail_nb_bits
, u8
*tail
)
170 int is_i_frame
= frame_gop_seqno
== 0;
173 bs_init(s
, buf
, size
);
174 bs_write_ue(s
, 0); /* first_mb_in_slice */
175 bs_write_ue(s
, is_i_frame
? 2 : 5); /* slice_type - I or P */
176 bs_write_ue(s
, 0); /* pic_parameter_set_id */
177 bs_write(s
, ilog2(MAX_GOP_SIZE
), frame_gop_seqno
); /* frame_num */
179 bs_write_ue(s
, idr_pic_id
);
181 /* pic_order_cnt_lsb */
182 bs_write(s
, ilog2(MAX_GOP_SIZE
), frame_gop_seqno
);
185 bs_write1(s
, 0); /* no_output_of_prior_pics_flag */
186 bs_write1(s
, 0); /* long_term_reference_flag */
188 bs_write1(s
, 0); /* num_ref_idx_active_override_flag */
189 bs_write1(s
, 0); /* ref_pic_list_reordering_flag_l0 */
190 bs_write1(s
, 0); /* adaptive_ref_pic_marking_mode_flag */
193 bs_write_se(s
, 0); /* slice_qp_delta */
195 if (s
->bits_left
!= 8) {
196 *tail
= ((s
->ptr
[0]) << s
->bits_left
);
197 *tail_nb_bits
= 8 - s
->bits_left
;
206 void tw5864_h264_put_stream_header(u8
**buf
, size_t *space_left
, int qp
,
207 int width
, int height
)
212 memcpy(*buf
, marker
, sizeof(marker
));
216 **buf
= 0x67; /* SPS NAL header */
220 nal_len
= tw5864_h264_gen_sps_rbsp(*buf
, *space_left
, width
, height
);
222 *space_left
-= nal_len
;
225 memcpy(*buf
, marker
, sizeof(marker
));
229 **buf
= 0x68; /* PPS NAL header */
233 nal_len
= tw5864_h264_gen_pps_rbsp(*buf
, *space_left
, qp
);
235 *space_left
-= nal_len
;
238 void tw5864_h264_put_slice_header(u8
**buf
, size_t *space_left
,
239 unsigned int idr_pic_id
,
240 unsigned int frame_gop_seqno
,
241 int *tail_nb_bits
, u8
*tail
)
245 memcpy(*buf
, marker
, sizeof(marker
));
249 /* Frame NAL header */
250 **buf
= (frame_gop_seqno
== 0) ? 0x25 : 0x21;
254 nal_len
= tw5864_h264_gen_slice_head(*buf
, *space_left
, idr_pic_id
,
255 frame_gop_seqno
, tail_nb_bits
,
258 *space_left
-= nal_len
;