Index: trunk/source/Lib/TLibDecoder/TDecCu.cpp
===================================================================
--- trunk/source/Lib/TLibDecoder/TDecCu.cpp	(revision 1196)
+++ trunk/source/Lib/TLibDecoder/TDecCu.cpp	(revision 1313)
@@ -2,7 +2,7 @@
  * License, included below. This software may be subject to other third party
  * and contributor rights, including patent rights, and no such rights are
- * granted under this license.  
+ * granted under this license.
  *
-* Copyright (c) 2010-2015, ITU/ISO/IEC
+ * Copyright (c) 2010-2015, ITU/ISO/IEC
  * All rights reserved.
  *
@@ -37,4 +37,6 @@
 
 #include "TDecCu.h"
+#include "TLibCommon/TComTU.h"
+#include "TLibCommon/TComPrediction.h"
 
 //! \ingroup TLibDecoder
@@ -50,5 +52,5 @@
   m_ppcYuvReco = NULL;
   m_ppcCU      = NULL;
-#if H_3D_DBBP
+#if NH_3D_DBBP
   m_ppcYuvRecoDBBP = NULL;
 #endif
@@ -67,35 +69,44 @@
 
 /**
- \param    uiMaxDepth    total number of allowable depth
- \param    uiMaxWidth    largest CU width
- \param    uiMaxHeight   largest CU height
+ \param    uiMaxDepth      total number of allowable depth
+ \param    uiMaxWidth      largest CU width
+ \param    uiMaxHeight     largest CU height
+ \param    chromaFormatIDC chroma format
  */
-Void TDecCu::create( UInt uiMaxDepth, UInt uiMaxWidth, UInt uiMaxHeight )
+Void TDecCu::create( UInt uiMaxDepth, UInt uiMaxWidth, UInt uiMaxHeight, ChromaFormat chromaFormatIDC )
 {
   m_uiMaxDepth = uiMaxDepth+1;
-  
+
   m_ppcYuvResi = new TComYuv*[m_uiMaxDepth-1];
   m_ppcYuvReco = new TComYuv*[m_uiMaxDepth-1];
   m_ppcCU      = new TComDataCU*[m_uiMaxDepth-1];
-#if H_3D_DBBP
+#if NH_3D_DBBP
   m_ppcYuvRecoDBBP = new TComYuv*[m_uiMaxDepth-1];
 #endif
-  
-  UInt uiNumPartitions;
+
   for ( UInt ui = 0; ui < m_uiMaxDepth-1; ui++ )
   {
-    uiNumPartitions = 1<<( ( m_uiMaxDepth - ui - 1 )<<1 );
+    UInt uiNumPartitions = 1<<( ( m_uiMaxDepth - ui - 1 )<<1 );
     UInt uiWidth  = uiMaxWidth  >> ui;
     UInt uiHeight = uiMaxHeight >> ui;
-    
-    m_ppcYuvResi[ui] = new TComYuv;    m_ppcYuvResi[ui]->create( uiWidth, uiHeight );
-    m_ppcYuvReco[ui] = new TComYuv;    m_ppcYuvReco[ui]->create( uiWidth, uiHeight );
-    m_ppcCU     [ui] = new TComDataCU; m_ppcCU     [ui]->create( uiNumPartitions, uiWidth, uiHeight, true, uiMaxWidth >> (m_uiMaxDepth - 1) );
-#if H_3D_DBBP
-    m_ppcYuvRecoDBBP[ui] = new TComYuv;    m_ppcYuvRecoDBBP[ui]->create( uiWidth, uiHeight );
-#endif
-  }
-  
+
+    // The following arrays (m_ppcYuvResi, m_ppcYuvReco and m_ppcCU) are only required for CU depths
+    // although data is allocated for all possible depths of the CU/TU tree except the last.
+    // Since the TU tree will always include at least one additional depth greater than the CU tree,
+    // there will be enough entries for these arrays.
+    // (Section 7.4.3.2: "The CVS shall not contain data that result in (Log2MinTrafoSize) MinTbLog2SizeY
+    //                    greater than or equal to MinCbLog2SizeY")
+    // TODO: tidy the array allocation given the above comment.
+
+    m_ppcYuvResi[ui] = new TComYuv;    m_ppcYuvResi[ui]->create( uiWidth, uiHeight, chromaFormatIDC );
+    m_ppcYuvReco[ui] = new TComYuv;    m_ppcYuvReco[ui]->create( uiWidth, uiHeight, chromaFormatIDC );
+    m_ppcCU     [ui] = new TComDataCU; m_ppcCU     [ui]->create( chromaFormatIDC, uiNumPartitions, uiWidth, uiHeight, true, uiMaxWidth >> (m_uiMaxDepth - 1) );
+#if NH_3D_DBBP
+    m_ppcYuvRecoDBBP[ui] = new TComYuv;    m_ppcYuvRecoDBBP[ui]->create( uiWidth, uiHeight, chromaFormatIDC );
+#endif
+}
+
   m_bDecodeDQP = false;
+  m_IsChromaQpAdjCoded = false;
 
   // initialize partition order.
@@ -103,5 +114,5 @@
   initZscanToRaster(m_uiMaxDepth, 1, 0, piTmp);
   initRasterToZscan( uiMaxWidth, uiMaxHeight, m_uiMaxDepth );
-  
+
   // initialize conversion matrix from partition index to pel
   initRasterToPelXY( uiMaxWidth, uiMaxHeight, m_uiMaxDepth );
@@ -115,13 +126,13 @@
     m_ppcYuvReco[ui]->destroy(); delete m_ppcYuvReco[ui]; m_ppcYuvReco[ui] = NULL;
     m_ppcCU     [ui]->destroy(); delete m_ppcCU     [ui]; m_ppcCU     [ui] = NULL;
-#if H_3D_DBBP
+#if NH_3D_DBBP
     m_ppcYuvRecoDBBP[ui]->destroy(); delete m_ppcYuvRecoDBBP[ui]; m_ppcYuvRecoDBBP[ui] = NULL;
 #endif
   }
-  
+
   delete [] m_ppcYuvResi; m_ppcYuvResi = NULL;
   delete [] m_ppcYuvReco; m_ppcYuvReco = NULL;
   delete [] m_ppcCU     ; m_ppcCU      = NULL;
-#if H_3D_DBBP
+#if NH_3D_DBBP
   delete [] m_ppcYuvRecoDBBP; m_ppcYuvRecoDBBP = NULL;
 #endif
@@ -132,24 +143,33 @@
 // ====================================================================================================================
 
-/** \param    pcCU        pointer of CU data
- \param    ruiIsLast   last data?
+/** 
+ Parse a CTU.
+ \param    pCtu                      [in/out] pointer to CTU data structure
+ \param    isLastCtuOfSliceSegment   [out]    true, if last CTU of the slice segment
  */
-Void TDecCu::decodeCU( TComDataCU* pcCU, UInt& ruiIsLast )
-{
-  if ( pcCU->getSlice()->getPPS()->getUseDQP() )
+Void TDecCu::decodeCtu( TComDataCU* pCtu, Bool& isLastCtuOfSliceSegment )
+{
+  if ( pCtu->getSlice()->getPPS()->getUseDQP() )
   {
     setdQPFlag(true);
   }
 
+  if ( pCtu->getSlice()->getUseChromaQpAdj() )
+  {
+    setIsChromaQpAdjCoded(true);
+  }
+  
   // start from the top level CU
-  xDecodeCU( pcCU, 0, 0, ruiIsLast);
-}
-
-/** \param    pcCU        pointer of CU data
+  xDecodeCU( pCtu, 0, 0, isLastCtuOfSliceSegment);
+}
+
+/** 
+ Decoding process for a CTU.
+ \param    pCtu                      [in/out] pointer to CTU data structure
  */
-Void TDecCu::decompressCU( TComDataCU* pcCU )
-{
-#if !H_3D_IV_MERGE
-  xDecompressCU( pcCU, 0,  0 );
+Void TDecCu::decompressCtu( TComDataCU* pCtu )
+{
+#if !NH_3D_IV_MERGE
+  xDecompressCU( pCtu, 0,  0 );
 #endif
 }
@@ -159,77 +179,47 @@
 // ====================================================================================================================
 
-/**decode end-of-slice flag
- * \param pcCU
- * \param uiAbsPartIdx 
- * \param uiDepth 
- * \returns Bool
- */
-Bool TDecCu::xDecodeSliceEnd( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth)
-{
-  UInt uiIsLast;
-  TComPic* pcPic = pcCU->getPic();
-  TComSlice * pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx());
-  UInt uiCurNumParts    = pcPic->getNumPartInCU() >> (uiDepth<<1);
-  UInt uiWidth = pcSlice->getSPS()->getPicWidthInLumaSamples();
-  UInt uiHeight = pcSlice->getSPS()->getPicHeightInLumaSamples();
-  UInt uiGranularityWidth = g_uiMaxCUWidth;
-  UInt uiPosX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
-  UInt uiPosY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
-
-  if(((uiPosX+pcCU->getWidth(uiAbsPartIdx))%uiGranularityWidth==0||(uiPosX+pcCU->getWidth(uiAbsPartIdx)==uiWidth))
-    &&((uiPosY+pcCU->getHeight(uiAbsPartIdx))%uiGranularityWidth==0||(uiPosY+pcCU->getHeight(uiAbsPartIdx)==uiHeight)))
-  {
-    m_pcEntropyDecoder->decodeTerminatingBit( uiIsLast );
+//! decode end-of-slice flag
+Bool TDecCu::xDecodeSliceEnd( TComDataCU* pcCU, UInt uiAbsPartIdx )
+{
+  UInt uiIsLastCtuOfSliceSegment;
+
+  if (pcCU->isLastSubCUOfCtu(uiAbsPartIdx))
+  {
+    m_pcEntropyDecoder->decodeTerminatingBit( uiIsLastCtuOfSliceSegment );
   }
   else
   {
-    uiIsLast=0;
-  }
-  
-  if(uiIsLast) 
-  {
-    if(pcSlice->isNextSliceSegment()&&!pcSlice->isNextSlice()) 
-    {
-      pcSlice->setSliceSegmentCurEndCUAddr(pcCU->getSCUAddr()+uiAbsPartIdx+uiCurNumParts);
-    }
-    else 
-    {
-      pcSlice->setSliceCurEndCUAddr(pcCU->getSCUAddr()+uiAbsPartIdx+uiCurNumParts);
-      pcSlice->setSliceSegmentCurEndCUAddr(pcCU->getSCUAddr()+uiAbsPartIdx+uiCurNumParts);
-    }
-  }
-
-  return uiIsLast>0;
-}
-
-/** decode CU block recursively
- * \param pcCU
- * \param uiAbsPartIdx 
- * \param uiDepth 
- * \returns Void
- */
-
-Void TDecCu::xDecodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt& ruiIsLast)
-{
-  TComPic* pcPic = pcCU->getPic();
-  UInt uiCurNumParts    = pcPic->getNumPartInCU() >> (uiDepth<<1);
+    uiIsLastCtuOfSliceSegment=0;
+  }
+
+  return uiIsLastCtuOfSliceSegment>0;
+}
+
+//! decode CU block recursively
+Void TDecCu::xDecodeCU( TComDataCU*const pcCU, const UInt uiAbsPartIdx, const UInt uiDepth, Bool &isLastCtuOfSliceSegment)
+{
+  TComPic* pcPic        = pcCU->getPic();
+  const TComSPS &sps    = pcPic->getPicSym()->getSPS();
+  const TComPPS &pps    = pcPic->getPicSym()->getPPS();
+  const UInt maxCuWidth = sps.getMaxCUWidth();
+  const UInt maxCuHeight= sps.getMaxCUHeight();
+  UInt uiCurNumParts    = pcPic->getNumPartitionsInCtu() >> (uiDepth<<1);
   UInt uiQNumParts      = uiCurNumParts>>2;
-  
+
+
   Bool bBoundary = false;
   UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
-  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
+  UInt uiRPelX   = uiLPelX + (maxCuWidth>>uiDepth)  - 1;
   UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
-  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
+  UInt uiBPelY   = uiTPelY + (maxCuHeight>>uiDepth) - 1;
 #if H_MV_ENC_DEC_TRAC
   DTRACE_CU_S("=========== coding_quadtree ===========\n")
   DTRACE_CU("x0", uiLPelX)
   DTRACE_CU("x1", uiTPelY)
-  DTRACE_CU("log2CbSize", g_uiMaxCUWidth>>uiDepth)
+  DTRACE_CU("log2CbSize", maxCuWidth>>uiDepth)
   DTRACE_CU("cqtDepth"  , uiDepth)
 #endif
 
-  TComSlice * pcSlice = pcCU->getPic()->getSlice(pcCU->getPic()->getCurrSliceIdx());
-  Bool bStartInCU = pcCU->getSCUAddr()+uiAbsPartIdx+uiCurNumParts>pcSlice->getSliceSegmentCurStartCUAddr()&&pcCU->getSCUAddr()+uiAbsPartIdx<pcSlice->getSliceSegmentCurStartCUAddr();
-  if((!bStartInCU) && ( uiRPelX < pcSlice->getSPS()->getPicWidthInLumaSamples() ) && ( uiBPelY < pcSlice->getSPS()->getPicHeightInLumaSamples() ) )
+  if( ( uiRPelX < sps.getPicWidthInLumaSamples() ) && ( uiBPelY < sps.getPicHeightInLumaSamples() ) )
   {
     m_pcEntropyDecoder->decodeSplitFlag( pcCU, uiAbsPartIdx, uiDepth );
@@ -239,9 +229,8 @@
     bBoundary = true;
   }
-  
-  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth ) ) || bBoundary )
+  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary )
   {
     UInt uiIdx = uiAbsPartIdx;
-    if( (g_uiMaxCUWidth>>uiDepth) == pcCU->getSlice()->getPPS()->getMinCuDQPSize() && pcCU->getSlice()->getPPS()->getUseDQP())
+    if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP())
     {
       setdQPFlag(true);
@@ -249,37 +238,30 @@
     }
 
