[x265] [PATCH 2 of 2] Control SAO and Deblock independence

Min Chen chenm003 at 163.com
Thu Sep 19 11:16:28 CEST 2013


# HG changeset patch
# User Min Chen <chenm003 at 163.com>
# Date 1379582154 -28800
# Node ID 9860ced6859d0779769c1e9369869dcb41bcd5b5
# Parent  434dc0ee509734c1ee57a7650b2ba02b62c5d8c6
Control SAO and Deblock independence

diff -r 434dc0ee5097 -r 9860ced6859d source/encoder/framefilter.cpp
--- a/source/encoder/framefilter.cpp	Thu Sep 19 17:15:33 2013 +0800
+++ b/source/encoder/framefilter.cpp	Thu Sep 19 17:15:54 2013 +0800
@@ -42,9 +42,11 @@
 {
     if (m_cfg->param.bEnableLoopFilter)
     {
-        assert(m_cfg->param.bEnableSAO);
         m_loopFilter.destroy();
+    }
 
+    if (m_cfg->param.bEnableSAO)
+    {
         // NOTE: I don't check sao flag since loopfilter and sao have same control status
         m_sao.destroy();
         m_sao.destroyEncBuffer();
@@ -62,6 +64,10 @@
     if (top->param.bEnableLoopFilter)
     {
         m_loopFilter.create(g_maxCUDepth);
+    }
+
+    if (top->param.bEnableSAO)
+    {
         m_sao.setSaoLcuBoundary(top->param.saoLcuBoundary);
         m_sao.setSaoLcuBasedOptimization(top->param.saoLcuBasedOptimization);
         m_sao.setMaxNumOffsetsPerPic(top->getMaxNumOffsetsPerPic());
@@ -74,6 +80,7 @@
 {
     m_pic = pic;
 
+    m_saoRowDelay = m_cfg->param.bEnableLoopFilter ? 1 : 0;
     m_loopFilter.setCfg(pic->getSlice()->getPPS()->getLoopFilterAcrossTilesEnabledFlag());
     m_rdGoOnSbacCoder.init(&m_rdGoOnBinCodersCABAC);
     m_entropyCoder.setEntropyCoder(&m_rdGoOnSbacCoder, pic->getSlice());
@@ -83,7 +90,10 @@
     {
         m_sao.resetStats();
         m_sao.createPicSaoInfo(pic);
+    }
 
+    if (m_cfg->param.bEnableSAO)
+    {
         SAOParam* saoParam = pic->getPicSym()->getSaoParam();
         m_sao.resetSAOParam(saoParam);
         m_sao.rdoSaoUnitRowInit(saoParam);
@@ -92,7 +102,7 @@
 
 void FrameFilter::end()
 {
-    if (m_cfg->param.bEnableLoopFilter)
+    if (m_cfg->param.bEnableSAO)
     {
         m_sao.destroyPicSaoInfo();
     }
@@ -102,14 +112,14 @@
 {
     PPAScopeEvent(Thread_filterCU);
 
-    if (!m_cfg->param.bEnableLoopFilter)
+    if (!m_cfg->param.bEnableLoopFilter && !m_cfg->param.bEnableSAO)
     {
         processRowPost(row);
         return;
     }
 
     // NOTE: We are here only active both of loopfilter and sao, the row 0 always finished, so we can safe to copy row[0]'s data
-    if (row == 0)
+    if (row == 0 && m_cfg->param.bEnableSAO)
     {
         // NOTE: not need, seems HM's bug, I want to keep output exact matched.
         m_rdGoOnBinCodersCABAC.m_fracBits = ((TEncBinCABACCounter*)((TEncSbac*)m_rdGoOnSbacCoderRow0->m_pcBinIf))->m_fracBits;
@@ -120,66 +130,43 @@
     const uint32_t lineStartCUAddr = row * numCols;
 
     // SAO parameter estimation using non-deblocked pixels for LCU bottom and right boundary areas
-    if (m_cfg->param.saoLcuBasedOptimization && m_cfg->param.saoLcuBoundary)
+    if (m_cfg->param.bEnableSAO && m_cfg->param.saoLcuBasedOptimization && m_cfg->param.saoLcuBoundary)
     {
         m_sao.calcSaoStatsRowCus_BeforeDblk(m_pic, row);
     }
 
-    for (UInt col = 0; col < numCols; col++)
+    if (m_cfg->param.bEnableLoopFilter)
     {
-        const uint32_t cuAddr = lineStartCUAddr + col;
-        TComDataCU* cu = m_pic->getCU(cuAddr);
+        for (UInt col = 0; col < numCols; col++)
+        {
+            const uint32_t cuAddr = lineStartCUAddr + col;
+            TComDataCU* cu = m_pic->getCU(cuAddr);
 
-        m_loopFilter.loopFilterCU(cu, EDGE_VER);
+            m_loopFilter.loopFilterCU(cu, EDGE_VER);
 
-        if (col > 0)
+            if (col > 0)
+            {
+                TComDataCU* cu_prev = m_pic->getCU(cuAddr - 1);
+                m_loopFilter.loopFilterCU(cu_prev, EDGE_HOR);
+            }
+        }
+
         {
-            TComDataCU* cu_prev = m_pic->getCU(cuAddr - 1);
+            TComDataCU* cu_prev = m_pic->getCU(lineStartCUAddr + numCols - 1);
             m_loopFilter.loopFilterCU(cu_prev, EDGE_HOR);
         }
     }
 
-    {
-        TComDataCU* cu_prev = m_pic->getCU(lineStartCUAddr + numCols - 1);
-        m_loopFilter.loopFilterCU(cu_prev, EDGE_HOR);
-    }
-
     // SAO
     SAOParam* saoParam = m_pic->getPicSym()->getSaoParam();
-    if (m_sao.getSaoLcuBasedOptimization())
+    if (m_cfg->param.bEnableSAO && m_sao.getSaoLcuBasedOptimization())
     {
         m_sao.rdoSaoUnitRow(saoParam, row);
 
         // NOTE: Delay a row because SAO decide need top row pixels at next row, is it HM's bug?
-        if (row > 0)
+        if (row >= m_saoRowDelay)
         {
-            // NOTE: these flag is not use in this mode
-            assert(saoParam->oneUnitFlag[0] == false);
-            assert(saoParam->oneUnitFlag[1] == false);
-            assert(saoParam->oneUnitFlag[2] == false);
-
-            if (saoParam->bSaoFlag[0])
-            {
-                m_sao.processSaoUnitRow(saoParam->saoLcuParam[0], row - 1, 0);
-            }
-            if (saoParam->bSaoFlag[1])
-            {
-                m_sao.processSaoUnitRow(saoParam->saoLcuParam[1], row - 1, 1);
-                m_sao.processSaoUnitRow(saoParam->saoLcuParam[2], row - 1, 2);
-            }
-
-            // TODO: this code is NOT VERIFIED because TransformSkip and PCM modes have some bugs, they are never enabled
-            bool  bPCMFilter = (m_pic->getSlice()->getSPS()->getUsePCM() && m_pic->getSlice()->getSPS()->getPCMFilterDisableFlag()) ? true : false;
-            if (bPCMFilter || m_pic->getSlice()->getPPS()->getTransquantBypassEnableFlag())
-            {
-                for (UInt col = 0; col < numCols; col++)
-                {
-                    const uint32_t cuAddr = lineStartCUAddr - numCols + col;
-                    TComDataCU* cu = m_pic->getCU(cuAddr);
-
-                    xPCMCURestoration(cu, 0, 0);
-                }
-            }
+            processSao(row - m_saoRowDelay);
         }
     }
 
@@ -192,29 +179,13 @@
 
     if (row == m_numRows - 1)
     {
-        m_sao.rdoSaoUnitRowEnd(saoParam, m_pic->getNumCUsInFrame());
+        if (m_cfg->param.bEnableSAO)
+        {
+            m_sao.rdoSaoUnitRowEnd(saoParam, m_pic->getNumCUsInFrame());
 
-        // Process Last row of SAO
-        if (saoParam->bSaoFlag[0])
-        {
-            m_sao.processSaoUnitRow(saoParam->saoLcuParam[0], row, 0);
-        }
-        if (saoParam->bSaoFlag[1])
-        {
-            m_sao.processSaoUnitRow(saoParam->saoLcuParam[1], row, 1);
-            m_sao.processSaoUnitRow(saoParam->saoLcuParam[2], row, 2);
-        }
-
-        // TODO: this code is NOT VERIFIED because TransformSkip and PCM modes have some bugs, they are never enabled
-        bool  bPCMFilter = (m_pic->getSlice()->getSPS()->getUsePCM() && m_pic->getSlice()->getSPS()->getPCMFilterDisableFlag()) ? true : false;
-        if (bPCMFilter || m_pic->getSlice()->getPPS()->getTransquantBypassEnableFlag())
-        {
-            for (UInt col = 0; col < numCols; col++)
+            for(int i = m_numRows - m_saoRowDelay; i < m_numRows; i++)
             {
-                const uint32_t cuAddr = lineStartCUAddr + col;
-                TComDataCU* cu = m_pic->getCU(cuAddr);
-
-                xPCMCURestoration(cu, 0, 0);
+                processSao(i);
             }
         }
 
@@ -284,3 +255,38 @@
         m_pic->m_reconRowWait.trigger();
     }
 }
+
+void FrameFilter::processSao(int row)
+{
+    const uint32_t numCols = m_pic->getPicSym()->getFrameWidthInCU();
+    const uint32_t lineStartCUAddr = row * numCols;
+    SAOParam* saoParam = m_pic->getPicSym()->getSaoParam();
+
+    // NOTE: these flag is not use in this mode
+    assert(saoParam->oneUnitFlag[0] == false);
+    assert(saoParam->oneUnitFlag[1] == false);
+    assert(saoParam->oneUnitFlag[2] == false);
+
+    if (saoParam->bSaoFlag[0])
+    {
+        m_sao.processSaoUnitRow(saoParam->saoLcuParam[0], row, 0);
+    }
+    if (saoParam->bSaoFlag[1])
+    {
+        m_sao.processSaoUnitRow(saoParam->saoLcuParam[1], row, 1);
+        m_sao.processSaoUnitRow(saoParam->saoLcuParam[2], row, 2);
+    }
+
+    // TODO: this code is NOT VERIFIED because TransformSkip and PCM modes have some bugs, they are never enabled
+    bool  bPCMFilter = (m_pic->getSlice()->getSPS()->getUsePCM() && m_pic->getSlice()->getSPS()->getPCMFilterDisableFlag()) ? true : false;
+    if (bPCMFilter || m_pic->getSlice()->getPPS()->getTransquantBypassEnableFlag())
+    {
+        for (UInt col = 0; col < numCols; col++)
+        {
+            const uint32_t cuAddr = lineStartCUAddr + col;
+            TComDataCU* cu = m_pic->getCU(cuAddr);
+
+            xPCMCURestoration(cu, 0, 0);
+        }
+    }
+}
diff -r 434dc0ee5097 -r 9860ced6859d source/encoder/framefilter.h
--- a/source/encoder/framefilter.h	Thu Sep 19 17:15:33 2013 +0800
+++ b/source/encoder/framefilter.h	Thu Sep 19 17:15:54 2013 +0800
@@ -52,6 +52,7 @@
 
     void processRow(int row);
     void processRowPost(int row);
+    void processSao(int row);
 
 protected:
 
@@ -63,6 +64,7 @@
     TComLoopFilter              m_loopFilter;
     TEncSampleAdaptiveOffset    m_sao;
     int                         m_numRows;
+    int                         m_saoRowDelay;
 
     // SAO
     TEncEntropy                 m_entropyCoder;
diff -r 434dc0ee5097 -r 9860ced6859d source/x265.cpp
--- a/source/x265.cpp	Thu Sep 19 17:15:33 2013 +0800
+++ b/source/x265.cpp	Thu Sep 19 17:15:54 2013 +0800
@@ -400,11 +400,6 @@
             this->input->setDimensions(param->sourceWidth, param->sourceHeight);
             this->input->setBitDepth(inputBitDepth);
         }
-        if (param->bEnableLoopFilter ^ param->bEnableSAO)
-        {
-            log(X265_LOG_ERROR, "Loopfilter and SAO must be same value\n");
-            return true;
-        }
 
         /* rules for input, output and internal bitdepths as per help text */
         if (!param->internalBitDepth) { param->internalBitDepth = inputBitDepth; }



More information about the x265-devel mailing list