[x265] [PATCH] framepp: fix bug with '--sao-lcu-bounds 1' and move part of sao into compress loop

Min Chen chenm003 at 163.com
Fri Aug 16 14:16:06 CEST 2013


# HG changeset patch
# User Min Chen <chenm003 at 163.com>
# Date 1376655357 -28800
# Node ID fd7740c9441317b47fd8f986d3bf29f1e411bc8f
# Parent  c2f5275ecb4986da2a1116dd7445cc2536fa19fd
framepp: fix bug with '--sao-lcu-bounds 1' and move part of sao into compress loop

diff -r c2f5275ecb49 -r fd7740c94413 source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp
--- a/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp	Fri Aug 16 20:15:57 2013 +0800
@@ -119,7 +119,7 @@
 /** convert Level Row Col to Idx
  * \param   level,  row,  col
  */
-Int  TComSampleAdaptiveOffset::convertLevelRowCol2Idx(Int level, Int row, Int col)
+Int  TComSampleAdaptiveOffset::convertLevelRowCol2Idx(Int level, Int row, Int col) const
 {
     Int idx;
 
@@ -336,7 +336,7 @@
 /** allocate memory for SAO parameters
  * \param    *saoParam
  */
-Void TComSampleAdaptiveOffset::allocSaoParam(SAOParam *saoParam)
+Void TComSampleAdaptiveOffset::allocSaoParam(SAOParam *saoParam) const
 {
     saoParam->maxSplitLevel = m_maxSplitLevel;
     saoParam->saoPart[0] = new SAOQTPart[m_numCulPartsLevel[saoParam->maxSplitLevel]];
@@ -355,7 +355,7 @@
 /** initialize SAO parameters
  * \param    *saoParam,  iPartLevel,  iPartRow,  iPartCol,  iParentPartIdx,  StartCUX,  EndCUX,  StartCUY,  EndCUY,  yCbCr
  */
-Void TComSampleAdaptiveOffset::initSAOParam(SAOParam *saoParam, Int partLevel, Int partRow, Int partCol, Int parentPartIdx, Int startCUX, Int endCUX, Int startCUY, Int endCUY, Int yCbCr)
+Void TComSampleAdaptiveOffset::initSAOParam(SAOParam *saoParam, Int partLevel, Int partRow, Int partCol, Int parentPartIdx, Int startCUX, Int endCUX, Int startCUY, Int endCUY, Int yCbCr) const
 {
     Int j;
     Int partIdx = convertLevelRowCol2Idx(partLevel, partRow, partCol);
diff -r c2f5275ecb49 -r fd7740c94413 source/Lib/TLibCommon/TComSampleAdaptiveOffset.h
--- a/source/Lib/TLibCommon/TComSampleAdaptiveOffset.h	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/Lib/TLibCommon/TComSampleAdaptiveOffset.h	Fri Aug 16 20:15:57 2013 +0800
@@ -186,10 +186,10 @@
     Void create(UInt sourceWidth, UInt sourceHeight, UInt maxCUWidth, UInt maxCUHeight);
     Void destroy();
 
-    Int  convertLevelRowCol2Idx(Int level, Int row, Int col);
+    Int  convertLevelRowCol2Idx(Int level, Int row, Int col) const;
 
-    Void initSAOParam(SAOParam* saoParam, Int partLevel, Int partRow, Int partCol, Int parentPartIdx, Int startCUX, Int endCUX, Int startCUY, Int endCUY, Int yCbCr);
-    Void allocSaoParam(SAOParam* saoParam);
+    Void initSAOParam(SAOParam* saoParam, Int partLevel, Int partRow, Int partCol, Int parentPartIdx, Int startCUX, Int endCUX, Int startCUY, Int endCUY, Int yCbCr) const;
+    Void allocSaoParam(SAOParam* saoParam) const;
     Void resetSAOParam(SAOParam* saoParam);
     static Void freeSaoParam(SAOParam* saoParam);
 
diff -r c2f5275ecb49 -r fd7740c94413 source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp
--- a/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp	Fri Aug 16 20:15:57 2013 +0800
@@ -73,6 +73,12 @@
 {}
 
 // ====================================================================================================================
+// Static
+// ====================================================================================================================
+Int64  ****TEncSampleAdaptiveOffset::m_countPreDblk = NULL;
+Int64  ****TEncSampleAdaptiveOffset::m_offsetOrgPreDblk = NULL;
+
+// ====================================================================================================================
 // Constants
 // ====================================================================================================================
 
@@ -466,53 +472,56 @@
     }
     Int numLcu = m_numCuInWidth * m_numCuInHeight;
 
-    for (Int i = 0; i < numLcu; i++)
+    if (m_countPreDblk)
     {
-        for (Int j = 0; j < 3; j++)
+        for (Int i = 0; i < numLcu; i++)
         {
-            for (Int k = 0; k < MAX_NUM_SAO_TYPE; k++)
+            for (Int j = 0; j < 3; j++)
             {
-                if (m_countPreDblk[i][j][k])
+                for (Int k = 0; k < MAX_NUM_SAO_TYPE; k++)
                 {
-                    delete [] m_countPreDblk[i][j][k];
+                    if (m_countPreDblk[i][j][k])
+                    {
+                        delete [] m_countPreDblk[i][j][k];
+                    }
+                    if (m_offsetOrgPreDblk[i][j][k])
+                    {
+                        delete [] m_offsetOrgPreDblk[i][j][k];
+                    }
                 }
-                if (m_offsetOrgPreDblk[i][j][k])
+
+                if (m_countPreDblk[i][j])
                 {
-                    delete [] m_offsetOrgPreDblk[i][j][k];
+                    delete [] m_countPreDblk[i][j];
+                }
+                if (m_offsetOrgPreDblk[i][j])
+                {
+                    delete [] m_offsetOrgPreDblk[i][j];
                 }
             }
 
-            if (m_countPreDblk[i][j])
+            if (m_countPreDblk[i])
             {
-                delete [] m_countPreDblk[i][j];
+                delete [] m_countPreDblk[i];
             }
-            if (m_offsetOrgPreDblk[i][j])
+            if (m_offsetOrgPreDblk[i])
             {
-                delete [] m_offsetOrgPreDblk[i][j];
+                delete [] m_offsetOrgPreDblk[i];
             }
         }
 
-        if (m_countPreDblk[i])
+        if (m_countPreDblk)
         {
-            delete [] m_countPreDblk[i];
+            delete [] m_countPreDblk;
+            m_countPreDblk = NULL;
         }
-        if (m_offsetOrgPreDblk[i])
+        if (m_offsetOrgPreDblk)
         {
-            delete [] m_offsetOrgPreDblk[i];
+            delete [] m_offsetOrgPreDblk;
+            m_offsetOrgPreDblk = NULL;
         }
     }
 
-    if (m_countPreDblk)
-    {
-        delete [] m_countPreDblk;
-        m_countPreDblk = NULL;
-    }
-    if (m_offsetOrgPreDblk)
-    {
-        delete [] m_offsetOrgPreDblk;
-        m_offsetOrgPreDblk = NULL;
-    }
-
     Int maxDepth = 4;
     Int depth;
     for (depth = 0; depth < maxDepth + 1; depth++)
@@ -570,22 +579,27 @@
     }
 
     Int numLcu = m_numCuInWidth * m_numCuInHeight;
-    m_countPreDblk  = new Int64 * **[numLcu];
-    m_offsetOrgPreDblk = new Int64 * **[numLcu];
-    for (Int i = 0; i < numLcu; i++)
+    if (m_countPreDblk == NULL)
     {
-        m_countPreDblk[i]  = new Int64 * *[3];
-        m_offsetOrgPreDblk[i] = new Int64 * *[3];
+        assert(m_offsetOrgPreDblk == NULL);
 
-        for (Int j = 0; j < 3; j++)
+        m_countPreDblk  = new Int64 * **[numLcu];
+        m_offsetOrgPreDblk = new Int64 * **[numLcu];
+        for (Int i = 0; i < numLcu; i++)
         {
-            m_countPreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
-            m_offsetOrgPreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
+            m_countPreDblk[i]  = new Int64 * *[3];
+            m_offsetOrgPreDblk[i] = new Int64 * *[3];
 
-            for (Int k = 0; k < MAX_NUM_SAO_TYPE; k++)
+            for (Int j = 0; j < 3; j++)
             {
-                m_countPreDblk[i][j][k]   = new Int64[MAX_NUM_SAO_CLASS];
-                m_offsetOrgPreDblk[i][j][k] = new Int64[MAX_NUM_SAO_CLASS];
+                m_countPreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
+                m_offsetOrgPreDblk[i][j] = new Int64 *[MAX_NUM_SAO_TYPE];
+
+                for (Int k = 0; k < MAX_NUM_SAO_TYPE; k++)
+                {
+                    m_countPreDblk[i][j][k]   = new Int64[MAX_NUM_SAO_CLASS];
+                    m_offsetOrgPreDblk[i][j][k] = new Int64[MAX_NUM_SAO_CLASS];
+                }
             }
         }
     }
@@ -1488,6 +1502,307 @@
     }
 }
 
