shithub: openh264

Download patch

ref: cf8574575201ffbedc00374aa138fff17e859f4a
parent: c7b50517386d21e3d4906c36e020602f3c253e53
author: dong zhang <dongzha@cisco.com>
date: Sun Sep 28 07:21:14 EDT 2014

add decoder cabac support and add  UT

--- a/codec/build/iOS/dec/welsdec/welsdec.xcodeproj/project.pbxproj
+++ b/codec/build/iOS/dec/welsdec/welsdec.xcodeproj/project.pbxproj
@@ -30,6 +30,8 @@
 		4CE4469F18BC5EAB0017DF25 /* welsDecoderExt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4468518BC5EAB0017DF25 /* welsDecoderExt.cpp */; };
 		4CE447AC18BC6BE90017DF25 /* block_add_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4CE447A718BC6BE90017DF25 /* block_add_neon.S */; };
 		4CE447AE18BC6BE90017DF25 /* intra_pred_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4CE447A918BC6BE90017DF25 /* intra_pred_neon.S */; };
+		6A3E814219D79AE900C19C1F /* cabac_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */; };
+		6A3E814419D7A40600C19C1F /* parse_mb_syn_cabac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */; };
 		6C749B6A197CC6E600A111F9 /* block_add_aarch64_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C749B69197CC6E600A111F9 /* block_add_aarch64_neon.S */; };
 		9ABF4382193EB60900A6BD61 /* expand_pic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9ABF4381193EB60900A6BD61 /* expand_pic.cpp */; };
 		9AED66561946A1DE009A3567 /* welsCodecTrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AED66551946A1DE009A3567 /* welsCodecTrace.cpp */; };
@@ -109,6 +111,10 @@
 		4CE4468518BC5EAB0017DF25 /* welsDecoderExt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = welsDecoderExt.cpp; sourceTree = "<group>"; };
 		4CE447A718BC6BE90017DF25 /* block_add_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = block_add_neon.S; sourceTree = "<group>"; };
 		4CE447A918BC6BE90017DF25 /* intra_pred_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = intra_pred_neon.S; sourceTree = "<group>"; };
+		6A3E814019D79AD900C19C1F /* cabac_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cabac_decoder.h; sourceTree = "<group>"; };
+		6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cabac_decoder.cpp; sourceTree = "<group>"; };
+		6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_mb_syn_cabac.cpp; sourceTree = "<group>"; };
+		6A3E814519D7A40D00C19C1F /* parse_mb_syn_cabac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_mb_syn_cabac.h; sourceTree = "<group>"; };
 		6C749B69197CC6E600A111F9 /* block_add_aarch64_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = block_add_aarch64_neon.S; path = arm64/block_add_aarch64_neon.S; sourceTree = "<group>"; };
 		9ABF4380193EB5F700A6BD61 /* expand_pic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = expand_pic.h; path = ../../../common/inc/expand_pic.h; sourceTree = "<group>"; };
 		9ABF4381193EB60900A6BD61 /* expand_pic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = expand_pic.cpp; path = ../../../common/src/expand_pic.cpp; sourceTree = "<group>"; };
@@ -191,6 +197,8 @@
 		4CE4464418BC5EAA0017DF25 /* inc */ = {
 			isa = PBXGroup;
 			children = (
+				6A3E814519D7A40D00C19C1F /* parse_mb_syn_cabac.h */,
+				6A3E814019D79AD900C19C1F /* cabac_decoder.h */,
 				9AED665A1946A21D009A3567 /* utils.h */,
 				9ABF4380193EB5F700A6BD61 /* expand_pic.h */,
 				F0B204FA18FD23CF005DA23F /* error_concealment.h */,
@@ -232,6 +240,8 @@
 		4CE4466618BC5EAA0017DF25 /* src */ = {
 			isa = PBXGroup;
 			children = (
+				6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */,
+				6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */,
 				9AED66581946A203009A3567 /* utils.cpp */,
 				9ABF4381193EB60900A6BD61 /* expand_pic.cpp */,
 				F0B204FB18FD23D8005DA23F /* error_concealment.cpp */,
@@ -346,6 +356,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				6A3E814419D7A40600C19C1F /* parse_mb_syn_cabac.cpp in Sources */,
 				4CE4469B18BC5EAB0017DF25 /* pic_queue.cpp in Sources */,
 				4CE4469F18BC5EAB0017DF25 /* welsDecoderExt.cpp in Sources */,
 				4CE4469318BC5EAB0017DF25 /* fmo.cpp in Sources */,
@@ -355,6 +366,7 @@
 				4CE4469518BC5EAB0017DF25 /* manage_dec_ref.cpp in Sources */,
 				4CE4468A18BC5EAB0017DF25 /* au_parser.cpp in Sources */,
 				4CE4469918BC5EAB0017DF25 /* mv_pred.cpp in Sources */,
+				6A3E814219D79AE900C19C1F /* cabac_decoder.cpp in Sources */,
 				4CE447AC18BC6BE90017DF25 /* block_add_neon.S in Sources */,
 				6C749B6A197CC6E600A111F9 /* block_add_aarch64_neon.S in Sources */,
 				4CE4469418BC5EAB0017DF25 /* get_intra_predictor.cpp in Sources */,
--- a/codec/build/win32/dec/WelsDecCore.vcproj
+++ b/codec/build/win32/dec/WelsDecCore.vcproj
@@ -656,6 +656,10 @@
 					>
 				</File>
 				<File
+					RelativePath="..\..\..\decoder\core\inc\cabac_decoder.h"
+					>
+				</File>
+				<File
 					RelativePath="..\..\..\common\inc\copy_mb.h"
 					>
 				</File>
@@ -776,6 +780,10 @@
 					>
 				</File>
 				<File
+					RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cabac.h"
+					>
+				</File>
+				<File
 					RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cavlc.h"
 					>
 				</File>
@@ -833,6 +841,10 @@
 					>
 				</File>
 				<File
+					RelativePath="..\..\..\decoder\core\src\cabac_decoder.cpp"
+					>
+				</File>
+				<File
 					RelativePath="..\..\..\common\src\common_tables.cpp"
 					>
 				</File>
@@ -910,6 +922,10 @@
 				</File>
 				<File
 					RelativePath="..\..\..\decoder\core\src\mv_pred.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\decoder\core\src\parse_mb_syn_cabac.cpp"
 					>
 				</File>
 				<File
--- a/codec/decoder/core/inc/bit_stream.h
+++ b/codec/decoder/core/inc/bit_stream.h
@@ -35,7 +35,6 @@
 #define WELS_BIT_STREAM_H__
 
 #include "typedefs.h"
-
 namespace WelsDec {
 
 /*
@@ -64,7 +63,7 @@
  */
 int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t kiSize);
 
-void InitReadBits (PBitStringAux pBitString);
+int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset);
 
 
 
--- /dev/null
+++ b/codec/decoder/core/inc/cabac_decoder.h
@@ -1,0 +1,111 @@
+/*!
+ * \copy
+ *     Copyright (c)  2009-2013, Cisco Systems
+ *     All rights reserved.
+ *
+ *     Redistribution and use in source and binary forms, with or without
+ *     modification, are permitted provided that the following conditions
+ *     are met:
+ *
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *
+ *        * Redistributions in binary form must reproduce the above copyright
+ *          notice, this list of conditions and the following disclaimer in
+ *          the documentation and/or other materials provided with the
+ *          distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *     POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \file	cabac_decoder.h
+ *
+ * \brief	Interfaces introduced for cabac decoder
+ *
+ * \date	10/10/2014 Created
+ *
+ *************************************************************************************
+ */
+#ifndef WELS_CABAC_DECODER_H__
+#define WELS_CABAC_DECODER_H__
+
+#include "decoder_context.h"
+#include "error_code.h"
+#include "wels_common_defs.h"
+namespace WelsDec {
+static const uint8_t g_kRenormTable256[256] = {
+  6, 6, 6, 6, 6, 6, 6, 6,
+  5, 5, 5, 5, 5, 5, 5, 5,
+  4, 4, 4, 4, 4, 4, 4, 4,
+  4, 4, 4, 4, 4, 4, 4, 4,
+  3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1
+};
+
+
+//1. CABAC context initialization
+void WelsCabacGlobalInit(PWelsDecoderContext pCabacCtx);
+void WelsCabacContextInit (PWelsDecoderContext  pCtx, uint8_t eSliceType, int32_t iCabacInitIdc, int32_t iQp);
+
+//2. decoding Engine initialization
+int32_t InitCabacDecEngineFromBS (PWelsCabacDecEngine pDecEngine, SBitStringAux* pBsAux);
+void RestoreCabacDecEngineToBS (PWelsCabacDecEngine pDecEngine, SBitStringAux* pBsAux);
+//3. actual decoding
+int32_t Read32BitsCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiValue, int32_t& iNumBitsRead);
+int32_t DecodeBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBit);
+int32_t DecodeBypassCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal);
+int32_t  DecodeTerminateCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal);
+
+//4. unary parsing
+int32_t DecodeUnaryBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, int32_t iCtxOffset,
+                             uint32_t& uiSymVal);
+
+//5. EXGk parsing
+int32_t DecodeExpBypassCabac (PWelsCabacDecEngine pDecEngine, int32_t iCount, uint32_t& uiSymVal);
+uint32_t DecodeUEGLevelCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBinVal);
+int32_t DecodeUEGMvCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t iMaxC,  uint32_t& uiCode);
+
+#define WELS_CABAC_HALF    0x01FE
+#define WELS_CABAC_QUARTER 0x0100
+#define WELS_CABAC_FALSE_RETURN(iErrorInfo) \
+if(iErrorInfo) { \
+  return iErrorInfo; \
+}
+}
+#endif
--- a/codec/decoder/core/inc/dec_frame.h
+++ b/codec/decoder/core/inc/dec_frame.h
@@ -66,10 +66,12 @@
   int8_t*  pMbType;
   int32_t* pSliceIdc;				// using int32_t for slice_idc
   int16_t	(*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
+  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*  pCbp;
+  uint8_t *pCbfDc;
   int8_t (*pNzc)[24];
   int8_t (*pNzcRs)[24];
   int8_t*  pResidualPredFlag;
--- a/codec/decoder/core/inc/dec_golomb.h
+++ b/codec/decoder/core/inc/dec_golomb.h
@@ -219,7 +219,7 @@
 static inline int32_t BsGetTrailingBits (uint8_t* pBuf) {
 // TODO
   uint32_t uiValue = *pBuf;
-  int32_t iRetNum = 1;
+  int32_t iRetNum = 0;
 
   do {
     if (uiValue & 1)
--- a/codec/decoder/core/inc/decode_slice.h
+++ b/codec/decoder/core/inc/decode_slice.h
@@ -38,12 +38,17 @@
 namespace WelsDec {
 
 int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx);
-int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur);
+int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
 
 int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx);
-int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur);
-typedef int32_t (*PWelsDecMbCavlcFunc) (PWelsDecoderContext pCtx, PNalUnit pNalCur);
+int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
+typedef int32_t (*PWelsDecMbFunc) (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
 
+int32_t WelsDecodeMbCabacISlice(PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
+int32_t WelsDecodeMbCabacPSlice(PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
+int32_t WelsDecodeMbCabacISliceBaseMode0(PWelsDecoderContext pCtx, uint32_t& uiEosFlag);
+int32_t WelsDecodeMbCabacPSliceBaseMode0(PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiEosFlag);
+
 int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx); //construction based on slice
 
 int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur);
@@ -77,6 +82,8 @@
 void SetNonZeroCount_c (int8_t* pNonZeroCount);
 
 void WelsBlockFuncInit (SBlockFunc* pFunc,  int32_t iCpu);
+void WelsBlockZero16x16_c(int16_t * block, int32_t stride);
+void WelsBlockZero8x8_c(int16_t * block, int32_t stride);
 
 } // namespace WelsDec
 
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -43,6 +43,7 @@
 #include "utils.h"
 #include "wels_const.h"
 #include "wels_common_basis.h"
+#include "wels_common_defs.h"
 #include "codec_app_def.h"
 #include "parameter_sets.h"
 #include "nalu.h"
@@ -56,7 +57,43 @@
 #include "expand_pic.h"
 
 namespace WelsDec {
+#define MAX_PRED_MODE_ID_I16x16  3
+#define MAX_PRED_MODE_ID_CHROMA  3
+#define MAX_PRED_MODE_ID_I4x4    8
+#define  WELS_QP_MAX    51
 
+typedef struct SWels_Cabac_Element {
+  uint8_t uiState;
+  uint8_t uiMPS;
+}SWelsCabacCtx, *PWelsCabacCtx;
+
+typedef struct
+{
+  uint64_t uiRange;
+  uint64_t uiOffset;
+  int32_t iBitsLeft;
+  uint8_t *pBuffStart;
+  uint8_t *pBuffCurr;
+  uint8_t *pBuffEnd;
+} SWelsCabacDecEngine, *PWelsCabacDecEngine;
+
+#define NEW_CTX_OFFSET_MB_TYPE_I 3
+#define NEW_CTX_OFFSET_SKIP 11
+#define NEW_CTX_OFFSET_SUBMB_TYPE 21
+#define NEW_CTX_OFFSET_MVD 40
+#define NEW_CTX_OFFSET_REF_NO 54
+#define NEW_CTX_OFFSET_DELTA_QP 60
+#define NEW_CTX_OFFSET_IPR 68
+#define NEW_CTX_OFFSET_CIPR 64
+#define NEW_CTX_OFFSET_CBP 73
+#define NEW_CTX_OFFSET_CBF 85
+#define NEW_CTX_OFFSET_MAP 105
+#define NEW_CTX_OFFSET_LAST 166
+#define NEW_CTX_OFFSET_ONE 227
+#define NEW_CTX_OFFSET_ABS 232
+#define CTX_NUM_MVD 7
+#define CTX_NUM_CBP 4
+
 typedef struct TagDataBuffer {
 uint8_t* pHead;
 uint8_t* pEnd;
@@ -141,16 +178,20 @@
 } SDeblockingFunc, *PDeblockingFunc;
 
 typedef void (*PWelsNonZeroCountFunc) (int8_t* pNonZeroCount);
-
+typedef void (*PWelsBlockZeroFunc) (int16_t* block,int32_t stride);
 typedef  struct  TagBlockFunc {
 PWelsNonZeroCountFunc		pWelsSetNonZeroCountFunc;
+PWelsBlockZeroFunc			pWelsBlockZero16x16Func;
+PWelsBlockZeroFunc			pWelsBlockZero8x8Func;
 } SBlockFunc;
 
-typedef void (*PWelsFillNeighborMbInfoIntra4x4Func) (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+typedef void (*PWelsFillNeighborMbInfoIntra4x4Func) (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
     int8_t* pIntraPredMode, PDqLayer pCurLayer);
-typedef int32_t (*PWelsParseIntra4x4ModeFunc) (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
+typedef void (*PWelsMapNeighToSample) (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail);
+typedef void (*PWelsMap16NeighToSample) (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail);
+typedef int32_t (*PWelsParseIntra4x4ModeFunc) (PWelsNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
     PDqLayer pCurDqLayer);
-typedef int32_t (*PWelsParseIntra16x16ModeFunc) (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
+typedef int32_t (*PWelsParseIntra16x16ModeFunc) (PWelsNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
 
 enum {
 OVERWRITE_NONE = 0,
@@ -202,6 +243,8 @@
   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*/
+  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];
   int8_t	(*pNzcRs[LAYER_NUM_EXCHANGEABLE])[24];
   int16_t (*pScaledTCoeff[LAYER_NUM_EXCHANGEABLE])[MB_COEFF_LIST_SIZE]; /*need be aligned*/
@@ -308,8 +351,8 @@
 int32_t iCurSeqIntervalMaxPicHeight;
 
 PWelsFillNeighborMbInfoIntra4x4Func  pFillInfoCacheIntra4x4Func;
-PWelsParseIntra4x4ModeFunc           pParseIntra4x4ModeFunc;
-PWelsParseIntra16x16ModeFunc         pParseIntra16x16ModeFunc;
+PWelsMapNeighToSample pMap4x4NeighToSampleFunc;
+PWelsMap16NeighToSample pMap16x16NeighToSampleFunc;
 
 //feedback whether or not have VCL in current AU, and the temporal ID
 int32_t iFeedbackVclNalInAu;
@@ -325,7 +368,10 @@
 //Save the last nal header info
 SNalUnitHeaderExt sLastNalHdrExt;
 SSliceHeader      sLastSliceHeader;
-
+SWelsCabacCtx sWelsCabacContexts[4][WELS_QP_MAX + 1][WELS_CONTEXT_COUNT];
+bool bCabacInited;
+SWelsCabacCtx   pCabacCtx[WELS_CONTEXT_COUNT];
+PWelsCabacDecEngine   pCabacDecEngine;
 } SWelsDecoderContext, *PWelsDecoderContext;
 
 static inline void ResetActiveSPSForEachLayer (PWelsDecoderContext pCtx) {
@@ -336,6 +382,7 @@
 //#ifdef __cplusplus
 //}
 //#endif//__cplusplus
+
 
 } // namespace WelsDec
 
--- a/codec/decoder/core/inc/error_code.h
+++ b/codec/decoder/core/inc/error_code.h
@@ -180,7 +180,9 @@
 ERR_INFO_INVALID_MMCO_SHOART2LONG,
 ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW,
 ERR_INFO_INVALID_MMCO_REF_NUM_NOT_ENOUGH,
-ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX
+ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX,
+//for CABAC
+ERR_CABAC_NO_BS_TO_READ,
 };
 //-----------------------------------------------------------------------------------------------------------
 
--- a/codec/decoder/core/inc/mb_cache.h
+++ b/codec/decoder/core/inc/mb_cache.h
@@ -69,7 +69,11 @@
 int32_t iTopType;
 int32_t iLeftTopType;
 int32_t iRightTopType;
-} SNeighAvail, *PNeighAvail;
+
+int8_t  iTopCbp;
+int8_t  iLeftCbp;
+int8_t iDummy[2]; //for align
+} SWelsNeighAvail, *PWelsNeighAvail;
 
 } // namespace WelsDec
 
