shithub: openh264

Download patch

ref: a45c661525edea3c001a7314390c91092b43367d
parent: 01fd220ef9f9c0859d02e35ec7f56cc5596dd137
author: zhuiling <[email protected]>
date: Wed Jan 21 09:07:32 EST 2015

to support different chroma qp

fix travis ci error

--- a/codec/common/inc/deblocking_common.h
+++ b/codec/common/inc/deblocking_common.h
@@ -15,6 +15,14 @@
                           int8_t* pTc);
 void DeblockChromaEq4H_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride, int32_t iAlpha, int32_t iBeta);
 
+void DeblockChromaLt4V2_c (uint8_t* pPixCbCr, int32_t iStride, int32_t iAlpha, int32_t iBeta,
+                          int8_t* pTc);
+void DeblockChromaEq4V2_c (uint8_t* pPixCbCr, int32_t iStride, int32_t iAlpha, int32_t iBeta);
+
+void DeblockChromaLt4H2_c (uint8_t* pPixCbCr, int32_t iStride, int32_t iAlpha, int32_t iBeta,
+                          int8_t* pTc);
+void DeblockChromaEq4H2_c (uint8_t* pPixCbCr,int32_t iStride, int32_t iAlpha, int32_t iBeta);
+
 void WelsNonZeroCount_c (int8_t* pNonZeroCount);
 
 #if defined(__cplusplus)
--- a/codec/common/src/deblocking_common.cpp
+++ b/codec/common/src/deblocking_common.cpp
@@ -1,5 +1,6 @@
 #include "deblocking_common.h"
 #include "macros.h"
