xref: /linux/drivers/media/v4l2-core/v4l2-h264.c (revision d206cef03c4827984e6ac88a9472b70c41f5b28d)
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
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 
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 
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 
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 
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  */
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 
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 
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 
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 
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 
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
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
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