从 HEVC 参考软件中获取一些信息
Get some information from HEVC reference software
我是 HEVC 的新手,我现在正在了解参考软件(现在正在查看帧内预测)。
编码后需要获取如下信息
- 给定 CTU 的 CU 结构
- 对于计算期间的每个 CU,它的信息(例如 QP 值、Luma 的选择模式、色度的选择模式、CU 是否处于 CTU 拆分决策的最终 CU 结构中等)
我知道 CTU 的决定是在 TEncSlice.cpp
中调用 m_pcCuEncoder->compressCtu( pCtu )
时做出的。但我究竟从哪里可以获得这些具体信息呢?有人可以帮我弄这个吗?
p.s。我也在学习 C++(我有 Java 背景)。
编辑:post 是编码器端的解决方案。然而,解码器端的解决方案远没有那么复杂。
如果您不熟悉代码,那么在编码器处获取 CTU 信息(分区等)有点棘手。但我会尽力帮助你。
我要告诉你的一切都是基于 JEM 代码而不是 HM,但我很确定你也可以将它们应用到 HM。
您可能已经注意到,每个 CTU 的 compression/encoding 有两个完全独立的阶段:
- RDO 阶段:首先是 "make the decisions" 的率失真优化循环。在这个阶段,几乎所有可能的参数组合都会被测试(例如,不同的分区、内部模式、过滤器等)。在此阶段结束时,RDO 确定最佳组合并将它们传递到第二阶段。
- 编码阶段:此处编码器执行实际的最终编码步骤。这包括根据在 RDO 阶段确定的参数将所有 bin 写入比特流。
在CTU级别,这两个阶段分别由m_pcCuEncoder->compressCtu( pCtu )
和m_pcCuEncoder->encodeCtu( pCtu )
函数执行,都在TEncSlice.cpp
文件的compressSlice()
函数中.
鉴于以上信息,您必须在第二阶段而不是第一阶段中寻找您要寻找的东西(你可能已经知道这些东西,但我怀疑你可能正在看第一阶段)。
所以,现在这是我获取您的信息的建议。这不是最好的方法,但在这里更容易解释。
您首先在 HM 代码中转到这一点:
compressGOP() -> encodeSlice() -> encodeCtu() -> xEncodeCU()
然后找到预测模式(intra/inter)编码的行:
m_pcEntropyCoder->encodePredMode()
此时,您可以访问 pcCU
对象,其中包含所有最终决策,包括您在第一阶段做出的查找信息。在代码的这一点上,您正在处理单个 CU 而不是整个 CTU。但是如果你想要整个 CTU 的信息,你可以返回
compressGOP() -> encodeSlice() -> encodeCtu()
并找到第一次调用xEncodeCU()
函数的那一行。在那里,您将有权访问 pCtu
对象。
提醒:每个TComDataCU
对象(pcCU
如果你在CU级别,或者pCtu
如果你在CTU级别)大小 WxH
被拆分为大小 4x4
的 NumPartition=(W/4)x(H/4)
个分区。每个分区都可以通过指示其 Z 扫描顺序的索引 (uiAbsPartIdx
) 访问。例如,<x=8,y=0>
处分区的 uiAbsPartIdx
为 4。
现在,您执行以下步骤:
通过调用 pCtu->getTotalNumPart()
获取 pCtu
中的分区数 (NumPartition
)。
遍历所有 NumPartition
分区并调用函数 pCtu->getWidth(idx)
、pCtu->getHeight(idx)
、pCtu->getCUPelX(idx)
和 pCtu->getCUPelY()
,其中 idx
是你的循环迭代器。这些函数 return 每个 CU
的以下信息与 idx
处的 4x4
分区重合:宽度、高度、positionX、positionY。 [两个位置都是相对于帧的像素<0,0>
]
以上信息足以推导出当前pCtu
的CTU分区!所以最后一步就是写一段代码来做到这一点。
这是如何在第二阶段(即编码阶段)提取 CTU 分区信息的示例。但是,您可以调用一些适当的函数来获取第二个问题中的其他信息。例如,要获得选定的亮度帧内模式,您可以调用 pCtu->getIntraDir(CHANNEL_TYPE_LUMA, idx)
,而不是 getWidth()/getHeight()
函数。或pCtu->getQP(CHANNEL_TYPE_LUMA, idx)
获取QP值。
您始终可以在 TComDataCU
class (TComDataCU.cpp
) 中找到提供 pCtu
级别有用信息的函数列表。
希望对您有所帮助。如果没有,请告诉我!
祝你好运,
我是 HEVC 的新手,我现在正在了解参考软件(现在正在查看帧内预测)。
编码后需要获取如下信息
- 给定 CTU 的 CU 结构
- 对于计算期间的每个 CU,它的信息(例如 QP 值、Luma 的选择模式、色度的选择模式、CU 是否处于 CTU 拆分决策的最终 CU 结构中等)
我知道 CTU 的决定是在 TEncSlice.cpp
中调用 m_pcCuEncoder->compressCtu( pCtu )
时做出的。但我究竟从哪里可以获得这些具体信息呢?有人可以帮我弄这个吗?
p.s。我也在学习 C++(我有 Java 背景)。
编辑:post 是编码器端的解决方案。然而,解码器端的解决方案远没有那么复杂。
如果您不熟悉代码,那么在编码器处获取 CTU 信息(分区等)有点棘手。但我会尽力帮助你。 我要告诉你的一切都是基于 JEM 代码而不是 HM,但我很确定你也可以将它们应用到 HM。
您可能已经注意到,每个 CTU 的 compression/encoding 有两个完全独立的阶段:
- RDO 阶段:首先是 "make the decisions" 的率失真优化循环。在这个阶段,几乎所有可能的参数组合都会被测试(例如,不同的分区、内部模式、过滤器等)。在此阶段结束时,RDO 确定最佳组合并将它们传递到第二阶段。
- 编码阶段:此处编码器执行实际的最终编码步骤。这包括根据在 RDO 阶段确定的参数将所有 bin 写入比特流。
在CTU级别,这两个阶段分别由m_pcCuEncoder->compressCtu( pCtu )
和m_pcCuEncoder->encodeCtu( pCtu )
函数执行,都在TEncSlice.cpp
文件的compressSlice()
函数中.
鉴于以上信息,您必须在第二阶段而不是第一阶段中寻找您要寻找的东西(你可能已经知道这些东西,但我怀疑你可能正在看第一阶段)。
所以,现在这是我获取您的信息的建议。这不是最好的方法,但在这里更容易解释。 您首先在 HM 代码中转到这一点:
compressGOP() -> encodeSlice() -> encodeCtu() -> xEncodeCU()
然后找到预测模式(intra/inter)编码的行:
m_pcEntropyCoder->encodePredMode()
此时,您可以访问 pcCU
对象,其中包含所有最终决策,包括您在第一阶段做出的查找信息。在代码的这一点上,您正在处理单个 CU 而不是整个 CTU。但是如果你想要整个 CTU 的信息,你可以返回
compressGOP() -> encodeSlice() -> encodeCtu()
并找到第一次调用xEncodeCU()
函数的那一行。在那里,您将有权访问 pCtu
对象。
提醒:每个TComDataCU
对象(pcCU
如果你在CU级别,或者pCtu
如果你在CTU级别)大小 WxH
被拆分为大小 4x4
的 NumPartition=(W/4)x(H/4)
个分区。每个分区都可以通过指示其 Z 扫描顺序的索引 (uiAbsPartIdx
) 访问。例如,<x=8,y=0>
处分区的 uiAbsPartIdx
为 4。
现在,您执行以下步骤:
通过调用
pCtu->getTotalNumPart()
获取pCtu
中的分区数 (NumPartition
)。遍历所有
NumPartition
分区并调用函数pCtu->getWidth(idx)
、pCtu->getHeight(idx)
、pCtu->getCUPelX(idx)
和pCtu->getCUPelY()
,其中idx
是你的循环迭代器。这些函数 return 每个CU
的以下信息与idx
处的4x4
分区重合:宽度、高度、positionX、positionY。 [两个位置都是相对于帧的像素<0,0>
]以上信息足以推导出当前
pCtu
的CTU分区!所以最后一步就是写一段代码来做到这一点。
这是如何在第二阶段(即编码阶段)提取 CTU 分区信息的示例。但是,您可以调用一些适当的函数来获取第二个问题中的其他信息。例如,要获得选定的亮度帧内模式,您可以调用 pCtu->getIntraDir(CHANNEL_TYPE_LUMA, idx)
,而不是 getWidth()/getHeight()
函数。或pCtu->getQP(CHANNEL_TYPE_LUMA, idx)
获取QP值。
您始终可以在 TComDataCU
class (TComDataCU.cpp
) 中找到提供 pCtu
级别有用信息的函数列表。
希望对您有所帮助。如果没有,请告诉我!
祝你好运,