Index: /branches/SHM-dev/source/App/TAppEncoder/TAppEncCfg.cpp
===================================================================
--- /branches/SHM-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 1331)
+++ /branches/SHM-dev/source/App/TAppEncoder/TAppEncCfg.cpp	(revision 1332)
@@ -1364,4 +1364,6 @@
   ("SAO",                                             m_bUseSAO,                                         true, "Enable Sample Adaptive Offset")
   ("TestSAODisableAtPictureLevel",                    m_bTestSAODisableAtPictureLevel,                  false, "Enables the testing of disabling SAO at the picture level after having analysed all blocks")
+  ("SaoEncodingRate",                                 m_saoEncodingRate,                                 0.75, "When >0 SAO early picture termination is enabled for luma and chroma")
+  ("SaoEncodingRateChroma",                           m_saoEncodingRateChroma,                            0.5, "The SAO early picture termination rate to use for chroma (when m_SaoEncodingRate is >0). If <=0, use results for luma")
   ("MaxNumOffsetsPerPic",                             m_maxNumOffsetsPerPic,                             2048, "Max number of SAO offset per picture (Default: 2048)")
   ("SAOLcuBoundary",                                  m_saoCtuBoundary,                                 false, "0: right/bottom CTU boundary areas skipped from SAO parameter estimation, 1: non-deblocked pixels are used for those areas")
Index: /branches/SHM-dev/source/App/TAppEncoder/TAppEncCfg.h
===================================================================
--- /branches/SHM-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 1331)
+++ /branches/SHM-dev/source/App/TAppEncoder/TAppEncCfg.h	(revision 1332)
@@ -249,4 +249,6 @@
   Bool      m_bUseSAO;
   Bool      m_bTestSAODisableAtPictureLevel;
+  Double    m_saoEncodingRate;                                ///< When >0 SAO early picture termination is enabled for luma and chroma
+  Double    m_saoEncodingRateChroma;                          ///< The SAO early picture termination rate to use for chroma (when m_SaoEncodingRate is >0). If <=0, use results for luma.
   Int       m_maxNumOffsetsPerPic;                            ///< SAO maximun number of offset per picture
   Bool      m_saoCtuBoundary;                                 ///< SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
Index: /branches/SHM-dev/source/App/TAppEncoder/TAppEncTop.cpp
===================================================================
--- /branches/SHM-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 1331)
+++ /branches/SHM-dev/source/App/TAppEncoder/TAppEncTop.cpp	(revision 1332)
@@ -520,4 +520,6 @@
     m_acTEncTop[layer].setUseSAO                                            ( m_bUseSAO );
     m_acTEncTop[layer].setTestSAODisableAtPictureLevel                      ( m_bTestSAODisableAtPictureLevel );
+    m_acTEncTop[layer].setSaoEncodingRate                                   ( m_saoEncodingRate );
+    m_acTEncTop[layer].setSaoEncodingRateChroma                             ( m_saoEncodingRateChroma );
     m_acTEncTop[layer].setMaxNumOffsetsPerPic                               ( m_maxNumOffsetsPerPic );
 
@@ -954,4 +956,6 @@
   m_cTEncTop.setUseSAO                                            ( m_bUseSAO );
   m_cTEncTop.setTestSAODisableAtPictureLevel                      ( m_bTestSAODisableAtPictureLevel );
+  m_cTEncTop.setSaoEncodingRate                                   ( m_saoEncodingRate );
+  m_cTEncTop.setSaoEncodingRateChroma                             ( m_saoEncodingRateChroma );
   m_cTEncTop.setMaxNumOffsetsPerPic                               ( m_maxNumOffsetsPerPic);
 
Index: /branches/SHM-dev/source/Lib/TLibEncoder/TEncCfg.h
===================================================================
--- /branches/SHM-dev/source/Lib/TLibEncoder/TEncCfg.h	(revision 1331)
+++ /branches/SHM-dev/source/Lib/TLibEncoder/TEncCfg.h	(revision 1332)
@@ -165,4 +165,6 @@
   Bool      m_bUseSAO;
   Bool      m_bTestSAODisableAtPictureLevel;
+  Double    m_saoEncodingRate;       // When non-0 SAO early picture termination is enabled for luma and chroma
+  Double    m_saoEncodingRateChroma; // The SAO early picture termination rate to use for chroma (when m_SaoEncodingRate is >0). If <=0, use results for luma.
   Int       m_maxNumOffsetsPerPic;
   Bool      m_saoCtuBoundary;
