VVC/VTM参考软件数据结构(翻译加解读)

本文是对VVC参考软件下doc目录中的NextSoftware-Data Structure的一个翻译和解读。

动机

HM的缺点
  • 复杂的数据结构
    • Z-index
    • 令人产生歧义的数据模型(TComDataCu)
  • 糟糕的代码可读性
    • 复杂的内存操作与一般的数据流混合在一起
    • 缺乏数据和逻辑封装
  • 复杂的可拓展性
    • 数据结构设计的时候伴随着严格的设定,例如:square blocks
    • 由于错误的实现,很多设想都被抛弃了

目标

下一代参考软件的设计准则
  • 简单的、没有歧义的数据模型
    • 现代的面向对象的设计,即快速又整洁
  • 全局的像素地址
    • 去除Z-index
    • 去除二级的信号地址:CTU到Z-Index
  • 封装繁琐的操作,例如:内存操作
    • 使得一般的流程更加易读
  • 更好的代码可读性
    • 能够简单地拓展

回顾HM模型的数据结构

  • TComDataCU
    • 保存编码的信息
    • 可能表示一个CU或者一个CTU(包含多个CU)
    • 基本上是图像位置到编码信息的映射
  • TComCU
    • 允许更容易的TU结构导航的对象
    • 不包含实际的数据,而是包含在TComDataCU中
  • TComPicYuv
    • 保存视频信号

下一代参考软件的模型

导航
  • Size、Position、Area(Position+Size),这三个结构都是使用结构体实现的,包含在 EncoderLib 中的Common.h文件中
    • 表示基础的二维信息
  • CompArea
    • 一个给定的分量的区域
  • UnitArea
    • 表示多通道信号中的区域
    • 描述共同定位分量组成的一组块
信号存储,包含在 CommonLib 中的Buffer.h文件中
  • AreaBuf:结构体模版
    • 描述了在线性的内存中一个二维信号的布局
    • 包含了一些简单的操作:copy、fill
  • UnitAreaBuf
    • 描述了在线性的内存中一个多组件二维信号的布局
    • 包含了简单的操作:copy,fill
  • PelStorage
    • 一个UnitAreaBuf,同时也分配自己的内存

编码信息

  • Picture
    • 包含了输入输出信号作为元数据(slice info等等)
  • Coding、PredictionUnit、TransformUnit
    • 单一对象对应着单一的单元
    • 包含相应的信息
    • 包含位置信息(从UnitArea中得到)
  • CodingStructure
    • 控制CodingUnit,通过Picture链接他们
    • 对于自上而下的RD搜索包含额外的功能

VVC的基本UML图

VVC/VTM参考软件数据结构(翻译加解读)_第1张图片

HM与VVC之间的对比

HM VVC
Z-index,(CTU)-RS-address,Depth Position,Size,(Comp)Area,UnitArea
TComDataCU CodingUnit, PredictionUnit, TransformUnit Operations in CU, PU, TU namespaces CodingStructure
TComTU Partitioning is governed by Partitioner
TComPicYuv Picture
TComPic Picture
TComYuv UnitAreaBuf

细节描述

CodingStructure基础

CondingStrcture包含了CodingUnit等等一系列的对象, 并可以将他们映射到Picture上面,它可以看做是TComDataCU的一个替代品,但是是全局分配的 。***Top-level***的CoddingStructure包括了在当前帧的所有CUPUTU,而***Sub-level***的CodingStructure则是包含了一个特定的UnitArea表示,在创建之后需要被填满,使用addCU/PU/TU方法创建映射到特定的对象,getCU/PU/TU方法可以获取到使用全局位置寻址的特定对象,并且能够使用dynamic_cache动态地分配需要的资源以提高性能。

使用CodingStructure进行RD-Search

  • 专为自上而下的方法设计
  • 允许使用“透明”全局上下文进行本地测试编码,遵循众所周知的具有向上传播的最佳临时方案
  • 分层次地级联
    • 一个CodingStructure被设置去表达一个局部的UnitArea
    • UnitArea之外的调用将转发到父类CodingStructure
  • 父节点不知道子节点
    • 最好的候选者将被传播给父节点

下面看几张图来解释 Hierarchical Cascading with CodingStructure

VVC/VTM参考软件数据结构(翻译加解读)_第2张图片

cs2调用getCU({32, 32})的时候,查询此位置是否是当前的Codingstructure管理的CodingUnit,得到结果是当前的CodingStrucure于是返回此CodingUnit

VVC/VTM参考软件数据结构(翻译加解读)_第3张图片

cs2调用getCU({16, 32})的时候,查询此位置是否是当前的Codingstructure管理的CodingUnit,得到结果不是当前的CodingStrucure,于是自底向上去其父类CodingStructure中去寻找,找到后返回当前查询位置的CodingUnit

VVC/VTM参考软件数据结构(翻译加解读)_第4张图片

cs1调用getCU({32, 32})的时候,查询此位置是否是当前的Codingstructure管理的CodingUnit,得到结果不是当前的CodingStrucure,由于其无法得知其子节点的信息,所以返回了一个空指针。

划分
  • 一个简单的类来管理划分(CU和TU,四叉树或者别的可能的类)
  • 建模为堆栈-在当前处理的区域创建新的划分作为levels
  • 对于HEVC来说
    • 包含了当前划分的一个访问器
    • 深度(CU,TU)以及实际当前的UnitArea
  • 对于四叉二叉树来说
    • 允许设置划分的限制(约束在一定程度上分裂)
    • 允许执行分割合理性检查