+
 //  C code only
 void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta,
                        int8_t* pTc) {
@@ -178,6 +179,70 @@
 }
 void DeblockChromaEq4H_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride, int32_t iAlpha, int32_t iBeta) {
   DeblockChromaEq4_c (pPixCb, pPixCr, 1, iStride, iAlpha, iBeta);
+}
+
+void DeblockChromaLt42_c (uint8_t* pPixCbCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
+                          int32_t iBeta, int8_t* pTc) {
+  int32_t p0, p1, q0, q1, iDeta;
+  bool bDetaP0Q0, bDetaP1P0, bDetaQ1Q0;
+
+  for (int32_t i = 0; i < 8; i++) {
+    int32_t iTc0 = pTc[i >> 1];
+    if (iTc0 > 0) {
+      p0 = pPixCbCr[-iStrideX];
+      p1 = pPixCbCr[-2 * iStrideX];
+      q0 = pPixCbCr[0];
+      q1 = pPixCbCr[iStrideX];
+
+      bDetaP0Q0 =  WELS_ABS (p0 - q0) < iAlpha;
+      bDetaP1P0 =  WELS_ABS (p1 - p0) < iBeta;
+      bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
+      if (bDetaP0Q0 && bDetaP1P0 &&	bDetaQ1Q0) {
+        iDeta = WELS_CLIP3 ((((q0 - p0) << 2) + (p1 - q1) + 4) >> 3, -iTc0, iTc0);
+        pPixCbCr[-iStrideX] = WelsClip1 (p0 + iDeta);     /* p0' */
+        pPixCbCr[0]  = WelsClip1 (q0 - iDeta);     /* q0' */
+      }
+
+
+    }
+    pPixCbCr += iStrideY;
+  }
+}
+void DeblockChromaEq42_c (uint8_t* pPixCbCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
+                          int32_t iBeta) {
+  int32_t p0, p1, q0, q1;
+  bool bDetaP0Q0, bDetaP1P0, bDetaQ1Q0;
+  for (int32_t i = 0; i < 8; i++) {
+    p0 = pPixCbCr[-iStrideX];
+    p1 = pPixCbCr[-2 * iStrideX];
+    q0 = pPixCbCr[0];
+    q1 = pPixCbCr[iStrideX];
+    bDetaP0Q0 = WELS_ABS (p0 - q0) < iAlpha;
+    bDetaP1P0 = WELS_ABS (p1 - p0) < iBeta;
+    bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
+    if (bDetaP0Q0 && bDetaP1P0 && bDetaQ1Q0) {
+      pPixCbCr[-iStrideX] = ((p1 << 1) + p0 + q1 + 2) >> 2;     /* p0' */
+      pPixCbCr[0]  = ((q1 << 1) + q0 + p1 + 2) >> 2;     /* q0' */
+    }
+
+    pPixCbCr += iStrideY;
+  }
+}
+
+void DeblockChromaLt4V2_c (uint8_t* pPixCbCr, int32_t iStride, int32_t iAlpha, int32_t iBeta,
+                           int8_t* tc) {
+  DeblockChromaLt42_c (pPixCbCr, iStride, 1, iAlpha, iBeta, tc);
+}
+void DeblockChromaLt4H2_c (uint8_t* pPixCbCr, int32_t iStride, int32_t iAlpha, int32_t iBeta,
+                           int8_t* tc) {
+
+  DeblockChromaLt42_c (pPixCbCr, 1, iStride, iAlpha, iBeta, tc);
+}
+void DeblockChromaEq4V2_c (uint8_t* pPixCbCr, int32_t iStride, int32_t iAlpha, int32_t iBeta) {
+  DeblockChromaEq42_c (pPixCbCr, iStride, 1, iAlpha, iBeta);
+}
+void DeblockChromaEq4H2_c (uint8_t* pPixCbCr, int32_t iStride, int32_t iAlpha, int32_t iBeta) {
+  DeblockChromaEq42_c (pPixCbCr, 1, iStride, iAlpha, iBeta);
 }
 
 void WelsNonZeroCount_c (int8_t* pNonZeroCount) {
--- a/codec/decoder/core/inc/dec_frame.h
+++ b/codec/decoder/core/inc/dec_frame.h
@@ -69,7 +69,7 @@
   int16_t	(*pMvd[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
   int8_t	(*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM];
   int8_t*  pLumaQp;
-  int8_t*  pChromaQp;
+  int8_t  (*pChromaQp)[2];
   int8_t*  pCbp;
   uint8_t *pCbfDc;
   int8_t (*pNzc)[24];
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -164,7 +164,7 @@
 EWelsSliceType  eSliceType;
 int8_t	iSliceAlphaC0Offset;
 int8_t	iSliceBetaOffset;
-int8_t  iChromaQP;
+int8_t  iChromaQP[2];
 int8_t  iLumaQP;
 struct TagDeblockingFunc*  pLoopf;
 } SDeblockingFilter, *PDeblockingFilter;
@@ -177,6 +177,10 @@
     int32_t iBeta, int8_t* iTc);
 typedef void (*PChromaDeblockingEQ4Func) (uint8_t* iSampleCb, uint8_t* iSampleCr, int32_t iStride, int32_t iAlpha,
     int32_t iBeta);
+    typedef void (*PChromaDeblockingLT4Func2) (uint8_t* iSampleCbr,int32_t iStride, int32_t iAlpha,
+    int32_t iBeta,int8_t* iTc);
+    typedef void (*PChromaDeblockingEQ4Func2) (uint8_t* iSampleCbr,int32_t iStride, int32_t iAlpha,
+    int32_t iBeta);
 
 typedef struct TagDeblockingFunc {
 PLumaDeblockingLT4Func    pfLumaDeblockingLT4Ver;
@@ -188,6 +192,12 @@
 PChromaDeblockingEQ4Func  pfChromaDeblockingEQ4Ver;
 PChromaDeblockingLT4Func  pfChromaDeblockingLT4Hor;
 PChromaDeblockingEQ4Func  pfChromaDeblockingEQ4Hor;
+
+PChromaDeblockingLT4Func2  pfChromaDeblockingLT4Ver2;
+PChromaDeblockingEQ4Func2  pfChromaDeblockingEQ4Ver2;
+PChromaDeblockingLT4Func2  pfChromaDeblockingLT4Hor2;
+PChromaDeblockingEQ4Func2  pfChromaDeblockingEQ4Hor2; 
+
 } SDeblockingFunc, *PDeblockingFunc;
 
 typedef void (*PWelsNonZeroCountFunc) (int8_t* pNonZeroCount);
@@ -260,7 +270,7 @@
   int16_t	(*pMv[LAYER_NUM_EXCHANGEABLE][LIST_A])[MB_BLOCK4x4_NUM][MV_A]; //[LAYER_NUM_EXCHANGEABLE   MB_BLOCK4x4_NUM*]
   int8_t	(*pRefIndex[LAYER_NUM_EXCHANGEABLE][LIST_A])[MB_BLOCK4x4_NUM];
   int8_t*	pLumaQp[LAYER_NUM_EXCHANGEABLE];	/*mb luma_qp*/
-  int8_t*	pChromaQp[LAYER_NUM_EXCHANGEABLE];					/*mb chroma_qp*/
+  int8_t	(*pChromaQp[LAYER_NUM_EXCHANGEABLE])[2];					/*mb chroma_qp*/
   int16_t	(*pMvd[LAYER_NUM_EXCHANGEABLE][LIST_A])[MB_BLOCK4x4_NUM][MV_A]; //[LAYER_NUM_EXCHANGEABLE   MB_BLOCK4x4_NUM*]
   uint8_t *pCbfDc[LAYER_NUM_EXCHANGEABLE];
   int8_t	(*pNzc[LAYER_NUM_EXCHANGEABLE])[24];
--- a/codec/decoder/core/inc/parameter_sets.h
+++ b/codec/decoder/core/inc/parameter_sets.h
@@ -155,7 +155,7 @@
 
   int32_t		iPicInitQp;
   int32_t		iPicInitQs;
-  int32_t		iChromaQpIndexOffset;
+  int32_t		iChromaQpIndexOffset[2];//cb,cr
 
   bool		bEntropyCodingModeFlag;
   bool		bPicOrderPresentFlag;
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -1336,10 +1336,11 @@
   pPps->iPicInitQs = PIC_INIT_QS_OFFSET + iCode;
   WELS_CHECK_SE_BOTH_ERROR (pPps->iPicInitQs, PPS_PIC_INIT_QP_QS_MIN, PPS_PIC_INIT_QP_QS_MAX, "pic_init_qs_minus26 + 26",
                             GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_PIC_INIT_QS));