+Void TEncSampleAdaptiveOffset::calcSaoStatsLCu_BeforeDblk(TComPic* pic, Int addr)
+{
+    Int yCbCr;
+    Int x, y;
+    TComSPS *pTmpSPS =  pic->getSlice()->getSPS();
+
+    Pel* fenc;
+    Pel* pRec;
+    Int stride;
+    Int lcuHeight = pTmpSPS->getMaxCUHeight();
+    Int lcuWidth  = pTmpSPS->getMaxCUWidth();
+    UInt rPelX;
+    UInt bPelY;
+    Int64* stats;
+    Int64* count;
+    Int classIdx;
+    Int picWidthTmp = 0;
+    Int picHeightTmp = 0;
+    Int startX;
+    Int startY;
+    Int endX;
+    Int endY;
+    Int firstX, firstY;
+
+    Int j, k;
+
+    Int isChroma;
+    Int numSkipLine, numSkipLineRight;
+
+    UInt lPelX, tPelY;
+    TComDataCU *pTmpCu;
+    Pel* pTableBo;
+
+    lcuHeight = pTmpSPS->getMaxCUHeight();
+    lcuWidth  = pTmpSPS->getMaxCUWidth();
+    pTmpCu = pic->getCU(addr);
+    lPelX   = pTmpCu->getCUPelX();
+    tPelY   = pTmpCu->getCUPelY();
+    for (yCbCr = 0; yCbCr < 3; yCbCr++)
+    {
+        isChroma = (yCbCr != 0) ? 1 : 0;
+
+        for (j = 0; j < MAX_NUM_SAO_TYPE; j++)
+        {
+            for (k = 0; k < MAX_NUM_SAO_CLASS; k++)
+            {
+                TEncSampleAdaptiveOffset::m_countPreDblk[addr][yCbCr][j][k] = 0;
+                TEncSampleAdaptiveOffset::m_offsetOrgPreDblk[addr][yCbCr][j][k] = 0;
+            }
+        }
+
+        if (yCbCr == 0)
+        {
+            picWidthTmp  = m_picWidth;
+            picHeightTmp = m_picHeight;
+        }
+        else if (yCbCr == 1)
+        {
+            picWidthTmp  = m_picWidth  >> isChroma;
+            picHeightTmp = m_picHeight >> isChroma;
+            lcuWidth     = lcuWidth    >> isChroma;
+            lcuHeight    = lcuHeight   >> isChroma;
+            lPelX       = lPelX      >> isChroma;
+            tPelY       = tPelY      >> isChroma;
+        }
+        rPelX       = lPelX + lcuWidth;
+        bPelY       = tPelY + lcuHeight;
+        rPelX       = rPelX > picWidthTmp  ? picWidthTmp  : rPelX;
+        bPelY       = bPelY > picHeightTmp ? picHeightTmp : bPelY;
+        lcuWidth     = rPelX - lPelX;
+        lcuHeight    = bPelY - tPelY;
+
+        stride    =  (yCbCr == 0) ? pic->getStride() : pic->getCStride();
+        pTableBo = (yCbCr == 0) ? m_lumaTableBo : m_chromaTableBo;
+
+        //if(iSaoType == BO)
+
+        numSkipLine = isChroma ? 1 : 3;
+        numSkipLineRight = isChroma ? 2 : 4;
+
+        stats = TEncSampleAdaptiveOffset::m_offsetOrgPreDblk[addr][yCbCr][SAO_BO];
+        count = TEncSampleAdaptiveOffset::m_countPreDblk[addr][yCbCr][SAO_BO];
+
+        fenc = getPicYuvAddr(pic->getPicYuvOrg(), yCbCr, addr);
+        pRec = getPicYuvAddr(pic->getPicYuvRec(), yCbCr, addr);
+
+        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth - numSkipLineRight;
+        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight - numSkipLine;
+
+        for (y = 0; y < lcuHeight; y++)
+        {
+            for (x = 0; x < lcuWidth; x++)
+            {
+                if (x < startX && y < startY)
+                    continue;
+
+                classIdx = pTableBo[pRec[x]];
+                if (classIdx)
+                {
+                    stats[classIdx] += (fenc[x] - pRec[x]);
+                    count[classIdx]++;
+                }
+            }
+
+            fenc += stride;
+            pRec += stride;
+        }
+
+        Int signLeft;
+        Int signRight;
+        Int signDown;
+        Int signDown1;
+        Int signDown2;
+
+        UInt uiEdgeType;
+
+        //if (iSaoType == EO_0)
+
+        numSkipLine = isChroma ? 1 : 3;
+        numSkipLineRight = isChroma ? 3 : 5;
+
+        stats = TEncSampleAdaptiveOffset::m_offsetOrgPreDblk[addr][yCbCr][SAO_EO_0];
+        count = TEncSampleAdaptiveOffset::m_countPreDblk[addr][yCbCr][SAO_EO_0];
+
+        fenc = getPicYuvAddr(pic->getPicYuvOrg(), yCbCr, addr);
+        pRec = getPicYuvAddr(pic->getPicYuvRec(), yCbCr, addr);
+
+        startX   = (rPelX == picWidthTmp) ? lcuWidth - 1 : lcuWidth - numSkipLineRight;
+        startY   = (bPelY == picHeightTmp) ? lcuHeight : lcuHeight - numSkipLine;
+        firstX   = (lPelX == 0) ? 1 : 0;
+        endX   = (rPelX == picWidthTmp) ? lcuWidth - 1 : lcuWidth;
+
+        for (y = 0; y < lcuHeight; y++)
+        {
+            signLeft = xSign(pRec[firstX] - pRec[firstX - 1]);
+            for (x = firstX; x < endX; x++)
+            {
+                signRight =  xSign(pRec[x] - pRec[x + 1]);
+                uiEdgeType =  signRight + signLeft + 2;
+                signLeft  = -signRight;
+
+                if (x < startX && y < startY)
+                    continue;
+
+                stats[m_eoTable[uiEdgeType]] += (fenc[x] - pRec[x]);
+                count[m_eoTable[uiEdgeType]]++;
+            }
+
+            fenc += stride;
+            pRec += stride;
+        }
+
+        //if (iSaoType == EO_1)
+
+        numSkipLine = isChroma ? 2 : 4;
+        numSkipLineRight = isChroma ? 2 : 4;
+
+        stats = TEncSampleAdaptiveOffset::m_offsetOrgPreDblk[addr][yCbCr][SAO_EO_1];
+        count = TEncSampleAdaptiveOffset::m_countPreDblk[addr][yCbCr][SAO_EO_1];
+
+        fenc = getPicYuvAddr(pic->getPicYuvOrg(), yCbCr, addr);
+        pRec = getPicYuvAddr(pic->getPicYuvRec(), yCbCr, addr);
+
+        startX   = (rPelX == picWidthTmp) ? lcuWidth : lcuWidth - numSkipLineRight;
+        startY   = (bPelY == picHeightTmp) ? lcuHeight - 1 : lcuHeight - numSkipLine;
+        firstY = (tPelY == 0) ? 1 : 0;
+        endY   = (bPelY == picHeightTmp) ? lcuHeight - 1 : lcuHeight;
+        if (firstY == 1)
+        {
+            fenc += stride;
+            pRec += stride;
+        }
+
+        for (x = 0; x < lcuWidth; x++)
+        {
+            m_upBuff1[x] = xSign(pRec[x] - pRec[x - stride]);
+        }
+
+        for (y = firstY; y < endY; y++)
+        {
+            for (x = 0; x < lcuWidth; x++)
+            {
+                signDown     =  xSign(pRec[x] - pRec[x + stride]);
+                uiEdgeType    =  signDown + m_upBuff1[x] + 2;
+                m_upBuff1[x] = -signDown;
+
+                if (x < startX && y < startY)
+                    continue;
+
+                stats[m_eoTable[uiEdgeType]] += (fenc[x] - pRec[x]);
+                count[m_eoTable[uiEdgeType]]++;
+            }
+
+            fenc += stride;
+            pRec += stride;
+        }
+
+        //if (iSaoType == EO_2)
+
+        numSkipLine = isChroma ? 2 : 4;
+        numSkipLineRight = isChroma ? 3 : 5;
+
+        stats = TEncSampleAdaptiveOffset::m_offsetOrgPreDblk[addr][yCbCr][SAO_EO_2];
+        count = TEncSampleAdaptiveOffset::m_countPreDblk[addr][yCbCr][SAO_EO_2];
+
+        fenc = getPicYuvAddr(pic->getPicYuvOrg(), yCbCr, addr);
+        pRec = getPicYuvAddr(pic->getPicYuvRec(), yCbCr, addr);
+
+        startX   = (rPelX == picWidthTmp) ? lcuWidth - 1 : lcuWidth - numSkipLineRight;
+        startY   = (bPelY == picHeightTmp) ? lcuHeight - 1 : lcuHeight - numSkipLine;
+        firstX   = (lPelX == 0) ? 1 : 0;
+        firstY = (tPelY == 0) ? 1 : 0;
+        endX   = (rPelX == picWidthTmp) ? lcuWidth - 1 : lcuWidth;
+        endY   = (bPelY == picHeightTmp) ? lcuHeight - 1 : lcuHeight;
+        if (firstY == 1)
+        {
+            fenc += stride;
+            pRec += stride;
+        }
+
+        for (x = firstX; x < endX; x++)
+        {
+            m_upBuff1[x] = xSign(pRec[x] - pRec[x - stride - 1]);
+        }
+
+        for (y = firstY; y < endY; y++)
+        {
+            signDown2 = xSign(pRec[stride + startX] - pRec[startX - 1]);
+            for (x = firstX; x < endX; x++)
+            {
+                signDown1      =  xSign(pRec[x] - pRec[x + stride + 1]);
+                uiEdgeType      =  signDown1 + m_upBuff1[x] + 2;
+                m_upBufft[x + 1] = -signDown1;
+
+                if (x < startX && y < startY)
+                    continue;
+
+                stats[m_eoTable[uiEdgeType]] += (fenc[x] - pRec[x]);
+                count[m_eoTable[uiEdgeType]]++;
+            }
+
+            m_upBufft[firstX] = signDown2;
+            m_swap     = m_upBuff1;
+            m_upBuff1 = m_upBufft;
+            m_upBufft = m_swap;
+
+            pRec += stride;
+            fenc += stride;
+        }
+
+        //if (iSaoType == EO_3)
+
+        numSkipLine = isChroma ? 2 : 4;
+        numSkipLineRight = isChroma ? 3 : 5;
+
+        stats = TEncSampleAdaptiveOffset::m_offsetOrgPreDblk[addr][yCbCr][SAO_EO_3];
+        count = TEncSampleAdaptiveOffset::m_countPreDblk[addr][yCbCr][SAO_EO_3];
+
+        fenc = getPicYuvAddr(pic->getPicYuvOrg(), yCbCr, addr);
+        pRec = getPicYuvAddr(pic->getPicYuvRec(), yCbCr, addr);
+
+        startX   = (rPelX == picWidthTmp) ? lcuWidth - 1 : lcuWidth - numSkipLineRight;
+        startY   = (bPelY == picHeightTmp) ? lcuHeight - 1 : lcuHeight - numSkipLine;
+        firstX   = (lPelX == 0) ? 1 : 0;
+        firstY = (tPelY == 0) ? 1 : 0;
+        endX   = (rPelX == picWidthTmp) ? lcuWidth - 1 : lcuWidth;
+        endY   = (bPelY == picHeightTmp) ? lcuHeight - 1 : lcuHeight;
+        if (firstY == 1)
+        {
+            fenc += stride;
+            pRec += stride;
+        }
+
+        for (x = firstX - 1; x < endX; x++)
+        {
+            m_upBuff1[x] = xSign(pRec[x] - pRec[x - stride + 1]);
+        }
+
+        for (y = firstY; y < endY; y++)
+        {
+            for (x = firstX; x < endX; x++)
+            {
+                signDown1      =  xSign(pRec[x] - pRec[x + stride - 1]);
+                uiEdgeType      =  signDown1 + m_upBuff1[x] + 2;
+                m_upBuff1[x - 1] = -signDown1;
+
+                if (x < startX && y < startY)
+                    continue;
+
+                stats[m_eoTable[uiEdgeType]] += (fenc[x] - pRec[x]);
+                count[m_eoTable[uiEdgeType]]++;
+            }
+
+            m_upBuff1[endX - 1] = xSign(pRec[endX - 1 + stride] - pRec[endX]);
+
+            pRec += stride;
+            fenc += stride;
+        }
+    }
+}
+
 /** get SAO statistics
  * \param  *psQTPart,  yCbCr
  */
