SVT-AV1源码分析函数 svt_av1_cost_coeffs_txb

devtools/2025/3/17 1:31:38/

一 函数作用说明

svt_av1_cost_coeffs_txb 用于计算变换块(Transform Block, TXB)中量化系数的码率失真成本(Rate - Distortion Cost).

该函数在视频编码 如AV1 的模式决策,阶段被调用,目的是评估当前变换块编码的比特率和失真的权衡,从而选择最佳的模式。

参数说明:

// Note: don't call this function when eob is 0.

uint64_t svt_av1_cost_coeffs_txb(

struct ModeDecisionContext *ctx, //模式决策上下文,包含编码参数,中间计算结果,概率模型,量化参数,以及算法控制标志

uint8_t allow_update_cdf,//是否允许更新上下文自适应二进制算数编码CABAC的概率模型,CDF,通常为0

FRAME_CONTEXT *ec_ctx,//帧级别的熵编码上下文,存储符号的概率分别模型,用于比特率估算。

struct ModeDecisionCandidateBuffer *cand_bf, //候选模式缓冲区,存储当前候选模式的数据 比如量化系数,预测模式等

const TranLow *const qcoeff,//量化后的变换系数数组指针

uint16_t eob,//变换块的非零系数结束为止End of Block 即最后一个非零系数的索引

PlaneType plane_type, //通道类型,Y/UV

TxSize transform_size, //变换村村,

TxType transform_type,//变换类型 DCT, ADST等

int16_t txb_skip_ctx, //变换块是否跳过上下文索引,用于熵编码概率模型的选择

int16_t dc_sign_ctx, //DC系数符号上下文索引,用于熵编码概率模型的选择

Bool reduced_transform_set_flag //是否使用简化的变换集

)

1.1 初始化上下文

根据plane_type 和transform_size 获取对应的熵编码概率模型(CDF表)

确定是否需要跳过当前块的编码 通过txb_skip_ctx 上下文

1.2 计算跳过块的代价

若块中所有系数均为零(eob == 0) ,直接计算跳过块的比特率成本。

1.3 计算非跳过块的代价

DC系数处理,

计算DC系数的符号Sign和幅值 的编码成本。

AC系数处理

逆扫描通过扫描顺序表 遍历所有非零AC系数,计算每一点的

幅值编码成本(包括二进制化,旁路编码)

符号编码成本(仅对非零系数)

EOB 位置编码

编码ROB位置的额外比特开销。

1.4 码率失真

结合量化系数失真(通常预计算并存储在cand_bf中)和比特率成本,生成最终的码率失真代价

RDCost = lambda * rate + Distortion

1.5 更新概率模型

若allow_update_cdf为1,根据实际编码结果更新 CDF 表,以提升后续符号的编码效率。

CDF:表示符号的概率累积分布表,例如,某个二进制符号的概率模型可能初始化为{0.5,0.5} 但是随着编码数据的变化,CDF会逐步更新为{0.3,0.7}等。

二 函数源码分析

uint64_t svt_av1_cost_coeffs_txb(

struct ModeDecisionContext *ctx,

uint8_t allow_update_cdf,

FRAME_CONTEXT *ec_ctx,

struct ModeDecisionCandidateBuffer *cand_bf,

const TranLow *const qcoeff,

uint16_t eob,

PlaneType plane_type,

TxSize transform_size,

TxType transform_type,

int16_t txb_skip_ctx,

int16_t dc_sign_ctx,

Bool reduced_transform_set_flag)

{

//Note: there is a different version of this function in AOM that seems to be efficient as its name is:

//warehouse_efficients_txb

//计算变换尺寸的上下文索引

const TxSize txs_ctx = (TxSize)((txsize_sqr_map[transform_size] + txsize_sqr_up_map[transform_size] + 1) >> 1);

//获取变换类别

const TxClass tx_class = tx_type_to_class[transform_type];

//获取变换块的对数宽度

int32_t cost;

const int32_t bwl = get_txb_bwl_tab[transform_size];

//获取变换块的宽度和高度

const int32_t width = get_txb_wide_tab[transform_size];

const int32_t height = get_txb_high_tab[transform_size];

//获取扫描顺序

const ScanOrder *const scan_order = &av1_scan_orders[transform_size][transform_type]; // get_scan(tx_size, tx_type);//根据变换块尺寸和类型获取扫描顺序

const int16_t *const scan = scan_order->scan;//定义存储系数级别的缓冲区

uint8_t levels_buf[TX_PAD_2D];

uint8_t *const levels = set_levels(levels_buf, width);

//断言txs_ctx 在有效范围内

DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);

