Skip to content

Commit 11442b7

Browse files
ndufresnemchehab
authored andcommitted
media: hantro: Add H.264 field decoding support
This adds the required code to support field decoding. While most of the code is derived from Rockchip and VSI reference code, the reduction of the reference list to 16 entries was found by trial and errors. The list consists of all the references with the opposite field parity. The strategy is to deduplicate the reference picture that points to the same storage (same index). The choice of opposite parity has been made to keep the other field of the current field pair in the list. This method may not be robust if a field was lost. [hverkuil: fix typos in the comment before deduplicate_reflist()] [hverkuil: document new cur_poc field] Signed-off-by: Jonas Karlman <[email protected]> Signed-off-by: Nicolas Dufresne <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 3630e49 commit 11442b7

File tree

2 files changed

+110
-14
lines changed

2 files changed

+110
-14
lines changed

drivers/staging/media/hantro/hantro_h264.c

Lines changed: 108 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
#define POC_BUFFER_SIZE 34
2323
#define SCALING_LIST_SIZE (6 * 16 + 2 * 64)
2424

25+
/*
26+
* For valid and long term reference marking, index are reversed, so bit 31
27+
* indicates the status of the picture 0.
28+
*/
29+
#define REF_BIT(i) BIT(32 - 1 - (i))
30+
2531
/* Data structure describing auxiliary buffer format. */
2632
struct hantro_h264_dec_priv_tbl {
2733
u32 cabac_table[CABAC_INIT_BUFFER_SIZE];
@@ -227,6 +233,7 @@ static void prepare_table(struct hantro_ctx *ctx)
227233
{
228234
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
229235
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
236+
const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
230237
struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu;
231238
const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
232239
u32 dpb_longterm = 0;
@@ -237,20 +244,45 @@ static void prepare_table(struct hantro_ctx *ctx)
237244
tbl->poc[i * 2] = dpb[i].top_field_order_cnt;
238245
tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt;
239246

247+
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
248+
continue;
249+
240250
/*
241251
* Set up bit maps of valid and long term DPBs.
242-
* NOTE: The bits are reversed, i.e. MSb is DPB 0.
252+
* NOTE: The bits are reversed, i.e. MSb is DPB 0. For frame
253+
* decoding, bit 31 to 15 are used, while for field decoding,
254+
* all bits are used, with bit 31 being a top field, 30 a bottom
255+
* field and so on.
243256
*/
244-
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
245-
dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
246-
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
247-
dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
257+
if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) {
258+
if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF)
259+
dpb_valid |= REF_BIT(i * 2);
260+
261+
if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
262+
dpb_valid |= REF_BIT(i * 2 + 1);
263+
264+
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) {
265+
dpb_longterm |= REF_BIT(i * 2);
266+
dpb_longterm |= REF_BIT(i * 2 + 1);
267+
}
268+
} else {
269+
dpb_valid |= REF_BIT(i);
270+
271+
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
272+
dpb_longterm |= REF_BIT(i);
273+
}
274+
}
275+
ctx->h264_dec.dpb_valid = dpb_valid;
276+
ctx->h264_dec.dpb_longterm = dpb_longterm;
277+
278+
if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) ||
279+
!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) {
280+
tbl->poc[32] = ctx->h264_dec.cur_poc;
281+
tbl->poc[33] = 0;
282+
} else {
283+
tbl->poc[32] = dec_param->top_field_order_cnt;
284+
tbl->poc[33] = dec_param->bottom_field_order_cnt;
248285
}
249-
ctx->h264_dec.dpb_valid = dpb_valid << 16;
250-
ctx->h264_dec.dpb_longterm = dpb_longterm << 16;
251-
252-
tbl->poc[32] = dec_param->top_field_order_cnt;
253-
tbl->poc[33] = dec_param->bottom_field_order_cnt;
254286

