Skip to content
Snippets Groups Projects
Commit ca1733fb authored by Nicolas Dufresne's avatar Nicolas Dufresne
Browse files

WIP: Drafted interlaced support

This is a large patch that sketch the idea, this is not working. Will
reconstruct smaller patches, making sure it works every step now.
parent 5662d54d
No related merge requests found
......@@ -34,16 +34,20 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
cur_frame_num = dec_params->frame_num;
memset(b, 0, sizeof(*b));
if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC))
if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) {
b->cur_pic_order_count = min(dec_params->bottom_field_order_cnt,
dec_params->top_field_order_cnt);
else if (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
b->cur_pic_field = V4L2_H264_FRAME_REF;
} else if (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) {
b->cur_pic_order_count = dec_params->bottom_field_order_cnt;
else
b->cur_pic_field = V4L2_H264_BOTTOM_FIELD_REF;
} else {
b->cur_pic_order_count = dec_params->top_field_order_cnt;
b->cur_pic_field = V4L2_H264_TOP_FIELD_REF;
}
for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
u32 pic_order_count;
struct v4l2_h264_reference *ref;
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
continue;
......@@ -52,11 +56,13 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
b->refs[i].longterm = true;
/* FIXME we are missing a flag for "non-existing" references. */
/*
* 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 reference, frame_num is set to
* long_term_frame_idx which requires no wrapping.
*/
if (dpb[i].frame_num > cur_frame_num)
b->refs[i].frame_num = (int)dpb[i].frame_num -
......@@ -64,21 +70,37 @@ 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].pic_order_count = pic_order_count;
b->unordered_reflist[b->num_valid] = i;
if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) {
b->refs[i].top_field_order_cnt = min(dpb[i].bottom_field_order_cnt,
dpb[i].top_field_order_cnt);
ref = &b->unordered_reflist[b->num_refs];
ref->index = i;
ref->fields = V4L2_H264_FRAME_REF;
b->num_refs++;
} else {
if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF) {
b->refs[i].top_field_order_cnt = dpb[i].top_field_order_cnt;
ref = &b->unordered_reflist[b->num_refs];
ref->index = i;
ref->fields = V4L2_H264_TOP_FIELD_REF;
b->num_refs++;
}
if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF) {
b->refs[i].bottom_field_order_cnt = dpb[i].bottom_field_order_cnt;
ref = &b->unordered_reflist[b->num_refs];
ref->index = i;
ref->fields = V4L2_H264_BOTTOM_FIELD_REF;
b->num_refs++;
}
}
b->num_valid++;
}
for (i = b->num_valid; i < ARRAY_SIZE(b->unordered_reflist); i++)
b->unordered_reflist[i] = i;
for (i = b->num_refs; i < ARRAY_SIZE(b->unordered_reflist); i++)
b->unordered_reflist[i] = (struct v4l2_h264_reference) { i, 0 };
}
EXPORT_SYMBOL_GPL(v4l2_h264_init_reflist_builder);
......@@ -88,8 +110,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))
......@@ -116,15 +138,54 @@ static int v4l2_h264_p_ref_list_cmp(const void *ptra, const void *ptrb,
-1 : 1;
}
static int v4l2_h264_b0_ref_list_cmp(const void *ptra, const void *ptrb,
static s32 v4l2_h264_get_poc(const struct v4l2_h264_reflist_builder *b,
const struct v4l2_h264_reference *ref)
{
if (ref->fields == V4L2_H264_BOTTOM_FIELD_REF)
return b->refs[ref->index].bottom_field_order_cnt;
else
return b->refs[ref->index].top_field_order_cnt;
}
static int v4l2_h264_b0_st_ref_list_cmp(const void *ptra, const void *ptrb,
const void *data)
{
const struct v4l2_h264_reflist_builder *builder = data;
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))
return 1;
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
* 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;
else if (poca < builder->cur_pic_order_count)
return pocb < poca ? -1 : 1;
return poca < pocb ? -1 : 1;
}
static int v4l2_h264_b0_ref_list_cmp(const void *ptra, const void *ptrb,
const void *data)
{
const struct v4l2_h264_reflist_builder *builder = data;
u8 idxa, idxb;
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))
......@@ -144,17 +205,34 @@ 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;
return v4l2_h264_b0_st_ref_list_cmp(ptra, ptrb, data);
}
static int v4l2_h264_b1_st_ref_list_cmp(const void *ptra, const void *ptrb,
const void *data)
{
const struct v4l2_h264_reflist_builder *builder = data;
s32 poca, pocb;
u8 idxa, idxb;
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))
return 1;
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
* followed by short term pics with POC > cur POC in POC ascending
* 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 poca < pocb ? -1 : 1;
return pocb < poca ? -1 : 1;
else if (poca < builder->cur_pic_order_count)
return pocb < poca ? -1 : 1;
......@@ -165,17 +243,17 @@ static int v4l2_h264_b1_ref_list_cmp(const void *ptra, const void *ptrb,
const void *data)
{
const struct v4l2_h264_reflist_builder *builder = data;
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))
return 1;
if (builder->refs[idxa].longterm != builder->refs[idxb].longterm) {
/* Short term pics first. */
if (!builder->refs[idxa].longterm)
return -1;
......@@ -189,21 +267,159 @@ 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;
return v4l2_h264_b1_st_ref_list_cmp(ptra, ptrb, data);
}
static int v4l2_h264_desc_frame_num_cmp(const void *ptra, const void *ptrb,
const void *data)
{
const struct v4l2_h264_reflist_builder *b = data;
u8 idxa, idxb;
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))
return 1;
return b->refs[idxb].frame_num < b->refs[idxa].frame_num ? -1 : 1;
}
static int v4l2_h264_asc_frame_num_cmp(const void *ptra, const void *ptrb,
const void *data)
{
const struct v4l2_h264_reflist_builder *b = data;
u8 idxa, idxb;
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))
return 1;
return b->refs[idxa].frame_num < b->refs[idxb].frame_num ? -1 : 1;
}
static void v4l2_h264_alternate_field_merge(struct v4l2_h264_reference *reflist,
struct v4l2_h264_reference tmp_list[2][V4L2_H264_REF_LIST_LEN],
const u8 tmp_len[2],
const struct v4l2_h264_reflist_builder *b)
{
const u8 field = b->cur_pic_field;
int l = 0, i = 0, j = 0, k = 0;
for (l = 0; l < 2; l++) {
do {
for (; i < tmp_len[l]; i++) {
if (tmp_list[l][i].fields == field) {
reflist[k++] = tmp_list[l][i];
break;
}
}
for (; i < tmp_len[l]; i++) {
if (tmp_list[l][i].fields != field) {
reflist[k++] = tmp_list[l][i];
break;
}
}
} while (i < tmp_len[l] || j < tmp_len[l]);
}
}
static void v4l2_h264_build_p_ref_frame_list(const struct v4l2_h264_reflist_builder *b,
struct v4l2_h264_reference *reflist)
{
memcpy(reflist, b->unordered_reflist,
sizeof(b->unordered_reflist[0]) * b->num_refs);
sort_r(reflist, b->num_refs, sizeof(*reflist),
v4l2_h264_p_ref_list_cmp, NULL, b);
}
static void v4l2_h264_split_short_and_long_refs(const struct v4l2_h264_reflist_builder *b,
struct v4l2_h264_reference refs[2][V4L2_H264_REF_LIST_LEN],
u8 refs_len[2])
{
int i;
refs_len[0] = refs_len[1] = 0;
for (i = 0; i < b->num_valid; i++) {
u8 idx = b->unordered_reflist[i].index;
u8 list_idx = 0;
if (b->refs[idx].longterm)
list_idx = 1;
refs[list_idx][refs_len[list_idx]] = b->unordered_reflist[i];
refs_len[list_idx]++;
}
}
static void v4l2_h264_build_p_ref_field_list(const struct v4l2_h264_reflist_builder *b,
struct v4l2_h264_reference *reflist)
{
struct v4l2_h264_reference tmp_list[2][V4L2_H264_REF_LIST_LEN];
u8 tmp_len[2];
v4l2_h264_split_short_and_long_refs(b, tmp_list, tmp_len);
/* Sort short term in descending frame_num_wrap */
sort_r(tmp_list[0], tmp_len[0], sizeof(*tmp_list[0]),
v4l2_h264_desc_frame_num_cmp, NULL, b);
/* Short long term in ascending long_term_frame_idx */
sort_r(tmp_list[1], tmp_len[1], sizeof(*tmp_list[1]),
v4l2_h264_asc_frame_num_cmp, NULL, b);
/*
* 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.
* Merge references by alternating their field parity, starting with
* current picture parity. Do this for short term first, followed by
* long term.
*/
if ((poca < builder->cur_pic_order_count) !=
(pocb < builder->cur_pic_order_count))
return pocb < poca ? -1 : 1;
else if (poca < builder->cur_pic_order_count)
return pocb < poca ? -1 : 1;
v4l2_h264_alternate_field_merge(reflist, tmp_list, tmp_len, b);
}
return poca < pocb ? -1 : 1;
static void v4l2_h264_build_b_ref_frame_list(const struct v4l2_h264_reflist_builder *b,
struct v4l2_h264_reference *b0_reflist,
struct v4l2_h264_reference *b1_reflist)
{
memcpy(b0_reflist, b->unordered_reflist,
sizeof(b->unordered_reflist[0]) * b->num_valid);
sort_r(b0_reflist, b->num_valid, sizeof(*b0_reflist),
v4l2_h264_b0_ref_list_cmp, NULL, b);
memcpy(b1_reflist, b->unordered_reflist,
sizeof(b->unordered_reflist[0]) * b->num_valid);
sort_r(b1_reflist, b->num_valid, sizeof(*b1_reflist),
v4l2_h264_b1_ref_list_cmp, NULL, b);
}
static void v4l2_h264_build_b_ref_field_list(const struct v4l2_h264_reflist_builder *b,
struct v4l2_h264_reference *b0_reflist,
struct v4l2_h264_reference *b1_reflist)
{
struct v4l2_h264_reference tmp_list[2][V4L2_H264_REF_LIST_LEN];
u8 tmp_len[2] = { 0, 0 };
v4l2_h264_split_short_and_long_refs(b, tmp_list, tmp_len);
/* Long term reference is the same for b0 and b1 */
sort_r(tmp_list[1], tmp_len[1], sizeof(*tmp_list[1]),
v4l2_h264_asc_frame_num_cmp , NULL, b);
/* Sort for B0 POC order */
sort_r(tmp_list[0], tmp_len[0], sizeof(*tmp_list[0]),
v4l2_h264_b0_st_ref_list_cmp, NULL, b);
v4l2_h264_alternate_field_merge(b0_reflist, tmp_list, tmp_len, b);
/* Sort again but for B1 POC order */
sort_r(tmp_list[0], tmp_len[0], sizeof(*tmp_list[0]),
v4l2_h264_b1_st_ref_list_cmp, NULL, b);
v4l2_h264_alternate_field_merge(b1_reflist, tmp_list, tmp_len, b);
}
/**
......@@ -220,12 +436,12 @@ 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);
sort_r(reflist, builder->num_valid, sizeof(*reflist),
v4l2_h264_p_ref_list_cmp, NULL, builder);
if (builder->cur_pic_field == V4L2_H264_FRAME_REF)
v4l2_h264_build_p_ref_frame_list(builder, reflist);
else
v4l2_h264_build_p_ref_field_list(builder, reflist);
}
EXPORT_SYMBOL_GPL(v4l2_h264_build_p_ref_list);
......@@ -245,17 +461,14 @@ 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);
sort_r(b0_reflist, builder->num_valid, sizeof(*b0_reflist),
v4l2_h264_b0_ref_list_cmp, NULL, builder);
memcpy(b1_reflist, builder->unordered_reflist,
sizeof(builder->unordered_reflist[0]) * builder->num_valid);
sort_r(b1_reflist, builder->num_valid, sizeof(*b1_reflist),
v4l2_h264_b1_ref_list_cmp, NULL, builder);
if (builder->cur_pic_field == V4L2_H264_FRAME_REF)
v4l2_h264_build_b_ref_frame_list(builder, b0_reflist, b1_reflist);
else
v4l2_h264_build_b_ref_field_list(builder, b0_reflist, b1_reflist);
if (builder->num_valid > 1 &&
!memcmp(b1_reflist, b0_reflist, builder->num_valid))
......
......@@ -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;
......@@ -135,6 +135,8 @@ static void set_ref(struct hantro_ctx *ctx)
vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF);
vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF);
/* FIXME Field decoding */
/*
* Set up reference frame picture numbers.
*
......@@ -157,12 +159,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++));
}
......@@ -171,12 +173,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);
/*
......@@ -185,12 +187,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++));
}
......
......@@ -77,9 +77,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[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN];
struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN];
};
/**
......
......@@ -298,7 +298,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;
u32 reg;
int i;
......@@ -307,20 +307,22 @@ static void set_ref(struct hantro_ctx *ctx)
b1_reflist = ctx->h264_dec.reflists.b1;
p_reflist = ctx->h264_dec.reflists.p;
reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9]) |
VDPU_REG_PINIT_RLIST_F8(p_reflist[8]) |
VDPU_REG_PINIT_RLIST_F7(p_reflist[7]) |
VDPU_REG_PINIT_RLIST_F6(p_reflist[6]) |
VDPU_REG_PINIT_RLIST_F5(p_reflist[5]) |
VDPU_REG_PINIT_RLIST_F4(p_reflist[4]);
/* FIXME handle field decoding */
reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9].index) |
VDPU_REG_PINIT_RLIST_F8(p_reflist[8].index) |
VDPU_REG_PINIT_RLIST_F7(p_reflist[7].index) |
VDPU_REG_PINIT_RLIST_F6(p_reflist[6].index) |
VDPU_REG_PINIT_RLIST_F5(p_reflist[5].index) |
VDPU_REG_PINIT_RLIST_F4(p_reflist[4].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(74));
reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15]) |
VDPU_REG_PINIT_RLIST_F14(p_reflist[14]) |
VDPU_REG_PINIT_RLIST_F13(p_reflist[13]) |
VDPU_REG_PINIT_RLIST_F12(p_reflist[12]) |
VDPU_REG_PINIT_RLIST_F11(p_reflist[11]) |
VDPU_REG_PINIT_RLIST_F10(p_reflist[10]);
reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15].index) |
VDPU_REG_PINIT_RLIST_F14(p_reflist[14].index) |
VDPU_REG_PINIT_RLIST_F13(p_reflist[13].index) |
VDPU_REG_PINIT_RLIST_F12(p_reflist[12].index) |
VDPU_REG_PINIT_RLIST_F11(p_reflist[11].index) |
VDPU_REG_PINIT_RLIST_F10(p_reflist[10].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(75));
reg = VDPU_REG_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, 1)) |
......@@ -355,54 +357,54 @@ static void set_ref(struct hantro_ctx *ctx)
VDPU_REG_REFER14_NBR(hantro_h264_get_ref_nbr(ctx, 14));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(83));
reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5]) |
VDPU_REG_BINIT_RLIST_F4(b0_reflist[4]) |
VDPU_REG_BINIT_RLIST_F3(b0_reflist[3]) |
VDPU_REG_BINIT_RLIST_F2(b0_reflist[2]) |
VDPU_REG_BINIT_RLIST_F1(b0_reflist[1]) |
VDPU_REG_BINIT_RLIST_F0(b0_reflist[0]);
reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5].index) |
VDPU_REG_BINIT_RLIST_F4(b0_reflist[4].index) |
VDPU_REG_BINIT_RLIST_F3(b0_reflist[3].index) |
VDPU_REG_BINIT_RLIST_F2(b0_reflist[2].index) |
VDPU_REG_BINIT_RLIST_F1(b0_reflist[1].index) |
VDPU_REG_BINIT_RLIST_F0(b0_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(100));
reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11]) |
VDPU_REG_BINIT_RLIST_F10(b0_reflist[10]) |
VDPU_REG_BINIT_RLIST_F9(b0_reflist[9]) |
VDPU_REG_BINIT_RLIST_F8(b0_reflist[8]) |
VDPU_REG_BINIT_RLIST_F7(b0_reflist[7]) |
VDPU_REG_BINIT_RLIST_F6(b0_reflist[6]);
reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11].index) |
VDPU_REG_BINIT_RLIST_F10(b0_reflist[10].index) |
VDPU_REG_BINIT_RLIST_F9(b0_reflist[9].index) |
VDPU_REG_BINIT_RLIST_F8(b0_reflist[8].index) |
VDPU_REG_BINIT_RLIST_F7(b0_reflist[7].index) |
VDPU_REG_BINIT_RLIST_F6(b0_reflist[6].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(101));
reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15]) |
VDPU_REG_BINIT_RLIST_F14(b0_reflist[14]) |
VDPU_REG_BINIT_RLIST_F13(b0_reflist[13]) |
VDPU_REG_BINIT_RLIST_F12(b0_reflist[12]);
reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15].index) |
VDPU_REG_BINIT_RLIST_F14(b0_reflist[14].index) |
VDPU_REG_BINIT_RLIST_F13(b0_reflist[13].index) |
VDPU_REG_BINIT_RLIST_F12(b0_reflist[12].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(102));
reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5]) |
VDPU_REG_BINIT_RLIST_B4(b1_reflist[4]) |
VDPU_REG_BINIT_RLIST_B3(b1_reflist[3]) |
VDPU_REG_BINIT_RLIST_B2(b1_reflist[2]) |
VDPU_REG_BINIT_RLIST_B1(b1_reflist[1]) |
VDPU_REG_BINIT_RLIST_B0(b1_reflist[0]);
reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5].index) |
VDPU_REG_BINIT_RLIST_B4(b1_reflist[4].index) |
VDPU_REG_BINIT_RLIST_B3(b1_reflist[3].index) |
VDPU_REG_BINIT_RLIST_B2(b1_reflist[2].index) |
VDPU_REG_BINIT_RLIST_B1(b1_reflist[1].index) |
VDPU_REG_BINIT_RLIST_B0(b1_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(103));
reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11]) |
VDPU_REG_BINIT_RLIST_B10(b1_reflist[10]) |
VDPU_REG_BINIT_RLIST_B9(b1_reflist[9]) |
VDPU_REG_BINIT_RLIST_B8(b1_reflist[8]) |
VDPU_REG_BINIT_RLIST_B7(b1_reflist[7]) |
VDPU_REG_BINIT_RLIST_B6(b1_reflist[6]);
reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11].index) |
VDPU_REG_BINIT_RLIST_B10(b1_reflist[10].index) |
VDPU_REG_BINIT_RLIST_B9(b1_reflist[9].index) |
VDPU_REG_BINIT_RLIST_B8(b1_reflist[8].index) |
VDPU_REG_BINIT_RLIST_B7(b1_reflist[7].index) |
VDPU_REG_BINIT_RLIST_B6(b1_reflist[6].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(104));
reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15]) |
VDPU_REG_BINIT_RLIST_B14(b1_reflist[14]) |
VDPU_REG_BINIT_RLIST_B13(b1_reflist[13]) |
VDPU_REG_BINIT_RLIST_B12(b1_reflist[12]);
reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15].index) |
VDPU_REG_BINIT_RLIST_B14(b1_reflist[14].index) |
VDPU_REG_BINIT_RLIST_B13(b1_reflist[13].index) |
VDPU_REG_BINIT_RLIST_B12(b1_reflist[12].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(105));
reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3]) |
VDPU_REG_PINIT_RLIST_F2(p_reflist[2]) |
VDPU_REG_PINIT_RLIST_F1(p_reflist[1]) |
VDPU_REG_PINIT_RLIST_F0(p_reflist[0]);
reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3].index) |
VDPU_REG_PINIT_RLIST_F2(p_reflist[2].index) |
VDPU_REG_PINIT_RLIST_F1(p_reflist[1].index) |
VDPU_REG_PINIT_RLIST_F0(p_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(106));
reg = VDPU_REG_REFER_LTERM_E(ctx->h264_dec.dpb_longterm);
......
......@@ -97,12 +97,12 @@ struct rkvdec_h264_priv_tbl {
u8 err_info[RKV_ERROR_INFO_SIZE];
};
#define RKVDEC_H264_DPB_SIZE 16
#define RKVDEC_H264_REF_LIST_LEN 32
struct rkvdec_h264_reflists {
u8 p[RKVDEC_H264_DPB_SIZE];
u8 b0[RKVDEC_H264_DPB_SIZE];
u8 b1[RKVDEC_H264_DPB_SIZE];
struct v4l2_h264_reference p[RKVDEC_H264_REF_LIST_LEN];
struct v4l2_h264_reference b0[RKVDEC_H264_REF_LIST_LEN];
struct v4l2_h264_reference b1[RKVDEC_H264_REF_LIST_LEN];
u8 num_valid;
};
......@@ -762,28 +762,36 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx,
for (j = 0; j < RKVDEC_NUM_REFLIST; j++) {
for (i = 0; i < h264_ctx->reflists.num_valid; i++) {
u8 dpb_valid = 0;
u8 idx = 0;
struct v4l2_h264_reference *ref = NULL;
u8 dpb_valid;
switch (j) {
case 0:
idx = h264_ctx->reflists.p[i];
ref = &h264_ctx->reflists.p[i];
break;
case 1:
idx = h264_ctx->reflists.b0[i];
ref = &h264_ctx->reflists.p[i];
break;
case 2:
idx = h264_ctx->reflists.b1[i];
ref = &h264_ctx->reflists.b0[i];
break;
}
if (idx >= ARRAY_SIZE(dec_params->dpb))
if (ref->index >= ARRAY_SIZE(dec_params->dpb))
continue;
dpb_valid = !!(dpb[idx].flags &
V4L2_H264_DPB_ENTRY_FLAG_ACTIVE);
/*
* FIXME check if using TS if a refefrence is found and
* adapt dpb_valud accordingly. This is the safe way to
* determin if we have an "non-existing" frame being
* referenced.
*/
dpb_valid = 1;
set_ps_field(hw_rps, DPB_INFO(i, j),
idx | dpb_valid << 4);
ref->index | dpb_valid << 4);
set_ps_field(hw_rps, BOTTOM_FLAG(i, j),
ref->fields == V4L2_H264_BOTTOM_FIELD_REF);
}
}
}
......
......@@ -18,12 +18,16 @@
* @refs.pic_order_count: reference picture order count
* @refs.frame_num: reference frame number
* @refs.pic_num: reference picture number
* @refs.top_field_order_cnt: top field order count
* @refs.bottom_field_order_cnt: bottom field order count
* @refs.longterm: set to true for a long term reference
* @refs: array of references
* @num_refs: number of reference pictures in the @refs array
* @cur_pic_order_count: picture order count of the frame being decoded
* @unordered_reflist: unordered list of references. Will be used to generate
* ordered P/B0/B1 lists
* @num_valid: number of valid references in the refs array
* @num_valid: number of valid reference pictures or fields in the
* @unordered_reflist array
*
* This object stores the context of the P/B0/B1 reference list builder.
* This procedure is described in section '8.2.4 Decoding process for reference
......@@ -31,13 +35,16 @@
*/
struct v4l2_h264_reflist_builder {
struct {
s32 pic_order_count;
int frame_num;
u32 pic_num;
s32 top_field_order_cnt;
s32 bottom_field_order_cnt;
u16 longterm : 1;
} refs[V4L2_H264_NUM_DPB_ENTRIES];
u8 num_refs;
s32 cur_pic_order_count;
u8 unordered_reflist[V4L2_H264_NUM_DPB_ENTRIES];
u8 cur_pic_field;
struct v4l2_h264_reference unordered_reflist[V4L2_H264_REF_LIST_LEN];
u8 num_valid;
};
......@@ -63,7 +70,8 @@ v4l2_h264_init_reflist_builder(struct v4l2_h264_reflist_builder *b,
*/
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);
/**
* v4l2_h264_build_p_ref_list() - Build the P reference list
......@@ -79,6 +87,6 @@ v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder,
*/
void
v4l2_h264_build_p_ref_list(const struct v4l2_h264_reflist_builder *builder,
u8 *reflist);
struct v4l2_h264_reference *reflist);
#endif /* _MEDIA_V4L2_H264_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment