<div dir="ltr">As expected there is not much change in performance, since SAO is very less time consuming module compared to other modules like look-ahead, motion estimation etc.<div>And I have modified only one function in SAO. I have tested one 4k video(tearsofsteel-4k-1000f-s214.y4m) with medium preset which has 1214 frames using intel vtune.</div><div><br></div><div><b>Before: 2545,02 (total cpu time)</b></div><div><b>After:    2536,95 (total CPU time)</b></div><div><b><br></b></div><div>Thanks</div><div>Ashok</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 18, 2016 at 9:39 PM, Pradeep Ramachandran <span dir="ltr"><<a href="mailto:pradeep@multicorewareinc.com" target="_blank">pradeep@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Ashok,<div>What is the impact on performance that you expect from these changes to SAO? Can you run encodes with 4K videos in ABR mode for ultrafast, medium, and veryslow and share the impact of performance if we expect an impact (which I think there will be)?</div></div><div class="gmail_extra"><br clear="all"><div><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Pradeep Ramachandran, PhD<div>Solution Architect at <a href="http://www.multicorewareinc.com/" style="font-size:12.8px" target="_blank">www.multicorewareinc.com/</a></div><div>Adjunct Faculty at<a href="http://www.cse.iitm.ac.in" target="_blank"> www.cse.iitm.ac.in</a>/</div><div><a href="http://pradeeprama.info/" style="font-size:12.8px" target="_blank">pradeeprama.info/</a><br></div><div><span style="font-size:12.8px">Ph:   +91 99627 82018</span><br></div></div></div></div></div></div></div></div></div></div>
<br><div class="gmail_quote"><div><div class="h5">On Mon, Jan 18, 2016 at 9:21 PM,  <span dir="ltr"><<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"># HG changeset patch<br>
# User Ashok Kumar Mishra<<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>><br>
# Date 1453132285 -19800<br>
#      Mon Jan 18 21:21:25 2016 +0530<br>
# Node ID 0f89b83c6fe64181296a51392ff52236dc6a934e<br>
# Parent  add820b8cde0fc82a643fd32717def5a3e2f3888<br>
SAO: perform merge distortion and cost calculation in one loop<br>
<br>
diff -r add820b8cde0 -r 0f89b83c6fe6 source/encoder/sao.cpp<br>
--- a/source/encoder/sao.cpp    Mon Jan 18 21:20:57 2016 +0530<br>
+++ b/source/encoder/sao.cpp    Mon Jan 18 21:21:25 2016 +0530<br>
@@ -758,16 +758,6 @@<br>
     std::swap(m_tmpL1[2], m_tmpL2[2]);<br>
 }<br>
<br>
-void SAO::copySaoUnit(SaoCtuParam* saoUnitDst, const SaoCtuParam* saoUnitSrc)<br>
-{<br>
-    saoUnitDst->mergeMode   = saoUnitSrc->mergeMode;<br>
-    saoUnitDst->typeIdx     = saoUnitSrc->typeIdx;<br>
-    saoUnitDst->bandPos     = saoUnitSrc->bandPos;<br>
-<br>
-    for (int i = 0; i < SAO_NUM_OFFSET; i++)<br>
-        saoUnitDst->offset[i] = saoUnitSrc->offset[i];<br>
-}<br>
-<br>
 /* Calculate SAO statistics for current CTU without non-crossing slice */<br>
 void SAO::calcSaoStatsCu(int addr, int plane)<br>
 {<br>
@@ -1233,158 +1223,12 @@<br>
         m_depthSaoRate[1 * SAO_DEPTHRATE_SIZE + m_refDepth] = m_numNoSao[1] / ((double)numctus);<br>
 }<br>