@@ -1834,8 +2149,8 @@
                         m_offset[compIdx][j][k] = 0;
                         if (m_saoLcuBasedOptimization && m_saoLcuBoundary)
                         {
-                            m_count[compIdx][j][k] = m_countPreDblk[addr][compIdx][j][k];
-                            m_offsetOrg[compIdx][j][k] = m_offsetOrgPreDblk[addr][compIdx][j][k];
+                            m_count[compIdx][j][k] = TEncSampleAdaptiveOffset::m_countPreDblk[addr][compIdx][j][k];
+                            m_offsetOrg[compIdx][j][k] = TEncSampleAdaptiveOffset::m_offsetOrgPreDblk[addr][compIdx][j][k];
                         }
                         else
                         {
diff -r c2f5275ecb49 -r fd7740c94413 source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h
--- a/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h	Fri Aug 16 20:15:57 2013 +0800
@@ -65,8 +65,8 @@
     Int64  ***m_count;    //[MAX_NUM_SAO_PART][MAX_NUM_SAO_TYPE][MAX_NUM_SAO_CLASS];
     Int64  ***m_offset;   //[MAX_NUM_SAO_PART][MAX_NUM_SAO_TYPE][MAX_NUM_SAO_CLASS];
     Int64  ***m_offsetOrg; //[MAX_NUM_SAO_PART][MAX_NUM_SAO_TYPE];
-    Int64  ****m_countPreDblk;    //[LCU][YCbCr][MAX_NUM_SAO_TYPE][MAX_NUM_SAO_CLASS];
-    Int64  ****m_offsetOrgPreDblk; //[LCU][YCbCr][MAX_NUM_SAO_TYPE][MAX_NUM_SAO_CLASS];
+    static Int64  ****m_countPreDblk;    //[LCU][YCbCr][MAX_NUM_SAO_TYPE][MAX_NUM_SAO_CLASS];
+    static Int64  ****m_offsetOrgPreDblk; //[LCU][YCbCr][MAX_NUM_SAO_TYPE][MAX_NUM_SAO_CLASS];
     Int64  **m_rate;      //[MAX_NUM_SAO_PART][MAX_NUM_SAO_TYPE];
     Int64  **m_dist;      //[MAX_NUM_SAO_PART][MAX_NUM_SAO_TYPE];
     Double **m_cost;      //[MAX_NUM_SAO_PART][MAX_NUM_SAO_TYPE];
@@ -96,6 +96,7 @@
     Void calcSaoStatsBlock(Pel* recStart, Pel* orgStart, Int stride, Int64** stats, Int64** counts, UInt width, UInt height, Bool* bBorderAvail, Int yCbCr);
     Void calcSaoStatsCuOrg(Int addr, Int partIdx, Int yCbCr);
     Void calcSaoStatsCu_BeforeDblk(TComPic* pic);
+    Void calcSaoStatsLCu_BeforeDblk(TComPic* pic, Int addr);
     Void destroyEncBuffer();
     Void createEncBuffer();
     Void assignSaoUnitSyntax(SaoLcuParam* saoLcuParam,  SAOQTPart* saoPart, Bool &oneUnitFlag);
diff -r c2f5275ecb49 -r fd7740c94413 source/Lib/TLibEncoder/TEncTop.cpp
--- a/source/Lib/TLibEncoder/TEncTop.cpp	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/Lib/TLibEncoder/TEncTop.cpp	Fri Aug 16 20:15:57 2013 +0800
@@ -167,6 +167,7 @@
             if (param.bEnableSAO)
             {
                 // TODO: these should be allocated on demand within the encoder
+                // NOTE: the SAO pointer from m_frameEncoder for read m_maxSplitLevel, etc, we can remove it later
                 pic->getPicSym()->allocSaoParam(m_frameEncoder->getSAO());
             }
             pic->getSlice()->setPOC(MAX_INT);
diff -r c2f5275ecb49 -r fd7740c94413 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/encoder/frameencoder.cpp	Fri Aug 16 20:15:57 2013 +0800
@@ -71,11 +71,6 @@
         delete[] m_rows;
     }
 