--- /dev/null
+++ b/codec/decoder/core/inc/parse_mb_syn_cabac.h
@@ -1,0 +1,72 @@
+/*!
+ * \copy
+ *     Copyright (c)  2009-2013, Cisco Systems
+ *     All rights reserved.
+ *
+ *     Redistribution and use in source and binary forms, with or without
+ *     modification, are permitted provided that the following conditions
+ *     are met:
+ *
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *
+ *        * Redistributions in binary form must reproduce the above copyright
+ *          notice, this list of conditions and the following disclaimer in
+ *          the documentation and/or other materials provided with the
+ *          distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *     POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \file	parse_mb_syn_cabac.h
+ *
+ * \brief	cabac parse for syntax elements
+ *
+ * \date	10/10/2014 Created
+ *
+ *************************************************************************************
+ */
+#ifndef WELS_PARSE_MB_SYN_CABAC_H__
+#define WELS_PARSE_MB_SYN_CABAC_H__
+
+#include "decoder_context.h"
+#include "cabac_decoder.h"
+namespace WelsDec {
+int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal);
+int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip);
+int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
+int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
+int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType);
+int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal);
+int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal);
+int32_t ParseInterMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+                                   int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]);
+int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
+                          int8_t ref_idx[LIST_A][30],
+                          int32_t iListIdx, int32_t index, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal);
+int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
+                           int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal);
+int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
+int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta);
+int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t index, int32_t iResProperty,
+                           PWelsDecoderContext pCtx, uint32_t& uiCbpBit);
+int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
+                                  uint32_t& uiBinVal);
+int32_t ParseSignificantCoeffCabac (int32_t* significant, int32_t iResProperty, PWelsDecoderContext pCtx);
+int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
+                                 int32_t index, int32_t iMaxNumCoeff, const uint8_t* pScanTable, int32_t iResProperty, int16_t* sTCoeff, uint8_t uiQp,
+                                 PWelsDecoderContext pCtx);
+int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx);
+}
+//#pragma pack()
+#endif
--- a/codec/decoder/core/inc/parse_mb_syn_cavlc.h
+++ b/codec/decoder/core/inc/parse_mb_syn_cavlc.h
@@ -49,101 +49,19 @@
 
 namespace WelsDec {
 
-#define I16_LUMA_DC  1
-#define I16_LUMA_AC  2
-#define LUMA_DC_AC   3
-#define CHROMA_DC    4
-#define CHROMA_AC    5
 
-typedef struct TagReadBitsCache {
-uint32_t uiCache32Bit;
-uint8_t  uiRemainBits;
-uint8_t*  pBuf;
-} SReadBitsCache;
 
-#define SHIFT_BUFFER(pBitsCache)	{	pBitsCache->pBuf+=2; pBitsCache->uiRemainBits += 16; pBitsCache->uiCache32Bit |= (((pBitsCache->pBuf[2] << 8) | pBitsCache->pBuf[3]) << (32 - pBitsCache->uiRemainBits));	}
-#define POP_BUFFER(pBitsCache, iCount)	{ pBitsCache->uiCache32Bit <<= iCount;	pBitsCache->uiRemainBits -= iCount;	}
-
-static const uint8_t g_kuiZigzagScan[16] = { //4*4block residual zig-zag scan order
-0,  1,  4,  8,
-5,  2,  3,  6,
-9, 12, 13, 10,
-7, 11, 14, 15,
-};
-
-
-typedef struct TagI16PredInfo {
-int8_t iPredMode;
-int8_t iLeftAvail;
-int8_t iTopAvail;
-int8_t iLeftTopAvail;
-} SI16PredInfo;
-static const SI16PredInfo g_ksI16PredInfo[4] = {
-{I16_PRED_V, 0, 1, 0},
-{I16_PRED_H, 1, 0, 0},
-{         0, 0, 0, 0},
-{I16_PRED_P, 1, 1, 1},
-};
-
-static const SI16PredInfo g_ksChromaPredInfo[4] = {
-{       0, 0, 0, 0},
-{C_PRED_H, 1, 0, 0},
-{C_PRED_V, 0, 1, 0},
-{C_PRED_P, 1, 1, 1},
-};
-
-
-typedef struct TagI4PredInfo {
-int8_t iPredMode;
-int8_t iLeftAvail;
-int8_t iTopAvail;
-int8_t iLeftTopAvail;
-//	int8_t right_top_avail; //when right_top unavailable but top avail, we can pad the right-top with the rightmost pixel of top
-} SI4PredInfo;
-static const SI4PredInfo g_ksI4PredInfo[9] = {
-{  I4_PRED_V, 0, 1, 0},
-{  I4_PRED_H, 1, 0, 0},
-{          0, 0, 0, 0},
-{I4_PRED_DDL, 0, 1, 0},
-{I4_PRED_DDR, 1, 1, 1},
-{ I4_PRED_VR, 1, 1, 1},
-{ I4_PRED_HD, 1, 1, 1},
-{ I4_PRED_VL, 0, 1, 0},
-{ I4_PRED_HU, 1, 0, 0},
-};
-
-static const uint8_t g_kuiI16CbpTable[6] = {0, 16, 32, 15, 31, 47}; //reference to JM
-
-
-typedef struct TagPartMbInfo {
-MbType iType;
-int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
-int8_t iPartWidth; //based on 4*4 block
-} SPartMbInfo;
-static const SPartMbInfo g_ksInterMbTypeInfo[5] = {
-{MB_TYPE_16x16,    1, 4},
-{MB_TYPE_16x8,     2, 4},
-{MB_TYPE_8x16,     2, 2},
-{MB_TYPE_8x8,      4, 4},
-{MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
-};
-static const SPartMbInfo g_ksInterSubMbTypeInfo[4] = {
-{SUB_MB_TYPE_8x8, 1, 2},
-{SUB_MB_TYPE_8x4, 2, 2},
-{SUB_MB_TYPE_4x8, 2, 1},
-{SUB_MB_TYPE_4x4, 4, 1},
-};
-
-void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer);
-void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, PDqLayer pCurLayer);
-void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
+void GetNeighborAvailMbType (PWelsNeighAvail pNeighAvail, PDqLayer pCurLayer);
+void WelsFillCacheNonZeroCount (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, PDqLayer pCurLayer);
+void WelsFillCacheConstrain0Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
                                       PDqLayer pCurLayer);
-void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
+void WelsFillCacheConstrain1Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
                                       PDqLayer pCurLayer);
-void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+void WelsFillCacheInterCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+                         int16_t iMvArray[LIST_A][30][MV_A], int16_t iMvdCache[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer);
+void WelsFillCacheInter (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
                          int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer);
 
-
 /*!
  * \brief   check iPredMode for intra16x16 eligible or not
  * \param 	input : current iPredMode
@@ -190,19 +108,7 @@
                                 PWelsDecoderContext pCtx);
 
 /*!
- * \brief   parsing intra mode
- * \param 	input : current mb, bit-stream
- * \param 	output: 0 indicating decoding correctly; -1 means error
- */
-int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
-                                     PDqLayer pCurDqLayer);
-int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
-                                     PDqLayer pCurDqLayer);
-int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
-int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
-
-/*!
- * \brief   parsing inter info (including ref_index and mvd)
+ * \brief   parsing inter info (including ref_index and pMvd)
  * \param 	input : decoding context, current mb, bit-stream
  * \param 	output: 0 indicating decoding correctly; -1 means error
  */
--- a/codec/decoder/core/inc/slice.h
+++ b/codec/decoder/core/inc/slice.h
@@ -197,6 +197,7 @@
 /*from lower layer: slice header*/
 uint8_t		eSliceType;
 uint8_t		uiPadding[2];
+int32_t     iLastDeltaQp;
 } SSlice, *PSlice;
 
 } // namespace WelsDec
--- a/codec/decoder/core/inc/wels_common_basis.h
+++ b/codec/decoder/core/inc/wels_common_basis.h
@@ -47,6 +47,11 @@
 extern const uint8_t g_kuiScan8[24];
 extern const uint8_t g_kuiLumaDcZigzagScan[16];
 extern const uint8_t g_kuiChromaDcScan[4];
+extern const uint8_t g_kMbNonZeroCountIdx[24];
+extern const uint8_t g_kCacheNzcScanIdx[4*4+4+4+3];
+extern const uint8_t g_kCache26ScanIdx[16];
+extern const uint8_t g_kCache30ScanIdx[16];
+extern const uint8_t g_kNonZeroScanIdxC[4];
 /* Profile IDC */
 typedef uint8_t		ProfileIdc;
 enum {
@@ -118,7 +123,94 @@
 #define IS_I_BL(type) ( (type) == MB_TYPE_INTRA_BL )
 #define IS_SUB8x8(type) (MB_TYPE_8x8 == (type) || MB_TYPE_8x8_REF0 == (type))
 
+#define I16_LUMA_DC  1
+#define I16_LUMA_AC  2
+#define LUMA_DC_AC   3
+#define CHROMA_DC    4
+#define CHROMA_AC    5
+#define CHROMA_DC_U  6
+#define CHROMA_DC_V  7
+#define CHROMA_AC_U  8
+#define CHROMA_AC_V  9
 
+typedef struct TagReadBitsCache {
+    uint32_t uiCache32Bit;
+    uint8_t  uiRemainBits;
+    uint8_t*  pBuf;
+} SReadBitsCache;
+
+#define SHIFT_BUFFER(pBitsCache)	{	pBitsCache->pBuf+=2; pBitsCache->uiRemainBits += 16; pBitsCache->uiCache32Bit |= (((pBitsCache->pBuf[2] << 8) | pBitsCache->pBuf[3]) << (32 - pBitsCache->uiRemainBits));	}
+#define POP_BUFFER(pBitsCache, iCount)	{ pBitsCache->uiCache32Bit <<= iCount;	pBitsCache->uiRemainBits -= iCount;	}
+
+static const uint8_t g_kuiZigzagScan[16] = { //4*4block residual zig-zag scan order
+    0,  1,  4,  8,
+    5,  2,  3,  6,
+    9, 12, 13, 10,
+    7, 11, 14, 15,
+};
+
+
+typedef struct TagI16PredInfo {
+    int8_t iPredMode;
+    int8_t iLeftAvail;
+    int8_t iTopAvail;
+    int8_t iLeftTopAvail;
+} SI16PredInfo;
+static const SI16PredInfo g_ksI16PredInfo[4] = {
+    {I16_PRED_V, 0, 1, 0},
+    {I16_PRED_H, 1, 0, 0},
+    {         0, 0, 0, 0},
+    {I16_PRED_P, 1, 1, 1},
+};
+
+static const SI16PredInfo g_ksChromaPredInfo[4] = {
+    {       0, 0, 0, 0},
+    {C_PRED_H, 1, 0, 0},
+    {C_PRED_V, 0, 1, 0},
+    {C_PRED_P, 1, 1, 1},
+};
+
+
+typedef struct TagI4PredInfo {
+    int8_t iPredMode;
+    int8_t iLeftAvail;
+    int8_t iTopAvail;
+    int8_t iLeftTopAvail;
+    //	int8_t right_top_avail; //when right_top unavailable but top avail, we can pad the right-top with the rightmost pixel of top
+} SI4PredInfo;
+static const SI4PredInfo g_ksI4PredInfo[9] = {
+    {  I4_PRED_V, 0, 1, 0},
+    {  I4_PRED_H, 1, 0, 0},
+    {          0, 0, 0, 0},
+    {I4_PRED_DDL, 0, 1, 0},
+    {I4_PRED_DDR, 1, 1, 1},
+    { I4_PRED_VR, 1, 1, 1},
+    { I4_PRED_HD, 1, 1, 1},
+    { I4_PRED_VL, 0, 1, 0},
+    { I4_PRED_HU, 1, 0, 0},
+};
+
+static const uint8_t g_kuiI16CbpTable[6] = {0, 16, 32, 15, 31, 47}; 
+
+
+typedef struct TagPartMbInfo {
+    MbType iType;
+    int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
+    int8_t iPartWidth; //based on 4*4 block
+} SPartMbInfo;
+static const SPartMbInfo g_ksInterMbTypeInfo[5] = {
+    {MB_TYPE_16x16,    1, 4},
+    {MB_TYPE_16x8,     2, 4},
+    {MB_TYPE_8x16,     2, 2},
+    {MB_TYPE_8x8,      4, 4},
+    {MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
+};
+static const SPartMbInfo g_ksInterSubMbTypeInfo[4] = {
+    {SUB_MB_TYPE_8x8, 1, 2},
+    {SUB_MB_TYPE_8x4, 2, 2},
+    {SUB_MB_TYPE_4x8, 2, 1},
+    {SUB_MB_TYPE_4x4, 4, 1},
+};
 
 } // namespace WelsDec
 
--- a/codec/decoder/core/inc/wels_const.h
+++ b/codec/decoder/core/inc/wels_const.h
@@ -96,4 +96,10 @@
 #define MAX_ACCESS_UNIT_CAPACITY 7077888 //Maximum AU size in bytes for level 5.2 for single frame
 #define MAX_MACROBLOCK_CAPACITY 5000 //Maximal legal MB capacity, 15000 bits is enough
 
+enum {
+    BASE_MB = 0,
+    NON_AVC_REWRITE_ENHANCE_MB =1,
+    AVC_REWRITE_ENHANCE_MB = 2
+};
+
 #endif//WELS_CONSTANCE_H__
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -43,7 +43,6 @@
 #include "error_code.h"
 #include "memmgr_nal_unit.h"
 #include "decoder_core.h"
-#include "decoder_core.h"
 
 namespace WelsDec {
 /*!
@@ -227,14 +226,18 @@
     pCurNal->sNalHeaderExt.sNalUnitHeader.uiForbiddenZeroBit = pNalUnitHeader->uiForbiddenZeroBit;
     pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc		  = pNalUnitHeader->uiNalRefIdc;
     pCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType	      = pNalUnitHeader->eNalUnitType;
+    if (pNalUnitHeader->uiNalRefIdc != 0) {
+      pBs = &pCtx->sBs;
+      iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
 
-    pBs = &pCtx->sBs;
-
-    iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
-
-    InitBits (pBs, pNal, iBitSize);
-
-    ParsePrefixNalUnit (pCtx, pBs);
+      iErr = InitBits (pBs, pNal, iBitSize);
+      if (iErr) {
+        WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_PREFIX: InitBits() fail due invalid access.");
+        pCtx->iErrorCode	|= dsBitstreamError;
+        return NULL;
+      }
+      ParsePrefixNalUnit (pCtx, pBs);
+    }
     pCurNal->sNalData.sPrefixNal.bPrefixNalCorrectFlag = true;
 
     break;
@@ -309,7 +312,12 @@
 
     pBs = &pCurAu->pNalUnitsList[uiAvailNalNum - 1]->sNalData.sVclNal.sSliceBitsRead;
     iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
-    InitBits (pBs, pNal, iBitSize);
+    iErr = InitBits (pBs, pNal, iBitSize);
+    if (iErr) {
+      WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_CODED_SLICE: InitBits() fail due invalid access.");
+      pCtx->iErrorCode	|= dsBitstreamError;
+      return NULL;
+    }
     iErr = ParseSliceHeaderSyntaxs (pCtx, pBs, bExtensionFlag);
     if (iErr != ERR_NONE) {
       if ((uiAvailNalNum == 1) && (pCurNal->sNalHeaderExt.bIdrFlag)) { //IDR parse error
@@ -505,8 +513,16 @@
   switch (eNalType) {
   case NAL_UNIT_SPS:
   case NAL_UNIT_SUBSET_SPS:
-    if (iBitSize > 0)
-      InitBits (pBs, pRbsp, iBitSize);
+    if (iBitSize > 0) {
+      iErr = InitBits (pBs, pRbsp, iBitSize);
+      if (ERR_NONE != iErr) {
+        if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
+          pCtx->iErrorCode |= dsNoParamSets;
+        else
+          pCtx->iErrorCode |= dsBitstreamError;
+        return iErr;
+      }
+    }
     iErr = ParseSps (pCtx, pBs, &iPicWidth, &iPicHeight);
     if (ERR_NONE != iErr) {	// modified for pSps/pSubsetSps invalid, 12/1/2009
       if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
@@ -519,8 +535,16 @@
     break;
 
   case NAL_UNIT_PPS:
-    if (iBitSize > 0)
-      InitBits (pBs, pRbsp, iBitSize);
+    if (iBitSize > 0) {
+      iErr = InitBits (pBs, pRbsp, iBitSize);
+      if (ERR_NONE != iErr) {
+        if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
+          pCtx->iErrorCode |= dsNoParamSets;
+        else
+          pCtx->iErrorCode |= dsBitstreamError;
+        return iErr;
+      }
+    }
     iErr = ParsePps (pCtx, &pCtx->sPpsBuffer[0], pBs);
     if (ERR_NONE != iErr) {	// modified for pps invalid, 12/1/2009
       if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
--- a/codec/decoder/core/src/bit_stream.cpp
+++ b/codec/decoder/core/src/bit_stream.cpp
@@ -38,6 +38,7 @@
  *************************************************************************************
  */
 #include "bit_stream.h"
+#include "error_code.h"
 
 namespace WelsDec {
 
@@ -47,10 +48,14 @@
   return uiValue;
 }
 
-void InitReadBits (PBitStringAux pBitString) {
+int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset) {
+  if(pBitString->pCurBuf>=(pBitString->pEndBuf - iEndOffset)) {
+    return ERR_INFO_INVALID_ACCESS;
+  }
   pBitString->uiCurBits  = GetValue4Bytes (pBitString->pCurBuf);
   pBitString->pCurBuf  += 4;
   pBitString->iLeftBits = -16;
+  return ERR_NONE;
 }
 
 /*!
@@ -60,7 +65,7 @@
  * \param	kpBuf		bit-stream buffer
  * \param	kiSize	    size in bits for decoder; size in bytes for encoder
  *
- * \return	size of buffer data in byte; failed in -1 return
+ * \return	0: success, other: fail
  */
 int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t kiSize) {
   const int32_t kiSizeBuf = (kiSize + 7) >> 3;
@@ -67,16 +72,17 @@
   uint8_t* pTmp = (uint8_t*)kpBuf;
 
   if (NULL == pTmp)
-    return -1;
+    return ERR_INFO_INVALID_ACCESS;
 
   pBitString->pStartBuf   = pTmp;				// buffer to start position
   pBitString->pEndBuf	    = pTmp + kiSizeBuf;	// buffer + length
   pBitString->iBits	    = kiSize;				// count bits of overall bitstreaming inputindex;
-
   pBitString->pCurBuf   = pBitString->pStartBuf;
-  InitReadBits (pBitString);
-
-  return kiSizeBuf;
+  int32_t iErr = InitReadBits (pBitString, 0);
+  if(iErr) {
+    return iErr;
+  }
+  return ERR_NONE;
 }
 
 } // namespace WelsDec