数据的归属

  • 每一个数据都属于某一个对象,并需要分配内存以及释放
  • Picture
    • 归属于EncLibDecLib
    • 拥有信号的缓冲区,Slice对象,SEI消息和TileMap
  • AreaBuf,UnitBuf
    • 不保存任何数据
  • PelStorage
    • 可能拥有某些缓冲区,取决于是否创建或从缓冲区创建
    • 拥有的数据保存在m_origin成员变量中
  • CodingStructure
    • Top-Layer:属于Picture
      • 链接至图像的信号缓冲区,但是并不拥有这些缓冲区
    • Other(暂时存在于RD-Search):属于EncCuIntraSearch
      • 包含一些信号的缓冲区,并拥有他们
    • 总是拥有描述结构和布局的缓冲区(非信号)
    • 拥有变化系数缓冲区
    • 不拥有CodingUnit,仅仅是通过dynamic_cache链接到他们
  • CodingUnit,PredictionUnit,TransformUnit
    • 属于dynamic_cache,其中对象是通过get获取,通过cache来释放
  • TransformUnit
    • 不拥有变换系数缓冲区
    • CodingStructure链接到缓冲区
  • dynamic_cache
    • Top-Level的缓冲区是全局的(在运行时动态分配。并在退出的时候释放)
    • RD-Search的缓冲区是属于EncCuIntraSearch

代码片段

在一个CU中迭代所有TUs的一个帧间解码的例子
  • PUs的迭代调用和traversePUs(…)相似
  • CU只包含了一个TUPU的时候firstTUfirstPU可以被作为快速访问器
// 对CU中那些被cu描述对的TUs调用xDecoderInterTU
for (auto& currTU:CU::traverseTUs(cu))
{
	//大括号换行,简直反人类,手动尼克杨问号???
	xDecoderInterTU(currTU, compID);
} 

常见的问题

运动信息保存在哪里?
  • 最初使用HEVC,运动矢量存储的最小分辨率是PU
  • 针对h.266标准最新提出的工具打破了这一常规(VCEG-AZ10)
    • 对于运动矢量信息来说Sub-Pu的分辨率将被需要
    • 将sub-PUs存储为PUs将会破坏提出PU的逻辑
    • 解决方案:用于子PU解析的运动信息的附加缓冲器
    • 例子:
Mv mvL0 = cs.getPU( pos )->mv[0]; // obsolete low-res call
Mv mvL0 = cs.getMotionInfo( pos ).mv[0]; // new next-style high-res call
  • 旧的调用还在允许,可能会提供子分辨的结果
  • PU::spanMotionInfo方法设定了这个缓冲区

标准软件的参考

####### Size,Position,Area

  • Size
    • width,height:UInt-描述了一个矩形的大小
  • Position
    • x,y:Int-描述了一个点的二维位置信息
  • Area:Size,Position
    • 继承自SizePosition,一个位于特定位置的特定大小的矩形
  • CompArea:Area
    • 一个多分量信号的特定分量的(compID)Area
UnitArea,CodingUnit,PredictionUnit,TransformUnit
  • UnitArea
    • blocks[0…N-1]:CompArea
    • N个多分量信号blocks的融合
  • CoingUnit:UnitArea
    • 描述如何编码被UnitArea所描述的这个区域
  • PredictionUnit:UnitArea
    • 描述此UnitArea的预测信号是怎样生成的
  • TransformUnit:UnitArea
    • 描述此UnitArea的变换编码是如何应用的
AreaBuf
  • AreaBuf< T >
    • at(x, y):返回信号在(x, y)处的值
    • bufAt(x, y):返回一个指向(x, y)位置的缓冲区的未加工(raw)的指针
    • subBuf(x, y, w, h):返回一个AreaBuf,描述距离(x, y)的偏移量为(w, h)的位置的缓冲区
    • fill(val):使用特定的值填充特定的区域
    • copyFrom(other):从别的区域将内容复制过来
    • substract,addVag, reconstruct,removeHighFreq:取代TComYuv功能的方法
  • UnitBuf< T >,与AreaBuf有相似的接口
    • bufs[0…N-1]:AreaBuf:包含了信号不同分量的说明
CodingStructure Basics
  • CodingStrcture Basics
    • area:UnitArea类型,描述了CodingStructure跨越了图像的哪些区域
    • addCU(UnitArea):创建并定位跨越了UnitArea的CodingUnit
    • getCU(position):返回位于指定位置的CodingUnit(TransformUnitPredictionUnit存在模拟接口)
    • setDecomp(CompArea):设置指定的CompArea以重建
    • setDecomp(UnitArea):模拟多通道的操作
    • isDecomp(Position):返回这个位置的重建信号是否已被生成
RD-Search with CodingStructure
  • CodingStructure
    • initStructData(…):清除当前包含的所有数据(信号和编码信息)
    • initSubStructure(…):将一个新的CodingStructure连接到下一层
    • useSubStructure(…):从子结构中复制编码数据
    • copyStructure(…):从其他结构中复制编码信息,并不受到父子之间的约束关系

你可能感兴趣的:(视频编码,VVC视频编码技术)