1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Rockchip video decoder hevc common functions
4 *
5 * Copyright (C) 2025 Collabora, Ltd.
6 * Detlev Casanova <detlev.casanova@collabora.com>
7 *
8 * Copyright (C) 2023 Collabora, Ltd.
9 * Sebastian Fricke <sebastian.fricke@collabora.com>
10 *
11 * Copyright (C) 2019 Collabora, Ltd.
12 * Boris Brezillon <boris.brezillon@collabora.com>
13 *
14 * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
15 * Jeffy Chen <jeffy.chen@rock-chips.com>
16 */
17
18 #include <linux/v4l2-common.h>
19 #include <media/v4l2-hevc.h>
20 #include <media/v4l2-mem2mem.h>
21
22 #include "rkvdec.h"
23 #include "rkvdec-hevc-common.h"
24
25 /* Store the Short term ref pic set calculated values */
26 struct calculated_rps_st_set {
27 u8 num_delta_pocs;
28 u8 num_negative_pics;
29 u8 num_positive_pics;
30 u8 used_by_curr_pic_s0[16];
31 u8 used_by_curr_pic_s1[16];
32 s32 delta_poc_s0[16];
33 s32 delta_poc_s1[16];
34 };
35
compute_tiles_uniform(struct rkvdec_hevc_run * run,u16 log2_min_cb_size,u16 width,u16 height,s32 pic_in_cts_width,s32 pic_in_cts_height,u16 * column_width,u16 * row_height)36 void compute_tiles_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
37 u16 width, u16 height, s32 pic_in_cts_width,
38 s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
39 {
40 const struct v4l2_ctrl_hevc_pps *pps = run->pps;
41 unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
42 unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
43 int i;
44
45 for (i = 0; i < num_cols; i++)
46 column_width[i] = ((i + 1) * pic_in_cts_width) /
47 (pps->num_tile_columns_minus1 + 1) -
48 (i * pic_in_cts_width) /
49 (pps->num_tile_columns_minus1 + 1);
50
51 for (i = 0; i < num_rows; i++)
52 row_height[i] = ((i + 1) * pic_in_cts_height) /
53 (pps->num_tile_rows_minus1 + 1) -
54 (i * pic_in_cts_height) /
55 (pps->num_tile_rows_minus1 + 1);
56 }
57
compute_tiles_non_uniform(struct rkvdec_hevc_run * run,u16 log2_min_cb_size,u16 width,u16 height,s32 pic_in_cts_width,s32 pic_in_cts_height,u16 * column_width,u16 * row_height)58 void compute_tiles_non_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
59 u16 width, u16 height, s32 pic_in_cts_width,
60 s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
61 {
62 const struct v4l2_ctrl_hevc_pps *pps = run->pps;
63 unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
64 unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
65 s32 sum = 0;
66 int i;
67
68 /* The last tile entry is written after the loop, so iterate one less. */
69 for (i = 0; i < num_cols - 1; i++) {
70 column_width[i] = pps->column_width_minus1[i] + 1;
71 sum += column_width[i];
72 }
73 column_width[i] = pic_in_cts_width - sum;
74
75 sum = 0;
76 for (i = 0; i < num_rows - 1; i++) {
77 row_height[i] = pps->row_height_minus1[i] + 1;
78 sum += row_height[i];
79 }
80 row_height[i] = pic_in_cts_height - sum;
81 }
82
assemble_scalingfactor0(struct rkvdec_ctx * ctx,u8 * output,const struct v4l2_ctrl_hevc_scaling_matrix * input)83 static void assemble_scalingfactor0(struct rkvdec_ctx *ctx, u8 *output,
84 const struct v4l2_ctrl_hevc_scaling_matrix *input)
85 {
86 const struct rkvdec_variant *variant = ctx->dev->variant;
87 int offset = 0;
88
89 variant->ops->flatten_matrices(output, (const u8 *)input->scaling_list_4x4, 6, 4);
90 offset = 6 * 16 * sizeof(u8);
91 variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_8x8, 6, 8);
92 offset += 6 * 64 * sizeof(u8);
93 variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_16x16,
94 6, 8);
95 offset += 6 * 64 * sizeof(u8);
96 /* Add a 128 byte padding with 0s between the two 32x32 matrices */
97 variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_32x32,
98 1, 8);
99 offset += 64 * sizeof(u8);
100 memset(output + offset, 0, 128);
101 offset += 128 * sizeof(u8);
102 variant->ops->flatten_matrices(output + offset,
103 (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)),
104 1, 8);
105 offset += 64 * sizeof(u8);
106 memset(output + offset, 0, 128);
107 }
108
109 /*
110 * Required layout:
111 * A = scaling_list_dc_coef_16x16
112 * B = scaling_list_dc_coef_32x32
113 * 0 = Padding
114 *
115 * A, A, A, A, A, A, B, 0, 0, B, 0, 0
116 */
assemble_scalingdc(u8 * output,const struct v4l2_ctrl_hevc_scaling_matrix * input)117 static void assemble_scalingdc(u8 *output, const struct v4l2_ctrl_hevc_scaling_matrix *input)
118 {
119 u8 list_32x32[6] = {0};
120
121 memcpy(output, input->scaling_list_dc_coef_16x16, 6 * sizeof(u8));
122 list_32x32[0] = input->scaling_list_dc_coef_32x32[0];
123 list_32x32[3] = input->scaling_list_dc_coef_32x32[1];
124 memcpy(output + 6 * sizeof(u8), list_32x32, 6 * sizeof(u8));
125 }
126
translate_scaling_list(struct rkvdec_ctx * ctx,struct scaling_factor * output,const struct v4l2_ctrl_hevc_scaling_matrix * input)127 static void translate_scaling_list(struct rkvdec_ctx *ctx, struct scaling_factor *output,
128 const struct v4l2_ctrl_hevc_scaling_matrix *input)
129 {
130 assemble_scalingfactor0(ctx, output->scalingfactor0, input);
131 memcpy(output->scalingfactor1, (const u8 *)input->scaling_list_4x4, 96);
132 assemble_scalingdc(output->scalingdc, input);
133 memset(output->reserved, 0, 4 * sizeof(u8));
134 }
135
rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_ctx * ctx,struct rkvdec_hevc_run * run,struct scaling_factor * scaling_factor,struct v4l2_ctrl_hevc_scaling_matrix * cache)136 void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_ctx *ctx,
137 struct rkvdec_hevc_run *run,
138 struct scaling_factor *scaling_factor,
139 struct v4l2_ctrl_hevc_scaling_matrix *cache)
140 {
141 const struct v4l2_ctrl_hevc_scaling_matrix *scaling = run->scaling_matrix;
142
143 if (!memcmp(cache, scaling,
144 sizeof(struct v4l2_ctrl_hevc_scaling_matrix)))
145 return;
146
147 translate_scaling_list(ctx, scaling_factor, scaling);
148
149 memcpy(cache, scaling,
150 sizeof(struct v4l2_ctrl_hevc_scaling_matrix));
151 }
152
rkvdec_hevc_assemble_hw_lt_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps)153 static void rkvdec_hevc_assemble_hw_lt_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps)
154 {
155 const struct v4l2_ctrl_hevc_sps *sps = run->sps;
156
157 if (!run->ext_sps_lt_rps)
158 return;
159
160 for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
161 rkvdec_set_bw_field(rps->info, RPS_LT_REF_PIC_POC_LSB(i),
162 run->ext_sps_lt_rps[i].lt_ref_pic_poc_lsb_sps);
163 rkvdec_set_bw_field(rps->info, RPS_LT_REF_USED_BY_CURR_PIC(i),
164 !!(run->ext_sps_lt_rps[i].flags &
165 V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT));
166 }
167 }
168
rkvdec_hevc_assemble_hw_st_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps,struct calculated_rps_st_set * calculated_rps_st_sets)169 static void rkvdec_hevc_assemble_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
170 struct calculated_rps_st_set *calculated_rps_st_sets)
171 {
172 const struct v4l2_ctrl_hevc_sps *sps = run->sps;
173
174 for (int i = 0; i < sps->num_short_term_ref_pic_sets; i++) {
175 int poc = 0;
176 int j = 0;
177 const struct calculated_rps_st_set *set = &calculated_rps_st_sets[i];
178
179 rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_NUM_NEGATIVE(i),
180 set->num_negative_pics);
181 rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_NUM_POSITIVE(i),
182 set->num_positive_pics);
183
184 for (; j < set->num_negative_pics; j++) {
185 rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_DELTA_POC(i, j),
186 set->delta_poc_s0[j]);
187 rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_USED(i, j),
188 set->used_by_curr_pic_s0[j]);
189 }
190 poc = j;
191
192 for (j = 0; j < set->num_positive_pics; j++) {
193 rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_DELTA_POC(i, poc + j),
194 set->delta_poc_s1[j]);
195 rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_USED(i, poc + j),
196 set->used_by_curr_pic_s1[j]);
197 }
198 }
199 }
200
201 /*
202 * Compute the short term ref pic set parameters based on its reference short term ref pic
203 */
st_ref_pic_set_prediction(struct rkvdec_hevc_run * run,int idx,struct calculated_rps_st_set * calculated_rps_st_sets)204 static void st_ref_pic_set_prediction(struct rkvdec_hevc_run *run, int idx,
205 struct calculated_rps_st_set *calculated_rps_st_sets)
206 {
207 const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
208 struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx];
209 struct calculated_rps_st_set *ref_rps;
210 u8 st_rps_idx = idx;
211 u8 ref_rps_idx = 0;
212 s16 delta_rps = 0;
213 u8 use_delta_flag[16] = { 0 };
214 u8 used_by_curr_pic_flag[16] = { 0 };
215 int i, j;
216 int dPoc;
217
218 if ((unsigned int)rps_data->delta_idx_minus1 + 1 > idx)
219 return;
220
221 ref_rps_idx = st_rps_idx - (rps_data->delta_idx_minus1 + 1); /* 7-59 */
222 delta_rps = (1 - 2 * rps_data->delta_rps_sign) *
223 (rps_data->abs_delta_rps_minus1 + 1); /* 7-60 */
224
225 ref_rps = &calculated_rps_st_sets[ref_rps_idx];
226
227 for (j = 0; j <= ref_rps->num_delta_pocs; j++) {
228 used_by_curr_pic_flag[j] = !!(rps_data->used_by_curr_pic & (1 << j));
229 use_delta_flag[j] = !!(rps_data->use_delta_flag & (1 << j));
230 }
231
232 /* 7-61: calculate num_negative_pics, delta_poc_s0 and used_by_curr_pic_s0 */
233 i = 0;
234 for (j = (ref_rps->num_positive_pics - 1); j >= 0; j--) {
235 dPoc = ref_rps->delta_poc_s1[j] + delta_rps;
236 if (dPoc < 0 && use_delta_flag[ref_rps->num_negative_pics + j]) {
237 st_rps->delta_poc_s0[i] = dPoc;
238 st_rps->used_by_curr_pic_s0[i++] =
239 used_by_curr_pic_flag[ref_rps->num_negative_pics + j];
240 }
241 }
242 if (delta_rps < 0 && use_delta_flag[ref_rps->num_delta_pocs]) {
243 st_rps->delta_poc_s0[i] = delta_rps;
244 st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs];
245 }
246 for (j = 0; j < ref_rps->num_negative_pics; j++) {
247 dPoc = ref_rps->delta_poc_s0[j] + delta_rps;
248 if (dPoc < 0 && use_delta_flag[j]) {
249 st_rps->delta_poc_s0[i] = dPoc;
250 st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[j];
251 }
252 }
253 st_rps->num_negative_pics = i;
254
255 /* 7-62: calculate num_positive_pics, delta_poc_s1 and used_by_curr_pic_s1 */
256 i = 0;
257 for (j = (ref_rps->num_negative_pics - 1); j >= 0; j--) {
258 dPoc = ref_rps->delta_poc_s0[j] + delta_rps;
259 if (dPoc > 0 && use_delta_flag[j]) {
260 st_rps->delta_poc_s1[i] = dPoc;
261 st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[j];
262 }
263 }
264 if (delta_rps > 0 && use_delta_flag[ref_rps->num_delta_pocs]) {
265 st_rps->delta_poc_s1[i] = delta_rps;
266 st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs];
267 }
268 for (j = 0; j < ref_rps->num_positive_pics; j++) {
269 dPoc = ref_rps->delta_poc_s1[j] + delta_rps;
270 if (dPoc > 0 && use_delta_flag[ref_rps->num_negative_pics + j]) {
271 st_rps->delta_poc_s1[i] = dPoc;
272 st_rps->used_by_curr_pic_s1[i++] =
273 used_by_curr_pic_flag[ref_rps->num_negative_pics + j];
274 }
275 }
276 st_rps->num_positive_pics = i;
277
278 st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics;
279 }
280
281 /*
282 * Compute the short term ref pic set parameters based on the control's data.
283 */
st_ref_pic_set_calculate(struct rkvdec_hevc_run * run,int idx,struct calculated_rps_st_set * calculated_rps_st_sets)284 static void st_ref_pic_set_calculate(struct rkvdec_hevc_run *run, int idx,
285 struct calculated_rps_st_set *calculated_rps_st_sets)
286 {
287 const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
288 struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx];
289 int j, i = 0;
290
291 /* 7-63 */
292 st_rps->num_negative_pics = rps_data->num_negative_pics;
293 /* 7-64 */
294 st_rps->num_positive_pics = rps_data->num_positive_pics;
295
296 for (i = 0; i < st_rps->num_negative_pics; i++) {
297 /* 7-65 */
298 st_rps->used_by_curr_pic_s0[i] = !!(rps_data->used_by_curr_pic & (1 << i));
299
300 if (i == 0) {
301 /* 7-67 */
302 st_rps->delta_poc_s0[i] = -(rps_data->delta_poc_s0_minus1[i] + 1);
303 } else {
304 /* 7-69 */
305 st_rps->delta_poc_s0[i] =
306 st_rps->delta_poc_s0[i - 1] -
307 (rps_data->delta_poc_s0_minus1[i] + 1);
308 }
309 }
310
311 for (j = 0; j < st_rps->num_positive_pics; j++) {
312 /* 7-66 */
313 st_rps->used_by_curr_pic_s1[j] = !!(rps_data->used_by_curr_pic & (1 << (i + j)));
314
315 if (j == 0) {
316 /* 7-68 */
317 st_rps->delta_poc_s1[j] = rps_data->delta_poc_s1_minus1[j] + 1;
318 } else {
319 /* 7-70 */
320 st_rps->delta_poc_s1[j] =
321 st_rps->delta_poc_s1[j - 1] +
322 (rps_data->delta_poc_s1_minus1[j] + 1);
323 }
324 }
325
326 /* 7-71 */
327 st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics;
328 }
329
rkvdec_hevc_prepare_hw_st_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps,struct v4l2_ctrl_hevc_ext_sps_st_rps * cache)330 static void rkvdec_hevc_prepare_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
331 struct v4l2_ctrl_hevc_ext_sps_st_rps *cache)
332 {
333 int idx;
334
335 if (!run->ext_sps_st_rps)
336 return;
337
338 if (!memcmp(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps)))
339 return;
340
341 struct calculated_rps_st_set *calculated_rps_st_sets =
342 kzalloc(sizeof(struct calculated_rps_st_set) *
343 run->sps->num_short_term_ref_pic_sets, GFP_KERNEL);
344
345 for (idx = 0; idx < run->sps->num_short_term_ref_pic_sets; idx++) {
346 const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
347
348 if (rps_data->flags & V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED)
349 st_ref_pic_set_prediction(run, idx, calculated_rps_st_sets);
350 else
351 st_ref_pic_set_calculate(run, idx, calculated_rps_st_sets);
352 }
353
354 rkvdec_hevc_assemble_hw_st_rps(run, rps, calculated_rps_st_sets);
355
356 kfree(calculated_rps_st_sets);
357
358 memcpy(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps));
359 }
360
rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps,struct v4l2_ctrl_hevc_ext_sps_st_rps * st_cache)361 void rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
362 struct v4l2_ctrl_hevc_ext_sps_st_rps *st_cache)
363 {
364 rkvdec_hevc_prepare_hw_st_rps(run, rps, st_cache);
365 rkvdec_hevc_assemble_hw_lt_rps(run, rps);
366 }
367
368 struct vb2_buffer *
get_ref_buf(struct rkvdec_ctx * ctx,struct rkvdec_hevc_run * run,unsigned int dpb_idx)369 get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run,
370 unsigned int dpb_idx)
371 {
372 struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
373 const struct v4l2_ctrl_hevc_decode_params *decode_params = run->decode_params;
374 const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
375 struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
376 struct vb2_buffer *buf = NULL;
377
378 if (dpb_idx < decode_params->num_active_dpb_entries)
379 buf = vb2_find_buffer(cap_q, dpb[dpb_idx].timestamp);
380
381 /*
382 * If a DPB entry is unused or invalid, the address of current destination
383 * buffer is returned.
384 */
385 if (!buf)
386 return &run->base.bufs.dst->vb2_buf;
387
388 return buf;
389 }
390
391 #define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2
392
rkvdec_hevc_adjust_fmt(struct rkvdec_ctx * ctx,struct v4l2_format * f)393 int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f)
394 {
395 struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
396
397 fmt->num_planes = 1;
398 if (!fmt->plane_fmt[0].sizeimage)
399 fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
400 RKVDEC_HEVC_MAX_DEPTH_IN_BYTES;
401 return 0;
402 }
403
rkvdec_hevc_get_image_fmt(struct rkvdec_ctx * ctx,struct v4l2_ctrl * ctrl)404 enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx,
405 struct v4l2_ctrl *ctrl)
406 {
407 const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps;
408
409 if (ctrl->id != V4L2_CID_STATELESS_HEVC_SPS)
410 return RKVDEC_IMG_FMT_ANY;
411
412 if (sps->bit_depth_luma_minus8 == 0) {
413 if (sps->chroma_format_idc == 2)
414 return RKVDEC_IMG_FMT_422_8BIT;
415 else
416 return RKVDEC_IMG_FMT_420_8BIT;
417 } else if (sps->bit_depth_luma_minus8 == 2) {
418 if (sps->chroma_format_idc == 2)
419 return RKVDEC_IMG_FMT_422_10BIT;
420 else
421 return RKVDEC_IMG_FMT_420_10BIT;
422 }
423
424 return RKVDEC_IMG_FMT_ANY;
425 }
426
rkvdec_hevc_run_preamble(struct rkvdec_ctx * ctx,struct rkvdec_hevc_run * run)427 void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx,
428 struct rkvdec_hevc_run *run)
429 {
430 struct v4l2_ctrl *ctrl;
431
432 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
433 V4L2_CID_STATELESS_HEVC_DECODE_PARAMS);
434 run->decode_params = ctrl ? ctrl->p_cur.p : NULL;
435 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
436 V4L2_CID_STATELESS_HEVC_SLICE_PARAMS);
437 run->slices_params = ctrl ? ctrl->p_cur.p : NULL;
438 run->num_slices = ctrl ? ctrl->new_elems : 0;
439 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
440 V4L2_CID_STATELESS_HEVC_SPS);
441 run->sps = ctrl ? ctrl->p_cur.p : NULL;
442 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
443 V4L2_CID_STATELESS_HEVC_PPS);
444 run->pps = ctrl ? ctrl->p_cur.p : NULL;
445 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
446 V4L2_CID_STATELESS_HEVC_SCALING_MATRIX);
447 run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL;
448
449 if (ctx->has_sps_st_rps) {
450 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
451 V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS);
452 run->ext_sps_st_rps = ctrl ? ctrl->p_cur.p : NULL;
453 } else {
454 run->ext_sps_st_rps = NULL;
455 }
456 if (ctx->has_sps_lt_rps) {
457 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
458 V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS);
459 run->ext_sps_lt_rps = ctrl ? ctrl->p_cur.p : NULL;
460 } else {
461 run->ext_sps_lt_rps = NULL;
462 }
463
464 rkvdec_run_preamble(ctx, &run->base);
465 }
466