-    if (m_cfg->param.bEnableSAO)
-    {
-        m_sao.destroy();
-        m_sao.destroyEncBuffer();
-    }
     m_frameFilter.destroy();
 }
 
@@ -85,14 +80,6 @@
     m_cfg = top;
     m_numRows = numRows;
 
-    if (m_cfg->param.bEnableSAO)
-    {
-        m_sao.setSaoLcuBoundary(m_cfg->param.saoLcuBoundary);
-        m_sao.setSaoLcuBasedOptimization(m_cfg->param.saoLcuBasedOptimization);
-        m_sao.setMaxNumOffsetsPerPic(m_cfg->getMaxNumOffsetsPerPic());
-        m_sao.create(m_cfg->param.sourceWidth, m_cfg->param.sourceHeight, g_maxCUWidth, g_maxCUHeight);
-        m_sao.createEncBuffer();
-    }
     m_frameFilter.init(top, numRows);
 
     m_rows = new CTURow[m_numRows];
@@ -467,6 +454,11 @@
     cntIntraNxN = 0;
 #endif // if CU_STAT_LOGFILE
 
+    if (m_sps.getUseSAO())
+    {
+        pic->createNonDBFilterInfo(slice->getSliceCurEndCUAddr(), 0);
+    }
+
     // Analyze CTU rows, most of the hard work is done here
     // frame is compressed in a wave-front pattern if WPP is enabled. Loop filter runs as a
     // wave-front behind the CU compression and reconstruction
