组合平均法是在Merge列表构建过程中的一种填充候选的方法。
一、 在HEVC中,使用组合候选的方法作为Merge候选列表构建的一种备选方法,该方法比较复杂,对于一个BSlice中的PU而言,其中需要两个MV(一个前向、一个后向),因此在构建Merge候选列表的时候,每个候选需要提供两个MV,当需要用到组合候选法去填充Merge列表的时候,需要对前面已经填充进列表中的前4个候选中的前后向MV使用两两组合的方式产生新的候选再放入到Merge列表中。组合的方式具体为下表所示:
其中combIdx为进行组合的候选MV对的序号,也是可能添加进Merge列表中最后一个候选的组合MV;L0CandIdx和L1CandIdx分别表示进行组合的两个MV所在的候选项在原Merge候选列表中的序号。
如列表中所示,Merge列表中前4个候选的任意一个候选的前向MV和另一个候选的后向MV相互组合出一个新的MV对(新候选),总共12种组合方式,在这12中选出一个添加到Merge列表中,在检查冗余的基础上,最多只允许添加一个。
二、 在目前的VVC中,摈弃之前繁杂的组合候选的方式,L次会议上的L0090提出了简化的成对平均候选的方法,不需要12种繁杂的组合,只需要将Merge列表中已经添加进去的前两个候选(0、1)的前向MV进行两两平均得到新的前向MV,以及后向MV进行两两平均得到新的后向MV。然后用这两个平均后的MV组合成一个新的候选,将该新候选添加到Merge列表中。在检查冗余的基础上最多只允许添加一个成对平均候选。
成对平均候选在VTM6.0中的代码如下,有较为详细的注释,如有注释不对的地方欢迎指正:
#if JVET_L0090_PAIR_AVG
// pairwise-average candidates
//这里开始成对平均候选的填充
{
if (cnt > 1 && cnt < maxNumMergeCand)//如果此时Merge列表还没有被填满
{
//对当前Merge候选项中进行初始化,即赋予零MV
mrgCtx.mvFieldNeighbours[cnt * 2].setMvField( Mv( 0, 0 ), NOT_VALID );
mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField( Mv( 0, 0 ), NOT_VALID );
// calculate average MV for L0 and L1 seperately
//接下来计算前后向各自的平均MV
unsigned char interDir = 0;
#if JVET_O0057_ALTHPELIF
//半像素插值滤波器是否可用
mrgCtx.useAltHpelIf[cnt] = (mrgCtx.useAltHpelIf[0] == mrgCtx.useAltHpelIf[1]) ? mrgCtx.useAltHpelIf[0] : false;
#endif
//对Merge列表中前两个候选的前向和后向的MV分别进行循环
for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ )
{
const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx;//第一个候选的参考帧索引
const short refIdxJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].refIdx;//第二个候选的参考帧索引
//如果两个候选的MV都不可用,则直接跳出进行另一向MV的平均
if( (refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID) )
{
continue;
}
interDir += 1 << refListId;
//如果两个MV都有效,则对两个MV进行两两平均
if( (refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) )
{
const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;//第一个候选的MV
const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;//第二个候选的MV
// average two MVs
Mv avgMv = MvI;
avgMv += MvJ;
roundAffineMv(avgMv.hor, avgMv.ver, 1);
mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI );
}
// only one MV is valid, take the only one MV
//若只有其中一个MV有效,则仅仅将该有效的MV作为平均的MV
else if( refIdxI != NOT_VALID )
{
Mv singleMv = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxI );
}
else if( refIdxJ != NOT_VALID )
{
Mv singleMv = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxJ );
}
}
mrgCtx.interDirNeighbours[cnt] = interDir;
//如果预测方向有效,则将该成对候选MV添加到Merge列表中去
if( interDir > 0 )
{
cnt++;
}
}
// early termination
if( cnt == maxNumMergeCand )
{
return;
}
}
#endif