+    if( uiDepth == pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcCU->getSlice()->getUseChromaQpAdj() )
+    {
+      setIsChromaQpAdjCoded(true);
+    }
+
     for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ )
     {
       uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ];
       uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ];
-      
-      Bool bSubInSlice = pcCU->getSCUAddr()+uiIdx+uiQNumParts>pcSlice->getSliceSegmentCurStartCUAddr();
-      if ( bSubInSlice )
-      {
-        if ( !ruiIsLast && ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
-        {
-          xDecodeCU( pcCU, uiIdx, uiDepth+1, ruiIsLast );
-        }
-        else
-        {
-          pcCU->setOutsideCUPart( uiIdx, uiDepth+1 );
-        }
-      }
-      
+
+      if ( !isLastCtuOfSliceSegment && ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) )
+      {
+        xDecodeCU( pcCU, uiIdx, uiDepth+1, isLastCtuOfSliceSegment );
+      }
+      else
+      {
+        pcCU->setOutsideCUPart( uiIdx, uiDepth+1 );
+      }
+
       uiIdx += uiQNumParts;
     }
-    if( (g_uiMaxCUWidth>>uiDepth) == pcCU->getSlice()->getPPS()->getMinCuDQPSize() && pcCU->getSlice()->getPPS()->getUseDQP())
+    if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP())
     {
       if ( getdQPFlag() )
       {
-        UInt uiQPSrcPartIdx;
-        if ( pcPic->getCU( pcCU->getAddr() )->getSliceSegmentStartCU(uiAbsPartIdx) != pcSlice->getSliceSegmentCurStartCUAddr() )
-        {
-          uiQPSrcPartIdx = pcSlice->getSliceSegmentCurStartCUAddr() % pcPic->getNumPartInCU();
-        }
-        else
-        {
-          uiQPSrcPartIdx = uiAbsPartIdx;
-        }
+        UInt uiQPSrcPartIdx = uiAbsPartIdx;
         pcCU->setQPSubParts( pcCU->getRefQP( uiQPSrcPartIdx ), uiAbsPartIdx, uiDepth ); // set QP to default QP
       }
@@ -287,5 +269,5 @@
     return;
   }
-  
+
 #if H_MV_ENC_DEC_TRAC
   DTRACE_CU_S("=========== coding_unit ===========\n")
@@ -303,43 +285,58 @@
 #endif
 
-  if( (g_uiMaxCUWidth>>uiDepth) >= pcCU->getSlice()->getPPS()->getMinCuDQPSize() && pcCU->getSlice()->getPPS()->getUseDQP())
+  if( uiDepth <= pps.getMaxCuDQPDepth() && pps.getUseDQP())
   {
     setdQPFlag(true);
     pcCU->setQPSubParts( pcCU->getRefQP(uiAbsPartIdx), uiAbsPartIdx, uiDepth ); // set QP to default QP
   }
-#if H_3D_NBDV 
+#if NH_3D_NBDV 
   DisInfo DvInfo; 
   DvInfo.m_acNBDV.setZero();
   DvInfo.m_aVIdxCan = 0;
-#if H_3D_NBDV_REF  
+#if NH_3D_NBDV_REF  
   DvInfo.m_acDoNBDV.setZero();
 #endif
  
- 
-  if(!pcCU->getSlice()->isIntra())
-  {
-#if H_3D_ARP && H_3D_IV_MERGE
-    if( pcCU->getSlice()->getIvResPredFlag() || pcCU->getSlice()->getIvMvPredFlag() )
+if(!pcCU->getSlice()->isIntra())
+  {
+#if NH_3D_ARP && NH_3D_IV_MERGE && NH_3D_VSP
+    if( pcCU->getSlice()->getIvResPredFlag() || pcCU->getSlice()->getIvMvPredFlag() || pcCU->getSlice()->getViewSynthesisPredFlag() )
 #else 
+#if NH_3D_IV_MERGE && NH_3D_VSP
+    if( pcCU->getSlice()->getIvMvPredFlag() || pcCU->getSlice()->getViewSynthesisPredFlag() )
+#else
+#if NH_3D_ARP && NH_3D_VSP
+    if( pcCU->getSlice()->getIvResPredFlag() || pcCU->getSlice()->getViewSynthesisPredFlag() )
+#else
+#if NH_3D_VSP
+    if( pcCU->getSlice()->getViewSynthesisPredFlag() )
+#else
 #if H_3D_ARP
-    if( pcCU->getSlice()->getVPS()->getUseAdvRP(pcCU->getSlice()->getLayerId()) )
+    if( pcCU->getSlice()->getIvResPredFlag( ) )
 #else
 #if H_3D_IV_MERGE
     if( pcCU->getSlice()->getVPS()->getIvMvPredFlag(pcCU->getSlice()->getLayerId()) )
 #else
+#if NH_3D_DBBP
+    if( pcCU->getSlice()->getDepthBasedBlkPartFlag() )
+#else
     if (0)
 #endif
 #endif
 #endif
-    {
-      m_ppcCU[uiDepth]->copyInterPredInfoFrom( pcCU, uiAbsPartIdx, REF_PIC_LIST_0, true );
-      m_ppcCU[uiDepth]->copyDVInfoFrom( pcCU, uiAbsPartIdx);
+#endif
+#endif
+#endif
+#endif
+    {
+      m_ppcCU[uiDepth]->copyInterPredInfoFrom(pcCU, uiAbsPartIdx, REF_PIC_LIST_0, true);
+      m_ppcCU[uiDepth]->copyDVInfoFrom(pcCU, uiAbsPartIdx);
       PartSize ePartTemp = m_ppcCU[uiDepth]->getPartitionSize(0);
       UChar cWidTemp     = m_ppcCU[uiDepth]->getWidth(0);
       UChar cHeightTemp  = m_ppcCU[uiDepth]->getHeight(0);
-      m_ppcCU[uiDepth]->setWidth  ( 0, pcCU->getSlice()->getSPS()->getMaxCUWidth ()/(1<<uiDepth)  );
-      m_ppcCU[uiDepth]->setHeight ( 0, pcCU->getSlice()->getSPS()->getMaxCUHeight()/(1<<uiDepth)  );
-      m_ppcCU[uiDepth]->setPartSizeSubParts( SIZE_2Nx2N, 0, uiDepth );     
-#if H_3D_IV_MERGE
+      m_ppcCU[uiDepth]->setWidth (0, pcCU->getSlice()->getSPS()->getMaxCUWidth () / (1 << uiDepth));
+      m_ppcCU[uiDepth]->setHeight(0, pcCU->getSlice()->getSPS()->getMaxCUHeight() / (1 << uiDepth));
+      m_ppcCU[uiDepth]->setPartSizeSubParts(SIZE_2Nx2N, 0, uiDepth);     
+#if NH_3D_IV_MERGE
       if( pcCU->getSlice()->getIsDepth())
       {
@@ -349,5 +346,5 @@
       {
 #endif
-#if H_3D_NBDV_REF
+#if NH_3D_NBDV_REF
       if( pcCU->getSlice()->getDepthBasedBlkPartFlag() )  //Notes from QC: please check the condition for DoNBDV. Remove this comment once it is done.
       {
@@ -359,5 +356,5 @@
         m_ppcCU[uiDepth]->getDisMvpCandNBDV(&DvInfo);
       }
-#if H_3D_IV_MERGE
+#if NH_3D_IV_MERGE
       }
 #endif
@@ -372,17 +369,22 @@
       }
 #endif
-
       pcCU->setDvInfoSubParts(DvInfo, uiAbsPartIdx, uiDepth);
-      m_ppcCU[uiDepth]->setPartSizeSubParts( ePartTemp, 0, uiDepth );
-      m_ppcCU[uiDepth]->setWidth  ( 0, cWidTemp );
-      m_ppcCU[uiDepth]->setHeight ( 0, cHeightTemp );
+      m_ppcCU[uiDepth]->setPartSizeSubParts(ePartTemp, 0, uiDepth);
+      m_ppcCU[uiDepth]->setWidth(0, cWidTemp);
+      m_ppcCU[uiDepth]->setHeight(0, cHeightTemp);
      }
   }
 #endif
-  if (pcCU->getSlice()->getPPS()->getTransquantBypassEnableFlag())
+
+  if( uiDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcCU->getSlice()->getUseChromaQpAdj() )
+  {
+    setIsChromaQpAdjCoded(true);
+  }
+
+  if (pps.getTransquantBypassEnableFlag())
   {
     m_pcEntropyDecoder->decodeCUTransquantBypassFlag( pcCU, uiAbsPartIdx, uiDepth );
   }
-  
+
   // decode CU mode and the partition size
   if( !pcCU->getSlice()->isIntra())
@@ -390,5 +392,6 @@
     m_pcEntropyDecoder->decodeSkipFlag( pcCU, uiAbsPartIdx, uiDepth );
   }
- 
+
+
   if( pcCU->isSkipped(uiAbsPartIdx) )
   {
@@ -400,6 +403,10 @@
     m_ppcCU[uiDepth]->copyInterPredInfoFrom( pcCU, uiAbsPartIdx, REF_PIC_LIST_0 );
     m_ppcCU[uiDepth]->copyInterPredInfoFrom( pcCU, uiAbsPartIdx, REF_PIC_LIST_1 );
-#if H_3D_IV_MERGE
+#if NH_3D_IV_MERGE
     m_ppcCU[uiDepth]->copyDVInfoFrom(pcCU, uiAbsPartIdx);
+    TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS_MEM << 1]; // double length for mv of both lists
+    UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS_MEM];
+#else
+#if NH_3D_MLC
     TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS_MEM << 1]; // double length for mv of both lists
     UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS_MEM];
@@ -408,4 +415,5 @@
     UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
 #endif
+#endif
     Int numValidMergeCand = 0;
     for( UInt ui = 0; ui < m_ppcCU[uiDepth]->getSlice()->getMaxNumMergeCand(); ++ui )
@@ -415,50 +423,54 @@
     m_pcEntropyDecoder->decodeMergeIndex( pcCU, 0, uiAbsPartIdx, uiDepth );
     UInt uiMergeIndex = pcCU->getMergeIndex(uiAbsPartIdx);
-#if H_3D_ARP
+#if NH_3D_ARP
     m_pcEntropyDecoder->decodeARPW( pcCU , uiAbsPartIdx , uiDepth );
 #endif
-#if H_3D_IC
+#if NH_3D_IC
     m_pcEntropyDecoder->decodeICFlag( pcCU, uiAbsPartIdx, uiDepth );
 #endif
 
-#if H_3D_VSP
+
+#if NH_3D_VSP
     Int vspFlag[MRG_MAX_NUM_CANDS_MEM];
     memset(vspFlag, 0, sizeof(Int)*MRG_MAX_NUM_CANDS_MEM);
-#if H_3D_SPIVMP
+#endif
+#if NH_3D_SPIVMP
     Bool bSPIVMPFlag[MRG_MAX_NUM_CANDS_MEM];
     memset(bSPIVMPFlag, false, sizeof(Bool)*MRG_MAX_NUM_CANDS_MEM);
     TComMvField*  pcMvFieldSP;
     UChar* puhInterDirSP;
-    pcMvFieldSP = new TComMvField[pcCU->getPic()->getPicSym()->getNumPartition()*2]; 
-    puhInterDirSP = new UChar[pcCU->getPic()->getPicSym()->getNumPartition()]; 
-#endif
+    pcMvFieldSP = new TComMvField[pcCU->getPic()->getPicSym()->getNumPartitionsInCtu()*2]; 
+    puhInterDirSP = new UChar[pcCU->getPic()->getPicSym()->getNumPartitionsInCtu()]; 
+#endif
+
+#if NH_3D_MLC
     m_ppcCU[uiDepth]->initAvailableFlags();
+#endif
     m_ppcCU[uiDepth]->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, uiMergeIndex );
+#if NH_3D_MLC
     m_ppcCU[uiDepth]->xGetInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours 
-#if H_3D_SPIVMP
+#if NH_3D_SPIVMP
       , pcMvFieldSP, puhInterDirSP
 #endif
       , numValidMergeCand, uiMergeIndex );
 
