Merge tag 'vfio-v6.9-rc1' of https://github.com/awilliam/linux-vfio
[linux-2.6-microblaze.git] / drivers / media / v4l2-core / v4l2-h264.c
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         if (!(*out_str))
309                 return NULL;
310
311         n += snprintf(*out_str + n, tmp_str_size - n, "|");
312
313         for (i = 0; i < builder->num_valid; i++) {
314                 /* this is pic_num for frame and frame_num (wrapped) for field,
315                  * but for frame pic_num is equal to frame_num (wrapped).
316                  */
317                 int frame_num = builder->refs[reflist[i].index].frame_num;
318                 bool longterm = builder->refs[reflist[i].index].longterm;
319
320                 n += scnprintf(*out_str + n, tmp_str_size - n, "%i%c%c|",
321                                frame_num, longterm ? 'l' : 's',
322                                ref_type_to_char(reflist[i].fields));
323         }
324
325         return *out_str;
326 }
327
328 static void print_ref_list_p(const struct v4l2_h264_reflist_builder *builder,
329                              struct v4l2_h264_reference *reflist)
330 {
331         char *buf = NULL;
332
333         pr_debug("ref_pic_list_p (cur_poc %u%c) %s\n",
334                  builder->cur_pic_order_count,
335                  ref_type_to_char(builder->cur_pic_fields),
336                  format_ref_list_p(builder, reflist, &buf));
337
338         kfree(buf);
339 }
340
341 static const char *format_ref_list_b(const struct v4l2_h264_reflist_builder *builder,
342                                      struct v4l2_h264_reference *reflist,
343                                      char **out_str)
344 {
345         int n = 0, i;
346
347         *out_str = kmalloc(tmp_str_size, GFP_KERNEL);
348         if (!(*out_str))
349                 return NULL;
350
351         n += snprintf(*out_str + n, tmp_str_size - n, "|");
352
353         for (i = 0; i < builder->num_valid; i++) {
354                 int frame_num = builder->refs[reflist[i].index].frame_num;
355                 u32 poc = v4l2_h264_get_poc(builder, reflist + i);
356                 bool longterm = builder->refs[reflist[i].index].longterm;
357
358                 n += scnprintf(*out_str + n, tmp_str_size - n, "%i%c%c|",
359                                longterm ? frame_num : poc,
360                                longterm ? 'l' : 's',
361                                ref_type_to_char(reflist[i].fields));
362         }
363
364         return *out_str;
365 }
366
367 static void print_ref_list_b(const struct v4l2_h264_reflist_builder *builder,
368                              struct v4l2_h264_reference *reflist, u8 list_num)
369 {
370         char *buf = NULL;
371
372         pr_debug("ref_pic_list_b%u (cur_poc %u%c) %s",
373                  list_num, builder->cur_pic_order_count,
374                  ref_type_to_char(builder->cur_pic_fields),
375                  format_ref_list_b(builder, reflist, &buf));
376
377         kfree(buf);
378 }
379
380 /**
381  * v4l2_h264_build_p_ref_list() - Build the P reference list
382  *
383  * @builder: reference list builder context
384  * @reflist: 32 sized array used to store the P reference list. Each entry
385  *           is a v4l2_h264_reference structure
386  *
387  * This functions builds the P reference lists. This procedure is describe in
388  * section '8.2.4 Decoding process for reference picture lists construction'
389  * of the H264 spec. This function can be used by H264 decoder drivers that
390  * need to pass a P reference list to the hardware.
391  */
392 void
393 v4l2_h264_build_p_ref_list(const struct v4l2_h264_reflist_builder *builder,
394                            struct v4l2_h264_reference *reflist)
395 {
396         memcpy(reflist, builder->unordered_reflist,
397                sizeof(builder->unordered_reflist[0]) * builder->num_valid);
398         sort_r(reflist, builder->num_valid, sizeof(*reflist),
399                v4l2_h264_p_ref_list_cmp, NULL, builder);
400
401         if (builder->cur_pic_fields != V4L2_H264_FRAME_REF)
402                 reorder_field_reflist(builder, reflist);
403
404         print_ref_list_p(builder, reflist);
405 }
406 EXPORT_SYMBOL_GPL(v4l2_h264_build_p_ref_list);
407
408 /**
409  * v4l2_h264_build_b_ref_lists() - Build the B0/B1 reference lists
410  *
411  * @builder: reference list builder context
412  * @b0_reflist: 32 sized array used to store the B0 reference list. Each entry
413  *              is a v4l2_h264_reference structure
414  * @b1_reflist: 32 sized array used to store the B1 reference list. Each entry
415  *              is a v4l2_h264_reference structure
416  *
417  * This functions builds the B0/B1 reference lists. This procedure is described
418  * in section '8.2.4 Decoding process for reference picture lists construction'
419  * of the H264 spec. This function can be used by H264 decoder drivers that
420  * need to pass B0/B1 reference lists to the hardware.
421  */
422 void
423 v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder,
424                             struct v4l2_h264_reference *b0_reflist,
425                             struct v4l2_h264_reference *b1_reflist)
426 {
427         memcpy(b0_reflist, builder->unordered_reflist,
428                sizeof(builder->unordered_reflist[0]) * builder->num_valid);
429         sort_r(b0_reflist, builder->num_valid, sizeof(*b0_reflist),
430                v4l2_h264_b0_ref_list_cmp, NULL, builder);
431
432         memcpy(b1_reflist, builder->unordered_reflist,
433                sizeof(builder->unordered_reflist[0]) * builder->num_valid);
434         sort_r(b1_reflist, builder->num_valid, sizeof(*b1_reflist),
435                v4l2_h264_b1_ref_list_cmp, NULL, builder);
436
437         if (builder->cur_pic_fields != V4L2_H264_FRAME_REF) {
438                 reorder_field_reflist(builder, b0_reflist);
439                 reorder_field_reflist(builder, b1_reflist);
440         }
441
442         if (builder->num_valid > 1 &&
443             !memcmp(b1_reflist, b0_reflist, builder->num_valid))
444                 swap(b1_reflist[0], b1_reflist[1]);
445
446         print_ref_list_b(builder, b0_reflist, 0);
447         print_ref_list_b(builder, b1_reflist, 1);
448 }
449 EXPORT_SYMBOL_GPL(v4l2_h264_build_b_ref_lists);
450
451 MODULE_LICENSE("GPL");
452 MODULE_DESCRIPTION("V4L2 H264 Helpers");
453 MODULE_AUTHOR("Boris Brezillon <boris.brezillon@collabora.com>");