cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tw5864-h264.c (6424B)


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