<br>
-void SAO::rdoSaoUnitRow(SAOParam* saoParam, int idxY)<br>
-{<br>
-    SaoCtuParam mergeSaoParam[NUM_MERGE_MODE][2];<br>
-    double lambda[3] = {m_lumaLambda, m_chromaLambda, m_chromaLambda};<br>
-    bool allowMerge[2]; // left, up<br>
-    allowMerge[1] = (idxY > 0);<br>
-<br>
-    for (int idxX = 0; idxX < m_numCuInWidth; idxX++)<br>
-    {<br>
-        int addr     = idxX + idxY * m_numCuInWidth;<br>
-        int addrUp   = idxY ? addr - m_numCuInWidth : -1;<br>
-        int addrLeft = idxX ? addr - 1 : -1;<br>
-        allowMerge[0] = (idxX > 0);<br>
-<br>
-        m_entropyCoder.load(m_rdContexts.cur);<br>
-        if (allowMerge[0])<br>
-            m_entropyCoder.codeSaoMerge(0);<br>
-        if (allowMerge[1])<br>
-            m_entropyCoder.codeSaoMerge(0);<br>
-        m_entropyCoder.store(m_rdContexts.temp);<br>
-<br>
-        // reset stats Y, Cb, Cr<br>
-        X265_CHECK(sizeof(PerPlane) == (sizeof(int32_t) * (NUM_PLANE * MAX_NUM_SAO_TYPE * MAX_NUM_SAO_CLASS)), "Found Padding space in struct PerPlane");<br>
-<br>
-        // TODO: Confirm the address space is continuous<br>
-        if (m_param->bSaoNonDeblocked)<br>
-        {<br>
-            memcpy(m_count, m_countPreDblk[addr], sizeof(m_count));<br>
-            memcpy(m_offsetOrg, m_offsetOrgPreDblk[addr], sizeof(m_offsetOrg));<br>
-        }<br>
-        else<br>
-        {<br>
-            memset(m_count, 0, sizeof(m_count));<br>
-            memset(m_offsetOrg, 0, sizeof(m_offsetOrg));<br>
-        }<br>
-<br>
-        saoParam->ctuParam[0][addr].reset();<br>
-        saoParam->ctuParam[1][addr].reset();<br>
-        saoParam->ctuParam[2][addr].reset();<br>
-<br>
-        if (saoParam->bSaoFlag[0])<br>
-            calcSaoStatsCu(addr, 0);<br>
-<br>
-        if (saoParam->bSaoFlag[1])<br>
-        {<br>
-            calcSaoStatsCu(addr, 1);<br>
-            calcSaoStatsCu(addr, 2);<br>
-        }<br>
-<br>
-        double mergeDist[NUM_MERGE_MODE] = {0.0, 0.0, 0.0};<br>
-        saoLumaComponentParamDist(saoParam, addr, mergeDist);<br>
-        if (m_chromaFormat != X265_CSP_I400)<br>
-            saoChromaComponentParamDist(saoParam, addr, mergeDist);<br>
-<br>
-        // merge left or merge up<br>
-        for (int plane = 0; plane < 3; plane++)<br>
-        {<br>
-            for (int mergeIdx = 0; mergeIdx < 2; mergeIdx++)<br>
-            {<br>
-                SaoCtuParam* mergeSrcParam = NULL;<br>
-                if (addrLeft >= 0 && mergeIdx == 0)<br>
-                    mergeSrcParam = &(saoParam->ctuParam[plane][addrLeft]);<br>
-                else if (addrUp >= 0 && mergeIdx == 1)<br>
-                    mergeSrcParam = &(saoParam->ctuParam[plane][addrUp]);<br>
-                if (mergeSrcParam)<br>
-                {<br>
-                    int64_t estDist = 0;<br>
-                    int typeIdx = mergeSrcParam->typeIdx;<br>
-                    if (typeIdx >= 0)<br>
-                    {<br>
-                        int bandPos = (typeIdx == SAO_BO) ? mergeSrcParam->bandPos : 0;<br>
-                        for (int classIdx = 0; classIdx < SAO_NUM_OFFSET; classIdx++)<br>
-                        {<br>
-                            int mergeOffset = mergeSrcParam->offset[classIdx];<br>
-                            estDist += estSaoDist(m_count[plane][typeIdx][classIdx + bandPos + 1], mergeOffset, m_offsetOrg[plane][typeIdx][classIdx + bandPos + 1]);<br>
-                        }<br>
-                    }<br>
-<br>
-                    copySaoUnit(&mergeSaoParam[plane][mergeIdx], mergeSrcParam);<br>
-                    mergeSaoParam[plane][mergeIdx].mergeMode = mergeIdx ? SAO_MERGE_UP : SAO_MERGE_LEFT;<br>
-                    mergeDist[mergeIdx + 1] += ((double)estDist / lambda[plane]);<br>
-                }<br>
-            }<br>
-        }<br>
-<br>
-        if (saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1])<br>
-        {<br>
-            // Cost of new SAO_params<br>
-            m_entropyCoder.load(m_rdContexts.cur);<br>
-            m_entropyCoder.resetBits();<br>
-            if (allowMerge[0])<br>
-                m_entropyCoder.codeSaoMerge(0);<br>
-            if (allowMerge[1])<br>
-                m_entropyCoder.codeSaoMerge(0);<br>
-            for (int plane = 0; plane < 3; plane++)<br>
-            {<br>
-                if (saoParam->bSaoFlag[plane > 0])<br>
-                    m_entropyCoder.codeSaoOffset(saoParam->ctuParam[plane][addr], plane);<br>
-            }<br>
-<br>
-            uint32_t rate = m_entropyCoder.getNumberOfWrittenBits();<br>
-            double bestCost = mergeDist[0] + (double)rate;<br>
-            m_entropyCoder.store(m_rdContexts.temp);<br>
-<br>
-            // Cost of Merge<br>
-            for (int mergeIdx = 0; mergeIdx < 2; ++mergeIdx)<br>
-            {<br>
-                if (!allowMerge[mergeIdx])<br>
-                    continue;<br>
-<br>
-                m_entropyCoder.load(m_rdContexts.cur);<br>
-                m_entropyCoder.resetBits();<br>
-                if (allowMerge[0])<br>
-                    m_entropyCoder.codeSaoMerge(1 - mergeIdx);<br>
-                if (allowMerge[1] && (mergeIdx == 1))<br>
-                    m_entropyCoder.codeSaoMerge(1);<br>
-<br>
-                rate = m_entropyCoder.getNumberOfWrittenBits();<br>
-                double mergeCost = mergeDist[mergeIdx + 1] + (double)rate;<br>
-                if (mergeCost < bestCost)<br>
-                {<br>
-                    SaoMergeMode mergeMode = mergeIdx ? SAO_MERGE_UP : SAO_MERGE_LEFT;<br>
-                    bestCost = mergeCost;<br>
-                    m_entropyCoder.store(m_rdContexts.temp);<br>
-                    for (int plane = 0; plane < 3; plane++)<br>
-                    {<br>
-                        mergeSaoParam[plane][mergeIdx].mergeMode = mergeMode;<br>
-                        if (saoParam->bSaoFlag[plane > 0])<br>
-                            copySaoUnit(&saoParam->ctuParam[plane][addr], &mergeSaoParam[plane][mergeIdx]);<br>
-                    }<br>
-                }<br>
-            }<br>
-<br>
-            if (saoParam->ctuParam[0][addr].typeIdx < 0)<br>
-                m_numNoSao[0]++;<br>
-            if (m_chromaFormat != X265_CSP_I400 && saoParam->ctuParam[1][addr].typeIdx < 0)<br>
-                m_numNoSao[1]++;<br>
-<br>
-            m_entropyCoder.load(m_rdContexts.temp);<br>
-            m_entropyCoder.store(m_rdContexts.cur);<br>
-        }<br>
-    }<br>
-}<br>
-<br>
 void SAO::rdoSaoUnitCu(SAOParam* saoParam, int rowBaseAddr, int idxX, int addr)<br>
 {<br>
-    SaoCtuParam mergeSaoParam[NUM_MERGE_MODE][2];<br>
     double lambda[3] = {m_lumaLambda, m_chromaLambda, m_chromaLambda};<br>
     const bool allowMerge[2] = {(idxX != 0), (rowBaseAddr != 0)}; // left, up<br>
<br>
-    const int addrUp   = rowBaseAddr ? addr - m_numCuInWidth : -1;<br>
-    const int addrLeft = idxX ? addr - 1 : -1;<br>
+    const int addrMerge[2] = {(idxX ? addr - 1 : -1), (rowBaseAddr ? addr - m_numCuInWidth : -1)};// left, up<br>
<br>
     bool chroma = m_param->internalCsp != X265_CSP_I400;<br>
     int planes = chroma ? 3 : 1;<br>
@@ -1425,45 +1269,14 @@<br>
         calcSaoStatsCu(addr, 1);<br>
         calcSaoStatsCu(addr, 2);<br>
         saoStatsInitialOffset(1);<br>
-        saoStatsInitialOffset(2);<br>
+//        saoStatsInitialOffset(2);<br>
     }<br>
