74bd1bc043ce6780ed2a3542b385387555a70c9f
[openwrt/staging/blogic.git] /
1 From c93803888818493c5a0b8eb150256e5f4e6887e8 Mon Sep 17 00:00:00 2001
2 From: John Cox <jc@kynesim.co.uk>
3 Date: Thu, 8 Apr 2021 18:34:09 +0100
4 Subject: [PATCH] media: rpivid: Improve SPS/PPS error
5 handling/validation
6
7 Move size and width checking from bitstream processing to control
8 validation
9
10 Signed-off-by: John Cox <jc@kynesim.co.uk>
11 ---
12 drivers/staging/media/rpivid/rpivid.c | 5 +-
13 drivers/staging/media/rpivid/rpivid.h | 6 +-
14 drivers/staging/media/rpivid/rpivid_h265.c | 132 ++++++++++++++++++---
15 3 files changed, 121 insertions(+), 22 deletions(-)
16
17 --- a/drivers/staging/media/rpivid/rpivid.c
18 +++ b/drivers/staging/media/rpivid/rpivid.c
19 @@ -38,12 +38,14 @@ static const struct rpivid_control rpivi
20 {
21 .cfg = {
22 .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS,
23 + .ops = &rpivid_hevc_sps_ctrl_ops,
24 },
25 .required = true,
26 },
27 {
28 .cfg = {
29 .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS,
30 + .ops = &rpivid_hevc_pps_ctrl_ops,
31 },
32 .required = true,
33 },
34 @@ -119,7 +121,7 @@ static int rpivid_init_ctrls(struct rpiv
35
36 for (i = 0; i < rpivid_ctrls_COUNT; i++) {
37 ctrl = v4l2_ctrl_new_custom(hdl, &rpivid_ctrls[i].cfg,
38 - NULL);
39 + ctx);
40 if (hdl->error) {
41 v4l2_err(&dev->v4l2_dev,
42 "Failed to create new custom control id=%#x\n",
43 @@ -191,6 +193,7 @@ static int rpivid_request_validate(struc
44 if (!ctrl_test) {
45 v4l2_info(&ctx->dev->v4l2_dev,
46 "Missing required codec control\n");
47 + v4l2_ctrl_request_hdl_put(hdl);
48 return -ENOENT;
49 }
50 }
51 --- a/drivers/staging/media/rpivid/rpivid.h
52 +++ b/drivers/staging/media/rpivid/rpivid.h
53 @@ -185,7 +185,7 @@ struct rpivid_dev {
54 struct platform_device *pdev;
55 struct device *dev;
56 struct v4l2_m2m_dev *m2m_dev;
57 - struct rpivid_dec_ops *dec_ops;
58 + const struct rpivid_dec_ops *dec_ops;
59
60 /* Device file mutex */
61 struct mutex dev_mutex;
62 @@ -201,7 +201,9 @@ struct rpivid_dev {
63 struct rpivid_hw_irq_ctrl ic_active2;
64 };
65
66 -extern struct rpivid_dec_ops rpivid_dec_ops_h265;
67 +extern const struct rpivid_dec_ops rpivid_dec_ops_h265;
68 +extern const struct v4l2_ctrl_ops rpivid_hevc_sps_ctrl_ops;
69 +extern const struct v4l2_ctrl_ops rpivid_hevc_pps_ctrl_ops;
70
71 struct v4l2_ctrl *rpivid_find_ctrl(struct rpivid_ctx *ctx, u32 id);
72 void *rpivid_find_control_data(struct rpivid_ctx *ctx, u32 id);
73 --- a/drivers/staging/media/rpivid/rpivid_h265.c
74 +++ b/drivers/staging/media/rpivid/rpivid_h265.c
75 @@ -1432,9 +1432,13 @@ static int updated_ps(struct rpivid_dec_
76 s->ctb_addr_rs_to_ts = kmalloc_array(s->ctb_size,
77 sizeof(*s->ctb_addr_rs_to_ts),
78 GFP_KERNEL);
79 + if (!s->ctb_addr_rs_to_ts)
80 + goto fail;
81 s->ctb_addr_ts_to_rs = kmalloc_array(s->ctb_size,
82 sizeof(*s->ctb_addr_ts_to_rs),
83 GFP_KERNEL);
84 + if (!s->ctb_addr_ts_to_rs)
85 + goto fail;
86
87 if (!(s->pps.flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED)) {
88 s->tile_width = 1;
89 @@ -1446,8 +1450,12 @@ static int updated_ps(struct rpivid_dec_
90
91 s->col_bd = kmalloc((s->tile_width + 1) * sizeof(*s->col_bd),
92 GFP_KERNEL);
93 + if (!s->col_bd)
94 + goto fail;
95 s->row_bd = kmalloc((s->tile_height + 1) * sizeof(*s->row_bd),
96 GFP_KERNEL);
97 + if (!s->row_bd)
98 + goto fail;
99
100 s->col_bd[0] = 0;
101 for (i = 1; i < s->tile_width; i++)
102 @@ -1462,8 +1470,13 @@ static int updated_ps(struct rpivid_dec_
103 s->row_bd[s->tile_height] = s->ctb_height;
104
105 fill_rs_to_ts(s);
106 -
107 return 0;
108 +
109 +fail:
110 + free_ps_info(s);
111 + /* Set invalid to force reload */
112 + s->sps.pic_width_in_luma_samples = 0;
113 + return -ENOMEM;
114 }
115
116 static int write_cmd_buffer(struct rpivid_dev *const dev,
117 @@ -1694,7 +1707,9 @@ static void rpivid_h265_setup(struct rpi
118 memcpy(&s->pps, run->h265.pps, sizeof(s->pps));
119
120 /* Recalc stuff as required */
121 - updated_ps(s);
122 + rv = updated_ps(s);
123 + if (rv)
124 + goto fail;
125 }
126
127 de = dec_env_new(ctx);
128 @@ -1772,22 +1787,6 @@ static void rpivid_h265_setup(struct rpi
129 goto fail;
130 }
131
132 - if (s->sps.pic_width_in_luma_samples > 4096 ||
133 - s->sps.pic_height_in_luma_samples > 4096) {
134 - v4l2_warn(&dev->v4l2_dev,
135 - "Pic dimension (%dx%d) exeeds 4096\n",
136 - s->sps.pic_width_in_luma_samples,
137 - s->sps.pic_height_in_luma_samples);
138 - goto fail;
139 - }
140 - if ((s->tile_width != 1 || s->tile_height != 1) &&
141 - (s->pps.flags &
142 - V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) {
143 - v4l2_warn(&dev->v4l2_dev,
144 - "Tiles + WPP not supported\n");
145 - goto fail;
146 - }
147 -
148 // Fill in ref planes with our address s.t. if we mess
149 // up refs somehow then we still have a valid address
150 // entry
151 @@ -2515,9 +2514,104 @@ static void rpivid_h265_trigger(struct r
152 }
153 }
154
155 -struct rpivid_dec_ops rpivid_dec_ops_h265 = {
156 +const struct rpivid_dec_ops rpivid_dec_ops_h265 = {
157 .setup = rpivid_h265_setup,
158 .start = rpivid_h265_start,
159 .stop = rpivid_h265_stop,
160 .trigger = rpivid_h265_trigger,
161 };
162 +
163 +static int try_ctrl_sps(struct v4l2_ctrl *ctrl)
164 +{
165 + const struct v4l2_ctrl_hevc_sps *const sps = ctrl->p_new.p_hevc_sps;
166 + struct rpivid_ctx *const ctx = ctrl->priv;
167 + struct rpivid_dev *const dev = ctx->dev;
168 +
169 + if (sps->chroma_format_idc != 1) {
170 + v4l2_warn(&dev->v4l2_dev,
171 + "Chroma format (%d) unsupported\n",
172 + sps->chroma_format_idc);
173 + return -EINVAL;
174 + }
175 +
176 + if (sps->bit_depth_luma_minus8 != 0 &&
177 + sps->bit_depth_luma_minus8 != 2) {
178 + v4l2_warn(&dev->v4l2_dev,
179 + "Luma depth (%d) unsupported\n",
180 + sps->bit_depth_luma_minus8 + 8);
181 + return -EINVAL;
182 + }
183 +
184 + if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) {
185 + v4l2_warn(&dev->v4l2_dev,
186 + "Chroma depth (%d) != Luma depth (%d)\n",
187 + sps->bit_depth_chroma_minus8 + 8,
188 + sps->bit_depth_luma_minus8 + 8);
189 + return -EINVAL;
190 + }
191 +
192 + if (!sps->pic_width_in_luma_samples ||
193 + !sps->pic_height_in_luma_samples ||
194 + sps->pic_width_in_luma_samples > 4096 ||
195 + sps->pic_height_in_luma_samples > 4096) {
196 + v4l2_warn(&dev->v4l2_dev,
197 + "Bad sps width (%u) x height (%u)\n",
198 + sps->pic_width_in_luma_samples,
199 + sps->pic_height_in_luma_samples);
200 + return -EINVAL;
201 + }
202 +
203 + if (!ctx->dst_fmt_set)
204 + return 0;
205 +
206 + if ((sps->bit_depth_luma_minus8 == 0 &&
207 + ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_COL128) ||
208 + (sps->bit_depth_luma_minus8 == 2 &&
209 + ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_10_COL128)) {
210 + v4l2_warn(&dev->v4l2_dev,
211 + "SPS luma depth %d does not match capture format\n",
212 + sps->bit_depth_luma_minus8 + 8);
213 + return -EINVAL;
214 + }
215 +
216 + if (sps->pic_width_in_luma_samples > ctx->dst_fmt.width ||
217 + sps->pic_height_in_luma_samples > ctx->dst_fmt.height) {
218 + v4l2_warn(&dev->v4l2_dev,
219 + "SPS size (%dx%d) > capture size (%d,%d)\n",
220 + sps->pic_width_in_luma_samples,
221 + sps->pic_height_in_luma_samples,
222 + ctx->dst_fmt.width,
223 + ctx->dst_fmt.height);
224 + return -EINVAL;
225 + }
226 +
227 + return 0;
228 +}
229 +
230 +const struct v4l2_ctrl_ops rpivid_hevc_sps_ctrl_ops = {
231 + .try_ctrl = try_ctrl_sps,
232 +};
233 +
234 +static int try_ctrl_pps(struct v4l2_ctrl *ctrl)
235 +{
236 + const struct v4l2_ctrl_hevc_pps *const pps = ctrl->p_new.p_hevc_pps;
237 + struct rpivid_ctx *const ctx = ctrl->priv;
238 + struct rpivid_dev *const dev = ctx->dev;
239 +
240 + if ((pps->flags &
241 + V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED) &&
242 + (pps->flags &
243 + V4L2_HEVC_PPS_FLAG_TILES_ENABLED) &&
244 + (pps->num_tile_columns_minus1 || pps->num_tile_rows_minus1)) {
245 + v4l2_warn(&dev->v4l2_dev,
246 + "WPP + Tiles not supported\n");
247 + return -EINVAL;
248 + }
249 +
250 + return 0;
251 +}
252 +
253 +const struct v4l2_ctrl_ops rpivid_hevc_pps_ctrl_ops = {
254 + .try_ctrl = try_ctrl_pps,
255 +};
256 +