Skip to content

Commit

Permalink
media: h264: Use v4l2_h264_reference for reflist
Browse files Browse the repository at this point in the history
In preparation for adding field decoding support, convert the byte arrays
for reflist into array of struct v4l2_h264_reference. That struct will
allow us to mark which field of the reference picture is being referenced.

[hverkuil: top_field_order_cnt -> pic_order_count]

Signed-off-by: Nicolas Dufresne <[email protected]>
Reviewed-by: Ezequiel Garcia <[email protected]>
Tested-by: Dmitry Osipenko <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
ndufresne authored and mchehab committed May 17, 2022
1 parent 4d52db4 commit 2e2c3d6
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 132 deletions.
21 changes: 17 additions & 4 deletions drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,24 @@
#define GET_MTK_VDEC_PARAM(param) \
{ dst_param->param = src_param->param; }

/*
* The firmware expects unused reflist entries to have the value 0x20.
*/
void mtk_vdec_h264_fixup_ref_list(u8 *ref_list, size_t num_valid)
void mtk_vdec_h264_get_ref_list(u8 *ref_list,
const struct v4l2_h264_reference *v4l2_ref_list,
int num_valid)
{
u32 i;

/*
* TODO The firmware does not support field decoding. Future
* implementation must use v4l2_ref_list[i].fields to obtain
* the reference field parity.
*/

for (i = 0; i < num_valid; i++)
ref_list[i] = v4l2_ref_list[i].index;

/*
* The firmware expects unused reflist entries to have the value 0x20.
*/
memset(&ref_list[num_valid], 0x20, 32 - num_valid);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,15 @@ struct h264_fb {
};

/**
* mtk_vdec_h264_fixup_ref_list - fixup unused reference to 0x20.
* mtk_vdec_h264_get_ref_list - translate V4L2 reference list
*
* @ref_list: reference picture list
* @num_valid: used reference number
* @ref_list: Mediatek reference picture list
* @v4l2_ref_list: V4L2 reference picture list
* @num_valid: used reference number
*/
void mtk_vdec_h264_fixup_ref_list(u8 *ref_list, size_t num_valid);
void mtk_vdec_h264_get_ref_list(u8 *ref_list,
const struct v4l2_h264_reference *v4l2_ref_list,
int num_valid);

/**
* mtk_vdec_h264_get_ctrl_ptr - get each CID contrl address.
Expand Down
15 changes: 10 additions & 5 deletions drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ static int get_vdec_decode_parameters(struct vdec_h264_slice_inst *inst)
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
struct mtk_h264_dec_slice_param *slice_param = &inst->h264_slice_param;
struct v4l2_h264_reflist_builder reflist_builder;
struct v4l2_h264_reference v4l2_p0_reflist[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference v4l2_b0_reflist[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference v4l2_b1_reflist[V4L2_H264_REF_LIST_LEN];
u8 *p0_reflist = slice_param->decode_params.ref_pic_list_p0;
u8 *b0_reflist = slice_param->decode_params.ref_pic_list_b0;
u8 *b1_reflist = slice_param->decode_params.ref_pic_list_b1;
Expand Down Expand Up @@ -137,12 +140,14 @@ static int get_vdec_decode_parameters(struct vdec_h264_slice_inst *inst)
/* Build the reference lists */
v4l2_h264_init_reflist_builder(&reflist_builder, dec_params, sps,
inst->dpb);
v4l2_h264_build_p_ref_list(&reflist_builder, p0_reflist);
v4l2_h264_build_b_ref_lists(&reflist_builder, b0_reflist, b1_reflist);
v4l2_h264_build_p_ref_list(&reflist_builder, v4l2_p0_reflist);
v4l2_h264_build_b_ref_lists(&reflist_builder, v4l2_b0_reflist,
v4l2_b1_reflist);

/* Adapt the built lists to the firmware's expectations */
mtk_vdec_h264_fixup_ref_list(p0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_fixup_ref_list(b0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_fixup_ref_list(b1_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(p0_reflist, v4l2_p0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(b0_reflist, v4l2_b0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(b1_reflist, v4l2_b1_reflist, reflist_builder.num_valid);

memcpy(&inst->vsi_ctx.h264_slice_params, slice_param,
sizeof(inst->vsi_ctx.h264_slice_params));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ static int get_vdec_sig_decode_parameters(struct vdec_h264_slice_inst *inst)
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
struct vdec_h264_slice_lat_dec_param *slice_param = &inst->h264_slice_param;
struct v4l2_h264_reflist_builder reflist_builder;
struct v4l2_h264_reference v4l2_p0_reflist[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference v4l2_b0_reflist[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference v4l2_b1_reflist[V4L2_H264_REF_LIST_LEN];
u8 *p0_reflist = slice_param->decode_params.ref_pic_list_p0;
u8 *b0_reflist = slice_param->decode_params.ref_pic_list_b0;
u8 *b1_reflist = slice_param->decode_params.ref_pic_list_b1;
Expand Down Expand Up @@ -256,13 +259,14 @@ static int get_vdec_sig_decode_parameters(struct vdec_h264_slice_inst *inst)

/* Build the reference lists */
v4l2_h264_init_reflist_builder(&reflist_builder, dec_params, sps, inst->dpb);
v4l2_h264_build_p_ref_list(&reflist_builder, p0_reflist);
v4l2_h264_build_p_ref_list(&reflist_builder, v4l2_p0_reflist);
v4l2_h264_build_b_ref_lists(&reflist_builder, v4l2_b0_reflist, v4l2_b1_reflist);

v4l2_h264_build_b_ref_lists(&reflist_builder, b0_reflist, b1_reflist);
/* Adapt the built lists to the firmware's expectations */
mtk_vdec_h264_fixup_ref_list(p0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_fixup_ref_list(b0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_fixup_ref_list(b1_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(p0_reflist, v4l2_p0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(b0_reflist, v4l2_b0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(b1_reflist, v4l2_b1_reflist, reflist_builder.num_valid);

memcpy(&inst->vsi_ctx.h264_slice_params, slice_param,
sizeof(inst->vsi_ctx.h264_slice_params));

Expand All @@ -276,6 +280,9 @@ static void vdec_h264_slice_fill_decode_reflist(struct vdec_h264_slice_inst *ins
struct v4l2_ctrl_h264_decode_params *dec_params = &share_info->dec_params;
struct v4l2_ctrl_h264_sps *sps = &share_info->sps;
struct v4l2_h264_reflist_builder reflist_builder;
struct v4l2_h264_reference v4l2_p0_reflist[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference v4l2_b0_reflist[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference v4l2_b1_reflist[V4L2_H264_REF_LIST_LEN];
u8 *p0_reflist = slice_param->decode_params.ref_pic_list_p0;
u8 *b0_reflist = slice_param->decode_params.ref_pic_list_b0;
u8 *b1_reflist = slice_param->decode_params.ref_pic_list_b1;
Expand All @@ -291,13 +298,13 @@ static void vdec_h264_slice_fill_decode_reflist(struct vdec_h264_slice_inst *ins
/* Build the reference lists */
v4l2_h264_init_reflist_builder(&reflist_builder, dec_params, sps,
inst->dpb);
v4l2_h264_build_p_ref_list(&reflist_builder, p0_reflist);
v4l2_h264_build_b_ref_lists(&reflist_builder, b0_reflist, b1_reflist);
v4l2_h264_build_p_ref_list(&reflist_builder, v4l2_p0_reflist);
v4l2_h264_build_b_ref_lists(&reflist_builder, v4l2_b0_reflist, v4l2_b1_reflist);

/* Adapt the built lists to the firmware's expectations */
mtk_vdec_h264_fixup_ref_list(p0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_fixup_ref_list(b0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_fixup_ref_list(b1_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(p0_reflist, v4l2_p0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(b0_reflist, v4l2_b0_reflist, reflist_builder.num_valid);
mtk_vdec_h264_get_ref_list(b1_reflist, v4l2_b1_reflist, reflist_builder.num_valid);
}

static int vdec_h264_slice_alloc_mv_buf(struct vdec_h264_slice_inst *inst,
Expand Down
19 changes: 12 additions & 7 deletions drivers/media/platform/nvidia/tegra-vde/h264.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ struct tegra_vde_h264_decoder_ctx {
};

struct h264_reflists {
u8 p[V4L2_H264_NUM_DPB_ENTRIES];
u8 b0[V4L2_H264_NUM_DPB_ENTRIES];
u8 b1[V4L2_H264_NUM_DPB_ENTRIES];
struct v4l2_h264_reference p[V4L2_H264_NUM_DPB_ENTRIES];
struct v4l2_h264_reference b0[V4L2_H264_NUM_DPB_ENTRIES];
struct v4l2_h264_reference b1[V4L2_H264_NUM_DPB_ENTRIES];
};

static int tegra_vde_wait_mbe(struct tegra_vde *vde)
Expand Down Expand Up @@ -765,10 +765,10 @@ static int tegra_vde_h264_setup_frames(struct tegra_ctx *ctx,
struct tegra_m2m_buffer *tb = vb_to_tegra_buf(&dst->vb2_buf);
struct tegra_ctx_h264 *h = &ctx->h264;
struct v4l2_h264_reflist_builder b;
struct v4l2_h264_reference *dpb_id;
struct h264_reflists reflists;
struct vb2_buffer *ref;
unsigned int i;
u8 *dpb_id;
int err;

/*
Expand Down Expand Up @@ -811,14 +811,16 @@ static int tegra_vde_h264_setup_frames(struct tegra_ctx *ctx,
}

for (i = 0; i < b.num_valid; i++) {
ref = get_ref_buf(ctx, dst, dpb_id[i]);
int dpb_idx = dpb_id[i].index;

err = tegra_vde_h264_setup_frame(ctx, h264, &b, ref, dpb_id[i],
ref = get_ref_buf(ctx, dst, dpb_idx);

err = tegra_vde_h264_setup_frame(ctx, h264, &b, ref, dpb_idx,
h264->dpb_frames_nb++);
if (err)
return err;

if (b.refs[dpb_id[i]].pic_order_count < b.cur_pic_order_count)
if (b.refs[dpb_idx].pic_order_count < b.cur_pic_order_count)
h264->dpb_ref_frames_with_earlier_poc_nb++;
}

Expand Down Expand Up @@ -880,6 +882,9 @@ static int tegra_vde_h264_setup_context(struct tegra_ctx *ctx,
if (h->pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
return -EOPNOTSUPP;

if (h->decode_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)
return -EOPNOTSUPP;

if (h->sps->profile_idc == 66)
h264->baseline_profile = 1;

Expand Down
33 changes: 17 additions & 16 deletions drivers/media/v4l2-core/v4l2-h264.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
pic_order_count = dpb[i].top_field_order_cnt;

b->refs[i].pic_order_count = pic_order_count;
b->unordered_reflist[b->num_valid] = i;
b->unordered_reflist[b->num_valid].index = i;
b->num_valid++;
}

for (i = b->num_valid; i < ARRAY_SIZE(b->unordered_reflist); i++)
b->unordered_reflist[i] = i;
b->unordered_reflist[i].index = i;
}
EXPORT_SYMBOL_GPL(v4l2_h264_init_reflist_builder);

Expand All @@ -90,8 +90,8 @@ static int v4l2_h264_p_ref_list_cmp(const void *ptra, const void *ptrb,
const struct v4l2_h264_reflist_builder *builder = data;
u8 idxa, idxb;

idxa = *((u8 *)ptra);
idxb = *((u8 *)ptrb);
idxa = ((struct v4l2_h264_reference *)ptra)->index;
idxb = ((struct v4l2_h264_reference *)ptrb)->index;

if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
idxb >= V4L2_H264_NUM_DPB_ENTRIES))
Expand Down Expand Up @@ -125,8 +125,8 @@ static int v4l2_h264_b0_ref_list_cmp(const void *ptra, const void *ptrb,
s32 poca, pocb;
u8 idxa, idxb;

idxa = *((u8 *)ptra);
idxb = *((u8 *)ptrb);
idxa = ((struct v4l2_h264_reference *)ptra)->index;
idxb = ((struct v4l2_h264_reference *)ptrb)->index;

if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
idxb >= V4L2_H264_NUM_DPB_ENTRIES))
Expand Down Expand Up @@ -170,8 +170,8 @@ static int v4l2_h264_b1_ref_list_cmp(const void *ptra, const void *ptrb,
s32 poca, pocb;
u8 idxa, idxb;

idxa = *((u8 *)ptra);
idxb = *((u8 *)ptrb);
idxa = ((struct v4l2_h264_reference *)ptra)->index;
idxb = ((struct v4l2_h264_reference *)ptrb)->index;

if (WARN_ON(idxa >= V4L2_H264_NUM_DPB_ENTRIES ||
idxb >= V4L2_H264_NUM_DPB_ENTRIES))
Expand Down Expand Up @@ -212,8 +212,8 @@ static int v4l2_h264_b1_ref_list_cmp(const void *ptra, const void *ptrb,
* v4l2_h264_build_p_ref_list() - Build the P reference list
*
* @builder: reference list builder context
* @reflist: 16-bytes array used to store the P reference list. Each entry
* is an index in the DPB
* @reflist: 16 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'
Expand All @@ -222,7 +222,7 @@ static int v4l2_h264_b1_ref_list_cmp(const void *ptra, const void *ptrb,
*/
void
v4l2_h264_build_p_ref_list(const struct v4l2_h264_reflist_builder *builder,
u8 *reflist)
struct v4l2_h264_reference *reflist)
{
memcpy(reflist, builder->unordered_reflist,
sizeof(builder->unordered_reflist[0]) * builder->num_valid);
Expand All @@ -235,10 +235,10 @@ EXPORT_SYMBOL_GPL(v4l2_h264_build_p_ref_list);
* v4l2_h264_build_b_ref_lists() - Build the B0/B1 reference lists
*
* @builder: reference list builder context
* @b0_reflist: 16-bytes array used to store the B0 reference list. Each entry
* is an index in the DPB
* @b1_reflist: 16-bytes array used to store the B1 reference list. Each entry
* is an index in the DPB
* @b0_reflist: 16 sized array used to store the B0 reference list. Each entry
* is a v4l2_h264_reference structure
* @b1_reflist: 16 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'
Expand All @@ -247,7 +247,8 @@ EXPORT_SYMBOL_GPL(v4l2_h264_build_p_ref_list);
*/
void
v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder,
u8 *b0_reflist, u8 *b1_reflist)
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);
Expand Down
38 changes: 19 additions & 19 deletions drivers/staging/media/hantro/hantro_g1_h264_dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)

static void set_ref(struct hantro_ctx *ctx)
{
const u8 *b0_reflist, *b1_reflist, *p_reflist;
const struct v4l2_h264_reference *b0_reflist, *b1_reflist, *p_reflist;
struct hantro_dev *vpu = ctx->dev;
int reg_num;
u32 reg;
Expand Down Expand Up @@ -157,12 +157,12 @@ static void set_ref(struct hantro_ctx *ctx)
*/
reg_num = 0;
for (i = 0; i < 15; i += 3) {
reg = G1_REG_BD_REF_PIC_BINIT_RLIST_F0(b0_reflist[i]) |
G1_REG_BD_REF_PIC_BINIT_RLIST_F1(b0_reflist[i + 1]) |
G1_REG_BD_REF_PIC_BINIT_RLIST_F2(b0_reflist[i + 2]) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B0(b1_reflist[i]) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B1(b1_reflist[i + 1]) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B2(b1_reflist[i + 2]);
reg = G1_REG_BD_REF_PIC_BINIT_RLIST_F0(b0_reflist[i].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_F1(b0_reflist[i + 1].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_F2(b0_reflist[i + 2].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B0(b1_reflist[i].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B1(b1_reflist[i + 1].index) |
G1_REG_BD_REF_PIC_BINIT_RLIST_B2(b1_reflist[i + 2].index);
vdpu_write_relaxed(vpu, reg, G1_REG_BD_REF_PIC(reg_num++));
}

Expand All @@ -171,12 +171,12 @@ static void set_ref(struct hantro_ctx *ctx)
* of forward and backward reference picture lists and first 4 entries
* of P forward picture list.
*/
reg = G1_REG_BD_P_REF_PIC_BINIT_RLIST_F15(b0_reflist[15]) |
G1_REG_BD_P_REF_PIC_BINIT_RLIST_B15(b1_reflist[15]) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F0(p_reflist[0]) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F1(p_reflist[1]) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F2(p_reflist[2]) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F3(p_reflist[3]);
reg = G1_REG_BD_P_REF_PIC_BINIT_RLIST_F15(b0_reflist[15].index) |
G1_REG_BD_P_REF_PIC_BINIT_RLIST_B15(b1_reflist[15].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F0(p_reflist[0].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F1(p_reflist[1].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F2(p_reflist[2].index) |
G1_REG_BD_P_REF_PIC_PINIT_RLIST_F3(p_reflist[3].index);
vdpu_write_relaxed(vpu, reg, G1_REG_BD_P_REF_PIC);

/*
Expand All @@ -185,12 +185,12 @@ static void set_ref(struct hantro_ctx *ctx)
*/
reg_num = 0;
for (i = 4; i < HANTRO_H264_DPB_SIZE; i += 6) {
reg = G1_REG_FWD_PIC_PINIT_RLIST_F0(p_reflist[i]) |
G1_REG_FWD_PIC_PINIT_RLIST_F1(p_reflist[i + 1]) |
G1_REG_FWD_PIC_PINIT_RLIST_F2(p_reflist[i + 2]) |
G1_REG_FWD_PIC_PINIT_RLIST_F3(p_reflist[i + 3]) |
G1_REG_FWD_PIC_PINIT_RLIST_F4(p_reflist[i + 4]) |
G1_REG_FWD_PIC_PINIT_RLIST_F5(p_reflist[i + 5]);
reg = G1_REG_FWD_PIC_PINIT_RLIST_F0(p_reflist[i].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F1(p_reflist[i + 1].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F2(p_reflist[i + 2].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F3(p_reflist[i + 3].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F4(p_reflist[i + 4].index) |
G1_REG_FWD_PIC_PINIT_RLIST_F5(p_reflist[i + 5].index);
vdpu_write_relaxed(vpu, reg, G1_REG_FWD_PIC(reg_num++));
}

Expand Down
6 changes: 3 additions & 3 deletions drivers/staging/media/hantro/hantro_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ struct hantro_h264_dec_ctrls {
* @b1: B1 reflist
*/
struct hantro_h264_dec_reflists {
u8 p[HANTRO_H264_DPB_SIZE];
u8 b0[HANTRO_H264_DPB_SIZE];
u8 b1[HANTRO_H264_DPB_SIZE];
struct v4l2_h264_reference p[HANTRO_H264_DPB_SIZE];
struct v4l2_h264_reference b0[HANTRO_H264_DPB_SIZE];
struct v4l2_h264_reference b1[HANTRO_H264_DPB_SIZE];
};

/**
Expand Down
Loading

0 comments on commit 2e2c3d6

Please sign in to comment.