/* * Size of the tempory buffer allocated when printing reference lists. The * output will be truncated if the size is too small.
*/ staticconstint tmp_str_size = 1024;
/** * v4l2_h264_init_reflist_builder() - Initialize a P/B0/B1 reference list * builder * * @b: the builder context to initialize * @dec_params: decode parameters control * @sps: SPS control * @dpb: DPB to use when creating the reference list
*/ void
v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, conststruct v4l2_ctrl_h264_decode_params *dec_params, conststruct v4l2_ctrl_h264_sps *sps, conststruct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES])
{ int cur_frame_num, max_frame_num; unsignedint i;
for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) { if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) continue;
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
b->refs[i].longterm = true;
/* * Handle frame_num wraparound as described in section * '8.2.4.1 Decoding process for picture numbers' of the spec. * For long term references, frame_num is set to * long_term_frame_idx which requires no wrapping.
*/ if (!b->refs[i].longterm && dpb[i].frame_num > cur_frame_num)
b->refs[i].frame_num = (int)dpb[i].frame_num -
max_frame_num; else
b->refs[i].frame_num = dpb[i].frame_num;
for (i = b->num_valid; i < ARRAY_SIZE(b->unordered_reflist); i++)
b->unordered_reflist[i].index = i;
}
EXPORT_SYMBOL_GPL(v4l2_h264_init_reflist_builder);
static s32 v4l2_h264_get_poc(conststruct v4l2_h264_reflist_builder *b, conststruct v4l2_h264_reference *ref)
{ switch (ref->fields) { case V4L2_H264_FRAME_REF: return min(b->refs[ref->index].top_field_order_cnt,
b->refs[ref->index].bottom_field_order_cnt); case V4L2_H264_TOP_FIELD_REF: return b->refs[ref->index].top_field_order_cnt; case V4L2_H264_BOTTOM_FIELD_REF: return b->refs[ref->index].bottom_field_order_cnt;
}
if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
idxb >= V4L2_H264_NUM_DPB_ENTRIES)) return 1;
if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) { /* Short term pics first. */ if (!builder->refs[idxa].longterm) return -1; else return 1;
}
/* * For frames, short term pics are in descending pic num order and long * term ones in ascending order. For fields, the same direction is used * but with frame_num (wrapped). For frames, the value of pic_num and * frame_num are the same (see formula (8-28) and (8-29)). For this * reason we can use frame_num only and share this function between * frames and fields reflist.
*/ if (!builder->refs[idxa].longterm) return builder->refs[idxb].frame_num <
builder->refs[idxa].frame_num ?
-1 : 1;
if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
idxb >= V4L2_H264_NUM_DPB_ENTRIES)) return 1;
if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) { /* Short term pics first. */ if (!builder->refs[idxa].longterm) return -1; else return 1;
}
/* Long term pics in ascending frame num order. */ if (builder->refs[idxa].longterm) return builder->refs[idxa].frame_num <
builder->refs[idxb].frame_num ?
-1 : 1;
/* * Short term pics with POC < cur POC first in POC descending order * followed by short term pics with POC > cur POC in POC ascending * order.
*/ if ((poca < builder->cur_pic_order_count) !=
(pocb < builder->cur_pic_order_count)) return poca < pocb ? -1 : 1; elseif (poca < builder->cur_pic_order_count) return pocb < poca ? -1 : 1;
if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
idxb >= V4L2_H264_NUM_DPB_ENTRIES)) return 1;
if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) { /* Short term pics first. */ if (!builder->refs[idxa].longterm) return -1; else return 1;
}
/* Long term pics in ascending frame num order. */ if (builder->refs[idxa].longterm) return builder->refs[idxa].frame_num <
builder->refs[idxb].frame_num ?
-1 : 1;
/* * Short term pics with POC > cur POC first in POC ascending order * followed by short term pics with POC < cur POC in POC descending * order.
*/ if ((poca < builder->cur_pic_order_count) !=
(pocb < builder->cur_pic_order_count)) return pocb < poca ? -1 : 1; elseif (poca < builder->cur_pic_order_count) return pocb < poca ? -1 : 1;
return poca < pocb ? -1 : 1;
}
/* * The references need to be reordered so that references are alternating * between top and bottom field references starting with the current picture * parity. This has to be done for short term and long term references * separately.
*/ staticvoid reorder_field_reflist(conststruct v4l2_h264_reflist_builder *b, struct v4l2_h264_reference *reflist)
{ struct v4l2_h264_reference tmplist[V4L2_H264_REF_LIST_LEN];
u8 lt, i = 0, j = 0, k = 0;
staticchar ref_type_to_char(u8 ref_type)
{ switch (ref_type) { case V4L2_H264_FRAME_REF: return'f'; case V4L2_H264_TOP_FIELD_REF: return't'; case V4L2_H264_BOTTOM_FIELD_REF: return'b';
}
return'?';
}
staticconstchar *format_ref_list_p(conststruct v4l2_h264_reflist_builder *builder, struct v4l2_h264_reference *reflist, char **out_str)
{ int n = 0, i;
*out_str = kmalloc(tmp_str_size, GFP_KERNEL); if (!(*out_str)) return NULL;
n += snprintf(*out_str + n, tmp_str_size - n, "|");
for (i = 0; i < builder->num_valid; i++) { /* this is pic_num for frame and frame_num (wrapped) for field, * but for frame pic_num is equal to frame_num (wrapped).
*/ int frame_num = builder->refs[reflist[i].index].frame_num; bool longterm = builder->refs[reflist[i].index].longterm;
n += scnprintf(*out_str + n, tmp_str_size - n, "%i%c%c|",
frame_num, longterm ? 'l' : 's',
ref_type_to_char(reflist[i].fields));
}
/** * v4l2_h264_build_p_ref_list() - Build the P reference list * * @builder: reference list builder context * @reflist: 32 sized array used to store the P reference list. Each entry * is a v4l2_h264_reference structure * * This functions builds the P reference lists. This procedure is describe in * section '8.2.4 Decoding process for reference picture lists construction' * of the H264 spec. This function can be used by H264 decoder drivers that * need to pass a P reference list to the hardware.
*/ void
v4l2_h264_build_p_ref_list(conststruct v4l2_h264_reflist_builder *builder, struct v4l2_h264_reference *reflist)
{
memcpy(reflist, builder->unordered_reflist, sizeof(builder->unordered_reflist[0]) * builder->num_valid);
sort_r(reflist, builder->num_valid, sizeof(*reflist),
v4l2_h264_p_ref_list_cmp, NULL, builder);
if (builder->cur_pic_fields != V4L2_H264_FRAME_REF)
reorder_field_reflist(builder, reflist);
/** * v4l2_h264_build_b_ref_lists() - Build the B0/B1 reference lists * * @builder: reference list builder context * @b0_reflist: 32 sized array used to store the B0 reference list. Each entry * is a v4l2_h264_reference structure * @b1_reflist: 32 sized array used to store the B1 reference list. Each entry * is a v4l2_h264_reference structure * * This functions builds the B0/B1 reference lists. This procedure is described * in section '8.2.4 Decoding process for reference picture lists construction' * of the H264 spec. This function can be used by H264 decoder drivers that * need to pass B0/B1 reference lists to the hardware.
*/ void
v4l2_h264_build_b_ref_lists(conststruct v4l2_h264_reflist_builder *builder, struct v4l2_h264_reference *b0_reflist, struct v4l2_h264_reference *b1_reflist)
{
memcpy(b0_reflist, builder->unordered_reflist, sizeof(builder->unordered_reflist[0]) * builder->num_valid);
sort_r(b0_reflist, builder->num_valid, sizeof(*b0_reflist),
v4l2_h264_b0_ref_list_cmp, NULL, builder);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.