<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Apr 7, 2017 at 4:04 PM,  <span dir="ltr"><<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Ashok Kumar Mishra <<a href="mailto:ashok@multicorewareinc.com">ashok@multicorewareinc.com</a>><br>
# Date 1491215527 -19800<br>
#      Mon Apr 03 16:02:07 2017 +0530<br>
# Node ID 195ae8f499fc61bcdc6865cf7cffe7<wbr>d0d7c486f0<br>
# Parent  08a05ca9fd16c9f5efb1ce4d8389bd<wbr>a8a63f5f7d<br>
Improved sao implementation by limiting sao types<br></blockquote><div><br></div><div>Looks good. The X265_BUILD number has to be incremented as x265_param has been modified, but I can absorb this in my push.</div><div>Do you have any performance numbers to share to show the impact of limit-sao?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst  Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/doc/reST/cli.rst  Mon Apr 03 16:02:07 2017 +0530<br>
@@ -1690,6 +1690,12 @@<br>
        disabled, SAO analysis skips the right/bottom boundary areas.<br>
        Default disabled<br>
<br>
+.. option:: --limit-sao, --no-limit-sao<br>
+    Limit SAO filter computation by early terminating SAO process based<br>
+    on inter prediction mode, CTU spatial-domain correlations, and relations<br>
+    between luma and chroma.<br>
+    Default disabled<br>
+<br>
 VUI (Video Usability Information) options<br>
 ==============================<wbr>===========<br>
<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/common/param.cpp<br>
--- a/source/common/param.cpp   Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/common/param.cpp   Mon Apr 03 16:02:07 2017 +0530<br>
@@ -187,6 +187,7 @@<br>
     /* SAO Loop Filter */<br>
     param->bEnableSAO = 1;<br>
     param->bSaoNonDeblocked = 0;<br>
+    param->bLimitSAO = 0;<br>
<br>
     /* Coding Quality */<br>
     param->cbQpOffset = 0;<br>
@@ -272,7 +273,6 @@<br>
     param->bAQMotion = 0;<br>
     param->bHDROpt = 0;<br>
     param->analysisRefineLevel = 5;<br>
-<br>
 }<br>
<br>
 int x265_param_default_preset(<wbr>x265_param* param, const char* preset, const char* tune)<br>
@@ -949,6 +949,7 @@<br>
         }<br>
         OPT("hdr") p->bEmitHDRSEI = atobool(value);<br>
         OPT("hdr-opt") p->bHDROpt = atobool(value);<br>
+        OPT("limit-sao") p->bLimitSAO = atobool(value);<br>
         else<br>
             return X265_PARAM_BAD_NAME;<br>
     }<br>
@@ -1658,6 +1659,7 @@<br>
     BOOL(p->bEmitHDRSEI, "hdr");<br>
     BOOL(p->bHDROpt, "hdr-opt");<br>
     s += sprintf(s, " refine-level=%d", p->analysisRefineLevel);<br>
+    BOOL(p->bLimitSAO, "limit-sao");<br>
 #undef BOOL<br>
     return buf;<br>
 }<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp        Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/encoder/encoder.cpp        Mon Apr 03 16:02:07 2017 +0530<br>
@@ -2109,6 +2109,7 @@<br>
     /* some options make no sense if others are disabled */<br>
     p->bSaoNonDeblocked &= p->bEnableSAO;<br>
     p->bEnableTSkipFast &= p->bEnableTransformSkip;<br>
+    p->bLimitSAO &= p->bEnableSAO;<br>
<br>
     /* initialize the conformance window */<br>
     m_conformanceWindow.bEnabled = false;<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/encoder/sao.cpp<br>
--- a/source/encoder/sao.cpp    Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/encoder/sao.cpp    Mon Apr 03 16:02:07 2017 +0530<br>
@@ -734,6 +734,7 @@<br>
 /* Calculate SAO statistics for current CTU without non-crossing slice */<br>
 void SAO::calcSaoStatsCTU(int addr, int plane)<br>
 {<br>
+    Slice* slice = m_frame->m_encData->m_slice;<br>
     const PicYuv* reconPic = m_frame->m_reconPic;<br>
     const CUData* cu = m_frame->m_encData->getPicCTU(<wbr>addr);<br>
     const pixel* fenc0 = m_frame->m_fencPic-><wbr>getPlaneAddr(plane, addr);<br>
@@ -858,59 +859,63 @@<br>
             primitives.saoCuStatsE1(diff + startY * MAX_CU_SIZE, rec0 + startY * stride, stride, upBuff1, endX, endY - startY, m_offsetOrg[plane][SAO_EO_1], m_count[plane][SAO_EO_1]);<br>
         }<br>
