参考链接:
https://blog.csdn.net/hevc_cjl/article/details/8183144
https://blog.csdn.net/tianzhaixing2013/article/details/8694105
https://blog.csdn.net/u010854339/article/details/8994985
最近在HEVC的代码中,学习了实现Zscan和Raster两种扫描方式的转换方法。根据以上三个参考链接,整理资料如下:
背景补充:
HEVC中,CU采用递归的四叉树划分结构,Zscan扫描可以很好地适应该种编码结构,有利于CU的寻址。
光栅扫描,也叫逐行扫描,形象直观,容易计算X、Y坐标,有利于像素点的寻址。
在不同的应用中,为方便计算,需要采用不同的扫描方式,故有相互转换之需求。
HM代码中的 initZscanToRaster() 和initRasterToZscan() 函数(附个人注释):
Void initZscanToRaster (Int iMaxDepth, Int iDepth, UInt uiStartVal, UInt*& rpuiCurrIdx)
{
Int iStride = 1 << ( iMaxDepth - 1); // CU的尺寸,例如CU16x16对应的iStride为16.
if ( iDepth == iMaxDepth )
{
rpuiCurrIdx[0] = uiStartVal;
rpuiCurrIdx++; // Zscan的值递增1,0~(iStride*iStride-1)
}
else
{
Int iStep = iStride >> iDepth; // iDepth取值范围为1~(iMaxDepth-1)
initZscanToRaster ( iMaxDepth, iDepth+1, uiStartVal, rpuiCurrIdx); // 四行递归调用,因为Zscan由2x2的Z字形扫描嵌套构成。
initZscanToRaster ( iMaxDepth, iDepth+1, uiStartVal+iStep, rpuiCurrIdx);
initZscanToRaster ( iMaxDepth, iDepth+1, uiStartVal+iStep*iStride, rpuiCurrIdx);
initZscanToRaster ( iMaxDepth, iDepth+1, uiStartVal+iStep*iStride+iStep, rpuiCurrIdx);
}
}
Void initRasterToZscan (UInt uiMaxCUWidth, Uint uiMaxCUHeight, UInt uiMaxDepth)
{
UInt uiMinCUWidth = uiMaxCUWidth >> (uiMaxDepth - 1);
UInt uiMinCUHeight = uiMaxCUHeight >> (uiMaxDepth - 1);
UInt uiNumPartInWidth = (UInt)uiMaxCUWidth / uiMinCUWidth;
UInt uiNumPartInHeight = (UInt)uiMaxCUHeight / uiMinCUHeight;
for (UInt i = 0; i < uiNumPartInWidth*uiNumPartInHeight; i++)
{
g_auiRasterToZscan[ g_auiZscanToRaster[i] ] = i; // Zscan到Raster扫描的对应关系中,Zscan的值是加1递增的,故反向对应即可。
}
}
16x16的Zscan见下图:
注:8x8Zscan和4x4Zscan可在16x16Zscan中找到,此处略。
16x16的光栅扫描见下图:
8x8的光栅扫描见下图:
4x4的光栅扫描见下图:
ZscanToRaster16x16 的对应关系示例:
g_auiZscanToRaster[0] = 0;
g_auiZscanToRaster[1] = 1;
g_auiZscanToRaster[2] = 16;
g_auiZscanToRaster[3] = 17;
g_auiRasterToZscan[0] = 0;
g_auiRasterToZscan[1] = 1;
g_auiRasterToZscan[16] = 2;
g_auiRasterToZscan[17] = 3;
ZscanToRaster8x8 的对应关系示例:
g_auiZscanToRaster[0] = 0;
g_auiZscanToRaster[1] = 1;
g_auiZscanToRaster[2] = 8;
g_auiZscanToRaster[3] = 9;
g_auiRasterToZscan[0] = 0;
g_auiRasterToZscan[1] = 1;
g_auiRasterToZscan[8] = 2;
g_auiRasterToZscan[9] = 3;
ZscanToRaster4x4 的对应关系示例:
g_auiZscanToRaster[0] = 0;
g_auiZscanToRaster[1] = 1;
g_auiZscanToRaster[2] = 4;
g_auiZscanToRaster[3] = 5;
g_auiRasterToZscan[0] = 0;
g_auiRasterToZscan[1] = 1;
g_auiRasterToZscan[4] = 2;
g_auiRasterToZscan[5] = 3;