调查了这个函数在HM14.0代码框架中的三处引用。
下面三处代码中的目的是计算当前CU在整张图片中的像素位置。整体思路都是先获得父CU的像素位置,再加上子CU的像素偏移量。
m_uiCUPelX = pcCU->getCUPelX() + ( g_uiMaxCUWidth>>uiDepth )*( uiPartUnitIdx & 1 );
m_uiCUPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
m_uiCUPelX = pcCU->getCUPelX() + m_pcPic->getMinCUWidth ()*( iRastPartIdx % m_pcPic->getNumPartInWidth() );
第一处:g_uiMaxCUWidth 是LCU(最大CU)的宽度,如果已知当前CU(pcCU的子块)的深度,就能通过右移的方式获得当前CU的宽度;uiPartUnitIdx 是当前CU在pcCU中的 Zscan 序号(Zscan 序号范围为0-3),uiPartUnitIdx & 1 为当前CU在pcCU中偏移(0偏移意味着当前CU的横坐标与pcCU的横坐标一致,1偏移意味着当前CU的横坐标比pcCU的横坐标多出一个当前CU宽度的距离)。
第二处:这也是我纠结了很久的点。uiAbsPartIdx 是指当前CU在LCU中的Zscan 序号。说点题外话:LCU的大小一般为64* 64像素,最小的CU大小为4 *4像素,所以CTU中共包含256个最小CU块,Zscan 序号范围为 0-255。再说点题外话:LCU的分割形式有很多种,最后分割出的CU块的大小不一,这就会导致有的CU中实际上包含了好几个最小CU块,也就使得LCU中各CU的 uiAbsPartIdx 是不连续的。好的,废话说完。g_auiZscanToRaster、g_auiRasterToPelX 这两个数组的功能还是很清晰的,第一个是将 Zscan 序号转化为 Raster 序号,第二个是将 Raster 序号转化为实际的像素偏移量。此时的 pcCU 应该是 LCU,用 LCU的 X 坐标加上当前 CU 相对于 LCU 的 X 坐标偏移,就可以得到当前 CU 的 X 坐标了。否则就说不通了。这句代码出现在 copySubCU 函数中。
第三处:首先要明确的是,m_pcPic->getNumPartInWidth() 的结果是 LCU的宽上具有宽度为4的最小 CU 的个数,iRastPartIdx 为当前 CU 相对于 LCU 的 Raster 索引,这样 m_pcPic->getMinCUWidth ()*( iRastPartIdx % m_pcPic->getNumPartInWidth() ) 就代表了当前 CU 相对于 LCU 的 X 像素偏移。
OVER!