assert(txs_ctx < TX_SIZES);

//获取系数成本表

const LvMapCoeffCost *const coeff_costs = &ctx->md_rate_est_ctx->coeff_fac_bits[txs_ctx][plane_type];

//计算eob多尺寸索引

const int32_t eob_multi_size = txsize_log2_minus4[transform_size];

//获取 eob成本表

const LvMapEobCost *const eob_bits = &ctx->md_rate_est_ctx->eob_frac_bits[eob_multi_size][plane_type];

// eob must be greater than 0 here.

//断言eob > 0

assert(eob > 0);

//初始化成本为跳过变换块的成本

cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];

//如果允许更新CDF

if (allow_update_cdf)

//更新跳过变换块的CDF

update_cdf(ec_ctx->txb_skip_cdf[txs_ctx][txb_skip_ctx], eob == 0, 2);

//如果eob 大雨1,初始化系数级别

if (eob > 1)

svt_av1_txb_init_levels(qcoeff,

width,

height,

levels); // NM - Needs to be optimized - to be combined with the quantisation.

//初始化系数级别,可能需要优化并与量化结合

//判断是否为帧间模式

const Bool is_inter = is_inter_mode(cand_bf->cand->pred_mode);

// Transform type bit estimation

//添加变换类型比特估计

cost += plane_type > PLANE_TYPE_Y ? 0

: av1_transform_type_rate_estimation(ctx,

allow_update_cdf,

ec_ctx,

cand_bf,

is_inter,

transform_size,

transform_type,

reduced_transform_set_flag);

//计算eob成本

// Transform eob bit estimation

int32_t eob_cost = get_eob_cost(eob, eob_bits, coeff_costs, tx_class);

cost += eob_cost;

//如果允许更新CDF,更新eob上下文

if (allow_update_cdf)

svt_av1_update_eob_context(eob, transform_size, tx_class, plane_type, ec_ctx, allow_update_cdf);

//获取非零系数上下文

// Transform non-zero coeff bit estimation

svt_av1_get_nz_map_contexts(levels,

scan,

eob,

transform_size,

tx_class,

coeff_contexts); // NM - Assembly version is available in AOM //获取非零系数上下文

//AOM有汇编版本, 断言eob不超过宽度乘以高度

assert(eob <= width * height);

//如果允许更新CDF

if (allow_update_cdf) {

//遍历系数

for (int c = eob - 1; c >= 0; --c) {

//获取扫描位置

const int pos = scan[c];

//获取系数上下文

const int coeff_ctx = coeff_contexts[pos];

//获取量化系数

const TranLow v = qcoeff[pos];

//获取系数级别

const TranLow level = abs(v);

//如果是最后一个系数

if (c == eob - 1) {

//断言系数上下文在有效范围内

assert(coeff_ctx < 4);

//更新eob 基础CDF update_cdf(ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx], AOMMIN(level, 3) - 1, 3);

} else {

//更新基础CDF update_cdf(ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx], AOMMIN(level, 3), 4);

}

//如果启用熵统计

{

if (c == eob - 1) {

assert(coeff_ctx < 4);

#if CONFIG_ENTROPY_STATS

++td->counts

->coeff_base_eob_multi[cdf_idx][txsize_ctx][plane_type][coeff_ctx][AOMMIN(level, 3) - 1];

} else {

++td->counts->coeff_base_multi[cdf_idx][txsize_ctx][plane_type][coeff_ctx][AOMMIN(level, 3)];

#endif

}

}

//如果级别超过基础级别

if (level > NUM_BASE_LEVELS) {

//计算基础范围

const int base_range = level - 1 - NUM_BASE_LEVELS;

int br_ctx;

//确定br上下文

if (eob == 1)

br_ctx = 0;

else

br_ctx = get_br_ctx(levels, pos, bwl, tx_class);

//更新br CDF

for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {

const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);

update_cdf(ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)][plane_type][br_ctx], k, BR_CDF_SIZE);

//处理LPS

for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {

#if CONFIG_ENTROPY_STATS

++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type][lps][br_ctx][lps == k];

#endif // CONFIG_ENTROPY_STATS

if (lps == k)

break;

}