--- /dev/null
+++ b/codec/decoder/core/src/cabac_decoder.cpp
@@ -1,0 +1,330 @@
+/*!
+ * \copy
+ *     Copyright (c)  2013, Cisco Systems
+ *     All rights reserved.
+ *
+ *     Redistribution and use in source and binary forms, with or without
+ *     modification, are permitted provided that the following conditions
+ *     are met:
+ *
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *
+ *        * Redistributions in binary form must reproduce the above copyright
+ *          notice, this list of conditions and the following disclaimer in
+ *          the documentation and/or other materials provided with the
+ *          distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *     POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	cabac_decoder.cpp:	deals with cabac state transition and related functions
+ */
+#include "cabac_decoder.h"
+namespace WelsDec {
+static const int16_t g_kMvdBinPos2Ctx [8] = {0, 1, 2, 3, 3, 3, 3, 3};
+
+void WelsCabacGlobalInit (PWelsDecoderContext pCtx) {
+  for (int32_t iModel = 0; iModel < 4; iModel++) {
+    for (int32_t iQp = 0; iQp <= WELS_QP_MAX; iQp++)
+      for (int32_t iIdx = 0; iIdx < WELS_CONTEXT_COUNT; iIdx++) {
+        int32_t m               = g_kiCabacGlobalContextIdx[iIdx][iModel][0];
+        int32_t n               = g_kiCabacGlobalContextIdx[iIdx][iModel][1];
+        int32_t iPreCtxState    = WELS_CLIP3 ((((m * iQp) >> 4) + n), 1, 126);
+        uint8_t uiValMps         = 0;
+        uint8_t uiStateIdx       = 0;
+        if (iPreCtxState <= 63) {
+          uiStateIdx = 63 - iPreCtxState;
+          uiValMps = 0;
+        } else {
+          uiStateIdx = iPreCtxState - 64;
+          uiValMps = 1;
+        }
+        pCtx->sWelsCabacContexts[iModel][iQp][iIdx].uiState = uiStateIdx;
+        pCtx->sWelsCabacContexts[iModel][iQp][iIdx].uiMPS = uiValMps;
+      }
+  }
+  pCtx->bCabacInited = true;
+}
+
+// ------------------- 1. context initialization
+void WelsCabacContextInit (PWelsDecoderContext  pCtx, uint8_t eSliceType, int32_t iCabacInitIdc, int32_t iQp) {
+  int32_t iIdx =  pCtx->eSliceType == WelsCommon::I_SLICE ? 0 : iCabacInitIdc + 1;
+  if (!pCtx->bCabacInited) {
+    WelsCabacGlobalInit (pCtx);
+  }
+  memcpy (pCtx->pCabacCtx, pCtx->sWelsCabacContexts[iIdx][iQp],
+          WELS_CONTEXT_COUNT * sizeof (SWelsCabacCtx));
+}
+
+// ------------------- 2. decoding Engine initialization
+int32_t InitCabacDecEngineFromBS (PWelsCabacDecEngine pDecEngine, PBitStringAux pBsAux) {
+  int32_t iRemainingBits = - pBsAux->iLeftBits; //pBsAux->iLeftBits < 0
+  int32_t iRemainingBytes = (iRemainingBits >> 3) + 2; //+2: indicating the pre-read 2 bytes
+  uint8_t* pCurr;
+
+  pCurr = pBsAux->pCurBuf - iRemainingBytes;
+  if(pCurr >= (pBsAux->pEndBuf - 1)) {
+    return ERR_INFO_INVALID_ACCESS;
+  }
+  pDecEngine->uiOffset = ((pCurr[0] << 16) | (pCurr[1] << 8) | pCurr[2]);
+  pDecEngine->uiOffset <<= 16;
+  pDecEngine->uiOffset |= (pCurr[3] << 8) | pCurr[4];
+  pDecEngine->iBitsLeft = 31;
+  pDecEngine->pBuffCurr = pCurr + 5;
+
+  pDecEngine->uiRange = WELS_CABAC_HALF;
+  pDecEngine->pBuffStart = pBsAux->pStartBuf;
+  pDecEngine->pBuffEnd = pBsAux->pEndBuf;
+  pBsAux->iLeftBits = 0;
+  return ERR_NONE;
+}
+
+void RestoreCabacDecEngineToBS (PWelsCabacDecEngine pDecEngine, PBitStringAux pBsAux) {
+  //CABAC decoding finished, changing to SBitStringAux
+  pDecEngine->pBuffCurr -= (pDecEngine->iBitsLeft >> 3);
+  pDecEngine->iBitsLeft = 0;     //pcm_alignment_zero_bit in CABAC
+  pBsAux->iLeftBits = 0;
+  pBsAux->pStartBuf = pDecEngine->pBuffStart;
+  pBsAux->pCurBuf = pDecEngine->pBuffCurr;
+  pBsAux->uiCurBits = 0;
+  pBsAux->iIndex = 0;
+}
+
+// ------------------- 3. actual decoding
+int32_t Read32BitsCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiValue, int32_t& iNumBitsRead) {
+  intX_t iLeftBytes = pDecEngine->pBuffEnd - pDecEngine->pBuffCurr;
+  iNumBitsRead = 0;
+  uiValue = 0;
+  if (iLeftBytes <= 0) {
+    return ERR_CABAC_NO_BS_TO_READ;
+  }
+  switch (iLeftBytes) {
+  case 3:
+    uiValue = ((pDecEngine->pBuffCurr[0]) << 16 | (pDecEngine->pBuffCurr[1]) << 8 | (pDecEngine->pBuffCurr[2]));
+    pDecEngine->pBuffCurr += 3;
+    iNumBitsRead = 24;
+    break;
+  case 2:
+    uiValue = ((pDecEngine->pBuffCurr[0]) << 8 | (pDecEngine->pBuffCurr[1]));
+    pDecEngine->pBuffCurr += 2;
+    iNumBitsRead = 16;
+    break;
+  case 1:
+    uiValue = pDecEngine->pBuffCurr[0];
+    pDecEngine->pBuffCurr += 1;
+    iNumBitsRead = 8;
+    break;
+  default:
+    uiValue = ((pDecEngine->pBuffCurr[0] << 24) | (pDecEngine->pBuffCurr[1]) << 16 | (pDecEngine->pBuffCurr[2]) << 8 |
+               (pDecEngine->pBuffCurr[3]));
+    pDecEngine->pBuffCurr += 4;
+    iNumBitsRead = 32;
+    break;
+  }
+  return ERR_NONE;
+}
+
+int32_t DecodeBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBinVal) {
+  int32_t iErrorInfo = ERR_NONE;
+  uint32_t uiState = pBinCtx->uiState;
+  uiBinVal = pBinCtx->uiMPS;
+  uint64_t uiOffset = pDecEngine->uiOffset;
+  uint64_t uiRange = pDecEngine->uiRange;
+
+  int32_t iRenorm = 1;
+  uint32_t uiRangeLPS = g_kuiCabacRangeLps[uiState][ (uiRange >> 6) & 0x03];
+  uiRange -= uiRangeLPS;
+  if (uiOffset >= (uiRange << pDecEngine->iBitsLeft)) { //LPS
+    uiOffset -= (uiRange << pDecEngine->iBitsLeft);
+    uiBinVal ^= 0x0001;
+    if (!uiState)
+      pBinCtx->uiMPS ^= 0x01;
+    pBinCtx->uiState = g_kuiStateTransTable[uiState][0];
+    iRenorm = g_kRenormTable256[uiRangeLPS];
+    uiRange = (uiRangeLPS << iRenorm);
+  } else {  //MPS
+    pBinCtx->uiState = g_kuiStateTransTable[uiState][1];
+    if (uiRange >= WELS_CABAC_QUARTER) {
+      pDecEngine->uiRange = uiRange;
+      return ERR_NONE;
+    } else {
+      uiRange <<= 1;
+    }
+  }
+  //Renorm
+  pDecEngine->uiRange = uiRange;
+  pDecEngine->iBitsLeft -= iRenorm;
+  if (pDecEngine->iBitsLeft > 0) {
+    pDecEngine->uiOffset = uiOffset;
+    return ERR_NONE;
+  }
+  uint32_t uiVal = 0;
+  int32_t iNumBitsRead = 0;
+  iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);
+  pDecEngine->uiOffset = (uiOffset << iNumBitsRead) | uiVal;
+  pDecEngine->iBitsLeft += iNumBitsRead;
+  if (iErrorInfo && pDecEngine->iBitsLeft < 0) {
+    return iErrorInfo;
+  }
+  return ERR_NONE;
+}
+
+int32_t DecodeBypassCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal) {
+  int32_t iErrorInfo = ERR_NONE;
+  int32_t iBitsLeft = pDecEngine->iBitsLeft;
+  uint64_t uiOffset = pDecEngine->uiOffset;
+  uint64_t uiRangeValue;
+
+
+  if (iBitsLeft <= 0) {
+    uint32_t uiVal = 0;
+    int32_t iNumBitsRead = 0;
+    iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);
+    uiOffset = (uiOffset << iNumBitsRead) | uiVal;
+    iBitsLeft = iNumBitsRead;
+    if (iErrorInfo && iBitsLeft == 0) {
+      return iErrorInfo;
+    }
+  }
+  iBitsLeft--;
+  uiRangeValue = (pDecEngine->uiRange << iBitsLeft);
+  if (uiOffset >= uiRangeValue) {
+    pDecEngine->iBitsLeft = iBitsLeft;
+    pDecEngine->uiOffset = uiOffset - uiRangeValue;
+    uiBinVal = 1;
+    return ERR_NONE;
+  }
+  pDecEngine->iBitsLeft = iBitsLeft;
+  pDecEngine->uiOffset = uiOffset;
+  uiBinVal = 0;
+  return ERR_NONE;
+}
+
+int32_t DecodeTerminateCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal) {
+  int32_t iErrorInfo = ERR_NONE;
+  uint64_t uiRange = pDecEngine->uiRange - 2;
+  int64_t uiOffset = pDecEngine->uiOffset;
+
+  if (uiOffset >= (uiRange << pDecEngine->iBitsLeft)) {
+    uiBinVal = 1;
+  } else {
+    uiBinVal = 0;
+    // Renorm
+    if (uiRange < WELS_CABAC_QUARTER) {
+      int32_t iRenorm = g_kRenormTable256[uiRange];
+      pDecEngine->uiRange = (uiRange << iRenorm);
+      pDecEngine->iBitsLeft -= iRenorm;
+      if (pDecEngine->iBitsLeft < 0) {
+        uint32_t uiVal = 0;
+        int32_t iNumBitsRead = 0;
+        iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);
+        pDecEngine->uiOffset = (pDecEngine->uiOffset << iNumBitsRead) | uiVal;
+        pDecEngine->iBitsLeft += iNumBitsRead;
+      }
+      if (iErrorInfo && pDecEngine->iBitsLeft < 0) {
+        return iErrorInfo;
+      }
+      return ERR_NONE;
+    } else {
+      pDecEngine->uiRange = uiRange;
+      return ERR_NONE;
+    }
+  }
+  return ERR_NONE;
+}
+
+int32_t DecodeUnaryBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, int32_t iCtxOffset,
+                             uint32_t& uiSymVal) {
+  uiSymVal = 0;
+  WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiSymVal));
+  if (uiSymVal == 0) {
+    return ERR_NONE;
+  } else {
+    uint32_t uiCode;
+    pBinCtx += iCtxOffset;
+    uiSymVal = 0;
+    do {
+      WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiCode));
+      ++uiSymVal;
+    } while (uiCode != 0);
+    return ERR_NONE;
+  }
+}
+
+int32_t DecodeExpBypassCabac (PWelsCabacDecEngine pDecEngine, int32_t iCount, uint32_t& uiSymVal) {
+  uint32_t uiCode;
+  int32_t iSymTmp = 0;
+  int32_t iSymTmp2 = 0;
+  uiSymVal = 0;
+  do {
+    WELS_READ_VERIFY (DecodeBypassCabac (pDecEngine, uiCode));
+    if (uiCode == 1) {
+      iSymTmp += (1 << iCount);
+      ++iCount;
+    }
+  } while (uiCode != 0);
+
+  while (iCount--) {
+    WELS_READ_VERIFY (DecodeBypassCabac (pDecEngine, uiCode));
+    if (uiCode == 1) {
+      iSymTmp2 |= (1 << iCount);
+    }
+  }
+  uiSymVal = (uint32_t) (iSymTmp + iSymTmp2);
+  return ERR_NONE;
+}
+
+uint32_t DecodeUEGLevelCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiCode) {
+  uiCode = 0;
+  WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiCode));
+  if (uiCode == 0)
+    return ERR_NONE;
+  else {
+    uint32_t uiTmp, uiCount = 1;
+    uiCode = 0;
+    do {
+      WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiTmp));
+      ++uiCode;
+      ++uiCount;
+    } while (uiTmp != 0 && uiCount != 13);
+
+    if (uiTmp != 0) {
+      WELS_READ_VERIFY (DecodeExpBypassCabac (pDecEngine, 0, uiTmp));
+      uiCode += uiTmp + 1;
+    }
+    return ERR_NONE;
+  }
+  return ERR_NONE;
+}
+
+int32_t DecodeUEGMvCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t iMaxBin,  uint32_t& uiCode) {
+  WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx + g_kMvdBinPos2Ctx[0], uiCode));
+  if (uiCode == 0)
+    return ERR_NONE;
+  else {
+    uint32_t uiTmp, uiCount = 1;
+    uiCode = 0;
+    do {
+      WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx + g_kMvdBinPos2Ctx[uiCount++], uiTmp));
+      uiCode++;
+    } while (uiTmp != 0 && uiCount != 8);
+
+    if (uiTmp != 0) {
+      WELS_READ_VERIFY (DecodeExpBypassCabac (pDecEngine, 3, uiTmp));
+      uiCode += (uiTmp + 1);
+    }
+    return ERR_NONE;
+  }
+}
+}
--- a/codec/decoder/core/src/decode_slice.cpp
+++ b/codec/decoder/core/src/decode_slice.cpp
@@ -44,6 +44,7 @@
 #include "decode_slice.h"
 
 #include "parse_mb_syn_cavlc.h"
+#include "parse_mb_syn_cabac.h"
 #include "rec_mb.h"
 #include "mv_pred.h"
 
@@ -318,6 +319,576 @@
   pBlk[iStride1] = (iE - iB) >> 1;
 }
 