@@ -491,13 +483,6 @@
     }
 #endif // if LOGGING
 
-    // SAO parameter estimation using non-deblocked pixels for LCU bottom and right boundary areas
-    if (m_cfg->param.saoLcuBasedOptimization && m_cfg->param.saoLcuBoundary)
-    {
-        m_sao.resetStats();
-        m_sao.calcSaoStatsCu_BeforeDblk(pic);
-    }
-
     // wait for loop filter completion
     if (m_cfg->param.bEnableLoopFilter)
     {
@@ -505,12 +490,6 @@
         m_frameFilter.dequeue();
     }
 
-    if (m_sps.getUseSAO())
-    {
-        pic->createNonDBFilterInfo(slice->getSliceCurEndCUAddr(), 0);
-        m_sao.createPicSaoInfo(pic);
-    }
-
     if (m_cfg->param.bEnableWavefront)
     {
         slice->setNextSlice(true);
@@ -556,11 +535,11 @@
         entropyCoder->setBitstream(&m_bitCounter);
 
         // CHECK_ME: I think the SAO uses a temp Sbac only, so I always use [0], am I right?
-        m_sao.startSaoEnc(pic, entropyCoder, getRDGoOnSbacCoder(0));
+        getSAO()->startSaoEnc(pic, entropyCoder, getRDGoOnSbacCoder(0));
 
         SAOParam* saoParam = pic->getPicSym()->getSaoParam();
-        m_sao.SAOProcess(saoParam, slice->getLambdaLuma(), slice->getLambdaChroma(), slice->getDepth());
-        m_sao.endSaoEnc();
+        getSAO()->SAOProcess(saoParam, slice->getLambdaLuma(), slice->getLambdaChroma(), slice->getDepth());
+        getSAO()->endSaoEnc();
         PCMLFDisableProcess(pic);
 
         slice->setSaoEnabledFlag((saoParam->bSaoFlag[0] == 1) ? true : false);
@@ -686,7 +665,7 @@
 
     if (m_sps.getUseSAO())
     {
-        m_sao.destroyPicSaoInfo();
+        m_frameFilter.end();
         pic->destroyNonDBFilterInfo();
     }
     pic->compressMotion();
diff -r c2f5275ecb49 -r fd7740c94413 source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/encoder/frameencoder.h	Fri Aug 16 20:15:57 2013 +0800
@@ -136,7 +136,7 @@
     /* Frame singletons, last the life of the encoder */
     TEncSbac*               getSingletonSbac() { return &m_sbacCoder; }
 
-    TEncSampleAdaptiveOffset* getSAO()         { return &m_sao; }
+    TEncSampleAdaptiveOffset* getSAO()         { return &m_frameFilter.m_sao[0]; }
 
     TEncCavlc*              getCavlcCoder()    { return &m_cavlcCoder; }
 
@@ -187,7 +187,6 @@
     TEncBinCABAC             m_binCoderCABAC;
     TEncCavlc                m_cavlcCoder;
     FrameFilter              m_frameFilter;
-    TEncSampleAdaptiveOffset m_sao;
     TComBitCounter           m_bitCounter;
 
     TComPic*                 m_pic;
diff -r c2f5275ecb49 -r fd7740c94413 source/encoder/framefilter.cpp
--- a/source/encoder/framefilter.cpp	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/encoder/framefilter.cpp	Fri Aug 16 20:15:57 2013 +0800
@@ -40,6 +40,7 @@
     , m_rows_active(NULL)
     , m_locks(NULL)
     , m_loopFilter(NULL)
+    , m_sao(NULL)
 {}
 
 void FrameFilter::destroy()
@@ -63,12 +64,17 @@
 
     if (m_cfg->param.bEnableLoopFilter)
     {
+        assert(m_cfg->param.bEnableSAO);
         for (int i = 0; i < m_numRows; ++i)
         {
             m_loopFilter[i].destroy();
+            // NOTE: I don't check sao flag since loopfilter and sao have same control status
+            m_sao[i].destroy();
+            m_sao[i].destroyEncBuffer();
         }
 
         delete[] m_loopFilter;
+        delete[] m_sao;
     }
 }
 