#if CONFIG_ENTROPY_STATS

++td->counts->coeff_lps_multi[cdf_idx][AOMMIN(txsize_ctx, TX_32X32)][plane_type][br_ctx][k];

#endif

if (k < BR_CDF_SIZE - 1)

break;

}

}

}

//如果直流系数不是0,更新直流符号CDF

if (qcoeff[0] != 0)

update_cdf(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], qcoeff[0] < 0, 2);

//检查对于128x128, 需要在每个Txb的基础上更新txb_context (dc_sign + skip_ctx)

//返回0, 表示更新CDF完成

//TODO: CHKN for 128x128 where we need more than one TXb, we need to update the txb_context(dc_sign+skip_ctx) in a Txb basis

return 0;

}

//计算系数成本并返回, 系数已经经过了调整了 ,重新计算一次成本

cost += av1_cost_coeffs_txb_loop_cost_eob(

ctx, eob, scan, qcoeff, coeff_contexts, coeff_costs, dc_sign_ctx, levels, bwl, transform_type);

return cost;

}


http://www.ppmy.cn/devtools/167701.html

相关文章

starrocks批量启停脚本

#!/bin/bash # 定义 StarRocks 安装目录 STARROCKS_HOME"/path/to/starrocks" # 定义 FE 和 BE 节点列表 FE_NODES("fe_node1_ip" "fe_node2_ip" "fe_node3_ip") BE_NODES("be_node1_ip" "be_node2_ip" "be_…

[023-01-40].第40节:组件应用 - OpenFeign与 Sentinel 集成实现fallback服务降级

SpringCloud学习大纲 一、需求说明&#xff1a; 需求1&#xff1a;通过fallback属性进行统一配置 a.问题分析&#xff1a; 1.需要实现cloudalibaba-consumer-nacos-order83模块通过OpenFeign调用cloudalibaba-provider-payment9001 83服务通过OpenFeign调用 9001微服务&…

玩转github

me github 可以给仓库添加开发人员吗 4o 是的&#xff0c;GitHub允许仓库管理员为仓库添加开发人员&#xff0c;并设置这些开发人员的角色和权限。这里是一个简单的步骤指导&#xff0c;教你如何给一个 GitHub 仓库添加开发人员&#xff1a; 前提条件 你必须有这个仓库的权限&…

DICOM开发者常用DICOM开源库详解

DICOM开发工具与开源库,涵盖C++、C#、Python、Java、JavaScript等多种编程语言。这些库在功能、性能和社区支持方面各有优势,开发者可根据项目需求选择合适的工具。 DICOM开发工具与开源库详解 一、C++库 1. DCMTK(DICOM Toolkit) </

LinkedList底层结构和源码分析(JDK1.8)

参考视频&#xff1a;韩顺平Java集合 特点 LinkedList 底层实现了 双向链表 和 双端队列 的特点。可以添加任意元素&#xff08;元素可以重复&#xff09;&#xff0c;包括 null。线程不安全&#xff0c;没有实现同步。 LinkedList 底层结构 LinkedList 底层维护了一个双向链…

maven笔记

maven介绍和作用 Maven 是一款为 Java 项目构建管理、依赖管理的工具&#xff08;软件&#xff09;&#xff0c;使用 Maven 可以自动化构建、测试、打包和发布项目&#xff0c;大大提高了开发效率和质量。 主要作用的理解&#xff1a; 依赖管理&#xff1a; 在编写项目时我…

数学 :矩阵

文章目录 前言1. 基本矩阵运算1.1 矩阵加法1.2 矩阵减法1.3 矩阵乘法 2. 转置矩阵3. 旋转矩阵小结 【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 前言 在许多应用场合下&#xff0c;我们都需要用矩阵来表示公式&#xff0c;接下来简洁描述矩阵…

【初级篇】如何使用DeepSeek和Dify构建高效的企业级智能客服系统

在当今数字化时代,企业面临着日益增长的客户服务需求。使用Dify创建智能客服不仅能够提升客户体验,还能显著提高企业的运营效率。关于DIfy的安装部署,大家可以参考之前的文章: 【入门级篇】Dify安装+DeepSeek模型配置保姆级教程_mindie dify deepseek-CSDN博客 AI智能客服…