+void WelsMap4x4NeighToSampleNormal (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {
+  if (pNeighAvail->iLeftAvail) {  //left
+    pSampleAvail[ 6] =
+      pSampleAvail[12] =
+        pSampleAvail[18] =
+          pSampleAvail[24] = 1;
+  }
+  if (pNeighAvail->iLeftTopAvail) { //top_left
+    pSampleAvail[0] = 1;
+  }
+  if (pNeighAvail->iTopAvail) { //top
+    pSampleAvail[1] =
+      pSampleAvail[2] =
+        pSampleAvail[3] =
+          pSampleAvail[4] = 1;
+  }
+  if (pNeighAvail->iRightTopAvail) { //top_right
+    pSampleAvail[5] = 1;
+  }
+}
+
+void WelsMap4x4NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {
+  if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {   //left
+    pSampleAvail[ 6] =
+      pSampleAvail[12] =
+        pSampleAvail[18] =
+          pSampleAvail[24] = 1;
+  }
+  if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {  //top_left
+    pSampleAvail[0] = 1;
+  }
+  if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {  //top
+    pSampleAvail[1] =
+      pSampleAvail[2] =
+        pSampleAvail[3] =
+          pSampleAvail[4] = 1;
+  }
+  if (pNeighAvail->iRightTopAvail && IS_INTRA (pNeighAvail->iRightTopType)) {  //top_right
+    pSampleAvail[5] = 1;
+  }
+}
+void WelsMap16x16NeighToSampleNormal (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {
+  if (pNeighAvail->iLeftAvail) {
+    *pSampleAvail = (1 << 2);
+  }
+  if (pNeighAvail->iLeftTopAvail) {
+    *pSampleAvail |= (1 << 1);
+  }
+  if (pNeighAvail->iTopAvail) {
+    *pSampleAvail |= 1;
+  }
+}
+
+void WelsMap16x16NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {
+  if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {
+    *pSampleAvail = (1 << 2);
+  }
+  if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {
+    *pSampleAvail |= (1 << 1);
+  }
+  if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {
+    *pSampleAvail |= 1;
+  }
+}
+
+int32_t ParseIntra4x4Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t* pIntraPredMode,
+                           PBitStringAux pBs,
+                           PDqLayer pCurDqLayer) {
+  int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  int32_t iFinalMode, i;
+
+  uint8_t uiNeighAvail = 0;
+  uint32_t uiCode;
+  int32_t iCode;
+  pCtx->pMap4x4NeighToSampleFunc (pNeighAvail, iSampleAvail);
+  uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
+  for (i = 0; i < 16; i++) {
+    int32_t iPrevIntra4x4PredMode = 0;
+    if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
+      WELS_READ_VERIFY (ParseIntraPredModeLumaCabac (pCtx, iCode));
+      iPrevIntra4x4PredMode = iCode;
+    } else {
+      WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
+      iPrevIntra4x4PredMode = uiCode;
+    }
+    const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
+
+    int8_t iBestMode;
+    if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
+      if (iPrevIntra4x4PredMode == -1)
+        iBestMode = kiPredMode;
+      else
+        iBestMode = iPrevIntra4x4PredMode + (iPrevIntra4x4PredMode >= kiPredMode);
+    } else {
+      if (iPrevIntra4x4PredMode) {
+        iBestMode = kiPredMode;
+      } else {
+        WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode));
+        iBestMode = uiCode + (uiCode >= kiPredMode);
+      }
+    }
+
+    iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
+    if (iFinalMode  == ERR_INVALID_INTRA4X4_MODE) {
+      return ERR_INFO_INVALID_I4x4_PRED_MODE;
+    }
+
+    pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
+
+    pIntraPredMode[g_kuiScan8[i]] = iBestMode;
+
+    iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
+  }
+  ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
+  pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
+  pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
+  pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
+  if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
+    WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));
+    if (iCode > MAX_PRED_MODE_ID_CHROMA) {
+      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
+    }
+    pCurDqLayer->pChromaPredMode[iMbXy] = iCode;
+  } else {
+    WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
+    if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
+      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
+    }
+    pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
+  }
+
+  if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
+      || CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
+    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
+  }
+
+  return ERR_NONE;
+}
+
+int32_t ParseIntra16x16Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, PBitStringAux pBs,
+                             PDqLayer pCurDqLayer) {
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
+  uint32_t uiCode;
+  int32_t iCode;
+  pCtx->pMap16x16NeighToSampleFunc (pNeighAvail, &uiNeighAvail);
+
+  if (CheckIntra16x16PredMode (uiNeighAvail,
+                               &pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
+    return ERR_INFO_INVALID_I16x16_PRED_MODE;
+  }
+  if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
+    WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));
+    if (iCode > MAX_PRED_MODE_ID_CHROMA) {
+      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
+    }
+    pCurDqLayer->pChromaPredMode[iMbXy] = iCode;
+  } else {
+    WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
+    if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
+      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
+    }
+    pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
+  }
+  if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
+      || CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
+    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
+  }
+
+  return ERR_NONE;
+}
+
+int32_t WelsDecodeMbCabacISliceBaseMode0 (PWelsDecoderContext pCtx, uint32_t& uiEosFlag) {
+  PDqLayer pCurLayer		 = pCtx->pCurDqLayer;
+  PBitStringAux pBsAux		 = pCurLayer->pBitStringAux;
+  PSlice pSlice			 = &pCurLayer->sLayerInfo.sSliceInLayer;
+  PSliceHeader pSliceHeader		 = &pSlice->sSliceHeaderExt.sSliceHeader;
+  SWelsNeighAvail sNeighAvail;
+  int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
+  int32_t iScanIdxEnd   = pSlice->sSliceHeaderExt.uiScanIdxEnd;
+  int32_t iMbXy = pCurLayer->iMbXyIndex;
+  int32_t iMbMode, i;
+  uint32_t uiMbType = 0, uiCbp = 0, uiCbpLuma = 0, uiCbpChroma = 0;
+
+  ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
+
+  pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
+  pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag;
+  GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
+  WELS_READ_VERIFY (ParseMBTypeISliceCabac (pCtx, &sNeighAvail, uiMbType));
+  if (uiMbType > 25) {
+    return ERR_INFO_INVALID_MB_TYPE;
+  } else if (25 == uiMbType) {   //I_PCM
+    WELS_READ_VERIFY (ParseIPCMInfoCabac (pCtx));
+    WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
+    if (uiEosFlag) {
+      RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
+    }
+    return ERR_NONE;
+  } else if (0 == uiMbType) { //I4x4
+    ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
+    pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
+    pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
+    WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBsAux, pCurLayer));
+    //get uiCbp for I4x4
+    WELS_READ_VERIFY (ParseCbpInfoCabac (pCtx, &sNeighAvail, uiCbp));
+    pCurLayer->pCbp[iMbXy] = uiCbp;
+    uiCbpChroma = uiCbp >> 4;
+    uiCbpLuma = uiCbp & 15;
+  } else { //I16x16;
+    pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA16x16;
+    pCurLayer->pIntraPredMode[iMbXy][7] = (uiMbType - 1) & 3;
+    pCurLayer->pCbp[iMbXy] = g_kuiI16CbpTable[ (uiMbType - 1) >> 2];
+    uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
+    uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
+    WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
+    WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBsAux, pCurLayer));
+  }
+  iMbMode = BASE_MB;
+
+  memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (pCurLayer->pScaledTCoeff[iMbXy][0]));
+  ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
+  pCurLayer->pCbfDc[iMbXy] = 0;
+
+  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)];
+  }
+
+  if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
+    int32_t iQpDelta, iId8x8, iId4x4;
+    WELS_READ_VERIFY (ParseDeltaQpCabac (pCtx, iQpDelta));
+    if (iQpDelta > 25 || iQpDelta < -26) {//out of iQpDelta range
+      return ERR_INFO_INVALID_QP;
+    }
+    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)];
+    if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
+      //step1: Luma DC
+      WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 0, 16, g_kuiLumaDcZigzagScan,
+                        I16_LUMA_DC, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy], pCtx));
+      //step2: Luma AC
+      if (uiCbpLuma) {
+        for (i = 0; i < 16; i++) {
+          WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, i,
+                            iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), I16_LUMA_AC,
+                            pCurLayer->pScaledTCoeff[iMbXy] + (i << 4), pCurLayer->pLumaQp[iMbXy], pCtx));
+        }
+        ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
+        ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
+        ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
+        ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
+      } else { //pNonZeroCount = 0
+        ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
+        ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
+        ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
+        ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
+      }
+    } else { //non-MB_TYPE_INTRA16x16
+      for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
+        if (uiCbpLuma & (1 << iId8x8)) {
+          int32_t iIdx = (iId8x8 << 2);
+          for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
+            //Luma (DC and AC decoding together)
+            WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, iIdx, iScanIdxEnd - iScanIdxStart + 1,
+                              g_kuiZigzagScan + iScanIdxStart, LUMA_DC_AC, pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pLumaQp[iMbXy],
+                              pCtx));
+            iIdx++;
+          }
+        } else {
+          ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2)]], 0);
+          ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2) + 2]], 0);
+        }
+      }
+      ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
+      ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
+      ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
+      ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
+    }
+
+    //chroma
+    //step1: DC
+    if (1 == uiCbpChroma || 2 == uiCbpChroma) {
+      //Cb Cr
+      WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 16 + (0 << 2), 4, g_kuiChromaDcScan,
+                        CHROMA_DC_V, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (0 << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
+      WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 16 + (1 << 2), 4, g_kuiChromaDcScan,
+                        CHROMA_DC_U, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (1 << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
+    }
+
+    //step2: AC
+    if (2 == uiCbpChroma) {
+      for (i = 0; i < 2; i++) { //Cb Cr
+        int32_t iResProperty = i ? CHROMA_AC_V : CHROMA_AC_U;
+        int32_t iIdx = 16 + (i << 2);
+        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), iResProperty,
+                            pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
+          iIdx++;
+        }
+      }
+      ST16 (&pCurLayer->pNzc[iMbXy][16], LD16 (&pNonZeroCount[6 + 8 * 1]));
+      ST16 (&pCurLayer->pNzc[iMbXy][20], LD16 (&pNonZeroCount[6 + 8 * 2]));
+      ST16 (&pCurLayer->pNzc[iMbXy][18], LD16 (&pNonZeroCount[6 + 8 * 4]));
+      ST16 (&pCurLayer->pNzc[iMbXy][22], LD16 (&pNonZeroCount[6 + 8 * 5]));
+    } else {
+      ST16 (&pCurLayer->pNzc[iMbXy][16], 0);
+      ST16 (&pCurLayer->pNzc[iMbXy][20], 0);
+      ST16 (&pCurLayer->pNzc[iMbXy][18], 0);
+      ST16 (&pCurLayer->pNzc[iMbXy][22], 0);
+    }
+  } else {
+    ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
+  }
+
+  WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
+  if (uiEosFlag) {
+    RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
+  }
+  return ERR_NONE;
+}
+
+int32_t WelsDecodeMbCabacISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
+  WELS_READ_VERIFY (WelsDecodeMbCabacISliceBaseMode0 (pCtx, uiEosFlag));
+  return ERR_NONE;
+}
+
+int32_t WelsDecodeMbCabacPSliceBaseMode0 (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiEosFlag) {
+  PDqLayer pCurLayer		 = pCtx->pCurDqLayer;
+  PBitStringAux pBsAux		 = pCurLayer->pBitStringAux;
+  PSlice pSlice			 = &pCurLayer->sLayerInfo.sSliceInLayer;
+  PSliceHeader pSliceHeader		 = &pSlice->sSliceHeaderExt.sSliceHeader;
+
+  int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
+  int32_t iScanIdxEnd   = pSlice->sSliceHeaderExt.uiScanIdxEnd;
+  int32_t iMbXy = pCurLayer->iMbXyIndex;
+
+  int32_t iMbMode, i;
+  uint32_t uiMbType = 0, uiCbp = 0, uiCbpLuma = 0, uiCbpChroma = 0;
+
+  ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
+
+  pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
+
+  WELS_READ_VERIFY (ParseMBTypePSliceCabac (pCtx, pNeighAvail, uiMbType));
+  // uiMbType = 4 is not allowded.
+  if (uiMbType < 4) { //Inter mode
+    int16_t pMotionVector[LIST_A][30][MV_A];
+    int16_t pMvdCache[LIST_A][30][MV_A];
+    int8_t	pRefIndex[LIST_A][30];
+    pCurLayer->pMbType[iMbXy] = g_ksInterMbTypeInfo[uiMbType].iType;
+    WelsFillCacheInterCabac (pNeighAvail, pNonZeroCount, pMotionVector, pMvdCache, pRefIndex, pCurLayer);
+    WELS_READ_VERIFY (ParseInterMotionInfoCabac (pCtx, pNeighAvail, pNonZeroCount, pMotionVector, pMvdCache, pRefIndex));
+    iMbMode = BASE_MB;
+    pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
+  } else { //Intra mode
+    uiMbType -= 5;
+    if (uiMbType > 25) {
+      return ERR_INFO_INVALID_MB_TYPE;
+    }
+
+    if (25 == uiMbType) {   //I_PCM
+      WELS_READ_VERIFY (ParseIPCMInfoCabac (pCtx));
+      WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
+      if (uiEosFlag) {
+        RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
+      }
+      return ERR_NONE;
+    } else { //normal Intra mode
+      if (0 == uiMbType) { //Intra4x4
+        ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
+        pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
+        pCtx->pFillInfoCacheIntra4x4Func (pNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
+        WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, pNeighAvail, pIntraPredMode, pBsAux, pCurLayer));
+      } else { //Intra16x16
+        pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA16x16;
+        pCurLayer->pIntraPredMode[iMbXy][7] = (uiMbType - 1) & 3;
+        pCurLayer->pCbp[iMbXy] = g_kuiI16CbpTable[ (uiMbType - 1) >> 2];
+        uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
+        uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
+        WelsFillCacheNonZeroCount (pNeighAvail, pNonZeroCount, pCurLayer);
+        WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, pNeighAvail, pBsAux, pCurLayer));
+      }
+      iMbMode = BASE_MB;
+    }
+  }
+
+  if (MB_TYPE_INTRA16x16 != pCurLayer->pMbType[iMbXy]) {
+    WELS_READ_VERIFY (ParseCbpInfoCabac (pCtx, pNeighAvail, uiCbp));
+    pCurLayer->pCbp[iMbXy] = uiCbp;
+    uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
+    uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
+  }
+
+  pCtx->sBlockFunc.pWelsBlockZero16x16Func (pCurLayer->pScaledTCoeff[iMbXy], 16);
+  pCtx->sBlockFunc.pWelsBlockZero8x8Func (pCurLayer->pScaledTCoeff[iMbXy] + 256, 8);
+  pCtx->sBlockFunc.pWelsBlockZero8x8Func (pCurLayer->pScaledTCoeff[iMbXy] + 256 + 64, 8);
+
+  ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
+  ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
+
+  if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
+    int32_t iQpDelta, iId8x8, iId4x4;
+
+    WELS_READ_VERIFY (ParseDeltaQpCabac (pCtx, iQpDelta));
+    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)];
+
+    if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
+      //step1: Luma DC
+      WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, 0, 16, g_kuiLumaDcZigzagScan,
+                        I16_LUMA_DC, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy], pCtx));
+      //step2: Luma AC
+      if (uiCbpLuma) {
+        for (i = 0; i < 16; i++) {
+          WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, i, iScanIdxEnd - WELS_MAX (iScanIdxStart,
+                            1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), I16_LUMA_AC, pCurLayer->pScaledTCoeff[iMbXy] + (i << 4),
+                            pCurLayer->pLumaQp[iMbXy], pCtx));
+        }
+        ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
+        ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
+        ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
+        ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
+      } else {
+        ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
+        ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
+        ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
+        ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
+      }
+    } else { //non-MB_TYPE_INTRA16x16
+      for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
+        if (uiCbpLuma & (1 << iId8x8)) {
+          int32_t iIdx = (iId8x8 << 2);
+          for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
+            //Luma (DC and AC decoding together)
+            WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, iIdx, iScanIdxEnd - iScanIdxStart + 1,
+                              g_kuiZigzagScan + iScanIdxStart, LUMA_DC_AC, pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pLumaQp[iMbXy],
+                              pCtx));
+            iIdx++;
+          }
+        } else {
+          ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[iId8x8 << 2]], 0);
+          ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2) + 2]], 0);
+        }
+      }
+      ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
+      ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
+      ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
+      ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
+    }
+
+    //chroma
+    //step1: DC
+    if (1 == uiCbpChroma || 2 == uiCbpChroma) {
+      for (i = 0; i < 2; i++) {
+        int32_t iResProperty = i ? CHROMA_DC_V : CHROMA_DC_U;
+        WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, 16 + (i << 2), 4, g_kuiChromaDcScan,
+                          iResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
+      }
+    }
+    //step2: AC
+    if (2 == uiCbpChroma) {
+      for (i = 0; i < 2; i++) {
+        int32_t iResProperty = i ? CHROMA_AC_V : CHROMA_AC_U;
+        int32_t index = 16 + (i << 2);
+        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),
+                            iResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (index << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
+          index++;
+        }
+      }
+      ST16 (&pCurLayer->pNzc[iMbXy][16], LD16 (&pNonZeroCount[6 + 8 * 1]));
+      ST16 (&pCurLayer->pNzc[iMbXy][20], LD16 (&pNonZeroCount[6 + 8 * 2]));
+      ST16 (&pCurLayer->pNzc[iMbXy][18], LD16 (&pNonZeroCount[6 + 8 * 4]));
+      ST16 (&pCurLayer->pNzc[iMbXy][22], LD16 (&pNonZeroCount[6 + 8 * 5]));
+    } else {
+      ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
+      ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
+    }
+  } else {
+    pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
+    pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
+                                  pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
+  }
+
+  WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
+  if (uiEosFlag) {
+    RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
+  }
+
+  return ERR_NONE;
+}
+
+int32_t WelsDecodeMbCabacPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
+  PDqLayer pCurLayer		 = pCtx->pCurDqLayer;
+  PSlice pSlice			 = &pCurLayer->sLayerInfo.sSliceInLayer;
+  PSliceHeader pSliceHeader		 = &pSlice->sSliceHeaderExt.sSliceHeader;
+  uint32_t uiCode;
+  int32_t iMbXy = pCurLayer->iMbXyIndex;
+  int32_t i;
+  SWelsNeighAvail uiNeighAvail;
+  pCurLayer->pCbp[iMbXy] = 0;
+  pCurLayer->pCbfDc[iMbXy] = 0;
+  pCurLayer->pChromaPredMode[iMbXy] = C_PRED_DC;
+
+  GetNeighborAvailMbType (&uiNeighAvail, pCurLayer);
+  WELS_READ_VERIFY (ParseSkipFlagCabac (pCtx, &uiNeighAvail, uiCode));
+  if (uiCode) {
+    int16_t pMv[2] = {0};
+    pCurLayer->pMbType[iMbXy] = MB_TYPE_SKIP;
+    ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
+    ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
+
+    pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
+    memset (pCurLayer->pRefIndex[0][iMbXy], 0, sizeof (int8_t) * 16);
+
+    //predict mv
+    PredPSkipMvFromNeighbor (pCurLayer, pMv);
+    for (i = 0; i < 16; i++) {
+      ST32 (pCurLayer->pMv[0][iMbXy][i], * (uint32_t*)pMv);
+      ST32 (pCurLayer->pMvd[0][iMbXy][i], 0);
+    }
+
+    if (!pSlice->sSliceHeaderExt.bDefaultResidualPredFlag) {
+      memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (int16_t));
+    }
+
+    //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 neighboring CABAC usage
+    pSlice->iLastDeltaQp = 0;
+
+    WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
+
+    return ERR_NONE;
+  }
+
+  WELS_READ_VERIFY (WelsDecodeMbCabacPSliceBaseMode0 (pCtx, &uiNeighAvail, uiEosFlag));
+  return ERR_NONE;
+}
+
 int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur) {
   PDqLayer pCurLayer = pCtx->pCurDqLayer;
   PFmo pFmo = pCtx->pFmo;
@@ -329,34 +900,50 @@
   PSliceHeader pSliceHeader = &pSliceHeaderExt->sSliceHeader;
   int32_t iMbX, iMbY;
   const int32_t kiCountNumMb = pSliceHeader->pSps->uiTotalMbCount; //need to be correct when fmo or multi slice
-  PBitStringAux pBs = pCurLayer->pBitStringAux;
-  intX_t iUsedBits  = 0;
+  uint32_t uiEosFlag = 0;
+  PWelsDecMbFunc pDecMbFunc;
 
-  PWelsDecMbCavlcFunc pDecMbCavlcFunc;
-
   pSlice->iTotalMbInCurSlice = 0; //initialize at the starting of slice decoding.
 
-  if (P_SLICE == pSliceHeader->eSliceType) {
-    pDecMbCavlcFunc = WelsDecodeMbCavlcPSlice;
-  } else { //I_SLICE
-    pDecMbCavlcFunc = WelsDecodeMbCavlcISlice;
+  if (pCtx->pPps->bEntropyCodingModeFlag) {
+    if (pSlice->sSliceHeaderExt.bAdaptiveMotionPredFlag ||
+        pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag ||
+        pSlice->sSliceHeaderExt.bAdaptiveResidualPredFlag) {
+      WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
+               "WelsDecodeSlice()::::ILP flag exist, not supported with CABAC enabled!");
+      pCtx->iErrorCode |= dsBitstreamError;
+      return dsBitstreamError;
+    }
+    if (P_SLICE == pSliceHeader->eSliceType)
+      pDecMbFunc = WelsDecodeMbCabacPSlice;
+    else //I_SLICE. B_SLICE not supported now
+      pDecMbFunc = WelsDecodeMbCabacISlice;
+  } else {
+    if (P_SLICE == pSliceHeader->eSliceType) {
+      pDecMbFunc = WelsDecodeMbCavlcPSlice;
+    } else { //I_SLICE
+      pDecMbFunc = WelsDecodeMbCavlcISlice;
+    }
   }
 
   if (pSliceHeader->pPps->bConstainedIntraPredFlag) {
     pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain1Intra4x4;
-    pCtx->pParseIntra4x4ModeFunc      = ParseIntra4x4ModeConstrain1;
-    pCtx->pParseIntra16x16ModeFunc    = ParseIntra16x16ModeConstrain1;
+    pCtx->pMap4x4NeighToSampleFunc    = WelsMap4x4NeighToSampleConstrain1;
+    pCtx->pMap16x16NeighToSampleFunc  = WelsMap16x16NeighToSampleConstrain1;
   } else {
     pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain0Intra4x4;
-    pCtx->pParseIntra4x4ModeFunc      = ParseIntra4x4ModeConstrain0;
-    pCtx->pParseIntra16x16ModeFunc    = ParseIntra16x16ModeConstrain0;
+    pCtx->pMap4x4NeighToSampleFunc    = WelsMap4x4NeighToSampleNormal;
+    pCtx->pMap16x16NeighToSampleFunc  = WelsMap16x16NeighToSampleNormal;
   }
 
   pCtx->eSliceType = pSliceHeader->eSliceType;
-
   if (pCurLayer->sLayerInfo.pPps->bEntropyCodingModeFlag == 1) {
-    //CABAC encoding is unsupported yet!
-    return -1;
+    int32_t iQp = pSlice->sSliceHeaderExt.sSliceHeader.iSliceQp;
+    int32_t iCabacInitIdc = pSlice->sSliceHeaderExt.sSliceHeader.iCabacInitIdc;
+    WelsCabacContextInit (pCtx, pSlice->eSliceType, iCabacInitIdc, iQp);
+    //InitCabacCtx (pCtx->pCabacCtx, pSlice->eSliceType, iCabacInitIdc, iQp);
+    pSlice->iLastDeltaQp = 0;
+    WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux));
   }
 
   iNextMbXyIndex = pSliceHeader->iFirstMbInSlice;
@@ -398,7 +985,7 @@
     }
 
     pCurLayer->pSliceIdc[iNextMbXyIndex] = iSliceIdc;
-    iRet = pDecMbCavlcFunc (pCtx,  pNalCur);
+    iRet = pDecMbFunc (pCtx,  pNalCur, uiEosFlag);
 
     if (iRet != ERR_NONE) {
       return iRet;
@@ -405,24 +992,14 @@
     }
 
     ++pSlice->iTotalMbInCurSlice;
-
+    if (uiEosFlag) { //end of slice
+      break;
+    }
     if (pSliceHeader->pPps->uiNumSliceGroups > 1) {
       iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex);
     } else {
       ++iNextMbXyIndex;
     }
-
-    // check whether there is left bits to read next time in case multiple slices
-    iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
-    if (iUsedBits == pBs->iBits && 0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun) {	// slice boundary
-      break;
-    }
-    if (iUsedBits > pBs->iBits) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
-      WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
-               "WelsDecodeSlice()::::pBs incomplete, iUsedBits:%" PRId64" > pBs->iBits:%d, MUST stop decoding.",
-               (int64_t) iUsedBits, pBs->iBits);
-      return -1;
-    }
     iMbX = iNextMbXyIndex % pCurLayer->iMbWidth;
     iMbY = iNextMbXyIndex / pCurLayer->iMbWidth;
     pCurLayer->iMbX =  iMbX;
@@ -440,7 +1017,7 @@
   PSlice pSlice			 = &pCurLayer->sLayerInfo.sSliceInLayer;
   PSliceHeader pSliceHeader		     = &pSlice->sSliceHeaderExt.sSliceHeader;
 
-  SNeighAvail sNeighAvail;
+  SWelsNeighAvail sNeighAvail;
 
   int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
   int32_t iScanIdxEnd   = pSlice->sSliceHeaderExt.uiScanIdxEnd;
@@ -455,11 +1032,11 @@
   int32_t iCode;
 
   ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
-
+  GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
   pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
   pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag;
 
-  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //mb_type
+  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //uiMbType
   uiMbType = uiCode;
   if (uiMbType > 25) {
     return ERR_INFO_INVALID_MB_TYPE;
@@ -508,20 +1085,18 @@
     }
 
     pBs->pCurBuf += 384;
-    InitReadBits (pBs);
 
     //step 3: update QP and pNonZeroCount
     pCurLayer->pLumaQp[iMbXy] = 0;
     pCurLayer->pChromaQp[iMbXy] = 0;
     memset (pNzc, 16, sizeof (pCurLayer->pNzc[iMbXy]));   //Rec. 9.2.1 for PCM, nzc=16
+    WELS_READ_VERIFY(InitReadBits (pBs, 0));
     return 0;
   } else if (0 == uiMbType) { //reference to JM
     ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
     pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
     pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
-    if (pCtx->pParseIntra4x4ModeFunc (&sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
-      return -1;
-    }
+    WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBs, pCurLayer));
 
     //uiCbp
     WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //coded_block_pattern
@@ -542,9 +1117,7 @@
     uiCbpC = pCurLayer->pCbp[iMbXy] >> 4;
     uiCbpL = pCurLayer->pCbp[iMbXy] & 15;
     WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
-    if (pCtx->pParseIntra16x16ModeFunc (&sNeighAvail, pBs, pCurLayer)) {
-      return -1;
-    }
+    WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBs, pCurLayer));
   }
 
   memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (pCurLayer->pScaledTCoeff[iMbXy][0]));
