HM中去方块滤波的禁用方法

     有时候我们想禁用掉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相关的几个参数对应的句法元素。这种方法能较好的节省码流。

 

     最后,说了那么多,如果平时只是在编码端测试的话,那么还有另外一个办法禁掉DBF,那就是直接将m_pcLoopFilter->loopFilterPic( pcPic );这句话注释掉,简单、粗暴、有效,但不提倡,呵呵。。

相关文章
相关标签/搜索