<br>
-    double mergeDist[NUM_MERGE_MODE] = {0.0, 0.0, 0.0};<br>
+    double mergeDist[NUM_MERGE_MODE] = { 0.0 };<br>
     saoLumaComponentParamDist(saoParam, addr, mergeDist);<br>
     if (chroma)<br>
         saoChromaComponentParamDist(saoParam, addr, mergeDist);<br>
<br>
-    // merge left or merge up<br>
-    for (int plane = 0; plane < planes; plane++)<br>
-    {<br>
-        for (int mergeIdx = 0; mergeIdx < 2; mergeIdx++)<br>
-        {<br>
-            SaoCtuParam* mergeSrcParam = NULL;<br>
-            if (addrLeft >= 0 && mergeIdx == 0)<br>
-                mergeSrcParam = &(saoParam->ctuParam[plane][addrLeft]);<br>
-            else if (addrUp >= 0 && mergeIdx == 1)<br>
-                mergeSrcParam = &(saoParam->ctuParam[plane][addrUp]);<br>
-            if (mergeSrcParam)<br>
-            {<br>
-                int64_t estDist = 0;<br>
-                int typeIdx = mergeSrcParam->typeIdx;<br>
-                if (typeIdx >= 0)<br>
-                {<br>
-                    int bandPos = (typeIdx == SAO_BO) ? mergeSrcParam->bandPos : 0;<br>
-                    for (int classIdx = 0; classIdx < SAO_NUM_OFFSET; classIdx++)<br>
-                    {<br>
-                        int mergeOffset = mergeSrcParam->offset[classIdx];<br>
-                        estDist += estSaoDist(m_count[plane][typeIdx][classIdx + bandPos + 1], mergeOffset, m_offsetOrg[plane][typeIdx][classIdx + bandPos + 1]);<br>
-                    }<br>
-                }<br>
-<br>
-                copySaoUnit(&mergeSaoParam[plane][mergeIdx], mergeSrcParam);<br>
-                mergeSaoParam[plane][mergeIdx].mergeMode = mergeIdx ? SAO_MERGE_UP : SAO_MERGE_LEFT;<br>
-                mergeDist[mergeIdx + 1] += ((double)estDist / lambda[plane]);<br>
-            }<br>
-        }<br>
-    }<br>
-<br>
     if (saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1])<br>
     {<br>
         // Cost of new SAO_params<br>
@@ -1483,12 +1296,31 @@<br>
         double bestCost = mergeDist[0] + (double)rate;<br>
         m_entropyCoder.store(m_rdContexts.temp);<br>
<br>
-        // Cost of Merge<br>
+        // Cost of merge left or Up<br>
         for (int mergeIdx = 0; mergeIdx < 2; ++mergeIdx)<br>
         {<br>
             if (!allowMerge[mergeIdx])<br>
                 continue;<br>
<br>
+            for (int plane = 0; plane < 3; plane++)<br>
+            {<br>
+                int64_t estDist = 0;<br>
+                SaoCtuParam* mergeSrcParam = &(saoParam->ctuParam[plane][addrMerge[mergeIdx]]);<br>
+                int typeIdx = mergeSrcParam->typeIdx;<br>
+                if (typeIdx >= 0)<br>
+                {<br>
+                    int bandPos = (typeIdx == SAO_BO) ? mergeSrcParam->bandPos : 0;<br>
+                    for (int classIdx = 0; classIdx < SAO_NUM_OFFSET; classIdx++)<br>
+                    {<br>
+                        int mergeOffset = mergeSrcParam->offset[classIdx];<br>
+                        estDist += estSaoDist(m_count[plane][typeIdx][classIdx + bandPos + 1], mergeOffset, m_offsetOrg[plane][typeIdx][classIdx + bandPos + 1]);<br>
+                    }<br>
+                }<br>
+<br>
+                mergeDist[mergeIdx + 1] += ((double)estDist / lambda[plane]);<br>
+            }<br>
+<br>
+<br>
             m_entropyCoder.load(m_rdContexts.cur);<br>
             m_entropyCoder.resetBits();<br>
             if (allowMerge[0])<br>
@@ -1505,9 +1337,17 @@<br>
                 m_entropyCoder.store(m_rdContexts.temp);<br>
                 for (int plane = 0; plane < planes; plane++)<br>
                 {<br>
-                    mergeSaoParam[plane][mergeIdx].mergeMode = mergeMode;<br>
                     if (saoParam->bSaoFlag[plane > 0])<br>
-                        copySaoUnit(&saoParam->ctuParam[plane][addr], &mergeSaoParam[plane][mergeIdx]);<br>
+                    {<br>
+                        SaoCtuParam* dstCtuParam   = &saoParam->ctuParam[plane][addr];<br>
+                        SaoCtuParam* mergeSrcParam = &(saoParam->ctuParam[plane][addrMerge[mergeIdx]]);<br>
+                        dstCtuParam->mergeMode = mergeMode;<br>
+                        dstCtuParam->typeIdx   = mergeSrcParam->typeIdx;<br>
+                        dstCtuParam->bandPos   = mergeSrcParam->bandPos;<br>
+<br>
+                        for (int i = 0; i < SAO_NUM_OFFSET; i++)<br>
+                            dstCtuParam->offset[i] = mergeSrcParam->offset[i];<br>
+                    }<br>
                 }<br>
             }<br>
         }<br>
