libaom中的变换块以及rdoq过程

一 av1支持的变换块大小枚举

enum {

TX_4X4, // 4x4 transform

TX_8X8, // 8x8 transform

TX_16X16, // 16x16 transform

TX_32X32, // 32x32 transform

TX_64X64, // 64x64 transform

TX_4X8, // 4x8 transform

TX_8X4, // 8x4 transform

TX_8X16, // 8x16 transform

TX_16X8, // 16x8 transform

TX_16X32, // 16x32 transform

TX_32X16, // 32x16 transform

TX_32X64, // 32x64 transform

TX_64X32, // 64x32 transform

TX_4X16, // 4x16 transform

TX_16X4, // 16x4 transform

TX_8X32, // 8x32 transform

TX_32X8, // 32x8 transform

TX_16X64, // 16x64 transform

TX_64X16, // 64x16 transform

TX_SIZES_ALL, // Includes rectangular transforms

TX_SIZES = TX_4X8, // Does NOT include rectangular transforms

TX_SIZES_LARGEST = TX_64X64,

TX_INVALID = 255 // Invalid transform size

} UENUM1BYTE(TX_SIZE);

获取TXB 上下文函数 SPECIALIZE_GET_TXB_CTX(w, h)

#define SPECIALIZE_GET_TXB_CTX(w, h)

当然可以,下面是对宏 `SPECIALIZE_GET_TXB_CTX(w, h)` 中每一行的注释:

#define SPECIALIZE_GET_TXB_CTX(w, h)                                          \
  /  定义一个静态函数,用于获取特定大小的变换块上下文  /                \
  static void get_txb_ctx_##w##x##h(                                          \
      const BLOCK_SIZE plane_bsize, const int plane,                          \
      const ENTROPY_CONTEXT  const a, const ENTROPY_CONTEXT  const l,         \
      TXB_CTX *const txb_ctx) {                                               \
    /  静态数组,用于符号的上下文,0表示没有符号,-1和1分别表示负号和正号  / \
    static const int8_t signs[3] = { 0, -1, 1 };                              \
    /  静态数组,用于直流(DC)符号的上下文  /                                \
    static const int8_t dc_sign_contexts[4 * MAX_TX_SIZE_UNIT + 1] = {        \
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  \
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  \
      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2           \
    };                                                                        \
    /  获取变换块的大小枚举值  /                                              \
    const TX_SIZE tx_size = TX_##w##X##h;                                     \
    /  获取变换块宽度的单位数  /                                              \
    const int txb_w_unit = tx_size_wide_unit[tx_size];                        \
    /  获取变换块高度的单位数  /                                              \
    const int txb_h_unit = tx_size_high_unit[tx_size];                        \
    /  用于累加符号的变量  /                                                   \
    int dc_sign = 0;                                                          \
    /  循环变量  /                                                            \
    int k = 0;                                                                \
                                                                              \
    /  循环累加上方的符号上下文  /                                           \
    do {                                                                      \
      const unsigned int sign = ((uint8_t)a[k]) >> COEFF_CONTEXT_BITS;        \
      assert(sign <= 2);                                                      \
      dc_sign += signs[sign];                                                 \
    } while (++k < txb_w_unit);                                               \
                                                                              \
    /  重置循环变量  /                                                       \
    k = 0;                                                                    \
    /  循环累加左侧的符号上下文  /                                           \
    do {                                                                      \
      const unsigned int sign = ((uint8_t)l[k]) >> COEFF_CONTEXT_BITS;        \
      assert(sign <= 2);                                                      \
      dc_sign += signs[sign];                                                 \
    } while (++k < txb_h_unit);                                               \
                                                                              \
    /  设置直流符号上下文  /                                                  \
    txb_ctx->dc_sign_ctx = dc_sign_contexts[dc_sign + 2 * MAX_TX_SIZE_UNIT];  \
                                                                              \
    /  如果是Y平面(plane == 0)  /                                          \
    if (plane == 0) {                                                         \
      /  如果变换块大小与平面块大小相同,则跳过上下文为0  /                 \
      if (plane_bsize == txsize_to_bsize[tx_size]) {                          \
        txb_ctx->txb_skip_ctx = 0;                                            \
      } else {                                                                \
        /  跳过上下文的数组  /                                                \
        static const uint8_t skip_contexts[5][5] = { { 1, 2, 2, 2, 3 },       \
                                                     { 2, 4, 4, 4, 5 },       \
                                                     { 2, 4, 4, 4, 5 },       \
                                                     { 2, 4, 4, 4, 5 },       \
                                                     { 3, 5, 5, 5, 6 } };     \
        /  用于累加上方的跳过上下文  /                                        \
        int top = 0;                                                          \
        /  用于累加左侧的跳过上下文  /                                        \
        int left = 0;                                                         \
                                                                              \
        /  循环累加上方的跳过上下文  /                                        \
        k = 0;                                                                \
        do {                                                                  \
          top |= a[k];                                                        \
        } while (++k < txb_w_unit);                                           \
        top &= COEFF_CONTEXT_MASK;                                            \
        top = AOMMIN(top, 4);                                                 \
                                                                              \
        /  循环累加左侧的跳过上下文  /                                        \
        k = 0;                                                                \
        do {                                                                  \
          left |= l[k];                                                       \
        } while (++k < txb_h_unit);                                           \
        left &= COEFF_CONTEXT_MASK;                                           \
        left = AOMMIN(left, 4);                                               \
                                                                              \
        /  设置跳过上下文  /                                                   \
        txb_ctx->txb_skip_ctx = skip_contexts[top][left];                     \
      }                                                                       \
    } else {                                                                  \
      /  如果不是Y平面,根据tx_size和plane_bsize计算跳过上下文  /             \
      const int ctx_base = get_entropy_context(tx_size, a, l);                \
      const int ctx_offset = (num_pels_log2_lookup[plane_bsize] >             \
                              num_pels_log2_lookup[txsize_to_bsize[tx_size]]) \
                                 ? 10                                         \
                                 : 7;                                         \
      txb_ctx->txb_skip_ctx = ctx_base + ctx_offset;                          \
    }                                                                         \
  } 