-    m_ppcCU[uiDepth]->buildMCL( cMvFieldNeighbours, uhInterDirNeighbours, vspFlag
-#if H_3D_SPIVMP
+    m_ppcCU[uiDepth]->buildMCL( cMvFieldNeighbours, uhInterDirNeighbours
+#if NH_3D_VSP
+      , vspFlag
+#endif
+#if NH_3D_SPIVMP
       , bSPIVMPFlag
 #endif
       , numValidMergeCand );
+#endif
+#if NH_3D_VSP
     pcCU->setVSPFlagSubParts( vspFlag[uiMergeIndex], uiAbsPartIdx, 0, uiDepth );
-#else
-#if H_3D
-    m_ppcCU[uiDepth]->initAvailableFlags();
-    m_ppcCU[uiDepth]->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, uiMergeIndex );
-    m_ppcCU[uiDepth]->xGetInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, uiMergeIndex );
-#else
-    m_ppcCU[uiDepth]->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, uiMergeIndex );
-#endif
-#endif
+#endif
+
     pcCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeIndex], uiAbsPartIdx, 0, uiDepth );
 
     TComMv cTmpMv( 0, 0 );
     for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
-    {        
+    {
       if ( pcCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 )
       {
@@ -467,5 +479,5 @@
         pcCU->getCUMvField( RefPicList( uiRefListIdx ) )->setAllMvd( cTmpMv, SIZE_2Nx2N, uiAbsPartIdx, uiDepth );
         pcCU->getCUMvField( RefPicList( uiRefListIdx ) )->setAllMvField( cMvFieldNeighbours[ 2*uiMergeIndex + uiRefListIdx ], SIZE_2Nx2N, uiAbsPartIdx, uiDepth );
-#if H_3D_VSP
+#if NH_3D_VSP
         if( pcCU->getVSPFlag( uiAbsPartIdx ) != 0 )
         {
@@ -500,5 +512,5 @@
       }
     }
-#if H_3D_SPIVMP
+#if NH_3D_SPIVMP
     pcCU->setSPIVMPFlagSubParts(bSPIVMPFlag[uiMergeIndex], uiAbsPartIdx, 0, uiDepth ); 
     if (bSPIVMPFlag[uiMergeIndex])
@@ -524,15 +536,17 @@
 #endif
 
-    xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, ruiIsLast );
-#if H_3D_IV_MERGE
+    xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, isLastCtuOfSliceSegment );
+#if NH_3D_IV_MERGE
     xDecompressCU(pcCU, uiAbsPartIdx, uiDepth );
 #endif
+
     return;
   }
-#if H_3D
+#if NH_3D_DIS
   m_pcEntropyDecoder->decodeDIS( pcCU, uiAbsPartIdx, uiDepth );
   if(!pcCU->getDISFlag(uiAbsPartIdx))
   {
 #endif
+
   m_pcEntropyDecoder->decodePredMode( pcCU, uiAbsPartIdx, uiDepth );
   m_pcEntropyDecoder->decodePartSize( pcCU, uiAbsPartIdx, uiDepth );
@@ -544,9 +558,9 @@
     if(pcCU->getIPCMFlag(uiAbsPartIdx))
     {
-#if H_3D_DIM_SDC
+#if NH_3D_SDC_INTRA
       m_pcEntropyDecoder->decodeSDCFlag( pcCU, uiAbsPartIdx, uiDepth );
 #endif
-      xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, ruiIsLast );
-#if H_3D_IV_MERGE
+      xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, isLastCtuOfSliceSegment );
+#if NH_3D_IV_MERGE
       xDecompressCU(pcCU, uiAbsPartIdx, uiDepth );
 #endif
@@ -555,7 +569,4 @@
   }
 
-  UInt uiCurrWidth      = pcCU->getWidth ( uiAbsPartIdx );
-  UInt uiCurrHeight     = pcCU->getHeight( uiAbsPartIdx );
-  
   // prediction mode ( Intra : direction mode, Inter : Mv, reference idx )
   m_pcEntropyDecoder->decodePredInfo( pcCU, uiAbsPartIdx, uiDepth, m_ppcCU[uiDepth]);
@@ -563,16 +574,18 @@
   // Coefficient decoding
   Bool bCodeDQP = getdQPFlag();
-  m_pcEntropyDecoder->decodeCoeff( pcCU, uiAbsPartIdx, uiDepth, uiCurrWidth, uiCurrHeight, bCodeDQP );
+  Bool isChromaQpAdjCoded = getIsChromaQpAdjCoded();
+  m_pcEntropyDecoder->decodeCoeff( pcCU, uiAbsPartIdx, uiDepth, bCodeDQP, isChromaQpAdjCoded );
+  setIsChromaQpAdjCoded( isChromaQpAdjCoded );
   setdQPFlag( bCodeDQP );
-#if H_3D
-  }
-#endif
-  xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, ruiIsLast );
-#if H_3D_IV_MERGE
+#if NH_3D_DIS
+  }
+#endif
+  xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, isLastCtuOfSliceSegment );
+#if NH_3D_IV_MERGE
   xDecompressCU(pcCU, uiAbsPartIdx, uiDepth );
 #endif
 }
 
-Void TDecCu::xFinishDecodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt& ruiIsLast)
+Void TDecCu::xFinishDecodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool &isLastCtuOfSliceSegment)
 {
   if(  pcCU->getSlice()->getPPS()->getUseDQP())
@@ -581,39 +594,43 @@
   }
 
-  ruiIsLast = xDecodeSliceEnd( pcCU, uiAbsPartIdx, uiDepth);
-}
-
-Void TDecCu::xDecompressCU( TComDataCU* pcCU, UInt uiAbsPartIdx,  UInt uiDepth )
-{
-  TComPic* pcPic = pcCU->getPic();
-#if !H_3D_IV_MERGE
+  if (pcCU->getSlice()->getUseChromaQpAdj() && !getIsChromaQpAdjCoded())
+  {
+    pcCU->setChromaQpAdjSubParts( pcCU->getCodedChromaQpAdj(), uiAbsPartIdx, uiDepth ); // set QP
+  }
+
+  isLastCtuOfSliceSegment = xDecodeSliceEnd( pcCU, uiAbsPartIdx );
+}
+
+Void TDecCu::xDecompressCU( TComDataCU* pCtu, UInt uiAbsPartIdx,  UInt uiDepth )
+{
+  TComPic* pcPic = pCtu->getPic();
+#if !NH_3D_IV_MERGE
+  TComSlice * pcSlice = pCtu->getSlice();
+  const TComSPS &sps=*(pcSlice->getSPS());
+
   Bool bBoundary = false;
-  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
-  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
-  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
-  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
-
-  UInt uiCurNumParts    = pcPic->getNumPartInCU() >> (uiDepth<<1);
-  TComSlice * pcSlice = pcCU->getPic()->getSlice(pcCU->getPic()->getCurrSliceIdx());
-  Bool bStartInCU = pcCU->getSCUAddr()+uiAbsPartIdx+uiCurNumParts>pcSlice->getSliceSegmentCurStartCUAddr()&&pcCU->getSCUAddr()+uiAbsPartIdx<pcSlice->getSliceSegmentCurStartCUAddr();
-  if(bStartInCU||( uiRPelX >= pcSlice->getSPS()->getPicWidthInLumaSamples() ) || ( uiBPelY >= pcSlice->getSPS()->getPicHeightInLumaSamples() ) )
+  UInt uiLPelX   = pCtu->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
+  UInt uiRPelX   = uiLPelX + (sps.getMaxCUWidth()>>uiDepth)  - 1;
+  UInt uiTPelY   = pCtu->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
+  UInt uiBPelY   = uiTPelY + (sps.getMaxCUHeight()>>uiDepth) - 1;
+
+  if( ( uiRPelX >= sps.getPicWidthInLumaSamples() ) || ( uiBPelY >= sps.getPicHeightInLumaSamples() ) )
   {
     bBoundary = true;
   }
 
-  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth ) ) || bBoundary )
+  if( ( ( uiDepth < pCtu->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary )
   {
     UInt uiNextDepth = uiDepth + 1;
-    UInt uiQNumParts = pcCU->getTotalNumPart() >> (uiNextDepth<<1);
+    UInt uiQNumParts = pCtu->getTotalNumPart() >> (uiNextDepth<<1);
     UInt uiIdx = uiAbsPartIdx;
     for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++ )
     {
-      uiLPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ];
-      uiTPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ];
-
-      Bool binSlice = (pcCU->getSCUAddr()+uiIdx+uiQNumParts>pcSlice->getSliceSegmentCurStartCUAddr())&&(pcCU->getSCUAddr()+uiIdx<pcSlice->getSliceSegmentCurEndCUAddr());
-      if(binSlice&&( uiLPelX < pcSlice->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcSlice->getSPS()->getPicHeightInLumaSamples() ) )
-      {
-        xDecompressCU(pcCU, uiIdx, uiNextDepth );
+      uiLPelX = pCtu->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ];
+      uiTPelY = pCtu->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ];
+
+      if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) )
+      {
+        xDecompressCU(pCtu, uiIdx, uiNextDepth );
       }
 
@@ -622,14 +639,14 @@
     return;
   }
-#endif  
+#endif
   // Residual reconstruction
   m_ppcYuvResi[uiDepth]->clear();
 
-  m_ppcCU[uiDepth]->copySubCU( pcCU, uiAbsPartIdx, uiDepth );
+  m_ppcCU[uiDepth]->copySubCU( pCtu, uiAbsPartIdx );
 
   switch( m_ppcCU[uiDepth]->getPredictionMode(0) )
   {
-  case MODE_INTER:
-#if H_3D_DBBP
+    case MODE_INTER:
+#if NH_3D_DBBP
     if( m_ppcCU[uiDepth]->getDBBPFlag(0) )
     {
@@ -639,5 +656,5 @@
     {
 #endif
-#if H_3D_INTER_SDC
+#if NH_3D_SDC_INTER
       if( m_ppcCU[uiDepth]->getSDCFlag( 0 ) )
       {
@@ -647,19 +664,26 @@
       {
 #endif
-        xReconInter( m_ppcCU[uiDepth], uiDepth );
-#if H_3D_INTER_SDC
-      }
-#endif
-#if H_3D_DBBP
-    }
-#endif
-    break;
-  case MODE_INTRA:
-#if H_3D
+      xReconInter( m_ppcCU[uiDepth], uiDepth );
+#if NH_3D_SDC_INTER
+      }
+#endif
+#if NH_3D_DBBP
+    }
+#endif
+      break;
+    case MODE_INTRA:
+#if NH_3D
+#if NH_3D_DIS
     if( m_ppcCU[uiDepth]->getDISFlag(0) )
     {
       xReconDIS( m_ppcCU[uiDepth], 0, uiDepth );
     }
-#if H_3D_DIM_SDC
+#else
+    if(false )
+    {
+     // xReconDIS( m_ppcCU[uiDepth], 0, uiDepth );
+    }
+#endif
+#if NH_3D_SDC_INTRA
     else if( m_ppcCU[uiDepth]->getSDCFlag(0) )
     {
@@ -670,9 +694,21 @@
 #endif
       xReconIntraQT( m_ppcCU[uiDepth], uiDepth );
-    break;
-  default:
-    assert(0);
-    break;
-  }
+      break;
+    default:
+      assert(0);
+      break;
+  }
+
+#if DEBUG_STRING
+  const PredMode predMode=m_ppcCU[uiDepth]->getPredictionMode(0);
+  if (DebugOptionList::DebugString_Structure.getInt()&DebugStringGetPredModeMask(predMode))
+  {
+    PartSize eSize=m_ppcCU[uiDepth]->getPartitionSize(0);
+    std::ostream &ss(std::cout);
+
+    ss <<"###: " << (predMode==MODE_INTRA?"Intra   ":"Inter   ") << partSizeToString[eSize] << " CU at " << m_ppcCU[uiDepth]->getCUPelX() << ", " << m_ppcCU[uiDepth]->getCUPelY() << " width=" << UInt(m_ppcCU[uiDepth]->getWidth(0)) << std::endl;
+  }
+#endif
+
   if ( m_ppcCU[uiDepth]->isLosslessCoded(0) && (m_ppcCU[uiDepth]->getIPCMFlag(0) == false))
   {
@@ -685,15 +721,30 @@
 Void TDecCu::xReconInter( TComDataCU* pcCU, UInt uiDepth )
 {
-  
+
   // inter prediction
   m_pcPrediction->motionCompensation( pcCU, m_ppcYuvReco[uiDepth] );
-  
+
+#if DEBUG_STRING
+  const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTER);
+  if (DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask)
+  {
+    printBlockToStream(std::cout, "###inter-pred: ", *(m_ppcYuvReco[uiDepth]));
+  }
+#endif
+
   // inter recon
-  xDecodeInterTexture( pcCU, 0, uiDepth );
-  
+  xDecodeInterTexture( pcCU, uiDepth );
+
+#if DEBUG_STRING
+  if (DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask)
+  {
+    printBlockToStream(std::cout, "###inter-resi: ", *(m_ppcYuvResi[uiDepth]));
+  }
+#endif
+
   // clip for only non-zero cbp case
-  if  ( ( pcCU->getCbf( 0, TEXT_LUMA ) ) || ( pcCU->getCbf( 0, TEXT_CHROMA_U ) ) || ( pcCU->getCbf(0, TEXT_CHROMA_V ) ) )
-  {
-    m_ppcYuvReco[uiDepth]->addClip( m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], 0, pcCU->getWidth( 0 ) );
+  if  ( pcCU->getQtRootCbf( 0) )
+  {
+    m_ppcYuvReco[uiDepth]->addClip( m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], 0, pcCU->getWidth( 0 ), pcCU->getSlice()->getSPS()->getBitDepths() );
   }
   else