@@ -572,19 +1145,7 @@
       return ERR_INFO_INVALID_QP;
     }
 
-    pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp + iQpDelta; //update iLastMbQp
-    //refer to JVT-X201wcm1.doc equation(7-35)
-    if ((unsigned) (pCurLayer->pLumaQp[iMbXy]) > 51) {
-      if (pCurLayer->pLumaQp[iMbXy] < 0) {
-        pCurLayer->pLumaQp[iMbXy] += 52;
-      } else {
-        pCurLayer->pLumaQp[iMbXy] -= 52;
-      }
-    }
-    //QP should be in the range of [0, 51]
-    if (pCurLayer->pLumaQp[iMbXy] < 0 || pCurLayer->pLumaQp[iMbXy] > 51) {
-      return ERR_INFO_INVALID_QP;
-    }
+    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,
@@ -673,7 +1234,7 @@
   return 0;
 }
 
-int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
+int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
   PDqLayer pCurLayer = pCtx->pCurDqLayer;
   PBitStringAux pBs = pCurLayer->pBitStringAux;
   PSliceHeaderExt pSliceHeaderExt = &pCurLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt;
@@ -680,7 +1241,7 @@
   int32_t iBaseModeFlag;
   int32_t iRet = 0; //should have the return value to indicate decoding error or not, It's NECESSARY--2010.4.15
   uint32_t uiCode;
-
+  intX_t iUsedBits;
   if (pSliceHeaderExt->bAdaptiveBaseModeFlag == 1) {
     WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
     iBaseModeFlag = uiCode;
@@ -698,6 +1259,19 @@
     return iRet;
   }
 
+  // check whether there is left bits to read next time in case multiple slices
+  iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
+  // sub 1, for stop bit
+  if ((iUsedBits == (pBs->iBits - 1)) && (0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun)) {	// slice boundary
+    uiEosFlag = 1;
+  }
+  if (iUsedBits > (pBs->iBits -
+                   1)) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
+    WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
+             "WelsDecodeMbCavlcISlice()::::pBs incomplete, iUsedBits:%"PRId64" > pBs->iBits:%d, MUST stop decoding.",
+             (int64_t) iUsedBits, pBs->iBits);
+    return -1;
+  }
   return 0;
 }
 
@@ -708,11 +1282,10 @@
   PSlice pSlice			 = &pCurLayer->sLayerInfo.sSliceInLayer;
   PSliceHeader pSliceHeader		     = &pSlice->sSliceHeaderExt.sSliceHeader;
 
-  SNeighAvail sNeighAvail;
-
   int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
   int32_t iScanIdxEnd   = pSlice->sSliceHeaderExt.uiScanIdxEnd;
 
+  SWelsNeighAvail sNeighAvail;
   int32_t iMbX = pCurLayer->iMbX;
   int32_t iMbY = pCurLayer->iMbY;
   const int32_t iMbXy = pCurLayer->iMbXyIndex;
@@ -721,15 +1294,13 @@
   uint32_t uiMbType = 0, uiCbp = 0, uiCbpL = 0, uiCbpC = 0;
   uint32_t uiCode;
   int32_t iCode;
-
+  GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
   ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
   pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;//2009.10.23
-
-  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //mb_type
+  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //uiMbType
   uiMbType = uiCode;
   if (uiMbType < 5) { //inter MB type
     int16_t iMotionVector[LIST_A][30][MV_A];
-
     int8_t	iRefIndex[LIST_A][30];
     pCurLayer->pMbType[iMbXy] = g_ksInterMbTypeInfo[uiMbType].iType;
     WelsFillCacheInter (&sNeighAvail, pNonZeroCount, iMotionVector, iRefIndex, pCurLayer);
@@ -800,7 +1371,6 @@
       }
 
       pBs->pCurBuf += 384;
-      InitReadBits (pBs);
 
       //step 3: update QP and pNonZeroCount
       pCurLayer->pLumaQp[iMbXy] = 0;
@@ -812,6 +1382,7 @@
       ST32A4 (&pNzc[12], 0x10101010);
       ST32A4 (&pNzc[16], 0x10101010);
       ST32A4 (&pNzc[20], 0x10101010);
+      WELS_READ_VERIFY (InitReadBits (pBs, 0));
       return 0;
     } else {
       if (0 == uiMbType) {
@@ -818,7 +1389,7 @@
         ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
         pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
         pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
-        if (pCtx->pParseIntra4x4ModeFunc (&sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
+        if (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
           return -1;
         }
       } else { //I_PCM exclude, we can ignore it
@@ -828,7 +1399,7 @@
         uiCbpC = pCurLayer->pCbp[iMbXy] >> 4;
         uiCbpL = pCurLayer->pCbp[iMbXy] & 15;
         WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
-        if (pCtx->pParseIntra16x16ModeFunc (&sNeighAvail, pBs, pCurLayer)) {
+        if (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBs, pCurLayer)) {
           return -1;
         }
       }
@@ -877,19 +1448,7 @@
       return ERR_INFO_INVALID_QP;
     }
 
-    pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp + iQpDelta; //update iLastMbQp
-    //refer to JVT-X201wcm1.doc equation(7-35)
-    if ((unsigned) (pCurLayer->pLumaQp[iMbXy]) > 51) {
-      if (pCurLayer->pLumaQp[iMbXy] < 0) {
-        pCurLayer->pLumaQp[iMbXy] += 52;
-      } else {
-        pCurLayer->pLumaQp[iMbXy] -= 52;
-      }
-    }
-    //QP should be in the range of [0, 51]
-    if (pCurLayer->pLumaQp[iMbXy] < 0 || pCurLayer->pLumaQp[iMbXy] > 51) {
-      return ERR_INFO_INVALID_QP;
-    }
+    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,
@@ -978,12 +1537,12 @@
   return 0;
 }
 
-int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
+int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
   PDqLayer pCurLayer		 = pCtx->pCurDqLayer;
   PBitStringAux pBs		 = pCurLayer->pBitStringAux;
   PSlice pSlice			 = &pCurLayer->sLayerInfo.sSliceInLayer;
   PSliceHeader pSliceHeader		    = &pSlice->sSliceHeaderExt.sSliceHeader;
-
+  intX_t iUsedBits;
   const int32_t iMbXy = pCurLayer->iMbXyIndex;
   int8_t* pNzc = pCurLayer->pNzc[iMbXy];
   int32_t iBaseModeFlag, i;
@@ -996,7 +1555,6 @@
     if (-1 == pSlice->iMbSkipRun) {
       return -1;
     }
-
   }
   if (pSlice->iMbSkipRun--) {
     int16_t iMv[2];
@@ -1031,27 +1589,37 @@
     }
 
     pCurLayer->pCbp[iMbXy] = 0;
-
-    return 0;
-  }
-
-  if (pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag == 1) {
-    WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
-    iBaseModeFlag = uiCode;
   } else {
-    iBaseModeFlag = pSlice->sSliceHeaderExt.bDefaultBaseModeFlag;
+    if (pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag == 1) {
+      WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
+      iBaseModeFlag = uiCode;
+    } else {
+      iBaseModeFlag = pSlice->sSliceHeaderExt.bDefaultBaseModeFlag;
+    }
+    if (!iBaseModeFlag) {
+      iRet = WelsActualDecodeMbCavlcPSlice (pCtx);
+    } else {
+      WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "iBaseModeFlag (%d) != 0, inter-layer prediction not supported.",
+               iBaseModeFlag);
+      return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP);
+    }
+    if (iRet) { //occur error when parsing, MUST STOP decoding
+      return iRet;
+    }
   }
-  if (!iBaseModeFlag) {
-    iRet = WelsActualDecodeMbCavlcPSlice (pCtx);
-  } else {
-    WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "iBaseModeFlag (%d) != 0, inter-layer prediction not supported.",
-             iBaseModeFlag);
-    return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP);
+  // check whether there is left bits to read next time in case multiple slices
+  iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
+  // sub 1, for stop bit
+  if ((iUsedBits == (pBs->iBits - 1)) && (0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun)) {	// slice boundary
+    uiEosFlag = 1;
   }
-  if (iRet) { //occur error when parsing, MUST STOP decoding
-    return iRet;
+  if (iUsedBits > (pBs->iBits -
+                   1)) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
+    WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
+             "WelsDecodeMbCavlcISlice()::::pBs incomplete, iUsedBits:%"PRId64" > pBs->iBits:%d, MUST stop decoding.",
+             (int64_t) iUsedBits, pBs->iBits);
+    return -1;
   }
-
   return 0;
 }
 
@@ -1069,6 +1637,21 @@
     pFunc->pWelsSetNonZeroCountFunc		= SetNonZeroCount_AArch64_neon;
   }
 #endif
+
+  pFunc->pWelsBlockZero16x16Func	    = WelsBlockZero16x16_c;
+  pFunc->pWelsBlockZero8x8Func	    = WelsBlockZero8x8_c;
+  //TO DO add neon and X86
+#ifdef	HAVE_NEON
+  if (iCpu & WELS_CPU_NEON) {
+
+  }
+#endif
+
+#ifdef	HAVE_NEON_AARCH64
+  if (iCpu & WELS_CPU_NEON) {
+
+  }
+#endif
 }
 
 void SetNonZeroCount_c (int8_t* pNonZeroCount) {
@@ -1077,6 +1660,23 @@
   for (i = 0; i < 24; i++) {
     pNonZeroCount[i] = !!pNonZeroCount[i];
   }
+}
+
+void WelsBlockInit (int16_t* pBlock, int iW, int iH, int iStride, uint8_t uiVal) {
+  int32_t i;
+  int16_t* pDst = pBlock;
+
+  for (i = 0; i < iH; i++) {
+    memset (pDst, uiVal, iW * sizeof (int16_t));
+    pDst += iStride;
+  }
+}
+void WelsBlockZero16x16_c (int16_t* pBlock, int32_t iStride) {
+  WelsBlockInit (pBlock, 16, 16, iStride, 0);
+}
+
+void WelsBlockZero8x8_c (int16_t* pBlock, int32_t iStride) {
+  WelsBlockInit (pBlock, 8, 8, iStride, 0);
 }
 
 } // namespace WelsDec
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -139,8 +139,8 @@
   pCtx->uiCpuFlag					= 0;
 
   pCtx->bAuReadyFlag				= 0; // au data is not ready
+  pCtx->bCabacInited = false;
 
-
   pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);
 
   pCtx->iImgWidthInPixel		= 0;
@@ -241,6 +241,10 @@
 
   pCtx->bHaveGotMemory	= true;			// global memory for decoder context related is requested
   pCtx->pDec		        = NULL;			// need prefetch a new pic due to spatial size changed
+
+  if (pCtx->pCabacDecEngine == NULL)
+    pCtx->pCabacDecEngine = (SWelsCabacDecEngine*) WelsMalloc (sizeof (SWelsCabacDecEngine), "pCtx->pCabacDecEngine");
+
   return ERR_NONE;
 }
 
@@ -267,7 +271,7 @@
   pCtx->iImgWidthInPixel	= 0;
   pCtx->iImgHeightInPixel = 0;
   pCtx->bHaveGotMemory	= false;
-
+  WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
 }
 
 /*!
@@ -464,6 +468,7 @@
         } else {
 
           iConsumedBytes = 0;
+          pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero
           pNalPayload	= ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
           if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
             CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
@@ -502,13 +507,12 @@
             return pCtx->iErrorCode;
           }
 
-          pDstNal += iDstIdx; //update current position
+          pDstNal += (iDstIdx + 4); //init, increase 4 reserved zero bytes, used to store the next NAL
           if ((iSrcLength - iSrcConsumed + 4) > (pRawData->pEnd - pDstNal)) {
-            pRawData->pCurPos = pRawData->pHead;
+            pDstNal = pRawData->pCurPos = pRawData->pHead;
           } else {
             pRawData->pCurPos = pDstNal;
           }
-          pDstNal = pRawData->pCurPos + 4; //init, 4 bytes used to store the next NAL
 
           pSrcNal += iSrcIdx + 3;
           iSrcConsumed += 3;
@@ -524,6 +528,7 @@
     //last NAL decoding
 
     iConsumedBytes = 0;
+    pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero
     pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
     if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
       CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
@@ -557,8 +562,7 @@
       }
       return pCtx->iErrorCode;
     }
-    pDstNal += iDstIdx;
-    pRawData->pCurPos = pDstNal; //init the pCurPos for next NAL(s) storage
+    pRawData->pCurPos = pDstNal + iDstIdx + 4; //init, increase 4 reserved zero bytes, used to store the next NAL
   } else { /* no supplementary picture payload input, but stored a picture */
     PAccessUnit pCurAu	=
       pCtx->pAccessUnitList;	// current access unit, it will never point to NULL after decode's successful initialization
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -707,8 +707,11 @@
   }
 
   if (pPps->bEntropyCodingModeFlag) {
-    WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): CABAC in Enhancement layer not supported.");
-    return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_CABAC_EL);
+    if (pSliceHead->eSliceType != I_SLICE && pSliceHead->eSliceType != SI_SLICE) {
+      WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
+      pSliceHead->iCabacInitIdc = uiCode;
+    } else
+      pSliceHead->iCabacInitIdc = 0;
   }
 
   WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_qp_delta
@@ -1021,6 +1024,10 @@
                            "pCtx->sMb.pLumaQp[]");
     pCtx->sMb.pChromaQp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t),
                              "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[][]");
+    pCtx->sMb.pCbfDc[i] = (uint8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (uint8_t),
+                          "pCtx->sMb.pCbfDc[]");
     pCtx->sMb.pNzc[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24,
                         "pCtx->sMb.pNzc[]");
     pCtx->sMb.pNzcRs[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24,
@@ -1057,6 +1064,8 @@
                             (NULL == pCtx->sMb.pRefIndex[i][0]) ||
                             (NULL == pCtx->sMb.pLumaQp[i]) ||
                             (NULL == pCtx->sMb.pChromaQp[i]) ||
+                            (NULL == pCtx->sMb.pMvd[i][0]) ||
+                            (NULL == pCtx->sMb.pCbfDc[i]) ||
                             (NULL == pCtx->sMb.pNzc[i]) ||
                             (NULL == pCtx->sMb.pNzcRs[i]) ||
                             (NULL == pCtx->sMb.pScaledTCoeff[i]) ||
@@ -1076,7 +1085,6 @@
     ++ i;
   } while (i < LAYER_NUM_EXCHANGEABLE);
 
-
   pCtx->bInitialDqLayersMem	= true;
   pCtx->iPicWidthReq			= kiMaxWidth;
   pCtx->iPicHeightReq			= kiMaxHeight;
@@ -1124,6 +1132,16 @@
       pCtx->sMb.pChromaQp[i] = NULL;
     }
 