255287
assemble_scaling_list(ctx);
256288
}
@@ -326,6 +358,8 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
326358
{
327359
struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
328360
dma_addr_t dma_addr = 0;
361+
s32 cur_poc = ctx->h264_dec.cur_poc;
362+
u32 flags;
329363

330364
if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
331365
dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts);
@@ -343,7 +377,12 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
343377
dma_addr = hantro_get_dec_buf_addr(ctx, buf);
344378
}
345379

346-
return dma_addr;
380+
flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD ? 0x2 : 0;
381+
flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) <
382+
abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ?
383+
0x1 : 0;
384+
385+
return dma_addr | flags;
347386
}
348387

349388
u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx)
@@ -355,6 +394,47 @@ u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx)
355394
return dpb->frame_num;
356395
}
357396

397+
/*
398+
* Removes all references with the same parity as the current picture from the
399+
* reference list. The remaining list will have references with the opposite
400+
* parity. This is effectively a deduplication of references since each buffer
401+
* stores two fields. For this reason, each buffer is found twice in the
402+
* reference list.
403+
*
404+
* This technique has been chosen through trial and error. This simple approach
405+
* resulted in the highest conformance score. Note that this method may suffer
406+
* worse quality in the case an opposite reference frame has been lost. If this
407+
* becomes a problem in the future, it should be possible to add a preprocessing
408+
* to identify un-paired fields and avoid removing them.
409+
*/
410+
static void deduplicate_reflist(struct v4l2_h264_reflist_builder *b,
411+
struct v4l2_h264_reference *reflist)
412+
{
413+
int write_idx = 0;
414+
int i;
415+
416+
if (b->cur_pic_fields == V4L2_H264_FRAME_REF) {
417+
write_idx = b->num_valid;
418+
goto done;
419+
}
420+
421+
for (i = 0; i < b->num_valid; i++) {
422+
if (!(b->cur_pic_fields == reflist[i].fields)) {
423+
reflist[write_idx++] = reflist[i];
424+
continue;
425+
}
426+
}
427+
428+
done:
429+
/* Should not happen unless we have a bug in the reflist builder. */
430+
if (WARN_ON(write_idx > 16))
431+
write_idx = 16;
432+
433+
/* Clear the remaining, some streams fails otherwise */
434+
for (; write_idx < 16; write_idx++)
435+
reflist[write_idx].index = 15;
436+
}
437+
358438
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
359439
{
360440
struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec;
@@ -386,15 +466,29 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
386466
/* Update the DPB with new refs. */
387467
update_dpb(ctx);
388468

389-
/* Prepare data in memory. */
390-
prepare_table(ctx);
391-
392469
/* Build the P/B{0,1} ref lists. */
393470
v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode,
394471
ctrls->sps, ctx->h264_dec.dpb);
472+
h264_ctx->cur_poc = reflist_builder.cur_pic_order_count;
473+
474+
/* Prepare data in memory. */
475+
prepare_table(ctx);
476+
395477
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
396478
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
397479
h264_ctx->reflists.b1);
480+
481+
/*
482+
* Reduce ref lists to at most 16 entries, Hantro hardware will deduce
483+
* the actual picture lists in field through the dpb_valid,
484+
* dpb_longterm bitmap along with the current frame parity.
485+
*/
486+
if (reflist_builder.cur_pic_fields != V4L2_H264_FRAME_REF) {
487+
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.p);
488+
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b0);
489+
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b1);
490+
}
491+
398492
return 0;
399493
}
400494

drivers/staging/media/hantro/hantro_hw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct hantro_h264_dec_reflists {
8383
* @ctrls: V4L2 controls attached to a run
8484
* @dpb_longterm: DPB long-term
8585
* @dpb_valid: DPB valid
86+
* @cur_poc: Current picture order count
8687
*/
8788
struct hantro_h264_dec_hw_ctx {
8889
struct hantro_aux_buf priv;
@@ -91,6 +92,7 @@ struct hantro_h264_dec_hw_ctx {
9192
struct hantro_h264_dec_ctrls ctrls;
9293
u32 dpb_longterm;
9394
u32 dpb_valid;
95+
s32 cur_poc;
9496
};
9597

9698
/**

0 commit comments

Comments
 (0)