@@ -701,7 +752,14 @@
     m_ppcYuvReco[uiDepth]->copyPartToPartYuv( m_ppcYuvReco[uiDepth],0, pcCU->getWidth( 0 ),pcCU->getHeight( 0 ));
   }
-}
-
-#if H_3D
+#if DEBUG_STRING
+  if (DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask)
+  {
+    printBlockToStream(std::cout, "###inter-reco: ", *(m_ppcYuvReco[uiDepth]));
+  }
+#endif
+
+}
+
+#if NH_3D_DIS
 Void TDecCu::xReconDIS( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
 {
@@ -711,32 +769,29 @@
   TComYuv* pcRecoYuv  = m_ppcYuvReco[uiDepth];
 
-  UInt    uiStride    = pcRecoYuv->getStride  ();
-  Pel*    piReco      = pcRecoYuv->getLumaAddr( uiAbsPartIdx );
+  UInt    uiStride    = pcRecoYuv->getStride  (COMPONENT_Y);
+  Pel*    piReco      = pcRecoYuv->getAddr( COMPONENT_Y, uiAbsPartIdx );
 
 
   AOF( uiWidth == uiHeight );
   AOF( uiAbsPartIdx == 0 );
-
-  Bool  bAboveAvail = false;
-  Bool  bLeftAvail  = false;
-  pcCU->getPattern()->initPattern   ( pcCU, 0, uiAbsPartIdx );
-  pcCU->getPattern()->initAdiPattern( pcCU, uiAbsPartIdx, 0, 
-    m_pcPrediction->getPredicBuf       (),
-    m_pcPrediction->getPredicBufWidth  (),
-    m_pcPrediction->getPredicBufHeight (),
-    bAboveAvail, bLeftAvail
-    );
+  
+  TComTURecurse rTu(pcCU, 0);
+  const ChromaFormat chFmt     = rTu.GetChromaFormat();
 
   if ( pcCU->getDISType(uiAbsPartIdx) == 0 )
   {
-    m_pcPrediction->predIntraLumaAng( pcCU->getPattern(), VER_IDX, piReco, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );
+    const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(COMPONENT_Y, VER_IDX, uiWidth, uiHeight, chFmt, pcCU->getSlice()->getSPS()->getSpsRangeExtension().getIntraSmoothingDisabledFlag());
+    m_pcPrediction->initIntraPatternChType( rTu, COMPONENT_Y, bUseFilteredPredictions  DEBUG_STRING_PASS_INTO(sTemp) );
+    m_pcPrediction->predIntraAng( COMPONENT_Y,   VER_IDX, 0 /* Decoder does not have an original image */, 0, piReco, uiStride, rTu, bUseFilteredPredictions );
   }
   else if ( pcCU->getDISType(uiAbsPartIdx) == 1 )
   {
-    m_pcPrediction->predIntraLumaAng( pcCU->getPattern(), HOR_IDX, piReco, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );
+    const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(COMPONENT_Y, HOR_IDX, uiWidth, uiHeight, chFmt, pcCU->getSlice()->getSPS()->getSpsRangeExtension().getIntraSmoothingDisabledFlag());
+    m_pcPrediction->initIntraPatternChType( rTu, COMPONENT_Y, bUseFilteredPredictions  DEBUG_STRING_PASS_INTO(sTemp) );
+    m_pcPrediction->predIntraAng( COMPONENT_Y,   HOR_IDX, 0 /* Decoder does not have an original image */, 0, piReco, uiStride, rTu, bUseFilteredPredictions );
   }
   else if ( pcCU->getDISType(uiAbsPartIdx) == 2 )
   {
-    Pel pSingleDepth = 1 << ( g_bitDepthY - 1 );
+    Pel pSingleDepth = 1 << ( pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 1 );
     pcCU->getNeighDepth ( 0, 0, &pSingleDepth, 0 );
     for( UInt uiY = 0; uiY < uiHeight; uiY++ )
@@ -751,5 +806,5 @@
   else if ( pcCU->getDISType(uiAbsPartIdx) == 3 )
   {
-    Pel pSingleDepth = 1 << ( g_bitDepthY - 1 );
+    Pel pSingleDepth = 1 << ( pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 1 );
     pcCU->getNeighDepth ( 0, 0, &pSingleDepth, 1 );
     for( UInt uiY = 0; uiY < uiHeight; uiY++ )
@@ -764,7 +819,7 @@
 
   // clear UV
-  UInt  uiStrideC     = pcRecoYuv->getCStride();
-  Pel   *pRecCb       = pcRecoYuv->getCbAddr();
-  Pel   *pRecCr       = pcRecoYuv->getCrAddr();
+  UInt  uiStrideC     = pcRecoYuv->getStride(COMPONENT_Cb);
+  Pel   *pRecCb       = pcRecoYuv->getAddr(COMPONENT_Cb);
+  Pel   *pRecCr       = pcRecoYuv->getAddr(COMPONENT_Cr);
 
   for (Int y=0; y<uiHeight/2; y++)
@@ -772,6 +827,6 @@
     for (Int x=0; x<uiWidth/2; x++)
     {
-      pRecCb[x] = 1<<(g_bitDepthC-1);
-      pRecCr[x] = 1<<(g_bitDepthC-1);
+      pRecCb[x] = 1<<(pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA)-1);
+      pRecCr[x] = 1<<(pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA)-1);
     }
 
@@ -781,5 +836,5 @@
 }
 #endif
-#if H_3D_INTER_SDC
+#if NH_3D_SDC_INTER
 Void TDecCu::xReconInterSDC( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
 {
@@ -792,7 +847,8 @@
   Pel  *pResi;
   UInt uiPelX, uiPelY;
-  UInt uiResiStride = m_ppcYuvResi[uiDepth]->getStride();
-
-  pResi = m_ppcYuvResi[uiDepth]->getLumaAddr( 0 );
+  UInt uiResiStride = m_ppcYuvResi[uiDepth]->getStride( COMPONENT_Y );
+  Int  bitDepthC = pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA);
+
+  pResi = m_ppcYuvResi[uiDepth]->getAddr( COMPONENT_Y );
   for( uiPelY = 0; uiPelY < uiHeight; uiPelY++ )
   {
@@ -804,10 +860,10 @@
   }
 
-  m_ppcYuvReco[uiDepth]->addClip( m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], 0, pcCU->getWidth( 0 ) );
+  m_ppcYuvReco[uiDepth]->addClip( m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], 0, pcCU->getWidth( 0 ), pcCU->getSlice()->getSPS()->getBitDepths() );
 
   // clear UV
-  UInt  uiStrideC     = m_ppcYuvReco[uiDepth]->getCStride();
-  Pel   *pRecCb       = m_ppcYuvReco[uiDepth]->getCbAddr();
-  Pel   *pRecCr       = m_ppcYuvReco[uiDepth]->getCrAddr();
+  UInt  uiStrideC     = m_ppcYuvReco[uiDepth]->getStride( COMPONENT_Cb );
+  Pel   *pRecCb       = m_ppcYuvReco[uiDepth]->getAddr( COMPONENT_Cb );
+  Pel   *pRecCr       = m_ppcYuvReco[uiDepth]->getAddr( COMPONENT_Cr );
 
   for (Int y = 0; y < uiHeight/2; y++)
@@ -815,6 +871,6 @@
     for (Int x = 0; x < uiWidth/2; x++)
     {
-      pRecCb[x] = (Pel)( 1 << ( g_bitDepthC - 1 ) );
-      pRecCr[x] = (Pel)( 1 << ( g_bitDepthC - 1 ) );
+      pRecCb[x] = (Pel)( 1 << ( bitDepthC - 1 ) );
+      pRecCr[x] = (Pel)( 1 << ( bitDepthC - 1 ) );
     }
 
@@ -825,5 +881,5 @@
 #endif
 
-#if H_3D_DBBP
+#if NH_3D_DBBP
 Void TDecCu::xReconInterDBBP( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
 {
@@ -831,4 +887,6 @@
   AOF(!pcCU->getSlice()->isIntra());
   PartSize ePartSize = pcCU->getPartitionSize( 0 );
+  
+  Int bitDepthY = pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
   
   // get collocated depth block
@@ -851,5 +909,5 @@
   
   // first, extract the two sets of motion parameters
-  UInt uiPUOffset = ( g_auiPUOffset[UInt( ePartSize )] << ( ( pcCU->getSlice()->getSPS()->getMaxCUDepth() - uiDepth ) << 1 ) ) >> 4;
+  UInt uiPUOffset = ( g_auiPUOffset[UInt( ePartSize )] << ( ( pcCU->getSlice()->getSPS()->getMaxTotalCUDepth() - uiDepth ) << 1 ) ) >> 4;
   for( UInt uiSegment = 0; uiSegment < 2; uiSegment++ )
   {
@@ -857,4 +915,5 @@
     
     pDBBPTmpData->auhInterDir[uiSegment] = pcCU->getInterDir(uiPartAddr);
+    assert( pDBBPTmpData->auhInterDir[uiSegment] == 1 || pDBBPTmpData->auhInterDir[uiSegment] == 2  );  // only uni-prediction allowed
     
     for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
@@ -864,8 +923,10 @@
     }
     
+#if NH_3D
     AOF( pcCU->getARPW(uiPartAddr) == 0 );
     AOF( pcCU->getICFlag(uiPartAddr) == false );
     AOF( pcCU->getSPIVMPFlag(uiPartAddr) == false );
     AOF( pcCU->getVSPFlag(uiPartAddr) == 0 );
+#endif
   }
   
@@ -907,13 +968,13 @@
   
   // reconstruct final prediction signal by combining both segments
-  m_pcPrediction->combineSegmentsWithMask(apSegPredYuv, m_ppcYuvReco[uiDepth], pMask, pcCU->getWidth(0), pcCU->getHeight(0), 0, ePartSize);
+  m_pcPrediction->combineSegmentsWithMask(apSegPredYuv, m_ppcYuvReco[uiDepth], pMask, pcCU->getWidth(0), pcCU->getHeight(0), 0, ePartSize, bitDepthY);
 
   // inter recon
-  xDecodeInterTexture( pcCU, 0, uiDepth );
+  xDecodeInterTexture( pcCU, uiDepth );
   
   // clip for only non-zero cbp case
-  if  ( ( pcCU->getCbf( 0, TEXT_LUMA ) ) || ( pcCU->getCbf( 0, TEXT_CHROMA_U ) ) || ( pcCU->getCbf(0, TEXT_CHROMA_V ) ) )
-  {
-    m_ppcYuvReco[uiDepth]->addClip( m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], 0, pcCU->getWidth( 0 ) );
+  if  ( ( pcCU->getCbf( 0, COMPONENT_Y ) ) || ( pcCU->getCbf( 0, COMPONENT_Cb ) ) || ( pcCU->getCbf(0, COMPONENT_Cr ) ) )
+  {
+    m_ppcYuvReco[uiDepth]->addClip( m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], 0, pcCU->getWidth( 0 ), pcCU->getSlice()->getSPS()->getBitDepths() );
   }
   else
@@ -924,80 +985,208 @@
 #endif
 
+
 Void
