From patchwork Thu Mar 7 19:08:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Almeida X-Patchwork-Id: 778730 Received: from madrid.collaboradmins.com (madrid.collaboradmins.com [46.235.227.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1306012FF8C; Thu, 7 Mar 2024 19:12:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.235.227.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709838779; cv=none; b=UN9FQo/1tZcuy9j53+liZlwygVm+9XvQhMuNLSXzDI3yFwAOO6IXURMLv67vKpmp67GA4dgt2vvdCqNZk0PwhZWULFcPQhfvvfynwOi0HKRuX8dL12Lz8yq5fhj7eA3VuDx1JIZvPqjyNiEabeWOTboiM63gukf0fOZnvpxdQ9k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709838779; c=relaxed/simple; bh=9QFash5rhtEgauooL1CGidnfPpNBsj7gG+HqJ19XGoc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aQE759VWWv91IpreQ2j7pviTg5itPUVS6/txRMjmvV/ytITgVBVyXioFo2fQ6HIMT9Z4BZk4NCzaVFyumikZsStdVvjcrN+AQ05DMRTlT0vY2ZPJbvx4eyLJVE7njKkbrrpKnZPqbFjY1rbH6jpPnrhlTTPnng07N6qEc3Nf5o8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=aaKp2pDw; arc=none smtp.client-ip=46.235.227.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="aaKp2pDw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1709838773; bh=9QFash5rhtEgauooL1CGidnfPpNBsj7gG+HqJ19XGoc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aaKp2pDwHh/SgFq18lFU1SWNMhRhmKVqlw3x41po2BcbrvAfLF7kXsVBo1OUkHJTF F++Qxjf/vpBS+ZWKaK3+n2YU39lItdefxFxat8WqVbSSQshmKb0D+JARNVttKmH680 UazEoz3Pv4K2na6+izVM+28K7iQ78STpZxplbQOLorwRNZYZ/6dGysDdzl7GI5CBQ6 xR16rq/hKOdyht6+sccwPdGg7Mg+PsrdoG49Md+Rmd2TaTD6oxNyvxgbhy9iAHf4y7 /rkWI/JLiIb0q4K5vJ+OJMDfwZPV8H5d3PiaQuf4v01P2xxDh4k2Im3/x07zx0uz/2 x2YFTeBilzLKw== Received: from localhost.localdomain (cola.collaboradmins.com [195.201.22.229]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: dwlsalmeida) by madrid.collaboradmins.com (Postfix) with ESMTPSA id 062FF37820EE; Thu, 7 Mar 2024 19:12:49 +0000 (UTC) From: Daniel Almeida To: wedsonaf@gmail.com, ojeda@kernel.org, mchehab@kernel.org, hverkuil@xs4all.nl Cc: Daniel Almeida , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, kernel@collabora.com Subject: [RFC PATCH v2 1/2] v4l2-core: rewrite the VP9 library in Rust Date: Thu, 7 Mar 2024 16:08:15 -0300 Message-ID: <20240307190841.10260-2-daniel.almeida@collabora.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240307190841.10260-1-daniel.almeida@collabora.com> References: <20240227215146.46487-1-daniel.almeida@collabora.com> <20240307190841.10260-1-daniel.almeida@collabora.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- drivers/media/platform/verisilicon/Kconfig | 2 +- .../platform/verisilicon/hantro_g2_vp9_dec.c | 38 +- .../media/platform/verisilicon/hantro_hw.h | 8 +- drivers/media/v4l2-core/Kconfig | 5 + drivers/staging/media/rkvdec/Kconfig | 2 +- drivers/staging/media/rkvdec/rkvdec-vp9.c | 52 +- include/media/v4l2-vp9-rs.h | 99 + rust/bindings/bindings_helper.h | 1 + rust/kernel/lib.rs | 2 + rust/kernel/media.rs | 5 + rust/kernel/media/v4l2_core.rs | 6 + rust/kernel/media/v4l2_core/cbindgen.toml | 26 + rust/kernel/media/v4l2_core/vp9.rs | 2053 +++++++++++++++++ 13 files changed, 2249 insertions(+), 50 deletions(-) create mode 100644 include/media/v4l2-vp9-rs.h create mode 100644 rust/kernel/media.rs create mode 100644 rust/kernel/media/v4l2_core.rs create mode 100644 rust/kernel/media/v4l2_core/cbindgen.toml create mode 100644 rust/kernel/media/v4l2_core/vp9.rs diff --git a/drivers/media/platform/verisilicon/Kconfig b/drivers/media/platform/verisilicon/Kconfig index 24b927d8f182..d8e4e9b5de2f 100644 --- a/drivers/media/platform/verisilicon/Kconfig +++ b/drivers/media/platform/verisilicon/Kconfig @@ -12,7 +12,7 @@ config VIDEO_HANTRO select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select V4L2_H264 - select V4L2_VP9 + select V4L2_VP9_RS help Support for the Hantro IP based Video Processing Units present on Rockchip and NXP i.MX8M SoCs, which accelerate video and image diff --git a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c index 342e543dee4c..43990b550919 100644 --- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c +++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include "hantro.h" #include "hantro_vp9.h" @@ -63,7 +63,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_ * frame_context_idx = 0 * } */ - fctx_idx = v4l2_vp9_reset_frame_ctx(*dec_params, vp9_ctx->frame_context); + fctx_idx = v4l2_vp9_reset_frame_ctx_rs(*dec_params, &vp9_ctx->frame_context); vp9_ctx->cur.frame_context_idx = fctx_idx; /* 6.1 frame(sz): load_probs() and load_probs2() */ @@ -83,7 +83,7 @@ static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_ * fw_update_probs() performs actual probs updates or leaves probs as-is * for values for which a zero was passed from userspace. */ - v4l2_vp9_fw_update_probs(&vp9_ctx->probability_tables, prob_updates, *dec_params); + v4l2_vp9_fw_update_probs_rs(&vp9_ctx->probability_tables, prob_updates, *dec_params); return 0; } @@ -422,7 +422,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr if (segment_enabled) { if (update_data) update_feat_and_flag(vp9_ctx, seg, feat_id, segid); - if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid)) + if (v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled, feat_id, segid)) feat_val = feat_val_clip3(feat_val, vp9_ctx->feature_data[segid][feat_id], absolute, 255); @@ -435,7 +435,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr if (segment_enabled) { if (update_data) update_feat_and_flag(vp9_ctx, seg, feat_id, segid); - if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid)) + if (v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled, feat_id, segid)) feat_val = feat_val_clip3(feat_val, vp9_ctx->feature_data[segid][feat_id], absolute, 63); @@ -449,7 +449,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr if (update_data) update_feat_and_flag(vp9_ctx, seg, feat_id, segid); if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) && - v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid)) + v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled, feat_id, segid)) feat_val = vp9_ctx->feature_data[segid][feat_id] + 1; } hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val); @@ -460,7 +460,7 @@ static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fr if (segment_enabled) { if (update_data) update_feat_and_flag(vp9_ctx, seg, feat_id, segid); - feat_val = v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, + feat_val = v4l2_vp9_seg_feat_enabled_rs(&vp9_ctx->feature_enabled, feat_id, segid) ? 1 : 0; } hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val); @@ -637,17 +637,17 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram struct hantro_g2_probs *adaptive; struct hantro_g2_mv_probs *mv; const struct v4l2_vp9_segmentation *seg = &dec_params->seg; - const struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables; + const struct v4l2_vp9_frame_context_rs *probs = &vp9_ctx->probability_tables; int i, j, k, l, m; for (i = 0; i < ARRAY_SIZE(all_probs->kf_y_mode_prob); ++i) for (j = 0; j < ARRAY_SIZE(all_probs->kf_y_mode_prob[0]); ++j) { memcpy(all_probs->kf_y_mode_prob[i][j], - v4l2_vp9_kf_y_mode_prob[i][j], + v4l2_vp9_kf_y_mode_prob_rs[i][j], ARRAY_SIZE(all_probs->kf_y_mode_prob[i][j])); all_probs->kf_y_mode_prob_tail[i][j][0] = - v4l2_vp9_kf_y_mode_prob[i][j][8]; + v4l2_vp9_kf_y_mode_prob_rs[i][j][8]; } memcpy(all_probs->mb_segment_tree_probs, seg->tree_probs, @@ -657,10 +657,10 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram sizeof(all_probs->segment_pred_probs)); for (i = 0; i < ARRAY_SIZE(all_probs->kf_uv_mode_prob); ++i) { - memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob[i], + memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob_rs[i], ARRAY_SIZE(all_probs->kf_uv_mode_prob[i])); - all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob[i][8]; + all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob_rs[i][8]; } adaptive = &all_probs->probs; @@ -692,8 +692,8 @@ static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_fram } for (i = 0; i < ARRAY_SIZE(adaptive->partition[0]); ++i) { - memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs[i], - sizeof(v4l2_vp9_kf_partition_probs[i])); + memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs_rs[i], + sizeof(v4l2_vp9_kf_partition_probs_rs[i])); adaptive->partition[0][i][3] = 0; } @@ -933,7 +933,7 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx) if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) { /* error_resilient_mode == 0 && frame_parallel_decoding_mode == 0 */ - struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables; + struct v4l2_vp9_frame_context_rs *probs = &vp9_ctx->probability_tables; bool frame_is_intra = vp9_ctx->cur.flags & (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY); struct tx_and_skip { @@ -942,7 +942,7 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx) u8 tx32[2][3]; u8 skip[3]; } _tx_skip, *tx_skip = &_tx_skip; - struct v4l2_vp9_frame_symbol_counts *counts; + struct v4l2_vp9_frame_symbol_counts_rs *counts; struct symbol_counts *hantro_cnts; u32 tx16p[2][4]; int i; @@ -968,7 +968,8 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx) } counts->tx16p = &tx16p; - v4l2_vp9_adapt_coef_probs(probs, counts, + v4l2_vp9_adapt_coef_probs_rs(probs, + counts, !vp9_ctx->last.valid || vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME, frame_is_intra); @@ -984,7 +985,8 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx) mv_mode[i][3] = hantro_cnts->inter_mode_counts[i][2][1]; } counts->mv_mode = &mv_mode; - v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts, + v4l2_vp9_adapt_noncoef_probs_rs(&vp9_ctx->probability_tables, + counts, vp9_ctx->cur.reference_mode, vp9_ctx->cur.interpolation_filter, vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags); diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index 9aec8a79acdc..f8baa898ef53 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include "rockchip_av1_entropymode.h" @@ -231,9 +231,9 @@ struct hantro_vp9_dec_hw_ctx { struct hantro_aux_buf tile_edge; struct hantro_aux_buf segment_map; struct hantro_aux_buf misc; - struct v4l2_vp9_frame_symbol_counts cnts; - struct v4l2_vp9_frame_context probability_tables; - struct v4l2_vp9_frame_context frame_context[4]; + struct v4l2_vp9_frame_symbol_counts_rs cnts; + struct v4l2_vp9_frame_context_rs probability_tables; + struct v4l2_vp9_frame_context_rs frame_context[4]; struct hantro_vp9_frame_info cur; struct hantro_vp9_frame_info last; diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 331b8e535e5b..878229c2490b 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -48,6 +48,11 @@ config V4L2_H264 config V4L2_VP9 tristate +# Used by drivers that need the Rust equivalent to v4l2-vp9.ko +config V4L2_VP9_RS + tristate + depends on RUST + # Used by drivers that need v4l2-mem2mem.ko config V4L2_MEM2MEM_DEV tristate diff --git a/drivers/staging/media/rkvdec/Kconfig b/drivers/staging/media/rkvdec/Kconfig index 5f3bdd848a2c..245dc47082d4 100644 --- a/drivers/staging/media/rkvdec/Kconfig +++ b/drivers/staging/media/rkvdec/Kconfig @@ -8,7 +8,7 @@ config VIDEO_ROCKCHIP_VDEC select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select V4L2_H264 - select V4L2_VP9 + select V4L2_VP9_RS help Support for the Rockchip Video Decoder IP present on Rockchip SoCs, which accelerates video decoding. diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c index 0e7e16f20eeb..86c6903d11ab 100644 --- a/drivers/staging/media/rkvdec/rkvdec-vp9.c +++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include "rkvdec.h" #include "rkvdec-regs.h" @@ -157,10 +157,10 @@ struct rkvdec_vp9_frame_info { struct rkvdec_vp9_ctx { struct rkvdec_aux_buf priv_tbl; struct rkvdec_aux_buf count_tbl; - struct v4l2_vp9_frame_symbol_counts inter_cnts; - struct v4l2_vp9_frame_symbol_counts intra_cnts; - struct v4l2_vp9_frame_context probability_tables; - struct v4l2_vp9_frame_context frame_context[4]; + struct v4l2_vp9_frame_symbol_counts_rs inter_cnts; + struct v4l2_vp9_frame_symbol_counts_rs intra_cnts; + struct v4l2_vp9_frame_context_rs probability_tables; + struct v4l2_vp9_frame_context_rs frame_context[4]; struct rkvdec_vp9_frame_info cur; struct rkvdec_vp9_frame_info last; }; @@ -192,7 +192,7 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx, struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; struct rkvdec_vp9_intra_only_frame_probs *rkprobs; - const struct v4l2_vp9_frame_context *probs; + const struct v4l2_vp9_frame_context_rs *probs; unsigned int i, j, k; rkprobs = &tbl->probs.intra_only; @@ -209,15 +209,15 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx, } /* intra mode prob 80 x 128 bits */ - for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob); i++) { + for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs); i++) { unsigned int byte_count = 0; int idx = 0; /* vp9_kf_y_mode_prob */ - for (j = 0; j < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob[0]); j++) { - for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob[0][0]); + for (j = 0; j < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0]); j++) { + for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0][0]); k++) { - u8 val = v4l2_vp9_kf_y_mode_prob[i][j][k]; + u8 val = v4l2_vp9_kf_y_mode_prob_rs[i][j][k]; rkprobs->intra_mode[i].y_mode[idx++] = val; byte_count++; @@ -229,8 +229,8 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx, } } - for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob); ++i) { - const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob; + for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob_rs); ++i) { + const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob_rs; rkprobs->intra_mode[i / 23].uv_mode[i % 23] = ptr[i]; } @@ -242,7 +242,7 @@ static void init_inter_probs(struct rkvdec_ctx *ctx, struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; struct rkvdec_vp9_inter_frame_probs *rkprobs; - const struct v4l2_vp9_frame_context *probs; + const struct v4l2_vp9_frame_context_rs *probs; unsigned int i, j, k; rkprobs = &tbl->probs.inter; @@ -315,7 +315,7 @@ static void init_probs(struct rkvdec_ctx *ctx, struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; struct rkvdec_vp9_probs *rkprobs = &tbl->probs; const struct v4l2_vp9_segmentation *seg; - const struct v4l2_vp9_frame_context *probs; + const struct v4l2_vp9_frame_context_rs *probs; bool intra_only; dec_params = run->decode_params; @@ -330,7 +330,7 @@ static void init_probs(struct rkvdec_ctx *ctx, /* sb info 5 x 128 bit */ memcpy(rkprobs->partition, - intra_only ? v4l2_vp9_kf_partition_probs : probs->partition, + intra_only ? v4l2_vp9_kf_partition_probs_rs : probs->partition, sizeof(rkprobs->partition)); memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred)); @@ -448,7 +448,7 @@ static void config_ref_registers(struct rkvdec_ctx *ctx, static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid) { struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; - const struct v4l2_vp9_segmentation *seg; + struct v4l2_vp9_segmentation *seg; struct rkvdec_dev *rkvdec = ctx->dev; s16 feature_val; int feature_id; @@ -456,28 +456,28 @@ static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid) seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg; feature_id = V4L2_VP9_SEG_LVL_ALT_Q; - if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { + if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) { feature_val = seg->feature_data[segid][feature_id]; val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) | RKVDEC_SEGID_FRAME_QP_DELTA(feature_val); } feature_id = V4L2_VP9_SEG_LVL_ALT_L; - if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { + if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) { feature_val = seg->feature_data[segid][feature_id]; val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) | RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val); } feature_id = V4L2_VP9_SEG_LVL_REF_FRAME; - if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { + if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) { feature_val = seg->feature_data[segid][feature_id]; val |= RKVDEC_SEGID_REFERINFO_EN(1) | RKVDEC_SEGID_REFERINFO(feature_val); } feature_id = V4L2_VP9_SEG_LVL_SKIP; - if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) + if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) val |= RKVDEC_SEGID_FRAME_SKIP_EN(1); if (!segid && @@ -773,7 +773,7 @@ static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx, * frame_context_idx = 0 * } */ - fctx_idx = v4l2_vp9_reset_frame_ctx(dec_params, vp9_ctx->frame_context); + fctx_idx = v4l2_vp9_reset_frame_ctx_rs(dec_params, &vp9_ctx->frame_context); vp9_ctx->cur.frame_context_idx = fctx_idx; /* 6.1 frame(sz): load_probs() and load_probs2() */ @@ -793,7 +793,7 @@ static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx, * fw_update_probs() performs actual probs updates or leaves probs as-is * for values for which a zero was passed from userspace. */ - v4l2_vp9_fw_update_probs(&vp9_ctx->probability_tables, prob_updates, dec_params); + v4l2_vp9_fw_update_probs_rs(&vp9_ctx->probability_tables, prob_updates, dec_params); return 0; } @@ -871,7 +871,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) { /* error_resilient_mode == 0 && frame_parallel_decoding_mode == 0 */ - struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables; + struct v4l2_vp9_frame_context_rs *probs = &vp9_ctx->probability_tables; bool frame_is_intra = vp9_ctx->cur.flags & (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY); struct tx_and_skip { @@ -880,7 +880,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, u8 tx32[2][3]; u8 skip[3]; } _tx_skip, *tx_skip = &_tx_skip; - struct v4l2_vp9_frame_symbol_counts *counts; + struct v4l2_vp9_frame_symbol_counts_rs *counts; /* buffer the forward-updated TX and skip probs */ if (frame_is_intra) @@ -894,7 +894,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, copy_tx_and_skip(probs, tx_skip); counts = frame_is_intra ? &vp9_ctx->intra_cnts : &vp9_ctx->inter_cnts; - v4l2_vp9_adapt_coef_probs(probs, counts, + v4l2_vp9_adapt_coef_probs_rs(probs, counts, !vp9_ctx->last.valid || vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME, frame_is_intra); @@ -909,7 +909,7 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, counts->classes = &classes; /* load_probs2() already done */ - v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts, + v4l2_vp9_adapt_noncoef_probs_rs(&vp9_ctx->probability_tables, counts, vp9_ctx->cur.reference_mode, vp9_ctx->cur.interpolation_filter, vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags); diff --git a/include/media/v4l2-vp9-rs.h b/include/media/v4l2-vp9-rs.h new file mode 100644 index 000000000000..3e93f67b0002 --- /dev/null +++ b/include/media/v4l2-vp9-rs.h @@ -0,0 +1,99 @@ +#ifndef V4L2_VP9_RS_H +#define V4L2_VP9_RS_H + +/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ + +#include + +struct v4l2_vp9_frame_mv_context_rs { + uint8_t joint[3]; + uint8_t sign[2]; + uint8_t classes[2][10]; + uint8_t class0_bit[2]; + uint8_t bits[2][10]; + uint8_t class0_fr[2][2][3]; + uint8_t fr[2][3]; + uint8_t class0_hp[2]; + uint8_t hp[2]; +}; + +struct v4l2_vp9_frame_context_rs { + uint8_t tx8[2][1]; + uint8_t tx16[2][2]; + uint8_t tx32[2][3]; + uint8_t coef[4][2][2][6][6][3]; + uint8_t skip[3]; + uint8_t inter_mode[7][3]; + uint8_t interp_filter[4][2]; + uint8_t is_inter[4]; + uint8_t comp_mode[5]; + uint8_t single_ref[5][2]; + uint8_t comp_ref[5]; + uint8_t y_mode[4][9]; + uint8_t uv_mode[10][9]; + uint8_t partition[16][3]; + struct v4l2_vp9_frame_mv_context_rs mv; +}; + +struct v4l2_vp9_frame_symbol_counts_rs { + uint32_t (*partition)[16][4]; + uint32_t (*skip)[3][2]; + uint32_t (*intra_inter)[4][2]; + uint32_t (*tx32p)[2][4]; + uint32_t (*tx16p)[2][4]; + uint32_t (*tx8p)[2][2]; + uint32_t (*y_mode)[4][10]; + uint32_t (*uv_mode)[10][10]; + uint32_t (*comp)[5][2]; + uint32_t (*comp_ref)[5][2]; + uint32_t (*single_ref)[5][2][2]; + uint32_t (*mv_mode)[7][4]; + uint32_t (*filter)[4][3]; + uint32_t (*mv_joint)[4]; + uint32_t (*sign)[2][2]; + uint32_t (*classes)[2][11]; + uint32_t (*class0)[2][2]; + uint32_t (*bits)[2][10][2]; + uint32_t (*class0_fp)[2][2][4]; + uint32_t (*fp)[2][4]; + uint32_t (*class0_hp)[2][2]; + uint32_t (*hp)[2][2]; + uint32_t (*coeff[4][2][2][6][6])[3]; + uint32_t *eob[4][2][2][6][6][2]; +}; + +extern const uint8_t v4l2_vp9_kf_y_mode_prob_rs[10][10][9]; + +extern const uint8_t v4l2_vp9_kf_partition_probs_rs[16][3]; + +extern const uint8_t v4l2_vp9_kf_uv_mode_prob_rs[10][9]; + +extern const struct v4l2_vp9_frame_context_rs v4l2_vp9_default_probs_rs; + +/** + * Counterpart to 6.3 compressed_header(), but parsing has been done in userspace. + */ +void v4l2_vp9_fw_update_probs_rs(struct v4l2_vp9_frame_context_rs *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas, + const struct v4l2_ctrl_vp9_frame *dec_params); + +uint8_t v4l2_vp9_reset_frame_ctx_rs(const struct v4l2_ctrl_vp9_frame *dec_params, + struct v4l2_vp9_frame_context_rs (*frame_context)[4]); + +void v4l2_vp9_adapt_coef_probs_rs(struct v4l2_vp9_frame_context_rs *probs, + struct v4l2_vp9_frame_symbol_counts_rs *counts, + bool use_128, + bool frame_is_intra); + +void v4l2_vp9_adapt_noncoef_probs_rs(struct v4l2_vp9_frame_context_rs *probs, + struct v4l2_vp9_frame_symbol_counts_rs *counts, + uint8_t reference_mode, + uint8_t interpolation_filter, + uint8_t tx_mode, + uint32_t flags); + +bool v4l2_vp9_seg_feat_enabled_rs(const uint8_t (*feature_enabled)[8], + uint32_t feature, + uint32_t segid); + +#endif /* V4L2_VP9_RS_H */ diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index c651d38e5dd6..25e2c06bb967 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -25,6 +25,7 @@ #include #include #include +#include /* `bindgen` gets confused at certain things. */ const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index cc39195b0157..724e1d3bf2af 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -39,6 +39,8 @@ pub mod ioctl; #[cfg(CONFIG_KUNIT)] pub mod kunit; +#[cfg(CONFIG_MEDIA_SUPPORT)] +pub mod media; #[cfg(CONFIG_NET)] pub mod net; pub mod prelude; diff --git a/rust/kernel/media.rs b/rust/kernel/media.rs new file mode 100644 index 000000000000..72f5cd716874 --- /dev/null +++ b/rust/kernel/media.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Media support + +pub mod v4l2_core; \ No newline at end of file diff --git a/rust/kernel/media/v4l2_core.rs b/rust/kernel/media/v4l2_core.rs new file mode 100644 index 000000000000..7515fe748a65 --- /dev/null +++ b/rust/kernel/media/v4l2_core.rs @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! V4L2 Core + +#[cfg(CONFIG_V4L2_VP9_RS)] +pub mod vp9; \ No newline at end of file diff --git a/rust/kernel/media/v4l2_core/cbindgen.toml b/rust/kernel/media/v4l2_core/cbindgen.toml new file mode 100644 index 000000000000..ebbc8a5e2fff --- /dev/null +++ b/rust/kernel/media/v4l2_core/cbindgen.toml @@ -0,0 +1,26 @@ +# Generate the C API with: +# cbindgen --lang c -v --config rust/kernel/media/v4l2_core/cbindgen.toml --output include/media/v4l2-vp9-rs.h -- rust/kernel/media/v4l2_core/vp9.rs + +language = "C" + +# No , , , , +no_includes = true +style = "tag" + +sys_includes = ["media/v4l2-ctrls.h"] +autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" +usize_is_size_t = true +include_guard = "V4L2_VP9_RS_H" + +# Rename everything from bindgen +# See https://github.com/mozilla/cbindgen/issues/621 +# Also rename our mangled structs into snake_case for the C API +[export.rename] +"v4l2_ctrl_vp9_compressed_hdr" = "struct v4l2_ctrl_vp9_compressed_hdr" +"v4l2_ctrl_vp9_frame" = "struct v4l2_ctrl_vp9_frame" +"FrameContext" = "v4l2_vp9_frame_context_rs" +"FrameSymbolCounts" = "v4l2_vp9_frame_symbol_counts_rs" +"FrameMvContext" = "v4l2_vp9_frame_mv_context_rs" + +[enum] +prefix_with_name = true diff --git a/rust/kernel/media/v4l2_core/vp9.rs b/rust/kernel/media/v4l2_core/vp9.rs new file mode 100644 index 000000000000..62e3c1d7c625 --- /dev/null +++ b/rust/kernel/media/v4l2_core/vp9.rs @@ -0,0 +1,2053 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! VP9 helpers +//! This library was initially written by Andrzej Pietrasiewicz and ported into +//! Rust by Daniel Almeida. + +#![allow(missing_docs)] +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +#![allow(unused_variables)] + +#[repr(C)] +#[derive(Debug, Clone)] +pub struct FrameMvContext { + pub joint: [u8; 3], + pub sign: [u8; 2], + pub classes: [[u8; 10]; 2], + pub class0_bit: [u8; 2], + pub bits: [[u8; 10]; 2], + pub class0_fr: [[[u8; 3]; 2]; 2], + pub fr: [[u8; 3]; 2], + pub class0_hp: [u8; 2], + pub hp: [u8; 2], +} + +#[repr(C)] +#[derive(Debug, Clone)] +pub struct FrameContext { + pub tx8: [[u8; 1]; 2], + pub tx16: [[u8; 2]; 2], + pub tx32: [[u8; 3]; 2], + pub coef: [[[[[[u8; 3]; 6]; 6]; 2]; 2]; 4], + pub skip: [u8; 3], + pub inter_mode: [[u8; 3]; 7], + pub interp_filter: [[u8; 2]; 4], + pub is_inter: [u8; 4], + pub comp_mode: [u8; 5], + pub single_ref: [[u8; 2]; 5], + pub comp_ref: [u8; 5], + pub y_mode: [[u8; 9]; 4], + pub uv_mode: [[u8; 9]; 10], + pub partition: [[u8; 3]; 16], + pub mv: FrameMvContext, +} + +#[repr(C)] +#[derive(Debug)] +pub struct FrameSymbolCounts<'a> { + pub partition: &'a mut [[u32; 4]; 16], + pub skip: &'a mut [[u32; 2]; 3], + pub intra_inter: &'a mut [[u32; 2]; 4], + pub tx32p: &'a mut [[u32; 4]; 2], + pub tx16p: &'a mut [[u32; 4]; 2], + pub tx8p: &'a mut [[u32; 2]; 2], + pub y_mode: &'a mut [[u32; 10]; 4], + pub uv_mode: &'a mut [[u32; 10]; 10], + pub comp: &'a mut [[u32; 2]; 5], + pub comp_ref: &'a mut [[u32; 2]; 5], + pub single_ref: &'a mut [[[u32; 2]; 2]; 5], + pub mv_mode: &'a mut [[u32; 4]; 7], + pub filter: &'a mut [[u32; 3]; 4], + pub mv_joint: &'a mut [u32; 4], + pub sign: &'a mut [[u32; 2]; 2], + pub classes: &'a mut [[u32; 11]; 2], + pub class0: &'a mut [[u32; 2]; 2], + pub bits: &'a mut [[[u32; 2]; 10]; 2], + pub class0_fp: &'a mut [[[u32; 4]; 2]; 2], + pub fp: &'a mut [[u32; 4]; 2], + pub class0_hp: &'a mut [[u32; 2]; 2], + pub hp: &'a mut [[u32; 2]; 2], + pub coeff: [[[[[&'a mut [u32; 3]; 6]; 6]; 2]; 2]; 4], + pub eob: [[[[[[&'a mut u32; 2]; 6]; 6]; 2]; 2]; 4], +} + +#[no_mangle] +pub static v4l2_vp9_kf_y_mode_prob_rs: [[[u8; 9]; 10]; 10] = [ + [ + /* above = dc */ + [137, 30, 42, 148, 151, 207, 70, 52, 91], /*left = dc */ + [92, 45, 102, 136, 116, 180, 74, 90, 100], /*left = v */ + [73, 32, 19, 187, 222, 215, 46, 34, 100], /*left = h */ + [91, 30, 32, 116, 121, 186, 93, 86, 94], /*left = d45 */ + [72, 35, 36, 149, 68, 206, 68, 63, 105], /*left = d135*/ + [73, 31, 28, 138, 57, 124, 55, 122, 151], /*left = d117*/ + [67, 23, 21, 140, 126, 197, 40, 37, 171], /*left = d153*/ + [86, 27, 28, 128, 154, 212, 45, 43, 53], /*left = d207*/ + [74, 32, 27, 107, 86, 160, 63, 134, 102], /*left = d63 */ + [59, 67, 44, 140, 161, 202, 78, 67, 119], /*left = tm */ + ], + [ + /* above = v */ + [63, 36, 126, 146, 123, 158, 60, 90, 96], /*left = dc */ + [43, 46, 168, 134, 107, 128, 69, 142, 92], /*left = v */ + [44, 29, 68, 159, 201, 177, 50, 57, 77], /*left = h */ + [58, 38, 76, 114, 97, 172, 78, 133, 92], /*left = d45 */ + [46, 41, 76, 140, 63, 184, 69, 112, 57], /*left = d135*/ + [38, 32, 85, 140, 46, 112, 54, 151, 133], /*left = d117*/ + [39, 27, 61, 131, 110, 175, 44, 75, 136], /*left = d153*/ + [52, 30, 74, 113, 130, 175, 51, 64, 58], /*left = d207*/ + [47, 35, 80, 100, 74, 143, 64, 163, 74], /*left = d63 */ + [36, 61, 116, 114, 128, 162, 80, 125, 82], /*left = tm */ + ], + [ + /* above = h */ + [82, 26, 26, 171, 208, 204, 44, 32, 105], /*left = dc */ + [55, 44, 68, 166, 179, 192, 57, 57, 108], /*left = v */ + [42, 26, 11, 199, 241, 228, 23, 15, 85], /*left = h */ + [68, 42, 19, 131, 160, 199, 55, 52, 83], /*left = d45 */ + [58, 50, 25, 139, 115, 232, 39, 52, 118], /*left = d135*/ + [50, 35, 33, 153, 104, 162, 64, 59, 131], /*left = d117*/ + [44, 24, 16, 150, 177, 202, 33, 19, 156], /*left = d153*/ + [55, 27, 12, 153, 203, 218, 26, 27, 49], /*left = d207*/ + [53, 49, 21, 110, 116, 168, 59, 80, 76], /*left = d63 */ + [38, 72, 19, 168, 203, 212, 50, 50, 107], /*left = tm */ + ], + [ + /* above = d45 */ + [103, 26, 36, 129, 132, 201, 83, 80, 93], /*left = dc */ + [59, 38, 83, 112, 103, 162, 98, 136, 90], /*left = v */ + [62, 30, 23, 158, 200, 207, 59, 57, 50], /*left = h */ + [67, 30, 29, 84, 86, 191, 102, 91, 59], /*left = d45 */ + [60, 32, 33, 112, 71, 220, 64, 89, 104], /*left = d135*/ + [53, 26, 34, 130, 56, 149, 84, 120, 103], /*left = d117*/ + [53, 21, 23, 133, 109, 210, 56, 77, 172], /*left = d153*/ + [77, 19, 29, 112, 142, 228, 55, 66, 36], /*left = d207*/ + [61, 29, 29, 93, 97, 165, 83, 175, 162], /*left = d63 */ + [47, 47, 43, 114, 137, 181, 100, 99, 95], /*left = tm */ + ], + [ + /* above = d135 */ + [69, 23, 29, 128, 83, 199, 46, 44, 101], /*left = dc */ + [53, 40, 55, 139, 69, 183, 61, 80, 110], /*left = v */ + [40, 29, 19, 161, 180, 207, 43, 24, 91], /*left = h */ + [60, 34, 19, 105, 61, 198, 53, 64, 89], /*left = d45 */ + [52, 31, 22, 158, 40, 209, 58, 62, 89], /*left = d135*/ + [44, 31, 29, 147, 46, 158, 56, 102, 198], /*left = d117*/ + [35, 19, 12, 135, 87, 209, 41, 45, 167], /*left = d153*/ + [55, 25, 21, 118, 95, 215, 38, 39, 66], /*left = d207*/ + [51, 38, 25, 113, 58, 164, 70, 93, 97], /*left = d63 */ + [47, 54, 34, 146, 108, 203, 72, 103, 151], /*left = tm */ + ], + [ + /* above = d117 */ + [64, 19, 37, 156, 66, 138, 49, 95, 133], /*left = dc */ + [46, 27, 80, 150, 55, 124, 55, 121, 135], /*left = v */ + [36, 23, 27, 165, 149, 166, 54, 64, 118], /*left = h */ + [53, 21, 36, 131, 63, 163, 60, 109, 81], /*left = d45 */ + [40, 26, 35, 154, 40, 185, 51, 97, 123], /*left = d135*/ + [35, 19, 34, 179, 19, 97, 48, 129, 124], /*left = d117*/ + [36, 20, 26, 136, 62, 164, 33, 77, 154], /*left = d153*/ + [45, 18, 32, 130, 90, 157, 40, 79, 91], /*left = d207*/ + [45, 26, 28, 129, 45, 129, 49, 147, 123], /*left = d63 */ + [38, 44, 51, 136, 74, 162, 57, 97, 121], /*left = tm */ + ], + [ + /* above = d153 */ + [75, 17, 22, 136, 138, 185, 32, 34, 166], /*left = dc */ + [56, 39, 58, 133, 117, 173, 48, 53, 187], /*left = v */ + [35, 21, 12, 161, 212, 207, 20, 23, 145], /*left = h */ + [56, 29, 19, 117, 109, 181, 55, 68, 112], /*left = d45 */ + [47, 29, 17, 153, 64, 220, 59, 51, 114], /*left = d135*/ + [46, 16, 24, 136, 76, 147, 41, 64, 172], /*left = d117*/ + [34, 17, 11, 108, 152, 187, 13, 15, 209], /*left = d153*/ + [51, 24, 14, 115, 133, 209, 32, 26, 104], /*left = d207*/ + [55, 30, 18, 122, 79, 179, 44, 88, 116], /*left = d63 */ + [37, 49, 25, 129, 168, 164, 41, 54, 148], /*left = tm */ + ], + [ + /* above = d207 */ + [82, 22, 32, 127, 143, 213, 39, 41, 70], /*left = dc */ + [62, 44, 61, 123, 105, 189, 48, 57, 64], /*left = v */ + [47, 25, 17, 175, 222, 220, 24, 30, 86], /*left = h */ + [68, 36, 17, 106, 102, 206, 59, 74, 74], /*left = d45 */ + [57, 39, 23, 151, 68, 216, 55, 63, 58], /*left = d135*/ + [49, 30, 35, 141, 70, 168, 82, 40, 115], /*left = d117*/ + [51, 25, 15, 136, 129, 202, 38, 35, 139], /*left = d153*/ + [68, 26, 16, 111, 141, 215, 29, 28, 28], /*left = d207*/ + [59, 39, 19, 114, 75, 180, 77, 104, 42], /*left = d63 */ + [40, 61, 26, 126, 152, 206, 61, 59, 93], /*left = tm */ + ], + [ + /* above = d63 */ + [78, 23, 39, 111, 117, 170, 74, 124, 94], /*left = dc */ + [48, 34, 86, 101, 92, 146, 78, 179, 134], /*left = v */ + [47, 22, 24, 138, 187, 178, 68, 69, 59], /*left = h */ + [56, 25, 33, 105, 112, 187, 95, 177, 129], /*left = d45 */ + [48, 31, 27, 114, 63, 183, 82, 116, 56], /*left = d135*/ + [43, 28, 37, 121, 63, 123, 61, 192, 169], /*left = d117*/ + [42, 17, 24, 109, 97, 177, 56, 76, 122], /*left = d153*/ + [58, 18, 28, 105, 139, 182, 70, 92, 63], /*left = d207*/ + [46, 23, 32, 74, 86, 150, 67, 183, 88], /*left = d63 */ + [36, 38, 48, 92, 122, 165, 88, 137, 91], /*left = tm */ + ], + [ + /* above = tm */ + [65, 70, 60, 155, 159, 199, 61, 60, 81], /*left = dc */ + [44, 78, 115, 132, 119, 173, 71, 112, 93], /*left = v */ + [39, 38, 21, 184, 227, 206, 42, 32, 64], /*left = h */ + [58, 47, 36, 124, 137, 193, 80, 82, 78], /*left = d45 */ + [49, 50, 35, 144, 95, 205, 63, 78, 59], /*left = d135*/ + [41, 53, 52, 148, 71, 142, 65, 128, 51], /*left = d117*/ + [40, 36, 28, 143, 143, 202, 40, 55, 137], /*left = d153*/ + [52, 34, 29, 129, 183, 227, 42, 35, 43], /*left = d207*/ + [42, 44, 44, 104, 105, 164, 64, 130, 80], /*left = d63 */ + [43, 81, 53, 140, 169, 204, 68, 84, 72], /*left = tm */ + ], +]; + +#[no_mangle] +pub static v4l2_vp9_kf_partition_probs_rs: [[u8; 3]; 16] = [ + /* 8x8 -> 4x4 */ + [158, 97, 94], /* a/l both not split */ + [93, 24, 99], /* a split, l not split */ + [85, 119, 44], /* l split, a not split */ + [62, 59, 67], /* a/l both split */ + /* 16x16 -> 8x8 */ + [149, 53, 53], /* a/l both not split */ + [94, 20, 48], /* a split, l not split */ + [83, 53, 24], /* l split, a not split */ + [52, 18, 18], /* a/l both split */ + /* 32x32 -> 16x16 */ + [150, 40, 39], /* a/l both not split */ + [78, 12, 26], /* a split, l not split */ + [67, 33, 11], /* l split, a not split */ + [24, 7, 5], /* a/l both split */ + /* 64x64 -> 32x32 */ + [174, 35, 49], /* a/l both not split */ + [68, 11, 27], /* a split, l not split */ + [57, 15, 9], /* l split, a not split */ + [12, 3, 3], /* a/l both split */ +]; + +#[no_mangle] +pub static v4l2_vp9_kf_uv_mode_prob_rs: [[u8; 9]; 10] = [ + [144, 11, 54, 157, 195, 130, 46, 58, 108], /* y = dc */ + [118, 15, 123, 148, 131, 101, 44, 93, 131], /* y = v */ + [113, 12, 23, 188, 226, 142, 26, 32, 125], /* y = h */ + [120, 11, 50, 123, 163, 135, 64, 77, 103], /* y = d45 */ + [113, 9, 36, 155, 111, 157, 32, 44, 161], /* y = d135 */ + [116, 9, 55, 176, 76, 96, 37, 61, 149], /* y = d117 */ + [115, 9, 28, 141, 161, 167, 21, 25, 193], /* y = d153 */ + [120, 12, 32, 145, 195, 142, 32, 38, 86], /* y = d207 */ + [116, 12, 64, 120, 140, 125, 49, 115, 121], /* y = d63 */ + [102, 19, 66, 162, 182, 122, 35, 59, 128], /* y = tm */ +]; + +#[no_mangle] +pub static v4l2_vp9_default_probs_rs: FrameContext = FrameContext { + tx8: [[100], [66]], + tx16: [[20, 152], [15, 101]], + tx32: [[3, 136, 37], [5, 52, 13]], + coef: [ + [ + /* tx 4x4 */ + [ + /* block Type 0 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [195, 29, 183], + [84, 49, 136], + [8, 42, 71], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [31, 107, 169], + [35, 99, 159], + [17, 82, 140], + [8, 66, 114], + [2, 44, 76], + [1, 19, 32], + ], + [ + /* Coeff Band 2 */ + [40, 132, 201], + [29, 114, 187], + [13, 91, 157], + [7, 75, 127], + [3, 58, 95], + [1, 28, 47], + ], + [ + /* Coeff Band 3 */ + [69, 142, 221], + [42, 122, 201], + [15, 91, 159], + [6, 67, 121], + [1, 42, 77], + [1, 17, 31], + ], + [ + /* Coeff Band 4 */ + [102, 148, 228], + [67, 117, 204], + [17, 82, 154], + [6, 59, 114], + [2, 39, 75], + [1, 15, 29], + ], + [ + /* Coeff Band 5 */ + [156, 57, 233], + [119, 57, 212], + [58, 48, 163], + [29, 40, 124], + [12, 30, 81], + [3, 12, 31], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [191, 107, 226], + [124, 117, 204], + [25, 99, 155], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [29, 148, 210], + [37, 126, 194], + [8, 93, 157], + [2, 68, 118], + [1, 39, 69], + [1, 17, 33], + ], + [ + /* Coeff Band 2 */ + [41, 151, 213], + [27, 123, 193], + [3, 82, 144], + [1, 58, 105], + [1, 32, 60], + [1, 13, 26], + ], + [ + /* Coeff Band 3 */ + [59, 159, 220], + [23, 126, 198], + [4, 88, 151], + [1, 66, 114], + [1, 38, 71], + [1, 18, 34], + ], + [ + /* Coeff Band 4 */ + [114, 136, 232], + [51, 114, 207], + [11, 83, 155], + [3, 56, 105], + [1, 33, 65], + [1, 17, 34], + ], + [ + /* Coeff Band 5 */ + [149, 65, 234], + [121, 57, 215], + [61, 49, 166], + [28, 36, 114], + [12, 25, 76], + [3, 16, 42], + ], + ], + ], + [ + /* block Type 1 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [214, 49, 220], + [132, 63, 188], + [42, 65, 137], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [85, 137, 221], + [104, 131, 216], + [49, 111, 192], + [21, 87, 155], + [2, 49, 87], + [1, 16, 28], + ], + [ + /* Coeff Band 2 */ + [89, 163, 230], + [90, 137, 220], + [29, 100, 183], + [10, 70, 135], + [2, 42, 81], + [1, 17, 33], + ], + [ + /* Coeff Band 3 */ + [108, 167, 237], + [55, 133, 222], + [15, 97, 179], + [4, 72, 135], + [1, 45, 85], + [1, 19, 38], + ], + [ + /* Coeff Band 4 */ + [124, 146, 240], + [66, 124, 224], + [17, 88, 175], + [4, 58, 122], + [1, 36, 75], + [1, 18, 37], + ], + [ + /* Coeff Band 5 */ + [141, 79, 241], + [126, 70, 227], + [66, 58, 182], + [30, 44, 136], + [12, 34, 96], + [2, 20, 47], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [229, 99, 249], + [143, 111, 235], + [46, 109, 192], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [82, 158, 236], + [94, 146, 224], + [25, 117, 191], + [9, 87, 149], + [3, 56, 99], + [1, 33, 57], + ], + [ + /* Coeff Band 2 */ + [83, 167, 237], + [68, 145, 222], + [10, 103, 177], + [2, 72, 131], + [1, 41, 79], + [1, 20, 39], + ], + [ + /* Coeff Band 3 */ + [99, 167, 239], + [47, 141, 224], + [10, 104, 178], + [2, 73, 133], + [1, 44, 85], + [1, 22, 47], + ], + [ + /* Coeff Band 4 */ + [127, 145, 243], + [71, 129, 228], + [17, 93, 177], + [3, 61, 124], + [1, 41, 84], + [1, 21, 52], + ], + [ + /* Coeff Band 5 */ + [157, 78, 244], + [140, 72, 231], + [69, 58, 184], + [31, 44, 137], + [14, 38, 105], + [8, 23, 61], + ], + ], + ], + ], + [ + /* tx 8x8 */ + [ + /* block Type 0 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [125, 34, 187], + [52, 41, 133], + [6, 31, 56], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [37, 109, 153], + [51, 102, 147], + [23, 87, 128], + [8, 67, 101], + [1, 41, 63], + [1, 19, 29], + ], + [ + /* Coeff Band 2 */ + [31, 154, 185], + [17, 127, 175], + [6, 96, 145], + [2, 73, 114], + [1, 51, 82], + [1, 28, 45], + ], + [ + /* Coeff Band 3 */ + [23, 163, 200], + [10, 131, 185], + [2, 93, 148], + [1, 67, 111], + [1, 41, 69], + [1, 14, 24], + ], + [ + /* Coeff Band 4 */ + [29, 176, 217], + [12, 145, 201], + [3, 101, 156], + [1, 69, 111], + [1, 39, 63], + [1, 14, 23], + ], + [ + /* Coeff Band 5 */ + [57, 192, 233], + [25, 154, 215], + [6, 109, 167], + [3, 78, 118], + [1, 48, 69], + [1, 21, 29], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [202, 105, 245], + [108, 106, 216], + [18, 90, 144], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [33, 172, 219], + [64, 149, 206], + [14, 117, 177], + [5, 90, 141], + [2, 61, 95], + [1, 37, 57], + ], + [ + /* Coeff Band 2 */ + [33, 179, 220], + [11, 140, 198], + [1, 89, 148], + [1, 60, 104], + [1, 33, 57], + [1, 12, 21], + ], + [ + /* Coeff Band 3 */ + [30, 181, 221], + [8, 141, 198], + [1, 87, 145], + [1, 58, 100], + [1, 31, 55], + [1, 12, 20], + ], + [ + /* Coeff Band 4 */ + [32, 186, 224], + [7, 142, 198], + [1, 86, 143], + [1, 58, 100], + [1, 31, 55], + [1, 12, 22], + ], + [ + /* Coeff Band 5 */ + [57, 192, 227], + [20, 143, 204], + [3, 96, 154], + [1, 68, 112], + [1, 42, 69], + [1, 19, 32], + ], + ], + ], + [ + /* block Type 1 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [212, 35, 215], + [113, 47, 169], + [29, 48, 105], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [74, 129, 203], + [106, 120, 203], + [49, 107, 178], + [19, 84, 144], + [4, 50, 84], + [1, 15, 25], + ], + [ + /* Coeff Band 2 */ + [71, 172, 217], + [44, 141, 209], + [15, 102, 173], + [6, 76, 133], + [2, 51, 89], + [1, 24, 42], + ], + [ + /* Coeff Band 3 */ + [64, 185, 231], + [31, 148, 216], + [8, 103, 175], + [3, 74, 131], + [1, 46, 81], + [1, 18, 30], + ], + [ + /* Coeff Band 4 */ + [65, 196, 235], + [25, 157, 221], + [5, 105, 174], + [1, 67, 120], + [1, 38, 69], + [1, 15, 30], + ], + [ + /* Coeff Band 5 */ + [65, 204, 238], + [30, 156, 224], + [7, 107, 177], + [2, 70, 124], + [1, 42, 73], + [1, 18, 34], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [225, 86, 251], + [144, 104, 235], + [42, 99, 181], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [85, 175, 239], + [112, 165, 229], + [29, 136, 200], + [12, 103, 162], + [6, 77, 123], + [2, 53, 84], + ], + [ + /* Coeff Band 2 */ + [75, 183, 239], + [30, 155, 221], + [3, 106, 171], + [1, 74, 128], + [1, 44, 76], + [1, 17, 28], + ], + [ + /* Coeff Band 3 */ + [73, 185, 240], + [27, 159, 222], + [2, 107, 172], + [1, 75, 127], + [1, 42, 73], + [1, 17, 29], + ], + [ + /* Coeff Band 4 */ + [62, 190, 238], + [21, 159, 222], + [2, 107, 172], + [1, 72, 122], + [1, 40, 71], + [1, 18, 32], + ], + [ + /* Coeff Band 5 */ + [61, 199, 240], + [27, 161, 226], + [4, 113, 180], + [1, 76, 129], + [1, 46, 80], + [1, 23, 41], + ], + ], + ], + ], + [ + /* tx 16x16 */ + [ + /* block Type 0 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [7, 27, 153], + [5, 30, 95], + [1, 16, 30], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [50, 75, 127], + [57, 75, 124], + [27, 67, 108], + [10, 54, 86], + [1, 33, 52], + [1, 12, 18], + ], + [ + /* Coeff Band 2 */ + [43, 125, 151], + [26, 108, 148], + [7, 83, 122], + [2, 59, 89], + [1, 38, 60], + [1, 17, 27], + ], + [ + /* Coeff Band 3 */ + [23, 144, 163], + [13, 112, 154], + [2, 75, 117], + [1, 50, 81], + [1, 31, 51], + [1, 14, 23], + ], + [ + /* Coeff Band 4 */ + [18, 162, 185], + [6, 123, 171], + [1, 78, 125], + [1, 51, 86], + [1, 31, 54], + [1, 14, 23], + ], + [ + /* Coeff Band 5 */ + [15, 199, 227], + [3, 150, 204], + [1, 91, 146], + [1, 55, 95], + [1, 30, 53], + [1, 11, 20], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [19, 55, 240], + [19, 59, 196], + [3, 52, 105], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [41, 166, 207], + [104, 153, 199], + [31, 123, 181], + [14, 101, 152], + [5, 72, 106], + [1, 36, 52], + ], + [ + /* Coeff Band 2 */ + [35, 176, 211], + [12, 131, 190], + [2, 88, 144], + [1, 60, 101], + [1, 36, 60], + [1, 16, 28], + ], + [ + /* Coeff Band 3 */ + [28, 183, 213], + [8, 134, 191], + [1, 86, 142], + [1, 56, 96], + [1, 30, 53], + [1, 12, 20], + ], + [ + /* Coeff Band 4 */ + [20, 190, 215], + [4, 135, 192], + [1, 84, 139], + [1, 53, 91], + [1, 28, 49], + [1, 11, 20], + ], + [ + /* Coeff Band 5 */ + [13, 196, 216], + [2, 137, 192], + [1, 86, 143], + [1, 57, 99], + [1, 32, 56], + [1, 13, 24], + ], + ], + ], + [ + /* block Type 1 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [211, 29, 217], + [96, 47, 156], + [22, 43, 87], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [78, 120, 193], + [111, 116, 186], + [46, 102, 164], + [15, 80, 128], + [2, 49, 76], + [1, 18, 28], + ], + [ + /* Coeff Band 2 */ + [71, 161, 203], + [42, 132, 192], + [10, 98, 150], + [3, 69, 109], + [1, 44, 70], + [1, 18, 29], + ], + [ + /* Coeff Band 3 */ + [57, 186, 211], + [30, 140, 196], + [4, 93, 146], + [1, 62, 102], + [1, 38, 65], + [1, 16, 27], + ], + [ + /* Coeff Band 4 */ + [47, 199, 217], + [14, 145, 196], + [1, 88, 142], + [1, 57, 98], + [1, 36, 62], + [1, 15, 26], + ], + [ + /* Coeff Band 5 */ + [26, 219, 229], + [5, 155, 207], + [1, 94, 151], + [1, 60, 104], + [1, 36, 62], + [1, 16, 28], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [233, 29, 248], + [146, 47, 220], + [43, 52, 140], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [100, 163, 232], + [179, 161, 222], + [63, 142, 204], + [37, 113, 174], + [26, 89, 137], + [18, 68, 97], + ], + [ + /* Coeff Band 2 */ + [85, 181, 230], + [32, 146, 209], + [7, 100, 164], + [3, 71, 121], + [1, 45, 77], + [1, 18, 30], + ], + [ + /* Coeff Band 3 */ + [65, 187, 230], + [20, 148, 207], + [2, 97, 159], + [1, 68, 116], + [1, 40, 70], + [1, 14, 29], + ], + [ + /* Coeff Band 4 */ + [40, 194, 227], + [8, 147, 204], + [1, 94, 155], + [1, 65, 112], + [1, 39, 66], + [1, 14, 26], + ], + [ + /* Coeff Band 5 */ + [16, 208, 228], + [3, 151, 207], + [1, 98, 160], + [1, 67, 117], + [1, 41, 74], + [1, 17, 31], + ], + ], + ], + ], + [ + /* tx 32x32 */ + [ + /* block Type 0 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [17, 38, 140], + [7, 34, 80], + [1, 17, 29], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [37, 75, 128], + [41, 76, 128], + [26, 66, 116], + [12, 52, 94], + [2, 32, 55], + [1, 10, 16], + ], + [ + /* Coeff Band 2 */ + [50, 127, 154], + [37, 109, 152], + [16, 82, 121], + [5, 59, 85], + [1, 35, 54], + [1, 13, 20], + ], + [ + /* Coeff Band 3 */ + [40, 142, 167], + [17, 110, 157], + [2, 71, 112], + [1, 44, 72], + [1, 27, 45], + [1, 11, 17], + ], + [ + /* Coeff Band 4 */ + [30, 175, 188], + [9, 124, 169], + [1, 74, 116], + [1, 48, 78], + [1, 30, 49], + [1, 11, 18], + ], + [ + /* Coeff Band 5 */ + [10, 222, 223], + [2, 150, 194], + [1, 83, 128], + [1, 48, 79], + [1, 27, 45], + [1, 11, 17], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [36, 41, 235], + [29, 36, 193], + [10, 27, 111], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [85, 165, 222], + [177, 162, 215], + [110, 135, 195], + [57, 113, 168], + [23, 83, 120], + [10, 49, 61], + ], + [ + /* Coeff Band 2 */ + [85, 190, 223], + [36, 139, 200], + [5, 90, 146], + [1, 60, 103], + [1, 38, 65], + [1, 18, 30], + ], + [ + /* Coeff Band 3 */ + [72, 202, 223], + [23, 141, 199], + [2, 86, 140], + [1, 56, 97], + [1, 36, 61], + [1, 16, 27], + ], + [ + /* Coeff Band 4 */ + [55, 218, 225], + [13, 145, 200], + [1, 86, 141], + [1, 57, 99], + [1, 35, 61], + [1, 13, 22], + ], + [ + /* Coeff Band 5 */ + [15, 235, 212], + [1, 132, 184], + [1, 84, 139], + [1, 57, 97], + [1, 34, 56], + [1, 14, 23], + ], + ], + ], + [ + /* block Type 1 */ + [ + /* Intra */ + [ + /* Coeff Band 0 */ + [181, 21, 201], + [61, 37, 123], + [10, 38, 71], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [47, 106, 172], + [95, 104, 173], + [42, 93, 159], + [18, 77, 131], + [4, 50, 81], + [1, 17, 23], + ], + [ + /* Coeff Band 2 */ + [62, 147, 199], + [44, 130, 189], + [28, 102, 154], + [18, 75, 115], + [2, 44, 65], + [1, 12, 19], + ], + [ + /* Coeff Band 3 */ + [55, 153, 210], + [24, 130, 194], + [3, 93, 146], + [1, 61, 97], + [1, 31, 50], + [1, 10, 16], + ], + [ + /* Coeff Band 4 */ + [49, 186, 223], + [17, 148, 204], + [1, 96, 142], + [1, 53, 83], + [1, 26, 44], + [1, 11, 17], + ], + [ + /* Coeff Band 5 */ + [13, 217, 212], + [2, 136, 180], + [1, 78, 124], + [1, 50, 83], + [1, 29, 49], + [1, 14, 23], + ], + ], + [ + /* Inter */ + [ + /* Coeff Band 0 */ + [197, 13, 247], + [82, 17, 222], + [25, 17, 162], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + [ + /* Coeff Band 1 */ + [126, 186, 247], + [234, 191, 243], + [176, 177, 234], + [104, 158, 220], + [66, 128, 186], + [55, 90, 137], + ], + [ + /* Coeff Band 2 */ + [111, 197, 242], + [46, 158, 219], + [9, 104, 171], + [2, 65, 125], + [1, 44, 80], + [1, 17, 91], + ], + [ + /* Coeff Band 3 */ + [104, 208, 245], + [39, 168, 224], + [3, 109, 162], + [1, 79, 124], + [1, 50, 102], + [1, 43, 102], + ], + [ + /* Coeff Band 4 */ + [84, 220, 246], + [31, 177, 231], + [2, 115, 180], + [1, 79, 134], + [1, 55, 77], + [1, 60, 79], + ], + [ + /* Coeff Band 5 */ + [43, 243, 240], + [8, 180, 217], + [1, 115, 166], + [1, 84, 121], + [1, 51, 67], + [1, 16, 6], + ], + ], + ], + ], + ], + + skip: [192, 128, 64], + inter_mode: [ + [2, 173, 34], + [7, 145, 85], + [7, 166, 63], + [7, 94, 66], + [8, 64, 46], + [17, 81, 31], + [25, 29, 30], + ], + interp_filter: [[235, 162], [36, 255], [34, 3], [149, 144]], + is_inter: [9, 102, 187, 225], + comp_mode: [239, 183, 119, 96, 41], + single_ref: [[33, 16], [77, 74], [142, 142], [172, 170], [238, 247]], + comp_ref: [50, 126, 123, 221, 226], + y_mode: [ + [65, 32, 18, 144, 162, 194, 41, 51, 98], + [132, 68, 18, 165, 217, 196, 45, 40, 78], + [173, 80, 19, 176, 240, 193, 64, 35, 46], + [221, 135, 38, 194, 248, 121, 96, 85, 29], + ], + uv_mode: [ + [120, 7, 76, 176, 208, 126, 28, 54, 103], /* y dc */ + [48, 12, 154, 155, 139, 90, 34, 117, 119], /* y v */ + [67, 6, 25, 204, 243, 158, 13, 21, 96], /* y h */ + [97, 5, 44, 131, 176, 139, 48, 68, 97], /* y d45 */ + [83, 5, 42, 156, 111, 152, 26, 49, 152], /* y d135 */ + [80, 5, 58, 178, 74, 83, 33, 62, 145], /* y d117 */ + [86, 5, 32, 154, 192, 168, 14, 22, 163], /* y d153 */ + [85, 5, 32, 156, 216, 148, 19, 29, 73], /* y d207 */ + [77, 7, 64, 116, 132, 122, 37, 126, 120], /* y d63 */ + [101, 21, 107, 181, 192, 103, 19, 67, 125], /* y tm */ + ], + partition: [ + /* 8x8 -> 4x4 */ + [199, 122, 141], /* a/l both not split */ + [147, 63, 159], /* a split, l not split */ + [148, 133, 118], /* l split, a not split */ + [121, 104, 114], /* a/l both split */ + /* 16x16 -> 8x8 */ + [174, 73, 87], /* a/l both not split */ + [92, 41, 83], /* a split, l not split */ + [82, 99, 50], /* l split, a not split */ + [53, 39, 39], /* a/l both split */ + /* 32x32 -> 16x16 */ + [177, 58, 59], /* a/l both not split */ + [68, 26, 63], /* a split, l not split */ + [52, 79, 25], /* l split, a not split */ + [17, 14, 12], /* a/l both split */ + /* 64x64 -> 32x32 */ + [222, 34, 30], /* a/l both not split */ + [72, 16, 44], /* a split, l not split */ + [58, 32, 12], /* l split, a not split */ + [10, 7, 6], /* a/l both split */ + ], + mv: FrameMvContext { + joint: [32, 64, 96], + sign: [128, 128], + classes: [ + [224, 144, 192, 168, 192, 176, 192, 198, 198, 245], + [216, 128, 176, 160, 176, 176, 192, 198, 198, 208], + ], + class0_bit: [216, 208], + bits: [ + [136, 140, 148, 160, 176, 192, 224, 234, 234, 240], + [136, 140, 148, 160, 176, 192, 224, 234, 234, 240], + ], + class0_fr: [ + [[128, 128, 64], [96, 112, 64]], + [[128, 128, 64], [96, 112, 64]], + ], + fr: [[64, 96, 64], [64, 96, 64]], + class0_hp: [160, 160], + hp: [128, 128], + }, +}; + +pub fn fw_update_probs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, + dec_params: &bindings::v4l2_ctrl_vp9_frame, +) { + if u32::from(deltas.tx_mode) == bindings::V4L2_VP9_TX_MODE_SELECT { + update_tx_probs(probs, deltas); + } + + update_coeff_probs(probs, deltas, dec_params); + update_skip_probs(probs, deltas); + + if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0 + || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0 + { + return; + } + + update_inter_mode_probs(probs, deltas); + + if u32::from(dec_params.interpolation_filter) == bindings::V4L2_VP9_INTERP_FILTER_SWITCHABLE { + update_interp_filter_probs(probs, deltas); + } + + update_is_inter_probs(probs, deltas); + update_frame_reference_mode_probs(dec_params.reference_mode.into(), probs, deltas); + + update_y_mode_probs(probs, deltas); + update_partition_probs(probs, deltas); + update_mv_probs(probs, deltas, dec_params); +} + +pub fn reset_frame_ctx( + dec_params: &bindings::v4l2_ctrl_vp9_frame, + frame_context: &mut [FrameContext; 4], +) -> u8 { + let mut fctx_idx = dec_params.frame_context_idx; + + if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0 + || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0 + || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT != 0 + { + /* + * setup_past_independence() + * We do nothing here. Instead of storing default probs in some intermediate + * location and then copying from that location to appropriate contexts + * in save_probs() below, we skip that step and save default probs directly + * to appropriate contexts. + */ + + if dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0 + || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT != 0 + || u32::from(dec_params.reset_frame_context) == bindings::V4L2_VP9_RESET_FRAME_CTX_ALL + { + for i in 0..4 { + /* save_probs(i) */ + frame_context[i] = v4l2_vp9_default_probs_rs.clone(); + } + } else if u32::from(dec_params.reset_frame_context) + == bindings::V4L2_VP9_RESET_FRAME_CTX_SPEC + { + /* save_probs(fctx_idx) */ + frame_context[usize::from(fctx_idx)] = v4l2_vp9_default_probs_rs.clone(); + } + + fctx_idx = 0; + } + + fctx_idx +} + +pub fn adapt_coef_probs( + probs: &mut FrameContext, + counts: &mut FrameSymbolCounts<'_>, + use_128: bool, + frame_is_intra: bool, +) { + if frame_is_intra { + _adapt_coef_probs(probs, counts, 112); + } else { + if use_128 { + _adapt_coef_probs(probs, counts, 128); + } else { + _adapt_coef_probs(probs, counts, 112); + } + } +} + +pub fn adapt_noncoef_probs( + probs: &mut FrameContext, + counts: &mut FrameSymbolCounts<'_>, + reference_mode: u8, + interpolation_filter: u8, + tx_mode: u8, + flags: u32, +) { + for i in 0..probs.is_inter.len() { + probs.is_inter[i] = adapt_prob(probs.is_inter[i], counts.intra_inter[i]); + } + + for i in 0..probs.comp_mode.len() { + probs.comp_mode[i] = adapt_prob(probs.comp_mode[i], counts.comp[i]); + } + + for i in 0..probs.comp_ref.len() { + probs.comp_ref[i] = adapt_prob(probs.comp_ref[i], counts.comp_ref[i]); + } + + if u32::from(reference_mode) != bindings::V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE { + for i in 0..probs.single_ref.len() { + for j in 0..probs.single_ref[0].len() { + probs.single_ref[i][j] = + adapt_prob(probs.single_ref[i][j], counts.single_ref[i][j]); + } + } + } + + for i in 0..probs.inter_mode.len() { + adapt_probs_variant_c(&mut probs.inter_mode[i], &counts.mv_mode[i]); + } + + for i in 0..probs.y_mode.len() { + adapt_probs_variant_d(&mut probs.y_mode[i], &counts.y_mode[i]); + } + + for i in 0..probs.uv_mode.len() { + adapt_probs_variant_d(&mut probs.uv_mode[i], &counts.uv_mode[i]); + } + + for i in 0..probs.partition.len() { + adapt_probs_variant_e(&mut probs.partition[i], &counts.partition[i]); + } + + for i in 0..probs.skip.len() { + probs.skip[i] = adapt_prob(probs.skip[i], counts.skip[i]); + } + + if u32::from(interpolation_filter) == bindings::V4L2_VP9_INTERP_FILTER_SWITCHABLE { + for i in 0..probs.interp_filter.len() { + adapt_probs_variant_f(&mut probs.interp_filter[i], &counts.filter[i]); + } + } + + if u32::from(tx_mode) == bindings::V4L2_VP9_TX_MODE_SELECT { + for i in 0..probs.tx8.len() { + adapt_probs_variant_b(&mut probs.tx8[i], &counts.tx8p[i]); + adapt_probs_variant_f(&mut probs.tx16[i], &counts.tx16p[i]); + adapt_probs_variant_e(&mut probs.tx32[i], &counts.tx32p[i]); + } + } + + adapt_probs_variant_e(&mut probs.mv.joint, counts.mv_joint); + + for i in 0..probs.mv.sign.len() { + probs.mv.sign[i] = adapt_prob(probs.mv.sign[i], counts.sign[i]); + + adapt_probs_variant_g(&mut probs.mv.classes[i], &counts.classes[i]); + + probs.mv.class0_bit[i] = adapt_prob(probs.mv.class0_bit[i], counts.class0[i]); + + for j in 0..probs.mv.bits[0].len() { + probs.mv.bits[i][j] = adapt_prob(probs.mv.bits[i][j], counts.bits[i][j]); + } + + for j in 0..probs.mv.class0_fr[0].len() { + adapt_probs_variant_e(&mut probs.mv.class0_fr[i][j], &counts.class0_fp[i][j]); + } + + adapt_probs_variant_e(&mut probs.mv.fr[i], &counts.fp[i]); + + if flags & bindings::V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV == 0 { + continue; + } + + probs.mv.class0_hp[i] = adapt_prob(probs.mv.class0_hp[i], counts.class0_hp[i]); + + probs.mv.hp[i] = adapt_prob(probs.mv.hp[i], counts.hp[i]); + } +} + +pub fn seg_feat_enabled(feature_enabled: &[u8; 8], feature: u32, segid: u32) -> bool { + let mask = 1 << feature; + feature_enabled[segid as usize] & mask != 0 +} + +fn fastdiv(dividend: u32, divisor: u32) -> u32 { + const fn inv() -> [u32; SZ] { + let mut ret = [0; SZ]; + let mut i = 2; + let n = SZ + 1; + + while i <= n { + ret[i - 2] = (((1u64 << 32) + (i as u64 - 1)) / i as u64) as u32; + i += 1; + } + + ret + } + const SZ: usize = 255; + const INV: [u32; SZ] = inv::(); + if divisor - 2 >= SZ as u32 { + crate::pr_warn!("fastdiv: divisor {} too large", divisor); + return dividend; + } + + if divisor == 0 { + 0 + } else if divisor == 1 { + dividend + } else { + let ret = (u64::from(dividend) * u64::from(INV[divisor as usize - 2])) >> 32; + ret as u32 + } +} + +fn inv_recenter_nonneg(v: i32, m: i32) -> i32 { + if v > 2 * m { + v + } else if (v & 1) != 0 { + m - ((v + 1) >> 1) + } else { + m + (v >> 1) + } +} + +fn update_prob(delta: i32, prob: i32) -> i32 { + if delta == 0 { + prob + } else if prob <= 128 { + 1 + inv_recenter_nonneg(delta, prob - 1) + } else { + 255 - inv_recenter_nonneg(delta, 255 - prob) + } +} + +fn update_tx_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) { + for i in 0..probs.tx8.len() { + let p8x8 = &mut probs.tx8[i]; + let p16x16 = &mut probs.tx16[i]; + let p32x32 = &mut probs.tx32[i]; + + let d8x8 = &deltas.tx8[i]; + let d16x16 = &deltas.tx16[i]; + let d32x32 = &deltas.tx32[i]; + + p8x8[0] = update_prob(d8x8[0].into(), p8x8[0].into()) as u8; + p16x16[0] = update_prob(d16x16[0].into(), p16x16[0].into()) as u8; + p16x16[1] = update_prob(d16x16[1].into(), p16x16[1].into()) as u8; + p32x32[0] = update_prob(d32x32[0].into(), p32x32[0].into()) as u8; + p32x32[1] = update_prob(d32x32[1].into(), p32x32[1].into()) as u8; + p32x32[2] = update_prob(d32x32[2].into(), p32x32[2].into()) as u8; + } +} + +macro_rules! BAND_6 { + ($band:expr) => { + if $band == 0 { + 3 + } else { + 6 + } + }; +} + +fn update_coeff(deltas: &[[[u8; 3]; 6]; 6], probs: &mut [[[u8; 3]; 6]; 6]) { + for l in 0..6 { + for m in 0..BAND_6!(l) { + let p = &mut probs[l][m]; + let d = &deltas[l][m]; + + for n in 0..3 { + p[n] = update_prob(d[n].into(), p[n].into()) as u8; + } + } + } +} + +fn update_coeff_probs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, + dec_params: &bindings::v4l2_ctrl_vp9_frame, +) { + for i in 0..probs.coef.len() { + for j in 0..probs.coef[0].len() { + for k in 0..probs.coef[0][0].len() { + update_coeff(&deltas.coef[i][j][k], &mut probs.coef[i][j][k]); + } + } + + if usize::from(deltas.tx_mode) == i { + break; + } + } +} + +fn update_skip_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) { + for i in 0..probs.skip.len() { + probs.skip[i] = update_prob(deltas.skip[i].into(), probs.skip[i].into()) as u8; + } +} + +fn update_inter_mode_probs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, +) { + for i in 0..probs.inter_mode.len() { + let p = &mut probs.inter_mode[i]; + let d = &deltas.inter_mode[i]; + + p[0] = update_prob(d[0].into(), p[0].into()) as u8; + p[1] = update_prob(d[1].into(), p[1].into()) as u8; + p[2] = update_prob(d[2].into(), p[2].into()) as u8; + } +} + +fn update_interp_filter_probs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, +) { + for i in 0..probs.interp_filter.len() { + let p = &mut probs.interp_filter[i]; + let d = &deltas.interp_filter[i]; + + p[0] = update_prob(d[0].into(), p[0].into()) as u8; + p[1] = update_prob(d[1].into(), p[1].into()) as u8; + } +} + +fn update_is_inter_probs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, +) { + for i in 0..probs.is_inter.len() { + probs.is_inter[i] = update_prob(deltas.is_inter[i].into(), probs.is_inter[i].into()) as u8; + } +} + +fn update_frame_reference_mode_probs( + reference_mode: u32, + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, +) { + if reference_mode == bindings::V4L2_VP9_REFERENCE_MODE_SELECT { + for i in 0..probs.comp_mode.len() { + probs.comp_mode[i] = + update_prob(deltas.comp_mode[i].into(), probs.comp_mode[i].into()) as u8; + } + } + + if reference_mode != bindings::V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE { + for i in 0..probs.single_ref.len() { + let p = &mut probs.single_ref[i]; + let d = &deltas.single_ref[i]; + + p[0] = update_prob(d[0].into(), p[0].into()) as u8; + p[1] = update_prob(d[1].into(), p[1].into()) as u8; + } + } + + if reference_mode != bindings::V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE { + for i in 0..probs.comp_ref.len() { + probs.comp_ref[i] = + update_prob(deltas.comp_ref[i].into(), probs.comp_ref[i].into()) as u8; + } + } +} + +fn update_y_mode_probs(probs: &mut FrameContext, deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr) { + for i in 0..probs.y_mode.len() { + for j in 0..probs.y_mode[0].len() { + probs.y_mode[i][j] = + update_prob(deltas.y_mode[i][j].into(), probs.y_mode[i][j].into()) as u8; + } + } +} + +fn update_partition_probs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, +) { + for i in 0..4 { + for j in 0..4 { + let p = &mut probs.partition[i * 4 + j]; + let d = deltas.partition[i * 4 + j]; + + p[0] = update_prob(d[0].into(), p[0].into()) as u8; + p[1] = update_prob(d[1].into(), p[1].into()) as u8; + p[2] = update_prob(d[2].into(), p[2].into()) as u8; + } + } +} + +fn update_mv_prob(delta: i32, prob: i32) -> i32 { + if delta == 0 { + prob + } else { + delta + } +} + +fn update_mv_probs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, + dec_params: &bindings::v4l2_ctrl_vp9_frame, +) { + let p = &mut probs.mv.joint; + let d = &deltas.mv.joint; + + p[0] = update_mv_prob(d[0].into(), p[0].into()) as u8; + p[1] = update_mv_prob(d[1].into(), p[1].into()) as u8; + p[2] = update_mv_prob(d[2].into(), p[2].into()) as u8; + + for i in 0..probs.mv.sign.len() { + let p = &mut probs.mv.sign; + let d = &deltas.mv.sign; + p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8; + + let len = probs.mv.classes[0].len(); + let p = &mut probs.mv.classes[i]; + let d = &deltas.mv.classes[i]; + for j in 0..len { + p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8; + } + + let p = &mut probs.mv.class0_bit; + let d = &deltas.mv.class0_bit; + p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8; + + let len = probs.mv.bits[0].len(); + let p = &mut probs.mv.bits[i]; + let d = &deltas.mv.bits[i]; + for j in 0..len { + p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8; + } + + let len = probs.mv.class0_fr[0].len(); + for j in 0..len { + let p = &mut probs.mv.class0_fr[i][j]; + let d = &deltas.mv.class0_fr[i][j]; + + p[0] = update_mv_prob(d[0].into(), p[0].into()) as u8; + p[1] = update_mv_prob(d[1].into(), p[1].into()) as u8; + p[2] = update_mv_prob(d[2].into(), p[2].into()) as u8; + } + + let len = probs.mv.fr[i].len(); + let p = &mut probs.mv.fr[i]; + let d = &deltas.mv.fr[i]; + for j in 0..len { + p[j] = update_mv_prob(d[j].into(), p[j].into()) as u8; + } + + if (dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV) != 0 { + let p = &mut probs.mv.class0_hp; + let d = &deltas.mv.class0_hp; + p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8; + + let p = &mut probs.mv.hp; + let d = &deltas.mv.hp; + p[i] = update_mv_prob(d[i].into(), p[i].into()) as u8; + } + } +} + +macro_rules! clamp { + ($val:expr, $min:expr, $max:expr) => { + if $val < $min { + $min + } else if $val > $max { + $max + } else { + $val + } + }; +} + +fn merge_prob(pre_prob: u8, ct0: u32, ct1: u32, count_sat: u32, max_update_factor: u32) -> u8 { + let den = ct0 + ct1; + + if den == 0 { + /* + * prob = 128, count = 0, update_factor = 0 + * Round2's argument: pre_prob * 256 + * (pre_prob * 256 + 128) >> 8 == pre_prob + */ + return pre_prob; + } + + let prob = clamp!(((ct0 << 8) + (den >> 1)) / den, 1, 255); + let count = core::cmp::min(den, count_sat); + let factor = fastdiv(max_update_factor * count, count_sat); + + let prob = i64::from(prob); + let count = i64::from(count); + let factor = i64::from(factor); + let pre_prob = i64::from(pre_prob); + + /* + * Round2(pre_prob * (256 - factor) + prob * factor, 8) + * Round2(pre_prob * 256 + (prob - pre_prob) * factor, 8) + * (pre_prob * 256 >> 8) + (((prob - pre_prob) * factor + 128) >> 8) + */ + (pre_prob + (((prob - pre_prob) * factor + 128) >> 8)) + .try_into() + .unwrap() +} + +fn noncoef_merge_prob(pre_prob: u8, ct0: u32, ct1: u32) -> u8 { + merge_prob(pre_prob, ct0, ct1, 20, 128) +} + +/* 8.4.2 Merge probs process */ +/* + * merge_probs() is a recursive function in the spec. We avoid recursion in the kernel. + * That said, the "tree" parameter of merge_probs() controls how deep the recursion goes. + * It turns out that in all cases the recursive calls boil down to a short-ish series + * of merge_prob() invocations (note no "s"). + * + * Variant A + * --------- + * merge_probs(small_token_tree, 2): + * merge_prob(p[1], c[0], c[1] + c[2]) + * merge_prob(p[2], c[1], c[2]) + * + * Variant B + * --------- + * merge_probs(binary_tree, 0) or + * merge_probs(tx_size_8_tree, 0): + * merge_prob(p[0], c[0], c[1]) + * + * Variant C + * --------- + * merge_probs(inter_mode_tree, 0): + * merge_prob(p[0], c[2], c[1] + c[0] + c[3]) + * merge_prob(p[1], c[0], c[1] + c[3]) + * merge_prob(p[2], c[1], c[3]) + * + * Variant D + * --------- + * merge_probs(intra_mode_tree, 0): + * merge_prob(p[0], c[0], c[1] + ... + c[9]) + * merge_prob(p[1], c[9], c[1] + ... + c[8]) + * merge_prob(p[2], c[1], c[2] + ... + c[8]) + * merge_prob(p[3], c[2] + c[4] + c[5], c[3] + c[8] + c[6] + c[7]) + * merge_prob(p[4], c[2], c[4] + c[5]) + * merge_prob(p[5], c[4], c[5]) + * merge_prob(p[6], c[3], c[8] + c[6] + c[7]) + * merge_prob(p[7], c[8], c[6] + c[7]) + * merge_prob(p[8], c[6], c[7]) + * + * Variant E + * --------- + * merge_probs(partition_tree, 0) or + * merge_probs(tx_size_32_tree, 0) or + * merge_probs(mv_joint_tree, 0) or + * merge_probs(mv_fr_tree, 0): + * merge_prob(p[0], c[0], c[1] + c[2] + c[3]) + * merge_prob(p[1], c[1], c[2] + c[3]) + * merge_prob(p[2], c[2], c[3]) + * + * Variant F + * --------- + * merge_probs(interp_filter_tree, 0) or + * merge_probs(tx_size_16_tree, 0): + * merge_prob(p[0], c[0], c[1] + c[2]) + * merge_prob(p[1], c[1], c[2]) + * + * Variant G + * --------- + * merge_probs(mv_class_tree, 0): + * merge_prob(p[0], c[0], c[1] + ... + c[10]) + * merge_prob(p[1], c[1], c[2] + ... + c[10]) + * merge_prob(p[2], c[2] + c[3], c[4] + ... + c[10]) + * merge_prob(p[3], c[2], c[3]) + * merge_prob(p[4], c[4] + c[5], c[6] + ... + c[10]) + * merge_prob(p[5], c[4], c[5]) + * merge_prob(p[6], c[6], c[7] + ... + c[10]) + * merge_prob(p[7], c[7] + c[8], c[9] + c[10]) + * merge_prob(p[8], c[7], c[8]) + * merge_prob(p[9], c[9], [10]) + */ + +fn merge_probs_variant_a(p: &mut [u8], c: &[u32], count_sat: u32, update_factor: u32) { + p[1] = merge_prob(p[1], c[0], c[1] + c[2], count_sat, update_factor); + p[2] = merge_prob(p[2], c[1], c[2], count_sat, update_factor); +} + +fn merge_probs_variant_b(p: &mut [u8], c: &[u32], count_sat: u32, update_factor: u32) { + p[0] = merge_prob(p[0], c[0], c[1], count_sat, update_factor); +} + +fn merge_probs_variant_c(p: &mut [u8], c: &[u32]) { + p[0] = noncoef_merge_prob(p[0], c[2], c[1] + c[0] + c[3]); + p[1] = noncoef_merge_prob(p[1], c[0], c[1] + c[3]); + p[2] = noncoef_merge_prob(p[2], c[1], c[3]); +} + +fn merge_probs_variant_d(p: &mut [u8], c: &[u32]) { + let mut sum: u32 = c[1..=9].iter().sum(); + + p[0] = noncoef_merge_prob(p[0], c[0], sum); + sum -= c[9]; + p[1] = noncoef_merge_prob(p[1], c[9], sum); + sum -= c[1]; + p[2] = noncoef_merge_prob(p[2], c[1], sum); + let mut s2 = c[2] + c[4] + c[5]; + sum -= s2; + p[3] = noncoef_merge_prob(p[3], s2, sum); + s2 -= c[2]; + p[4] = noncoef_merge_prob(p[4], c[2], s2); + p[5] = noncoef_merge_prob(p[5], c[4], c[5]); + sum -= c[3]; + p[6] = noncoef_merge_prob(p[6], c[3], sum); + sum -= c[8]; + p[7] = noncoef_merge_prob(p[7], c[8], sum); + p[8] = noncoef_merge_prob(p[8], c[6], c[7]); +} + +fn merge_probs_variant_e(p: &mut [u8], c: &[u32]) { + p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2] + c[3]); + p[1] = noncoef_merge_prob(p[1], c[1], c[2] + c[3]); + p[2] = noncoef_merge_prob(p[2], c[2], c[3]); +} + +fn merge_probs_variant_f(p: &mut [u8], c: &[u32]) { + p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2]); + p[1] = noncoef_merge_prob(p[1], c[1], c[2]); +} + +fn merge_probs_variant_g(p: &mut [u8], c: &[u32]) { + let mut sum: u32 = c[1..=10].iter().sum(); + p[0] = noncoef_merge_prob(p[0], c[0], sum); + sum -= c[1]; + p[1] = noncoef_merge_prob(p[1], c[1], sum); + sum -= c[2] + c[3]; + p[2] = noncoef_merge_prob(p[2], c[2] + c[3], sum); + p[3] = noncoef_merge_prob(p[3], c[2], c[3]); + sum -= c[4] + c[5]; + p[4] = noncoef_merge_prob(p[4], c[4] + c[5], sum); + p[5] = noncoef_merge_prob(p[5], c[4], c[5]); + sum -= c[6]; + p[6] = noncoef_merge_prob(p[6], c[6], sum); + p[7] = noncoef_merge_prob(p[7], c[7] + c[8], c[9] + c[10]); + p[8] = noncoef_merge_prob(p[8], c[7], c[8]); + p[9] = noncoef_merge_prob(p[9], c[9], c[10]); +} + +fn adapt_probs_variant_a_coef(p: &mut [u8], c: &[u32], update_factor: u32) { + merge_probs_variant_a(p, c, 24, update_factor); +} + +fn adapt_probs_variant_b_coef(p: &mut [u8], c: &[u32], update_factor: u32) { + merge_probs_variant_b(p, c, 24, update_factor); +} + +fn _adapt_coeff( + i: usize, + j: usize, + k: usize, + probs: &mut FrameContext, + counts: &FrameSymbolCounts<'_>, + uf: u32, +) { + for l in 0..probs.coef[0][0][0].len() { + for m in 0..BAND_6!(l) { + let p = &mut probs.coef[i][j][k][l][m]; + let counts_more_coefs = [ + *counts.eob[i][j][k][l][m][1], + *counts.eob[i][j][k][l][m][0] - *counts.eob[i][j][k][l][m][1], + ]; + + adapt_probs_variant_a_coef(p, counts.coeff[i][j][k][l][m], uf); + adapt_probs_variant_b_coef(p, &counts_more_coefs, uf); + } + } +} + +fn _adapt_coef_probs(probs: &mut FrameContext, counts: &mut FrameSymbolCounts<'_>, uf: u32) { + for i in 0..probs.coef.len() { + for j in 0..probs.coef[0].len() { + for k in 0..probs.coef[0][0].len() { + _adapt_coeff(i, j, k, probs, counts, uf); + } + } + } +} + +fn adapt_probs_variant_b(p: &mut [u8], c: &[u32]) { + merge_probs_variant_b(p, c, 20, 128); +} + +fn adapt_probs_variant_c(p: &mut [u8], c: &[u32]) { + merge_probs_variant_c(p, c); +} + +fn adapt_probs_variant_d(p: &mut [u8], c: &[u32]) { + merge_probs_variant_d(p, c); +} + +fn adapt_probs_variant_e(p: &mut [u8], c: &[u32]) { + merge_probs_variant_e(p, c); +} + +fn adapt_probs_variant_f(p: &mut [u8], c: &[u32]) { + merge_probs_variant_f(p, c); +} + +fn adapt_probs_variant_g(p: &mut [u8], c: &[u32]) { + merge_probs_variant_g(p, c); +} + +fn adapt_prob(prob: u8, counts: [u32; 2]) -> u8 { + noncoef_merge_prob(prob, counts[0], counts[1]) +} + +// The C API for C drivers. +pub mod c { + use super::*; + #[no_mangle] + /// Counterpart to 6.3 compressed_header(), but parsing has been done in userspace. + pub extern "C" fn v4l2_vp9_fw_update_probs_rs( + probs: &mut FrameContext, + deltas: &bindings::v4l2_ctrl_vp9_compressed_hdr, + dec_params: &bindings::v4l2_ctrl_vp9_frame, + ) { + super::fw_update_probs(probs, deltas, dec_params); + } + + #[no_mangle] + pub extern "C" fn v4l2_vp9_reset_frame_ctx_rs( + dec_params: &bindings::v4l2_ctrl_vp9_frame, + frame_context: &mut [FrameContext; 4], + ) -> u8 { + super::reset_frame_ctx(dec_params, frame_context) + } + + #[no_mangle] + pub extern "C" fn v4l2_vp9_adapt_coef_probs_rs( + probs: &mut FrameContext, + counts: &mut FrameSymbolCounts<'_>, + use_128: bool, + frame_is_intra: bool, + ) { + super::adapt_coef_probs(probs, counts, use_128, frame_is_intra); + } + + #[no_mangle] + pub extern "C" fn v4l2_vp9_adapt_noncoef_probs_rs( + probs: &mut FrameContext, + counts: &mut FrameSymbolCounts<'_>, + reference_mode: u8, + interpolation_filter: u8, + tx_mode: u8, + flags: u32, + ) { + super::adapt_noncoef_probs( + probs, + counts, + reference_mode, + interpolation_filter, + tx_mode, + flags, + ); + } + + #[no_mangle] + pub extern "C" fn v4l2_vp9_seg_feat_enabled_rs( + feature_enabled: &[u8; 8], + feature: u32, + segid: u32, + ) -> bool { + super::seg_feat_enabled(feature_enabled, feature, segid) + } +} From patchwork Thu Mar 7 19:08:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Almeida X-Patchwork-Id: 779015 Received: from madrid.collaboradmins.com (madrid.collaboradmins.com [46.235.227.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 88BB2136983; Thu, 7 Mar 2024 19:13:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.235.227.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709838784; cv=none; b=TcqEbFzYJM4XRI0d/9/6AIFMX9crhsx+Xwqd9cVGZggh0AhdVwz7yyqKHdxX+e0n2RfBnIezXlDfzkpYplOgLaYN/CuPyiE/oZDuGmGIVoKYAPa1ViKCQzIA4PGP5T0ak18IsU5pekrE7Se3y8ud2N6g23eg+dk6EN0zHO83mEo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709838784; c=relaxed/simple; bh=Ip2lE0mlbIvlK/wNnyztRmiDquhn+dPX9ocwRDPsZyE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ertbhL6dIfY5uLALnMuFA3lGCs7EK616n7gM1hDekqlBPM7WuiOGfcjo3xgMLOHIIJU77kWs0UnaJwXzS9Xa7beTr2rhzvzx8a+SvO0FLj6F5pR+ewnQhKqc4tow/MD+GNMTRkIewLfrcoe5PawZ0CG9q0yQ18WSBnwADvdqPRg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=k1qZhgdX; arc=none smtp.client-ip=46.235.227.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="k1qZhgdX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1709838779; bh=Ip2lE0mlbIvlK/wNnyztRmiDquhn+dPX9ocwRDPsZyE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k1qZhgdXJG8OZfEgJs/DPqZuVEYQsarfUw7PiTJC1ZzbZBP0NAbu7RS7FgwjBsi8L 8PNm1J+Q3AhcIKyEuI8W9ts+UF9aVPUIe9/+Ws2V1EAPtOoxENwBUMTGVGHL8cHE7U nQGPywOOBU8H56xNTWR5PhdP5CKAuiQovedwkTseGm+vNcGDQltgdbKIVVfVJvBb07 34ZVTU0hqS2a/IiDWXxG/12ObX07GK+6GJGwnGdDPLy6J5O/oqSZ560rJ6WzmDBB69 U7rGfOlvE0mWYlFGGhgeMduXbAwX9ZZTw0Xj6Dh7jnWBwu57NX7fa0R0Y+WzfHmbaj M16aL6bmXsCoQ== Received: from localhost.localdomain (cola.collaboradmins.com [195.201.22.229]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: dwlsalmeida) by madrid.collaboradmins.com (Postfix) with ESMTPSA id 89DCB378134F; Thu, 7 Mar 2024 19:12:55 +0000 (UTC) From: Daniel Almeida To: wedsonaf@gmail.com, ojeda@kernel.org, mchehab@kernel.org, hverkuil@xs4all.nl Cc: Daniel Almeida , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, kernel@collabora.com Subject: [RFC PATCH v2 2/2] media: rkvdec: rewrite parts of the driver in Rust Date: Thu, 7 Mar 2024 16:08:16 -0300 Message-ID: <20240307190841.10260-3-daniel.almeida@collabora.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240307190841.10260-1-daniel.almeida@collabora.com> References: <20240227215146.46487-1-daniel.almeida@collabora.com> <20240307190841.10260-1-daniel.almeida@collabora.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- drivers/staging/media/rkvdec/Kconfig | 1 + drivers/staging/media/rkvdec/Makefile | 2 +- drivers/staging/media/rkvdec/cbindgen.toml | 36 ++ drivers/staging/media/rkvdec/common.rs | 19 + drivers/staging/media/rkvdec/regs.rs | 237 ++++++++ drivers/staging/media/rkvdec/rkvdec-vp9.c | 585 ++++--------------- drivers/staging/media/rkvdec/rkvdec_rs.h | 125 ++++ drivers/staging/media/rkvdec/rkvdec_rs.rs | 14 + drivers/staging/media/rkvdec/vp9.rs | 636 +++++++++++++++++++++ rust/helpers.c | 7 + 10 files changed, 1181 insertions(+), 481 deletions(-) create mode 100644 drivers/staging/media/rkvdec/cbindgen.toml create mode 100644 drivers/staging/media/rkvdec/common.rs create mode 100644 drivers/staging/media/rkvdec/regs.rs create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.h create mode 100644 drivers/staging/media/rkvdec/rkvdec_rs.rs create mode 100644 drivers/staging/media/rkvdec/vp9.rs diff --git a/drivers/staging/media/rkvdec/Kconfig b/drivers/staging/media/rkvdec/Kconfig index 245dc47082d4..1877b6b0153b 100644 --- a/drivers/staging/media/rkvdec/Kconfig +++ b/drivers/staging/media/rkvdec/Kconfig @@ -3,6 +3,7 @@ config VIDEO_ROCKCHIP_VDEC tristate "Rockchip Video Decoder driver" depends on ARCH_ROCKCHIP || COMPILE_TEST depends on VIDEO_DEV + depends on RUST select MEDIA_CONTROLLER select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_VMALLOC diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile index cb86b429cfaa..8e04aa7dbf16 100644 --- a/drivers/staging/media/rkvdec/Makefile +++ b/drivers/staging/media/rkvdec/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o -rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o +rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o rkvdec_rs.o diff --git a/drivers/staging/media/rkvdec/cbindgen.toml b/drivers/staging/media/rkvdec/cbindgen.toml new file mode 100644 index 000000000000..3ca785d26cc8 --- /dev/null +++ b/drivers/staging/media/rkvdec/cbindgen.toml @@ -0,0 +1,36 @@ +# Generate the C API with: +# cbindgen --lang c -v --config drivers/staging/media/rkvdec/cbindgen.toml --output drivers/staging/media/rkvdec/rkvdec_rs.h -- drivers/staging/media/rkvdec/rkvdec_rs.rs + +language = "C" + +# No , , , , +no_includes = true +style = "tag" + +sys_includes = ["media/v4l2-ctrls.h", "media/v4l2-vp9-rs.h", "linux/types.h"] +autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" +usize_is_size_t = true +include_guard = "RKVDEC_RS_H" + +# Rename everything from bindgen +# See https://github.com/mozilla/cbindgen/issues/621 +# Also rename our mangled structs into snake_case for the C API +[export.rename] +"v4l2_ctrl_vp9_frame" = "struct v4l2_ctrl_vp9_frame" +"v4l2_vp9_segmentation" = "struct v4l2_vp9_segmentation" +"v4l2_vp9_loop_filter" = "struct v4l2_vp9_loop_filter" +"Resolution" = "rkvdec_rs_resolution" +"Mv" = " rkvdec_rs_vp9_mv" +"InterFrameProbs" = " rkvdec_rs_vp9_inter_frame_probs" +"IntraModeProbs" = " rkvdec_rs_vp9_intra_mode_probs" +"IntraOnlyFrameProbs" = " rkvdec_rs_vp9_intra_only_frame_probs" +"FrameProbs" = " rkvdec_rs_vp9_frame_probs" +"HwProbs" = " rkvdec_rs_vp9_probs" +"DecodedBufferInfo" = "rkvdec_rs_decoded_buffer_info" +"FrameInfo" = "rkvdec_rs_frame_info" +"BaseRun" = "rkvdec_rs_base_run" +"Run" = "rkvdec_rs_run" +"FrameContext" = "struct v4l2_vp9_frame_context_rs" + +[enum] +prefix_with_name = true diff --git a/drivers/staging/media/rkvdec/common.rs b/drivers/staging/media/rkvdec/common.rs new file mode 100644 index 000000000000..0f9f35bc915f --- /dev/null +++ b/drivers/staging/media/rkvdec/common.rs @@ -0,0 +1,19 @@ +#![allow(missing_docs)] +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +#![allow(unused_variables)] + +use kernel::bindings; + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) struct Resolution { + pub(crate) width: u32, + pub(crate) height: u32, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) struct BaseRun { + pub(crate) decoded_resolution: Resolution, +} diff --git a/drivers/staging/media/rkvdec/regs.rs b/drivers/staging/media/rkvdec/regs.rs new file mode 100644 index 000000000000..644f4b07063d --- /dev/null +++ b/drivers/staging/media/rkvdec/regs.rs @@ -0,0 +1,237 @@ +#![allow(dead_code)] +#![allow(unused_macros)] + +pub(crate) const RKVDEC_REG_INTERRUPT: u32 = 0x004; +pub(crate) const RKVDEC_INTERRUPT_DEC_E: u32 = 1 << 0; +pub(crate) const RKVDEC_CONFIG_DEC_CLK_GATE_E: u32 = 1 << 1; +pub(crate) const RKVDEC_E_STRMD_CLKGATE_DIS: u32 = 1 << 2; +pub(crate) const RKVDEC_TIMEOUT_MODE: u32 = 1 << 3; +pub(crate) const RKVDEC_IRQ_DIS: u32 = 1 << 4; +pub(crate) const RKVDEC_TIMEOUT_E: u32 = 1 << 5; +pub(crate) const RKVDEC_BUF_EMPTY_E: u32 = 1 << 6; +pub(crate) const RKVDEC_STRM_E_WAITDECFIFO_EMPTY: u32 = 1 << 7; +pub(crate) const RKVDEC_IRQ: u32 = 1 << 8; +pub(crate) const RKVDEC_IRQ_RAW: u32 = 1 << 9; +pub(crate) const RKVDEC_E_REWRITE_VALID: u32 = 1 << 10; +pub(crate) const RKVDEC_COMMONIRQ_MODE: u32 = 1 << 11; +pub(crate) const RKVDEC_RDY_STA: u32 = 1 << 12; +pub(crate) const RKVDEC_BUS_STA: u32 = 1 << 13; +pub(crate) const RKVDEC_ERR_STA: u32 = 1 << 14; +pub(crate) const RKVDEC_TIMEOUT_STA: u32 = 1 << 15; +pub(crate) const RKVDEC_BUF_EMPTY_STA: u32 = 1 << 16; +pub(crate) const RKVDEC_COLMV_REF_ERR_STA: u32 = 1 << 17; +pub(crate) const RKVDEC_CABU_END_STA: u32 = 1 << 18; +pub(crate) const RKVDEC_H264ORVP9_ERR_MODE: u32 = 1 << 19; +pub(crate) const RKVDEC_SOFTRST_EN_P: u32 = 1 << 20; +pub(crate) const RKVDEC_FORCE_SOFTRESET_VALID: u32 = 1 << 21; +pub(crate) const RKVDEC_SOFTRESET_RDY: u32 = 1 << 22; +pub(crate) const RKVDEC_REG_SYSCTRL: u32 = 0x008; +pub(crate) const RKVDEC_IN_ENDIAN: u32 = 1 << 0; +pub(crate) const RKVDEC_IN_SWAP32_E: u32 = 1 << 1; +pub(crate) const RKVDEC_IN_SWAP64_E: u32 = 1 << 2; +pub(crate) const RKVDEC_STR_ENDIAN: u32 = 1 << 3; +pub(crate) const RKVDEC_STR_SWAP32_E: u32 = 1 << 4; +pub(crate) const RKVDEC_STR_SWAP64_E: u32 = 1 << 5; +pub(crate) const RKVDEC_OUT_ENDIAN: u32 = 1 << 6; +pub(crate) const RKVDEC_OUT_SWAP32_E: u32 = 1 << 7; +pub(crate) const RKVDEC_OUT_CBCR_SWAP: u32 = 1 << 8; +pub(crate) const RKVDEC_RLC_MODE_DIRECT_WRITE: u32 = 1 << 10; +pub(crate) const RKVDEC_RLC_MODE: u32 = 1 << 11; +macro_rules! RKVDEC_STRM_START_BIT { ($x:expr) => { ((($x) & 0x7f) << 12) } } +macro_rules! RKVDEC_MODE { ($x:expr) => { ((($x) & 0x03) << 20) } } +pub(crate) const RKVDEC_MODE_H264: u32 = 1; +pub(crate) const RKVDEC_MODE_VP9: u32 = 2; +pub(crate) const RKVDEC_RPS_MODE: u32 = 1 << 24; +pub(crate) const RKVDEC_STRM_MODE: u32 = 1 << 25; +pub(crate) const RKVDEC_H264_STRM_LASTPKT: u32 = 1 << 26; +pub(crate) const RKVDEC_H264_FIRSTSLICE_FLAG: u32 = 1 << 27; +pub(crate) const RKVDEC_H264_FRAME_ORSLICE: u32 = 1 << 28; +pub(crate) const RKVDEC_BUSPR_SLOT_DIS: u32 = 1 << 29; +pub(crate) const RKVDEC_REG_PICPAR: u32 = 0x00C; +macro_rules! RKVDEC_Y_HOR_VIRSTRIDE { ($x:expr) => { (($x) & 0x1ff) } } +pub(crate) const RKVDEC_SLICE_NUM_HIGHBIT: u32 = 1 << 11; +macro_rules! RKVDEC_UV_HOR_VIRSTRIDE { ($x:expr) => { ((($x) & 0x1ff) << 12) } } +macro_rules! RKVDEC_SLICE_NUM_LOWBITS { ($x:expr) => { ((($x) & 0x7ff) << 21) } } +pub(crate) const RKVDEC_REG_STRM_RLC_BASE: u32 = 0x010; +pub(crate) const RKVDEC_REG_STRM_LEN: u32 = 0x014; +macro_rules! RKVDEC_STRM_LEN { ($x:expr) => { (($x) & 0x7ffffff) } } +pub(crate) const RKVDEC_REG_CABACTBL_PROB_BASE: u32 = 0x018; +pub(crate) const RKVDEC_REG_DECOUT_BASE: u32 = 0x01C; +pub(crate) const RKVDEC_REG_Y_VIRSTRIDE: u32 = 0x020; +macro_rules! RKVDEC_Y_VIRSTRIDE { ($x:expr) => { (($x) & 0xfffff) } } +pub(crate) const RKVDEC_REG_YUV_VIRSTRIDE: u32 = 0x024; +macro_rules! RKVDEC_YUV_VIRSTRIDE { ($x:expr) => { (($x) & 0x1fffff) } } +macro_rules! RKVDEC_REG_H264_BASE_REFER { ($x:expr) => { ((($i) * 0x04) + 0x028) } } +pub(crate) const RKVDEC_REG_H264_BASE_REFER15: u32 = 0x0C0; +pub(crate) const RKVDEC_FIELD_REF: u32 = 1 << 0; +pub(crate) const RKVDEC_TOPFIELD_USED_REF: u32 = 1 << 1; +pub(crate) const RKVDEC_BOTFIELD_USED_REF: u32 = 1 << 2; +pub(crate) const RKVDEC_COLMV_USED_FLAG_REF: u32 = 1 << 3; +pub(crate) const RKVDEC_REG_VP9_LAST_FRAME_BASE: u32 = 0x02c; +pub(crate) const RKVDEC_REG_VP9_GOLDEN_FRAME_BASE: u32 = 0x030; +pub(crate) const RKVDEC_REG_VP9_ALTREF_FRAME_BASE: u32 = 0x034; +pub(crate) const RKVDEC_REG_VP9_CPRHEADER_OFFSET: u32 = 0x028; +macro_rules! RKVDEC_VP9_CPRHEADER_OFFSET { ($x:expr) => { (($x) & 0xffff) } } +pub(crate) const RKVDEC_REG_VP9_REFERLAST_BASE: u32 = 0x02C; +pub(crate) const RKVDEC_REG_VP9_REFERGOLDEN_BASE: u32 = 0x030; +pub(crate) const RKVDEC_REG_VP9_REFERALFTER_BASE: u32 = 0x034; +pub(crate) const RKVDEC_REG_VP9COUNT_BASE: u32 = 0x038; +pub(crate) const RKVDEC_VP9COUNT_UPDATE_EN: u32 = 1 << 0; +pub(crate) const RKVDEC_REG_VP9_SEGIDLAST_BASE: u32 = 0x03C; +pub(crate) const RKVDEC_REG_VP9_SEGIDCUR_BASE: u32 = 0x040; +macro_rules! RKVDEC_REG_VP9_FRAME_SIZE { ($x:expr) => { (($x) * 0x04 + 0x044) } } +macro_rules! RKVDEC_VP9_FRAMEWIDTH { ($x:expr) => { ((($x) & 0xffff) << 0) } } +macro_rules! RKVDEC_VP9_FRAMEHEIGHT { ($x:expr) => { ((($x) & 0xffff) << 16) } } +macro_rules! RKVDEC_VP9_SEGID_GRP { ($x:expr) => { (($x) * 0x04 + 0x050) } } +macro_rules! RKVDEC_SEGID_ABS_DELTA { ($x:expr) => { (($x) & 0x1) } } +macro_rules! RKVDEC_SEGID_FRAME_QP_DELTA_EN { ($x:expr) => { ((($x) & 0x1) << 1) } } +macro_rules! RKVDEC_SEGID_FRAME_QP_DELTA { ($x:expr) => { ((($x) & 0x1ff) << 2) } } +macro_rules! RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN { ($x:expr) => { ((($x) & 0x1) << 11) } } +macro_rules! RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE { ($x:expr) => { ((($x) & 0x7f) << 12) } } +macro_rules! RKVDEC_SEGID_REFERINFO_EN { ($x:expr) => { ((($x) & 0x1) << 19) } } +macro_rules! RKVDEC_SEGID_REFERINFO { ($x:expr) => { ((($x) & 0x03) << 20) } } +macro_rules! RKVDEC_SEGID_FRAME_SKIP_EN { ($x:expr) => { ((($x) & 0x1) << 22) } } +pub(crate) const RKVDEC_VP9_CPRHEADER_CONFIG: u32 = 0x070; +macro_rules! RKVDEC_VP9_TX_MODE { ($x:expr) => { (($x) & 0x07) } } +macro_rules! RKVDEC_VP9_FRAME_REF_MODE { ($x:expr) => { ((($x) & 0x03) << 3) } } +macro_rules! RKVDEC_VP9_REF_SCALE { ($x:expr) => { (($x) * 0x04 + 0x074) } } +macro_rules! RKVDEC_VP9_REF_HOR_SCALE { ($x:expr) => { (($x) & 0xffff) } } +macro_rules! RKVDEC_VP9_REF_VER_SCALE { ($x:expr) => { ((($x) & 0xffff) << 16) } } +pub(crate) const RKVDEC_VP9_REF_DELTAS_LASTFRAME: u32 = 0x080; +macro_rules! RKVDEC_REF_DELTAS_LASTFRAME { ($pos:expr, $val:expr) => { ((($val) & 0x7f) << (($pos) * 7)) } } +pub(crate) const RKVDEC_VP9_INFO_LASTFRAME: u32 = 0x084; +macro_rules! RKVDEC_MODE_DELTAS_LASTFRAME { ($pos:expr, $val:expr) => { ((($val) & 0x7f) << (($pos) * 7)) } } +pub(crate) const RKVDEC_SEG_EN_LASTFRAME: u32 = 1 << 16; +pub(crate) const RKVDEC_LAST_SHOW_FRAME: u32 = 1 << 17; +pub(crate) const RKVDEC_LAST_INTRA_ONLY: u32 = 1 << 18; +pub(crate) const RKVDEC_LAST_WIDHHEIGHT_EQCUR: u32 = 1 << 19; +macro_rules! RKVDEC_COLOR_SPACE_LASTKEYFRAME { ($x:expr) => { ((($x) & 0x07) << 20) } } +pub(crate) const RKVDEC_VP9_INTERCMD_BASE: u32 = 0x088; +pub(crate) const RKVDEC_VP9_INTERCMD_NUM: u32 = 0x08C; +macro_rules! RKVDEC_INTERCMD_NUM { ($x:expr) => { (($x) & 0xffffff) } } +pub(crate) const RKVDEC_VP9_LASTTILE_SIZE: u32 = 0x090; +macro_rules! RKVDEC_LASTTILE_SIZE { ($x:expr) => { (($x) & 0xffffff) } } +macro_rules! RKVDEC_VP9_HOR_VIRSTRIDE { ($i:expr) => { (($i) * 0x04 + 0x094) } } +macro_rules! RKVDEC_HOR_Y_VIRSTRIDE { ($x:expr) => { (($x) & 0x1ff) } } +macro_rules! RKVDEC_HOR_UV_VIRSTRIDE { ($x:expr) => { ((($x) & 0x1ff) << 16) } } +macro_rules! RKVDEC_REG_H264_POC_REFER0 { ($i:expr) => { ((($i) * 0x04) + 0x064) } } +macro_rules! RKVDEC_REG_H264_POC_REFER1 { ($i:expr) => { ((($i) * 0x04) + 0x0C4) } } +macro_rules! RKVDEC_REG_H264_POC_REFER2 { ($i:expr) => { ((($i) * 0x04) + 0x120) } } +macro_rules! RKVDEC_POC_REFER { ($x:expr) => { (($x) & 0xffffffff) } } +pub(crate) const RKVDEC_REG_CUR_POC0: u32 = 0x0A0; +pub(crate) const RKVDEC_REG_CUR_POC1: u32 = 0x128; +macro_rules! RKVDEC_CUR_POC { ($x:expr) => { (($x) & 0xffffffff) } } +pub(crate) const RKVDEC_REG_RLCWRITE_BASE: u32 = 0x0A4; +pub(crate) const RKVDEC_REG_PPS_BASE: u32 = 0x0A8; +pub(crate) const RKVDEC_REG_RPS_BASE: u32 = 0x0AC; +pub(crate) const RKVDEC_REG_STRMD_ERR_EN: u32 = 0x0B0; +macro_rules! RKVDEC_STRMD_ERR_EN { ($x:expr) => { (($x) & 0xffffffff) } } +pub(crate) const RKVDEC_REG_STRMD_ERR_STA: u32 = 0x0B4; +macro_rules! RKVDEC_STRMD_ERR_STA { ($x:expr) => { (($x) & 0xfffffff) } } +macro_rules! RKVDEC_COLMV_ERR_REF_PICIDX { ($x:expr) => { ((($x) & 0x0f) << 28) } } +pub(crate) const RKVDEC_REG_STRMD_ERR_CTU: u32 = 0x0B8; +macro_rules! RKVDEC_STRMD_ERR_CTU { ($x:expr) => { (($x) & 0xff) } } +macro_rules! RKVDEC_STRMD_ERR_CTU_YOFFSET { ($x:expr) => { ((($x) & 0xff) << 8) } } +macro_rules! RKVDEC_STRMFIFO_SPACE2FULL { ($x:expr) => { ((($x) & 0x7f) << 16) } } +pub(crate) const RKVDEC_VP9_ERR_EN_CTU0: u32 = 1 << 24; +pub(crate) const RKVDEC_REG_SAO_CTU_POS: u32 = 0x0BC; +macro_rules! RKVDEC_SAOWR_XOFFSET { ($x:expr) => { (($x) & 0x1ff) } } +macro_rules! RKVDEC_SAOWR_YOFFSET { ($x:expr) => { ((($x) & 0x3ff) << 16) } } +pub(crate) const RKVDEC_VP9_LAST_FRAME_YSTRIDE: u32 = 0x0C0; +pub(crate) const RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE: u32 = 0x0C4; +pub(crate) const RKVDEC_VP9_ALTREF_FRAME_YSTRIDE: u32 = 0x0C8; +macro_rules! RKVDEC_VP9_REF_YSTRIDE { ($x:expr) => { ((($x) & 0xfffff) << 0) } } +pub(crate) const RKVDEC_VP9_LAST_FRAME_YUVSTRIDE: u32 = 0x0CC; +macro_rules! RKVDEC_VP9_REF_YUVSTRIDE { ($x:expr) => { ((($x) & 0x1fffff) << 0) } } +pub(crate) const RKVDEC_VP9_REF_COLMV_BASE: u32 = 0x0D0; +pub(crate) const RKVDEC_REG_PERFORMANCE_CYCLE: u32 = 0x100; +macro_rules! RKVDEC_PERFORMANCE_CYCLE { ($x:expr) => { (($x) & 0xffffffff) } } +pub(crate) const RKVDEC_REG_AXI_DDR_RDATA: u32 = 0x104; +macro_rules! RKVDEC_AXI_DDR_RDATA { ($x:expr) => { (($x) & 0xffffffff) } } +pub(crate) const RKVDEC_REG_AXI_DDR_WDATA: u32 = 0x108; +macro_rules! RKVDEC_AXI_DDR_WDATA { ($x:expr) => { (($x) & 0xffffffff) } } +pub(crate) const RKVDEC_REG_FPGADEBUG_RESET: u32 = 0x10C; +pub(crate) const RKVDEC_BUSIFD_RESETN: u32 = 1 << 0; +pub(crate) const RKVDEC_CABAC_RESETN: u32 = 1 << 1; +pub(crate) const RKVDEC_DEC_CTRL_RESETN: u32 = 1 << 2; +pub(crate) const RKVDEC_TRANSD_RESETN: u32 = 1 << 3; +pub(crate) const RKVDEC_INTRA_RESETN: u32 = 1 << 4; +pub(crate) const RKVDEC_INTER_RESETN: u32 = 1 << 5; +pub(crate) const RKVDEC_RECON_RESETN: u32 = 1 << 6; +pub(crate) const RKVDEC_FILER_RESETN: u32 = 1 << 7; +pub(crate) const RKVDEC_REG_PERFORMANCE_SEL: u32 = 0x110; +macro_rules! RKVDEC_PERF_SEL_CNT0 { ($x:expr) => { (($x) & 0x3f) } } +macro_rules! RKVDEC_PERF_SEL_CNT1 { ($x:expr) => { ((($x) & 0x3f) << 8) } } +macro_rules! RKVDEC_PERF_SEL_CNT2 { ($x:expr) => { ((($x) & 0x3f) << 16) } } +macro_rules! RKVDEC_REG_PERFORMANCE_CNT { ($i:expr) => { (($i) * 0x04 + 0x114) } } +macro_rules! RKVDEC_PERF_CNT { ($x:expr) => { (($x) & 0xffffffff) } } +pub(crate) const RKVDEC_REG_H264_ERRINFO_BASE: u32 = 0x12C; +pub(crate) const RKVDEC_REG_H264_ERRINFO_NUM: u32 = 0x130; +macro_rules! RKVDEC_SLICEDEC_NUM { ($x:expr) => { (($x) & 0x3fff) } } +pub(crate) const RKVDEC_STRMD_DECT_ERR_FLAG: u32 = 1 << 15; +macro_rules! RKVDEC_ERR_PKT_NUM { ($x:expr) => { ((($x) & 0x3fff) << 16) } } +pub(crate) const RKVDEC_REG_H264_ERR_E: u32 = 0x134; +macro_rules! RKVDEC_H264_ERR_EN_HIGHBITS { ($x:expr) => { (($x) & 0x3fffffff) } } +pub(crate) const RKVDEC_REG_PREF_LUMA_CACHE_COMMAND: u32 = 0x410; +pub(crate) const RKVDEC_REG_PREF_CHR_CACHE_COMMAND: u32 = 0x450; +pub(crate) use RKVDEC_STRM_START_BIT; +pub(crate) use RKVDEC_MODE; +pub(crate) use RKVDEC_Y_HOR_VIRSTRIDE; +pub(crate) use RKVDEC_UV_HOR_VIRSTRIDE; +pub(crate) use RKVDEC_SLICE_NUM_LOWBITS; +pub(crate) use RKVDEC_STRM_LEN; +pub(crate) use RKVDEC_Y_VIRSTRIDE; +pub(crate) use RKVDEC_YUV_VIRSTRIDE; +pub(crate) use RKVDEC_REG_H264_BASE_REFER; +pub(crate) use RKVDEC_VP9_CPRHEADER_OFFSET; +pub(crate) use RKVDEC_REG_VP9_FRAME_SIZE; +pub(crate) use RKVDEC_VP9_FRAMEWIDTH; +pub(crate) use RKVDEC_VP9_FRAMEHEIGHT; +pub(crate) use RKVDEC_VP9_SEGID_GRP; +pub(crate) use RKVDEC_SEGID_ABS_DELTA; +pub(crate) use RKVDEC_SEGID_FRAME_QP_DELTA_EN; +pub(crate) use RKVDEC_SEGID_FRAME_QP_DELTA; +pub(crate) use RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN; +pub(crate) use RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE; +pub(crate) use RKVDEC_SEGID_REFERINFO_EN; +pub(crate) use RKVDEC_SEGID_REFERINFO; +pub(crate) use RKVDEC_SEGID_FRAME_SKIP_EN; +pub(crate) use RKVDEC_VP9_TX_MODE; +pub(crate) use RKVDEC_VP9_FRAME_REF_MODE; +pub(crate) use RKVDEC_VP9_REF_SCALE; +pub(crate) use RKVDEC_VP9_REF_HOR_SCALE; +pub(crate) use RKVDEC_VP9_REF_VER_SCALE; +pub(crate) use RKVDEC_REF_DELTAS_LASTFRAME; +pub(crate) use RKVDEC_MODE_DELTAS_LASTFRAME; +pub(crate) use RKVDEC_COLOR_SPACE_LASTKEYFRAME; +pub(crate) use RKVDEC_INTERCMD_NUM; +pub(crate) use RKVDEC_LASTTILE_SIZE; +pub(crate) use RKVDEC_VP9_HOR_VIRSTRIDE; +pub(crate) use RKVDEC_HOR_Y_VIRSTRIDE; +pub(crate) use RKVDEC_HOR_UV_VIRSTRIDE; +pub(crate) use RKVDEC_REG_H264_POC_REFER0; +pub(crate) use RKVDEC_REG_H264_POC_REFER1; +pub(crate) use RKVDEC_REG_H264_POC_REFER2; +pub(crate) use RKVDEC_POC_REFER; +pub(crate) use RKVDEC_CUR_POC; +pub(crate) use RKVDEC_STRMD_ERR_EN; +pub(crate) use RKVDEC_STRMD_ERR_STA; +pub(crate) use RKVDEC_COLMV_ERR_REF_PICIDX; +pub(crate) use RKVDEC_STRMD_ERR_CTU; +pub(crate) use RKVDEC_STRMD_ERR_CTU_YOFFSET; +pub(crate) use RKVDEC_STRMFIFO_SPACE2FULL; +pub(crate) use RKVDEC_SAOWR_XOFFSET; +pub(crate) use RKVDEC_SAOWR_YOFFSET; +pub(crate) use RKVDEC_VP9_REF_YSTRIDE; +pub(crate) use RKVDEC_VP9_REF_YUVSTRIDE; +pub(crate) use RKVDEC_PERFORMANCE_CYCLE; +pub(crate) use RKVDEC_AXI_DDR_RDATA; +pub(crate) use RKVDEC_AXI_DDR_WDATA; +pub(crate) use RKVDEC_PERF_SEL_CNT0; +pub(crate) use RKVDEC_PERF_SEL_CNT1; +pub(crate) use RKVDEC_PERF_SEL_CNT2; +pub(crate) use RKVDEC_REG_PERFORMANCE_CNT; +pub(crate) use RKVDEC_PERF_CNT; +pub(crate) use RKVDEC_SLICEDEC_NUM; +pub(crate) use RKVDEC_ERR_PKT_NUM; +pub(crate) use RKVDEC_H264_ERR_EN_HIGHBITS; \ No newline at end of file diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c index 86c6903d11ab..5af5a7fdcde2 100644 --- a/drivers/staging/media/rkvdec/rkvdec-vp9.c +++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c @@ -23,74 +23,15 @@ #include "rkvdec.h" #include "rkvdec-regs.h" +#include "rkvdec_rs.h" #define RKVDEC_VP9_PROBE_SIZE 4864 #define RKVDEC_VP9_COUNT_SIZE 13232 #define RKVDEC_VP9_MAX_SEGMAP_SIZE 73728 -struct rkvdec_vp9_intra_mode_probs { - u8 y_mode[105]; - u8 uv_mode[23]; -}; - -struct rkvdec_vp9_intra_only_frame_probs { - u8 coef_intra[4][2][128]; - struct rkvdec_vp9_intra_mode_probs intra_mode[10]; -}; - -struct rkvdec_vp9_inter_frame_probs { - u8 y_mode[4][9]; - u8 comp_mode[5]; - u8 comp_ref[5]; - u8 single_ref[5][2]; - u8 inter_mode[7][3]; - u8 interp_filter[4][2]; - u8 padding0[11]; - u8 coef[2][4][2][128]; - u8 uv_mode_0_2[3][9]; - u8 padding1[5]; - u8 uv_mode_3_5[3][9]; - u8 padding2[5]; - u8 uv_mode_6_8[3][9]; - u8 padding3[5]; - u8 uv_mode_9[9]; - u8 padding4[7]; - u8 padding5[16]; - struct { - u8 joint[3]; - u8 sign[2]; - u8 classes[2][10]; - u8 class0_bit[2]; - u8 bits[2][10]; - u8 class0_fr[2][2][3]; - u8 fr[2][3]; - u8 class0_hp[2]; - u8 hp[2]; - } mv; -}; - -struct rkvdec_vp9_probs { - u8 partition[16][3]; - u8 pred[3]; - u8 tree[7]; - u8 skip[3]; - u8 tx32[2][3]; - u8 tx16[2][2]; - u8 tx8[2][1]; - u8 is_inter[4]; - /* 128 bit alignment */ - u8 padding0[3]; - union { - struct rkvdec_vp9_inter_frame_probs inter; - struct rkvdec_vp9_intra_only_frame_probs intra_only; - }; - /* 128 bit alignment */ - u8 padding1[11]; -}; - /* Data structure describing auxiliary buffer format. */ struct rkvdec_vp9_priv_tbl { - struct rkvdec_vp9_probs probs; + struct rkvdec_rs_vp9_probs probs; u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE]; }; @@ -165,188 +106,6 @@ struct rkvdec_vp9_ctx { struct rkvdec_vp9_frame_info last; }; -static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane) -{ - unsigned int idx = 0, byte_count = 0; - int k, m, n; - u8 p; - - for (k = 0; k < 6; k++) { - for (m = 0; m < 6; m++) { - for (n = 0; n < 3; n++) { - p = coef[k][m][n]; - coeff_plane[idx++] = p; - byte_count++; - if (byte_count == 27) { - idx += 5; - byte_count = 0; - } - } - } - } -} - -static void init_intra_only_probs(struct rkvdec_ctx *ctx, - const struct rkvdec_vp9_run *run) -{ - struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; - struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; - struct rkvdec_vp9_intra_only_frame_probs *rkprobs; - const struct v4l2_vp9_frame_context_rs *probs; - unsigned int i, j, k; - - rkprobs = &tbl->probs.intra_only; - probs = &vp9_ctx->probability_tables; - - /* - * intra only 149 x 128 bits ,aligned to 152 x 128 bits coeff related - * prob 64 x 128 bits - */ - for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { - for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) - write_coeff_plane(probs->coef[i][j][0], - rkprobs->coef_intra[i][j]); - } - - /* intra mode prob 80 x 128 bits */ - for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs); i++) { - unsigned int byte_count = 0; - int idx = 0; - - /* vp9_kf_y_mode_prob */ - for (j = 0; j < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0]); j++) { - for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob_rs[0][0]); - k++) { - u8 val = v4l2_vp9_kf_y_mode_prob_rs[i][j][k]; - - rkprobs->intra_mode[i].y_mode[idx++] = val; - byte_count++; - if (byte_count == 27) { - byte_count = 0; - idx += 5; - } - } - } - } - - for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob_rs); ++i) { - const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob_rs; - - rkprobs->intra_mode[i / 23].uv_mode[i % 23] = ptr[i]; - } -} - -static void init_inter_probs(struct rkvdec_ctx *ctx, - const struct rkvdec_vp9_run *run) -{ - struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; - struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; - struct rkvdec_vp9_inter_frame_probs *rkprobs; - const struct v4l2_vp9_frame_context_rs *probs; - unsigned int i, j, k; - - rkprobs = &tbl->probs.inter; - probs = &vp9_ctx->probability_tables; - - /* - * inter probs - * 151 x 128 bits, aligned to 152 x 128 bits - * inter only - * intra_y_mode & inter_block info 6 x 128 bits - */ - - memcpy(rkprobs->y_mode, probs->y_mode, sizeof(rkprobs->y_mode)); - memcpy(rkprobs->comp_mode, probs->comp_mode, - sizeof(rkprobs->comp_mode)); - memcpy(rkprobs->comp_ref, probs->comp_ref, - sizeof(rkprobs->comp_ref)); - memcpy(rkprobs->single_ref, probs->single_ref, - sizeof(rkprobs->single_ref)); - memcpy(rkprobs->inter_mode, probs->inter_mode, - sizeof(rkprobs->inter_mode)); - memcpy(rkprobs->interp_filter, probs->interp_filter, - sizeof(rkprobs->interp_filter)); - - /* 128 x 128 bits coeff related */ - for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { - for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { - for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++) - write_coeff_plane(probs->coef[i][j][k], - rkprobs->coef[k][i][j]); - } - } - - /* intra uv mode 6 x 128 */ - memcpy(rkprobs->uv_mode_0_2, &probs->uv_mode[0], - sizeof(rkprobs->uv_mode_0_2)); - memcpy(rkprobs->uv_mode_3_5, &probs->uv_mode[3], - sizeof(rkprobs->uv_mode_3_5)); - memcpy(rkprobs->uv_mode_6_8, &probs->uv_mode[6], - sizeof(rkprobs->uv_mode_6_8)); - memcpy(rkprobs->uv_mode_9, &probs->uv_mode[9], - sizeof(rkprobs->uv_mode_9)); - - /* mv related 6 x 128 */ - memcpy(rkprobs->mv.joint, probs->mv.joint, - sizeof(rkprobs->mv.joint)); - memcpy(rkprobs->mv.sign, probs->mv.sign, - sizeof(rkprobs->mv.sign)); - memcpy(rkprobs->mv.classes, probs->mv.classes, - sizeof(rkprobs->mv.classes)); - memcpy(rkprobs->mv.class0_bit, probs->mv.class0_bit, - sizeof(rkprobs->mv.class0_bit)); - memcpy(rkprobs->mv.bits, probs->mv.bits, - sizeof(rkprobs->mv.bits)); - memcpy(rkprobs->mv.class0_fr, probs->mv.class0_fr, - sizeof(rkprobs->mv.class0_fr)); - memcpy(rkprobs->mv.fr, probs->mv.fr, - sizeof(rkprobs->mv.fr)); - memcpy(rkprobs->mv.class0_hp, probs->mv.class0_hp, - sizeof(rkprobs->mv.class0_hp)); - memcpy(rkprobs->mv.hp, probs->mv.hp, - sizeof(rkprobs->mv.hp)); -} - -static void init_probs(struct rkvdec_ctx *ctx, - const struct rkvdec_vp9_run *run) -{ - const struct v4l2_ctrl_vp9_frame *dec_params; - struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; - struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; - struct rkvdec_vp9_probs *rkprobs = &tbl->probs; - const struct v4l2_vp9_segmentation *seg; - const struct v4l2_vp9_frame_context_rs *probs; - bool intra_only; - - dec_params = run->decode_params; - probs = &vp9_ctx->probability_tables; - seg = &dec_params->seg; - - memset(rkprobs, 0, sizeof(*rkprobs)); - - intra_only = !!(dec_params->flags & - (V4L2_VP9_FRAME_FLAG_KEY_FRAME | - V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); - - /* sb info 5 x 128 bit */ - memcpy(rkprobs->partition, - intra_only ? v4l2_vp9_kf_partition_probs_rs : probs->partition, - sizeof(rkprobs->partition)); - - memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred)); - memcpy(rkprobs->tree, seg->tree_probs, sizeof(rkprobs->tree)); - memcpy(rkprobs->skip, probs->skip, sizeof(rkprobs->skip)); - memcpy(rkprobs->tx32, probs->tx32, sizeof(rkprobs->tx32)); - memcpy(rkprobs->tx16, probs->tx16, sizeof(rkprobs->tx16)); - memcpy(rkprobs->tx8, probs->tx8, sizeof(rkprobs->tx8)); - memcpy(rkprobs->is_inter, probs->is_inter, sizeof(rkprobs->is_inter)); - - if (intra_only) - init_intra_only_probs(ctx, run); - else - init_inter_probs(ctx, run); -} - struct rkvdec_vp9_ref_reg { u32 reg_frm_size; u32 reg_hor_stride; @@ -355,30 +114,6 @@ struct rkvdec_vp9_ref_reg { u32 reg_ref_base; }; -static struct rkvdec_vp9_ref_reg ref_regs[] = { - { - .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0), - .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0), - .reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE, - .reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE, - .reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE, - }, - { - .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1), - .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1), - .reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE, - .reg_yuv_stride = 0, - .reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE, - }, - { - .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2), - .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2), - .reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE, - .reg_yuv_stride = 0, - .reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE, - } -}; - static struct rkvdec_decoded_buffer * get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp) { @@ -409,84 +144,6 @@ static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf) yuv_len; } -static void config_ref_registers(struct rkvdec_ctx *ctx, - const struct rkvdec_vp9_run *run, - struct rkvdec_decoded_buffer *ref_buf, - struct rkvdec_vp9_ref_reg *ref_reg) -{ - unsigned int aligned_pitch, aligned_height, y_len, yuv_len; - struct rkvdec_dev *rkvdec = ctx->dev; - - aligned_height = round_up(ref_buf->vp9.height, 64); - writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(ref_buf->vp9.width) | - RKVDEC_VP9_FRAMEHEIGHT(ref_buf->vp9.height), - rkvdec->regs + ref_reg->reg_frm_size); - - writel_relaxed(vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0), - rkvdec->regs + ref_reg->reg_ref_base); - - if (&ref_buf->base.vb == run->base.bufs.dst) - return; - - aligned_pitch = round_up(ref_buf->vp9.width * ref_buf->vp9.bit_depth, 512) / 8; - y_len = aligned_height * aligned_pitch; - yuv_len = (y_len * 3) / 2; - - writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) | - RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16), - rkvdec->regs + ref_reg->reg_hor_stride); - writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16), - rkvdec->regs + ref_reg->reg_y_stride); - - if (!ref_reg->reg_yuv_stride) - return; - - writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16), - rkvdec->regs + ref_reg->reg_yuv_stride); -} - -static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid) -{ - struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; - struct v4l2_vp9_segmentation *seg; - struct rkvdec_dev *rkvdec = ctx->dev; - s16 feature_val; - int feature_id; - u32 val = 0; - - seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg; - feature_id = V4L2_VP9_SEG_LVL_ALT_Q; - if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) { - feature_val = seg->feature_data[segid][feature_id]; - val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) | - RKVDEC_SEGID_FRAME_QP_DELTA(feature_val); - } - - feature_id = V4L2_VP9_SEG_LVL_ALT_L; - if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) { - feature_val = seg->feature_data[segid][feature_id]; - val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) | - RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val); - } - - feature_id = V4L2_VP9_SEG_LVL_REF_FRAME; - if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) { - feature_val = seg->feature_data[segid][feature_id]; - val |= RKVDEC_SEGID_REFERINFO_EN(1) | - RKVDEC_SEGID_REFERINFO(feature_val); - } - - feature_id = V4L2_VP9_SEG_LVL_SKIP; - if (v4l2_vp9_seg_feat_enabled_rs(&seg->feature_enabled, feature_id, segid)) - val |= RKVDEC_SEGID_FRAME_SKIP_EN(1); - - if (!segid && - (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) - val |= RKVDEC_SEGID_ABS_DELTA(1); - - writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid)); -} - static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf, const struct v4l2_ctrl_vp9_frame *dec_params) { @@ -516,17 +173,11 @@ static void update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx) static void config_registers(struct rkvdec_ctx *ctx, const struct rkvdec_vp9_run *run) { - unsigned int y_len, uv_len, yuv_len, bit_depth, aligned_height, aligned_pitch, stream_len; const struct v4l2_ctrl_vp9_frame *dec_params; struct rkvdec_decoded_buffer *ref_bufs[3]; struct rkvdec_decoded_buffer *dst, *last, *mv_ref; struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; - u32 val, last_frame_info = 0; - const struct v4l2_vp9_segmentation *seg; - struct rkvdec_dev *rkvdec = ctx->dev; - dma_addr_t addr; bool intra_only; - unsigned int i; dec_params = run->decode_params; dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf); @@ -541,36 +192,17 @@ static void config_registers(struct rkvdec_ctx *ctx, update_dec_buf_info(dst, dec_params); update_ctx_cur_info(vp9_ctx, dst, dec_params); - seg = &dec_params->seg; intra_only = !!(dec_params->flags & (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); - writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9), - rkvdec->regs + RKVDEC_REG_SYSCTRL); - - bit_depth = dec_params->bit_depth; - aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64); - - aligned_pitch = round_up(ctx->decoded_fmt.fmt.pix_mp.width * - bit_depth, - 512) / 8; - y_len = aligned_height * aligned_pitch; - uv_len = y_len / 2; - yuv_len = y_len + uv_len; - - writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) | - RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16), - rkvdec->regs + RKVDEC_REG_PICPAR); - writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16), - rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); - writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16), - rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); - - stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0); - writel_relaxed(RKVDEC_STRM_LEN(stream_len), - rkvdec->regs + RKVDEC_REG_STRM_LEN); + if (!intra_only && + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && + vp9_ctx->last.valid) + mv_ref = last; + else + mv_ref = dst; /* * Reset count buffer, because decoder only output intra related syntax @@ -583,114 +215,110 @@ static void config_registers(struct rkvdec_ctx *ctx, vp9_ctx->cur.segmapid = vp9_ctx->last.segmapid; if (!intra_only && !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && - (!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) || - (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP))) + (!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) || + (dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP))) vp9_ctx->cur.segmapid++; - for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) - config_ref_registers(ctx, run, ref_bufs[i], &ref_regs[i]); - - for (i = 0; i < 8; i++) - config_seg_registers(ctx, i); - - writel_relaxed(RKVDEC_VP9_TX_MODE(vp9_ctx->cur.tx_mode) | - RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode), - rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG); - - if (!intra_only) { - const struct v4l2_vp9_loop_filter *lf; - s8 delta; - - if (vp9_ctx->last.valid) - lf = &vp9_ctx->last.lf; - else - lf = &vp9_ctx->cur.lf; - - val = 0; - for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { - delta = lf->ref_deltas[i]; - val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta); - } - - writel_relaxed(val, - rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME); - - for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { - delta = lf->mode_deltas[i]; - last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i, - delta); - } - } - - if (vp9_ctx->last.valid && !intra_only && - vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) - last_frame_info |= RKVDEC_SEG_EN_LASTFRAME; - - if (vp9_ctx->last.valid && - vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME) - last_frame_info |= RKVDEC_LAST_SHOW_FRAME; - - if (vp9_ctx->last.valid && - vp9_ctx->last.flags & - (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) - last_frame_info |= RKVDEC_LAST_INTRA_ONLY; - - if (vp9_ctx->last.valid && - last->vp9.width == dst->vp9.width && - last->vp9.height == dst->vp9.height) - last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR; - - writel_relaxed(last_frame_info, - rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME); - - writel_relaxed(stream_len - dec_params->compressed_header_size - - dec_params->uncompressed_header_size, - rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE); - - for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) { - unsigned int refw = ref_bufs[i]->vp9.width; - unsigned int refh = ref_bufs[i]->vp9.height; - u32 hscale, vscale; - - hscale = (refw << 14) / dst->vp9.width; - vscale = (refh << 14) / dst->vp9.height; - writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) | - RKVDEC_VP9_REF_VER_SCALE(vscale), - rkvdec->regs + RKVDEC_VP9_REF_SCALE(i)); - } - - addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); - writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); - addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0); - writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); - writel_relaxed(vp9_ctx->priv_tbl.dma + - offsetof(struct rkvdec_vp9_priv_tbl, probs), - rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); - writel_relaxed(vp9_ctx->count_tbl.dma, - rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE); - - writel_relaxed(vp9_ctx->priv_tbl.dma + + /* pack everything that Rust needs in order to run */ + struct rkvdec_rs_run rkvdec_rs_run = { + .base = { + { + .width = ctx->decoded_fmt.fmt.pix_mp.width, + .height = ctx->decoded_fmt.fmt.pix_mp.height, + } + }, + .decode_params = dec_params, + .hw_probs = &((struct rkvdec_vp9_priv_tbl *)vp9_ctx->priv_tbl.cpu)->probs, + .probability_tables = &vp9_ctx->probability_tables, + .src_address = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0), + .probs_address = vp9_ctx->priv_tbl.dma + offsetof(struct rkvdec_vp9_priv_tbl, probs), + .count_base_address = vp9_ctx->count_tbl.dma, + .segid_cur_base_address = vp9_ctx->priv_tbl.dma + offsetof(struct rkvdec_vp9_priv_tbl, segmap) + (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid), - rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE); - writel_relaxed(vp9_ctx->priv_tbl.dma + + .segid_last_base_address = vp9_ctx->priv_tbl.dma + offsetof(struct rkvdec_vp9_priv_tbl, segmap) + (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)), - rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE); - - if (!intra_only && - !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && - vp9_ctx->last.valid) - mv_ref = last; - else - mv_ref = dst; - - writel_relaxed(get_mv_base_addr(mv_ref), - rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE); + .motion_vectors_base_address = get_mv_base_addr(mv_ref), + .dst = { + .resolution = { + .width = dst->vp9.width, + .height = dst->vp9.height, + }, + .bit_depth = dst->vp9.bit_depth, + .same_as_dst = true, + .dma_address = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0), + }, + .ref_bufs = { + [0] = { + { + .width = ref_bufs[0]->vp9.width, + .height = ref_bufs[0]->vp9.height, + + }, + .bit_depth = ref_bufs[0]->vp9.bit_depth, + .same_as_dst = (&ref_bufs[0]->base.vb == run->base.bufs.dst), + .dma_address = vb2_dma_contig_plane_dma_addr(&ref_bufs[0]->base.vb.vb2_buf, 0), + }, + [1] = { + { + .width = ref_bufs[1]->vp9.width, + .height = ref_bufs[1]->vp9.height, + + }, + .bit_depth = ref_bufs[1]->vp9.bit_depth, + .same_as_dst = (&ref_bufs[1]->base.vb == run->base.bufs.dst), + .dma_address = vb2_dma_contig_plane_dma_addr(&ref_bufs[1]->base.vb.vb2_buf, 0), + }, + [2] = { + { + .width = ref_bufs[2]->vp9.width, + .height = ref_bufs[2]->vp9.height, + + }, + .bit_depth = ref_bufs[2]->vp9.bit_depth, + .same_as_dst = (&ref_bufs[2]->base.vb == run->base.bufs.dst), + .dma_address = vb2_dma_contig_plane_dma_addr(&ref_bufs[2]->base.vb.vb2_buf, 0), + } + }, + .last = { + .resolution = { + .width = last->vp9.width, + .height = last->vp9.height, + }, + .bit_depth = last->vp9.bit_depth, + .same_as_dst = (&last->base.vb == run->base.bufs.dst), + .dma_address = vb2_dma_contig_plane_dma_addr(&last->base.vb.vb2_buf, 0), + }, + + .stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0), + .cur_frame_info = { + .valid = vp9_ctx->cur.valid, + .frame_context_idx = vp9_ctx->cur.frame_context_idx, + .reference_mode = vp9_ctx->cur.reference_mode, + .tx_mode = vp9_ctx->cur.tx_mode, + .interpolation_filter = vp9_ctx->cur.interpolation_filter, + .flags = vp9_ctx->cur.flags, + .timestamp = vp9_ctx->cur.timestamp, + .seg = vp9_ctx->cur.seg, + .lf = vp9_ctx->cur.lf, + }, + .last_frame_info = { + .valid = vp9_ctx->last.valid, + .frame_context_idx = vp9_ctx->last.frame_context_idx, + .reference_mode = vp9_ctx->last.reference_mode, + .tx_mode = vp9_ctx->last.tx_mode, + .interpolation_filter = vp9_ctx->last.interpolation_filter, + .flags = vp9_ctx->last.flags, + .timestamp = vp9_ctx->last.timestamp, + .seg = vp9_ctx->last.seg, + .lf = vp9_ctx->last.lf, + }, + .regs = ctx->dev->regs, + }; - writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width | - (ctx->decoded_fmt.fmt.pix_mp.height << 16), - rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE); + rkvdec_rs_vp9_init_probs(&rkvdec_rs_run); + rkvdec_rs_vp9_config_registers(&rkvdec_rs_run); } static int validate_dec_params(struct rkvdec_ctx *ctx, @@ -810,9 +438,6 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) return ret; } - /* Prepare probs. */ - init_probs(ctx, &run); - /* Configure hardware registers. */ config_registers(ctx, &run); diff --git a/drivers/staging/media/rkvdec/rkvdec_rs.h b/drivers/staging/media/rkvdec/rkvdec_rs.h new file mode 100644 index 000000000000..207d0020546c --- /dev/null +++ b/drivers/staging/media/rkvdec/rkvdec_rs.h @@ -0,0 +1,125 @@ +#ifndef RKVDEC_RS_H +#define RKVDEC_RS_H + +/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ + +#include +#include +#include + +struct rkvdec_rs_resolution { + uint32_t width; + uint32_t height; +}; + +struct rkvdec_rs_base_run { + struct rkvdec_rs_resolution decoded_resolution; +}; + +struct rkvdec_rs_vp9_mv { + uint8_t joint[3]; + uint8_t sign[2]; + uint8_t classes[2][10]; + uint8_t class0_bit[2]; + uint8_t bits[2][10]; + uint8_t class0_fr[2][2][3]; + uint8_t fr[2][3]; + uint8_t class0_hp[2]; + uint8_t hp[2]; +}; + +struct rkvdec_rs_vp9_inter_frame_probs { + uint8_t y_mode[4][9]; + uint8_t comp_mode[5]; + uint8_t comp_ref[5]; + uint8_t single_ref[5][2]; + uint8_t inter_mode[7][3]; + uint8_t interp_filter[4][2]; + uint8_t padding0[11]; + uint8_t coef[2][4][2][128]; + uint8_t uv_mode_0_2[3][9]; + uint8_t padding1[5]; + uint8_t uv_mode_3_5[3][9]; + uint8_t padding2[5]; + uint8_t uv_mode_6_8[3][9]; + uint8_t padding3[5]; + uint8_t uv_mode_9[9]; + uint8_t padding4[7]; + uint8_t padding5[16]; + struct rkvdec_rs_vp9_mv mv; +}; + +struct rkvdec_rs_vp9_intra_mode_probs { + uint8_t y_mode[105]; + uint8_t uv_mode[23]; +}; + +struct rkvdec_rs_vp9_intra_only_frame_probs { + uint8_t coef_intra[4][2][128]; + struct rkvdec_rs_vp9_intra_mode_probs intra_mode[10]; +}; + +union rkvdec_rs_vp9_frame_probs { + struct rkvdec_rs_vp9_inter_frame_probs inter; + struct rkvdec_rs_vp9_intra_only_frame_probs intra_only; +}; + +struct rkvdec_rs_vp9_probs { + uint8_t partition[16][3]; + uint8_t pred[3]; + uint8_t tree[7]; + uint8_t skip[3]; + uint8_t tx32[2][3]; + uint8_t tx16[2][2]; + uint8_t tx8[2][1]; + uint8_t is_inter[4]; + uint8_t padding0[3]; + union rkvdec_rs_vp9_frame_probs frame_probs; + uint8_t padding1[11]; +}; + +struct rkvdec_rs_decoded_buffer_info { + struct rkvdec_rs_resolution resolution; + uint8_t bit_depth; + bool same_as_dst; + dma_addr_t dma_address; +}; + +struct rkvdec_rs_frame_info { + bool valid; + uint8_t segmapid; + uint8_t frame_context_idx; + uint8_t reference_mode; + uint8_t tx_mode; + uint8_t interpolation_filter; + uint32_t flags; + uint64_t timestamp; + struct v4l2_vp9_segmentation seg; + struct v4l2_vp9_loop_filter lf; +}; + +struct rkvdec_rs_run { + struct rkvdec_rs_base_run base; + const struct v4l2_ctrl_vp9_frame *decode_params; + struct rkvdec_rs_vp9_probs *hw_probs; + const struct v4l2_vp9_frame_context_rs *probability_tables; + dma_addr_t src_address; + dma_addr_t probs_address; + dma_addr_t count_base_address; + dma_addr_t segid_cur_base_address; + dma_addr_t segid_last_base_address; + dma_addr_t motion_vectors_base_address; + struct rkvdec_rs_decoded_buffer_info dst; + struct rkvdec_rs_decoded_buffer_info ref_bufs[3]; + struct rkvdec_rs_decoded_buffer_info last; + uint32_t stream_len; + struct rkvdec_rs_frame_info cur_frame_info; + struct rkvdec_rs_frame_info last_frame_info; + void *regs; +}; + +void rkvdec_rs_vp9_init_probs(struct rkvdec_rs_run *run); + +void rkvdec_rs_vp9_config_registers(struct rkvdec_rs_run *run); + +#endif /* RKVDEC_RS_H */ diff --git a/drivers/staging/media/rkvdec/rkvdec_rs.rs b/drivers/staging/media/rkvdec/rkvdec_rs.rs new file mode 100644 index 000000000000..a7a48b203225 --- /dev/null +++ b/drivers/staging/media/rkvdec/rkvdec_rs.rs @@ -0,0 +1,14 @@ +#![allow(missing_docs, unused_imports)] + +use kernel::prelude::*; + +const __LOG_PREFIX: &[u8] = b"rkvdec_rs\0"; +pub(crate) mod vp9; +mod common; +mod regs; + +macro_rules! round_up { + ($x:expr, $v:expr) => ((($x - 1) | ($v - 1)) + 1) +} + +pub(crate) use round_up; diff --git a/drivers/staging/media/rkvdec/vp9.rs b/drivers/staging/media/rkvdec/vp9.rs new file mode 100644 index 000000000000..74ea33eedc4c --- /dev/null +++ b/drivers/staging/media/rkvdec/vp9.rs @@ -0,0 +1,636 @@ +#![allow(missing_docs)] + +use crate::common; +use crate::regs; +use crate::round_up; +use kernel::bindings; +use kernel::media::v4l2_core::vp9; + +#[repr(C)] +#[derive(Debug)] +struct DecodedBufferInfo { + resolution: common::Resolution, + bit_depth: u8, + same_as_dst: bool, + dma_address: bindings::dma_addr_t, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct IntraModeProbs { + y_mode: [u8; 105], + uv_mode: [u8; 23], +} + +impl Default for IntraModeProbs { + fn default() -> Self { + Self { + y_mode: [0; 105], + uv_mode: [0; 23], + } + } +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct IntraOnlyFrameProbs { + coef_intra: [[[u8; 128]; 2]; 4], + intra_mode: [IntraModeProbs; 10], +} + +impl Default for IntraOnlyFrameProbs { + fn default() -> Self { + Self { + coef_intra: [[[0; 128]; 2]; 4], + intra_mode: [IntraModeProbs::default(); 10], + } + } +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct Mv { + joint: [u8; 3], + sign: [u8; 2], + classes: [[u8; 10]; 2], + class0_bit: [u8; 2], + bits: [[u8; 10]; 2], + class0_fr: [[[u8; 3]; 2]; 2], + fr: [[u8; 3]; 2], + class0_hp: [u8; 2], + hp: [u8; 2], +} + +impl Default for Mv { + fn default() -> Self { + Self { + joint: [0; 3], + sign: [0; 2], + classes: [[0; 10]; 2], + class0_bit: [0; 2], + bits: [[0; 10]; 2], + class0_fr: [[[0; 3]; 2]; 2], + fr: [[0; 3]; 2], + class0_hp: [0; 2], + hp: [0; 2], + } + } +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct InterFrameProbs { + y_mode: [[u8; 9]; 4], + comp_mode: [u8; 5], + comp_ref: [u8; 5], + single_ref: [[u8; 2]; 5], + inter_mode: [[u8; 3]; 7], + interp_filter: [[u8; 2]; 4], + padding0: [u8; 11], + coef: [[[[u8; 128]; 2]; 4]; 2], + uv_mode_0_2: [[u8; 9]; 3], + padding1: [u8; 5], + uv_mode_3_5: [[u8; 9]; 3], + padding2: [u8; 5], + uv_mode_6_8: [[u8; 9]; 3], + padding3: [u8; 5], + uv_mode_9: [u8; 9], + padding4: [u8; 7], + padding5: [u8; 16], + mv: Mv, +} + +impl Default for InterFrameProbs { + fn default() -> Self { + Self { + y_mode: [[0; 9]; 4], + comp_mode: [0; 5], + comp_ref: [0; 5], + single_ref: [[0; 2]; 5], + inter_mode: [[0; 3]; 7], + interp_filter: [[0; 2]; 4], + padding0: [0; 11], + coef: [[[[0; 128]; 2]; 4]; 2], + uv_mode_0_2: [[0; 9]; 3], + padding1: [0; 5], + uv_mode_3_5: [[0; 9]; 3], + padding2: [0; 5], + uv_mode_6_8: [[0; 9]; 3], + padding3: [0; 5], + uv_mode_9: [0; 9], + padding4: [0; 7], + padding5: [0; 16], + mv: Mv::default(), + } + } +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct HwProbs { + partition: [[u8; 3]; 16], + pred: [u8; 3], + tree: [u8; 7], + skip: [u8; 3], + tx32: [[u8; 3]; 2], + tx16: [[u8; 2]; 2], + tx8: [[u8; 1]; 2], + is_inter: [u8; 4], + padding0: [u8; 3], + frame_probs: FrameProbs, + padding1: [u8; 11], +} + +impl Default for HwProbs { + fn default() -> Self { + Self { + partition: [[0; 3]; 16], + pred: [0; 3], + tree: [0; 7], + skip: [0; 3], + tx32: [[0; 3]; 2], + tx16: [[0; 2]; 2], + tx8: [[0; 1]; 2], + is_inter: [0; 4], + padding0: [0; 3], + frame_probs: FrameProbs { + inter: InterFrameProbs::default(), + }, + padding1: [0; 11], + } + } +} + +#[repr(C)] +#[derive(Copy, Clone)] +union FrameProbs { + inter: InterFrameProbs, + intra_only: IntraOnlyFrameProbs, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct RefReg { + reg_frm_size: u32, + reg_hor_stride: u32, + reg_y_stride: u32, + reg_yuv_stride: u32, + reg_ref_base: u32, +} + +static REF_REGS: [RefReg; 3] = { + [ + RefReg { + reg_frm_size: regs::RKVDEC_REG_VP9_FRAME_SIZE!(0), + reg_hor_stride: regs::RKVDEC_VP9_HOR_VIRSTRIDE!(0), + reg_y_stride: regs::RKVDEC_VP9_LAST_FRAME_YSTRIDE, + reg_yuv_stride: regs::RKVDEC_VP9_LAST_FRAME_YUVSTRIDE, + reg_ref_base: regs::RKVDEC_REG_VP9_LAST_FRAME_BASE, + }, + RefReg { + reg_frm_size: regs::RKVDEC_REG_VP9_FRAME_SIZE!(1), + reg_hor_stride: regs::RKVDEC_VP9_HOR_VIRSTRIDE!(1), + reg_y_stride: regs::RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE, + reg_yuv_stride: 0, + reg_ref_base: regs::RKVDEC_REG_VP9_GOLDEN_FRAME_BASE, + }, + RefReg { + reg_frm_size: regs::RKVDEC_REG_VP9_FRAME_SIZE!(2), + reg_hor_stride: regs::RKVDEC_VP9_HOR_VIRSTRIDE!(2), + reg_y_stride: regs::RKVDEC_VP9_ALTREF_FRAME_YSTRIDE, + reg_yuv_stride: 0, + reg_ref_base: regs::RKVDEC_REG_VP9_ALTREF_FRAME_BASE, + }, + ] +}; + +#[repr(C)] +struct FrameInfo { + valid: bool, + segmapid: u8, + frame_context_idx: u8, + reference_mode: u8, + tx_mode: u8, + interpolation_filter: u8, + flags: u32, + timestamp: u64, + seg: bindings::v4l2_vp9_segmentation, + lf: bindings::v4l2_vp9_loop_filter, +} + +#[repr(C)] +pub(crate) struct Run<'a> { + base: crate::common::BaseRun, + decode_params: &'a bindings::v4l2_ctrl_vp9_frame, + hw_probs: &'a mut HwProbs, + probability_tables: &'a vp9::FrameContext, + src_address: bindings::dma_addr_t, + probs_address: bindings::dma_addr_t, + count_base_address: bindings::dma_addr_t, + segid_cur_base_address: bindings::dma_addr_t, + segid_last_base_address: bindings::dma_addr_t, + motion_vectors_base_address: bindings::dma_addr_t, + dst: DecodedBufferInfo, + ref_bufs: [DecodedBufferInfo; 3], + last: DecodedBufferInfo, + stream_len: u32, + cur_frame_info: FrameInfo, + last_frame_info: FrameInfo, + regs: *mut core::ffi::c_void, +} + +impl<'a> Run<'a> { + fn write_register(&self, val: impl Into, offset: u32) { + if offset > regs::RKVDEC_REG_PREF_CHR_CACHE_COMMAND { + kernel::pr_warn!( + "Invalid register offset: 0x{:x}, ignoring\n", + offset as usize + ); + return; + } + + // Safety: if we're here, C has mapped this range for us. So long as we + // write within it, we are safe. + unsafe { + let addr = self.regs.add(offset as usize); + bindings::writel_relaxed(val.into(), addr); + } + } + + fn write_coeff_plane(coef: &[[[u8; 3]; 6]; 6], coef_plane: &mut [u8; 128]) { + let mut idx = 0; + let mut byte_count = 0; + for coef in coef.iter().flatten().flatten() { + coef_plane[idx] = *coef; + idx += 1; + byte_count += 1; + + if byte_count == 27 { + idx += 5; + byte_count = 0; + } + } + } + + fn init_intra_only_probs(&mut self) { + // Safety: this was zero-initialized and we only write to it here. + let rkprobs = unsafe { &mut self.hw_probs.frame_probs.intra_only }; + let probs = self.probability_tables; + + for i in 0..probs.coef.len() { + for j in 0..probs.coef[0].len() { + Self::write_coeff_plane(&probs.coef[i][j][0], &mut rkprobs.coef_intra[i][j]); + } + } + + for i in 0..vp9::v4l2_vp9_kf_y_mode_prob_rs.len() { + let mut byte_count = 0; + let mut idx = 0; + + for j in 0..vp9::v4l2_vp9_kf_y_mode_prob_rs[0].len() { + for k in 0..vp9::v4l2_vp9_kf_y_mode_prob_rs[0][0].len() { + let val = vp9::v4l2_vp9_kf_y_mode_prob_rs[i][j][k]; + + rkprobs.intra_mode[i].y_mode[idx] = val; + + idx += 1; + byte_count += 1; + + if byte_count == 27 { + byte_count = 0; + idx += 5; + } + } + } + } + + for (i, uv_mode) in vp9::v4l2_vp9_kf_uv_mode_prob_rs + .iter() + .flatten() + .enumerate() + { + rkprobs.intra_mode[i / 23].uv_mode[i % 23] = *uv_mode; + } + } + + fn init_inter_probs(&mut self) { + // Safety: this was zero-initialized and we only write to it here. + let rkprobs = unsafe { &mut self.hw_probs.frame_probs.inter }; + let probs = self.probability_tables; + + rkprobs.y_mode = probs.y_mode; + rkprobs.comp_mode = probs.comp_mode; + rkprobs.comp_ref = probs.comp_ref; + rkprobs.single_ref = probs.single_ref; + rkprobs.inter_mode = probs.inter_mode; + rkprobs.interp_filter = probs.interp_filter; + + for (i, coef_i) in probs.coef.iter().enumerate() { + for (j, coef_j) in coef_i.iter().enumerate() { + for (k, _coef_k) in coef_j.iter().enumerate() { + Self::write_coeff_plane(&coef_j[k], &mut rkprobs.coef[k][i][j]); + } + } + } + + rkprobs.uv_mode_0_2.copy_from_slice(&probs.uv_mode[0..3]); + rkprobs.uv_mode_3_5.copy_from_slice(&probs.uv_mode[3..6]); + rkprobs.uv_mode_6_8.copy_from_slice(&probs.uv_mode[6..9]); + rkprobs.uv_mode_9 = probs.uv_mode[9]; + + rkprobs.mv.joint = probs.mv.joint; + rkprobs.mv.sign = probs.mv.sign; + rkprobs.mv.classes = probs.mv.classes; + rkprobs.mv.class0_bit = probs.mv.class0_bit; + rkprobs.mv.class0_bit = probs.mv.class0_bit; + rkprobs.mv.bits = probs.mv.bits; + rkprobs.mv.class0_fr = probs.mv.class0_fr; + rkprobs.mv.fr = probs.mv.fr; + rkprobs.mv.class0_hp = probs.mv.class0_hp; + rkprobs.mv.hp = probs.mv.hp; + } + + pub(crate) fn init_probs(&mut self) { + *self.hw_probs = Default::default(); + + let intra_only = self.decode_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0 + || self.decode_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0; + + if intra_only { + self.hw_probs.partition = vp9::v4l2_vp9_kf_partition_probs_rs; + } else { + self.hw_probs.partition = self.probability_tables.partition; + } + + self.hw_probs.pred = self.decode_params.seg.pred_probs; + self.hw_probs.tree = self.decode_params.seg.tree_probs; + self.hw_probs.skip = self.probability_tables.skip; + self.hw_probs.tx32 = self.probability_tables.tx32; + self.hw_probs.tx16 = self.probability_tables.tx16; + self.hw_probs.tx8 = self.probability_tables.tx8; + self.hw_probs.is_inter = self.probability_tables.is_inter; + + if intra_only { + self.init_intra_only_probs(); + } else { + self.init_inter_probs(); + } + } + + fn config_ref_registers(&mut self) { + for (ref_buf, ref_reg) in self.ref_bufs.iter().zip(&REF_REGS) { + let aligned_height = round_up!(ref_buf.resolution.height, 64); + + self.write_register( + regs::RKVDEC_VP9_FRAMEWIDTH!(ref_buf.resolution.width) + | regs::RKVDEC_VP9_FRAMEHEIGHT!(ref_buf.resolution.height), + ref_reg.reg_frm_size, + ); + + self.write_register( + u32::try_from(ref_buf.dma_address).unwrap(), + ref_reg.reg_ref_base, + ); + + if ref_buf.same_as_dst { + continue; + } + + let aligned_pitch = + round_up!(ref_buf.resolution.width * u32::from(ref_buf.bit_depth), 512) / 8; + let y_len = aligned_height * aligned_pitch; + let yuv_len = (y_len * 3) / 2; + + self.write_register( + regs::RKVDEC_HOR_Y_VIRSTRIDE!(aligned_pitch / 16) + | regs::RKVDEC_HOR_UV_VIRSTRIDE!(aligned_pitch / 16), + ref_reg.reg_hor_stride, + ); + + self.write_register( + regs::RKVDEC_VP9_REF_YSTRIDE!(y_len / 16), + ref_reg.reg_y_stride, + ); + + if ref_reg.reg_yuv_stride == 0 { + continue; + } + + self.write_register( + regs::RKVDEC_VP9_REF_YUVSTRIDE!(yuv_len / 16), + ref_reg.reg_yuv_stride, + ); + } + } + + fn config_seg_registers(&mut self) { + let seg = if self.last_frame_info.valid { + &self.last_frame_info.seg + } else { + &self.cur_frame_info.seg + }; + + for i in 0..seg.feature_enabled.len() { + let mut val = 0; + let mut feature_val; + let seg_flags = u32::from(seg.flags); + + let feature_id = bindings::V4L2_VP9_SEG_LVL_ALT_Q; + if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) { + feature_val = seg.feature_data[i][feature_id as usize]; + val |= regs::RKVDEC_SEGID_FRAME_QP_DELTA_EN!(1) + | regs::RKVDEC_SEGID_FRAME_QP_DELTA!(feature_val as u32); + } + + let feature_id = bindings::V4L2_VP9_SEG_LVL_ALT_L; + if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) { + feature_val = seg.feature_data[i][feature_id as usize]; + val |= regs::RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN!(1) + | regs::RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE!(feature_val as u32); + } + + let feature_id = bindings::V4L2_VP9_SEG_LVL_REF_FRAME; + if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) { + feature_val = seg.feature_data[i][feature_id as usize]; + val |= regs::RKVDEC_SEGID_REFERINFO_EN!(1) + | regs::RKVDEC_SEGID_REFERINFO!(feature_val as u32); + } + + let feature_id = bindings::V4L2_VP9_SEG_LVL_SKIP; + if vp9::seg_feat_enabled(&seg.feature_enabled, feature_id, i as u32) { + val |= regs::RKVDEC_SEGID_FRAME_SKIP_EN!(1); + } + + if i == 0 && (seg_flags & bindings::V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE != 0) + { + val |= regs::RKVDEC_SEGID_ABS_DELTA!(1) + } + + self.write_register(val, regs::RKVDEC_VP9_SEGID_GRP!(i as u32)); + } + } + + pub(crate) fn config_registers(&mut self) { + let dec_params = self.decode_params; + let intra_only = dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME != 0 + || dec_params.flags & bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY != 0; + + self.write_register( + regs::RKVDEC_MODE!(regs::RKVDEC_MODE_VP9), + regs::RKVDEC_REG_SYSCTRL, + ); + + let bit_depth = u32::from(dec_params.bit_depth); + let aligned_height = round_up!(self.base.decoded_resolution.height, 64); + let aligned_pitch = round_up!(self.base.decoded_resolution.width * bit_depth, 512) / 8; + + let y_len = aligned_height * aligned_pitch; + let uv_len = y_len / 2; + let yuv_len = y_len + uv_len; + + self.write_register( + regs::RKVDEC_Y_HOR_VIRSTRIDE!(aligned_pitch / 16) + | regs::RKVDEC_UV_HOR_VIRSTRIDE!(aligned_pitch / 16), + regs::RKVDEC_REG_PICPAR, + ); + + self.write_register( + regs::RKVDEC_Y_VIRSTRIDE!(y_len / 16), + regs::RKVDEC_REG_Y_VIRSTRIDE, + ); + self.write_register( + regs::RKVDEC_YUV_VIRSTRIDE!(yuv_len / 16), + regs::RKVDEC_REG_YUV_VIRSTRIDE, + ); + self.write_register( + regs::RKVDEC_STRM_LEN!(self.stream_len), + regs::RKVDEC_REG_STRM_LEN, + ); + + self.config_ref_registers(); + self.config_seg_registers(); + + let tx_mode = self.cur_frame_info.tx_mode; + + self.write_register( + regs::RKVDEC_VP9_TX_MODE!(tx_mode) + | regs::RKVDEC_VP9_FRAME_REF_MODE!(dec_params.reference_mode), + regs::RKVDEC_VP9_CPRHEADER_CONFIG, + ); + + let mut last_frame_info = 0; + if !intra_only { + let lf = if self.last_frame_info.valid { + &self.last_frame_info.lf + } else { + &self.cur_frame_info.lf + }; + + let mut val = 0; + for (i, delta) in lf.ref_deltas.iter().enumerate() { + val |= regs::RKVDEC_REF_DELTAS_LASTFRAME!(i, *delta as u32); + } + + self.write_register(val, regs::RKVDEC_VP9_REF_DELTAS_LASTFRAME); + + for (i, delta) in lf.mode_deltas.iter().enumerate() { + last_frame_info |= regs::RKVDEC_MODE_DELTAS_LASTFRAME!(i, *delta as u32); + } + } + + let seg_flags = u32::from(dec_params.seg.flags); + if self.last_frame_info.valid + && !intra_only + && seg_flags & bindings::V4L2_VP9_SEGMENTATION_FLAG_ENABLED != 0 + { + last_frame_info |= regs::RKVDEC_SEG_EN_LASTFRAME; + } + + if self.last_frame_info.valid + && self.last_frame_info.flags & bindings::V4L2_VP9_FRAME_FLAG_SHOW_FRAME != 0 + { + last_frame_info |= regs::RKVDEC_LAST_SHOW_FRAME; + } + + if self.last_frame_info.valid + && self.last_frame_info.flags + & (bindings::V4L2_VP9_FRAME_FLAG_KEY_FRAME + | bindings::V4L2_VP9_FRAME_FLAG_INTRA_ONLY) + != 0 + { + last_frame_info |= regs::RKVDEC_LAST_INTRA_ONLY; + } + + if self.last_frame_info.valid && self.last.resolution == self.dst.resolution { + last_frame_info |= regs::RKVDEC_LAST_WIDHHEIGHT_EQCUR; + } + + self.write_register(last_frame_info, regs::RKVDEC_VP9_INFO_LASTFRAME); + let last_tile_size = self.stream_len + - u32::from(dec_params.compressed_header_size) + - u32::from(dec_params.uncompressed_header_size); + + self.write_register(last_tile_size, regs::RKVDEC_VP9_LASTTILE_SIZE); + + for i in 0..REF_REGS.len() { + if intra_only { + break; + } + + let refw = self.ref_bufs[i].resolution.width; + let refh = self.ref_bufs[i].resolution.height; + let hscale = (refw << 14) / self.dst.resolution.width; + let vscale = (refh << 14) / self.dst.resolution.height; + + self.write_register( + regs::RKVDEC_VP9_REF_HOR_SCALE!(hscale) | regs::RKVDEC_VP9_REF_VER_SCALE!(vscale), + regs::RKVDEC_VP9_REF_SCALE!(i as u32), + ); + } + + self.write_register( + u32::try_from(self.dst.dma_address).unwrap(), + regs::RKVDEC_REG_DECOUT_BASE, + ); + self.write_register( + u32::try_from(self.src_address).unwrap(), + regs::RKVDEC_REG_STRM_RLC_BASE, + ); + + self.write_register( + u32::try_from(self.probs_address).unwrap(), + regs::RKVDEC_REG_CABACTBL_PROB_BASE, + ); + self.write_register( + u32::try_from(self.count_base_address).unwrap(), + regs::RKVDEC_REG_VP9COUNT_BASE, + ); + self.write_register( + u32::try_from(self.segid_cur_base_address).unwrap(), + regs::RKVDEC_REG_VP9_SEGIDCUR_BASE, + ); + self.write_register( + u32::try_from(self.segid_last_base_address).unwrap(), + regs::RKVDEC_REG_VP9_SEGIDLAST_BASE, + ); + + self.write_register( + u32::try_from(self.motion_vectors_base_address).unwrap(), + regs::RKVDEC_VP9_REF_COLMV_BASE, + ); + self.write_register( + self.base.decoded_resolution.width | (self.base.decoded_resolution.height << 16), + regs::RKVDEC_REG_PERFORMANCE_CYCLE, + ); + } +} + +#[no_mangle] +pub(crate) extern "C" fn rkvdec_rs_vp9_init_probs(run: &mut Run<'_>) { + run.init_probs(); +} + +#[no_mangle] +pub(crate) extern "C" fn rkvdec_rs_vp9_config_registers(run: &mut Run<'_>) { + run.config_registers(); +} diff --git a/rust/helpers.c b/rust/helpers.c index d146bbf25aec..fde0520e1d57 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -20,6 +20,7 @@ * Sorted alphabetically. */ +#include "asm/io.h" #include #include #include @@ -272,3 +273,9 @@ static_assert( __alignof__(size_t) == __alignof__(uintptr_t), "Rust code expects C `size_t` to match Rust `usize`" ); + +void rust_helper_writel_relaxed(u32 val, void *addr) +{ + writel_relaxed(val, addr); +} +EXPORT_SYMBOL_GPL(rust_helper_writel_relaxed);