-  WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode)); //chroma_qp_index_offset
-  pPps->iChromaQpIndexOffset                  = iCode;
-  WELS_CHECK_SE_BOTH_ERROR (pPps->iChromaQpIndexOffset, PPS_CHROMA_QP_INDEX_OFFSET_MIN, PPS_CHROMA_QP_INDEX_OFFSET_MAX,
+  WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode)); //chroma_qp_index_offset,cb
+  pPps->iChromaQpIndexOffset[0]                  = iCode;
+  WELS_CHECK_SE_BOTH_ERROR (pPps->iChromaQpIndexOffset[0], PPS_CHROMA_QP_INDEX_OFFSET_MIN, PPS_CHROMA_QP_INDEX_OFFSET_MAX,
                             "chroma_qp_index_offset", GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_CHROMA_QP_INDEX_OFFSET));
+  pPps->iChromaQpIndexOffset[1] = pPps->iChromaQpIndexOffset[0];//init cr qp offset
   WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //deblocking_filter_control_present_flag
   pPps->bDeblockingFilterControlPresentFlag   = !!uiCode;
   WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //constrained_intra_pred_flag
@@ -1346,20 +1347,28 @@
   pPps->bConstainedIntraPredFlag              = !!uiCode;
   WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //redundant_pic_cnt_present_flag
   pPps->bRedundantPicCntPresentFlag           = !!uiCode;
+  /*TODO: to judge whether going on to parse*/
 //going on to parse high profile syntax, need fix me
-  WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode));
-  pPps->bTransform_8x8_mode_flag = !!uiCode;
-  WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode));
-  pPps->bPicScalingMatrixPresentFlag = !!uiCode;
-  if (pPps->bPicScalingMatrixPresentFlag) {
-    if (pCtx->bSpsAvailFlags[pPps->iSpsId])
-      WELS_READ_VERIFY (ParseScalingList (&pCtx->sSpsBuffer[pPps->iSpsId], pBsAux, 1, pPps->bPicScalingListPresentFlag,
-                                          pPps->iScalingList4x4, pPps->iScalingList8x8));
-    else {
-      pCtx->bSpsLatePps = true;
-      WELS_READ_VERIFY (ParseScalingList (NULL, pBsAux, 1, pPps->bPicScalingListPresentFlag, pPps->iScalingList4x4,
-                                          pPps->iScalingList8x8));
+  if (0) {
+    WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode));
+    pPps->bTransform_8x8_mode_flag = !!uiCode;
+    WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode));
+    pPps->bPicScalingMatrixPresentFlag = !!uiCode;
+    if (pPps->bPicScalingMatrixPresentFlag) {
+      if (pCtx->bSpsAvailFlags[pPps->iSpsId])
+        WELS_READ_VERIFY (ParseScalingList (&pCtx->sSpsBuffer[pPps->iSpsId], pBsAux, 1, pPps->bPicScalingListPresentFlag,
+                                            pPps->iScalingList4x4, pPps->iScalingList8x8));
+      else {
+        pCtx->bSpsLatePps = true;
+        WELS_READ_VERIFY (ParseScalingList (NULL, pBsAux, 1, pPps->bPicScalingListPresentFlag, pPps->iScalingList4x4,
+                                            pPps->iScalingList8x8));
+      }
     }
+    //add second chroma qp parsing process
+    WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode)); //chroma_qp_index_offset,cr
+    pPps->iChromaQpIndexOffset[1]               = iCode;
+    WELS_CHECK_SE_BOTH_ERROR (pPps->iChromaQpIndexOffset[1], PPS_CHROMA_QP_INDEX_OFFSET_MIN, PPS_CHROMA_QP_INDEX_OFFSET_MAX,
+                              "second_chroma_qp_index_offset", GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_CHROMA_QP_INDEX_OFFSET));
   }
 
   if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
--- a/codec/decoder/core/src/deblocking.cpp
+++ b/codec/decoder/core/src/deblocking.cpp
@@ -332,13 +332,33 @@
   int32_t iAlpha;
   int32_t iBeta;
   ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
+  if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
 
-  GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
-                          iBeta);
+    GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                            iBeta);
 
-  if (iAlpha | iBeta) {
-    TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
-    pFilter->pLoopf->pfChromaDeblockingLT4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
+    if (iAlpha | iBeta) {
+      TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+      pFilter->pLoopf->pfChromaDeblockingLT4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
+    }
+  } else {
+
+    for (int i = 0; i < 2; i++) {
+
+
+      GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                              iBeta);
+
+      if (iAlpha | iBeta) {
+        uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+        TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+        pFilter->pLoopf->pfChromaDeblockingLT4Ver2 (pPixCbCr, iStride, iAlpha, iBeta, tc);
+      }
+
+
+
+    }
+
   }
   return;
 }