@@ -1524,75 +1364,81 @@<br>
<br>
 // Rounds the division of initial offsets by the number of samples in<br>
 // each of the statistics table entries.<br>
-void SAO::saoStatsInitialOffset(int plane)<br>
+void SAO::saoStatsInitialOffset(int planes)<br>
 {<br>
     // EO<br>
-    for (int typeIdx = 0; typeIdx < MAX_NUM_SAO_TYPE - 1; typeIdx++)<br>
+    for (int plane = planes; plane <= 2*planes; plane++)<br>
     {<br>
-        for (int classIdx = 1; classIdx < SAO_EO_LEN + 1; classIdx++)<br>
+        for (int typeIdx = 0; typeIdx < MAX_NUM_SAO_TYPE - 1; typeIdx++)<br>
         {<br>
-            int32_t  count     = m_count[plane][typeIdx][classIdx];<br>
-            int32_t& offsetOrg = m_offsetOrg[plane][typeIdx][classIdx];<br>
-            int32_t& offsetOut = m_offset[plane][typeIdx][classIdx];<br>
+            for (int classIdx = 1; classIdx < SAO_EO_LEN + 1; classIdx++)<br>
+            {<br>
+                int32_t  count     = m_count[plane][typeIdx][classIdx];<br>
+                int32_t& offsetOrg = m_offsetOrg[plane][typeIdx][classIdx];<br>
+                int32_t& offsetOut = m_offset[plane][typeIdx][classIdx];<br>
+<br>
+                if (count)<br>
+                {<br>
+                    offsetOut = roundIBDI(offsetOrg, count << SAO_BIT_INC);<br>
+                    offsetOut = x265_clip3(-OFFSET_THRESH + 1, OFFSET_THRESH - 1, offsetOut);<br>
+<br>
+                    if (classIdx < 3)<br>
+                        offsetOut = X265_MAX(offsetOut, 0);<br>
+                    else<br>
+                        offsetOut = X265_MIN(offsetOut, 0);<br>
+                }<br>
+            }<br>
+        }<br>
+    }<br>
+<br>
+    // BO<br>
+    for (int plane = planes; plane <= 2*planes; plane++)<br>
+    {<br>
+        for (int classIdx = 1; classIdx < SAO_NUM_BO_CLASSES + 1; classIdx++)<br>
+        {<br>
+            int32_t  count     = m_count[plane][SAO_BO][classIdx];<br>
+            int32_t& offsetOrg = m_offsetOrg[plane][SAO_BO][classIdx];<br>
+            int32_t& offsetOut = m_offset[plane][SAO_BO][classIdx];<br>
<br>
             if (count)<br>
             {<br>
                 offsetOut = roundIBDI(offsetOrg, count << SAO_BIT_INC);<br>
                 offsetOut = x265_clip3(-OFFSET_THRESH + 1, OFFSET_THRESH - 1, offsetOut);<br>
-<br>
-                if (classIdx < 3)<br>
-                    offsetOut = X265_MAX(offsetOut, 0);<br>
-                else<br>
-                    offsetOut = X265_MIN(offsetOut, 0);<br>
             }<br>
         }<br>
     }<br>
-    // BO<br>
-    for (int classIdx = 1; classIdx < SAO_NUM_BO_CLASSES + 1; classIdx++)<br>
-    {<br>
-        int32_t  count     = m_count[plane][SAO_BO][classIdx];<br>
-        int32_t& offsetOrg = m_offsetOrg[plane][SAO_BO][classIdx];<br>
-        int32_t& offsetOut = m_offset[plane][SAO_BO][classIdx];<br>
-<br>
-        if (count)<br>
-        {<br>
-            offsetOut = roundIBDI(offsetOrg, count << SAO_BIT_INC);<br>
-            offsetOut = x265_clip3(-OFFSET_THRESH + 1, OFFSET_THRESH - 1, offsetOut);<br>
-        }<br>
-    }<br>
 }<br>