@@ -724,4 +726,9 @@
   Void  setTestSAODisableAtPictureLevel (Bool bVal)                  { m_bTestSAODisableAtPictureLevel = bVal; }
   Bool  getTestSAODisableAtPictureLevel ( ) const                    { return m_bTestSAODisableAtPictureLevel; }
+
+  Void   setSaoEncodingRate(Double v)                                { m_saoEncodingRate = v; }
+  Double getSaoEncodingRate() const                                  { return m_saoEncodingRate; }
+  Void   setSaoEncodingRateChroma(Double v)                          { m_saoEncodingRateChroma = v; }
+  Double getSaoEncodingRateChroma() const                            { return m_saoEncodingRateChroma; }
   Void  setMaxNumOffsetsPerPic                   (Int iVal)          { m_maxNumOffsetsPerPic = iVal; }
   Int   getMaxNumOffsetsPerPic                   ()                  { return m_maxNumOffsetsPerPic; }
Index: /branches/SHM-dev/source/Lib/TLibEncoder/TEncGOP.cpp
===================================================================
--- /branches/SHM-dev/source/Lib/TLibEncoder/TEncGOP.cpp	(revision 1331)
+++ /branches/SHM-dev/source/Lib/TLibEncoder/TEncGOP.cpp	(revision 1332)
@@ -2615,5 +2615,5 @@
       m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(&tempBitCounter);
       m_pcSAO->initRDOCabacCoder(m_pcEncTop->getRDGoOnSbacCoder(), pcSlice);
-      m_pcSAO->SAOProcess(pcPic, sliceEnabled, pcPic->getSlice(0)->getLambdas(), m_pcCfg->getTestSAODisableAtPictureLevel()
+      m_pcSAO->SAOProcess(pcPic, sliceEnabled, pcPic->getSlice(0)->getLambdas(), m_pcCfg->getTestSAODisableAtPictureLevel(), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma()
 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
                           , m_pcCfg->getSaoCtuBoundary()
Index: /branches/SHM-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp
===================================================================
--- /branches/SHM-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp	(revision 1331)
+++ /branches/SHM-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp	(revision 1332)
@@ -127,7 +127,5 @@
 #endif
 
-#if SAO_ENCODING_CHOICE
   ::memset(m_saoDisabledRate, 0, sizeof(m_saoDisabledRate));
-#endif
 
   for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++)
@@ -254,5 +252,5 @@
 
 
-Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel
+Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma
 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
                                          , Bool isPreDBFSamplesUsed
@@ -277,9 +275,9 @@
 #endif
   //slice on/off
-  decidePicParams(sliceEnabled, pPic->getSlice(0)->getDepth());
+  decidePicParams(sliceEnabled, pPic->getSlice(0)->getDepth(), saoEncodingRate, saoEncodingRateChroma);
 
   //block on/off
   SAOBlkParam* reconParams = new SAOBlkParam[m_numCTUsPic]; //temporary parameter buffer for storing reconstructed SAO parameters
-  decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam(), bTestSAODisableAtPictureLevel);
+  decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam(), bTestSAODisableAtPictureLevel, saoEncodingRate, saoEncodingRateChroma);
   delete[] reconParams;
 }
@@ -364,5 +362,5 @@
 }
 
-Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, Int picTempLayer)
+Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, Int picTempLayer, const Double saoEncodingRate, const Double saoEncodingRateChroma)
 {
   //decide sliceEnabled[compIdx]
@@ -378,21 +376,25 @@
     sliceEnabled[compIdx] = true;
 
-#if SAO_ENCODING_CHOICE
-#if SAO_ENCODING_CHOICE_CHROMA
-    // decide slice-level on/off based on previous results
-    if( (picTempLayer > 0)
-      && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==COMPONENT_Y) ? SAO_ENCODING_RATE : SAO_ENCODING_RATE_CHROMA)) )
-    {
-      sliceEnabled[compIdx] = false;
-    }
-#else
-    // decide slice-level on/off based on previous results
-    if( (picTempLayer > 0)
-      && (m_saoDisabledRate[COMPONENT_Y][0] > SAO_ENCODING_RATE) )
-    {
-      sliceEnabled[compIdx] = false;
-    }
-#endif
-#endif
+    if (saoEncodingRate>0.0)
+    {
+      if (saoEncodingRateChroma>0.0)
+      {
+        // decide slice-level on/off based on previous results
+        if( (picTempLayer > 0)
+          && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==COMPONENT_Y) ? saoEncodingRate : saoEncodingRateChroma)) )
+        {
+          sliceEnabled[compIdx] = false;
+        }
+      }
+      else
+      {
+        // decide slice-level on/off based on previous results
+        if( (picTempLayer > 0)
+          && (m_saoDisabledRate[COMPONENT_Y][0] > saoEncodingRate) )
+        {
+          sliceEnabled[compIdx] = false;
+        }
+      }
+    }
   }
 }