上面主要获取熵编码上下文实现

typedef struct txb_ctx {

int txb_skip_ctx;

int dc_sign_ctx;

} TXB_CTX;

av1_optimize_b

->av1_optimize_txb

rdoq操作

  1. 量化系数的选择:RDOQ通过计算不同量化系数对应的率失真代价来选择最优系数。这涉及到对每个系数的量化代价和重建误差进行评估
  2. 符号和大小的优化:RDOQ不仅优化系数的大小,还优化符号(正负)的选择,以最小化整体的编码代价
  3. 上下文建模:RDOQ利用上下文信息(如相邻块的量化系数)来更准确地估计当前系数的编码代价
  4. 率失真优化:RDOQ通过比较不同量化级别的率失真代价来确定最优量化级别,这有助于在保持视频质量的同时减少编码比特数
  5. 快速算法:存在一些快速算法来减少RDOQ的计算复杂度,例如通过设定阈值来快速判断一个变换块是否为全零块(All Zero Block,AZB),从而跳过RDOQ过程

`av1_optimize_txb` 函数是AV1视频编码器中的一个关键函数,它负责对变换块(Transform Block,简称TXB)进行率失真优化(Rate-Distortion Optimization,简称RDO)。这个函数的主要目的是在编码过程中找到最佳的量化系数,以最小化编码的总代价(包括比特率和失真),同时保持视频质量。以下是对函数中关键步骤的解释:

1. **输入参数**:

- `cpi`:编码器的控制参数。

- `x`:宏块(Macro Block,简称MB)的数据结构。

- `plane`:当前处理的平面(例如Y、U、V)。

- `block`:当前处理的块索引。

- `tx_size`:变换块的大小。

- `tx_type`:变换类型(例如DCT、ADST等)。

- `txb_ctx`:变换块的上下文信息。

- `rate_cost`:输出的率代价。

- `sharpness`:锐度参数,影响编码的锐度。

2. **初始化和上下文获取**:

- 获取扫描顺序、量化矩阵、变换类型等必要的上下文信息。

3. **断言**:

- 确保输入的EOB(End of Block,块的最后一个非零系数的索引)大于0,因为如果EOB为0,则不需要优化。

4. **率失真优化**:

- 计算跳过编码的成本(`skip_cost`)和非跳过编码的成本(`non_skip_cost`)。

- 计算EOB的成本(`eob_cost`)。