@@ -348,13 +368,33 @@
   int32_t iAlpha;
   int32_t iBeta;
   ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
+  if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
 
-  GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
-                          iBeta);
 
-  if (iAlpha | iBeta) {
-    TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
-    pFilter->pLoopf->pfChromaDeblockingLT4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
+    GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                            iBeta);
+
+    if (iAlpha | iBeta) {
+      TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+      pFilter->pLoopf->pfChromaDeblockingLT4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
+    }
+
+
+  } else {
+
+    for (int i = 0; i < 2; i++) {
+
+      GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                              iBeta);
+
+      if (iAlpha | iBeta) {
+        uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+        TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+        pFilter->pLoopf->pfChromaDeblockingLT4Hor2 (pPixCbCr, iStride, iAlpha, iBeta, tc);
+      }
+
+
+    }
   }
   return;
 }
@@ -364,12 +404,27 @@
   int32_t iIndexA;
   int32_t iAlpha;
   int32_t iBeta;
+  if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
 
-  GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
-                          iBeta);
+    GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                            iBeta);
 
-  if (iAlpha | iBeta) {
-    pFilter->pLoopf->pfChromaDeblockingEQ4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta);
+    if (iAlpha | iBeta) {
+      pFilter->pLoopf->pfChromaDeblockingEQ4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta);
+    }
+  } else {
+
+    for (int i = 0; i < 2; i++) {
+
+      GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                              iBeta);
+
+      if (iAlpha | iBeta) {
+        uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+        pFilter->pLoopf->pfChromaDeblockingEQ4Ver2 (pPixCbCr, iStride, iAlpha, iBeta);
+      }
+
+    }
   }
   return;
 }
@@ -379,12 +434,29 @@
   int32_t iIndexA;
   int32_t iAlpha;
   int32_t iBeta;
+  if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) { // QP of cb and cr are the same
 
-  GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
-                          iBeta);
 
-  if (iAlpha | iBeta) {
-    pFilter->pLoopf->pfChromaDeblockingEQ4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta);
+
+
+    GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                            iBeta);
+    if (iAlpha | iBeta) {
+      pFilter->pLoopf->pfChromaDeblockingEQ4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta);
+    }
+  } else {
+
+    for (int i = 0; i < 2; i++) {
+
+
+      GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                              iBeta);
+      if (iAlpha | iBeta) {
+        uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+        pFilter->pLoopf->pfChromaDeblockingEQ4Hor2 (pPixCbCr, iStride, iAlpha, iBeta);
+      }
+    }
+
   }
   return;
 }
@@ -397,7 +469,8 @@
   int32_t iMbY = pCurDqLayer->iMbY;
 
   int32_t iCurLumaQp = pCurDqLayer->pLumaQp[iMbXyIndex];
-  int32_t iCurChromaQp = pCurDqLayer->pChromaQp[iMbXyIndex];
+  //int32_t* iCurChromaQp = pCurDqLayer->pChromaQp[iMbXyIndex];
+  int8_t* pCurChromaQp = pCurDqLayer->pChromaQp[iMbXyIndex];
   int32_t iLineSize   = pFilter->iCsStride[0];
   int32_t iLineSizeUV = pFilter->iCsStride[1];
 
@@ -406,11 +479,13 @@
   pDestCb = pFilter->pCsData[1] + ((iMbY * iLineSizeUV + iMbX) << 3);
   pDestCr = pFilter->pCsData[2] + ((iMbY * iLineSizeUV + iMbX) << 3);
 
