0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/sort.h>
0012
0013 #include <media/v4l2-h264.h>
0014
0015
0016
0017
0018
0019 static const int tmp_str_size = 1024;
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 void
0031 v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
0032 const struct v4l2_ctrl_h264_decode_params *dec_params,
0033 const struct v4l2_ctrl_h264_sps *sps,
0034 const struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES])
0035 {
0036 int cur_frame_num, max_frame_num;
0037 unsigned int i;
0038
0039 max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
0040 cur_frame_num = dec_params->frame_num;
0041
0042 memset(b, 0, sizeof(*b));
0043 if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) {
0044 b->cur_pic_order_count = min(dec_params->bottom_field_order_cnt,
0045 dec_params->top_field_order_cnt);
0046 b->cur_pic_fields = V4L2_H264_FRAME_REF;
0047 } else if (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) {
0048 b->cur_pic_order_count = dec_params->bottom_field_order_cnt;
0049 b->cur_pic_fields = V4L2_H264_BOTTOM_FIELD_REF;
0050 } else {
0051 b->cur_pic_order_count = dec_params->top_field_order_cnt;
0052 b->cur_pic_fields = V4L2_H264_TOP_FIELD_REF;
0053 }
0054
0055 for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
0056 if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
0057 continue;
0058
0059 if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
0060 b->refs[i].longterm = true;
0061
0062
0063
0064
0065
0066
0067
0068 if (!b->refs[i].longterm && dpb[i].frame_num > cur_frame_num)
0069 b->refs[i].frame_num = (int)dpb[i].frame_num -
0070 max_frame_num;
0071 else
0072 b->refs[i].frame_num = dpb[i].frame_num;
0073
0074 b->refs[i].top_field_order_cnt = dpb[i].top_field_order_cnt;
0075 b->refs[i].bottom_field_order_cnt = dpb[i].bottom_field_order_cnt;
0076
0077 if (b->cur_pic_fields == V4L2_H264_FRAME_REF) {
0078 u8 fields = V4L2_H264_FRAME_REF;
0079
0080 b->unordered_reflist[b->num_valid].index = i;
0081 b->unordered_reflist[b->num_valid].fields = fields;
0082 b->num_valid++;
0083 continue;
0084 }
0085
0086 if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF) {
0087 u8 fields = V4L2_H264_TOP_FIELD_REF;
0088
0089 b->unordered_reflist[b->num_valid].index = i;
0090 b->unordered_reflist[b->num_valid].fields = fields;
0091 b->num_valid++;
0092 }
0093
0094 if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF) {
0095 u8 fields = V4L2_H264_BOTTOM_FIELD_REF;
0096
0097 b->unordered_reflist[b->num_valid].index = i;
0098 b->unordered_reflist[b->num_valid].fields = fields;
0099 b->num_valid++;
0100 }
0101 }
0102
0103 for (i = b->num_valid; i < ARRAY_SIZE(b->unordered_reflist); i++)
0104 b->unordered_reflist[i].index = i;
0105 }
0106 EXPORT_SYMBOL_GPL(v4l2_h264_init_reflist_builder);
0107
0108 static s32 v4l2_h264_get_poc(const struct v4l2_h264_reflist_builder *b,
0109 const struct v4l2_h264_reference *ref)
0110 {
0111 switch (ref->fields) {
0112 case V4L2_H264_FRAME_REF:
0113 return min(b->refs[ref->index].top_field_order_cnt,
0114 b->refs[ref->index].bottom_field_order_cnt);
0115 case V4L2_H264_TOP_FIELD_REF:
0116 return b->refs[ref->index].top_field_order_cnt;
0117 case V4L2_H264_BOTTOM_FIELD_REF:
0118 return b->refs[ref->index].bottom_field_order_cnt;
0119 }
0120
0121
0122 return 0;
0123 }
0124
0125 static int v4l2_h264_p_ref_list_cmp(const void *ptra, const void *ptrb,
0126 const void *data)
0127 {
0128 const struct v4l2_h264_reflist_builder *builder = data;
0129 u8 idxa, idxb;
0130
0131 idxa = ((struct v4l2_h264_reference *)ptra)->index;
0132 idxb = ((struct v4l2_h264_reference *)ptrb)->index;
0133
0134 if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
0135 idxb >= V4L2_H264_NUM_DPB_ENTRIES))
0136 return 1;
0137
0138 if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) {
0139
0140 if (!builder->refs[idxa].longterm)
0141 return -1;
0142 else
0143 return 1;
0144 }
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 if (!builder->refs[idxa].longterm)
0155 return builder->refs[idxb].frame_num <
0156 builder->refs[idxa].frame_num ?
0157 -1 : 1;
0158
0159 return builder->refs[idxa].frame_num < builder->refs[idxb].frame_num ?
0160 -1 : 1;
0161 }
0162
0163 static int v4l2_h264_b0_ref_list_cmp(const void *ptra, const void *ptrb,
0164 const void *data)
0165 {
0166 const struct v4l2_h264_reflist_builder *builder = data;
0167 s32 poca, pocb;
0168 u8 idxa, idxb;
0169
0170 idxa = ((struct v4l2_h264_reference *)ptra)->index;
0171 idxb = ((struct v4l2_h264_reference *)ptrb)->index;
0172
0173 if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
0174 idxb >= V4L2_H264_NUM_DPB_ENTRIES))
0175 return 1;
0176
0177 if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) {
0178
0179 if (!builder->refs[idxa].longterm)
0180 return -1;
0181 else
0182 return 1;
0183 }
0184
0185
0186 if (builder->refs[idxa].longterm)
0187 return builder->refs[idxa].frame_num <
0188 builder->refs[idxb].frame_num ?
0189 -1 : 1;
0190
0191 poca = v4l2_h264_get_poc(builder, ptra);
0192 pocb = v4l2_h264_get_poc(builder, ptrb);
0193
0194
0195
0196
0197
0198
0199 if ((poca < builder->cur_pic_order_count) !=
0200 (pocb < builder->cur_pic_order_count))
0201 return poca < pocb ? -1 : 1;
0202 else if (poca < builder->cur_pic_order_count)
0203 return pocb < poca ? -1 : 1;
0204
0205 return poca < pocb ? -1 : 1;
0206 }
0207
0208 static int v4l2_h264_b1_ref_list_cmp(const void *ptra, const void *ptrb,
0209 const void *data)
0210 {
0211 const struct v4l2_h264_reflist_builder *builder = data;
0212 s32 poca, pocb;
0213 u8 idxa, idxb;
0214
0215 idxa = ((struct v4l2_h264_reference *)ptra)->index;
0216 idxb = ((struct v4l2_h264_reference *)ptrb)->index;
0217
0218 if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
0219 idxb >= V4L2_H264_NUM_DPB_ENTRIES))
0220 return 1;
0221
0222 if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) {
0223
0224 if (!builder->refs[idxa].longterm)
0225 return -1;
0226 else
0227 return 1;
0228 }
0229
0230
0231 if (builder->refs[idxa].longterm)
0232 return builder->refs[idxa].frame_num <
0233 builder->refs[idxb].frame_num ?
0234 -1 : 1;
0235
0236 poca = v4l2_h264_get_poc(builder, ptra);
0237 pocb = v4l2_h264_get_poc(builder, ptrb);
0238
0239
0240
0241
0242
0243
0244 if ((poca < builder->cur_pic_order_count) !=
0245 (pocb < builder->cur_pic_order_count))
0246 return pocb < poca ? -1 : 1;
0247 else if (poca < builder->cur_pic_order_count)
0248 return pocb < poca ? -1 : 1;
0249
0250 return poca < pocb ? -1 : 1;
0251 }
0252
0253
0254
0255
0256
0257
0258
0259 static void reorder_field_reflist(const struct v4l2_h264_reflist_builder *b,
0260 struct v4l2_h264_reference *reflist)
0261 {
0262 struct v4l2_h264_reference tmplist[V4L2_H264_REF_LIST_LEN];
0263 u8 lt, i = 0, j = 0, k = 0;
0264
0265 memcpy(tmplist, reflist, sizeof(tmplist[0]) * b->num_valid);
0266
0267 for (lt = 0; lt <= 1; lt++) {
0268 do {
0269 for (; i < b->num_valid && b->refs[tmplist[i].index].longterm == lt; i++) {
0270 if (tmplist[i].fields == b->cur_pic_fields) {
0271 reflist[k++] = tmplist[i++];
0272 break;
0273 }
0274 }
0275
0276 for (; j < b->num_valid && b->refs[tmplist[j].index].longterm == lt; j++) {
0277 if (tmplist[j].fields != b->cur_pic_fields) {
0278 reflist[k++] = tmplist[j++];
0279 break;
0280 }
0281 }
0282 } while ((i < b->num_valid && b->refs[tmplist[i].index].longterm == lt) ||
0283 (j < b->num_valid && b->refs[tmplist[j].index].longterm == lt));
0284 }
0285 }
0286
0287 static char ref_type_to_char(u8 ref_type)
0288 {
0289 switch (ref_type) {
0290 case V4L2_H264_FRAME_REF:
0291 return 'f';
0292 case V4L2_H264_TOP_FIELD_REF:
0293 return 't';
0294 case V4L2_H264_BOTTOM_FIELD_REF:
0295 return 'b';
0296 }
0297
0298 return '?';
0299 }
0300
0301 static const char *format_ref_list_p(const struct v4l2_h264_reflist_builder *builder,
0302 struct v4l2_h264_reference *reflist,
0303 char **out_str)
0304 {
0305 int n = 0, i;
0306
0307 *out_str = kmalloc(tmp_str_size, GFP_KERNEL);
0308
0309 n += snprintf(*out_str + n, tmp_str_size - n, "|");
0310
0311 for (i = 0; i < builder->num_valid; i++) {
0312
0313
0314
0315 int frame_num = builder->refs[reflist[i].index].frame_num;
0316 bool longterm = builder->refs[reflist[i].index].longterm;
0317
0318 n += scnprintf(*out_str + n, tmp_str_size - n, "%i%c%c|",
0319 frame_num, longterm ? 'l' : 's',
0320 ref_type_to_char(reflist[i].fields));
0321 }
0322
0323 return *out_str;
0324 }
0325
0326 static void print_ref_list_p(const struct v4l2_h264_reflist_builder *builder,
0327 struct v4l2_h264_reference *reflist)
0328 {
0329 char *buf = NULL;
0330
0331 pr_debug("ref_pic_list_p (cur_poc %u%c) %s\n",
0332 builder->cur_pic_order_count,
0333 ref_type_to_char(builder->cur_pic_fields),
0334 format_ref_list_p(builder, reflist, &buf));
0335
0336 kfree(buf);
0337 }
0338
0339 static const char *format_ref_list_b(const struct v4l2_h264_reflist_builder *builder,
0340 struct v4l2_h264_reference *reflist,
0341 char **out_str)
0342 {
0343 int n = 0, i;
0344
0345 *out_str = kmalloc(tmp_str_size, GFP_KERNEL);
0346
0347 n += snprintf(*out_str + n, tmp_str_size - n, "|");
0348
0349 for (i = 0; i < builder->num_valid; i++) {
0350 int frame_num = builder->refs[reflist[i].index].frame_num;
0351 u32 poc = v4l2_h264_get_poc(builder, reflist + i);
0352 bool longterm = builder->refs[reflist[i].index].longterm;
0353
0354 n += scnprintf(*out_str + n, tmp_str_size - n, "%i%c%c|",
0355 longterm ? frame_num : poc,
0356 longterm ? 'l' : 's',
0357 ref_type_to_char(reflist[i].fields));
0358 }
0359
0360 return *out_str;
0361 }
0362
0363 static void print_ref_list_b(const struct v4l2_h264_reflist_builder *builder,
0364 struct v4l2_h264_reference *reflist, u8 list_num)
0365 {
0366 char *buf = NULL;
0367
0368 pr_debug("ref_pic_list_b%u (cur_poc %u%c) %s",
0369 list_num, builder->cur_pic_order_count,
0370 ref_type_to_char(builder->cur_pic_fields),
0371 format_ref_list_b(builder, reflist, &buf));
0372
0373 kfree(buf);
0374 }
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388 void
0389 v4l2_h264_build_p_ref_list(const struct v4l2_h264_reflist_builder *builder,
0390 struct v4l2_h264_reference *reflist)
0391 {
0392 memcpy(reflist, builder->unordered_reflist,
0393 sizeof(builder->unordered_reflist[0]) * builder->num_valid);
0394 sort_r(reflist, builder->num_valid, sizeof(*reflist),
0395 v4l2_h264_p_ref_list_cmp, NULL, builder);
0396
0397 if (builder->cur_pic_fields != V4L2_H264_FRAME_REF)
0398 reorder_field_reflist(builder, reflist);
0399
0400 print_ref_list_p(builder, reflist);
0401 }
0402 EXPORT_SYMBOL_GPL(v4l2_h264_build_p_ref_list);
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418 void
0419 v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder,
0420 struct v4l2_h264_reference *b0_reflist,
0421 struct v4l2_h264_reference *b1_reflist)
0422 {
0423 memcpy(b0_reflist, builder->unordered_reflist,
0424 sizeof(builder->unordered_reflist[0]) * builder->num_valid);
0425 sort_r(b0_reflist, builder->num_valid, sizeof(*b0_reflist),
0426 v4l2_h264_b0_ref_list_cmp, NULL, builder);
0427
0428 memcpy(b1_reflist, builder->unordered_reflist,
0429 sizeof(builder->unordered_reflist[0]) * builder->num_valid);
0430 sort_r(b1_reflist, builder->num_valid, sizeof(*b1_reflist),
0431 v4l2_h264_b1_ref_list_cmp, NULL, builder);
0432
0433 if (builder->cur_pic_fields != V4L2_H264_FRAME_REF) {
0434 reorder_field_reflist(builder, b0_reflist);
0435 reorder_field_reflist(builder, b1_reflist);
0436 }
0437
0438 if (builder->num_valid > 1 &&
0439 !memcmp(b1_reflist, b0_reflist, builder->num_valid))
0440 swap(b1_reflist[0], b1_reflist[1]);
0441
0442 print_ref_list_b(builder, b0_reflist, 0);
0443 print_ref_list_b(builder, b1_reflist, 1);
0444 }
0445 EXPORT_SYMBOL_GPL(v4l2_h264_build_b_ref_lists);
0446
0447 MODULE_LICENSE("GPL");
0448 MODULE_DESCRIPTION("V4L2 H264 Helpers");
0449 MODULE_AUTHOR("Boris Brezillon <boris.brezillon@collabora.com>");