- 初始化累积的率(`accu_rate`)和失真(`accu_dist`)。

5. **系数更新**:

- 使用`update_coeff_general`和`update_coeff_eob`函数更新量化系数,计算不同量化级别的率失真代价。

- 根据变换类型(2D、水平、垂直)选择不同的更新策略。

6. **EOB处理**:

- 如果EOB为0,表示块中没有非零系数,只计算跳过编码的成本。

- 否则,计算非跳过编码的成本和变换类型成本。

7. **DC位置处理**:

- 特别处理DC位置的系数,因为DC系数对视频质量的影响较大。

8. **输出**:

- 更新宏块中的EOB和变换块的熵上下文。

- 返回最终的EOB值,并输出累积的率代价。

总的来说,`av1_optimize_txb`函数通过计算不同量化级别的率失真代价,选择最佳的量化系数,以最小化编码的总代价。这是AV1编码器中实现高效视频编码的关键步骤之一。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/61689.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 应用添加系统签名权限介绍

一、前言 Android 应用添加系统签名就能获取到系统权限调用一些系统接口&#xff0c; 添加系统签名的方式主要包括&#xff1a; 在Android Studio中配置签名文件生成apk 和 在源码目录编译添加系统签名生成apk。 本文介绍的都是一些基础的签名知识&#xff0c;后续延伸介绍相…

Spring 上下文对象

1. Spring 上下文对象概述 Spring 上下文对象&#xff08;ApplicationContext&#xff09;是 Spring 框架的核心接口之一&#xff0c;它扩展了 BeanFactory 接口&#xff0c;提供了更多企业级应用所需的功能。ApplicationContext 不仅可以管理 Bean 的生命周期和配置&#xff0…

Kafka-副本分配策略

一、上下文 《Kafka-创建topic源码》我们大致分析了topic创建的流程&#xff0c;为了保持它的完整性和清晰度。细节并没有展开分析。下面我们就来分析下副本的分配策略以及副本中的leader角色的确定逻辑。当有了副本分配策略&#xff0c;才会得到分区对应的broker&#xff0c;…

Move语言中的代币合约:设计和实现指南

系列文章目录 Task1&#xff1a;hello move&#x1f6aa; Task2&#xff1a;move coin&#x1f6aa; Task3&#xff1a;move nft&#x1f6aa; 更多精彩内容&#xff0c;敬请期待&#xff01;✌️ 文章目录 系列文章目录前言什么是 Sui 链&#xff1f;什么是 Move 编程语言&a…

精酿啤酒厂建设攻略——关键步骤与注意点

建设一家精酿啤酒厂&#xff0c;每一步都至关重要。在这里&#xff0c;小编将为您精心梳理建设精酿啤酒厂的详细步骤和关键注意点&#xff0c;助您在啤酒市场的蓝海中乘风破浪。从投资预算的精确规划&#xff0c;到市场渠道的精心布局&#xff0c;从产品特色的精准定位&#xf…

什么是UGFC?模块电脑(核心板)规范标准简介四

1. 概念 UGFC是Unified Gold Finger Core Board的缩写&#xff08;意指&#xff1a;统一接口定义金手指核心板&#xff09;&#xff0c;为武汉万象奥科电子有限公司基于企业标准定义的一种针对嵌入式、低功耗、通用型的小型计算机模块标准&#xff0c;采用204Pin金手指连接器…

数据科学与SQL:组距分组分析 | 区间分布问题

目录 0 问题描述 1 数据准备 2 问题分析 3 小结 0 问题描述 绝对值分布分析也可以理解为组距分组分析。对于某个指标而言&#xff0c;一个记录对应的指标值的绝对值&#xff0c;肯定落在所有指标值的绝对值的最小值和最大值构成的区间内&#xff0c;根据一定的算法&#x…

量子感知机

神经网络类似于人类大脑&#xff0c;是模拟生物神经网络进行信息处理的一种数学模型。它能解决分类、回归等问题&#xff0c;是机器学习的重要组成部分。量子神经网络是将量子理论与神经网络相结合而产生的一种新型计算模式。1995年美国路易斯安那州立大学KAK教授首次提出了量子…

mysql in查询大数据量业务无法避免情境下优化