+//Vertical margrin
   if (iBoundryFlag & LEFT_FLAG_MASK) {
     int32_t iLeftXyIndex = iMbXyIndex - 1;
     pFilter->iLumaQP   = (iCurLumaQp + pCurDqLayer->pLumaQp[iLeftXyIndex] + 1) >> 1;
-    pFilter->iChromaQP = (iCurChromaQp + pCurDqLayer->pChromaQp[iLeftXyIndex] + 1) >> 1;
-
+    for (int i = 0; i < 2; i++) {
+      pFilter->iChromaQP[i] = (pCurChromaQp[i] + pCurDqLayer->pChromaQp[iLeftXyIndex][i] + 1) >> 1;
+    }
     if (nBS[0][0][0] == 0x04) {
       FilteringEdgeLumaIntraV (pFilter, pDestY, iLineSize, NULL);
       FilteringEdgeChromaIntraV (pFilter, pDestCb, pDestCr, iLineSizeUV, NULL);
@@ -423,7 +498,8 @@
   }
 
   pFilter->iLumaQP = iCurLumaQp;
-  pFilter->iChromaQP = iCurChromaQp;
+  pFilter->iChromaQP[0] = pCurChromaQp[0];
+  pFilter->iChromaQP[1] = pCurChromaQp[1];
 
   if (* (uint32_t*)nBS[0][1] != 0) {
     FilteringEdgeLumaV (pFilter, &pDestY[1 << 2], iLineSize, nBS[0][1]);
@@ -441,7 +517,9 @@
   if (iBoundryFlag & TOP_FLAG_MASK) {
     int32_t iTopXyIndex = iMbXyIndex - pCurDqLayer->iMbWidth;
     pFilter->iLumaQP = (iCurLumaQp + pCurDqLayer->pLumaQp[iTopXyIndex] + 1) >> 1;
-    pFilter->iChromaQP = (iCurChromaQp + pCurDqLayer->pChromaQp[iTopXyIndex] + 1) >> 1;
+    for (int i = 0; i < 2; i++) {
+      pFilter->iChromaQP[i] = (pCurChromaQp[i] + pCurDqLayer->pChromaQp[iTopXyIndex][i] + 1) >> 1;
+    }
 
     if (nBS[1][0][0] == 0x04) {
       FilteringEdgeLumaIntraH (pFilter, pDestY, iLineSize, NULL);
@@ -455,7 +533,8 @@
   }
 
   pFilter->iLumaQP = iCurLumaQp;
-  pFilter->iChromaQP = iCurChromaQp;
+  pFilter->iChromaQP[0] = pCurChromaQp[0];
+  pFilter->iChromaQP[1] = pCurChromaQp[1];
 
   if (* (uint32_t*)nBS[1][1] != 0) {
     FilteringEdgeLumaH (pFilter, &pDestY[ (1 << 2)*iLineSize], iLineSize, nBS[1][1]);
@@ -527,8 +606,10 @@
   int32_t iMbWidth  = pCurDqLayer->iMbWidth;
   int32_t iLineSize  = pFilter->iCsStride[1];
 
-  uint8_t*  pDestCb, *pDestCr;
-  int32_t  iCurQp;
+  uint8_t* pDestCb;
+  uint8_t* pDestCr;
+  //int32_t  iCurQp;
+  int8_t* pCurQp;
   int32_t  iIndexA, iAlpha, iBeta;
 
   ENFORCE_STACK_ALIGN_1D (int8_t,  iTc,   4, 16);
@@ -536,33 +617,76 @@
 
   pDestCb = pFilter->pCsData[1] + ((iMbY * iLineSize + iMbX) << 3);
   pDestCr = pFilter->pCsData[2] + ((iMbY * iLineSize + iMbX) << 3);
-  iCurQp  = pCurDqLayer->pChromaQp[iMbXyIndex];
+  pCurQp  = pCurDqLayer->pChromaQp[iMbXyIndex];
+
   * (uint32_t*)uiBSx4 = 0x03030303;
 
-  // chroma v
+
+// chroma v
   if (iBoundryFlag & LEFT_FLAG_MASK) {
-    pFilter->iChromaQP = (iCurQp + pCurDqLayer->pChromaQp[iMbXyIndex - 1] + 1) >> 1;
+
+    for (int i = 0; i < 2; i++) {
+      pFilter->iChromaQP[i] = (pCurQp[i] + pCurDqLayer->pChromaQp[iMbXyIndex - 1][i] + 1) >> 1;
+
+    }
     FilteringEdgeChromaIntraV (pFilter, pDestCb, pDestCr, iLineSize, NULL);
   }
 
-  pFilter->iChromaQP   = iCurQp;
-  GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
-                          iBeta);
-  if (iAlpha | iBeta) {
-    TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
-    pFilter->pLoopf->pfChromaDeblockingLT4Hor (&pDestCb[2 << 1], &pDestCr[2 << 1], iLineSize, iAlpha, iBeta, iTc);
+  pFilter->iChromaQP[0]   = pCurQp[0];
+  pFilter->iChromaQP[1]   = pCurQp[1];;
+  if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
+    GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                            iBeta);
+    if (iAlpha | iBeta) {
+      TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
+      pFilter->pLoopf->pfChromaDeblockingLT4Hor (&pDestCb[2 << 1], &pDestCr[2 << 1], iLineSize, iAlpha, iBeta, iTc);
+    }
+  } else {
+
+    for (int i = 0; i < 2; i++) {
+      GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                              iBeta);
+      if (iAlpha | iBeta) {
+        uint8_t* pDestCbCr = (i == 0) ? &pDestCb[2 << 1] : &pDestCr[2 << 1];
+        TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
+        pFilter->pLoopf->pfChromaDeblockingLT4Hor2 (pDestCbCr, iLineSize, iAlpha, iBeta, iTc);
+      }
+
+    }
   }
 
   // chroma h
+
   if (iBoundryFlag & TOP_FLAG_MASK) {
-    pFilter->iChromaQP = (iCurQp + pCurDqLayer->pChromaQp[iMbXyIndex - iMbWidth] + 1) >> 1;
+    for (int i = 0; i < 2; i++) {
+      pFilter->iChromaQP[i] = (pCurQp[i] + pCurDqLayer->pChromaQp[iMbXyIndex - iMbWidth][i] + 1) >> 1;
+    }
     FilteringEdgeChromaIntraH (pFilter, pDestCb, pDestCr, iLineSize, NULL);
   }
 
-  pFilter->iChromaQP   = iCurQp;
-  if (iAlpha | iBeta) {
-    pFilter->pLoopf->pfChromaDeblockingLT4Ver (&pDestCb[ (2 << 1)*iLineSize], &pDestCr[ (2 << 1)*iLineSize], iLineSize,
-        iAlpha, iBeta, iTc);
+  pFilter->iChromaQP[0]   = pCurQp[0];
+  pFilter->iChromaQP[1]   = pCurQp[1];
+
+  if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
+    GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                            iBeta);
+    if (iAlpha | iBeta) {
+      pFilter->pLoopf->pfChromaDeblockingLT4Ver (&pDestCb[ (2 << 1)*iLineSize], &pDestCr[ (2 << 1)*iLineSize], iLineSize,
+          iAlpha, iBeta, iTc);
+    }
+  } else {
+    for (int i = 0; i < 2; i++) {
+
+      GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+                              iBeta);
+      if (iAlpha | iBeta) {
+        uint8_t* pDestCbCr = (i == 0) ? &pDestCb[ (2 << 1) * iLineSize] : &pDestCr[ (2 << 1) * iLineSize];
+        pFilter->pLoopf->pfChromaDeblockingLT4Ver2 (pDestCbCr, iLineSize,
+            iAlpha, iBeta, iTc);
+      }
+    }
+
+
   }
 }
 