<br>
-inline int SAO::estIterOffset(int typeIdx, int classIdx, double lambda, int offset, int32_t count, int32_t offsetOrg, int32_t* currentDistortionTableBo, double* currentRdCostTableBo)<br>
+inline int SAO::estIterOffset(int typeIdx, double lambda, int offset, int32_t count, int32_t offsetOrg, int& distBOClasses, double& costBOClasses)<br>
 {<br>
-    int offsetOut = 0;<br>
+    int bestOffset = 0;<br>
<br>
-    // Assuming sending quantized value 0 results in zero offset and sending the value zero needs 1 bit. entropy coder can be used to measure the exact rate here.<br>
-    double tempMinCost = lambda;<br>
+    // Assuming sending quantized value 0 results in zero offset and sending the value zero needs 1 bit.<br>
+    // entropy coder can be used to measure the exact rate here.<br>
+    double bestCost = lambda;<br>
     while (offset != 0)<br>
     {<br>
         // Calculate the bits required for signalling the offset<br>
-        int tempRate = (typeIdx == SAO_BO) ? (abs(offset) + 2) : (abs(offset) + 1);<br>
+        int rate = (typeIdx == SAO_BO) ? (abs(offset) + 2) : (abs(offset) + 1);<br>
         if (abs(offset) == OFFSET_THRESH - 1)<br>
-            tempRate--;<br>
+            rate--;<br>
<br>
         // Do the dequntization before distorion calculation<br>
-        int tempOffset = offset << SAO_BIT_INC;<br>
-        int64_t tempDist  = estSaoDist(count, tempOffset, offsetOrg);<br>
-        double tempCost   = ((double)tempDist + lambda * (double)tempRate);<br>
-        if (tempCost < tempMinCost)<br>
+        int64_t dist = estSaoDist(count, offset << SAO_BIT_INC, offsetOrg);<br>
+        double cost  = ((double)dist + lambda * (double)rate);<br>
+        if (cost < bestCost)<br>
         {<br>
-            tempMinCost = tempCost;<br>
-            offsetOut = offset;<br>
+            bestCost = cost;<br>
+            bestOffset = offset;<br>
             if (typeIdx == SAO_BO)<br>
             {<br>
-                currentDistortionTableBo[classIdx - 1] = (int)tempDist;<br>
-                currentRdCostTableBo[classIdx - 1] = tempCost;<br>
+                distBOClasses = (int)dist;<br>
+                costBOClasses = bestCost;<br>
             }<br>
         }<br>
         offset = (offset > 0) ? (offset - 1) : (offset + 1);<br>
     }<br>
-<br>
-    return offsetOut;<br>
+    return bestOffset;<br>
 }<br>
<br>
 void SAO::saoLumaComponentParamDist(SAOParam* saoParam, int addr, double* mergeDist)<br>
@@ -1602,8 +1448,8 @@<br>
<br>
     SaoCtuParam* lclCtuParam = &saoParam->ctuParam[0][addr];<br>
