mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-22 22:07:20 +07:00
media: hantro: h264: Use the generic H264 reflist builder
Now that the core provides generic reflist builders, we can use them instead of implementing our own. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
624922a273
commit
b5218cf40c
@ -8,6 +8,7 @@ config VIDEO_HANTRO
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select VIDEOBUF2_VMALLOC
|
||||
select V4L2_MEM2MEM_DEV
|
||||
select V4L2_H264
|
||||
help
|
||||
Support for the Hantro IP based Video Processing Units present on
|
||||
Rockchip and NXP i.MX8M SoCs, which accelerate video and image
|
||||
|
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/sort.h>
|
||||
#include <media/v4l2-h264.h>
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
|
||||
#include "hantro.h"
|
||||
@ -240,229 +240,6 @@ static void prepare_table(struct hantro_ctx *ctx)
|
||||
reorder_scaling_list(ctx);
|
||||
}
|
||||
|
||||
struct hantro_h264_reflist_builder {
|
||||
const struct v4l2_h264_dpb_entry *dpb;
|
||||
s32 pocs[HANTRO_H264_DPB_SIZE];
|
||||
u8 unordered_reflist[HANTRO_H264_DPB_SIZE];
|
||||
int frame_nums[HANTRO_H264_DPB_SIZE];
|
||||
s32 curpoc;
|
||||
u8 num_valid;
|
||||
};
|
||||
|
||||
static s32 get_poc(enum v4l2_field field, s32 top_field_order_cnt,
|
||||
s32 bottom_field_order_cnt)
|
||||
{
|
||||
switch (field) {
|
||||
case V4L2_FIELD_TOP:
|
||||
return top_field_order_cnt;
|
||||
case V4L2_FIELD_BOTTOM:
|
||||
return bottom_field_order_cnt;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return min(top_field_order_cnt, bottom_field_order_cnt);
|
||||
}
|
||||
|
||||
static void
|
||||
init_reflist_builder(struct hantro_ctx *ctx,
|
||||
struct hantro_h264_reflist_builder *b)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_slice_params *slice_params;
|
||||
const struct v4l2_ctrl_h264_decode_params *dec_param;
|
||||
const struct v4l2_ctrl_h264_sps *sps;
|
||||
struct vb2_v4l2_buffer *buf = hantro_get_dst_buf(ctx);
|
||||
const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
|
||||
struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q;
|
||||
int cur_frame_num, max_frame_num;
|
||||
unsigned int i;
|
||||
|
||||
dec_param = ctx->h264_dec.ctrls.decode;
|
||||
slice_params = &ctx->h264_dec.ctrls.slices[0];
|
||||
sps = ctx->h264_dec.ctrls.sps;
|
||||
max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
|
||||
cur_frame_num = slice_params->frame_num;
|
||||
|
||||
memset(b, 0, sizeof(*b));
|
||||
b->dpb = dpb;
|
||||
b->curpoc = get_poc(buf->field, dec_param->top_field_order_cnt,
|
||||
dec_param->bottom_field_order_cnt);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++) {
|
||||
int buf_idx;
|
||||
|
||||
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
|
||||
continue;
|
||||
|
||||
buf_idx = vb2_find_timestamp(cap_q, dpb[i].reference_ts, 0);
|
||||
if (buf_idx < 0)
|
||||
continue;
|
||||
|
||||
buf = to_vb2_v4l2_buffer(vb2_get_buffer(cap_q, buf_idx));
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (dpb[i].frame_num > cur_frame_num)
|
||||
b->frame_nums[i] = (int)dpb[i].frame_num - max_frame_num;
|
||||
else
|
||||
b->frame_nums[i] = dpb[i].frame_num;
|
||||
|
||||
b->pocs[i] = get_poc(buf->field, dpb[i].top_field_order_cnt,
|
||||
dpb[i].bottom_field_order_cnt);
|
||||
b->unordered_reflist[b->num_valid] = i;
|
||||
b->num_valid++;
|
||||
}
|
||||
|
||||
for (i = b->num_valid; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++)
|
||||
b->unordered_reflist[i] = i;
|
||||
}
|
||||
|
||||
static int p_ref_list_cmp(const void *ptra, const void *ptrb, const void *data)
|
||||
{
|
||||
const struct hantro_h264_reflist_builder *builder = data;
|
||||
const struct v4l2_h264_dpb_entry *a, *b;
|
||||
u8 idxa, idxb;
|
||||
|
||||
idxa = *((u8 *)ptra);
|
||||
idxb = *((u8 *)ptrb);
|
||||
a = &builder->dpb[idxa];
|
||||
b = &builder->dpb[idxb];
|
||||
|
||||
if ((a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) !=
|
||||
(b->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)) {
|
||||
/* Short term pics firt. */
|
||||
if (!(a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Short term pics in descending pic num order, long term ones in
|
||||
* ascending order.
|
||||
*/
|
||||
if (!(a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM))
|
||||
return HANTRO_CMP(builder->frame_nums[idxb],
|
||||
builder->frame_nums[idxa]);
|
||||
|
||||
return HANTRO_CMP(a->pic_num, b->pic_num);
|
||||
}
|
||||
|
||||
static int b0_ref_list_cmp(const void *ptra, const void *ptrb, const void *data)
|
||||
{
|
||||
const struct hantro_h264_reflist_builder *builder = data;
|
||||
const struct v4l2_h264_dpb_entry *a, *b;
|
||||
s32 poca, pocb;
|
||||
u8 idxa, idxb;
|
||||
|
||||
idxa = *((u8 *)ptra);
|
||||
idxb = *((u8 *)ptrb);
|
||||
a = &builder->dpb[idxa];
|
||||
b = &builder->dpb[idxb];
|
||||
|
||||
if ((a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) !=
|
||||
(b->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)) {
|
||||
/* Short term pics firt. */
|
||||
if (!(a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Long term pics in ascending pic num order. */
|
||||
if (a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
|
||||
return HANTRO_CMP(a->pic_num, b->pic_num);
|
||||
|
||||
poca = builder->pocs[idxa];
|
||||
pocb = builder->pocs[idxb];
|
||||
|
||||
/*
|
||||
* 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->curpoc) != (pocb < builder->curpoc))
|
||||
return HANTRO_CMP(poca, pocb);
|
||||
else if (poca < builder->curpoc)
|
||||
return HANTRO_CMP(pocb, poca);
|
||||
|
||||
return HANTRO_CMP(poca, pocb);
|
||||
}
|
||||
|
||||
static int b1_ref_list_cmp(const void *ptra, const void *ptrb, const void *data)
|
||||
{
|
||||
const struct hantro_h264_reflist_builder *builder = data;
|
||||
const struct v4l2_h264_dpb_entry *a, *b;
|
||||
s32 poca, pocb;
|
||||
u8 idxa, idxb;
|
||||
|
||||
idxa = *((u8 *)ptra);
|
||||
idxb = *((u8 *)ptrb);
|
||||
a = &builder->dpb[idxa];
|
||||
b = &builder->dpb[idxb];
|
||||
|
||||
if ((a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) !=
|
||||
(b->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)) {
|
||||
/* Short term pics firt. */
|
||||
if (!(a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Long term pics in ascending pic num order. */
|
||||
if (a->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
|
||||
return HANTRO_CMP(a->pic_num, b->pic_num);
|
||||
|
||||
poca = builder->pocs[idxa];
|
||||
pocb = builder->pocs[idxb];
|
||||
|
||||
/*
|
||||
* 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->curpoc) != (pocb < builder->curpoc))
|
||||
return HANTRO_CMP(pocb, poca);
|
||||
else if (poca < builder->curpoc)
|
||||
return HANTRO_CMP(pocb, poca);
|
||||
|
||||
return HANTRO_CMP(poca, pocb);
|
||||
}
|
||||
|
||||
static void
|
||||
build_p_ref_list(const struct hantro_h264_reflist_builder *builder,
|
||||
u8 *reflist)
|
||||
{
|
||||
memcpy(reflist, builder->unordered_reflist,
|
||||
sizeof(builder->unordered_reflist));
|
||||
sort_r(reflist, builder->num_valid, sizeof(*reflist),
|
||||
p_ref_list_cmp, NULL, builder);
|
||||
}
|
||||
|
||||
static void
|
||||
build_b_ref_lists(const struct hantro_h264_reflist_builder *builder,
|
||||
u8 *b0_reflist, u8 *b1_reflist)
|
||||
{
|
||||
memcpy(b0_reflist, builder->unordered_reflist,
|
||||
sizeof(builder->unordered_reflist));
|
||||
sort_r(b0_reflist, builder->num_valid, sizeof(*b0_reflist),
|
||||
b0_ref_list_cmp, NULL, builder);
|
||||
|
||||
memcpy(b1_reflist, builder->unordered_reflist,
|
||||
sizeof(builder->unordered_reflist));
|
||||
sort_r(b1_reflist, builder->num_valid, sizeof(*b1_reflist),
|
||||
b1_ref_list_cmp, NULL, builder);
|
||||
|
||||
if (builder->num_valid > 1 &&
|
||||
!memcmp(b1_reflist, b0_reflist, builder->num_valid))
|
||||
swap(b1_reflist[0], b1_reflist[1]);
|
||||
}
|
||||
|
||||
static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a,
|
||||
const struct v4l2_h264_dpb_entry *b)
|
||||
{
|
||||
@ -560,7 +337,7 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
|
||||
{
|
||||
struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec;
|
||||
struct hantro_h264_dec_ctrls *ctrls = &h264_ctx->ctrls;
|
||||
struct hantro_h264_reflist_builder reflist_builder;
|
||||
struct v4l2_h264_reflist_builder reflist_builder;
|
||||
|
||||
hantro_start_prepare_run(ctx);
|
||||
|
||||
@ -596,10 +373,12 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
|
||||
prepare_table(ctx);
|
||||
|
||||
/* Build the P/B{0,1} ref lists. */
|
||||
init_reflist_builder(ctx, &reflist_builder);
|
||||
build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
|
||||
build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
|
||||
h264_ctx->reflists.b1);
|
||||
v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode,
|
||||
&ctrls->slices[0], ctrls->sps,
|
||||
ctx->h264_dec.dpb);
|
||||
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
|
||||
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
|
||||
h264_ctx->reflists.b1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user