@@ -791,5 +793,7 @@
 }
 
-Void TEncSampleAdaptiveOffset::decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams, const Bool bTestSAODisableAtPictureLevel)
+Void TEncSampleAdaptiveOffset::decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv,
+                                               SAOBlkParam* reconParams, SAOBlkParam* codedParams, const Bool bTestSAODisableAtPictureLevel,
+                                               const Double saoEncodingRate, const Double saoEncodingRateChroma)
 {
   Bool allBlksDisabled = true;
@@ -895,31 +899,32 @@
   }
 
-#if SAO_ENCODING_CHOICE
-  Int picTempLayer = pic->getSlice(0)->getDepth();
-  Int numCtusForSAOOff[MAX_NUM_COMPONENT];
-
-  for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
-  {
-    numCtusForSAOOff[compIdx] = 0;
-    for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++)
-    {
-      if( reconParams[ctuRsAddr][compIdx].modeIdc == SAO_MODE_OFF)
-      {
-        numCtusForSAOOff[compIdx]++;
-      }
-    }
-  }
-#if SAO_ENCODING_CHOICE_CHROMA
-  for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
-  {
-    m_saoDisabledRate[compIdx][picTempLayer] = (Double)numCtusForSAOOff[compIdx]/(Double)m_numCTUsPic;
-  }
-#else
-  if (picTempLayer == 0)
-  {
-    m_saoDisabledRate[COMPONENT_Y][0] = (Double)(numCtusForSAOOff[COMPONENT_Y]+numCtusForSAOOff[COMPONENT_Cb]+numCtusForSAOOff[COMPONENT_Cr])/(Double)(m_numCTUsPic*3);
-  }
-#endif
-#endif
+  if (saoEncodingRate > 0.0)
+  {
+    Int picTempLayer = pic->getSlice(0)->getDepth();
+    Int numCtusForSAOOff[MAX_NUM_COMPONENT];
+
+    for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
+    {
+      numCtusForSAOOff[compIdx] = 0;
+      for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++)
+      {
+        if( reconParams[ctuRsAddr][compIdx].modeIdc == SAO_MODE_OFF)
+        {
+          numCtusForSAOOff[compIdx]++;
+        }
+      }
+    }
+    if (saoEncodingRateChroma > 0.0)
+    {
+      for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++)
+      {
+        m_saoDisabledRate[compIdx][picTempLayer] = (Double)numCtusForSAOOff[compIdx]/(Double)m_numCTUsPic;
+      }
+    }
+    else if (picTempLayer == 0)
+    {
+      m_saoDisabledRate[COMPONENT_Y][0] = (Double)(numCtusForSAOOff[COMPONENT_Y]+numCtusForSAOOff[COMPONENT_Cb]+numCtusForSAOOff[COMPONENT_Cr])/(Double)(m_numCTUsPic*3);
+    }
+  }
 }
 
Index: /branches/SHM-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h
===================================================================
--- /branches/SHM-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h	(revision 1331)
+++ /branches/SHM-dev/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h	(revision 1332)
@@ -109,5 +109,5 @@
   Void destroyEncData();
   Void initRDOCabacCoder(TEncSbac* pcRDGoOnSbacCoder, TComSlice* pcSlice) ;
-  Void SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel
+  Void SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma
 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
                 , Bool isPreDBFSamplesUsed
@@ -124,6 +124,6 @@
 #endif
                    );
-  Void decidePicParams(Bool* sliceEnabled, Int picTempLayer);
-  Void decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams, const Bool bTestSAODisableAtPictureLevel);
+  Void decidePicParams(Bool* sliceEnabled, Int picTempLayer, const Double saoEncodingRate, const Double saoEncodingRateChroma);
+  Void decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma);
   Void getBlkStats(const ComponentID compIdx, const Int channelBitDepth, SAOStatData* statsDataTypes, Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height, Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail
 #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK
@@ -156,7 +156,5 @@
   SAOStatData***         m_preDBFstatData;
 #endif
-#if SAO_ENCODING_CHOICE
   Double                 m_saoDisabledRate[MAX_NUM_COMPONENT][MAX_TLAYER];
-#endif
   Int                    m_skipLinesR[MAX_NUM_COMPONENT][NUM_SAO_NEW_TYPES];
   Int                    m_skipLinesB[MAX_NUM_COMPONENT][NUM_SAO_NEW_TYPES];
