有时候我们想禁用掉HM的去方块滤波,测试下去方块滤波的效果,很容易就想到要修改配置文件,根据注释,容易找到:
LoopFilterDisable : 1 # Disable deblocking filter (0=Filter, 1=No Filter)
但是运行完程序后就会发现,这个参数改为0或者改为1结果根本就是一样的(如果用过JM的也会发现相同的问题)。那么这到底是为什么呢?难道是程序的bug?其实不然,HM的编写者还不至于犯下这种低级错误。
仔细分析代码后就能找到答案:我们可以找到配置文件LoopFilterDisable这个参数在HM中对应的变量被赋值的地方,在TEncSlice.initEncSlice中有这么一段:
if ( m_pcCfg->getDeblockingFilterMetric() )
{
rpcSlice->setDeblockingFilterOverrideFlag(true);
rpcSlice->setDeblockingFilterDisable(false);
rpcSlice->setDeblockingFilterBetaOffsetDiv2( 0 );
rpcSlice->setDeblockingFilterTcOffsetDiv2( 0 );
} else
if (rpcSlice->getPPS()->getDeblockingFilterControlPresentFlag()) //!< 该标志必须有效配置文件对DBF参数的修改才会起作用
{
rpcSlice->getPPS()->setDeblockingFilterOverrideEnabledFlag( !m_pcCfg->getLoopFilterOffsetInPPS() );
rpcSlice->setDeblockingFilterOverrideFlag( !m_pcCfg->getLoopFilterOffsetInPPS() );
rpcSlice->getPPS()->setPicDisableDeblockingFilterFlag( m_pcCfg->getLoopFilterDisable() ); //!< *
rpcSlice->setDeblockingFilterDisable( m_pcCfg->getLoopFilterDisable() );
if ( !rpcSlice->getDeblockingFilterDisable())
{
if ( !m_pcCfg->getLoopFilterOffsetInPPS() && eSliceType!=I_SLICE)
{
rpcSlice->getPPS()->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_betaOffsetDiv2 + m_pcCfg->getLoopFilterBetaOffset() );
rpcSlice->getPPS()->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_tcOffsetDiv2 + m_pcCfg->getLoopFilterTcOffset() );
rpcSlice->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_betaOffsetDiv2 + m_pcCfg->getLoopFilterBetaOffset() );
rpcSlice->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_tcOffsetDiv2 + m_pcCfg->getLoopFilterTcOffset() );
}
else
{
rpcSlice->getPPS()->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getLoopFilterBetaOffset() );
rpcSlice->getPPS()->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getLoopFilterTcOffset() );
rpcSlice->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getLoopFilterBetaOffset() );
rpcSlice->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getLoopFilterTcOffset() );
}
}
}
else
{
rpcSlice->setDeblockingFilterOverrideFlag( false );
rpcSlice->setDeblockingFilterDisable( false ); //!< *
rpcSlice->setDeblockingFilterBetaOffsetDiv2( 0 );
rpcSlice->setDeblockingFilterTcOffsetDiv2( 0 );
}
只有在if (rpcSlice->getPPS()->getDeblockingFilterControlPresentFlag())成立的时候,配置文件中跟DBF有关的参数的值才会用于HM中对应变量的赋值,而这个flag对应到配置文件中就是:
DeblockingFilterControlPresent: 1 # Dbl control params present (0=not present, 1=present)
于是真相大白了,只有在该参数为1的前提下,配置文件中其他相关参数的设置才会起作用。
那么为什么要这么做呢?道理也不难想到——保证编解码器的一致性,如果没有一个句法元素来表明是否进行去方块滤波,那么解码器解码后得到的重建图像就有可能与编码端存在偏差。那么为什么不单独就用一个句法元素就好,还要额外用另外一个句法元素来进行控制呢?原因是,DBF的参数不止滤波与否这个,还有另外几个;很多时候,这几个参数值可以都用默认值,解码器和编码器都是一致的,则码流只需传输一个句法元素,用于表明是否采用默认参数,即deblocking_filter_control_present_flag。一旦该句法元素为1,则再额外传输跟DBF相关的几个参数对应的句法元素。这种方法能较好的节省码流。