-TDecCu::xIntraRecLumaBlk( TComDataCU* pcCU,
-                         UInt        uiTrDepth,
-                         UInt        uiAbsPartIdx,
-                         TComYuv*    pcRecoYuv,
-                         TComYuv*    pcPredYuv, 
-                         TComYuv*    pcResiYuv )
-{
-  UInt    uiWidth           = pcCU     ->getWidth   ( 0 ) >> uiTrDepth;
-  UInt    uiHeight          = pcCU     ->getHeight  ( 0 ) >> uiTrDepth;
-  UInt    uiStride          = pcRecoYuv->getStride  ();
-  Pel*    piReco            = pcRecoYuv->getLumaAddr( uiAbsPartIdx );
-  Pel*    piPred            = pcPredYuv->getLumaAddr( uiAbsPartIdx );
-  Pel*    piResi            = pcResiYuv->getLumaAddr( uiAbsPartIdx );
-  
-  UInt    uiNumCoeffInc     = ( pcCU->getSlice()->getSPS()->getMaxCUWidth() * pcCU->getSlice()->getSPS()->getMaxCUHeight() ) >> ( pcCU->getSlice()->getSPS()->getMaxCUDepth() << 1 );
-  TCoeff* pcCoeff           = pcCU->getCoeffY() + ( uiNumCoeffInc * uiAbsPartIdx );
-  
-  UInt    uiLumaPredMode    = pcCU->getLumaIntraDir     ( uiAbsPartIdx );
-  
-  UInt    uiZOrder          = pcCU->getZorderIdxInCU() + uiAbsPartIdx;
-  Pel*    piRecIPred        = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), uiZOrder );
-  UInt    uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride  ();
-  Bool    useTransformSkip  = pcCU->getTransformSkip(uiAbsPartIdx, TEXT_LUMA);
+TDecCu::xIntraRecBlk(       TComYuv*    pcRecoYuv,
+                            TComYuv*    pcPredYuv,
+                            TComYuv*    pcResiYuv,
+                      const ComponentID compID,
+                            TComTU     &rTu)
+{
+  if (!rTu.ProcessComponentSection(compID))
+  {
+    return;
+  }
+  const Bool       bIsLuma = isLuma(compID);
+
+
+  TComDataCU *pcCU = rTu.getCU();
+  const TComSPS &sps=*(pcCU->getSlice()->getSPS());
+  const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU();
+
+  const TComRectangle &tuRect  =rTu.getRect(compID);
+  const UInt uiWidth           = tuRect.width;
+  const UInt uiHeight          = tuRect.height;
+  const UInt uiStride          = pcRecoYuv->getStride (compID);
+        Pel* piPred            = pcPredYuv->getAddr( compID, uiAbsPartIdx );
+  const ChromaFormat chFmt     = rTu.GetChromaFormat();
+
+  if (uiWidth != uiHeight)
+  {
+    //------------------------------------------------
+
+    //split at current level if dividing into square sub-TUs
+
+    TComTURecurse subTURecurse(rTu, false, TComTU::VERTICAL_SPLIT, true, compID);
+
+    //recurse further
+    do
+    {
+      xIntraRecBlk(pcRecoYuv, pcPredYuv, pcResiYuv, compID, subTURecurse);
+    } while (subTURecurse.nextSection(rTu));
+
+    //------------------------------------------------
+
+    return;
+  }
+
+  const UInt uiChPredMode  = pcCU->getIntraDir( toChannelType(compID), uiAbsPartIdx );
+  const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize()));
+  const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode;
+  const UInt uiChFinalMode = ((chFmt == CHROMA_422)       && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode;
+
   //===== init availability pattern =====
-  Bool  bAboveAvail = false;
-  Bool  bLeftAvail  = false;
-  pcCU->getPattern()->initPattern   ( pcCU, uiTrDepth, uiAbsPartIdx );
-  pcCU->getPattern()->initAdiPattern( pcCU, uiAbsPartIdx, uiTrDepth, 
-                                     m_pcPrediction->getPredicBuf       (),
-                                     m_pcPrediction->getPredicBufWidth  (),
-                                     m_pcPrediction->getPredicBufHeight (),
-                                     bAboveAvail, bLeftAvail );
-  
+  const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, uiChFinalMode, uiWidth, uiHeight, chFmt, pcCU->getSlice()->getSPS()->getSpsRangeExtension().getIntraSmoothingDisabledFlag());
+
+#if DEBUG_STRING
+  std::ostream &ss(std::cout);
+#endif
+
+  DEBUG_STRING_NEW(sTemp)
+  m_pcPrediction->initIntraPatternChType( rTu, compID, bUseFilteredPredictions  DEBUG_STRING_PASS_INTO(sTemp) );
+
+
   //===== get prediction signal =====
-#if H_3D_DIM
-  if( isDimMode( uiLumaPredMode ) )
-  {
-    m_pcPrediction->predIntraLumaDepth( pcCU, uiAbsPartIdx, uiLumaPredMode, piPred, uiStride, uiWidth, uiHeight );
+#if NH_3D_DMM
+  if( bIsLuma && isDmmMode( uiChFinalMode ) )
+  {
+    m_pcPrediction->predIntraLumaDmm( pcCU, uiAbsPartIdx, getDmmType( uiChFinalMode ), piPred, uiStride, uiWidth, uiHeight );
   }
   else
   {
 #endif
-  m_pcPrediction->predIntraLumaAng( pcCU->getPattern(), uiLumaPredMode, piPred, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );
-#if H_3D_DIM
-  }
-#endif
-  
+  m_pcPrediction->predIntraAng( compID,   uiChFinalMode, 0 /* Decoder does not have an original image */, 0, piPred, uiStride, rTu, bUseFilteredPredictions );
+#if NH_3D_DMM
+  }
+#endif
+
+#if DEBUG_STRING
+  ss << sTemp;
+#endif
+
+  //===== inverse transform =====
+  Pel*      piResi            = pcResiYuv->getAddr( compID, uiAbsPartIdx );
+  TCoeff*   pcCoeff           = pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID);//( uiNumCoeffInc * uiAbsPartIdx );
+
+  const QpParam cQP(*pcCU, compID);
+
+
+  DEBUG_STRING_NEW(sDebug);
+#if DEBUG_STRING
+  const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA);
+  std::string *psDebug=(DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) ? &sDebug : 0;
+#endif
 #if H_3D
-  Bool useDltFlag = (isDimMode( uiLumaPredMode ) || uiLumaPredMode == HOR_IDX || uiLumaPredMode == VER_IDX || uiLumaPredMode == DC_IDX) && pcCU->getSlice()->getIsDepth() && pcCU->getSlice()->getPPS()->getDLT()->getUseDLTFlag(pcCU->getSlice()->getLayerIdInVps());
+  Bool useDltFlag = (isDmmMode( uiLumaPredMode ) || uiLumaPredMode == HOR_IDX || uiLumaPredMode == VER_IDX || uiLumaPredMode == DC_IDX) && pcCU->getSlice()->getIsDepth() && pcCU->getSlice()->getPPS()->getDLT()->getUseDLTFlag(pcCU->getSlice()->getLayerIdInVps());
 
   if ( pcCU->getCbf( uiAbsPartIdx, TEXT_LUMA, uiTrDepth ) || useDltFlag )
 #else
-  if ( pcCU->getCbf( uiAbsPartIdx, TEXT_LUMA, uiTrDepth ) )
-#endif
-  {
-  //===== inverse transform =====
-  m_pcTrQuant->setQPforQuant  ( pcCU->getQP(0), TEXT_LUMA, pcCU->getSlice()->getSPS()->getQpBDOffsetY(), 0 );
-
-  Int scalingListType = (pcCU->isIntra(uiAbsPartIdx) ? 0 : 3) + g_eTTable[(Int)TEXT_LUMA];
-    assert(scalingListType < SCALING_LIST_NUM);
-  m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), TEXT_LUMA, pcCU->getLumaIntraDir( uiAbsPartIdx ), piResi, uiStride, pcCoeff, uiWidth, uiHeight, scalingListType, useTransformSkip );
-
-  
+  if (pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0)
+#endif
+  {
+    m_pcTrQuant->invTransformNxN( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO(psDebug) );
+  }
+  else
+  {
+    for (UInt y = 0; y < uiHeight; y++)
+    {
+      for (UInt x = 0; x < uiWidth; x++)
+      {
+        piResi[(y * uiStride) + x] = 0;
+      }
+    }
+  }
+
+#if DEBUG_STRING
+  if (psDebug)
+  {
+    ss << (*psDebug);
+  }
+#endif
+
   //===== reconstruction =====