@@ -84,9 +90,15 @@
     if (top->param.bEnableLoopFilter)
     {
         m_loopFilter = new TComLoopFilter[numRows];
+        m_sao = new TEncSampleAdaptiveOffset[numRows];
         for (int i = 0; i < m_numRows; ++i)
         {
             m_loopFilter[i].create(g_maxCUDepth);
+            m_sao[i].setSaoLcuBoundary(top->param.saoLcuBoundary);
+            m_sao[i].setSaoLcuBasedOptimization(top->param.saoLcuBasedOptimization);
+            m_sao[i].setMaxNumOffsetsPerPic(top->getMaxNumOffsetsPerPic());
+            m_sao[i].create(top->param.sourceWidth, top->param.sourceHeight, g_maxCUWidth, g_maxCUHeight);
+            m_sao[i].createEncBuffer();
         }
     }
 
@@ -111,6 +123,10 @@
             m_pic->m_complete_lft[i] = 0;
             m_rows_active[i] = false;
             m_complete_lftV[i] = 0;
+
+            if (m_cfg->param.saoLcuBasedOptimization && m_cfg->param.saoLcuBoundary)
+                m_sao[i].resetStats();
+            m_sao[i].createPicSaoInfo(pic);
         }
         else
         {
@@ -131,6 +147,17 @@
     WaveFront::dequeue();
 }
 
