1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * V4L2 H264 helpers.
4 *
5 * Copyright (C) 2019 Collabora, Ltd.
6 *
7 * Author: Boris Brezillon <boris.brezillon@collabora.com>
8 */
9
10 #include <linux/module.h>
11 #include <linux/sort.h>
12
13 #include <media/v4l2-h264.h>
14
15 /*
16 * Size of the tempory buffer allocated when printing reference lists. The
17 * output will be truncated if the size is too small.
18 */
19 static const int tmp_str_size = 1024;
20
21 /**
22 * v4l2_h264_init_reflist_builder() - Initialize a P/B0/B1 reference list
23 * builder
24 *
25 * @b: the builder context to initialize
26 * @dec_params: decode parameters control
27 * @sps: SPS control
28 * @dpb: DPB to use when creating the reference list
29 */
30 void
v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder * b,const struct v4l2_ctrl_h264_decode_params * dec_params,const struct v4l2_ctrl_h264_sps * sps,const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES])31 v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
32 const struct v4l2_ctrl_h264_decode_params *dec_params,
33 const struct v4l2_ctrl_h264_sps *sps,
34 const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES])
35 {
36 int cur_frame_num, max_frame_num;
37 unsigned int i;
38
39 max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
40 cur_frame_num = dec_params->frame_num;
41
42 memset(b, 0, sizeof(*b));
43 if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) {
44 b->cur_pic_order_count = min(dec_params->bottom_field_order_cnt,
45 dec_params->top_field_order_cnt);
46 b->cur_pic_fields = V4L2_H264_FRAME_REF;
47 } else if (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) {
48 b->cur_pic_order_count = dec_params->bottom_field_order_cnt;
49 b->cur_pic_fields = V4L2_H264_BOTTOM_FIELD_REF;
50 } else {
51 b->cur_pic_order_count = dec_params->top_field_order_cnt;
52 b->cur_pic_fields = V4L2_H264_TOP_FIELD_REF;
53 }
54
55 for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
56 if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
57 continue;
58
59 if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
60 b->refs[i].longterm = true;
61
62 /*
63 * Handle frame_num wraparound as described in section
64 * '8.2.4.1 Decoding process for picture numbers' of the spec.
65 * For long term references, frame_num is set to
66 * long_term_frame_idx which requires no wrapping.
67 */
68 if (!b->refs[i].longterm && dpb[i].frame_num > cur_frame_num)
69 b->refs[i].frame_num = (int)dpb[i].frame_num -
70 max_frame_num;
71 else
72 b->refs[i].frame_num = dpb[i].frame_num;
73
74 b->refs[i].top_field_order_cnt = dpb[i].top_field_order_cnt;
75 b->refs[i].bottom_field_order_cnt = dpb[i].bottom_field_order_cnt;
76
77 if (b->cur_pic_fields == V4L2_H264_FRAME_REF) {
78 u8 fields = V4L2_H264_FRAME_REF;
79
80 b->unordered_reflist[b->num_valid].index = i;
81 b->unordered_reflist[b->num_valid].fields = fields;
82 b->num_valid++;
83 continue;
84 }
85
86 if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF) {
87 u8 fields = V4L2_H264_TOP_FIELD_REF;
88
89 b->unordered_reflist[b->num_valid].index = i;
90 b->unordered_reflist[b->num_valid].fields = fields;
91 b->num_valid++;
92 }
93
94 if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF) {
95 u8 fields = V4L2_H264_BOTTOM_FIELD_REF;
96
97 b->unordered_reflist[b->num_valid].index = i;
98 b->unordered_reflist[b->num_valid].fields = fields;
99 b->num_valid++;
100 }
101 }
102
103 for (i = b->num_valid; i < ARRAY_SIZE(b->unordered_reflist); i++)
104 b->unordered_reflist[i].index = i;
105 }
106 EXPORT_SYMBOL_GPL(v4l2_h264_init_reflist_builder);
107
v4l2_h264_get_poc(const struct v4l2_h264_reflist_builder * b,const struct v4l2_h264_reference * ref)108 static s32 v4l2_h264_get_poc(const struct v4l2_h264_reflist_builder *b,
109 const struct v4l2_h264_reference *ref)
110 {
111 switch (ref->fields) {
112 case V4L2_H264_FRAME_REF:
113 return min(b->refs[ref->index].top_field_order_cnt,
114 b->refs[ref->index].bottom_field_order_cnt);
115 case V4L2_H264_TOP_FIELD_REF:
116 return b->refs[ref->index].top_field_order_cnt;
117 case V4L2_H264_BOTTOM_FIELD_REF:
118 return b->refs[ref->index].bottom_field_order_cnt;
119 }
120
121 /* not reached */
122 return 0;
123 }
124
v4l2_h264_p_ref_list_cmp(const void * ptra,const void * ptrb,const void * data)125 static int v4l2_h264_p_ref_list_cmp(const void *ptra, const void *ptrb,
126 const void *data)
127 {
128 const struct v4l2_h264_reflist_builder *builder = data;
129 u8 idxa, idxb;
130
131 idxa = ((struct v4l2_h264_reference *)ptra)->index;
132 idxb = ((struct v4l2_h264_reference *)ptrb)->index;
133
134 if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
135 idxb >= V4L2_H264_NUM_DPB_ENTRIES))
136 return 1;
137
138 if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) {
139 /* Short term pics first. */
140 if (!builder->refs[idxa].longterm)
141 return -1;
142 else
143 return 1;
144 }
145
146 /*
147 * For frames, short term pics are in descending pic num order and long
148 * term ones in ascending order. For fields, the same direction is used
149 * but with frame_num (wrapped). For frames, the value of pic_num and
150 * frame_num are the same (see formula (8-28) and (8-29)). For this
151 * reason we can use frame_num only and share this function between
152 * frames and fields reflist.
153 */
154 if (!builder->refs[idxa].longterm)
155 return builder->refs[idxb].frame_num <
156 builder->refs[idxa].frame_num ?
157 -1 : 1;
158
159 return builder->refs[idxa].frame_num < builder->refs[idxb].frame_num ?
160 -1 : 1;
161 }
162
v4l2_h264_b0_ref_list_cmp(const void * ptra,const void * ptrb,const void * data)163 static int v4l2_h264_b0_ref_list_cmp(const void *ptra, const void *ptrb,
164 const void *data)
165 {
166 const struct v4l2_h264_reflist_builder *builder = data;
167 s32 poca, pocb;
168 u8 idxa, idxb;
169
170 idxa = ((struct v4l2_h264_reference *)ptra)->index;
171 idxb = ((struct v4l2_h264_reference *)ptrb)->index;
172
173 if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
174 idxb >= V4L2_H264_NUM_DPB_ENTRIES))
175 return 1;
176
177 if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) {
178 /* Short term pics first. */
179 if (!builder->refs[idxa].longterm)
180 return -1;
181 else
182 return 1;
183 }
184
185 /* Long term pics in ascending frame num order. */
186 if (builder->refs[idxa].longterm)
187 return builder->refs[idxa].frame_num <
188 builder->refs[idxb].frame_num ?
189 -1 : 1;
190
191 poca = v4l2_h264_get_poc(builder, ptra);
192 pocb = v4l2_h264_get_poc(builder, ptrb);
193
194 /*
195 * Short term pics with POC < cur POC first in POC descending order
196 * followed by short term pics with POC > cur POC in POC ascending
197 * order.
198 */
199 if ((poca < builder->cur_pic_order_count) !=
200 (pocb < builder->cur_pic_order_count))
201 return poca < pocb ? -1 : 1;
202 else if (poca < builder->cur_pic_order_count)
203 return pocb < poca ? -1 : 1;
204
205 return poca < pocb ? -1 : 1;
206 }
207
v4l2_h264_b1_ref_list_cmp(const void * ptra,const void * ptrb,const void * data)208 static int v4l2_h264_b1_ref_list_cmp(const void *ptra, const void *ptrb,
209 const void *data)
210 {
211 const struct v4l2_h264_reflist_builder *builder = data;
212 s32 poca, pocb;
213 u8 idxa, idxb;
214
215 idxa = ((struct v4l2_h264_reference *)ptra)->index;
216 idxb = ((struct v4l2_h264_reference *)ptrb)->index;
217
218 if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
219 idxb >= V4L2_H264_NUM_DPB_ENTRIES))
220 return 1;
221
222 if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) {
223 /* Short term pics first. */
224 if (!builder->refs[idxa].longterm)
225 return -1;
226 else
227 return 1;
228 }
229
230 /* Long term pics in ascending frame num order. */
231 if (builder->refs[idxa].longterm)
232 return builder->refs[idxa].frame_num <
233 builder->refs[idxb].frame_num ?
234 -1 : 1;
235
236 poca = v4l2_h264_get_poc(builder, ptra);
237 pocb = v4l2_h264_get_poc(builder, ptrb);
238
239 /*
240 * Short term pics with POC > cur POC first in POC ascending order
241 * followed by short term pics with POC < cur POC in POC descending
242 * order.
243 */
244 if ((poca < builder->cur_pic_order_count) !=
245 (pocb < builder->cur_pic_order_count))
246 return pocb < poca ? -1 : 1;
247 else if (poca < builder->cur_pic_order_count)
248 return pocb < poca ? -1 : 1;
249
250 return poca < pocb ? -1 : 1;
251 }
252
253 /*
254 * The references need to be reordered so that references are alternating
255 * between top and bottom field references starting with the current picture
256 * parity. This has to be done for short term and long term references
257 * separately.
258 */
reorder_field_reflist(const struct v4l2_h264_reflist_builder * b,struct v4l2_h264_reference * reflist)259 static void reorder_field_reflist(const struct v4l2_h264_reflist_builder *b,
260 struct v4l2_h264_reference *reflist)
261 {
262 struct v4l2_h264_reference tmplist[V4L2_H264_REF_LIST_LEN];
263 u8 lt, i = 0, j = 0, k = 0;
264
265 memcpy(tmplist, reflist, sizeof(tmplist[0]) * b->num_valid);
266
267 for (lt = 0; lt <= 1; lt++) {
268 do {
269 for (; i < b->num_valid && b->refs[tmplist[i].index].longterm == lt; i++) {
270 if (tmplist[i].fields == b->cur_pic_fields) {
271 reflist[k++] = tmplist[i++];
272 break;
273 }
274 }
275
276 for (; j < b->num_valid && b->refs[tmplist[j].index].longterm == lt; j++) {
277 if (tmplist[j].fields != b->cur_pic_fields) {
278 reflist[k++] = tmplist[j++];
279 break;
280 }
281 }
282 } while ((i < b->num_valid && b->refs[tmplist[i].index].longterm == lt) ||
283 (j < b->num_valid && b->refs[tmplist[j].index].longterm == lt));
284 }
285 }
286
ref_type_to_char(u8 ref_type)287 static char ref_type_to_char(u8 ref_type)
288 {
289 switch (ref_type) {
290 case V4L2_H264_FRAME_REF:
291 return 'f';
292 case V4L2_H264_TOP_FIELD_REF:
293 return 't';
294 case V4L2_H264_BOTTOM_FIELD_REF:
295 return 'b';
296 }
297
298 return '?';
299 }
300
format_ref_list_p(const struct v4l2_h264_reflist_builder * builder,struct v4l2_h264_reference * reflist,char ** out_str)301 static const char *format_ref_list_p(const struct v4l2_h264_reflist_builder *builder,
302 struct v4l2_h264_reference *reflist,
303 char **out_str)
304 {
305 int n = 0, i;
306
307 *out_str = kmalloc(tmp_str_size, GFP_KERNEL);
308
309 n += snprintf(*out_str + n, tmp_str_size - n, "|");
310
311 for (i = 0; i < builder->num_valid; i++) {
312 /* this is pic_num for frame and frame_num (wrapped) for field,
313 * but for frame pic_num is equal to frame_num (wrapped).
314 */
315 int frame_num = builder->refs[reflist[i].index].frame_num;
316 bool longterm = builder->refs[reflist[i].index].longterm;
317
318 n += scnprintf(*out_str + n, tmp_str_size - n, "%i%c%c|",
319 frame_num, longterm ? 'l' : 's',
320 ref_type_to_char(reflist[i].fields));
321 }
322
323 return *out_str;
324 }
325
print_ref_list_p(const struct v4l2_h264_reflist_builder * builder,struct v4l2_h264_reference * reflist)326 static void print_ref_list_p(const struct v4l2_h264_reflist_builder *builder,
327 struct v4l2_h264_reference *reflist)
328 {
329 char *buf = NULL;
330
331 pr_debug("ref_pic_list_p (cur_poc %u%c) %s\n",
332 builder->cur_pic_order_count,
333 ref_type_to_char(builder->cur_pic_fields),
334 format_ref_list_p(builder, reflist, &buf));
335
336 kfree(buf);
337 }
338
format_ref_list_b(const struct v4l2_h264_reflist_builder * builder,struct v4l2_h264_reference * reflist,char ** out_str)339 static const char *format_ref_list_b(const struct v4l2_h264_reflist_builder *builder,
340 struct v4l2_h264_reference *reflist,
341 char **out_str)
342 {
343 int n = 0, i;
344
345 *out_str = kmalloc(tmp_str_size, GFP_KERNEL);
346
347 n += snprintf(*out_str + n, tmp_str_size - n, "|");
348
349 for (i = 0; i < builder->num_valid; i++) {
350 int frame_num = builder->refs[reflist[i].index].frame_num;
351 u32 poc = v4l2_h264_get_poc(builder, reflist + i);
352 bool longterm = builder->refs[reflist[i].index].longterm;
353
354 n += scnprintf(*out_str + n, tmp_str_size - n, "%i%c%c|",
355 longterm ? frame_num : poc,
356 longterm ? 'l' : 's',
357 ref_type_to_char(reflist[i].fields));
358 }
359
360 return *out_str;
361 }
362
print_ref_list_b(const struct v4l2_h264_reflist_builder * builder,struct v4l2_h264_reference * reflist,u8 list_num)363 static void print_ref_list_b(const struct v4l2_h264_reflist_builder *builder,
364 struct v4l2_h264_reference *reflist, u8 list_num)
365 {
366 char *buf = NULL;
367
368 pr_debug("ref_pic_list_b%u (cur_poc %u%c) %s",
369 list_num, builder->cur_pic_order_count,
370 ref_type_to_char(builder->cur_pic_fields),
371 format_ref_list_b(builder, reflist, &buf));
372
373 kfree(buf);
374 }
375
376 /**
377 * v4l2_h264_build_p_ref_list() - Build the P reference list
378 *
379 * @builder: reference list builder context
380 * @reflist: 32 sized array used to store the P reference list. Each entry
381 * is a v4l2_h264_reference structure
382 *
383 * This functions builds the P reference lists. This procedure is describe in
384 * section '8.2.4 Decoding process for reference picture lists construction'
385 * of the H264 spec. This function can be used by H264 decoder drivers that
386 * need to pass a P reference list to the hardware.
387 */
388 void
v4l2_h264_build_p_ref_list(const struct v4l2_h264_reflist_builder * builder,struct v4l2_h264_reference * reflist)389 v4l2_h264_build_p_ref_list(const struct v4l2_h264_reflist_builder *builder,
390 struct v4l2_h264_reference *reflist)
391 {
392 memcpy(reflist, builder->unordered_reflist,
393 sizeof(builder->unordered_reflist[0]) * builder->num_valid);
394 sort_r(reflist, builder->num_valid, sizeof(*reflist),
395 v4l2_h264_p_ref_list_cmp, NULL, builder);
396
397 if (builder->cur_pic_fields != V4L2_H264_FRAME_REF)
398 reorder_field_reflist(builder, reflist);
399
400 print_ref_list_p(builder, reflist);
401 }
402 EXPORT_SYMBOL_GPL(v4l2_h264_build_p_ref_list);
403
404 /**
405 * v4l2_h264_build_b_ref_lists() - Build the B0/B1 reference lists
406 *
407 * @builder: reference list builder context
408 * @b0_reflist: 32 sized array used to store the B0 reference list. Each entry
409 * is a v4l2_h264_reference structure
410 * @b1_reflist: 32 sized array used to store the B1 reference list. Each entry
411 * is a v4l2_h264_reference structure
412 *
413 * This functions builds the B0/B1 reference lists. This procedure is described
414 * in section '8.2.4 Decoding process for reference picture lists construction'
415 * of the H264 spec. This function can be used by H264 decoder drivers that
416 * need to pass B0/B1 reference lists to the hardware.
417 */
418 void
v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder * builder,struct v4l2_h264_reference * b0_reflist,struct v4l2_h264_reference * b1_reflist)419 v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder,
420 struct v4l2_h264_reference *b0_reflist,
421 struct v4l2_h264_reference *b1_reflist)
422 {
423 memcpy(b0_reflist, builder->unordered_reflist,
424 sizeof(builder->unordered_reflist[0]) * builder->num_valid);
425 sort_r(b0_reflist, builder->num_valid, sizeof(*b0_reflist),
426 v4l2_h264_b0_ref_list_cmp, NULL, builder);
427
428 memcpy(b1_reflist, builder->unordered_reflist,
429 sizeof(builder->unordered_reflist[0]) * builder->num_valid);
430 sort_r(b1_reflist, builder->num_valid, sizeof(*b1_reflist),
431 v4l2_h264_b1_ref_list_cmp, NULL, builder);
432
433 if (builder->cur_pic_fields != V4L2_H264_FRAME_REF) {
434 reorder_field_reflist(builder, b0_reflist);
435 reorder_field_reflist(builder, b1_reflist);
436 }
437
438 if (builder->num_valid > 1 &&
439 !memcmp(b1_reflist, b0_reflist, builder->num_valid))
440 swap(b1_reflist[0], b1_reflist[1]);
441
442 print_ref_list_b(builder, b0_reflist, 0);
443 print_ref_list_b(builder, b1_reflist, 1);
444 }
445 EXPORT_SYMBOL_GPL(v4l2_h264_build_b_ref_lists);
446
447 MODULE_LICENSE("GPL");
448 MODULE_DESCRIPTION("V4L2 H264 Helpers");
449 MODULE_AUTHOR("Boris Brezillon <boris.brezillon@collabora.com>");
450