<br>
-        // SAO_EO_2: // dir: 135<br>
+        if (!m_param->bLimitSAO || ((slice->m_sliceType == P_SLICE && !cu->isSkipped(0)) ||<br>
+            (slice->m_sliceType != B_SLICE)))<br>
         {<br>
-            if (m_param->bSaoNonDeblocked)<br>
+            // SAO_EO_2: // dir: 135<br>
             {<br>
-                skipB = 4;<br>
-                skipR = 5;<br>
+                if (m_param->bSaoNonDeblocked)<br>
+                {<br>
+                    skipB = 4;<br>
+                    skipR = 5;<br>
+                }<br>
+<br>
+                fenc = fenc0;<br>
+                rec  = rec0;<br>
+<br>
+                startX = !lpelx;<br>
+                endX   = (rpelx == picWidth) ? ctuWidth - 1 : ctuWidth - skipR + plane_offset;<br>
+<br>
+                startY = bAboveUnavail;<br>
+                endY   = (bpely == picHeight) ? ctuHeight - 1 : ctuHeight - skipB + plane_offset;<br>
+                if (startY)<br>
+                {<br>
+                    fenc += stride;<br>
+                    rec += stride;<br>
+                }<br>
+<br>
+                primitives.sign(upBuff1, &rec[startX], &rec[startX - stride - 1], (endX - startX));<br>
+<br>
+                primitives.saoCuStatsE2(diff + startX + startY * MAX_CU_SIZE, rec0  + startX + startY * stride, stride, upBuff1, upBufft, endX - startX, endY - startY, m_offsetOrg[plane][SAO_EO_2], m_count[plane][SAO_EO_2]);<br>
             }<br>
<br>
-            fenc = fenc0;<br>
-            rec  = rec0;<br>
+            // SAO_EO_3: // dir: 45<br>
+            {<br>
+                if (m_param->bSaoNonDeblocked)<br>
+                {<br>
+                    skipB = 4;<br>
+                    skipR = 5;<br>
+                }<br>
<br>
-            startX = !lpelx;<br>
-            endX   = (rpelx == picWidth) ? ctuWidth - 1 : ctuWidth - skipR + plane_offset;<br>
+                fenc = fenc0;<br>
+                rec  = rec0;<br>
<br>
-            startY = bAboveUnavail;<br>
-            endY   = (bpely == picHeight) ? ctuHeight - 1 : ctuHeight - skipB + plane_offset;<br>
-            if (startY)<br>
-            {<br>
-                fenc += stride;<br>
-                rec += stride;<br>
+                startX = !lpelx;<br>
+                endX   = (rpelx == picWidth) ? ctuWidth - 1 : ctuWidth - skipR + plane_offset;<br>
+<br>
+                startY = bAboveUnavail;<br>
+                endY   = (bpely == picHeight) ? ctuHeight - 1 : ctuHeight - skipB + plane_offset;<br>
+<br>
+                if (startY)<br>
+                {<br>
+                    fenc += stride;<br>
+                    rec += stride;<br>
+                }<br>
+<br>
+                primitives.sign(upBuff1, &rec[startX - 1], &rec[startX - 1 - stride + 1], (endX - startX + 1));<br>
+<br>
+                primitives.saoCuStatsE3(diff + startX + startY * MAX_CU_SIZE, rec0  + startX + startY * stride, stride, upBuff1 + 1, endX - startX, endY - startY, m_offsetOrg[plane][SAO_EO_3], m_count[plane][SAO_EO_3]);<br>
             }<br>
-<br>
-            primitives.sign(upBuff1, &rec[startX], &rec[startX - stride - 1], (endX - startX));<br>
-<br>
-            primitives.saoCuStatsE2(diff + startX + startY * MAX_CU_SIZE, rec0  + startX + startY * stride, stride, upBuff1, upBufft, endX - startX, endY - startY, m_offsetOrg[plane][SAO_EO_2], m_count[plane][SAO_EO_2]);<br>
-        }<br>
-<br>
-        // SAO_EO_3: // dir: 45<br>
-        {<br>
-            if (m_param->bSaoNonDeblocked)<br>
-            {<br>
-                skipB = 4;<br>
-                skipR = 5;<br>
-            }<br>
-<br>
-            fenc = fenc0;<br>
-            rec  = rec0;<br>
-<br>
-            startX = !lpelx;<br>
-            endX   = (rpelx == picWidth) ? ctuWidth - 1 : ctuWidth - skipR + plane_offset;<br>
-<br>
-            startY = bAboveUnavail;<br>
-            endY   = (bpely == picHeight) ? ctuHeight - 1 : ctuHeight - skipB + plane_offset;<br>
-<br>
-            if (startY)<br>
-            {<br>
-                fenc += stride;<br>
-                rec += stride;<br>
-            }<br>
-<br>
-            primitives.sign(upBuff1, &rec[startX - 1], &rec[startX - 1 - stride + 1], (endX - startX + 1));<br>
-<br>
-            primitives.saoCuStatsE3(diff + startX + startY * MAX_CU_SIZE, rec0  + startX + startY * stride, stride, upBuff1 + 1, endX - startX, endY - startY, m_offsetOrg[plane][SAO_EO_3], m_count[plane][SAO_EO_3]);<br>
         }<br>
     }<br>
 }<br>