@@ -705,6 +829,11 @@
   pFunc->pfChromaDeblockingEQ4Ver	    = DeblockChromaEq4V_c;
   pFunc->pfChromaDeblockingLT4Hor	    = DeblockChromaLt4H_c;
   pFunc->pfChromaDeblockingEQ4Hor	    = DeblockChromaEq4H_c;
+
+  pFunc->pfChromaDeblockingLT4Ver2	    = DeblockChromaLt4V2_c;
+  pFunc->pfChromaDeblockingEQ4Ver2	    = DeblockChromaEq4V2_c;
+  pFunc->pfChromaDeblockingLT4Hor2	    = DeblockChromaLt4H2_c;
+  pFunc->pfChromaDeblockingEQ4Hor2	    = DeblockChromaEq4H2_c;
 
 #ifdef X86_ASM
   if (iCpu & WELS_CPU_SSSE3) {
--- a/codec/decoder/core/src/decode_slice.cpp
+++ b/codec/decoder/core/src/decode_slice.cpp
@@ -559,8 +559,10 @@
 
   if (pCurLayer->pCbp[iMbXy] == 0 && IS_INTRA4x4 (pCurLayer->pMbType[iMbXy])) {
     pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 ((pCurLayer->pLumaQp[iMbXy] +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset), 0, 51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 ((pCurLayer->pLumaQp[iMbXy] +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i]), 0, 51)];
+    }
   }
 
   if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
@@ -572,8 +574,10 @@
     }
     pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
     pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 ((pSlice->iLastMbQp +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset), 0, 51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 ((pSlice->iLastMbQp +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i]), 0, 51)];
+    }
     if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
       //step1: Luma DC
       WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 0, 16, g_kuiLumaDcZigzagScan,
@@ -625,7 +629,7 @@
       for (i = 0; i < 2; i++) {
         iMbResProperty = i ? CHROMA_DC_V : CHROMA_DC_U;
         WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 16 + (i << 2), 4, g_kuiChromaDcScan,
-                          iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
+                          iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6), pCurLayer->pChromaQp[iMbXy][i], pCtx));
       }
     }
 
@@ -637,7 +641,7 @@
         for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
           WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, iIdx,
                             iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), iMbResProperty,
-                            pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
+                            pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pChromaQp[iMbXy][i], pCtx));
           iIdx++;
         }
       }
@@ -772,8 +776,10 @@
     }
     pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
     pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];
+    }
 
     if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
       //step1: Luma DC
@@ -830,7 +836,7 @@
           iMbResProperty = i ? CHROMA_DC_V_INTER : CHROMA_DC_U_INTER;
 
         WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, 16 + (i << 2), 4, g_kuiChromaDcScan,
-                          iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
+                          iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6), pCurLayer->pChromaQp[iMbXy][i], pCtx));
       }
     }
     //step2: AC
@@ -844,7 +850,7 @@
         for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
           WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, index,
                             iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1),
-                            iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (index << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
+                            iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (index << 4), pCurLayer->pChromaQp[iMbXy][i], pCtx));
           index++;
         }
       }
@@ -858,8 +864,10 @@
     }
   } else {
     pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];
+    }
   }
 
   WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
@@ -911,8 +919,10 @@
 
     //reset rS
     pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp; //??????????????? dqaunt of previous mb
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];
+    }
 
     //for neighboring CABAC usage
     pSlice->iLastDeltaQp = 0;