<br>
-    int    currentDistortionTableBo[MAX_NUM_SAO_CLASS];<br>
-    double currentRdCostTableBo[MAX_NUM_SAO_CLASS];<br>
+    int    distBOClasses[MAX_NUM_SAO_CLASS];<br>
+    double costBOClasses[MAX_NUM_SAO_CLASS];<br>
<br>
     m_entropyCoder.load(m_rdContexts.temp);<br>
     m_entropyCoder.resetBits();<br>
@@ -1621,15 +1467,9 @@<br>
             int32_t& offsetOrg = m_offsetOrg[0][typeIdx][classIdx];<br>
             int32_t& offsetOut = m_offset[0][typeIdx][classIdx];<br>
<br>
-            if (count)<br>
-            {<br>
-                offsetOut = estIterOffset(typeIdx, classIdx, m_lumaLambda, offsetOut, count, offsetOrg, currentDistortionTableBo, currentRdCostTableBo);<br>
-            }<br>
-            else<br>
-            {<br>
-                offsetOrg = 0;<br>
-                offsetOut = 0;<br>
-            }<br>
+            if (offsetOut)<br>
+                offsetOut = estIterOffset(typeIdx, m_lumaLambda, offsetOut, count, offsetOrg, distBOClasses[0], costBOClasses[0]);<br>
+<br>
             estDist += estSaoDist(count, (int)offsetOut << SAO_BIT_INC, offsetOrg);<br>
         }<br>
<br>
@@ -1665,44 +1505,37 @@<br>
         int32_t& offsetOrg = m_offsetOrg[0][SAO_BO][classIdx];<br>
         int32_t& offsetOut = m_offset[0][SAO_BO][classIdx];<br>
<br>
-        currentDistortionTableBo[classIdx - 1] = 0;<br>
-        currentRdCostTableBo[classIdx - 1] = m_lumaLambda;<br>
+        distBOClasses[classIdx - 1] = 0;<br>
+        costBOClasses[classIdx - 1] = m_lumaLambda;<br>
<br>
-        if (count)<br>
-        {<br>
-            offsetOut = estIterOffset(SAO_BO, classIdx, m_lumaLambda, offsetOut, count, offsetOrg, currentDistortionTableBo, currentRdCostTableBo);<br>
-        }<br>
-        else<br>
-        {<br>
-            offsetOrg = 0;<br>
-            offsetOut = 0;<br>
-        }<br>
+        if (offsetOut)<br>
+            offsetOut = estIterOffset(SAO_BO, m_lumaLambda, offsetOut, count, offsetOrg, distBOClasses[classIdx - 1], costBOClasses[classIdx - 1]);<br>
     }<br>
<br>
     // Estimate Best Position<br>
-    double bestRDCostTableBo = MAX_DOUBLE;<br>
-    int    bestClassTableBo  = 0;<br>
+    double bestRDCostBO = MAX_DOUBLE;<br>
+    int    bestClassBO  = 0;<br>
<br>
     for (int i = 0; i < SAO_NUM_BO_CLASSES - SAO_BO_LEN + 1; i++)<br>
     {<br>
         double currentRDCost = 0.0;<br>
         for (int j = i; j < i + SAO_BO_LEN; j++)<br>
-            currentRDCost += currentRdCostTableBo[j];<br>
+            currentRDCost += costBOClasses[j];<br>
<br>
-        if (currentRDCost < bestRDCostTableBo)<br>
+        if (currentRDCost < bestRDCostBO)<br>
         {<br>
-            bestRDCostTableBo = currentRDCost;<br>
-            bestClassTableBo  = i;<br>
+            bestRDCostBO = currentRDCost;<br>
+            bestClassBO  = i;<br>
         }<br>
     }<br>
<br>
     estDist = 0;<br>
-    for (int classIdx = bestClassTableBo; classIdx < bestClassTableBo + SAO_BO_LEN; classIdx++)<br>
-        estDist += currentDistortionTableBo[classIdx];<br>
+    for (int classIdx = bestClassBO; classIdx < bestClassBO + SAO_BO_LEN; classIdx++)<br>
+        estDist += distBOClasses[classIdx];<br>
<br>
     m_entropyCoder.load(m_rdContexts.temp);<br>
     m_entropyCoder.resetBits();<br>
-    m_entropyCoder.codeSaoOffsetBO(m_offset[0][SAO_BO] + (bestClassTableBo + 1), bestClassTableBo, 0);<br>
+    m_entropyCoder.codeSaoOffsetBO(m_offset[0][SAO_BO] + (bestClassBO + 1), bestClassBO, 0);<br>
<br>
     uint32_t estRate = m_entropyCoder.getNumberOfWrittenBits();<br>
     double cost = (double)estDist + m_lumaLambda * (double)estRate;<br>
@@ -1714,9 +1547,9 @@<br>
<br>
         lclCtuParam->mergeMode = SAO_MERGE_NONE;<br>
         lclCtuParam->typeIdx = SAO_BO;<br>
-        lclCtuParam->bandPos = bestClassTableBo;<br>
+        lclCtuParam->bandPos = bestClassBO;<br>
         for (int classIdx = 0; classIdx < SAO_NUM_OFFSET; classIdx++)<br>
