| Author | Tokens | Token Proportion | Commits | Commit Proportion |
|---|---|---|---|---|
| Detlev Casanova | 2523 | 84.64% | 5 | 55.56% |
| Jonas Karlman | 380 | 12.75% | 1 | 11.11% |
| Boris Brezillon | 69 | 2.31% | 1 | 11.11% |
| Alex Bee | 5 | 0.17% | 1 | 11.11% |
| Nicolas Dufresne | 4 | 0.13% | 1 | 11.11% |
| Total | 2981 | 9 |
// SPDX-License-Identifier: GPL-2.0 /* * Rockchip video decoder hevc common functions * * Copyright (C) 2025 Collabora, Ltd. * Detlev Casanova <detlev.casanova@collabora.com> * * Copyright (C) 2023 Collabora, Ltd. * Sebastian Fricke <sebastian.fricke@collabora.com> * * Copyright (C) 2019 Collabora, Ltd. * Boris Brezillon <boris.brezillon@collabora.com> * * Copyright (C) 2016 Rockchip Electronics Co., Ltd. * Jeffy Chen <jeffy.chen@rock-chips.com> */ #include <linux/v4l2-common.h> #include <media/v4l2-mem2mem.h> #include "rkvdec.h" #include "rkvdec-hevc-common.h" /* Store the Short term ref pic set calculated values */ struct calculated_rps_st_set { u8 num_delta_pocs; u8 num_negative_pics; u8 num_positive_pics; u8 used_by_curr_pic_s0[16]; u8 used_by_curr_pic_s1[16]; s32 delta_poc_s0[16]; s32 delta_poc_s1[16]; }; void 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) { const struct v4l2_ctrl_hevc_pps *pps = run->pps; int i; for (i = 0; i < pps->num_tile_columns_minus1 + 1; i++) column_width[i] = ((i + 1) * pic_in_cts_width) / (pps->num_tile_columns_minus1 + 1) - (i * pic_in_cts_width) / (pps->num_tile_columns_minus1 + 1); for (i = 0; i < pps->num_tile_rows_minus1 + 1; i++) row_height[i] = ((i + 1) * pic_in_cts_height) / (pps->num_tile_rows_minus1 + 1) - (i * pic_in_cts_height) / (pps->num_tile_rows_minus1 + 1); } void 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) { const struct v4l2_ctrl_hevc_pps *pps = run->pps; s32 sum = 0; int i; for (i = 0; i < pps->num_tile_columns_minus1; i++) { column_width[i] = pps->column_width_minus1[i] + 1; sum += column_width[i]; } column_width[i] = pic_in_cts_width - sum; sum = 0; for (i = 0; i < pps->num_tile_rows_minus1; i++) { row_height[i] = pps->row_height_minus1[i] + 1; sum += row_height[i]; } row_height[i] = pic_in_cts_height - sum; } static void set_ref_poc(struct rkvdec_rps_short_term_ref_set *set, int poc, int value, int flag) { switch (poc) { case 0: set->delta_poc0 = value; set->used_flag0 = flag; break; case 1: set->delta_poc1 = value; set->used_flag1 = flag; break; case 2: set->delta_poc2 = value; set->used_flag2 = flag; break; case 3: set->delta_poc3 = value; set->used_flag3 = flag; break; case 4: set->delta_poc4 = value; set->used_flag4 = flag; break; case 5: set->delta_poc5 = value; set->used_flag5 = flag; break; case 6: set->delta_poc6 = value; set->used_flag6 = flag; break; case 7: set->delta_poc7 = value; set->used_flag7 = flag; break; case 8: set->delta_poc8 = value; set->used_flag8 = flag; break; case 9: set->delta_poc9 = value; set->used_flag9 = flag; break; case 10: set->delta_poc10 = value; set->used_flag10 = flag; break; case 11: set->delta_poc11 = value; set->used_flag11 = flag; break; case 12: set->delta_poc12 = value; set->used_flag12 = flag; break; case 13: set->delta_poc13 = value; set->used_flag13 = flag; break; case 14: set->delta_poc14 = value; set->used_flag14 = flag; break; } } static void assemble_scalingfactor0(struct rkvdec_ctx *ctx, u8 *output, const struct v4l2_ctrl_hevc_scaling_matrix *input) { const struct rkvdec_variant *variant = ctx->dev->variant; int offset = 0; variant->ops->flatten_matrices(output, (const u8 *)input->scaling_list_4x4, 6, 4); offset = 6 * 16 * sizeof(u8); variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_8x8, 6, 8); offset += 6 * 64 * sizeof(u8); variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_16x16, 6, 8); offset += 6 * 64 * sizeof(u8); /* Add a 128 byte padding with 0s between the two 32x32 matrices */ variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_32x32, 1, 8); offset += 64 * sizeof(u8); memset(output + offset, 0, 128); offset += 128 * sizeof(u8); variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)), 1, 8); offset += 64 * sizeof(u8); memset(output + offset, 0, 128); } /* * Required layout: * A = scaling_list_dc_coef_16x16 * B = scaling_list_dc_coef_32x32 * 0 = Padding * * A, A, A, A, A, A, B, 0, 0, B, 0, 0 */ static void assemble_scalingdc(u8 *output, const struct v4l2_ctrl_hevc_scaling_matrix *input) { u8 list_32x32[6] = {0}; memcpy(output, input->scaling_list_dc_coef_16x16, 6 * sizeof(u8)); list_32x32[0] = input->scaling_list_dc_coef_32x32[0]; list_32x32[3] = input->scaling_list_dc_coef_32x32[1]; memcpy(output + 6 * sizeof(u8), list_32x32, 6 * sizeof(u8)); } static void translate_scaling_list(struct rkvdec_ctx *ctx, struct scaling_factor *output, const struct v4l2_ctrl_hevc_scaling_matrix *input) { assemble_scalingfactor0(ctx, output->scalingfactor0, input); memcpy(output->scalingfactor1, (const u8 *)input->scaling_list_4x4, 96); assemble_scalingdc(output->scalingdc, input); memset(output->reserved, 0, 4 * sizeof(u8)); } void 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) { const struct v4l2_ctrl_hevc_scaling_matrix *scaling = run->scaling_matrix; if (!memcmp(cache, scaling, sizeof(struct v4l2_ctrl_hevc_scaling_matrix))) return; translate_scaling_list(ctx, scaling_factor, scaling); memcpy(cache, scaling, sizeof(struct v4l2_ctrl_hevc_scaling_matrix)); } static void rkvdec_hevc_assemble_hw_lt_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps) { const struct v4l2_ctrl_hevc_sps *sps = run->sps; if (!run->ext_sps_lt_rps) return; for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) { rps->refs[i].lt_ref_pic_poc_lsb = run->ext_sps_lt_rps[i].lt_ref_pic_poc_lsb_sps; rps->refs[i].used_by_curr_pic_lt_flag = !!(run->ext_sps_lt_rps[i].flags & V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT); } } static void rkvdec_hevc_assemble_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps, struct calculated_rps_st_set *calculated_rps_st_sets) { const struct v4l2_ctrl_hevc_sps *sps = run->sps; for (int i = 0; i < sps->num_short_term_ref_pic_sets; i++) { int poc = 0; int j = 0; const struct calculated_rps_st_set *set = &calculated_rps_st_sets[i]; rps->short_term_ref_sets[i].num_negative = set->num_negative_pics; rps->short_term_ref_sets[i].num_positive = set->num_positive_pics; for (; j < set->num_negative_pics; j++) { set_ref_poc(&rps->short_term_ref_sets[i], j, set->delta_poc_s0[j], set->used_by_curr_pic_s0[j]); } poc = j; for (j = 0; j < set->num_positive_pics; j++) { set_ref_poc(&rps->short_term_ref_sets[i], poc + j, set->delta_poc_s1[j], set->used_by_curr_pic_s1[j]); } } } /* * Compute the short term ref pic set parameters based on its reference short term ref pic */ static void st_ref_pic_set_prediction(struct rkvdec_hevc_run *run, int idx, struct calculated_rps_st_set *calculated_rps_st_sets) { const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx]; struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx]; struct calculated_rps_st_set *ref_rps; u8 st_rps_idx = idx; u8 ref_rps_idx = 0; s16 delta_rps = 0; u8 use_delta_flag[16] = { 0 }; u8 used_by_curr_pic_flag[16] = { 0 }; int i, j; int dPoc; ref_rps_idx = st_rps_idx - (rps_data->delta_idx_minus1 + 1); /* 7-59 */ delta_rps = (1 - 2 * rps_data->delta_rps_sign) * (rps_data->abs_delta_rps_minus1 + 1); /* 7-60 */ ref_rps = &calculated_rps_st_sets[ref_rps_idx]; for (j = 0; j <= ref_rps->num_delta_pocs; j++) { used_by_curr_pic_flag[j] = !!(rps_data->used_by_curr_pic & (1 << j)); use_delta_flag[j] = !!(rps_data->use_delta_flag & (1 << j)); } /* 7-61: calculate num_negative_pics, delta_poc_s0 and used_by_curr_pic_s0 */ i = 0; for (j = (ref_rps->num_positive_pics - 1); j >= 0; j--) { dPoc = ref_rps->delta_poc_s1[j] + delta_rps; if (dPoc < 0 && use_delta_flag[ref_rps->num_negative_pics + j]) { st_rps->delta_poc_s0[i] = dPoc; st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[ref_rps->num_negative_pics + j]; } } if (delta_rps < 0 && use_delta_flag[ref_rps->num_delta_pocs]) { st_rps->delta_poc_s0[i] = delta_rps; st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs]; } for (j = 0; j < ref_rps->num_negative_pics; j++) { dPoc = ref_rps->delta_poc_s0[j] + delta_rps; if (dPoc < 0 && use_delta_flag[j]) { st_rps->delta_poc_s0[i] = dPoc; st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[j]; } } st_rps->num_negative_pics = i; /* 7-62: calculate num_positive_pics, delta_poc_s1 and used_by_curr_pic_s1 */ i = 0; for (j = (ref_rps->num_negative_pics - 1); j >= 0; j--) { dPoc = ref_rps->delta_poc_s0[j] + delta_rps; if (dPoc > 0 && use_delta_flag[j]) { st_rps->delta_poc_s1[i] = dPoc; st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[j]; } } if (delta_rps > 0 && use_delta_flag[ref_rps->num_delta_pocs]) { st_rps->delta_poc_s1[i] = delta_rps; st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs]; } for (j = 0; j < ref_rps->num_positive_pics; j++) { dPoc = ref_rps->delta_poc_s1[j] + delta_rps; if (dPoc > 0 && use_delta_flag[ref_rps->num_negative_pics + j]) { st_rps->delta_poc_s1[i] = dPoc; st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[ref_rps->num_negative_pics + j]; } } st_rps->num_positive_pics = i; st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics; } /* * Compute the short term ref pic set parameters based on the control's data. */ static void st_ref_pic_set_calculate(struct rkvdec_hevc_run *run, int idx, struct calculated_rps_st_set *calculated_rps_st_sets) { const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx]; struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx]; int j, i = 0; /* 7-63 */ st_rps->num_negative_pics = rps_data->num_negative_pics; /* 7-64 */ st_rps->num_positive_pics = rps_data->num_positive_pics; for (i = 0; i < st_rps->num_negative_pics; i++) { /* 7-65 */ st_rps->used_by_curr_pic_s0[i] = !!(rps_data->used_by_curr_pic & (1 << i)); if (i == 0) { /* 7-67 */ st_rps->delta_poc_s0[i] = -(rps_data->delta_poc_s0_minus1[i] + 1); } else { /* 7-69 */ st_rps->delta_poc_s0[i] = st_rps->delta_poc_s0[i - 1] - (rps_data->delta_poc_s0_minus1[i] + 1); } } for (j = 0; j < st_rps->num_positive_pics; j++) { /* 7-66 */ st_rps->used_by_curr_pic_s1[j] = !!(rps_data->used_by_curr_pic & (1 << (i + j))); if (j == 0) { /* 7-68 */ st_rps->delta_poc_s1[j] = rps_data->delta_poc_s1_minus1[j] + 1; } else { /* 7-70 */ st_rps->delta_poc_s1[j] = st_rps->delta_poc_s1[j - 1] + (rps_data->delta_poc_s1_minus1[j] + 1); } } /* 7-71 */ st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics; } static void rkvdec_hevc_prepare_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps, struct v4l2_ctrl_hevc_ext_sps_st_rps *cache) { int idx; if (!run->ext_sps_st_rps) return; if (!memcmp(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps))) return; struct calculated_rps_st_set *calculated_rps_st_sets = kzalloc(sizeof(struct calculated_rps_st_set) * run->sps->num_short_term_ref_pic_sets, GFP_KERNEL); for (idx = 0; idx < run->sps->num_short_term_ref_pic_sets; idx++) { const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx]; if (rps_data->flags & V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED) st_ref_pic_set_prediction(run, idx, calculated_rps_st_sets); else st_ref_pic_set_calculate(run, idx, calculated_rps_st_sets); } rkvdec_hevc_assemble_hw_st_rps(run, rps, calculated_rps_st_sets); kfree(calculated_rps_st_sets); memcpy(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps)); } void rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps, struct v4l2_ctrl_hevc_ext_sps_st_rps *st_cache) { rkvdec_hevc_prepare_hw_st_rps(run, rps, st_cache); rkvdec_hevc_assemble_hw_lt_rps(run, rps); } struct vb2_buffer * get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run, unsigned int dpb_idx) { struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; const struct v4l2_ctrl_hevc_decode_params *decode_params = run->decode_params; const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb; struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; struct vb2_buffer *buf = NULL; if (dpb_idx < decode_params->num_active_dpb_entries) buf = vb2_find_buffer(cap_q, dpb[dpb_idx].timestamp); /* * If a DPB entry is unused or invalid, the address of current destination * buffer is returned. */ if (!buf) return &run->base.bufs.dst->vb2_buf; return buf; } #define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2 int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f) { struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; fmt->num_planes = 1; if (!fmt->plane_fmt[0].sizeimage) fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * RKVDEC_HEVC_MAX_DEPTH_IN_BYTES; return 0; } enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl) { const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps; if (ctrl->id != V4L2_CID_STATELESS_HEVC_SPS) return RKVDEC_IMG_FMT_ANY; if (sps->bit_depth_luma_minus8 == 0) { if (sps->chroma_format_idc == 2) return RKVDEC_IMG_FMT_422_8BIT; else return RKVDEC_IMG_FMT_420_8BIT; } else if (sps->bit_depth_luma_minus8 == 2) { if (sps->chroma_format_idc == 2) return RKVDEC_IMG_FMT_422_10BIT; else return RKVDEC_IMG_FMT_420_10BIT; } return RKVDEC_IMG_FMT_ANY; } void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run) { struct v4l2_ctrl *ctrl; ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS); run->decode_params = ctrl ? ctrl->p_cur.p : NULL; ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_HEVC_SLICE_PARAMS); run->slices_params = ctrl ? ctrl->p_cur.p : NULL; run->num_slices = ctrl ? ctrl->new_elems : 0; ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_HEVC_SPS); run->sps = ctrl ? ctrl->p_cur.p : NULL; ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_HEVC_PPS); run->pps = ctrl ? ctrl->p_cur.p : NULL; ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL; if (ctx->has_sps_st_rps) { ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS); run->ext_sps_st_rps = ctrl ? ctrl->p_cur.p : NULL; } else { run->ext_sps_st_rps = NULL; } if (ctx->has_sps_lt_rps) { ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS); run->ext_sps_lt_rps = ctrl ? ctrl->p_cur.p : NULL; } else { run->ext_sps_lt_rps = NULL; } rkvdec_run_preamble(ctx, &run->base); }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1