+    if (pCtx->sMb.pMvd[i][0]) {
+      WelsFree (pCtx->sMb.pMvd[i][0], "pCtx->sMb.pMvd[][]");
+      pCtx->sMb.pMvd[i][0] = NULL;
+    }
+
+    if (pCtx->sMb.pCbfDc[i]) {
+      WelsFree (pCtx->sMb.pCbfDc[i], "pCtx->sMb.pCbfDc[]");
+      pCtx->sMb.pCbfDc[i] = NULL;
+    }
+
     if (pCtx->sMb.pNzc[i]) {
       WelsFree (pCtx->sMb.pNzc[i], "pCtx->sMb.pNzc[]");
 
@@ -1754,6 +1772,8 @@
     pCurDq->pRefIndex[0]    = pCtx->sMb.pRefIndex[0][0];
     pCurDq->pLumaQp         = pCtx->sMb.pLumaQp[0];
     pCurDq->pChromaQp       = pCtx->sMb.pChromaQp[0];
+    pCurDq->pMvd[0]       = pCtx->sMb.pMvd[0][0];
+    pCurDq->pCbfDc       = pCtx->sMb.pCbfDc[0];
     pCurDq->pNzc			= pCtx->sMb.pNzc[0];
     pCurDq->pNzcRs			= pCtx->sMb.pNzcRs[0];
     pCurDq->pScaledTCoeff   = pCtx->sMb.pScaledTCoeff[0];
--- a/codec/decoder/core/src/decoder_data_tables.cpp
+++ b/codec/decoder/core/src/decoder_data_tables.cpp
@@ -54,6 +54,56 @@
 // extern at wels_common_basis.h
 
 /*common use table*/
+const uint8_t g_kMbNonZeroCountIdx[24] = {
+  //  0   1 | 4  5      luma 8*8 block           pNonZeroCount[16+8]
+  0,  1,  4,  5,   //  2   3 | 6  7        0  |  1                  0   1   2   3
+  2,  3,  6,  7,   //---------------      ---------                 4   5   6   7
+  8,  9, 12, 13,   //  8   9 | 12 13       2  |  3                  8   9  10  11
+  10, 11, 14, 15,   // 10  11 | 14 15-----------------------------> 12  13  14  15
+  16, 17, 20, 21,   //----------------    chroma 8*8 block          16  17  18  19
+  18, 19, 22, 23   // 16  17 | 20 21        0    1                 20  21  22  23
+};
+//cache element equal to 26
+
+const uint8_t g_kCacheNzcScanIdx[4 * 4 + 4 + 4 + 3] = {
+  /* Luma */
+  9, 10, 17, 18,	// 1+1*8, 2+1*8, 1+2*8, 2+2*8,
+  11, 12, 19, 20,	// 3+1*8, 4+1*8, 3+2*8, 4+2*8,
+  25, 26, 33, 34,	// 1+3*8, 2+3*8, 1+4*8, 2+4*8,
+  27, 28, 35, 36,	// 3+3*8, 4+3*8, 3+4*8, 4+4*8,
+  /* Cb */
+  14, 15,			// 6+1*8, 7+1*8,
+  22, 23,			// 6+2*8, 7+2*8,
+
+  /* Cr */
+  38, 39,			// 6+4*8, 7+4*8,
+  46, 47,			// 6+5*8, 7+5*8,
+  /* Luma DC */
+  41,   // 1+5*8
+  /* Chroma DC */
+  42, 43 // 2+5*8, 3+5*8,
+};
+
+const uint8_t g_kCache26ScanIdx[16] = { //intra4*4_pred_mode and pNonZeroCount cache scan index, 4*4 block as basic unit
+  6,  7, 11, 12,
+  8,  9, 13, 14,
+  16, 17, 21, 22,
+  18, 19, 23, 24
+};
+
+//cache element equal to 30
+const uint8_t g_kCache30ScanIdx[16] = { //mv or pRefIndex cache scan index, 4*4 block as basic unit
+  7,  8, 13, 14,
+  9, 10, 15, 16,
+  19, 20, 25, 26,
+  21, 22, 27, 28
+};
+
+const uint8_t g_kNonZeroScanIdxC[4] = { //pNonZeroCount cache for chroma, 4*4 block as basic unit
+  4, 5,
+  7, 8
+};
+
 const uint8_t g_kuiScan8[24] = {	// [16 + 2*4]
   9, 10, 17, 18,	// 1+1*8, 2+1*8, 1+2*8, 2+2*8,
   11, 12, 19, 20,	// 3+1*8, 4+1*8, 3+2*8, 4+2*8,
--- /dev/null
+++ b/codec/decoder/core/src/parse_mb_syn_cabac.cpp
@@ -1,0 +1,909 @@
+/*!
+ * \copy
+ *     Copyright (c)  2013, Cisco Systems
+ *     All rights reserved.
+ *
+ *     Redistribution and use in source and binary forms, with or without
+ *     modification, are permitted provided that the following conditions
+ *     are met:
+ *
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *
+ *        * Redistributions in binary form must reproduce the above copyright
+ *          notice, this list of conditions and the following disclaimer in
+ *          the documentation and/or other materials provided with the
+ *          distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *     POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	cabac_decoder.cpp:	cabac parse for syntax elements
+ */
+#include "parse_mb_syn_cabac.h"
+#include "mv_pred.h"
+#include "error_code.h"
+namespace WelsDec {
+#define IDX_UNUSED -1
+static const int16_t g_kMaxPos       [] = {IDX_UNUSED, 15, 14, 15, 3, 14, 3, 3, 14, 14};
+static const int16_t g_kMaxC2       [] = {IDX_UNUSED, 4, 4, 4, 3, 4, 3, 3, 4, 4};
+static const int16_t g_kBlockCat2CtxOffsetCBF[] = {IDX_UNUSED, 0, 4, 8, 12, 16, 12, 12, 16, 16};
+static const int16_t g_kBlockCat2CtxOffsetMap [] = {IDX_UNUSED, 0, 15, 29, 44, 47, 44, 44, 47, 47};
+static const int16_t g_kBlockCat2CtxOffsetLast[] = {IDX_UNUSED, 0, 15, 29, 44, 47, 44, 44, 47, 47};
+static const int16_t g_kBlockCat2CtxOffsetOne [] = {IDX_UNUSED, 0 , 10, 20, 30, 39, 30, 30, 39, 39};
+static const int16_t g_kBlockCat2CtxOffsetAbs [] = {IDX_UNUSED, 0 , 10, 20, 30, 39, 30, 30, 39, 39};
+
+const uint8_t g_kTopBlkInsideMb[24] = { //for index with z-order 0~23
+  //  0   1 | 4  5      luma 8*8 block           pNonZeroCount[16+8]
+  0,  0,  1,  1,   //  2   3 | 6  7        0  |  1                  0   1   2   3
+  0,  0,  1,  1,   //---------------      ---------                 4   5   6   7
+  1,  1,  1,  1,   //  8   9 | 12 13       2  |  3                  8   9  10  11
+  1,  1,  1,  1,  // 10  11 | 14 15-----------------------------> 12  13  14  15
+  0,  0,  1,  1,   //----------------    chroma 8*8 block          16  17  18  19
+  0,  0,  1,  1   // 16  17 | 20 21        0    1                 20  21  22  23
+  // 18  19 | 22 23
+};
+
+const uint8_t g_kLeftBlkInsideMb[24] = { //for index with z-order 0~23
+  //  0   1 | 4  5      luma 8*8 block           pNonZeroCount[16+8]
+  0,  1,  0,  1,   //  2   3 | 6  7        0  |  1                  0   1   2   3
+  1,  1,  1,  1,   //---------------      ---------                 4   5   6   7
+  0,  1,  0,  1,   //  8   9 | 12 13       2  |  3                  8   9  10  11
+  1,  1,  1,  1,  // 10  11 | 14 15-----------------------------> 12  13  14  15
+  0,  1,  0,  1,   //----------------    chroma 8*8 block          16  17  18  19
+  0,  1,  0,  1   // 16  17 | 20 21        0    1                 20  21  22  23
+  // 18  19 | 22 23
+};
+
+void UpdateP16x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
+                             const int8_t iListIdx) {
+  int32_t iRef32Bit = (int32_t) iRef;
+  const int32_t iRef4Bytes = (iRef32Bit << 24) | (iRef32Bit << 16) | (iRef32Bit << 8) | iRef32Bit;
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+  const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+  const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+  const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+  //mb
+  ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef4Bytes);
+  ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef4Bytes);
+  //cache
+  ST32 (&pRefIndex[iListIdx][iCacheIdx ], iRef4Bytes);
+  ST32 (&pRefIndex[iListIdx][iCacheIdx6], iRef4Bytes);
+}
+
+void UpdateP8x16RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
+                             const int8_t iListIdx) {
+  int16_t iRef16Bit = (int16_t) iRef;
+  const int16_t iRef2Bytes = (iRef16Bit << 8) | iRef16Bit;
+  int32_t i;
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  for (i = 0; i < 2; i++, iPartIdx += 8) {
+    const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+    const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+    const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+    const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+    //mb
+    ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef2Bytes);
+    ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef2Bytes);
+    //cache
+    ST16 (&pRefIndex[iListIdx][iCacheIdx ], iRef2Bytes);
+    ST16 (&pRefIndex[iListIdx][iCacheIdx6], iRef2Bytes);
+  }
+}
+
+void UpdateP8x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
+                            const int8_t iListIdx) {
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+  pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 1] =
+        pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 4] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 5] = iRef;
+}
+
+void UpdateP16x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvd[2], const int8_t iListIdx) {
+  int32_t pMvd32[2];
+  ST32 (&pMvd32[0], LD32 (pMvd));
+  ST32 (&pMvd32[1], LD32 (pMvd));
+  int32_t i;
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  for (i = 0; i < 16; i += 2) {
+    ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][i], LD64 (pMvd32));
+  }
+}
+
+void UpdateP16x8MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
+                          const int8_t iListIdx) {
+  int32_t pMvd32[2];
+  ST32 (&pMvd32[0], LD32 (pMvd));
+  ST32 (&pMvd32[1], LD32 (pMvd));
+  int32_t i;
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  for (i = 0; i < 2; i++, iPartIdx += 4) {
+    const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+    const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+    const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+    const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+    //mb
+    ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][  iScan4Idx ], LD64 (pMvd32));
+    ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][  iScan4Idx4], LD64 (pMvd32));
+    //cache
+    ST64 (pMvdCache[iListIdx][  iCacheIdx ], LD64 (pMvd32));
+    ST64 (pMvdCache[iListIdx][  iCacheIdx6], LD64 (pMvd32));
+  }
+}
+
+void UpdateP8x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
+                          const int8_t iListIdx) {
+  int32_t pMvd32[2];
+  ST32 (&pMvd32[0], LD32 (pMvd));
+  ST32 (&pMvd32[1], LD32 (pMvd));
+  int32_t i;
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+
+  for (i = 0; i < 2; i++, iPartIdx += 8) {
+    const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+    const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+    const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+    const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+    //mb
+    ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][  iScan4Idx ], LD64 (pMvd32));
+    ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][  iScan4Idx4], LD64 (pMvd32));
+    //cache
+    ST64 (pMvdCache[iListIdx][  iCacheIdx ], LD64 (pMvd32));
+    ST64 (pMvdCache[iListIdx][  iCacheIdx6], LD64 (pMvd32));
+  }
+}
+
+int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal) {
+  uiBinVal = 0;
+  WELS_READ_VERIFY (DecodeTerminateCabac (pCtx->pCabacDecEngine, uiBinVal));
+  return ERR_NONE;
+}
+
+int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip) {
+  uiSkip = 0;
+  int32_t iCtxInc = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_SKIP) + (pNeighAvail->iTopAvail
+                    && pNeighAvail->iTopType  != MB_TYPE_SKIP);
+  PWelsCabacCtx pBinCtx = (pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP + iCtxInc);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx, uiSkip));
+  return ERR_NONE;
+}
+
+
+int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal) {
+  uint32_t uiCode;
+  int32_t iIdxA = 0, iIdxB = 0;
+  int32_t iCtxInc;
+  uiBinVal = 0;
+  PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+  PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MB_TYPE_I; //I mode in I slice
+  iIdxA = (pNeighAvail->iLeftAvail) && (pNeighAvail->iLeftType != MB_TYPE_INTRA4x4
+                                        && pNeighAvail->iLeftType != MB_TYPE_INTRA8x8);
+  iIdxB = (pNeighAvail->iTopAvail) && (pNeighAvail->iTopType != MB_TYPE_INTRA4x4
+                                       && pNeighAvail->iTopType != MB_TYPE_INTRA8x8);
+  iCtxInc = iIdxA + iIdxB;
+  WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
+  uiBinVal = uiCode;
+  if (uiBinVal != 0) {  //I16x16
+    WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
+    if (uiCode == 1)
+      uiBinVal = 25; //I_PCM
+    else {
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+      uiBinVal = 1 + uiCode * 12;
+      //decoding of uiCbp:0,1,2
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
+      if (uiCode != 0) {
+        WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+        uiBinVal += 4;
+        if (uiCode != 0)
+          uiBinVal += 4;
+      }
+      //decoding of I pred-mode: 0,1,2,3
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
+      uiBinVal += (uiCode << 1);
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
+      uiBinVal += uiCode;
+    }
+  }
+  //I4x4
+  return ERR_NONE;
+}
+
+int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiMbType) {
+  uint32_t uiCode;
+  uiMbType = 0;
+  PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+
+  PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP;
+  WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+  if (uiCode) {
+    // Intra MB
+    WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
+    if (uiCode) { // Intra 16x16
+      WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
+      if (uiCode) {
+        uiMbType = 30;
+        return ERR_NONE;//MB_TYPE_INTRA_PCM;
+      }
+
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
+      uiMbType = 6 + uiCode * 12;
+
+      //uiCbp: 0,1,2
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
+      if (uiCode) {
+        uiMbType += 4;
+        WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
+        if (uiCode)
+          uiMbType += 4;
+      }
+
+      //IPredMode: 0,1,2,3
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
+      uiMbType += (uiCode << 1);
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
+      uiMbType += uiCode;
+    } else
+      // Intra 4x4
+      uiMbType = 5;
+  } else { // P MB
+    WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
+    if (uiCode) { //second bit
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
+      if (uiCode)
+        uiMbType = 1;
+      else
+        uiMbType = 2;
+    } else {
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+      if (uiCode)
+        uiMbType = 3;
+      else
+        uiMbType = 0;
+    }
+  }
+  return ERR_NONE;
+}
+int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType) {
+  uint32_t uiCode;
+  PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+  PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SUBMB_TYPE;
+  WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
+  if (uiCode)
+    uiSubMbType = 0;
+  else {
+    WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode));
+    if (uiCode) {
+      WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
+      uiSubMbType = 3 - uiCode;
+    } else {
+      uiSubMbType = 1;
+    }
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal) {
+  uint32_t uiCode;
+  iBinVal = 0;
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR, uiCode));
+  if (uiCode == 1)
+    iBinVal = -1;
+  else {
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
+    iBinVal |= uiCode;
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
+    iBinVal |= (uiCode << 1);
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
+    iBinVal |= (uiCode << 2);
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal) {
+  uint32_t uiCode;
+  int32_t iIdxA, iIdxB, iCtxInc;
+  int8_t* pChromaPredMode = pCtx->pCurDqLayer->pChromaPredMode;
+  int8_t* pMbType = pCtx->pCurDqLayer->pMbType;
+  int32_t iLeftAvail     = uiNeighAvail & 0x04;
+  int32_t iTopAvail      = uiNeighAvail & 0x01;
+
+  int32_t iMbXy = pCtx->pCurDqLayer->iMbXyIndex;
+  int32_t iMbXyTop = iMbXy - pCtx->pCurDqLayer->iMbWidth;
+  int32_t iMbXyLeft = iMbXy - 1;
+
+  iBinVal = 0;
+
+  iIdxB = iTopAvail  && (pChromaPredMode[iMbXyTop] > 0 && pChromaPredMode[iMbXyTop] <= 3)
+          && pMbType[iMbXyTop]  != MB_TYPE_INTRA_PCM;
+  iIdxA = iLeftAvail && (pChromaPredMode[iMbXyLeft] > 0 && pChromaPredMode[iMbXyLeft] <= 3)
+          && pMbType[iMbXyLeft] != MB_TYPE_INTRA_PCM;
+  iCtxInc = iIdxA + iIdxB;
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + iCtxInc, uiCode));
+  iBinVal = uiCode;
+  if (iBinVal != 0) {
+    uint32_t iSym;
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, iSym));
+    if (iSym == 0) {
+      iBinVal = (iSym + 1);
+      return ERR_NONE;
+    }
+    iSym = 0;
+    do {
+      WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, uiCode));
+      ++iSym;
+    } while ((uiCode != 0) && (iSym < 1));
+
+    if ((uiCode != 0) && (iSym == 1))
+      ++ iSym;
+    iBinVal = (iSym + 1);
+    return ERR_NONE;
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseInterMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+                                   int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]) {
+  PSlice pSlice				= &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
+  PSliceHeader pSliceHeader	= &pSlice->sSliceHeaderExt.sSliceHeader;
+  PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
+  PPicture* ppRefPic = pCtx->sRefPic.pRefList[LIST_0];
+  int32_t pRefCount[2];
+  int32_t i, j;
+  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+  int16_t pMv[4] = {0};
+  int16_t pMvd[4] = {0};
+  int8_t iRef[2] = {0};
+  int32_t iPartIdx;
+  int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
+  int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
+  pRefCount[0] = pSliceHeader->uiRefCount[0];
+  pRefCount[1] = pSliceHeader->uiRefCount[1];
+
+  switch (pCurDqLayer->pMbType[iMbXy]) {
+  case MB_TYPE_16x16: {
+    iPartIdx = 0;
+    WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
+                                        iRef[0]));
+    if ((iRef[0] < 0) || (iRef[0] >= pRefCount[0]) || (ppRefPic[iRef[0]] == NULL)) { //error ref_idx
+      if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
+        iRef[0] = 0;
+        pCtx->iErrorCode |= dsBitstreamError;
+      } else {
+        return ERR_INFO_INVALID_REF_INDEX;
+      }
+    }
+    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]));
+    pMv[0] += pMvd[0];
+    pMv[1] += pMvd[1];
+    WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+    UpdateP16x16MotionInfo (pCurDqLayer, iRef[0], pMv);
+    UpdateP16x16MvdCabac (pCurDqLayer, pMvd, LIST_0);
+  }
+  break;
+  case MB_TYPE_16x8:
+    for (i = 0; i < 2; i++) {
+      iPartIdx = i << 3;
+      WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
+                                          iRef[i]));
+      if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
+        if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
+          iRef[i] = 0;
+          pCtx->iErrorCode |= dsBitstreamError;
+        } else {
+          return ERR_INFO_INVALID_REF_INDEX;
+        }
+      }
+      UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
+    }
+    for (i = 0; i < 2; i++) {
+      iPartIdx = i << 3;
+      PredInter16x8Mv (pMotionVector, pRefIndex, iPartIdx, iRef[i], 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]));
+      pMv[0] += pMvd[0];
+      pMv[1] += pMvd[1];
+      WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+      UpdateP16x8MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
+      UpdateP16x8MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
+    }
+    break;
+  case MB_TYPE_8x16:
+    for (i = 0; i < 2; i++) {
+      iPartIdx = i << 2;
+      WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
+                                          iRef[i]));
+      if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
+        if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
+          iRef[i] = 0;
+          pCtx->iErrorCode |= dsBitstreamError;
+        } else {
+          return ERR_INFO_INVALID_REF_INDEX;
+        }
+      }
+      UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
+    }
+    for (i = 0; i < 2; i++) {
+      iPartIdx = i << 2;
+      PredInter8x16Mv (pMotionVector, pRefIndex, i << 2, iRef[i], pMv/*&mv[0], &mv[1]*/);
+
+      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]));
+      pMv[0] += pMvd[0];
+      pMv[1] += pMvd[1];
+      WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+      UpdateP8x16MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
+      UpdateP8x16MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
+    }
+    break;
+  case MB_TYPE_8x8:
+  case MB_TYPE_8x8_REF0: {
+    int8_t pRefIdx[4] = {0}, pSubPartCount[4], pPartW[4];
+    uint32_t uiSubMbType;
+    //sub_mb_type, partition
+    for (i = 0; i < 4; i++) {
+      WELS_READ_VERIFY (ParseSubMBTypeCabac (pCtx, pNeighAvail, uiSubMbType));
+      if (uiSubMbType >= 4) { //invalid sub_mb_type
+        return ERR_INFO_INVALID_SUB_MB_TYPE;
+      }
+      pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterSubMbTypeInfo[uiSubMbType].iType;
+      pSubPartCount[i] = g_ksInterSubMbTypeInfo[uiSubMbType].iPartCount;
+      pPartW[i] = g_ksInterSubMbTypeInfo[uiSubMbType].iPartWidth;
+    }
+
+    for (i = 0; i < 4; i++) {
+      int16_t iIdx8 = i << 2;
+      WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iIdx8, pRefCount[0], 1,
+                                          pRefIdx[i]));
+      if ((pRefIdx[i] < 0) || (pRefIdx[i] >= pRefCount[0]) || (ppRefPic[pRefIdx[i]] == NULL)) { //error ref_idx
+        if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
+          pRefIdx[i] = 0;
+          pCtx->iErrorCode |= dsBitstreamError;
+        } else {
+          return ERR_INFO_INVALID_REF_INDEX;
+        }
+      }
+      UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, pRefIdx[i], LIST_0);
+    }
+    //mv
+    for (i = 0; i < 4; i++) {
+      int8_t iPartCount = pSubPartCount[i];
+      uiSubMbType = pCurDqLayer->pSubMbType[iMbXy][i];
+      int16_t iPartIdx, iBlockW = pPartW[i];
+      uint8_t iScan4Idx, iCacheIdx;
+      iCacheIdx = g_kuiCache30ScanIdx[i << 2];
+      pRefIndex[0][iCacheIdx ] = pRefIndex[0][iCacheIdx + 1]
+                                 = pRefIndex[0][iCacheIdx + 6] = pRefIndex[0][iCacheIdx + 7] = pRefIdx[i];
+
+      for (j = 0; j < iPartCount; j++) {
+        iPartIdx = (i << 2) + j * iBlockW;
+        iScan4Idx = g_kuiScan4[iPartIdx];
+        iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+        PredMv (pMotionVector, pRefIndex, iPartIdx, iBlockW, pRefIdx[i], 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]));
+        pMv[0] += pMvd[0];
+        pMv[1] += pMvd[1];
+        WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+        if (SUB_MB_TYPE_8x8 == uiSubMbType) {
+          ST32 ((pMv + 2), LD32 (pMv));
+          ST32 ((pMvd + 2), LD32 (pMvd));
+          ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx], LD64 (pMv));
+          ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD64 (pMv));
+          ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx], LD64 (pMvd));
+          ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD64 (pMvd));
+          ST64 (pMotionVector[0][iCacheIdx  ], LD64 (pMv));
+          ST64 (pMotionVector[0][iCacheIdx + 6], LD64 (pMv));
+          ST64 (pMvdCache[0][iCacheIdx  ], LD64 (pMvd));
+          ST64 (pMvdCache[0][iCacheIdx + 6], LD64 (pMvd));
+        } else if (SUB_MB_TYPE_8x4 == uiSubMbType) {
+          ST32 ((pMv + 2), LD32 (pMv));
+          ST32 ((pMvd + 2), LD32 (pMvd));
+          ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx  ], LD64 (pMv));
+          ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx  ], LD64 (pMvd));
+          ST64 (pMotionVector[0][iCacheIdx  ], LD64 (pMv));
+          ST64 (pMvdCache[0][iCacheIdx  ], LD64 (pMvd));
+        } else if (SUB_MB_TYPE_4x8 == uiSubMbType) {
+          ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx  ], LD32 (pMv));
+          ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD32 (pMv));
+          ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx  ], LD32 (pMvd));
+          ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD32 (pMvd));
+          ST32 (pMotionVector[0][iCacheIdx  ], LD32 (pMv));
+          ST32 (pMotionVector[0][iCacheIdx + 6], LD32 (pMv));
+          ST32 (pMvdCache[0][iCacheIdx  ], LD32 (pMvd));
+          ST32 (pMvdCache[0][iCacheIdx + 6], LD32 (pMvd));
+        } else {  //SUB_MB_TYPE_4x4
+          ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx  ], LD32 (pMv));
+          ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx  ], LD32 (pMvd));
+          ST32 (pMotionVector[0][iCacheIdx  ], LD32 (pMv));
+          ST32 (pMvdCache[0][iCacheIdx  ], LD32 (pMvd));
+        }
+      }
+    }
+  }
+  break;
+  default:
+    break;
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
+                          int8_t ref_idx[LIST_A][30],
+                          int32_t iListIdx, int32_t iZOrderIdx, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal) {
+  if (iActiveRefNum == 1) {
+    iRefIdxVal = 0;
+    return ERR_NONE;
+  }
+  uint32_t uiCode;
+  int32_t iIdxA = 0, iIdxB = 0;
+  int32_t iCtxInc;
+  int8_t* pRefIdxInMB = pCtx->pCurDqLayer->pRefIndex[LIST_0][pCtx->pCurDqLayer->iMbXyIndex];
+  if (iZOrderIdx == 0) {
+    iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
+             && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
+    iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+             && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
+  } else if (iZOrderIdx == 4) {
+    iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
+             && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
+    iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
+  } else if (iZOrderIdx == 8) {
+    iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
+    iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+             && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
+  } else {
+    iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
+    iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
+  }
+
+  iCtxInc = iIdxA + (iIdxB << 1);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + iCtxInc, uiCode));
+  if (uiCode) {
+    WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + 4, 1, uiCode));
+    ++uiCode;
+  }
+  iRefIdxVal = (int8_t) uiCode;
+  return ERR_NONE;
+}
+
+int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
+                           int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal) {
+  uint32_t uiCode;
+  int32_t iIdxA = 0;
+  //int32_t sym;
+  int32_t iCtxInc;
+  PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MVD + iMvComp * CTX_NUM_MVD;
+  iMvdVal = 0;
+  if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 6] >= 0)
+    iIdxA = WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 6][iMvComp]);
+  if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 1] >= 0)
+    iIdxA += WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 1][iMvComp]);
+
+  if (iIdxA < 3)
+    iCtxInc = 0;
+  else if (iIdxA > 32)
+    iCtxInc = 2;
+  else
+    iCtxInc = 1;
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,  pBinCtx + iCtxInc, uiCode));
+  if (uiCode) {
+    WELS_READ_VERIFY (DecodeUEGMvCabac (pCtx->pCabacDecEngine, pBinCtx + 3, 3, uiCode));
+    iMvdVal = (int16_t) (uiCode + 1);
+    WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
+    if (uiCode) {
+      iMvdVal = -iMvdVal;
+    }
+  } else {
+    iMvdVal = 0;
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiCbp) {
+  int32_t iIdxA = 0, iIdxB = 0, pALeftMb[2], pBTopMb[2];
+  uiCbp = 0;
+  uint32_t pCbpBit[6];
+  int32_t iCtxInc;
+
+  //Luma: bit by bit for 4 8x8 blocks in z-order
+  pBTopMb[0]  = pNeighAvail->iTopAvail  && pNeighAvail->iTopType  != MB_TYPE_INTRA_PCM
+                && ((pNeighAvail->iTopCbp  & (1 << 2)) == 0);
+  pBTopMb[1]  = pNeighAvail->iTopAvail  && pNeighAvail->iTopType  != MB_TYPE_INTRA_PCM
+                && ((pNeighAvail->iTopCbp  & (1 << 3)) == 0);
+  pALeftMb[0] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+                && ((pNeighAvail->iLeftCbp & (1 << 1)) == 0);
+  pALeftMb[1] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+                && ((pNeighAvail->iLeftCbp & (1 << 3)) == 0);
+
+  //left_top 8x8 block
+  iCtxInc = pALeftMb[0] + (pBTopMb[0] << 1);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[0]));
+  if (pCbpBit[0])
+    uiCbp += 0x01;
+
+  //right_top 8x8 block
+  iIdxA = !pCbpBit[0];
+  iCtxInc = iIdxA + (pBTopMb[1] << 1);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[1]));
+  if (pCbpBit[1])
+    uiCbp += 0x02;
+
+  //left_bottom 8x8 block
+  iIdxB = !pCbpBit[0];
+  iCtxInc = pALeftMb[1] + (iIdxB << 1);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[2]));
+  if (pCbpBit[2])
+    uiCbp += 0x04;
+
+  //right_bottom 8x8 block
+  iIdxB = !pCbpBit[1];
+  iIdxA = !pCbpBit[2];
+  iCtxInc = iIdxA + (iIdxB << 1);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[3]));
+  if (pCbpBit[3])
+    uiCbp += 0x08;
+
+  //Chroma: bit by bit
+  iIdxB = pNeighAvail->iTopAvail  && (pNeighAvail->iTopType  == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp  >> 4));
+  iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4));
+
+  //BitIdx = 0
+  iCtxInc = iIdxA + (iIdxB << 1);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + CTX_NUM_CBP + iCtxInc,
+                                    pCbpBit[4]));
+
+  //BitIdx = 1
+  if (pCbpBit[4]) {
+    iIdxB = pNeighAvail->iTopAvail  && (pNeighAvail->iTopType  == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp  >> 4) == 2);
+    iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4) == 2);
+    iCtxInc = iIdxA + (iIdxB << 1);
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
+                                      pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + 2 * CTX_NUM_CBP + iCtxInc,
+                                      pCbpBit[5]));
+    uiCbp += 1 << (4 + pCbpBit[5]);
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta) {
+  uint32_t uiCode;
+  PSlice pCurrSlice = & (pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer);
+  iQpDelta = 0;
+  PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_DELTA_QP;
+  int32_t iCtxInc = (pCurrSlice->iLastDeltaQp != 0);
+  WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
+  if (uiCode != 0) {
+    WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pBinCtx + 2, 1, uiCode));
+    uiCode++;
+    iQpDelta = (uiCode + 1) >> 1;
+    if ((uiCode & 1) == 0)
+      iQpDelta = - iQpDelta;
+  }
+  pCurrSlice->iLastDeltaQp = iQpDelta;
+  return ERR_NONE;
+}
+
+int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t iZIndex, int32_t iResProperty,
+                           PWelsDecoderContext pCtx, uint32_t& uiCbfBit) {
+  int8_t nA, nB/*, zigzag_idx = 0*/;
+  int32_t iCurrBlkXy = pCtx->pCurDqLayer->iMbXyIndex;
+  int32_t iTopBlkXy = iCurrBlkXy - pCtx->pCurDqLayer->iMbWidth; //default value: MB neighboring
+  int32_t iLeftBlkXy = iCurrBlkXy - 1; //default value: MB neighboring
+  uint8_t* pCbfDc = pCtx->pCurDqLayer->pCbfDc;
+  int8_t* pMbType = pCtx->pCurDqLayer->pMbType;
+  int32_t iCtxInc;
+  uiCbfBit = 0;
+  nA = nB = IS_INTRA (pMbType[iCurrBlkXy]);
+
+  if (iResProperty == I16_LUMA_DC || iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) { //DC
+    if (pNeighAvail->iTopAvail)
+      nB = (pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iTopBlkXy] >> iResProperty) & 1);
+    if (pNeighAvail->iLeftAvail)
+      nA = (pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iLeftBlkXy] >> iResProperty) & 1);
+    iCtxInc = nA + (nB << 1);
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
+                                      pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
+    if (uiCbfBit)
+      pCbfDc[iCurrBlkXy] |= (1 << iResProperty);
+  } else { //AC
+    //for 4x4 blk, make sure blk-idx is correct
+    if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] != 0xff) { //top blk available
+      if (g_kTopBlkInsideMb[iZIndex])
+        iTopBlkXy = iCurrBlkXy;
+      nB = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] || pMbType[iTopBlkXy]  == MB_TYPE_INTRA_PCM;
+    }
+    if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] != 0xff) { //left blk available
+      if (g_kLeftBlkInsideMb[iZIndex])
+        iLeftBlkXy = iCurrBlkXy;
+      nA = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] || pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM;
+    }
+
+    iCtxInc = nA + (nB << 1);
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
+                                      pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
+                                  uint32_t& uiCoeffNum) {
+  uint32_t uiCode;
+  PWelsCabacCtx pMapCtx  = pCtx->pCabacCtx + NEW_CTX_OFFSET_MAP + g_kBlockCat2CtxOffsetMap [iResProperty];
+  PWelsCabacCtx pLastCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_LAST + g_kBlockCat2CtxOffsetLast[iResProperty];
+
+  int32_t i;
+  uiCoeffNum = 0;
+  int32_t i0 = 0;
+  int32_t i1 = g_kMaxPos[iResProperty];
+
+  for (i = i0; i < i1; ++i) {
+    //read significant
+    WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pMapCtx + i, uiCode));
+    if (uiCode) {
+      * (pSignificantMap++) = 1;
+      ++ uiCoeffNum;
+      //read last significant
+      WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pLastCtx + i, uiCode));
+      if (uiCode) {
+        memset (pSignificantMap, 0, (i1 - i) * sizeof (int32_t));
+        return ERR_NONE;
+      }
+    } else
+      * (pSignificantMap++) = 0;
+  }
+
+  //deal with last pSignificantMap if no data
+  //if(i < i1+1)
+  {
+    *pSignificantMap = 1;
+    ++uiCoeffNum;
+  }
+
+  return ERR_NONE;
+}
+
+int32_t ParseSignificantCoeffCabac (int32_t* pSignificant, int32_t iResProperty, PWelsDecoderContext pCtx) {
+  uint32_t uiCode;
+  PWelsCabacCtx pOneCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_ONE + g_kBlockCat2CtxOffsetOne[iResProperty];
+  PWelsCabacCtx pAbsCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_ABS + g_kBlockCat2CtxOffsetAbs[iResProperty];
+  const int16_t iMaxType = g_kMaxC2[iResProperty];
+  int32_t i = g_kMaxPos[iResProperty];
+  int32_t* pCoff = pSignificant + i;
+  int32_t c1 = 1;
+  int32_t c2 = 0;
+  for (; i >= 0; --i) {
+    if (*pCoff != 0) {
+      WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pOneCtx + c1, uiCode));
+      *pCoff += uiCode;
+      if (*pCoff == 2) {
+        WELS_READ_VERIFY (DecodeUEGLevelCabac (pCtx->pCabacDecEngine, pAbsCtx + c2, uiCode));
+        *pCoff += uiCode;
+        ++c2;
+        c2 = WELS_MIN (c2, iMaxType);
+        c1 = 0;
+      } else if (c1) {
+        ++c1;
+        c1 = WELS_MIN (c1, 4);
+      }
+      WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
+      if (uiCode)
+        *pCoff = - *pCoff;
+    }
+    pCoff--;
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
+                                 int32_t iIndex, int32_t iMaxNumCoeff,
+                                 const uint8_t* pScanTable, int32_t iResProperty, short* sTCoeff, /*int mb_mode*/ uint8_t uiQp,
+                                 PWelsDecoderContext pCtx) {
+  int32_t iCurNzCacheIdx;
+  const uint16_t* pDeQuantMul = g_kuiDequantCoeff[uiQp];
+  uint32_t uiTotalCoeffNum = 0;
+  uint32_t uiCbpBit;
+  int32_t pSignificantMap[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+  WELS_READ_VERIFY (ParseCbfInfoCabac (pNeighAvail, pNonZeroCountCache, iIndex, iResProperty, pCtx, uiCbpBit));
+  if (uiCbpBit) { //has coeff
+    WELS_READ_VERIFY (ParseSignificantMapCabac (pSignificantMap, iResProperty, pCtx, uiTotalCoeffNum));
+    WELS_READ_VERIFY (ParseSignificantCoeffCabac (pSignificantMap, iResProperty, pCtx));
+  }
+
+  iCurNzCacheIdx = g_kCacheNzcScanIdx[iIndex];
+  pNonZeroCountCache[iCurNzCacheIdx] = (uint8_t)uiTotalCoeffNum;
+  if (uiTotalCoeffNum == 0) {
+    return ERR_NONE;
+  }
+  int32_t j = 0;
+  if (iResProperty == I16_LUMA_DC) {
+    do {
+      if (pSignificantMap[j] != 0)
+        sTCoeff[pScanTable[j]] = pSignificantMap[j];
+      ++j;
+    } while (j < 16);
+  } else if (iResProperty == CHROMA_DC_U) {
+    do {
+      if (pSignificantMap[j] != 0)
+        sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[0];
+      ++j;
+    } while (j < 16);
+  } else { //luma ac, chroma ac
+    do {
+      if (pSignificantMap[j] != 0)
+        sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[pScanTable[j] & 0x07];
+      ++j;
+    } while (j < 16);
+  }
+  return ERR_NONE;
+}
+
+int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx) {
+  int32_t i;
+  PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+  SBitStringAux* pBsAux = pCtx->pCurDqLayer->pBitStringAux;
+  SDqLayer* pCurLayer = pCtx->pCurDqLayer;
+  int32_t iDstStrideLuma = pCurLayer->pDec->iLinesize[0];
+  int32_t iDstStrideChroma = pCurLayer->pDec->iLinesize[1];
+  int32_t iMbX = pCurLayer->iMbX;
+  int32_t iMbY = pCurLayer->iMbY;
+  int32_t iMbXy = pCurLayer->iMbXyIndex;
+
+  int32_t iMbOffsetLuma = (iMbX + iMbY * iDstStrideLuma) << 4;
+  int32_t iMbOffsetChroma = (iMbX + iMbY * iDstStrideChroma) << 3;
+
+  uint8_t* pMbDstY = pCtx->pDec->pData[0] + iMbOffsetLuma;
+  uint8_t* pMbDstU = pCtx->pDec->pData[1] + iMbOffsetChroma;
+  uint8_t* pMbDstV = pCtx->pDec->pData[2] + iMbOffsetChroma;
+
+  uint8_t* pPtrSrc;
+
+  pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA_PCM;
+  RestoreCabacDecEngineToBS (pCabacDecEngine, pBsAux);
+  intX_t iBytesLeft = pBsAux->pEndBuf - pBsAux->pCurBuf;
+  if (iBytesLeft < 384) {
+    return ERR_CABAC_NO_BS_TO_READ;
+  }
+  pPtrSrc = pBsAux->pCurBuf;
+  for (i = 0; i < 16; i++) {   //luma
+    memcpy (pMbDstY , pPtrSrc, 16);
+    pMbDstY += iDstStrideLuma;
+    pPtrSrc += 16;
+  }
+  for (i = 0; i < 8; i++) {   //cb
+    memcpy (pMbDstU, pPtrSrc, 8);
+    pMbDstU += iDstStrideChroma;
+    pPtrSrc += 8;
+  }
+  for (i = 0; i < 8; i++) {   //cr
+    memcpy (pMbDstV, pPtrSrc, 8);
+    pMbDstV += iDstStrideChroma;
+    pPtrSrc += 8;
+  }
+
+  pBsAux->pCurBuf += 384;
+
+  pCurLayer->pLumaQp[iMbXy] = 0;
+  pCurLayer->pChromaQp[iMbXy] = 0;
+  memset (pCurLayer->pNzc[iMbXy], 16, sizeof (pCurLayer->pNzc[iMbXy]));
+
+  //step 4: cabac engine init
+  WELS_READ_VERIFY (InitReadBits (pBsAux, 1));
+  WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCabacDecEngine, pBsAux));
+  return ERR_NONE;
+}
+}
--- a/codec/decoder/core/src/parse_mb_syn_cavlc.cpp
+++ b/codec/decoder/core/src/parse_mb_syn_cavlc.cpp
@@ -45,7 +45,7 @@
 
 namespace WelsDec {
 #define MAX_LEVEL_PREFIX 15
-void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
+void GetNeighborAvailMbType (PWelsNeighAvail pNeighAvail, PDqLayer pCurLayer) {
   int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc;
   int32_t iCurXy, iTopXy = 0, iLeftXy = 0, iLeftTopXy = 0, iRightTopXy = 0;
   int32_t iCurX, iCurY;
@@ -58,9 +58,11 @@
     iLeftXy = iCurXy - 1;
     iLeftSliceIdc = pCurLayer->pSliceIdc[iLeftXy];
     pNeighAvail->iLeftAvail = (iLeftSliceIdc == iCurSliceIdc);
+    pNeighAvail->iLeftCbp   = pNeighAvail->iLeftAvail ? pCurLayer->pCbp[iLeftXy] : 0;
   } else {
     pNeighAvail->iLeftAvail = 0;
     pNeighAvail->iLeftTopAvail = 0;
+    pNeighAvail->iLeftCbp = 0;
   }
 
   if (iCurY != 0) {
@@ -67,6 +69,7 @@
     iTopXy = iCurXy - pCurLayer->iMbWidth;
     iTopSliceIdc = pCurLayer->pSliceIdc[iTopXy];
     pNeighAvail->iTopAvail = (iTopSliceIdc == iCurSliceIdc);
+    pNeighAvail->iTopCbp   = pNeighAvail->iTopAvail ? pCurLayer->pCbp[iTopXy] : 0;
     if (iCurX != 0) {
       iLeftTopXy = iTopXy - 1;
       iLeftTopSliceIdc = pCurLayer->pSliceIdc[iLeftTopXy];
@@ -85,6 +88,7 @@
     pNeighAvail->iTopAvail = 0;
     pNeighAvail->iLeftTopAvail = 0;
     pNeighAvail->iRightTopAvail = 0;
+    pNeighAvail->iTopCbp   = 0;
   }
 
   pNeighAvail->iLeftType     = (pNeighAvail->iLeftAvail     ? pCurLayer->pMbType[iLeftXy]     : 0);
@@ -92,14 +96,11 @@
   pNeighAvail->iLeftTopType  = (pNeighAvail->iLeftTopAvail  ? pCurLayer->pMbType[iLeftTopXy]  : 0);
   pNeighAvail->iRightTopType = (pNeighAvail->iRightTopAvail ? pCurLayer->pMbType[iRightTopXy] : 0);
 }
-void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+void WelsFillCacheNonZeroCount (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
                                 PDqLayer pCurLayer) { //no matter slice type, intra_pred_constrained_flag
   int32_t iCurXy  = pCurLayer->iMbXyIndex;
   int32_t iTopXy  = 0;
   int32_t iLeftXy = 0;
-
-  GetNeighborAvailMbType (pNeighAvail, pCurLayer);
-
   if (pNeighAvail->iTopAvail) {
     iTopXy = iCurXy - pCurLayer->iMbWidth;
   }
@@ -143,7 +144,7 @@
       pNonZeroCount[5 + 8 * 5] = -1;//unavailable
   }
 }