@@ -1224,7 +1229,6 @@<br>
 void SAO::rdoSaoUnitCu(SAOParam* saoParam, int rowBaseAddr, int idxX, int addr)<br>
 {<br>
     Slice* slice = m_frame->m_encData->m_slice;<br>
-//    int qp = slice->m_sliceQp;<br>
     const CUData* cu = m_frame->m_encData->getPicCTU(<wbr>addr);<br>
     int qp = cu->m_qp[0];<br>
<br>
@@ -1263,17 +1267,6 @@<br>
     for (int i = 0; i < planes; i++)<br>
         saoParam->ctuParam[i][addr].<wbr>reset();<br>
<br>
-    if (saoParam->bSaoFlag[0])<br>
-        calcSaoStatsCTU(addr, 0);<br>
-<br>
-    if (saoParam->bSaoFlag[1])<br>
-    {<br>
-        calcSaoStatsCTU(addr, 1);<br>
-        calcSaoStatsCTU(addr, 2);<br>
-    }<br>
-<br>
-    saoStatsInitialOffset(planes);<br>
-<br>
     // SAO distortion calculation<br>
     m_entropyCoder.load(m_<wbr>rdContexts.cur);<br>
     m_entropyCoder.resetBits();<br>
@@ -1283,13 +1276,44 @@<br>
         m_entropyCoder.codeSaoMerge(0)<wbr>;<br>
     m_entropyCoder.store(m_<wbr>rdContexts.temp);<br>
<br>
-    // Estimate distortion and cost of new SAO params<br>
+    memset(m_offset, 0, sizeof(m_offset));<br>
     int64_t bestCost = 0;<br>
     int64_t rateDist = 0;<br>
+<br>
+    bool bAboveLeftAvail = true;<br>
+    for (int mergeIdx = 0; mergeIdx < 2; ++mergeIdx)<br>
+    {<br>
+        if (!allowMerge[mergeIdx])<br>
+            continue;<br>
+<br>
+        SaoCtuParam* mergeSrcParam = &(saoParam->ctuParam[0][<wbr>addrMerge[mergeIdx]]);<br>
+        bAboveLeftAvail = bAboveLeftAvail && (mergeSrcParam->typeIdx == -1);<br>
+    }<br>
+    // Don't apply sao if ctu is skipped or ajacent ctus are sao off<br>
+    bool bSaoOff = (slice->m_sliceType == B_SLICE) && (cu->isSkipped(0) || bAboveLeftAvail);<br>
+<br>
     // Estimate distortion and cost of new SAO params<br>
-    saoLumaComponentParamDist(<wbr>saoParam, addr, rateDist, lambda, bestCost);<br>
-    if (chroma)<br>
-        saoChromaComponentParamDist(<wbr>saoParam, addr, rateDist, lambda, bestCost);<br>
+    if (saoParam->bSaoFlag[0])<br>
+    {<br>
+        if (!m_param->bLimitSAO || !bSaoOff)<br>
+        {<br>
+            calcSaoStatsCTU(addr, 0);<br>
+            saoStatsInitialOffset(addr, 0);<br>
+            saoLumaComponentParamDist(<wbr>saoParam, addr, rateDist, lambda, bestCost);<br>
+        }<br>
+    }<br>
+<br>
+    SaoCtuParam* lclCtuParam = &saoParam->ctuParam[0][addr];<br>
+    if (saoParam->bSaoFlag[1])<br>
+    {<br>
+        if (!m_param->bLimitSAO || ((lclCtuParam->typeIdx != -1) && !bSaoOff))<br>
+        {<br>
+            calcSaoStatsCTU(addr, 1);<br>
+            calcSaoStatsCTU(addr, 2);<br>
+            saoStatsInitialOffset(addr, 1);<br>
+            saoChromaComponentParamDist(<wbr>saoParam, addr, rateDist, lambda, bestCost);<br>
+        }<br>
+    }<br>
<br>
     if (saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1])<br>
     {<br>
@@ -1360,14 +1384,26 @@<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 planes)<br>
+void SAO::saoStatsInitialOffset(int addr, int planes)<br>
 {<br>
-    memset(m_offset, 0, sizeof(m_offset));<br>
+    Slice* slice = m_frame->m_encData->m_slice;<br>
+    const CUData* cu = m_frame->m_encData->getPicCTU(<wbr>addr);<br>
+<br>
+    int maxSaoType;<br>
+    if (m_param->bLimitSAO && ((slice->m_sliceType == P_SLICE && cu->isSkipped(0)) ||<br>
+       (slice->m_sliceType == B_SLICE)))<br>
+    {<br>
+        maxSaoType = MAX_NUM_SAO_TYPE - 3;<br>
+    }<br>
+    else<br>
+    {<br>
+        maxSaoType = MAX_NUM_SAO_TYPE - 1;<br>
+    }<br>
<br>
     // EO<br>
-    for (int plane = 0; plane < planes; plane++)<br>
+    for (int plane = planes; plane <= planes * 2; plane++)<br>
     {<br>
-        for (int typeIdx = 0; typeIdx < MAX_NUM_SAO_TYPE - 1; typeIdx++)<br>
+        for (int typeIdx = 0; typeIdx < maxSaoType; typeIdx++)<br>
         {<br>
             for (int classIdx = 1; classIdx < SAO_NUM_OFFSET + 1; classIdx++)<br>
             {<br>
@@ -1390,7 +1426,7 @@<br>
     }<br>
<br>
     // BO<br>
-    for (int plane = 0; plane < planes; plane++)<br>
+    for (int plane = planes; plane <= planes * 2; plane++)<br>
     {<br>
         for (int classIdx = 0; classIdx < MAX_NUM_SAO_CLASS; classIdx++)<br>
         {<br>
@@ -1454,6 +1490,8 @@<br>
<br>
 void SAO::<wbr>saoLumaComponentParamDist(<wbr>SAOParam* saoParam, int32_t addr, int64_t& rateDist, int64_t* lambda, int64_t &bestCost)<br>
 {<br>
+    Slice* slice = m_frame->m_encData->m_slice;<br>
+    const CUData* cu = m_frame->m_encData->getPicCTU(<wbr>addr);<br>
     int64_t bestDist = 0;<br>
     int bestTypeIdx = -1;<br>
<br>
@@ -1469,13 +1507,24 @@<br>
<br>
     int64_t costPartBest = calcSaoRdoCost(0, m_entropyCoder.<wbr>getNumberOfWrittenBits(), lambda[0]);<br>
<br>
+    int maxSaoType;<br>
+    if (m_param->bLimitSAO && ((slice->m_sliceType == P_SLICE && cu->isSkipped(0)) ||<br>
+        (slice->m_sliceType == B_SLICE)))<br>
+    {<br>
+        maxSaoType = MAX_NUM_SAO_TYPE - 3;<br>
+    }<br>
+    else<br>
+    {<br>
+        maxSaoType = MAX_NUM_SAO_TYPE - 1;<br>
+    }<br>
+<br>
     //EO distortion calculation<br>
-    for (int typeIdx = 0; typeIdx < MAX_NUM_SAO_TYPE - 1; typeIdx++)<br>
+    for (int typeIdx = 0; typeIdx < maxSaoType; typeIdx++)<br>
     {<br>
         int64_t estDist = 0;<br>
         for (int classIdx = 1; classIdx < SAO_NUM_OFFSET + 1; classIdx++)<br>
         {<br>
-            int32_t&  count     = m_count[0][typeIdx][classIdx];<br>
+            int32_t&  count    = m_count[0][typeIdx][classIdx];<br>
             int32_t& offsetOrg = m_offsetOrg[0][typeIdx][<wbr>classIdx];<br>
             int32_t& offsetOut = m_offset[0][typeIdx][classIdx]<wbr>;<br>
<br>
@@ -1571,6 +1620,8 @@<br>
<br>
 void SAO::<wbr>saoChromaComponentParamDist(<wbr>SAOParam* saoParam, int32_t addr, int64_t& rateDist, int64_t* lambda, int64_t &bestCost)<br>
 {<br>
+    Slice* slice = m_frame->m_encData->m_slice;<br>
+    const CUData* cu = m_frame->m_encData->getPicCTU(<wbr>addr);<br>
     int64_t bestDist = 0;<br>
     int bestTypeIdx = -1;<br>
<br>
@@ -1587,8 +1638,19 @@<br>
     uint32_t bits = m_entropyCoder.<wbr>getNumberOfWrittenBits();<br>
     int64_t costPartBest = calcSaoRdoCost(0, bits, lambda[1]);<br>
<br>
+    int maxSaoType;<br>
+    if (m_param->bLimitSAO && ((slice->m_sliceType == P_SLICE && cu->isSkipped(0)) ||<br>
+        (slice->m_sliceType == B_SLICE)))<br>
+    {<br>
+        maxSaoType = MAX_NUM_SAO_TYPE - 3;<br>
+    }<br>
+    else<br>
+    {<br>
+        maxSaoType = MAX_NUM_SAO_TYPE - 1;<br>
+    }<br>
+<br>
     //EO RDO<br>
-    for (int typeIdx = 0; typeIdx < MAX_NUM_SAO_TYPE - 1; typeIdx++)<br>
+    for (int typeIdx = 0; typeIdx < maxSaoType; typeIdx++)<br>
     {<br>
         int64_t estDist[2] = {0, 0};<br>
         for (int compIdx = 1; compIdx < 3; compIdx++)<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/encoder/sao.h<br>
--- a/source/encoder/sao.h      Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/encoder/sao.h      Mon Apr 03 16:02:07 2017 +0530<br>
@@ -134,7 +134,7 @@<br>
     void rdoSaoUnitCu(SAOParam* saoParam, int rowBaseAddr, int idxX, int addr);<br>
     int64_t calcSaoRdoCost(int64_t distortion, uint32_t bits, int64_t lambda);<br>
<br>
-    void saoStatsInitialOffset(int planes);<br>
+    void saoStatsInitialOffset(int addr, int planes);<br>
<br>
     friend class FrameFilter;<br>
 };<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/test/regression-tests.<wbr>txt<br>
--- a/source/test/regression-<wbr>tests.txt  Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/test/regression-<wbr>tests.txt  Mon Apr 03 16:02:07 2017 +0530<br>
@@ -45,6 +45,7 @@<br>
 CrowdRun_1920x1080_50_10bit_<wbr>444.yuv,--preset veryslow --tskip --tskip-fast --no-scenecut --limit-tu 1<br>
 CrowdRun_1920x1080_50_10bit_<wbr>444.yuv,--preset veryslow --aq-mode 3 --aq-strength 1.5 --aq-motion --bitrate 5000<br>
 CrowdRun_1920x1080_50_10bit_<wbr>444.yuv,--preset veryslow --aq-mode 3 --aq-strength 1.5 --no-psy-rd --ssim-rd<br>
+CrowdRun_1920x1080_50_10bit_<wbr>422.yuv,--preset superfast --weightp --sao --limit-sao<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset superfast --weightp --qg-size 16<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset medium --tune psnr --bframes 16 --limit-modes<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset slow --temporal-layers --no-psy-rd --qg-size 32 --limit-refs 0 --cu-lossless<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/test/smoke-tests.txt<br>
--- a/source/test/smoke-tests.txt       Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/test/smoke-tests.txt       Mon Apr 03 16:02:07 2017 +0530<br>
@@ -19,6 +19,7 @@<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset=<wbr>veryfast --min-cu 16<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset=fast --weightb --interlace bff<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset=<wbr>veryslow --limit-ref 1 --limit-mode --tskip --limit-tu 1<br>
+CrowdRun_1920x1080_50_10bit_<wbr>444.yuv,--preset=superfast --bitrate 7000 --sao --limit-sao<br>
<br>
 # Main12 intraCost overflow bug test<br>
 720p50_parkrun_ter.y4m,--<wbr>preset medium<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/x265.h<br>
--- a/source/x265.h     Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/x265.h     Mon Apr 03 16:02:07 2017 +0530<br>
@@ -963,7 +963,7 @@<br>
     int       bEnableWeightedBiPred;<br>
<br>
     /* Enable source pixels in motion estimation. Default is disabled */<br>
-    int      bSourceReferenceEstimation;<br>
+    int       bSourceReferenceEstimation;<br>
<br>
     /*== Loop Filters ==*/<br>
<br>
@@ -1347,7 +1347,7 @@<br>
<br>
     /* This value represents the percentage difference between the inter cost and<br>
     * intra cost of a frame used in scenecut detection. Default 5. */<br>
-    double     scenecutBias;<br>
+    double    scenecutBias;<br>
<br>
     /* Use multiple worker threads dedicated to doing only lookahead instead of sharing<br>
     * the worker threads with Frame Encoders. A dedicated lookahead threadpool is created with the<br>
@@ -1357,16 +1357,16 @@<br>
     int       lookaheadThreads;<br>
<br>
     /* Optimize CU level QPs to signal consistent deltaQPs in frame for rd level > 4 */<br>
-    int        bOptCUDeltaQP;<br>
+    int       bOptCUDeltaQP;<br>
<br>
     /* Refine analysis in multipass ratecontrol based on analysis information stored */<br>
-    int         analysisMultiPassRefine;<br>
+    int       analysisMultiPassRefine;<br>
<br>
     /* Refine analysis in multipass ratecontrol based on distortion data stored */<br>
-    int         analysisMultiPassDistortion;<br>
+    int       analysisMultiPassDistortion;<br>
<br>
     /* Adaptive Quantization based on relative motion */<br>
-    int        bAQMotion;<br>
+    int       bAQMotion;<br>
<br>
     /* SSIM based RDO, based on residual divisive normalization scheme. Used for mode<br>
     * selection during analysis of CTUs, can achieve significant gain in terms of<br>
@@ -1390,6 +1390,11 @@<br>
     * level higher the informtion stored/reused. Default is 5 */<br>
     int       analysisRefineLevel;<br>
<br>
+     /* Limit Sample Adaptive Offset filter computation by early terminating SAO<br>
+     * process based on inter prediction mode, CTU spatial-domain correlations,<br>
+     * and relations between luma and chroma */<br>
+    int       bLimitSAO;<br>
+<br>
 } x265_param;<br>
<br>
 /* x265_param_alloc:<br>
diff -r 08a05ca9fd16 -r 195ae8f499fc source/x265cli.h<br>
--- a/source/x265cli.h  Mon Mar 27 12:35:20 2017 +0530<br>
+++ b/source/x265cli.h  Mon Apr 03 16:02:07 2017 +0530<br>
@@ -266,6 +266,8 @@<br>
     { "no-hdr",               no_argument, NULL, 0 },<br>
     { "hdr-opt",              no_argument, NULL, 0 },<br>
     { "no-hdr-opt",           no_argument, NULL, 0 },<br>
+    { "limit-sao",            no_argument, NULL, 0 },<br>
+    { "no-limit-sao",         no_argument, NULL, 0 },<br>
     { 0, 0, 0, 0 },<br>
     { 0, 0, 0, 0 },<br>
     { 0, 0, 0, 0 },<br>
@@ -454,6 +456,7 @@<br>
     H0("   --[no-]deblock                Enable Deblocking Loop Filter, optionally specify tC:Beta offsets Default %s\n", OPT(param->bEnableLoopFilter))<wbr>;<br>
     H0("   --[no-]sao                    Enable Sample Adaptive Offset. Default %s\n", OPT(param->bEnableSAO));<br>
     H1("   --[no-]sao-non-deblock        Use non-deblocked pixels, else right/bottom boundary areas skipped. Default %s\n", OPT(param->bSaoNonDeblocked));<br>
+    H0("   --[no-]limit-sao              Limit Sample Adaptive Offset types. Default %s\n", OPT(param->bLimitSAO));<br>
     H0("\nVUI options:\n");<br>
     H0("   --sar <width:height|int>      Sample Aspect Ratio, the ratio of width to height of an individual pixel.\n");<br>
     H0("                                 Choose from 0=undef, 1=1:1(\"square\"), 2=12:11, 3=10:11, 4=16:11,\n");<br>
______________________________<wbr>_________________<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/<wbr>listinfo/x265-devel</a><br>
</blockquote></div><br></div></div>