@@ -1145,7 +1155,7 @@
 
     //step 3: update QP and pNonZeroCount
     pCurLayer->pLumaQp[iMbXy] = 0;
-    pCurLayer->pChromaQp[iMbXy] = 0;
+    memset (pCurLayer->pChromaQp[iMbXy], 0, sizeof (pCurLayer->pChromaQp[iMbXy]));
     memset (pNzc, 16, sizeof (pCurLayer->pNzc[iMbXy]));   //Rec. 9.2.1 for PCM, nzc=16
     WELS_READ_VERIFY (InitReadBits (pBs, 0));
     return 0;
@@ -1186,8 +1196,10 @@
 
   if (pCurLayer->pCbp[iMbXy] == 0 && IS_INTRA4x4 (pCurLayer->pMbType[iMbXy])) {
     pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];
+    }
 
   }
 
@@ -1204,9 +1216,11 @@
 
     pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
     pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0,
-                                  51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i], 0,
+                                       51)];
+    }
 
 
     BsStartCavlc (pBs);
@@ -1262,7 +1276,7 @@
         iMbResProperty = i ? CHROMA_DC_V : CHROMA_DC_U;
         if (WelsResidualBlockCavlc (pVlcTable, pNonZeroCount, pBs,
                                     16 + (i << 2), 4, g_kuiChromaDcScan, iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6),
-                                    pCurLayer->pChromaQp[iMbXy], pCtx)) {
+                                    pCurLayer->pChromaQp[iMbXy][i], pCtx)) {
           return -1;//abnormal
         }
       }
@@ -1276,7 +1290,7 @@
         for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
           if (WelsResidualBlockCavlc (pVlcTable, pNonZeroCount, pBs, iIndex,
                                       iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1),
-                                      iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (iIndex << 4), pCurLayer->pChromaQp[iMbXy], pCtx)) {
+                                      iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (iIndex << 4), pCurLayer->pChromaQp[iMbXy][i], pCtx)) {
             return -1;//abnormal
           }
           iIndex++;
@@ -1435,7 +1449,7 @@
 
       //step 3: update QP and pNonZeroCount
       pCurLayer->pLumaQp[iMbXy] = 0;
-      pCurLayer->pChromaQp[iMbXy] = 0;
+      pCurLayer->pChromaQp[iMbXy][0] = pCurLayer->pChromaQp[iMbXy][1] = 0;
       //Rec. 9.2.1 for PCM, nzc=16
       ST32A4 (&pNzc[0], 0x10101010);
       ST32A4 (&pNzc[4], 0x10101010);
@@ -1493,8 +1507,10 @@
   ST32A4 (&pNzc[20], 0);
   if (pCurLayer->pCbp[iMbXy] == 0 && !IS_INTRA16x16 (pCurLayer->pMbType[iMbXy]) && !IS_I_BL (pCurLayer->pMbType[iMbXy])) {
     pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];
+    }
   }
 
   if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
@@ -1509,9 +1525,11 @@
 
     pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
     pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
-    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
-                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0,
-                                  51)];
+    for (i = 0; i < 2; i++) {
+      pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
+                                       pSliceHeader->pPps->iChromaQpIndexOffset[i], 0,
+                                       51)];
+    }
 
     BsStartCavlc (pBs);
 
@@ -1572,7 +1590,7 @@
 
         if (WelsResidualBlockCavlc (pVlcTable, pNonZeroCount, pBs,
                                     16 + (i << 2), 4, g_kuiChromaDcScan, iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6),
-                                    pCurLayer->pChromaQp[iMbXy], pCtx)) {
+                                    pCurLayer->pChromaQp[iMbXy][i], pCtx)) {
           return -1;//abnormal
         }
       }
@@ -1590,7 +1608,7 @@
         for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
           if (WelsResidualBlockCavlc (pVlcTable, pNonZeroCount, pBs, iIndex,
                                       iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1),
-                                      iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (iIndex << 4), pCurLayer->pChromaQp[iMbXy], pCtx)) {
+                                      iMbResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (iIndex << 4), pCurLayer->pChromaQp[iMbXy][i], pCtx)) {
             return -1;//abnormal
           }
           iIndex++;
@@ -1655,8 +1673,10 @@
     if (!pSlice->sSliceHeaderExt.bDefaultResidualPredFlag ||
         (pNalCur->sNalHeaderExt.uiQualityId == 0 && pNalCur->sNalHeaderExt.uiDependencyId == 0)) {
       pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
-      pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
-                                    pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
+      for (i = 0; i < 2; i++) {
+        pCurLayer->pChromaQp[iMbXy][i] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
+                                         pSliceHeader->pPps->iChromaQpIndexOffset[i], 0, 51)];
+      }
     }
 
     pCurLayer->pCbp[iMbXy] = 0;
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -1079,7 +1079,7 @@
                                   int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pRefIndex[][]");
     pCtx->sMb.pLumaQp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t),
                            "pCtx->sMb.pLumaQp[]");