+void FrameFilter::end()
+{
+    if (m_cfg->param.bEnableLoopFilter)
+    {
+        for (int i = 0; i < m_numRows; i++)
+        {
+            m_sao[i].destroyPicSaoInfo();
+        }
+    }
+}
+
 void FrameFilter::enqueueRow(int row)
 {
     ScopedLock self(m_locks[row]);
@@ -174,6 +201,12 @@
         const uint32_t cuAddr = lineStartCUAddr + col;
         TComDataCU* cu = m_pic->getCU(cuAddr);
 
+        // SAO parameter estimation using non-deblocked pixels for LCU bottom and right boundary areas
+        if (m_cfg->param.saoLcuBasedOptimization && m_cfg->param.saoLcuBoundary)
+        {
+            m_sao[row].calcSaoStatsLCu_BeforeDblk(m_pic, cuAddr);
+        }
+
         m_loopFilter[row].loopFilterCU(cu, EDGE_VER);
         m_complete_lftV[row]++;
 
diff -r c2f5275ecb49 -r fd7740c94413 source/encoder/framefilter.h
--- a/source/encoder/framefilter.h	Fri Aug 16 07:02:26 2013 -0500
+++ b/source/encoder/framefilter.h	Fri Aug 16 20:15:57 2013 +0800
@@ -27,6 +27,7 @@
 
 #include "TLibCommon/TComPic.h"
 #include "TLibCommon/TComLoopFilter.h"
+#include "TLibEncoder/TEncSampleAdaptiveOffset.h"
 
 #include "threading.h"
 #include "wavefront.h"
@@ -52,6 +53,7 @@
     void destroy();
 
     void start(TComPic *pic);
+    void end();
 
     void wait();
 
@@ -69,9 +71,10 @@
 
 public:
 
-    TComLoopFilter*     m_loopFilter;
-    int                 m_numRows;
-    Event               m_completionEvent;
+    TComLoopFilter*             m_loopFilter;
+    TEncSampleAdaptiveOffset*   m_sao;
+    int                         m_numRows;
+    Event                       m_completionEvent;
 };
 
 }



More information about the x265-devel mailing list