-  Pel* pPred      = piPred;
-  Pel* pResi      = piResi;
-  Pel* pReco      = piReco;
-  Pel* pRecIPred  = piRecIPred;
+  const UInt uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride(compID);
+
+  const Bool useCrossComponentPrediction = isChroma(compID) && (pcCU->getCrossComponentPredictionAlpha(uiAbsPartIdx, compID) != 0);
+  const Pel* pResiLuma  = pcResiYuv->getAddr( COMPONENT_Y, uiAbsPartIdx );
+  const Int  strideLuma = pcResiYuv->getStride( COMPONENT_Y );
+
+        Pel* pPred      = piPred;
+        Pel* pResi      = piResi;
+        Pel* pReco      = pcRecoYuv->getAddr( compID, uiAbsPartIdx );
+        Pel* pRecIPred  = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx );
+
+
+#if DEBUG_STRING
+  const Bool bDebugPred=((DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
+  const Bool bDebugResi=((DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
+  const Bool bDebugReco=((DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
+  if (bDebugPred || bDebugResi || bDebugReco)
+  {
+    ss << "###: " << "CompID: " << compID << " pred mode (ch/fin): " << uiChPredMode << "/" << uiChFinalMode << " absPartIdx: " << rTu.GetAbsPartIdxTU() << std::endl;
+  }
+#endif
+
+  const Int clipbd = sps.getBitDepth(toChannelType(compID));
+#if O0043_BEST_EFFORT_DECODING
+  const Int bitDepthDelta = sps.getStreamBitDepth(toChannelType(compID)) - clipbd;
+#endif
+
+  if( useCrossComponentPrediction )
+  {
+    TComTrQuant::crossComponentPrediction( rTu, compID, pResiLuma, piResi, piResi, uiWidth, uiHeight, strideLuma, uiStride, uiStride, true );
+  }
+
   for( UInt uiY = 0; uiY < uiHeight; uiY++ )
   {
+#if DEBUG_STRING
+    if (bDebugPred || bDebugResi || bDebugReco)
+    {
+      ss << "###: ";
+    }
+
+    if (bDebugPred)
+    {
+      ss << " - pred: ";
+      for( UInt uiX = 0; uiX < uiWidth; uiX++ )
+      {
+        ss << pPred[ uiX ] << ", ";
+      }
+    }
+    if (bDebugResi)
+    {
+      ss << " - resi: ";
+    }
+#endif
+
     for( UInt uiX = 0; uiX < uiWidth; uiX++ )
     {
-      pReco    [ uiX ] = ClipY( pPred[ uiX ] + pResi[ uiX ] );
+#if DEBUG_STRING
+      if (bDebugResi)
+      {
+        ss << pResi[ uiX ] << ", ";
+      }
+#endif
+#if O0043_BEST_EFFORT_DECODING
+      pReco    [ uiX ] = ClipBD( rightShiftEvenRounding<Pel>(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta), clipbd );
+#else
+      pReco    [ uiX ] = ClipBD( pPred[ uiX ] + pResi[ uiX ], clipbd );
+#endif
       pRecIPred[ uiX ] = pReco[ uiX ];
     }
+#if DEBUG_STRING
+    if (bDebugReco)
+    {
+      ss << " - reco: ";
+      for( UInt uiX = 0; uiX < uiWidth; uiX++ )
+      {
+        ss << pReco[ uiX ] << ", ";
+      }
+    }
+
+    if (bDebugPred || bDebugResi || bDebugReco)
+    {
+      ss << "\n";
+    }
+#endif
     pPred     += uiStride;
     pResi     += uiStride;
@@ -1006,154 +1195,8 @@
   }
 }
-  else
-  {
-    //===== reconstruction =====
-    Pel* pPred      = piPred;
-    Pel* pReco      = piReco;
-    Pel* pRecIPred  = piRecIPred;
-    for ( Int y = 0; y < uiHeight; y++ )
-    {
-      for ( Int x = 0; x < uiWidth; x++ )
-      {
-        pReco    [ x ] = pPred[ x ];
-        pRecIPred[ x ] = pReco[ x ];
-      }
-      pPred     += uiStride;
-      pReco     += uiStride;
-      pRecIPred += uiRecIPredStride;
-    }
-  }
-}
-
-
-Void
-TDecCu::xIntraRecChromaBlk( TComDataCU* pcCU,
-                           UInt        uiTrDepth,
-                           UInt        uiAbsPartIdx,
-                           TComYuv*    pcRecoYuv,
-                           TComYuv*    pcPredYuv, 
-                           TComYuv*    pcResiYuv,
-                           UInt        uiChromaId )
-{
-  UInt uiFullDepth  = pcCU->getDepth( 0 ) + uiTrDepth;
-  UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> uiFullDepth ] + 2;
-
-  if( uiLog2TrSize == 2 )
-  {
-    assert( uiTrDepth > 0 );
-    uiTrDepth--;
-    UInt uiQPDiv = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth( 0 ) + uiTrDepth ) << 1 );
-    Bool bFirstQ = ( ( uiAbsPartIdx % uiQPDiv ) == 0 );
-    if( !bFirstQ )
-    {
-      return;
-    }
-  }
-
-  TextType  eText             = ( uiChromaId > 0 ? TEXT_CHROMA_V : TEXT_CHROMA_U );
-  UInt      uiWidth           = pcCU     ->getWidth   ( 0 ) >> ( uiTrDepth + 1 );
-  UInt      uiHeight          = pcCU     ->getHeight  ( 0 ) >> ( uiTrDepth + 1 );
-  UInt      uiStride          = pcRecoYuv->getCStride ();
-  Pel*      piReco            = ( uiChromaId > 0 ? pcRecoYuv->getCrAddr( uiAbsPartIdx ) : pcRecoYuv->getCbAddr( uiAbsPartIdx ) );
-  Pel*      piPred            = ( uiChromaId > 0 ? pcPredYuv->getCrAddr( uiAbsPartIdx ) : pcPredYuv->getCbAddr( uiAbsPartIdx ) );
-  Pel*      piResi            = ( uiChromaId > 0 ? pcResiYuv->getCrAddr( uiAbsPartIdx ) : pcResiYuv->getCbAddr( uiAbsPartIdx ) );
-
-  UInt      uiNumCoeffInc     = ( ( pcCU->getSlice()->getSPS()->getMaxCUWidth() * pcCU->getSlice()->getSPS()->getMaxCUHeight() ) >> ( pcCU->getSlice()->getSPS()->getMaxCUDepth() << 1 ) ) >> 2;
-  TCoeff*   pcCoeff           = ( uiChromaId > 0 ? pcCU->getCoeffCr() : pcCU->getCoeffCb() ) + ( uiNumCoeffInc * uiAbsPartIdx );
-
-  UInt      uiChromaPredMode  = pcCU->getChromaIntraDir( 0 );
-
-  UInt      uiZOrder          = pcCU->getZorderIdxInCU() + uiAbsPartIdx;
-  Pel*      piRecIPred        = ( uiChromaId > 0 ? pcCU->getPic()->getPicYuvRec()->getCrAddr( pcCU->getAddr(), uiZOrder ) : pcCU->getPic()->getPicYuvRec()->getCbAddr( pcCU->getAddr(), uiZOrder ) );
-  UInt      uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getCStride();
-  Bool      useTransformSkipChroma = pcCU->getTransformSkip(uiAbsPartIdx,eText);
-  //===== init availability pattern =====
-  Bool  bAboveAvail = false;
-  Bool  bLeftAvail  = false;
-  pcCU->getPattern()->initPattern         ( pcCU, uiTrDepth, uiAbsPartIdx );
-
-  pcCU->getPattern()->initAdiPatternChroma( pcCU, uiAbsPartIdx, uiTrDepth,
-    m_pcPrediction->getPredicBuf       (),
-    m_pcPrediction->getPredicBufWidth  (),
-    m_pcPrediction->getPredicBufHeight (),
-    bAboveAvail, bLeftAvail );
-  Int* pPatChroma   = ( uiChromaId > 0 ? pcCU->getPattern()->getAdiCrBuf( uiWidth, uiHeight, m_pcPrediction->getPredicBuf() ) : pcCU->getPattern()->getAdiCbBuf( uiWidth, uiHeight, m_pcPrediction->getPredicBuf() ) );
-
-  //===== get prediction signal =====
-  {
-    if( uiChromaPredMode == DM_CHROMA_IDX )
-    {
-      uiChromaPredMode = pcCU->getLumaIntraDir( 0 );
-#if H_3D_DIM
-      mapDepthModeToIntraDir( uiChromaPredMode );
-#endif
-    }
-    m_pcPrediction->predIntraChromaAng( pPatChroma, uiChromaPredMode, piPred, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );  
-  }
-
-  if ( pcCU->getCbf( uiAbsPartIdx, eText, uiTrDepth ) )
-  {
-    //===== inverse transform =====
-    Int curChromaQpOffset;
-    if(eText == TEXT_CHROMA_U)
-    {
-      curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCbQpOffset() + pcCU->getSlice()->getSliceQpDeltaCb();
-    }
-    else
-    {
-      curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr();
-    }
-    m_pcTrQuant->setQPforQuant  ( pcCU->getQP(0), eText, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset );
-
-    Int scalingListType = (pcCU->isIntra(uiAbsPartIdx) ? 0 : 3) + g_eTTable[(Int)eText];
-    assert(scalingListType < SCALING_LIST_NUM);
-    m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), eText, REG_DCT, piResi, uiStride, pcCoeff, uiWidth, uiHeight, scalingListType, useTransformSkipChroma );
-
-    //===== reconstruction =====
-    Pel* pPred      = piPred;
-    Pel* pResi      = piResi;
-    Pel* pReco      = piReco;
-    Pel* pRecIPred  = piRecIPred;
-    for( UInt uiY = 0; uiY < uiHeight; uiY++ )
-    {
-      for( UInt uiX = 0; uiX < uiWidth; uiX++ )
-      {
-        pReco    [ uiX ] = ClipC( pPred[ uiX ] + pResi[ uiX ] );
-        pRecIPred[ uiX ] = pReco[ uiX ];
-      }
-      pPred     += uiStride;
-      pResi     += uiStride;
-      pReco     += uiStride;
-      pRecIPred += uiRecIPredStride;
-    }
-  }
-  else
-  {
-    //===== reconstruction =====
-    Pel* pPred      = piPred;
-    Pel* pReco      = piReco;
-    Pel* pRecIPred  = piRecIPred;
-    for ( Int y = 0; y < uiHeight; y++ )
-    {
-      for ( Int x = 0; x < uiWidth; x++ )
-      {
-        pReco    [ x ] = pPred[ x ];
-        pRecIPred[ x ] = pReco[ x ];
-      }
-      pPred     += uiStride;
-      pReco     += uiStride;
-      pRecIPred += uiRecIPredStride;
-    }    
-  }
-}
-
 
 Void
 TDecCu::xReconIntraQT( TComDataCU* pcCU, UInt uiDepth )
 {
-  UInt  uiInitTrDepth = ( pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1 );
-  UInt  uiNumPart     = pcCU->getNumPartitions();
-  UInt  uiNumQParts   = pcCU->getTotalNumPart() >> 2;
-  
   if (pcCU->getIPCMFlag(0))
   {
@@ -1161,150 +1204,157 @@
     return;
   }
-
-  for( UInt uiPU = 0; uiPU < uiNumPart; uiPU++ )
-  {
-    xIntraLumaRecQT( pcCU, uiInitTrDepth, uiPU * uiNumQParts, m_ppcYuvReco[uiDepth], m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth] );
-  }  
-
-  for( UInt uiPU = 0; uiPU < uiNumPart; uiPU++ )
-  {
-    xIntraChromaRecQT( pcCU, uiInitTrDepth, uiPU * uiNumQParts, m_ppcYuvReco[uiDepth], m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth] );
-  }
-
-}
-
-#if H_3D_DIM_SDC
+  const UInt numChType = pcCU->getPic()->getChromaFormat()!=CHROMA_400 ? 2 : 1;
+  for (UInt chType=CHANNEL_TYPE_LUMA; chType<numChType; chType++)
+  {
+    const ChannelType chanType=ChannelType(chType);
+    const Bool NxNPUHas4Parts = ::isChroma(chanType) ? enable4ChromaPUsInIntraNxNCU(pcCU->getPic()->getChromaFormat()) : true;
+    const UInt uiInitTrDepth = ( pcCU->getPartitionSize(0) != SIZE_2Nx2N && NxNPUHas4Parts ? 1 : 0 );
+
+    TComTURecurse tuRecurseCU(pcCU, 0);
+    TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT);
+
+    do
+    {
+      xIntraRecQT( m_ppcYuvReco[uiDepth], m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], chanType, tuRecurseWithPU );
+    } while (tuRecurseWithPU.nextSection(tuRecurseCU));
+  }
+}
+
+#if NH_3D_SDC_INTRA
 Void TDecCu::xReconIntraSDC( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
 {
-  UInt uiWidth        = pcCU->getWidth  ( 0 );
-  UInt uiHeight       = pcCU->getHeight ( 0 );
-  TComWedgelet* dmm4SegmentationOrg = new TComWedgelet( uiWidth, uiHeight );
-  UInt numParts = 1;
-  UInt sdcDepth    = 0;
   TComYuv* pcRecoYuv  = m_ppcYuvReco[uiDepth];
   TComYuv* pcPredYuv  = m_ppcYuvReco[uiDepth];
   TComYuv* pcResiYuv  = m_ppcYuvResi[uiDepth];
 
-  UInt    uiStride = 0;
-  Pel*    piReco;
-  Pel*    piPred;
-  Pel*    piResi;
-
-  UInt    uiZOrder;        
-  Pel*    piRecIPred;      
-  UInt    uiRecIPredStride;
-
-  UInt    uiLumaPredMode = 0;  
-
-  if ((uiWidth >> pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize()) > 1)
-  {
-    numParts = uiWidth * uiWidth >> (2 * pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize());
-    sdcDepth = g_aucConvertToBit[uiWidth] + 2 - pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize();
-    uiWidth = uiHeight = (1 << pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize());
-  }
-
-  for ( Int i = 0; i < numParts; i++ )
-  {
-    uiStride    = pcRecoYuv->getStride  ();
-    piReco      = pcRecoYuv->getLumaAddr( uiAbsPartIdx );
-    piPred      = pcPredYuv->getLumaAddr( uiAbsPartIdx );
-    piResi      = pcResiYuv->getLumaAddr( uiAbsPartIdx );
-
-    uiZOrder          = pcCU->getZorderIdxInCU() + uiAbsPartIdx;
-    piRecIPred        = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), uiZOrder );
-    uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride  ();
-
-    uiLumaPredMode    = pcCU->getLumaIntraDir     ( uiAbsPartIdx );
-
-    AOF( uiWidth == uiHeight );
-
-    //===== init availability pattern =====
-    Bool  bAboveAvail = false;
-    Bool  bLeftAvail  = false;
-
-    pcCU->getPattern()->initPattern   ( pcCU, sdcDepth, uiAbsPartIdx );
-    pcCU->getPattern()->initAdiPattern( pcCU, uiAbsPartIdx, sdcDepth, m_pcPrediction->getPredicBuf(), m_pcPrediction->getPredicBufWidth(), m_pcPrediction->getPredicBufHeight(), bAboveAvail, bLeftAvail );
-
-    TComWedgelet* dmm4Segmentation = new TComWedgelet( uiWidth, uiHeight );
-    //===== get prediction signal =====
-    if( isDimMode( uiLumaPredMode ) )
-    {
-      m_pcPrediction->predIntraLumaDepth( pcCU, uiAbsPartIdx, uiLumaPredMode, piPred, uiStride, uiWidth, uiHeight, false, dmm4Segmentation  );
-      Bool* dmm4PatternSplit = dmm4Segmentation->getPattern();
-      Bool* dmm4PatternOrg = dmm4SegmentationOrg->getPattern();
-      for( UInt k = 0; k < (uiWidth*uiHeight); k++ ) 
-      { 
-        dmm4PatternOrg[k+(uiAbsPartIdx<<4)] = dmm4PatternSplit[k];
-      }
-    }
-    else
-    {
-      m_pcPrediction->predIntraLumaAng( pcCU->getPattern(), uiLumaPredMode, piPred, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );
-    }
-
-    if ( numParts > 1 )
-    {
-      for( UInt uiY = 0; uiY < uiHeight; uiY++ )
-      {
-        for( UInt uiX = 0; uiX < uiWidth; uiX++ )
-        {
-          piReco        [ uiX ] = ClipY( piPred[ uiX ] );
-          piRecIPred    [ uiX ] = piReco[ uiX ];
-        }
-        piPred     += uiStride;
-        piReco     += uiStride;
-        piRecIPred += uiRecIPredStride;
-      }
-    }
-    uiAbsPartIdx += ( (uiWidth * uiWidth) >> 4 );
-    dmm4Segmentation->destroy(); delete dmm4Segmentation;
-  }
-  uiAbsPartIdx = 0;
-  
-  if ( numParts > 1 )
-  {
-    uiWidth = pcCU->getWidth( 0 );
-    uiHeight = pcCU->getHeight( 0 );
-  }
-  piReco      = pcRecoYuv->getLumaAddr( uiAbsPartIdx );
-  piPred      = pcPredYuv->getLumaAddr( uiAbsPartIdx );
-  piResi      = pcResiYuv->getLumaAddr( uiAbsPartIdx );
-  uiZOrder          = pcCU->getZorderIdxInCU() + uiAbsPartIdx;
-  piRecIPred        = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), uiZOrder );
-  uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride  ();
-  // number of segments depends on prediction mode
-  UInt uiNumSegments = 1;
+  UInt uiWidth        = pcCU->getWidth ( 0 );
+  UInt uiHeight       = pcCU->getHeight( 0 );
+  UInt uiLumaPredMode = pcCU->getIntraDir( CHANNEL_TYPE_LUMA, uiAbsPartIdx );
+  const Int bitDepthY = pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
+  const TComSPS     &sps    = *(pcCU->getSlice()->getSPS());
+  const ChromaFormat chFmt  = pcCU->getPic()->getChromaFormat();
+
+  UInt sdcDepth = 0;
+  UInt uiStride;
+  Pel* piReco;
+  Pel* piPred;
+  Pel* piResi;
+
+  Pel* piRecIPred;
+  UInt uiRecIPredStride;
+  
+  Pel apDCPredValues[2];
+  UInt uiNumSegments;
+
   Bool* pbMask = NULL;
   UInt uiMaskStride = 0;