-void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
+void WelsFillCacheConstrain1Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
                                       PDqLayer pCurLayer) { //no matter slice type
   int32_t iCurXy  = pCurLayer->iMbXyIndex;
   int32_t iTopXy  = 0;
@@ -189,7 +190,7 @@
   }
 }
 
-void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
+void WelsFillCacheConstrain0Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
                                       PDqLayer pCurLayer) { //no matter slice type
   int32_t iCurXy  = pCurLayer->iMbXyIndex;
   int32_t iTopXy  = 0;
@@ -235,8 +236,8 @@
   }
 }
 
-void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
-                         int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer) {
+void WelsFillCacheInterCabac(PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int16_t iMvArray[LIST_A][30][MV_A], int16_t iMvdCache[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer)
+{
   int32_t iCurXy      = pCurLayer->iMbXyIndex;
   int32_t iTopXy      = 0;
   int32_t iLeftXy     = 0;
@@ -265,6 +266,12 @@
     ST32 (iMvArray[0][12], LD32 (pCurLayer->pMv[0][iLeftXy][ 7]));
     ST32 (iMvArray[0][18], LD32 (pCurLayer->pMv[0][iLeftXy][11]));
     ST32 (iMvArray[0][24], LD32 (pCurLayer->pMv[0][iLeftXy][15]));
+
+    ST32(iMvdCache[0][ 6], LD32(pCurLayer->pMvd[0][iLeftXy][ 3]));
+    ST32(iMvdCache[0][12], LD32(pCurLayer->pMvd[0][iLeftXy][ 7]));
+    ST32(iMvdCache[0][18], LD32(pCurLayer->pMvd[0][iLeftXy][11]));
+    ST32(iMvdCache[0][24], LD32(pCurLayer->pMvd[0][iLeftXy][15]));
+
     iRefIdxArray[0][ 6] = pCurLayer->pRefIndex[0][iLeftXy][ 3];
     iRefIdxArray[0][12] = pCurLayer->pRefIndex[0][iLeftXy][ 7];
     iRefIdxArray[0][18] = pCurLayer->pRefIndex[0][iLeftXy][11];
@@ -275,8 +282,136 @@
     ST32 (iMvArray[0][18], 0);
     ST32 (iMvArray[0][24], 0);
 
+    ST32(iMvdCache[0][ 6], 0);
+    ST32(iMvdCache[0][12], 0);
+    ST32(iMvdCache[0][18], 0);
+    ST32(iMvdCache[0][24], 0);
+
+
     if (0 == pNeighAvail->iLeftAvail) { //not available
       iRefIdxArray[0][ 6] =
+      iRefIdxArray[0][12] =
+      iRefIdxArray[0][18] =
+      iRefIdxArray[0][24] = REF_NOT_AVAIL;
+    } else { //available but is intra mb type
+      iRefIdxArray[0][ 6] =
+      iRefIdxArray[0][12] =
+      iRefIdxArray[0][18] =
+      iRefIdxArray[0][24] = REF_NOT_IN_LIST;
+    }
+  }
+  if (pNeighAvail->iLeftTopAvail && IS_INTER (pNeighAvail->iLeftTopType)) {
+    ST32 (iMvArray[0][0], LD32 (pCurLayer->pMv[0][iLeftTopXy][15]));
+    ST32(iMvdCache[0][0], LD32(pCurLayer->pMvd[0][iLeftTopXy][15]));
+    iRefIdxArray[0][0] = pCurLayer->pRefIndex[0][iLeftTopXy][15];
+  } else {
+    ST32 (iMvArray[0][0], 0);
+    ST32(iMvdCache[0][0], 0);
+    if (0 == pNeighAvail->iLeftTopAvail) { //not available
+      iRefIdxArray[0][0] = REF_NOT_AVAIL;
+    } else { //available but is intra mb type
+      iRefIdxArray[0][0] = REF_NOT_IN_LIST;
+    }
+  }
+
+  if (pNeighAvail->iTopAvail && IS_INTER (pNeighAvail->iTopType)) {
+    ST64 (iMvArray[0][1], LD64 (pCurLayer->pMv[0][iTopXy][12]));
+    ST64 (iMvArray[0][3], LD64 (pCurLayer->pMv[0][iTopXy][14]));
+    ST64(iMvdCache[0][1], LD64(pCurLayer->pMvd[0][iTopXy][12]));
+    ST64(iMvdCache[0][3], LD64(pCurLayer->pMvd[0][iTopXy][14]));
+    ST32 (&iRefIdxArray[0][1], LD32 (&pCurLayer->pRefIndex[0][iTopXy][12]));
+  } else {
+    ST64 (iMvArray[0][1], 0);
+    ST64 (iMvArray[0][3], 0);
+    ST64(iMvdCache[0][1], 0);
+    ST64(iMvdCache[0][3], 0);
+    if (0 == pNeighAvail->iTopAvail) { //not available
+      iRefIdxArray[0][1] =
+      iRefIdxArray[0][2] =
+      iRefIdxArray[0][3] =
+      iRefIdxArray[0][4] = REF_NOT_AVAIL;
+    } else { //available but is intra mb type
+      iRefIdxArray[0][1] =
+      iRefIdxArray[0][2] =
+      iRefIdxArray[0][3] =
+      iRefIdxArray[0][4] = REF_NOT_IN_LIST;
+    }
+  }
+
+  if (pNeighAvail->iRightTopAvail && IS_INTER (pNeighAvail->iRightTopType)) {
+    ST32 (iMvArray[0][5], LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
+    ST32(iMvdCache[0][5], LD32(pCurLayer->pMvd[0][iRightTopXy][12]));
+    iRefIdxArray[0][5] = pCurLayer->pRefIndex[0][iRightTopXy][12];
+  } else {
+    ST32 (iMvArray[0][5], 0);
+    if (0 == pNeighAvail->iRightTopAvail) { //not available
+      iRefIdxArray[0][5] = REF_NOT_AVAIL;
+    } else { //available but is intra mb type
+      iRefIdxArray[0][5] = REF_NOT_IN_LIST;
+    }
+  }
+
+  //right-top 4*4 block unavailable
+  ST32 (iMvArray[0][ 9], 0);
+  ST32 (iMvArray[0][21], 0);
+  ST32 (iMvArray[0][11], 0);
+  ST32 (iMvArray[0][17], 0);
+  ST32 (iMvArray[0][23], 0);
+  ST32(iMvdCache[0][ 9], 0);
+  ST32(iMvdCache[0][21], 0);
+  ST32(iMvdCache[0][11], 0);
+  ST32(iMvdCache[0][17], 0);
+  ST32(iMvdCache[0][23], 0);
+  iRefIdxArray[0][ 9] =
+  iRefIdxArray[0][21] =
+  iRefIdxArray[0][11] =
+  iRefIdxArray[0][17] =
+  iRefIdxArray[0][23] = REF_NOT_AVAIL;
+}
+
+void WelsFillCacheInter (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+                         int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer)
+{
+  int32_t iCurXy      = pCurLayer->iMbXyIndex;
+  int32_t iTopXy      = 0;
+  int32_t iLeftXy     = 0;
+  int32_t iLeftTopXy  = 0;
+  int32_t iRightTopXy = 0;
+
+  //stuff non_zero_coeff_count from pNeighAvail(left and top)
+  WelsFillCacheNonZeroCount (pNeighAvail, pNonZeroCount, pCurLayer);
+
+  if (pNeighAvail->iTopAvail) {
+    iTopXy = iCurXy - pCurLayer->iMbWidth;
+  }
+  if (pNeighAvail->iLeftAvail) {
+    iLeftXy = iCurXy - 1;
+  }
+  if (pNeighAvail->iLeftTopAvail) {
+    iLeftTopXy = iCurXy - 1 - pCurLayer->iMbWidth;
+  }
+  if (pNeighAvail->iRightTopAvail) {
+    iRightTopXy = iCurXy + 1 - pCurLayer->iMbWidth;
+  }
+
+  //stuff mv_cache and iRefIdxArray from left and top (inter)
+  if (pNeighAvail->iLeftAvail && IS_INTER (pNeighAvail->iLeftType)) {
+    ST32 (iMvArray[0][ 6], LD32 (pCurLayer->pMv[0][iLeftXy][ 3]));
+    ST32 (iMvArray[0][12], LD32 (pCurLayer->pMv[0][iLeftXy][ 7]));
+    ST32 (iMvArray[0][18], LD32 (pCurLayer->pMv[0][iLeftXy][11]));
+    ST32 (iMvArray[0][24], LD32 (pCurLayer->pMv[0][iLeftXy][15]));
+    iRefIdxArray[0][ 6] = pCurLayer->pRefIndex[0][iLeftXy][ 3];
+    iRefIdxArray[0][12] = pCurLayer->pRefIndex[0][iLeftXy][ 7];
+    iRefIdxArray[0][18] = pCurLayer->pRefIndex[0][iLeftXy][11];
+    iRefIdxArray[0][24] = pCurLayer->pRefIndex[0][iLeftXy][15];
+  } else {
+    ST32 (iMvArray[0][ 6], 0);
+    ST32 (iMvArray[0][12], 0);
+    ST32 (iMvArray[0][18], 0);
+    ST32 (iMvArray[0][24], 0);
+
+    if (0 == pNeighAvail->iLeftAvail) { //not available
+      iRefIdxArray[0][ 6] =
         iRefIdxArray[0][12] =
           iRefIdxArray[0][18] =
             iRefIdxArray[0][24] = REF_NOT_AVAIL;
@@ -298,7 +433,6 @@
       iRefIdxArray[0][0] = REF_NOT_IN_LIST;
     }
   }
-
   if (pNeighAvail->iTopAvail && IS_INTER (pNeighAvail->iTopType)) {
     ST64 (iMvArray[0][1], LD64 (pCurLayer->pMv[0][iTopXy][12]));
     ST64 (iMvArray[0][3], LD64 (pCurLayer->pMv[0][iTopXy][14]));
@@ -306,7 +440,6 @@
   } else {
     ST64 (iMvArray[0][1], 0);
     ST64 (iMvArray[0][3], 0);
-
     if (0 == pNeighAvail->iTopAvail) { //not available
       iRefIdxArray[0][1] =
         iRefIdxArray[0][2] =
@@ -319,7 +452,6 @@
             iRefIdxArray[0][4] = REF_NOT_IN_LIST;
     }
   }
-
   if (pNeighAvail->iRightTopAvail && IS_INTER (pNeighAvail->iRightTopType)) {
     ST32 (iMvArray[0][5], LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
     iRefIdxArray[0][5] = pCurLayer->pRefIndex[0][iRightTopXy][12];
@@ -331,7 +463,6 @@
       iRefIdxArray[0][5] = REF_NOT_IN_LIST;
     }
   }
-
   //right-top 4*4 block unavailable
   ST32 (iMvArray[0][ 9], 0);
   ST32 (iMvArray[0][21], 0);
@@ -358,9 +489,6 @@
   return iBestMode;
 }
 
-#define MAX_PRED_MODE_ID_I16x16  3
-#define MAX_PRED_MODE_ID_CHROMA  3
-#define MAX_PRED_MODE_ID_I4x4    8
 #define CHECK_I16_MODE(a, b, c, d)                           \
                       ((a == g_ksI16PredInfo[a].iPredMode) &&  \
 					   (b >= g_ksI16PredInfo[a].iLeftAvail) && \
@@ -755,216 +883,6 @@
       j          = kpZigzagTable[ iCoeffNum ];
       pTCoeff[j] = iLevel[i] * kpDequantCoeff[j & 0x07];
     }
-  }
-
-  return 0;
-}
-
-int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
-                                     PDqLayer pCurDqLayer) {
-  int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
-  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
-  int32_t iFinalMode, i;
-
-  uint8_t uiNeighAvail = 0;
-  uint32_t uiCode;
-  if (pNeighAvail->iLeftAvail) {  //left
-    iSampleAvail[ 6] =
-      iSampleAvail[12] =
-        iSampleAvail[18] =
-          iSampleAvail[24] = 1;
-  }
-  if (pNeighAvail->iLeftTopAvail) { //top_left
-    iSampleAvail[0] = 1;
-  }
-  if (pNeighAvail->iTopAvail) { //top
-    iSampleAvail[1] =
-      iSampleAvail[2] =
-        iSampleAvail[3] =
-          iSampleAvail[4] = 1;
-  }
-  if (pNeighAvail->iRightTopAvail) { //top_right
-    iSampleAvail[5] = 1;
-  }
-
-  uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
-
-  for (i = 0; i < 16; i++) {
-    WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ]
-    const int32_t kiPrevIntra4x4PredMode = uiCode;
-    const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
-
-    int8_t iBestMode;
-    if (kiPrevIntra4x4PredMode) {
-      iBestMode = kiPredMode;
-    } else { //kPrevIntra4x4PredMode == 0
-      WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode)); //rem_intra4x4_pred_mode[ luma4x4BlkIdx ]
-      const int32_t kiRemIntra4x4PredMode = uiCode;
-      if (kiRemIntra4x4PredMode < kiPredMode) {
-        iBestMode = kiRemIntra4x4PredMode;
-      } else {
-        iBestMode = kiRemIntra4x4PredMode + 1;
-      }
-    }
-
-    iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
-    if (iFinalMode  == ERR_INVALID_INTRA4X4_MODE) {
-      return ERR_INFO_INVALID_I4x4_PRED_MODE;
-    }
-
-    pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
-
-    pIntraPredMode[g_kuiScan8[i]] = iBestMode;
-
-    iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
-  }
-  ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
-  pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
-  pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
-  pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
-  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
-  if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
-  }
-  pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
-  if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
-  }
-
-  return 0;
-}
-
-int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
-                                     PDqLayer pCurDqLayer) {
-  int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
-  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
-  int32_t iFinalMode, i;
-
-  uint8_t uiNeighAvail = 0;
-  uint32_t uiCode;
-  if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {   //left
-    iSampleAvail[ 6] =
-      iSampleAvail[12] =
-        iSampleAvail[18] =
-          iSampleAvail[24] = 1;
-  }
-  if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {  //top_left
-    iSampleAvail[0] = 1;
-  }
-  if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {  //top
-    iSampleAvail[1] =
-      iSampleAvail[2] =
-        iSampleAvail[3] =
-          iSampleAvail[4] = 1;
-  }
-  if (pNeighAvail->iRightTopAvail && IS_INTRA (pNeighAvail->iRightTopType)) {  //top_right
-    iSampleAvail[5] = 1;
-  }
-
-  uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
-
-  for (i = 0; i < 16; i++) {
-    WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ]
-    const int32_t kiPrevIntra4x4PredMode = uiCode; //1bit
-    const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
-
-    int8_t iBestMode;
-    if (kiPrevIntra4x4PredMode) {
-      iBestMode = kiPredMode;
-    } else { //kPrevIntra4x4PredMode == 0
-      WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode)); //rem_intra4x4_pred_mode[ luma4x4BlkIdx ]
-      const int32_t kiRemIntra4x4PredMode = uiCode;
-      if (kiRemIntra4x4PredMode < kiPredMode) {
-        iBestMode = kiRemIntra4x4PredMode;
-      } else {
-        iBestMode = kiRemIntra4x4PredMode + 1;
-      }
-    }
-
-    iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
-    if (iFinalMode  == ERR_INVALID_INTRA4X4_MODE) {
-      return ERR_INFO_INVALID_I4x4_PRED_MODE;
-    }
-
-    pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
-
-    pIntraPredMode[g_kuiScan8[i]] = iBestMode;
-
-    iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
-  }
-  ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
-  pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
-  pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
-  pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
-  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
-  if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
-  }
-  pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
-  if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
-  }
-
-  return 0;
-}
-
-int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
-  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
-  uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
-  uint32_t uiCode;
-  if (pNeighAvail->iLeftAvail) {
-    uiNeighAvail = (1 << 2);
-  }
-  if (pNeighAvail->iLeftTopAvail) {
-    uiNeighAvail |= (1 << 1);
-  }
-  if (pNeighAvail->iTopAvail) {
-    uiNeighAvail |= 1;
-  }
-
-  if (CheckIntra16x16PredMode (uiNeighAvail,
-                               &pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
-    return ERR_INFO_INVALID_I16x16_PRED_MODE;
-  }
-  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
-  if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
-  }
-  pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
-
-  if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
-  }
-
-  return 0;
-}
-
-int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
-  int32_t iMbXy = pCurDqLayer->iMbXyIndex;
-  uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
-  uint32_t uiCode;
-  if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {
-    uiNeighAvail = (1 << 2);
-  }
-  if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {
-    uiNeighAvail |= (1 << 1);
-  }
-  if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {
-    uiNeighAvail |= 1;
-  }
-
-  if (CheckIntra16x16PredMode (uiNeighAvail,
-                               &pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
-    return ERR_INFO_INVALID_I16x16_PRED_MODE;
-  }
-  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
-  if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
-  }
-  pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
-
-  if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
-    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
   }
 
   return 0;
