Merge branch 'akpm' (patches from Andrew)
[cascardo/linux.git] / drivers / media / pci / tw5864 / tw5864-h264.c
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 }