有時候我們想禁用掉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相關的幾個參數對應的句法元素。這種方法能較好的節省碼流。