Skip to content

Commit 560438e

Browse files
cazouHans Verkuil
authored andcommitted
media: rkvdec: Move h264 functions to common file
This is a preparation commit to add support for new variants of the decoder. The functions will later be shared with vdpu381 (rk3588) and vdpu383 (rk3576). 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 cf29115 commit 560438e

4 files changed

Lines changed: 348 additions & 304 deletions

File tree

drivers/media/platform/rockchip/rkvdec/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ rockchip-vdec-y += \
44
rkvdec.o \
55
rkvdec-cabac.o \
66
rkvdec-h264.o \
7+
rkvdec-h264-common.o \
78
rkvdec-hevc.o \
89
rkvdec-vp9.o
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Rockchip video decoder h264 common functions
4+
*
5+
* Copyright (C) 2025 Collabora, Ltd.
6+
* Detlev Casanova <detlev.casanova@collabora.com>
7+
*
8+
* Copyright (C) 2019 Collabora, Ltd.
9+
* Boris Brezillon <boris.brezillon@collabora.com>
10+
*
11+
* Copyright (C) 2016 Rockchip Electronics Co., Ltd.
12+
* Jeffy Chen <jeffy.chen@rock-chips.com>
13+
*/
14+
15+
#include <linux/v4l2-common.h>
16+
#include <media/v4l2-h264.h>
17+
#include <media/v4l2-mem2mem.h>
18+
19+
#include "rkvdec.h"
20+
#include "rkvdec-h264-common.h"
21+
22+
#define RKVDEC_NUM_REFLIST 3
23+
24+
static void set_dpb_info(struct rkvdec_rps_entry *entries,
25+
u8 reflist,
26+
u8 refnum,
27+
u8 info,
28+
bool bottom)
29+
{
30+
struct rkvdec_rps_entry *entry = &entries[(reflist * 4) + refnum / 8];
31+
u8 idx = refnum % 8;
32+
33+
switch (idx) {
34+
case 0:
35+
entry->dpb_info0 = info;
36+
entry->bottom_flag0 = bottom;
37+
break;
38+
case 1:
39+
entry->dpb_info1 = info;
40+
entry->bottom_flag1 = bottom;
41+
break;
42+
case 2:
43+
entry->dpb_info2 = info;
44+
entry->bottom_flag2 = bottom;
45+
break;
46+
case 3:
47+
entry->dpb_info3 = info;
48+
entry->bottom_flag3 = bottom;
49+
break;
50+
case 4:
51+
entry->dpb_info4 = info;
52+
entry->bottom_flag4 = bottom;
53+
break;
54+
case 5:
55+
entry->dpb_info5 = info;
56+
entry->bottom_flag5 = bottom;
57+
break;
58+
case 6:
59+
entry->dpb_info6 = info;
60+
entry->bottom_flag6 = bottom;
61+
break;
62+
case 7:
63+
entry->dpb_info7 = info;
64+
entry->bottom_flag7 = bottom;
65+
break;
66+
}
67+
}
68+
69+
void lookup_ref_buf_idx(struct rkvdec_ctx *ctx,
70+
struct rkvdec_h264_run *run)
71+
{
72+
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
73+
u32 i;
74+
75+
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
76+
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
77+
const struct v4l2_h264_dpb_entry *dpb = run->decode_params->dpb;
78+
struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
79+
struct vb2_buffer *buf = NULL;
80+
81+
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) {
82+
buf = vb2_find_buffer(cap_q, dpb[i].reference_ts);
83+
if (!buf)
84+
pr_debug("No buffer for reference_ts %llu",
85+
dpb[i].reference_ts);
86+
}
87+
88+
run->ref_buf[i] = buf;
89+
}
90+
}
91+
92+
void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder,
93+
struct rkvdec_h264_run *run,
94+
struct rkvdec_h264_reflists *reflists,
95+
struct rkvdec_rps *hw_rps)
96+
{
97+
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
98+
const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb;
99+
100+
u32 i, j;
101+
102+
memset(hw_rps, 0, sizeof(*hw_rps));
103+
104+
/*
105+
* Assign an invalid pic_num if DPB entry at that position is inactive.
106+
* If we assign 0 in that position hardware will treat that as a real
107+
* reference picture with pic_num 0, triggering output picture
108+
* corruption.
109+
*/
110+
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
111+
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
112+
continue;
113+
114+
hw_rps->frame_num[i] = builder->refs[i].frame_num;
115+
}
116+
117+
for (j = 0; j < RKVDEC_NUM_REFLIST; j++) {
118+
for (i = 0; i < builder->num_valid; i++) {
119+
struct v4l2_h264_reference *ref;
120+
bool dpb_valid;
121+
bool bottom;
122+
123+
switch (j) {
124+
case 0:
125+
ref = &reflists->p[i];
126+
break;
127+
case 1:
128+
ref = &reflists->b0[i];
129+
break;
130+
case 2:
131+
ref = &reflists->b1[i];
132+
break;
133+
}
134+
135+
if (WARN_ON(ref->index >= ARRAY_SIZE(dec_params->dpb)))
136+
continue;
137+
138+
dpb_valid = !!(run->ref_buf[ref->index]);
139+
bottom = ref->fields == V4L2_H264_BOTTOM_FIELD_REF;
140+
141+
set_dpb_info(hw_rps->entries, j, i, ref->index | (dpb_valid << 4), bottom);
142+
}
143+
}
144+
}
145+
146+
void assemble_hw_scaling_list(struct rkvdec_h264_run *run,
147+
struct rkvdec_h264_scaling_list *scaling_list)
148+
{
149+
const struct v4l2_ctrl_h264_scaling_matrix *scaling = run->scaling_matrix;
150+
const struct v4l2_ctrl_h264_pps *pps = run->pps;
151+
152+
if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
153+
return;
154+
155+
BUILD_BUG_ON(sizeof(scaling_list->scaling_list_4x4) !=
156+
sizeof(scaling->scaling_list_4x4));
157+
BUILD_BUG_ON(sizeof(scaling_list->scaling_list_8x8) !=
158+
sizeof(scaling->scaling_list_8x8));
159+
160+
memcpy(scaling_list->scaling_list_4x4,
161+
scaling->scaling_list_4x4,
162+
sizeof(scaling->scaling_list_4x4));
163+
164+
memcpy(scaling_list->scaling_list_8x8,
165+
scaling->scaling_list_8x8,
166+
sizeof(scaling->scaling_list_8x8));
167+
}
168+
169+
#define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2
170+
171+
int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
172+
struct v4l2_format *f)
173+
{
174+
struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
175+
176+
fmt->num_planes = 1;
177+
if (!fmt->plane_fmt[0].sizeimage)
178+
fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
179+
RKVDEC_H264_MAX_DEPTH_IN_BYTES;
180+
return 0;
181+
}
182+
183+
enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx,
184+
struct v4l2_ctrl *ctrl)
185+
{
186+
const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
187+
188+
if (ctrl->id != V4L2_CID_STATELESS_H264_SPS)
189+
return RKVDEC_IMG_FMT_ANY;
190+
191+
if (sps->bit_depth_luma_minus8 == 0) {
192+
if (sps->chroma_format_idc == 2)
193+
return RKVDEC_IMG_FMT_422_8BIT;
194+
else
195+
return RKVDEC_IMG_FMT_420_8BIT;
196+
} else if (sps->bit_depth_luma_minus8 == 2) {
197+
if (sps->chroma_format_idc == 2)
198+
return RKVDEC_IMG_FMT_422_10BIT;
199+
else
200+
return RKVDEC_IMG_FMT_420_10BIT;
201+
}
202+
203+
return RKVDEC_IMG_FMT_ANY;
204+
}
205+
206+
int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
207+
const struct v4l2_ctrl_h264_sps *sps)
208+
{
209+
unsigned int width, height;
210+
211+
if (sps->chroma_format_idc > 2)
212+
/* Only 4:0:0, 4:2:0 and 4:2:2 are supported */
213+
return -EINVAL;
214+
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
215+
/* Luma and chroma bit depth mismatch */
216+
return -EINVAL;
217+
if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2)
218+
/* Only 8-bit and 10-bit is supported */
219+
return -EINVAL;
220+
221+
width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
222+
height = (sps->pic_height_in_map_units_minus1 + 1) * 16;
223+
224+
/*
225+
* When frame_mbs_only_flag is not set, this is field height,
226+
* which is half the final height (see (7-18) in the
227+
* specification)
228+
*/
229+
if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
230+
height *= 2;
231+
232+
if (width > ctx->coded_fmt.fmt.pix_mp.width ||
233+
height > ctx->coded_fmt.fmt.pix_mp.height)
234+
return -EINVAL;
235+
236+
return 0;
237+
}
238+
239+
void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx,
240+
struct rkvdec_h264_run *run)
241+
{
242+
struct v4l2_ctrl *ctrl;
243+
244+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
245+
V4L2_CID_STATELESS_H264_DECODE_PARAMS);
246+
run->decode_params = ctrl ? ctrl->p_cur.p : NULL;
247+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
248+
V4L2_CID_STATELESS_H264_SPS);
249+
run->sps = ctrl ? ctrl->p_cur.p : NULL;
250+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
251+
V4L2_CID_STATELESS_H264_PPS);
252+
run->pps = ctrl ? ctrl->p_cur.p : NULL;
253+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
254+
V4L2_CID_STATELESS_H264_SCALING_MATRIX);
255+
run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL;
256+
257+
rkvdec_run_preamble(ctx, &run->base);
258+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Rockchip video decoder h264 common functions
4+
*
5+
* Copyright (C) 2025 Collabora, Ltd.
6+
* Detlev Casanova <detlev.casanova@collabora.com>
7+
*
8+
* Copyright (C) 2019 Collabora, Ltd.
9+
* Boris Brezillon <boris.brezillon@collabora.com>
10+
*
11+
* Copyright (C) 2016 Rockchip Electronics Co., Ltd.
12+
* Jeffy Chen <jeffy.chen@rock-chips.com>
13+
*/
14+
15+
#include <media/v4l2-h264.h>
16+
#include <media/v4l2-mem2mem.h>
17+
18+
#include "rkvdec.h"
19+
20+
struct rkvdec_h264_scaling_list {
21+
u8 scaling_list_4x4[6][16];
22+
u8 scaling_list_8x8[6][64];
23+
u8 padding[128];
24+
};
25+
26+
struct rkvdec_h264_reflists {
27+
struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN];
28+
struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN];
29+
struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN];
30+
};
31+
32+
struct rkvdec_h264_run {
33+
struct rkvdec_run base;
34+
const struct v4l2_ctrl_h264_decode_params *decode_params;
35+
const struct v4l2_ctrl_h264_sps *sps;
36+
const struct v4l2_ctrl_h264_pps *pps;
37+
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
38+
struct vb2_buffer *ref_buf[V4L2_H264_NUM_DPB_ENTRIES];
39+
};
40+
41+
struct rkvdec_rps_entry {
42+
u32 dpb_info0: 5;
43+
u32 bottom_flag0: 1;
44+
u32 view_index_off0: 1;
45+
u32 dpb_info1: 5;
46+
u32 bottom_flag1: 1;
47+
u32 view_index_off1: 1;
48+
u32 dpb_info2: 5;
49+
u32 bottom_flag2: 1;
50+
u32 view_index_off2: 1;
51+
u32 dpb_info3: 5;
52+
u32 bottom_flag3: 1;
53+
u32 view_index_off3: 1;
54+
u32 dpb_info4: 5;
55+
u32 bottom_flag4: 1;
56+
u32 view_index_off4: 1;
57+
u32 dpb_info5: 5;
58+
u32 bottom_flag5: 1;
59+
u32 view_index_off5: 1;
60+
u32 dpb_info6: 5;
61+
u32 bottom_flag6: 1;
62+
u32 view_index_off6: 1;
63+
u32 dpb_info7: 5;
64+
u32 bottom_flag7: 1;
65+
u32 view_index_off7: 1;
66+
} __packed;
67+
68+
struct rkvdec_rps {
69+
u16 frame_num[16];
70+
u32 reserved0;
71+
struct rkvdec_rps_entry entries[12];
72+
u32 reserved1[66];
73+
} __packed;
74+
75+
void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *run);
76+
void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder,
77+
struct rkvdec_h264_run *run,
78+
struct rkvdec_h264_reflists *reflists,
79+
struct rkvdec_rps *hw_rps);
80+
void assemble_hw_scaling_list(struct rkvdec_h264_run *run,
81+
struct rkvdec_h264_scaling_list *scaling_list);
82+
int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f);
83+
enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl);
84+
int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx, const struct v4l2_ctrl_h264_sps *sps);
85+
void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *run);

0 commit comments

Comments
 (0)