-  
-  if( getDimType( uiLumaPredMode ) == DMM1_IDX )
-  {
-    Int uiTabIdx = pcCU->getDmmWedgeTabIdx(DMM1_IDX, uiAbsPartIdx);
-
-    WedgeList* pacWedgeList  = pcCU->isDMM1UpscaleMode(uiWidth) ? &g_dmmWedgeLists[(g_aucConvertToBit[pcCU->getDMM1BasePatternWidth(uiWidth)])] :  &g_dmmWedgeLists[(g_aucConvertToBit[uiWidth])];
-    TComWedgelet* pcWedgelet = &(pacWedgeList->at( uiTabIdx ));
-
-    uiNumSegments = 2;
-
-    pbMask       = pcCU->isDMM1UpscaleMode( uiWidth ) ? pcWedgelet->getScaledPattern(uiWidth) : pcWedgelet->getPattern();
-    uiMaskStride = pcCU->isDMM1UpscaleMode( uiWidth ) ? uiWidth : pcWedgelet->getStride();
-  }
-  if( getDimType( uiLumaPredMode ) == DMM4_IDX )
-  {
-    uiNumSegments = 2;
-    pbMask  = dmm4SegmentationOrg->getPattern();
-    uiMaskStride = dmm4SegmentationOrg->getStride();
-  }
-  // get DC prediction for each segment
-  Pel apDCPredValues[2];
-  if ( getDimType( uiLumaPredMode ) == DMM1_IDX || getDimType( uiLumaPredMode ) == DMM4_IDX )
-  {
-    apDCPredValues[0] = pcCU->getDmmPredictor( 0 );
-    apDCPredValues[1] = pcCU->getDmmPredictor( 1 );
-  }
-  else
-  {
-    m_pcPrediction->analyzeSegmentsSDC(piPred, uiStride, uiWidth, apDCPredValues, uiNumSegments, pbMask, uiMaskStride, uiLumaPredMode);
-  }
+
+#if NH_3D_DMM
+  if( isDmmMode( uiLumaPredMode ) )
+  {
+    assert( uiWidth == uiHeight  );
+    assert( uiWidth >= DMM_MIN_SIZE && uiWidth <= DMM_MAX_SIZE );
+    assert( !((uiWidth >> pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize()) > 1) );
+
+    uiNumSegments     = 2;
+
+    uiStride          = pcRecoYuv->getStride( COMPONENT_Y );
+    piReco            = pcRecoYuv->getAddr  ( COMPONENT_Y, uiAbsPartIdx );
+    piPred            = pcPredYuv->getAddr  ( COMPONENT_Y, uiAbsPartIdx );
+    piResi            = pcResiYuv->getAddr  ( COMPONENT_Y, uiAbsPartIdx );
+
+    piRecIPred        = pcCU->getPic()->getPicYuvRec()->getAddr  ( COMPONENT_Y, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx );
+    uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride( COMPONENT_Y );
+
+    //===== init availability pattern =====
+    TComTURecurse tuRecurseCU(pcCU, 0);
+    TComTURecurse tuRecurseWithPU(tuRecurseCU, false, TComTU::DONT_SPLIT);
+
+    m_pcPrediction->initIntraPatternChType( tuRecurseWithPU, COMPONENT_Y, false DEBUG_STRING_PASS_INTO(sTemp) );
+
+    // get partition
+    pbMask       = new Bool[ uiWidth*uiHeight ];
+    uiMaskStride = uiWidth;
+    switch( getDmmType( uiLumaPredMode ) )
+    {
+    case( DMM1_IDX ): { (getWedgeListScaled( uiWidth )->at( pcCU->getDmm1WedgeTabIdx( uiAbsPartIdx ) )).getPatternScaledCopy( uiWidth, pbMask ); } break;
+    case( DMM4_IDX ): { m_pcPrediction->predContourFromTex( pcCU, uiAbsPartIdx, uiWidth, uiHeight, pbMask );                                     } break;
+    default: assert(0);
+    }
+
+    // get predicted partition values
+    Pel predDC1 = 0, predDC2 = 0;
+    m_pcPrediction->predBiSegDCs( pcCU, uiAbsPartIdx, uiWidth, uiHeight, pbMask, uiMaskStride, predDC1, predDC2 );
+
+    // set prediction signal
+    Pel* pDst = piPred;
+    m_pcPrediction->assignBiSegDCs( pDst, uiStride, pbMask, uiMaskStride, predDC1, predDC2 );
+    apDCPredValues[0] = predDC1;
+    apDCPredValues[1] = predDC2;
+  }
+  else // regular HEVC intra modes
+  {
+#endif
+    uiNumSegments = 1;
+
+    if( ( uiWidth >> pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) > 1 )
+    {
+      sdcDepth = g_aucConvertToBit[uiWidth] + 2 - pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize();
+    }
+    
+    //===== loop over partitions =====
+    TComTURecurse tuRecurseCU(pcCU, 0);
+    TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (sdcDepth==0)?TComTU::DONT_SPLIT:TComTU::QUAD_SPLIT);
+
+    do
+    {
+      const TComRectangle &puRect = tuRecurseWithPU.getRect(COMPONENT_Y);
+      const UInt uiAbsPartIdxTU = tuRecurseWithPU.GetAbsPartIdxTU();
+      
+      Pel* piPredTU       = pcPredYuv->getAddr  ( COMPONENT_Y, uiAbsPartIdxTU );
+      UInt uiStrideTU     = pcPredYuv->getStride( COMPONENT_Y );
+      
+      Pel* piRecIPredTU   = pcCU->getPic()->getPicYuvRec()->getAddr( COMPONENT_Y, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdxTU );
+      UInt uiRecIPredStrideTU  = pcCU->getPic()->getPicYuvRec()->getStride(COMPONENT_Y);
+      
+      const Bool bUseFilter = TComPrediction::filteringIntraReferenceSamples(COMPONENT_Y, uiLumaPredMode, puRect.width, puRect.height, chFmt, sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag());
+      
+      //===== init pattern for luma prediction =====
+      
+      m_pcPrediction->initIntraPatternChType( tuRecurseWithPU, COMPONENT_Y, bUseFilter  DEBUG_STRING_PASS_INTO(sTemp) );
+      
+      m_pcPrediction->predIntraAng( COMPONENT_Y, uiLumaPredMode, NULL, uiStrideTU, piPredTU, uiStrideTU, tuRecurseWithPU, bUseFilter );
+      
+      // copy for prediction of next part
+      for( UInt uiY = 0; uiY < puRect.height; uiY++ )
+      {
+        for( UInt uiX = 0; uiX < puRect.width; uiX++ )
+        {
+          piPredTU      [ uiX ] = ClipBD( piPredTU[ uiX ], bitDepthY );
+          piRecIPredTU  [ uiX ] = piPredTU[ uiX ];
+        }
+        piPredTU     += uiStrideTU;
+        piRecIPredTU += uiRecIPredStrideTU;
+      }
+      
+      
+    } while (tuRecurseWithPU.nextSection(tuRecurseCU));
+
+    // reset to full block
+    uiWidth  = pcCU->getWidth( 0 );
+    uiHeight = pcCU->getHeight( 0 );
+
+    uiStride          = pcRecoYuv->getStride( COMPONENT_Y );
+    piReco            = pcRecoYuv->getAddr  ( COMPONENT_Y, uiAbsPartIdx );
+    piPred            = pcPredYuv->getAddr  ( COMPONENT_Y, uiAbsPartIdx );
+    piResi            = pcResiYuv->getAddr  ( COMPONENT_Y, uiAbsPartIdx );
+    
+    piRecIPred        = pcCU->getPic()->getPicYuvRec()->getAddr  ( COMPONENT_Y, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx );
+    uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride( COMPONENT_Y );
+
+    m_pcPrediction->predConstantSDC( piPred, uiStride, uiWidth, apDCPredValues[0] ); apDCPredValues[1] = 0;
+#if NH_3D_DMM
+  }
+#endif
   
   // reconstruct residual based on mask + DC residuals
@@ -1312,5 +1362,5 @@
   for( UInt uiSegment = 0; uiSegment < uiNumSegments; uiSegment++ )
   {
-#if H_3D_DIM_DLT
+#if NH_3D_DLT
     Pel   pPredIdx    = pcCU->getSlice()->getPPS()->getDLT()->depthValue2idx( pcCU->getSlice()->getLayerIdInVps(), apDCPredValues[uiSegment] );
     Pel   pResiIdx    = pcCU->getSDCSegmentDCOffset(uiSegment, uiAbsPartIdx);
@@ -1339,5 +1389,5 @@
       Pel pResiDC = apDCResiValues[ucSegment];
       
-      pReco    [ uiX ] = ClipY( pPred[ uiX ] + pResiDC );
+      pReco    [ uiX ] = ClipBD( pPred[ uiX ] + pResiDC, bitDepthY );
       pRecIPred[ uiX ] = pReco[ uiX ];
     }
@@ -1349,8 +1399,8 @@
   }
   
-  // clear UV
-  UInt  uiStrideC     = pcPredYuv->getCStride();
-  Pel   *pRecCb       = pcPredYuv->getCbAddr();
-  Pel   *pRecCr       = pcPredYuv->getCrAddr();
+  // clear chroma
+  UInt  uiStrideC     = pcPredYuv->getStride( COMPONENT_Cb );
+  Pel   *pRecCb       = pcPredYuv->getAddr  ( COMPONENT_Cb, uiAbsPartIdx );
+  Pel   *pRecCr       = pcPredYuv->getAddr  ( COMPONENT_Cr, uiAbsPartIdx );
   
   for (Int y=0; y<uiHeight/2; y++)
@@ -1365,74 +1415,54 @@
     pRecCr += uiStrideC;
   }
-  dmm4SegmentationOrg->destroy(); delete dmm4SegmentationOrg;
-}
-#endif
-
-/** Function for deriving recontructed PU/CU Luma sample with QTree structure
- * \param pcCU pointer of current CU
- * \param uiTrDepth current tranform split depth
- * \param uiAbsPartIdx  part index
+#if NH_3D_DMM
+  if( pbMask ) { delete[] pbMask; }
+#endif
+}
+#endif
+
+
+/** Function for deriving reconstructed PU/CU chroma samples with QTree structure
  * \param pcRecoYuv pointer to reconstructed sample arrays
  * \param pcPredYuv pointer to prediction sample arrays
  * \param pcResiYuv pointer to residue sample arrays
- * 
- \ This function dervies recontructed PU/CU Luma sample with recursive QTree structure
+ * \param chType    texture channel type (luma/chroma)
+ * \param rTu       reference to transform data
+ *
+ \ This function derives reconstructed PU/CU chroma samples with QTree recursive structure
  */
+
 Void
