编辑:这篇文章是编码器端的解决方案。然而,解码器端的解决方案远没有那么复杂。
如果您不熟悉代码,那么在编码器中获取 CTU 信息(分区等)有点棘手。但我会尽力帮助你。
我要告诉你的一切都是基于 JEM 代码而不是 HM,但我很确定你也可以将它们应用到 HM。
您可能已经注意到,每个 CTU 的压缩/编码有两个完全独立的阶段:
- RDO 阶段:首先是率失真优化循环来“做出决定”。在此阶段,实际上测试所有可能的参数组合(例如不同的分区、帧内模式、滤波器等)。在此阶段结束时,RDO 确定最佳组合并将其传递到第二阶段。
- 编码阶段:这里编码器执行实际的最终编码步骤。这包括根据 RDO 阶段确定的参数将所有 bin 写入比特流。
在 CTU 级别,这两个阶段由m_pcCuEncoder->compressCtu( pCtu )
和m_pcCuEncoder->encodeCtu( pCtu )
函数分别在compressSlice()
的功能TEncSlice.cpp
file.
鉴于上述信息,您必须在以下位置查找您要查找的内容:第二阶段而不是第一阶段(你可能已经知道这些事情,但我怀疑你可能正在看第一阶段)。
所以,现在这是我获取信息的建议。这不是最好的方法,但在这里更容易解释。
您首先在 HM 代码中转到这一点:
compressGOP() -> encodeSlice() -> encodeCtu() -> xEncodeCU()
然后找到预测模式(帧内/帧间)编码的行:
m_pcEntropyCoder->encodePredMode()
此时,您可以访问pcCU
对象,其中包含在第一阶段做出的所有最终决策,包括您要查找的信息。在代码的这一点上,您处理的是单个 CU,而不是整个 CTU。但如果您想要整个 CTU 的信息,您可以返回
compressGOP() -> encodeSlice() -> encodeCtu()
并找到该行xEncodeCU()
函数第一次被调用。在那里,您将可以访问pCtu
object.
提醒: each TComDataCU
目的 (pcCU
如果您处于 CU 级别,或者pCtu
如果您处于 CTU 级别)的规模WxH
被分割为NumPartition=(W/4)x(H/4)
大小分区4x4
。每个分区都可以通过索引访问(uiAbsPartIdx
) 表示其 Z 扫描顺序。例如,uiAbsPartIdx
对于分区<x=8,y=0>
is 4.
现在,您执行以下步骤:
获取分区数(NumPartition
)在你的pCtu
通过致电pCtu->getTotalNumPart()
.
循环所有NumPartition
分区并调用函数pCtu->getWidth(idx)
, pCtu->getHeight(idx)
, pCtu->getCUPelX(idx)
and pCtu->getCUPelY()
, where idx
是你的循环迭代器。这些函数返回每个的以下信息CU
恰逢4x4
分区于idx
:宽度、高度、X 位置、Y 位置。 [两个位置都是相对于像素的<0,0>
框架的]
上述信息足以推导当前的CTU分区pCtu
!所以最后一步是编写一段代码来做到这一点。
这是如何在第二阶段(即编码阶段)提取 CTU 分区信息的示例。但是,您可以调用一些适当的函数来获取第二个问题中的其他信息。例如,要获取选定的亮度帧内模式,您可以调用pCtu->getIntraDir(CHANNEL_TYPE_LUMA, idx)
, 代替getWidth()/getHeight()
功能。或者pCtu->getQP(CHANNEL_TYPE_LUMA, idx)
得到QP值。
您始终可以在以下位置找到提供有用信息的函数列表:pCtu
水平,在TComDataCU
class (TComDataCU.cpp
).
我希望这可以帮助你。如果没有,请告诉我!
祝你好运,