--- a/codec/decoder/targets.mk
+++ b/codec/decoder/targets.mk
@@ -2,6 +2,7 @@
 DECODER_CPP_SRCS=\
 	$(DECODER_SRCDIR)/core/src/au_parser.cpp\
 	$(DECODER_SRCDIR)/core/src/bit_stream.cpp\
+	$(DECODER_SRCDIR)/core/src/cabac_decoder.cpp\
 	$(DECODER_SRCDIR)/core/src/deblocking.cpp\
 	$(DECODER_SRCDIR)/core/src/decode_mb_aux.cpp\
 	$(DECODER_SRCDIR)/core/src/decode_slice.cpp\
@@ -16,6 +17,7 @@
 	$(DECODER_SRCDIR)/core/src/mem_align.cpp\
 	$(DECODER_SRCDIR)/core/src/memmgr_nal_unit.cpp\
 	$(DECODER_SRCDIR)/core/src/mv_pred.cpp\
+	$(DECODER_SRCDIR)/core/src/parse_mb_syn_cabac.cpp\
 	$(DECODER_SRCDIR)/core/src/parse_mb_syn_cavlc.cpp\
 	$(DECODER_SRCDIR)/core/src/pic_queue.cpp\
 	$(DECODER_SRCDIR)/core/src/rec_mb.cpp\
binary files /dev/null b/res/QCIF_2P_I_allIPCM.264 differ
binary files /dev/null b/res/test_cif_I_CABAC_PCM.264 differ
binary files /dev/null b/res/test_cif_I_CABAC_slice.264 differ
binary files /dev/null b/res/test_cif_P_CABAC_slice.264 differ
binary files /dev/null b/res/test_qcif_cabac.264 differ
--- a/test/api/decoder_test.cpp
+++ b/test/api/decoder_test.cpp
@@ -119,7 +119,12 @@
   {"res/SVA_CL1_E.264", "4fe09ab6cdc965ea10a20f1d6dd38aca954412bb"},
   {"res/SVA_FM1_E.264", "fad08c4ff7cf2307b6579853d0f4652fc26645d3"},
   {"res/SVA_NL1_B.264", "6d63f72a0c0d833b1db0ba438afff3b4180fb3e6"},
-  {"res/SVA_NL2_E.264", "70453ef8097c94dd190d6d2d1d5cb83c67e66238"}
+  {"res/SVA_NL2_E.264", "70453ef8097c94dd190d6d2d1d5cb83c67e66238"},
+  {"res/test_cif_I_CABAC_PCM.264", "95fdf21470d3bbcf95505abb2164042063a79d98"},
+  {"res/test_cif_I_CABAC_slice.264", "19121bc67f2b13fb8f030504fc0827e1ac6d0fdb"},
+  {"res/test_cif_P_CABAC_slice.264", "521bbd0ba2422369b724c7054545cf107a56f959"},
+  {"res/test_qcif_cabac.264", "587d1d05943f3cd416bf69469975fdee05361e69"},
+  {"res/QCIF_2P_I_allIPCM.264", "8724c0866ebdba7ebb7209a0c0c3ae3ae38a0240"}
 };
 
 INSTANTIATE_TEST_CASE_P (DecodeFile, DecoderOutputTest,
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -763,7 +763,7 @@
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   int32_t iSpsPpsIdAddition = 1;
   encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
-  int32_t iIDRPeriod = 60;
+  int32_t iIDRPeriod = pow(2,(param_.iTemporalLayerNum-1)) * ((rand() % 5) + 1);
   encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
   SLTRConfig sLtrConfigVal;
   sLtrConfigVal.bEnableLongTermReference = 1;
@@ -1854,7 +1854,7 @@
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   int32_t iSpsPpsIdAddition = 1;
   encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
-  int32_t iIDRPeriod = 15;
+  int32_t iIDRPeriod = pow(2,(param_.iTemporalLayerNum-1)) * ((rand() % 5) + 1);
   encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
   SLTRConfig sLtrConfigVal;
   sLtrConfigVal.bEnableLongTermReference = 1;