-    pCtx->sMb.pChromaQp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t),
+    pCtx->sMb.pChromaQp[i] = (int8_t (*)[2])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 2,
                              "pCtx->sMb.pChromaQp[]");
     pCtx->sMb.pMvd[i][0] = (int16_t (*)[16][2])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (
                              int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMvd[][]");
--- a/codec/decoder/core/src/parse_mb_syn_cabac.cpp
+++ b/codec/decoder/core/src/parse_mb_syn_cabac.cpp
@@ -385,7 +385,8 @@
         return ERR_INFO_INVALID_REF_INDEX;
       }
     }
-    pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || !(ppRefPic[iRef[0]]&&ppRefPic[iRef[0]]->bIsComplete);
+    pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[0]]
+                            && ppRefPic[iRef[0]]->bIsComplete);
     PredMv (pMotionVector, pRefIndex, 0, 4, iRef[0], pMv);
     WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
     WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
@@ -410,7 +411,8 @@
           return ERR_INFO_INVALID_REF_INDEX;
         }
       }
-      pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || !(ppRefPic[iRef[i]]&&ppRefPic[iRef[i]]->bIsComplete);
+      pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[i]]
+                              && ppRefPic[iRef[i]]->bIsComplete);
       UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
     }
     for (i = 0; i < 2; i++) {
@@ -439,7 +441,8 @@
           return ERR_INFO_INVALID_REF_INDEX;
         }
       }
-      pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || !(ppRefPic[iRef[i]]&&ppRefPic[iRef[i]]->bIsComplete);
+      pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[i]]
+                              && ppRefPic[iRef[i]]->bIsComplete);
       UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
     }
     for (i = 0; i < 2; i++) {
@@ -483,7 +486,8 @@
           return ERR_INFO_INVALID_REF_INDEX;
         }
       }
-      pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || !(ppRefPic[pRefIdx[i]]&&ppRefPic[pRefIdx[i]]->bIsComplete);
+      pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[pRefIdx[i]]
+                              && ppRefPic[pRefIdx[i]]->bIsComplete);
       UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, pRefIdx[i], LIST_0);
     }
     //mv
@@ -912,7 +916,7 @@
   pBsAux->pCurBuf += 384;
 
   pCurLayer->pLumaQp[iMbXy] = 0;
-  pCurLayer->pChromaQp[iMbXy] = 0;
+  pCurLayer->pChromaQp[iMbXy][0] = pCurLayer->pChromaQp[iMbXy][1] = 0;
   memset (pCurLayer->pNzc[iMbXy], 16, sizeof (pCurLayer->pNzc[iMbXy]));
 
   //step 4: cabac engine init
--- a/test/decoder/DecUT_DeblockCommon.cpp
+++ b/test/decoder/DecUT_DeblockCommon.cpp
@@ -641,7 +641,7 @@
   sFilter.pLoopf->pfChromaDeblockingEQ4Hor = &UT_DeblockingFuncChromaEQ4Func;
   sFilter.pLoopf->pfChromaDeblockingEQ4Ver = &UT_DeblockingFuncChromaEQ4Func;
 
-  int8_t iChromaQP[9];
+  int8_t iChromaQP[9][2];
   sDqLayer.pChromaQp = iChromaQP;
 
   uint8_t iCb[9] = {0};
@@ -656,7 +656,7 @@
 
 #define UT_DB_CHROMA_TEST(iFlag, iQP, iV0, iV1, iV2) \
   iBoundryFlag = iFlag; \
-  memset(iChromaQP, iQP, sizeof(int8_t)*9); \
+  memset(iChromaQP, iQP, sizeof(int8_t)*9*2); \
   memset(iCb, 0, sizeof(uint8_t)*9); \
   memset(iCr, 0, sizeof(uint8_t)*9); \
   FilteringEdgeChromaHV(&sDqLayer, &sFilter, iBoundryFlag); \
@@ -894,7 +894,7 @@
   sFilter.iCsStride[1] = 2;
 
   int8_t iLumaQP[50] = {0};
-  int8_t iChromaQP[9] = {0};
+  int8_t iChromaQP[9][2] = {{0, 0}};
   sDqLayer.pLumaQp = iLumaQP;
   sDqLayer.pChromaQp = iChromaQP;
 
@@ -910,7 +910,7 @@
 
 #define UT_DB_MACROBLOCK_TEST( iBoundFlag, iQP, iLumaV0, iLumaV1, iLumaV2, iChromaV0, iChromaV1, iChromaV2 ) \
   memset(sDqLayer.pLumaQp, iQP, sizeof(int8_t)*50); \
-  memset(sDqLayer.pChromaQp, iQP, sizeof(int8_t)*9); \
+  memset(sDqLayer.pChromaQp, iQP, sizeof(int8_t)*9*2); \
   memset(sFilter.pCsData[0], 0, sizeof(int8_t)*50); \
   memset(sFilter.pCsData[1], 0, sizeof(int8_t)*9); \
   memset(sFilter.pCsData[2], 0, sizeof(int8_t)*9); \