-            lclCtuParam->offset[classIdx] = (int)m_offset[0][SAO_BO][classIdx + bestClassTableBo + 1];<br>
+            lclCtuParam->offset[classIdx] = (int)m_offset[0][SAO_BO][classIdx + bestClassBO + 1];<br>
     }<br>
<br>
     mergeDist[0] = ((double)bestDist / m_lumaLambda);<br>
@@ -1732,9 +1565,9 @@<br>
<br>
     SaoCtuParam* lclCtuParam[2] = { &saoParam->ctuParam[1][addr], &saoParam->ctuParam[2][addr] };<br>
<br>
-    double currentRdCostTableBo[MAX_NUM_SAO_CLASS];<br>
-    int    currentDistortionTableBo[MAX_NUM_SAO_CLASS];<br>
-    int    bestClassTableBo[2] = { 0, 0 };<br>
+    double costBOClasses[MAX_NUM_SAO_CLASS];<br>
+    int    distBOClasses[MAX_NUM_SAO_CLASS];<br>
+    int    bestClassBO[2] = { 0, 0 };<br>
<br>
     m_entropyCoder.load(m_rdContexts.temp);<br>
     m_entropyCoder.resetBits();<br>
@@ -1754,15 +1587,8 @@<br>
                 int32_t& offsetOrg = m_offsetOrg[compIdx][typeIdx][classIdx];<br>
                 int32_t& offsetOut = m_offset[compIdx][typeIdx][classIdx];<br>
<br>
-                if (count)<br>
-                {<br>
-                    offsetOut = estIterOffset(typeIdx, classIdx, m_chromaLambda, offsetOut, count, offsetOrg, currentDistortionTableBo, currentRdCostTableBo);<br>
-                }<br>
-                else<br>
-                {<br>
-                    offsetOrg = 0;<br>
-                    offsetOut = 0;<br>
-                }<br>
+                if (offsetOut)<br>
+                    offsetOut = estIterOffset(typeIdx, m_chromaLambda, offsetOut, count, offsetOrg, distBOClasses[0], costBOClasses[0]);<br>
<br>
                 estDist[compIdx - 1] += estSaoDist(count, (int)offsetOut << SAO_BIT_INC, offsetOrg);<br>
             }<br>
@@ -1772,9 +1598,7 @@<br>
         m_entropyCoder.resetBits();<br>
<br>
         for (int compIdx = 0; compIdx < 2; compIdx++)<br>
-        {<br>
             m_entropyCoder.codeSaoOffsetEO(m_offset[compIdx + 1][typeIdx] + 1, typeIdx, compIdx + 1);<br>
-        }<br>
<br>
         uint32_t estRate = m_entropyCoder.getNumberOfWrittenBits();<br>
         double cost = (double)(estDist[0] + estDist[1]) + m_chromaLambda * (double)estRate;<br>
@@ -1805,7 +1629,7 @@<br>
     // Estimate Best Position<br>
     for (int compIdx = 1; compIdx < 3; compIdx++)<br>
     {<br>
-        double bestRDCostTableBo = MAX_DOUBLE;<br>
+        double bestRDCostBO = MAX_DOUBLE;<br>
<br>
         for (int classIdx = 1; classIdx < SAO_NUM_BO_CLASSES + 1; classIdx++)<br>
         {<br>
@@ -1813,45 +1637,36 @@<br>
             int32_t& offsetOrg = m_offsetOrg[compIdx][SAO_BO][classIdx];<br>
             int32_t& offsetOut = m_offset[compIdx][SAO_BO][classIdx];<br>
<br>
-            currentDistortionTableBo[classIdx - 1] = 0;<br>
-            currentRdCostTableBo[classIdx - 1] = m_chromaLambda;<br>
+            distBOClasses[classIdx - 1] = 0;<br>
+            costBOClasses[classIdx - 1] = m_chromaLambda;<br>
<br>
-            if (count)<br>
-            {<br>
-                offsetOut = estIterOffset(SAO_BO, classIdx, m_chromaLambda, offsetOut, count, offsetOrg, currentDistortionTableBo, currentRdCostTableBo);<br>
-            }<br>
-            else<br>
-            {<br>
-                offsetOrg = 0;<br>
-                offsetOut = 0;<br>
-            }<br>
+            if (offsetOut)<br>
+                offsetOut = estIterOffset(SAO_BO, m_chromaLambda, offsetOut, count, offsetOrg, distBOClasses[classIdx - 1], costBOClasses[classIdx - 1]);<br>
         }<br>
<br>
         for (int i = 0; i < SAO_NUM_BO_CLASSES - SAO_BO_LEN + 1; i++)<br>
         {<br>
             double currentRDCost = 0.0;<br>
             for (int j = i; j < i + SAO_BO_LEN; j++)<br>
-                currentRDCost += currentRdCostTableBo[j];<br>
+                currentRDCost += costBOClasses[j];<br>
<br>
-            if (currentRDCost < bestRDCostTableBo)<br>
+            if (currentRDCost < bestRDCostBO)<br>
             {<br>
-                bestRDCostTableBo = currentRDCost;<br>
-                bestClassTableBo[compIdx - 1]  = i;<br>
+                bestRDCostBO = currentRDCost;<br>
+                bestClassBO[compIdx - 1]  = i;<br>
             }<br>
         }<br>
<br>
         estDist[compIdx - 1] = 0;<br>
-        for (int classIdx = bestClassTableBo[compIdx - 1]; classIdx < bestClassTableBo[compIdx - 1] + SAO_BO_LEN; classIdx++)<br>
-            estDist[compIdx - 1] += currentDistortionTableBo[classIdx];<br>
+        for (int classIdx = bestClassBO[compIdx - 1]; classIdx < bestClassBO[compIdx - 1] + SAO_BO_LEN; classIdx++)<br>
+            estDist[compIdx - 1] += distBOClasses[classIdx];<br>
     }<br>
