Skip to content

Commit c9a59dc

Browse files
cazouHans Verkuil
authored andcommitted
media: rkvdec: Add HEVC support for the VDPU381 variant
The VDPU381 supports HEVC decoding up to 7680x4320@30fps. It could double that when using both decoder cores. It support YUV420 (8 and 10 bits) as well as AFBC (not implemented here) The fluster score is 146/147 for JCT-VC-HEVC_V1, tested on ROCK 5B. None of the other test suites works. Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock 5B Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
1 parent fde2490 commit c9a59dc

6 files changed

Lines changed: 1120 additions & 0 deletions

File tree

drivers/media/platform/rockchip/rkvdec/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ rockchip-vdec-y += \
99
rkvdec-hevc-common.o \
1010
rkvdec-rcb.o \
1111
rkvdec-vdpu381-h264.o \
12+
rkvdec-vdpu381-hevc.o \
1213
rkvdec-vdpu383-h264.o \
1314
rkvdec-vp9.o

drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c

Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,125 @@
2121
#include "rkvdec.h"
2222
#include "rkvdec-hevc-common.h"
2323

24+
/* Store the Short term ref pic set calculated values */
25+
struct calculated_rps_st_set {
26+
u8 num_delta_pocs;
27+
u8 num_negative_pics;
28+
u8 num_positive_pics;
29+
u8 used_by_curr_pic_s0[16];
30+
u8 used_by_curr_pic_s1[16];
31+
s32 delta_poc_s0[16];
32+
s32 delta_poc_s1[16];
33+
};
34+
35+
void compute_tiles_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
36+
u16 width, u16 height, s32 pic_in_cts_width,
37+
s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
38+
{
39+
const struct v4l2_ctrl_hevc_pps *pps = run->pps;
40+
int i;
41+
42+
for (i = 0; i < pps->num_tile_columns_minus1 + 1; i++)
43+
column_width[i] = ((i + 1) * pic_in_cts_width) /
44+
(pps->num_tile_columns_minus1 + 1) -
45+
(i * pic_in_cts_width) /
46+
(pps->num_tile_columns_minus1 + 1);
47+
48+
for (i = 0; i < pps->num_tile_rows_minus1 + 1; i++)
49+
row_height[i] = ((i + 1) * pic_in_cts_height) /
50+
(pps->num_tile_rows_minus1 + 1) -
51+
(i * pic_in_cts_height) /
52+
(pps->num_tile_rows_minus1 + 1);
53+
}
54+
55+
void compute_tiles_non_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
56+
u16 width, u16 height, s32 pic_in_cts_width,
57+
s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
58+
{
59+
const struct v4l2_ctrl_hevc_pps *pps = run->pps;
60+
s32 sum = 0;
61+
int i;
62+
63+
for (i = 0; i < pps->num_tile_columns_minus1; i++) {
64+
column_width[i] = pps->column_width_minus1[i] + 1;
65+
sum += column_width[i];
66+
}
67+
column_width[i] = pic_in_cts_width - sum;
68+
69+
sum = 0;
70+
for (i = 0; i < pps->num_tile_rows_minus1; i++) {
71+
row_height[i] = pps->row_height_minus1[i] + 1;
72+
sum += row_height[i];
73+
}
74+
row_height[i] = pic_in_cts_height - sum;
75+
}
76+
77+
static void set_ref_poc(struct rkvdec_rps_short_term_ref_set *set, int poc, int value, int flag)
78+
{
79+
switch (poc) {
80+
case 0:
81+
set->delta_poc0 = value;
82+
set->used_flag0 = flag;
83+
break;
84+
case 1:
85+
set->delta_poc1 = value;
86+
set->used_flag1 = flag;
87+
break;
88+
case 2:
89+
set->delta_poc2 = value;
90+
set->used_flag2 = flag;
91+
break;
92+
case 3:
93+
set->delta_poc3 = value;
94+
set->used_flag3 = flag;
95+
break;
96+
case 4:
97+
set->delta_poc4 = value;
98+
set->used_flag4 = flag;
99+
break;
100+
case 5:
101+
set->delta_poc5 = value;
102+
set->used_flag5 = flag;
103+
break;
104+
case 6:
105+
set->delta_poc6 = value;
106+
set->used_flag6 = flag;
107+
break;
108+
case 7:
109+
set->delta_poc7 = value;
110+
set->used_flag7 = flag;
111+
break;
112+
case 8:
113+
set->delta_poc8 = value;
114+
set->used_flag8 = flag;
115+
break;
116+
case 9:
117+
set->delta_poc9 = value;
118+
set->used_flag9 = flag;
119+
break;
120+
case 10:
121+
set->delta_poc10 = value;
122+
set->used_flag10 = flag;
123+
break;
124+
case 11:
125+
set->delta_poc11 = value;
126+
set->used_flag11 = flag;
127+
break;
128+
case 12:
129+
set->delta_poc12 = value;
130+
set->used_flag12 = flag;
131+
break;
132+
case 13:
133+
set->delta_poc13 = value;
134+
set->used_flag13 = flag;
135+
break;
136+
case 14:
137+
set->delta_poc14 = value;
138+
set->used_flag14 = flag;
139+
break;
140+
}
141+
}
142+
24143
/*
25144
* Flip one or more matrices along their main diagonal and flatten them
26145
* before writing it to the memory.
@@ -120,6 +239,211 @@ void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run,
120239
sizeof(struct v4l2_ctrl_hevc_scaling_matrix));
121240
}
122241

242+
static void rkvdec_hevc_assemble_hw_lt_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps)
243+
{
244+
const struct v4l2_ctrl_hevc_sps *sps = run->sps;
245+
246+
if (!run->ext_sps_lt_rps)
247+
return;
248+
249+
for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
250+
rps->refs[i].lt_ref_pic_poc_lsb =
251+
run->ext_sps_lt_rps[i].lt_ref_pic_poc_lsb_sps;
252+
rps->refs[i].used_by_curr_pic_lt_flag =
253+
!!(run->ext_sps_lt_rps[i].flags & V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT);
254+
}
255+
}
256+
257+
static void rkvdec_hevc_assemble_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
258+
struct calculated_rps_st_set *calculated_rps_st_sets)
259+
{
260+
const struct v4l2_ctrl_hevc_sps *sps = run->sps;
261+
262+
for (int i = 0; i < sps->num_short_term_ref_pic_sets; i++) {
263+
int poc = 0;
264+
int j = 0;
265+
const struct calculated_rps_st_set *set = &calculated_rps_st_sets[i];
266+
267+
rps->short_term_ref_sets[i].num_negative = set->num_negative_pics;
268+
rps->short_term_ref_sets[i].num_positive = set->num_positive_pics;
269+
270+
for (; j < set->num_negative_pics; j++) {
271+
set_ref_poc(&rps->short_term_ref_sets[i], j,
272+
set->delta_poc_s0[j], set->used_by_curr_pic_s0[j]);
273+
}
274+
poc = j;
275+
276+
for (j = 0; j < set->num_positive_pics; j++) {
277+
set_ref_poc(&rps->short_term_ref_sets[i], poc + j,
278+
set->delta_poc_s1[j], set->used_by_curr_pic_s1[j]);
279+
}
280+
}
281+
}
282+
283+
/*
284+
* Compute the short term ref pic set parameters based on its reference short term ref pic
285+
*/
286+
static void st_ref_pic_set_prediction(struct rkvdec_hevc_run *run, int idx,
287+
struct calculated_rps_st_set *calculated_rps_st_sets)
288+
{
289+
const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
290+
struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx];
291+
struct calculated_rps_st_set *ref_rps;
292+
u8 st_rps_idx = idx;
293+
u8 ref_rps_idx = 0;
294+
s16 delta_rps = 0;
295+
u8 use_delta_flag[16] = { 0 };
296+
u8 used_by_curr_pic_flag[16] = { 0 };
297+
int i, j;
298+
int dPoc;
299+
300+
ref_rps_idx = st_rps_idx - (rps_data->delta_idx_minus1 + 1); /* 7-59 */
301+
delta_rps = (1 - 2 * rps_data->delta_rps_sign) *
302+
(rps_data->abs_delta_rps_minus1 + 1); /* 7-60 */
303+
304+
ref_rps = &calculated_rps_st_sets[ref_rps_idx];
305+
306+
for (j = 0; j <= ref_rps->num_delta_pocs; j++) {
307+
used_by_curr_pic_flag[j] = !!(rps_data->used_by_curr_pic & (1 << j));
308+
use_delta_flag[j] = !!(rps_data->use_delta_flag & (1 << j));
309+
}
310+
311+
/* 7-61: calculate num_negative_pics, delta_poc_s0 and used_by_curr_pic_s0 */
312+
i = 0;
313+
for (j = (ref_rps->num_positive_pics - 1); j >= 0; j--) {
314+
dPoc = ref_rps->delta_poc_s1[j] + delta_rps;
315+
if (dPoc < 0 && use_delta_flag[ref_rps->num_negative_pics + j]) {
316+
st_rps->delta_poc_s0[i] = dPoc;
317+
st_rps->used_by_curr_pic_s0[i++] =
318+
used_by_curr_pic_flag[ref_rps->num_negative_pics + j];
319+
}
320+
}
321+
if (delta_rps < 0 && use_delta_flag[ref_rps->num_delta_pocs]) {
322+
st_rps->delta_poc_s0[i] = delta_rps;
323+
st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs];
324+
}
325+
for (j = 0; j < ref_rps->num_negative_pics; j++) {
326+
dPoc = ref_rps->delta_poc_s0[j] + delta_rps;
327+
if (dPoc < 0 && use_delta_flag[j]) {
328+
st_rps->delta_poc_s0[i] = dPoc;
329+
st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[j];
330+
}
331+
}
332+
st_rps->num_negative_pics = i;
333+
334+
/* 7-62: calculate num_positive_pics, delta_poc_s1 and used_by_curr_pic_s1 */
335+
i = 0;
336+
for (j = (ref_rps->num_negative_pics - 1); j >= 0; j--) {
337+
dPoc = ref_rps->delta_poc_s0[j] + delta_rps;
338+
if (dPoc > 0 && use_delta_flag[j]) {
339+
st_rps->delta_poc_s1[i] = dPoc;
340+
st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[j];
341+
}
342+
}
343+
if (delta_rps > 0 && use_delta_flag[ref_rps->num_delta_pocs]) {
344+
st_rps->delta_poc_s1[i] = delta_rps;
345+
st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs];
346+
}
347+
for (j = 0; j < ref_rps->num_positive_pics; j++) {
348+
dPoc = ref_rps->delta_poc_s1[j] + delta_rps;
349+
if (dPoc > 0 && use_delta_flag[ref_rps->num_negative_pics + j]) {
350+
st_rps->delta_poc_s1[i] = dPoc;
351+
st_rps->used_by_curr_pic_s1[i++] =
352+
used_by_curr_pic_flag[ref_rps->num_negative_pics + j];
353+
}
354+
}
355+
st_rps->num_positive_pics = i;
356+
357+
st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics;
358+
}
359+
360+
/*
361+
* Compute the short term ref pic set parameters based on the control's data.
362+
*/
363+
static void st_ref_pic_set_calculate(struct rkvdec_hevc_run *run, int idx,
364+
struct calculated_rps_st_set *calculated_rps_st_sets)
365+
{
366+
const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
367+
struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx];
368+
int j, i = 0;
369+
370+
/* 7-63 */
371+
st_rps->num_negative_pics = rps_data->num_negative_pics;
372+
/* 7-64 */
373+
st_rps->num_positive_pics = rps_data->num_positive_pics;
374+
375+
for (i = 0; i < st_rps->num_negative_pics; i++) {
376+
/* 7-65 */
377+
st_rps->used_by_curr_pic_s0[i] = !!(rps_data->used_by_curr_pic & (1 << i));
378+
379+
if (i == 0) {
380+
/* 7-67 */
381+
st_rps->delta_poc_s0[i] = -(rps_data->delta_poc_s0_minus1[i] + 1);
382+
} else {
383+
/* 7-69 */
384+
st_rps->delta_poc_s0[i] =
385+
st_rps->delta_poc_s0[i - 1] -
386+
(rps_data->delta_poc_s0_minus1[i] + 1);
387+
}
388+
}
389+
390+
for (j = 0; j < st_rps->num_positive_pics; j++) {
391+
/* 7-66 */
392+
st_rps->used_by_curr_pic_s1[j] = !!(rps_data->used_by_curr_pic & (1 << (i + j)));
393+
394+
if (j == 0) {
395+
/* 7-68 */
396+
st_rps->delta_poc_s1[j] = rps_data->delta_poc_s1_minus1[j] + 1;
397+
} else {
398+
/* 7-70 */
399+
st_rps->delta_poc_s1[j] =
400+
st_rps->delta_poc_s1[j - 1] +
401+
(rps_data->delta_poc_s1_minus1[j] + 1);
402+
}
403+
}
404+
405+
/* 7-71 */
406+
st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics;
407+
}
408+
409+
static void rkvdec_hevc_prepare_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
410+
struct v4l2_ctrl_hevc_ext_sps_st_rps *cache)
411+
{
412+
int idx;
413+
414+
if (!run->ext_sps_st_rps)
415+
return;
416+
417+
if (!memcmp(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps)))
418+
return;
419+
420+
struct calculated_rps_st_set *calculated_rps_st_sets =
421+
kzalloc(sizeof(struct calculated_rps_st_set) *
422+
run->sps->num_short_term_ref_pic_sets, GFP_KERNEL);
423+
424+
for (idx = 0; idx < run->sps->num_short_term_ref_pic_sets; idx++) {
425+
const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
426+
427+
if (rps_data->flags & V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED)
428+
st_ref_pic_set_prediction(run, idx, calculated_rps_st_sets);
429+
else
430+
st_ref_pic_set_calculate(run, idx, calculated_rps_st_sets);
431+
}
432+
433+
rkvdec_hevc_assemble_hw_st_rps(run, rps, calculated_rps_st_sets);
434+
435+
kfree(calculated_rps_st_sets);
436+
437+
memcpy(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps));
438+
}
439+
440+
void rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
441+
struct v4l2_ctrl_hevc_ext_sps_st_rps *st_cache)
442+
{
443+
rkvdec_hevc_prepare_hw_st_rps(run, rps, st_cache);
444+
rkvdec_hevc_assemble_hw_lt_rps(run, rps);
445+
}
446+
123447
struct vb2_buffer *
124448
get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run,
125449
unsigned int dpb_idx)
@@ -201,5 +525,16 @@ void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx,
201525
V4L2_CID_STATELESS_HEVC_SCALING_MATRIX);
202526
run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL;
203527

528+
if (ctx->has_sps_st_rps) {
529+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
530+
V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS);
531+
run->ext_sps_st_rps = ctrl ? ctrl->p_cur.p : NULL;
532+
}
533+
if (ctx->has_sps_lt_rps) {
534+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
535+
V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS);
536+
run->ext_sps_lt_rps = ctrl ? ctrl->p_cur.p : NULL;
537+
}
538+
204539
rkvdec_run_preamble(ctx, &run->base);
205540
}

0 commit comments

Comments
 (0)