-TDecCu::xIntraLumaRecQT( TComDataCU* pcCU,
-                     UInt        uiTrDepth,
-                     UInt        uiAbsPartIdx,
-                     TComYuv*    pcRecoYuv,
-                     TComYuv*    pcPredYuv, 
-                     TComYuv*    pcResiYuv )
-{
-  UInt uiFullDepth  = pcCU->getDepth(0) + uiTrDepth;
+TDecCu::xIntraRecQT(TComYuv*    pcRecoYuv,
+                    TComYuv*    pcPredYuv,
+                    TComYuv*    pcResiYuv,
+                    const ChannelType chType,
+                    TComTU     &rTu)
+{
+  UInt uiTrDepth    = rTu.GetTransformDepthRel();
+  TComDataCU *pcCU  = rTu.getCU();
+  UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU();
   UInt uiTrMode     = pcCU->getTransformIdx( uiAbsPartIdx );
   if( uiTrMode == uiTrDepth )
   {
-    xIntraRecLumaBlk  ( pcCU, uiTrDepth, uiAbsPartIdx, pcRecoYuv, pcPredYuv, pcResiYuv );
+    if (isLuma(chType))
+    {
+      xIntraRecBlk( pcRecoYuv, pcPredYuv, pcResiYuv, COMPONENT_Y,  rTu );
+    }
+    else
+    {
+      const UInt numValidComp=getNumberValidComponents(rTu.GetChromaFormat());
+      for(UInt compID=COMPONENT_Cb; compID<numValidComp; compID++)
+      {
+        xIntraRecBlk( pcRecoYuv, pcPredYuv, pcResiYuv, ComponentID(compID), rTu );
+      }
+    }
   }
   else
   {
-    UInt uiNumQPart  = pcCU->getPic()->getNumPartInCU() >> ( ( uiFullDepth + 1 ) << 1 );
-    for( UInt uiPart = 0; uiPart < 4; uiPart++ )
-    {
-      xIntraLumaRecQT( pcCU, uiTrDepth + 1, uiAbsPartIdx + uiPart * uiNumQPart, pcRecoYuv, pcPredYuv, pcResiYuv );
-    }
-  }
-}
-
-/** Function for deriving recontructed PU/CU chroma samples with QTree structure
- * \param pcCU pointer of current CU
- * \param uiTrDepth current tranform split depth
- * \param uiAbsPartIdx  part index
- * \param pcRecoYuv pointer to reconstructed sample arrays
- * \param pcPredYuv pointer to prediction sample arrays
- * \param pcResiYuv pointer to residue sample arrays
- * 
- \ This function dervies recontructed PU/CU chroma samples with QTree recursive structure
- */
-Void
-TDecCu::xIntraChromaRecQT( TComDataCU* pcCU,
-                     UInt        uiTrDepth,
-                     UInt        uiAbsPartIdx,
-                     TComYuv*    pcRecoYuv,
-                     TComYuv*    pcPredYuv, 
-                     TComYuv*    pcResiYuv )
-{
-  UInt uiFullDepth  = pcCU->getDepth(0) + uiTrDepth;
-  UInt uiTrMode     = pcCU->getTransformIdx( uiAbsPartIdx );
-  if( uiTrMode == uiTrDepth )
-  {
-    xIntraRecChromaBlk( pcCU, uiTrDepth, uiAbsPartIdx, pcRecoYuv, pcPredYuv, pcResiYuv, 0 );
-    xIntraRecChromaBlk( pcCU, uiTrDepth, uiAbsPartIdx, pcRecoYuv, pcPredYuv, pcResiYuv, 1 );
-  }
-  else
-  {
-    UInt uiNumQPart  = pcCU->getPic()->getNumPartInCU() >> ( ( uiFullDepth + 1 ) << 1 );
-    for( UInt uiPart = 0; uiPart < 4; uiPart++ )
-    {
-      xIntraChromaRecQT( pcCU, uiTrDepth + 1, uiAbsPartIdx + uiPart * uiNumQPart, pcRecoYuv, pcPredYuv, pcResiYuv );
-    }
+    TComTURecurse tuRecurseChild(rTu, false);
+    do
+    {
+      xIntraRecQT( pcRecoYuv, pcPredYuv, pcResiYuv, chType, tuRecurseChild );
+    } while (tuRecurseChild.nextSection(rTu));
   }
 }
@@ -1440,42 +1470,25 @@
 Void TDecCu::xCopyToPic( TComDataCU* pcCU, TComPic* pcPic, UInt uiZorderIdx, UInt uiDepth )
 {
-  UInt uiCUAddr = pcCU->getAddr();
-  
-  m_ppcYuvReco[uiDepth]->copyToPicYuv  ( pcPic->getPicYuvRec (), uiCUAddr, uiZorderIdx );
-  
+  UInt uiCtuRsAddr = pcCU->getCtuRsAddr();
+
+  m_ppcYuvReco[uiDepth]->copyToPicYuv  ( pcPic->getPicYuvRec (), uiCtuRsAddr, uiZorderIdx );
+
   return;
 }
 
-Void TDecCu::xDecodeInterTexture ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
-{
-  UInt    uiWidth    = pcCU->getWidth ( uiAbsPartIdx );
-  UInt    uiHeight   = pcCU->getHeight( uiAbsPartIdx );
-  TCoeff* piCoeff;
-  
-  Pel*    pResi;
-  UInt    trMode = pcCU->getTransformIdx( uiAbsPartIdx );
-  
-  // Y
-  piCoeff = pcCU->getCoeffY();
-  pResi = m_ppcYuvResi[uiDepth]->getLumaAddr();
-
-  m_pcTrQuant->setQPforQuant( pcCU->getQP( uiAbsPartIdx ), TEXT_LUMA, pcCU->getSlice()->getSPS()->getQpBDOffsetY(), 0 );
-
-  m_pcTrQuant->invRecurTransformNxN ( pcCU, 0, TEXT_LUMA, pResi, 0, m_ppcYuvResi[uiDepth]->getStride(), uiWidth, uiHeight, trMode, 0, piCoeff );
-  
-  // Cb and Cr
-  Int curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCbQpOffset() + pcCU->getSlice()->getSliceQpDeltaCb();
-  m_pcTrQuant->setQPforQuant( pcCU->getQP( uiAbsPartIdx ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset );
-
-  uiWidth  >>= 1;
-  uiHeight >>= 1;
-  piCoeff = pcCU->getCoeffCb(); pResi = m_ppcYuvResi[uiDepth]->getCbAddr();
-  m_pcTrQuant->invRecurTransformNxN ( pcCU, 0, TEXT_CHROMA_U, pResi, 0, m_ppcYuvResi[uiDepth]->getCStride(), uiWidth, uiHeight, trMode, 0, piCoeff );
-
-  curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr();
-  m_pcTrQuant->setQPforQuant( pcCU->getQP( uiAbsPartIdx ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset );
-
-  piCoeff = pcCU->getCoeffCr(); pResi = m_ppcYuvResi[uiDepth]->getCrAddr();
-  m_pcTrQuant->invRecurTransformNxN ( pcCU, 0, TEXT_CHROMA_V, pResi, 0, m_ppcYuvResi[uiDepth]->getCStride(), uiWidth, uiHeight, trMode, 0, piCoeff );
+Void TDecCu::xDecodeInterTexture ( TComDataCU* pcCU, UInt uiDepth )
+{
+
+  TComTURecurse tuRecur(pcCU, 0, uiDepth);
+
+  for(UInt ch=0; ch<pcCU->getPic()->getNumberValidComponents(); ch++)
+  {
+    const ComponentID compID=ComponentID(ch);
+    DEBUG_STRING_OUTPUT(std::cout, debug_reorder_data_inter_token[compID])
+
+    m_pcTrQuant->invRecurTransformNxN ( compID, m_ppcYuvResi[uiDepth], tuRecur );
+  }
+
+  DEBUG_STRING_OUTPUT(std::cout, debug_reorder_data_inter_token[MAX_NUM_COMPONENT])
 }
 
@@ -1488,38 +1501,17 @@
  * \param uiWidth CU width
  * \param uiHeight CU height
- * \param ttText texture component type
+ * \param compID colour component ID
  * \returns Void
  */
-Void TDecCu::xDecodePCMTexture( TComDataCU* pcCU, UInt uiPartIdx, Pel *piPCM, Pel* piReco, UInt uiStride, UInt uiWidth, UInt uiHeight, TextType ttText)
-{
-  UInt uiX, uiY;
-  Pel* piPicReco;
-  UInt uiPicStride;
-  UInt uiPcmLeftShiftBit; 
-
-  if( ttText == TEXT_LUMA )
-  {
-    uiPicStride   = pcCU->getPic()->getPicYuvRec()->getStride();
-    piPicReco = pcCU->getPic()->getPicYuvRec()->getLumaAddr(pcCU->getAddr(), pcCU->getZorderIdxInCU()+uiPartIdx);
-    uiPcmLeftShiftBit = g_bitDepthY - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
-  }
-  else
-  {
-    uiPicStride = pcCU->getPic()->getPicYuvRec()->getCStride();
-
-    if( ttText == TEXT_CHROMA_U )
-    {
-      piPicReco = pcCU->getPic()->getPicYuvRec()->getCbAddr(pcCU->getAddr(), pcCU->getZorderIdxInCU()+uiPartIdx);
-    }
-    else
-    {
-      piPicReco = pcCU->getPic()->getPicYuvRec()->getCrAddr(pcCU->getAddr(), pcCU->getZorderIdxInCU()+uiPartIdx);
-    }
-    uiPcmLeftShiftBit = g_bitDepthC - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
-  }
-
-  for( uiY = 0; uiY < uiHeight; uiY++ )
-  {
-    for( uiX = 0; uiX < uiWidth; uiX++ )
+Void TDecCu::xDecodePCMTexture( TComDataCU* pcCU, const UInt uiPartIdx, const Pel *piPCM, Pel* piReco, const UInt uiStride, const UInt uiWidth, const UInt uiHeight, const ComponentID compID)
+{
+        Pel* piPicReco         = pcCU->getPic()->getPicYuvRec()->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu()+uiPartIdx);
+  const UInt uiPicStride       = pcCU->getPic()->getPicYuvRec()->getStride(compID);
+  const TComSPS &sps           = *(pcCU->getSlice()->getSPS());
+  const UInt uiPcmLeftShiftBit = sps.getBitDepth(toChannelType(compID)) - sps.getPCMBitDepth(toChannelType(compID));
+
+  for(UInt uiY = 0; uiY < uiHeight; uiY++ )
+  {
+    for(UInt uiX = 0; uiX < uiWidth; uiX++ )
     {
       piReco[uiX] = (piPCM[uiX] << uiPcmLeftShiftBit);
@@ -1539,80 +1531,52 @@
 Void TDecCu::xReconPCM( TComDataCU* pcCU, UInt uiDepth )
 {
-  // Luma
-  UInt uiWidth  = (g_uiMaxCUWidth >> uiDepth);
-  UInt uiHeight = (g_uiMaxCUHeight >> uiDepth);
-
-  Pel* piPcmY = pcCU->getPCMSampleY();
-  Pel* piRecoY = m_ppcYuvReco[uiDepth]->getLumaAddr(0, uiWidth);
-
-  UInt uiStride = m_ppcYuvResi[uiDepth]->getStride();
-
-  xDecodePCMTexture( pcCU, 0, piPcmY, piRecoY, uiStride, uiWidth, uiHeight, TEXT_LUMA);
-
-  // Cb and Cr
-  UInt uiCWidth  = (uiWidth>>1);
-  UInt uiCHeight = (uiHeight>>1);
-
-  Pel* piPcmCb = pcCU->getPCMSampleCb();
-  Pel* piPcmCr = pcCU->getPCMSampleCr();
-  Pel* pRecoCb = m_ppcYuvReco[uiDepth]->getCbAddr();
-  Pel* pRecoCr = m_ppcYuvReco[uiDepth]->getCrAddr();
-
-  UInt uiCStride = m_ppcYuvReco[uiDepth]->getCStride();
-
-  xDecodePCMTexture( pcCU, 0, piPcmCb, pRecoCb, uiCStride, uiCWidth, uiCHeight, TEXT_CHROMA_U);
-  xDecodePCMTexture( pcCU, 0, piPcmCr, pRecoCr, uiCStride, uiCWidth, uiCHeight, TEXT_CHROMA_V);
-}
-
-/** Function for filling the PCM buffer of a CU using its reconstructed sample array 
- * \param pcCU pointer to current CU
- * \param uiDepth CU Depth
- * \returns Void
+  const UInt maxCuWidth     = pcCU->getSlice()->getSPS()->getMaxCUWidth();
+  const UInt maxCuHeight    = pcCU->getSlice()->getSPS()->getMaxCUHeight();
+  for (UInt ch=0; ch < pcCU->getPic()->getNumberValidComponents(); ch++)
+  {
+    const ComponentID compID = ComponentID(ch);
+    const UInt width  = (maxCuWidth >>(uiDepth+m_ppcYuvResi[uiDepth]->getComponentScaleX(compID)));
+    const UInt height = (maxCuHeight>>(uiDepth+m_ppcYuvResi[uiDepth]->getComponentScaleY(compID)));
+    const UInt stride = m_ppcYuvResi[uiDepth]->getStride(compID);
+    Pel * pPCMChannel = pcCU->getPCMSample(compID);
+    Pel * pRecChannel = m_ppcYuvReco[uiDepth]->getAddr(compID);
+    xDecodePCMTexture( pcCU, 0, pPCMChannel, pRecChannel, stride, width, height, compID );
+  }
+}
+
+/** Function for filling the PCM buffer of a CU using its reconstructed sample array
+ * \param pCU   pointer to current CU
+ * \param depth CU Depth
  */
 Void TDecCu::xFillPCMBuffer(TComDataCU* pCU, UInt depth)
 {
-  // Luma
-  UInt width  = (g_uiMaxCUWidth >> depth);
-  UInt height = (g_uiMaxCUHeight >> depth);
-
-  Pel* pPcmY = pCU->getPCMSampleY();
-  Pel* pRecoY = m_ppcYuvReco[depth]->getLumaAddr(0, width);
-
-  UInt stride = m_ppcYuvReco[depth]->getStride();
-
-  for(Int y = 0; y < height; y++ )
-  {
-    for(Int x = 0; x < width; x++ )
-    {
-      pPcmY[x] = pRecoY[x];
-    }
-    pPcmY += width;
-    pRecoY += stride;
-  }
-
-  // Cb and Cr
-  UInt widthC  = (width>>1);
-  UInt heightC = (height>>1);
-
-  Pel* pPcmCb = pCU->getPCMSampleCb();
-  Pel* pPcmCr = pCU->getPCMSampleCr();
-  Pel* pRecoCb = m_ppcYuvReco[depth]->getCbAddr();
-  Pel* pRecoCr = m_ppcYuvReco[depth]->getCrAddr();
-
-  UInt strideC = m_ppcYuvReco[depth]->getCStride();
-
-  for(Int y = 0; y < heightC; y++ )
-  {
-    for(Int x = 0; x < widthC; x++ )
-    {
-      pPcmCb[x] = pRecoCb[x];
-      pPcmCr[x] = pRecoCr[x];
-    }
-    pPcmCr += widthC;
-    pPcmCb += widthC;
-    pRecoCb += strideC;
-    pRecoCr += strideC;
-  }
-
+  const ChromaFormat format = pCU->getPic()->getChromaFormat();
+  const UInt numValidComp   = getNumberValidComponents(format);
+  const UInt maxCuWidth     = pCU->getSlice()->getSPS()->getMaxCUWidth();
+  const UInt maxCuHeight    = pCU->getSlice()->getSPS()->getMaxCUHeight();
+
+  for (UInt componentIndex = 0; componentIndex < numValidComp; componentIndex++)
+  {
+    const ComponentID component = ComponentID(componentIndex);
+
+    const UInt width  = maxCuWidth  >> (depth + getComponentScaleX(component, format));
+    const UInt height = maxCuHeight >> (depth + getComponentScaleY(component, format));
+
+    Pel *source      = m_ppcYuvReco[depth]->getAddr(component, 0, width);
+    Pel *destination = pCU->getPCMSample(component);
+
+    const UInt sourceStride = m_ppcYuvReco[depth]->getStride(component);
+
+    for (Int line = 0; line < height; line++)
+    {
+      for (Int column = 0; column < width; column++)
+      {
+        destination[column] = source[column];
+      }
+
+      source      += sourceStride;
+      destination += width;
+    }
+  }
 }
 