<br>
     m_entropyCoder.load(m_rdContexts.temp);<br>
     m_entropyCoder.resetBits();<br>
<br>
     for (int compIdx = 0; compIdx < 2; compIdx++)<br>
-    {<br>
-        m_entropyCoder.codeSaoOffsetBO(m_offset[compIdx + 1][SAO_BO] + (bestClassTableBo[compIdx] + 1), bestClassTableBo[compIdx], compIdx + 1);<br>
-    }<br>
+        m_entropyCoder.codeSaoOffsetBO(m_offset[compIdx + 1][SAO_BO] + (bestClassBO[compIdx] + 1), bestClassBO[compIdx], compIdx + 1);<br>
<br>
     uint32_t estRate = m_entropyCoder.getNumberOfWrittenBits();<br>
     double cost = (double)(estDist[0] + estDist[1]) + m_chromaLambda * (double)estRate;<br>
@@ -1865,9 +1680,9 @@<br>
         {<br>
             lclCtuParam[compIdx]->mergeMode = SAO_MERGE_NONE;<br>
             lclCtuParam[compIdx]->typeIdx = SAO_BO;<br>
-            lclCtuParam[compIdx]->bandPos = bestClassTableBo[compIdx];<br>
+            lclCtuParam[compIdx]->bandPos = bestClassBO[compIdx];<br>
             for (int classIdx = 0; classIdx < SAO_NUM_OFFSET; classIdx++)<br>
-                lclCtuParam[compIdx]->offset[classIdx] = (int)m_offset[compIdx + 1][SAO_BO][classIdx + bestClassTableBo[compIdx] + 1];<br>
+                lclCtuParam[compIdx]->offset[classIdx] = (int)m_offset[compIdx + 1][SAO_BO][classIdx + bestClassBO[compIdx] + 1];<br>
         }<br>
     }<br>
<br>
diff -r add820b8cde0 -r 0f89b83c6fe6 source/encoder/sao.h<br>
--- a/source/encoder/sao.h      Mon Jan 18 21:20:57 2016 +0530<br>
+++ b/source/encoder/sao.h      Mon Jan 18 21:21:25 2016 +0530<br>
@@ -136,7 +136,7 @@<br>
     void processSaoUnitCuLuma(SaoCtuParam* ctuParam, int idxY, int idxX);<br>
     void processSaoUnitCuChroma(SaoCtuParam* ctuParam[3], int idxY, int idxX);<br>
<br>
-    void copySaoUnit(SaoCtuParam* saoUnitDst, const SaoCtuParam* saoUnitSrc);<br>
+//    void copySaoUnit(SaoCtuParam* saoUnitDst, const SaoCtuParam* saoUnitSrc);<br>
<br>
     void calcSaoStatsCu(int addr, int plane);<br>
     void calcSaoStatsCu_BeforeDblk(Frame* pic, int idxX, int idxY);<br>
@@ -144,10 +144,10 @@<br>
     void saoLumaComponentParamDist(SAOParam* saoParam, int addr, double* mergeDist);<br>
     void saoChromaComponentParamDist(SAOParam* saoParam, int addr, double* mergeDist);<br>
<br>
-    inline int estIterOffset(int typeIdx, int classIdx, double lambda, int offset, int32_t count, int32_t offsetOrg,<br>
-                             int32_t* currentDistortionTableBo, double* currentRdCostTableBo);<br>
+    inline int estIterOffset(int typeIdx, double lambda, int offset, int32_t count, int32_t offsetOrg,<br>
+                             int& currentDistortionTableBo, double& currentRdCostTableBo);<br>
     void rdoSaoUnitRowEnd(const SAOParam* saoParam, int numctus);<br>
-    void rdoSaoUnitRow(SAOParam* saoParam, int idxY);<br>
+//    void rdoSaoUnitRow(SAOParam* saoParam, int idxY);<br>
     void rdoSaoUnitCu(SAOParam* saoParam, int rowBaseAddr, int idxX, int addr);<br>
<br>
     void saoStatsInitialOffset(int plane);<br></div></div>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br></div>
<br>_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
<br></blockquote></div><br></div>