在 MySQL 中&#xff0c;IN 查询操作广泛用于从数据库中检索符合条件的多条记录&#xff0c;但当涉及到大数据量的 IN 查询时&#xff0c;性能可能会显著下降。特别是当 IN 子句中的元素数量非常大时&#xff0c;MySQL 需要对每个元素进行匹配&#xff0c;这会导致查询变得非常…

大语言模型---ReLU函数的计算过程及其函数介绍

文章目录 1. 概要2. ReLU定义 1. 概要 **ReLU 作用&#xff1a;**主要用于为神经网络引入非线性能力&#xff0c;作用是将输入中的整数保留原值&#xff0c;负数置为 0。 从而在层与层之间引入非线性&#xff0c;使神经网络能够拟合复杂的非线性关系。 **ReLU使用场景&#xf…

SPSS统计学:连续均匀分布

概念 连续均匀分布是指在某个连续区间上&#xff0c;随机变量取值的概率密度函数是常数的分布。假设连续均匀分布的区间为[a,b]&#xff0c;其中a是区间的下界&#xff0c;b是区间的上界。 方差的推导 连续均匀分布的方差计算中出现数字12&#xff0c;是因为在推导过程中&…

时间请求参数、响应

&#xff08;7&#xff09;时间请求参数 1.默认格式转换 控制器 RequestMapping("/commonDate") ResponseBody public String commonDate(Date date){System.out.println("默认格式时间参数 date > "date);return "{module : commonDate}"; }…

JAVA八股与代码实践----接口与抽象类的区别和用法

接口和抽象类的区别 关键字abstractinterface 实例化不能直接实例化不能直接实例化 方法可以有抽象和具体方法只能有抽象方法&#xff08;Java 8 支持默认方法&#xff09; 变量可以有普通变量只能有常量 (public static final) 继承单继承多继承 构造函数可以定义不允许…

python学习记录18

1 函数的定义 python中的函数指使用某个定义好的名字指代一段完整的代码&#xff0c;在使用名字时可以直接调用整个代码&#xff0c;这个名字叫做函数名。利用函数可以达到编写一次即可多次调用的操作&#xff0c;从而减少代码量。 函数分为内置函数与自定义函数。内置函数例…

设计模式:4、命令模式(双重委托)

目录 0、定义 1、命令模式包括四种角色 2、命令模式的UML类图 3、代码示例 0、定义 将一个请求封装为一个对象&#xff0c;从而使用户可用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以及支持可撤销的操作。 1、命令模式包括四种角色 接…

WPF动画

在 WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;主要有两种类型的动画&#xff1a;属性动画&#xff08;Property Animation&#xff09;和关键帧动画&#xff08;Key - Frame Animation&#xff09;。属性动画用于简单地从一个起始值平滑地过渡…

VSCode汉化教程【简洁易懂】

我们安装完成后默认是英文界面。 找到插件选项卡&#xff0c;搜索“Chinese”&#xff0c;找到简体&#xff08;更具你的需要&#xff09;&#xff08;Microsoft提供&#xff09;Install。 安装完成后选择Change Language and Restart。

海洋通信船舶组网工业4G路由器应用

船舶是浩瀚海洋中探索与贸易的载体&#xff0c;更是船员们生活与工作的家园。为了在广阔的水域中搭建起稳定、高效的网络桥梁&#xff0c;工业4G路由器以卓越的通信组网能力&#xff0c;为船舶组网提供网络支持。 工业4G路由器以其强大的信号发射能力&#xff0c;确保船舶内部…

深入浅出分布式缓存:原理与应用

文章目录 概述缓存分片算法1. Hash算法2. 一致性Hash算法3. 应用场景Redis集群方案1. Redis 集群方案原理2. Redis 集群方案的优势3. Java 代码示例:Redis 集群数据定位Redis 集群中的节点通信机制:Gossip 协议Redis 集群的节点通信:Gossip 协议Redis 集群的节点通信流程Red…

麒麟部署一套NFS服务器,用于创建网络文件系统

一、服务端共享目录 在本例中,kyserver01(172.16.200.10)作为客户端,创建一个目录/testdir并挂载共享目录;kyserver02(172.16.200.11)作为服务端,创建一个共享目录/test,设置为读写权限,要求客户端使用root登录时映射为nobody用户、非root登录时保持不变。 服务端启…