1 /* 2 * TW5864 driver - H.264 headers generation functions 3 * 4 * Copyright (C) 2016 Bluecherry, LLC <maintainers@bluecherrydvr.com> 5 * 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. 10 * 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. 15 */ 16 17 #include <linux/log2.h> 18 19 #include "tw5864.h" 20 21 static u8 marker[] = { 0x00, 0x00, 0x00, 0x01 }; 22 23 /* 24 * Exponential-Golomb coding functions 25 * 26 * These functions are used for generation of H.264 bitstream headers. 27 * 28 * This code is derived from tw5864 reference driver by manufacturers, which 29 * itself apparently was derived from x264 project. 30 */ 31 32 /* Bitstream writing context */ 33 struct bs { 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 */ 38 }; 39 40 static void bs_init(struct bs *s, void *buf, int size) 41 { 42 s->buf = buf; 43 s->ptr = buf; 44 s->buf_end = s->ptr + size; 45 s->bits_left = 8; 46 } 47 48 static int bs_len(struct bs *s) 49 { 50 return s->ptr - s->buf; 51 } 52 53 static void bs_write(struct bs *s, int count, u32 bits) 54 { 55 if (s->ptr >= s->buf_end - 4) 56 return; 57 while (count > 0) { 58 if (count < 32) 59 bits &= (1 << count) - 1; 60 if (count < s->bits_left) { 61 *s->ptr = (*s->ptr << count) | bits; 62 s->bits_left -= count; 63 break; 64 } 65 *s->ptr = (*s->ptr << s->bits_left) | 66 (bits >> (count - s->bits_left)); 67 count -= s->bits_left; 68 s->ptr++; 69 s->bits_left = 8; 70 } 71 } 72 73 static void bs_write1(struct bs *s, u32 bit) 74 { 75 if (s->ptr < s->buf_end) { 76 *s->ptr <<= 1; 77 *s->ptr |= bit; 78 s->bits_left--; 79 if (s->bits_left == 0) { 80 s->ptr++; 81 s->bits_left = 8; 82 } 83 } 84 } 85 86 static void bs_write_ue(struct bs *s, u32 val) 87 { 88 if (val == 0) { 89 bs_write1(s, 1); 90 } else { 91 val++; 92 bs_write(s, 2 * fls(val) - 1, val); 93 } 94 } 95 96 static void bs_write_se(struct bs *s, int val) 97 { 98 bs_write_ue(s, val <= 0 ? -val * 2 : val * 2 - 1); 99 } 100 101 static void bs_rbsp_trailing(struct bs *s) 102 { 103 bs_write1(s, 1); 104 if (s->bits_left != 8) 105 bs_write(s, s->bits_left, 0x00); 106 } 107 108 /* H.264 headers generation functions */ 109 110 static int tw5864_h264_gen_sps_rbsp(u8 *buf, size_t size, int width, int height) 111 { 112 struct bs bs, *s; 113 114 s = &bs; 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 */ 135 bs_rbsp_trailing(s); 136 return bs_len(s); 137 } 138 139 static int tw5864_h264_gen_pps_rbsp(u8 *buf, size_t size, int qp) 140 { 141 struct bs bs, *s; 142 143 s = &bs; 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 */ 160 bs_rbsp_trailing(s); 161 return bs_len(s); 162 } 163 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) 168 { 169 struct bs bs, *s; 170 int is_i_frame = frame_gop_seqno == 0; 171 172 s = &bs; 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 */ 178 if (is_i_frame) 179 bs_write_ue(s, idr_pic_id); 180 181 /* pic_order_cnt_lsb */ 182 bs_write(s, ilog2(MAX_GOP_SIZE), frame_gop_seqno); 183 184 if (is_i_frame) { 185 bs_write1(s, 0); /* no_output_of_prior_pics_flag */ 186 bs_write1(s, 0); /* long_term_reference_flag */ 187 } else { 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 */ 191 } 192 193 bs_write_se(s, 0); /* slice_qp_delta */ 194 195 if (s->bits_left != 8) { 196 *tail = ((s->ptr[0]) << s->bits_left); 197 *tail_nb_bits = 8 - s->bits_left; 198 } else { 199 *tail = 0; 200 *tail_nb_bits = 0; 201 } 202 203 return bs_len(s); 204 } 205 206 void tw5864_h264_put_stream_header(u8 **buf, size_t *space_left, int qp, 207 int width, int height) 208 { 209 int nal_len; 210 211 /* SPS */ 212 memcpy(*buf, marker, sizeof(marker)); 213 *buf += 4; 214 *space_left -= 4; 215 216 **buf = 0x67; /* SPS NAL header */ 217 *buf += 1; 218 *space_left -= 1; 219 220 nal_len = tw5864_h264_gen_sps_rbsp(*buf, *space_left, width, height); 221 *buf += nal_len; 222 *space_left -= nal_len; 223 224 /* PPS */ 225 memcpy(*buf, marker, sizeof(marker)); 226 *buf += 4; 227 *space_left -= 4; 228 229 **buf = 0x68; /* PPS NAL header */ 230 *buf += 1; 231 *space_left -= 1; 232 233 nal_len = tw5864_h264_gen_pps_rbsp(*buf, *space_left, qp); 234 *buf += nal_len; 235 *space_left -= nal_len; 236 } 237 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) 242 { 243 int nal_len; 244 245 memcpy(*buf, marker, sizeof(marker)); 246 *buf += 4; 247 *space_left -= 4; 248 249 /* Frame NAL header */ 250 **buf = (frame_gop_seqno == 0) ? 0x25 : 0x21; 251 *buf += 1; 252 *space_left -= 1; 253 254 nal_len = tw5864_h264_gen_slice_head(*buf, *space_left, idr_pic_id, 255 frame_gop_seqno, tail_nb_bits, 256 tail); 257 *buf += nal_len; 258 *space_left -= nal_len; 259 } 260