diff options
author | Nicolas Dufresne <nicolas.dufresne@collabora.com> | 2022-05-13 23:29:06 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-05-17 11:01:10 +0300 |
commit | e5991e1fd90295b1eb8326a4a6c09012d6c5fc8d (patch) | |
tree | 389aff51727d5704c72f161f901b1fbbe989ad76 | |
parent | adc8a8d6c98a5c996aad41bf1625d87829bd76ba (diff) | |
download | linux-e5991e1fd90295b1eb8326a4a6c09012d6c5fc8d.tar.xz |
media: h264: Store all fields into the unordered list
When the current picture is a field, store each field into the
unordered_list and preserve both top and bottom picture order
count.
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Reviewed-by: Sebastian Fricke <sebastian.fricke@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
-rw-r--r-- | drivers/media/platform/nvidia/tegra-vde/h264.c | 2 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-h264.c | 65 | ||||
-rw-r--r-- | include/media/v4l2-h264.h | 6 |
3 files changed, 52 insertions, 21 deletions
diff --git a/drivers/media/platform/nvidia/tegra-vde/h264.c b/drivers/media/platform/nvidia/tegra-vde/h264.c index 4fb0aaad16d6..88f81a134ba0 100644 --- a/drivers/media/platform/nvidia/tegra-vde/h264.c +++ b/drivers/media/platform/nvidia/tegra-vde/h264.c @@ -820,7 +820,7 @@ static int tegra_vde_h264_setup_frames(struct tegra_ctx *ctx, if (err) return err; - if (b.refs[dpb_idx].pic_order_count < b.cur_pic_order_count) + if (b.refs[dpb_idx].top_field_order_cnt < b.cur_pic_order_count) h264->dpb_ref_frames_with_earlier_poc_nb++; } diff --git a/drivers/media/v4l2-core/v4l2-h264.c b/drivers/media/v4l2-core/v4l2-h264.c index 58f18bb0afb6..38d8dbda0045 100644 --- a/drivers/media/v4l2-core/v4l2-h264.c +++ b/drivers/media/v4l2-core/v4l2-h264.c @@ -47,8 +47,6 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, } for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) { - u32 pic_order_count; - if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) continue; @@ -59,8 +57,6 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, /* * Handle frame_num wraparound as described in section * '8.2.4.1 Decoding process for picture numbers' of the spec. - * TODO: This logic will have to be adjusted when we start - * supporting interlaced content. * For long term references, frame_num is set to * long_term_frame_idx which requires no wrapping. */ @@ -70,17 +66,33 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, else b->refs[i].frame_num = dpb[i].frame_num; - if (dpb[i].fields == V4L2_H264_FRAME_REF) - pic_order_count = min(dpb[i].top_field_order_cnt, - dpb[i].bottom_field_order_cnt); - else if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF) - pic_order_count = dpb[i].bottom_field_order_cnt; - else - pic_order_count = dpb[i].top_field_order_cnt; + b->refs[i].top_field_order_cnt = dpb[i].top_field_order_cnt; + b->refs[i].bottom_field_order_cnt = dpb[i].bottom_field_order_cnt; + + if (b->cur_pic_fields == V4L2_H264_FRAME_REF) { + u8 fields = V4L2_H264_FRAME_REF; + + b->unordered_reflist[b->num_valid].index = i; + b->unordered_reflist[b->num_valid].fields = fields; + b->num_valid++; + continue; + } + + if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF) { + u8 fields = V4L2_H264_TOP_FIELD_REF; + + b->unordered_reflist[b->num_valid].index = i; + b->unordered_reflist[b->num_valid].fields = fields; + b->num_valid++; + } - b->refs[i].pic_order_count = pic_order_count; - b->unordered_reflist[b->num_valid].index = i; - b->num_valid++; + if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF) { + u8 fields = V4L2_H264_BOTTOM_FIELD_REF; + + b->unordered_reflist[b->num_valid].index = i; + b->unordered_reflist[b->num_valid].fields = fields; + b->num_valid++; + } } for (i = b->num_valid; i < ARRAY_SIZE(b->unordered_reflist); i++) @@ -88,6 +100,23 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b, } EXPORT_SYMBOL_GPL(v4l2_h264_init_reflist_builder); +static s32 v4l2_h264_get_poc(const struct v4l2_h264_reflist_builder *b, + const struct 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; + } + + /* not reached */ + return 0; +} + static int v4l2_h264_p_ref_list_cmp(const void *ptra, const void *ptrb, const void *data) { @@ -150,8 +179,8 @@ static int v4l2_h264_b0_ref_list_cmp(const void *ptra, const void *ptrb, builder->refs[idxb].pic_num ? -1 : 1; - poca = builder->refs[idxa].pic_order_count; - pocb = builder->refs[idxb].pic_order_count; + poca = v4l2_h264_get_poc(builder, ptra); + pocb = v4l2_h264_get_poc(builder, ptrb); /* * Short term pics with POC < cur POC first in POC descending order @@ -195,8 +224,8 @@ static int v4l2_h264_b1_ref_list_cmp(const void *ptra, const void *ptrb, builder->refs[idxb].pic_num ? -1 : 1; - poca = builder->refs[idxa].pic_order_count; - pocb = builder->refs[idxb].pic_order_count; + poca = v4l2_h264_get_poc(builder, ptra); + pocb = v4l2_h264_get_poc(builder, ptrb); /* * Short term pics with POC > cur POC first in POC ascending order diff --git a/include/media/v4l2-h264.h b/include/media/v4l2-h264.h index e165a54c68fa..4cef717b3f18 100644 --- a/include/media/v4l2-h264.h +++ b/include/media/v4l2-h264.h @@ -15,7 +15,8 @@ /** * struct v4l2_h264_reflist_builder - Reference list builder object * - * @refs.pic_order_count: reference picture order count + * @refs.top_field_order_cnt: top field order count + * @refs.bottom_field_order_cnt: bottom field order count * @refs.frame_num: reference frame number * @refs.pic_num: reference picture number * @refs.longterm: set to true for a long term reference @@ -32,7 +33,8 @@ */ struct v4l2_h264_reflist_builder { struct { - s32 pic_order_count; + s32 top_field_order_cnt; + s32 bottom_field_order_cnt; int frame_num; u32 pic_num; u16 longterm : 1; |