shithub: openh264

ref: 063709c92e8bafe467d384f564afbdc6b66eb39a
dir: /codec/decoder/core/src/decoder_core.cpp/

View raw version
/*!
 * \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.
 *
 *	decoder_core.c:	Wels decoder framework core implementation
 */

#include <string.h>
#include "codec_def.h"
#include "decoder_core.h"
#include "typedefs.h"
#include "wels_const.h"
#include "wels_common_basis.h"
#include "codec_app_def.h"
#include "decoder_context.h"
#include "dec_golomb.h"
#include "bit_stream.h"
#include "error_code.h"
#include "parameter_sets.h"
#include "fmo.h"
#include "utils.h"
#include "memmgr_nal_unit.h"
#include "dec_frame.h"
#include "au_parser.h"
#include "pic_queue.h"
#include "ls_defines.h"
#include "decode_slice.h"
#include "manage_dec_ref.h"
#include "expand_pic.h"
#include "decoder.h"
#include "decode_mb_aux.h"
#include "mem_align.h"

namespace WelsDec {

static inline int32_t DecodeFrameConstruction( PWelsDecoderContext pCtx, uint8_t **ppDst, int32_t *pDstLen, int32_t *pWidth, int32_t *pHeight, SBufferInfo *pDstInfo )
{
	PDqLayer pCurDq = pCtx->pCurDqLayer;	
	PPicture pPic = pCtx->pDec;

	const int32_t kiWidth = pCurDq->iMbWidth << 4;
	const int32_t kiHeight= pCurDq->iMbHeight << 4;

	const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight;

	if ( pPic->iTotalNumMbRec != kiTotalNumMbInCurLayer )
	{
		WelsLog( pCtx, WELS_LOG_WARNING, "DecodeFrameConstruction():::iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d \n",
			pPic->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight );
		return -1;
	}
#ifdef NO_WAITING_AU
    pPic->iTotalNumMbRec = 0;
#endif

	if ( I_SLICE == pCurDq->sLayerInfo.sSliceInLayer.eSliceType )
	{
		memcpy( &(pCtx->sFrameCrop), &(pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), sizeof(SPosOffset) );//confirmed_safe_unsafe_usage
#ifdef LONG_TERM_REF
		pCtx->bParamSetsLostFlag      = false;
#else
		pCtx->bReferenceLostAtT0Flag = false;	// need initialize it due I_SLICE, 6/4/2010
#endif //LONG_TERM_REF
		WelsLog( pCtx, WELS_LOG_INFO, "DecodeFrameConstruction()::::output good I frame, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d.\n",
			kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, pCtx->sFrameCrop.iBottomOffset );
		WelsLog( pCtx, WELS_LOG_INFO, "After decoding, set_mode:[%s], eWorkMode:[%s], eBufferProperty:[%s]\n",
			DECODER_MODE_NAME(pCtx->iSetMode), DECODER_MODE_NAME(pCtx->iDecoderMode), OUTPUT_PROPERTY_NAME(pDstInfo->eBufferProperty));
	}
	
	//////output:::normal path
	ppDst[0]      = pPic->pData[0];
	ppDst[1]      = pPic->pData[1];
	ppDst[2]      = pPic->pData[2];
	*pDstLen     = pPic->iLinesize[0]; 
	*(pDstLen+1) = pPic->iLinesize[1];
	*pWidth      = kiWidth;
	*pHeight     = kiHeight;

	pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;

	pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset)*2;
	pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset)*2;
	pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
	pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
	ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset*2*pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset*2;
	ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset  *pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
	ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset  *pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
	pDstInfo->eBufferProperty = BUFFER_HOST;
	pDstInfo->iBufferStatus = 1;

	return 0;
}

inline BOOL_T    CheckSliceNeedReconstruct(int16_t iCurDid, int16_t iCurQid, bool_t bStoreRefBasePicFlag, 
	uint8_t uiDidMax, uint8_t uiLayerDqId, uint8_t uiTargetDqId)
{
    return ( (iCurDid == uiDidMax) && (iCurQid == BASE_QUALITY_ID) && (bStoreRefBasePicFlag) ) // store base
       || (uiLayerDqId == uiTargetDqId); // target layer
}

inline uint8_t GetTargetDqId(uint8_t uiTargetDqId,  SDecodingParam * psParam)
{
    uint8_t  uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255;

	return WELS_MIN(uiTargetDqId, uiRequiredDqId);
}
	

inline void_t    HandleReferenceLostL0(PWelsDecoderContext pCtx, PNalUnit pCurNal)
{
    if( 0 == pCurNal->sNalHeaderExt.uiTemporalId ){
		pCtx->bReferenceLostAtT0Flag = true;
    }
#ifndef LONG_TERM_REF
	if( pCtx->bReferenceLostAtT0Flag ){
		ResetParameterSetsState(pCtx);
	}	
#endif
	pCtx->iErrorCode |= dsBitstreamError;
}

inline void_t    HandleReferenceLost(PWelsDecoderContext pCtx, PNalUnit pCurNal)
{
    if( (0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId) ){
		pCtx->bReferenceLostAtT0Flag = true;
    }
#ifndef LONG_TERM_REF
	if( pCtx->bReferenceLostAtT0Flag ){
		ResetParameterSetsState(pCtx);
    }
#endif
	pCtx->iErrorCode |= dsRefLost;
}

inline int32_t  WelsDecodeConstructSlice(PWelsDecoderContext pCtx, PNalUnit pCurNal)
{
    int32_t  iRet = WelsTargetSliceConstruction(pCtx);

	if( iRet ){
		HandleReferenceLostL0(pCtx, pCurNal);
	}

	return iRet;
}

/*
 *	Predeclared function routines ..
 */
int32_t ParseRefPicListReordering ( PBitStringAux pBs, PSliceHeader pSh )
{
	int32_t iList = 0;
	const ESliceType keSt = pSh->eSliceType;
	PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering;
	
	if ( keSt == I_SLICE || keSt == SI_SLICE )
		return ERR_NONE;

	// Common syntaxs for P or B slices: list0, list1 followed if B slices used.
	do {
		pRefPicListReordering->bRefPicListReorderingFlag[iList]	= !!BsGetOneBit( pBs);

		if ( pRefPicListReordering->bRefPicListReorderingFlag[iList] ){
			int32_t iIdx = 0;
			do {
				const uint8_t kuiIdc = BsGetUe( pBs );	
				
				//Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)---
				if ((iIdx >= MAX_REF_PIC_COUNT )||(kuiIdc > 3))
				{
					return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING);
				}
				pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc	= kuiIdc;
				if ( kuiIdc == 3 )
					break;

				if ( iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT )
					return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING);
				
				if (kuiIdc == 0 || kuiIdc == 1){
					pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = BsGetUe( pBs );	// uiAbsDiffPicNumMinus1
				}
				else if (kuiIdc == 2){				
					pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum= BsGetUe( pBs );			
				}
				
				++ iIdx;
			} while(true);
		}
		if (keSt != B_SLICE)
			break;
		++ iList;
	} while(iList < LIST_A);
	
	return ERR_NONE;
}

int32_t ParseDecRefPicMarking ( PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps, const bool_t kbIdrFlag)
{
	PRefPicMarking const kpRefMarking = &pSh->sRefMarking;

	if ( kbIdrFlag ){
		kpRefMarking->bNoOutputOfPriorPicsFlag	= !!BsGetOneBit( pBs );
		kpRefMarking->bLongTermRefFlag			= !!BsGetOneBit( pBs );
	}
	else{
		kpRefMarking->bAdaptiveRefPicMarkingModeFlag	= !!BsGetOneBit( pBs );
		if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag){
			int32_t iIdx = 0;
			do {
				const int32_t kiMmco = BsGetUe( pBs );

				kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kiMmco;
				if (kiMmco == MMCO_END)
					break;

				if (kiMmco == MMCO_SHORT2UNUSED || kiMmco == MMCO_SHORT2LONG)
				{
					kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + BsGetUe( pBs );
					kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & ((1<<pSps->uiLog2MaxFrameNum)-1);
				}
				else if (kiMmco == MMCO_LONG2UNUSED)
					kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = BsGetUe( pBs );

				if (kiMmco == MMCO_SHORT2LONG || kiMmco == MMCO_LONG)
				{
					kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = BsGetUe( pBs );
				}
				else if (kiMmco == MMCO_SET_MAX_LONG)
					kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + BsGetUe( pBs );
				++ iIdx;

			} while(iIdx < MAX_MMCO_COUNT);
		}	
	}
	
	return ERR_NONE;
}

bool_t FillDefaultSliceHeaderExt ( PSliceHeaderExt pShExt, PNalUnitHeaderExt pNalExt )
{
	if ( pShExt == NULL || pNalExt == NULL )
		return false;

	if ( pNalExt->iNoInterLayerPredFlag || pNalExt->uiQualityId > 0 )
		pShExt->bBasePredWeightTableFlag	= false;
	else
		pShExt->bBasePredWeightTableFlag	= true;
    pShExt->uiRefLayerDqId = (uint8_t)-1;
	pShExt->uiDisableInterLayerDeblockingFilterIdc	= 0;
	pShExt->iInterLayerSliceAlphaC0Offset			= 0;
	pShExt->iInterLayerSliceBetaOffset				= 0;
	pShExt->bConstrainedIntraResamplingFlag			= false;
	pShExt->uiRefLayerChromaPhaseXPlus1Flag			= 0;
	pShExt->uiRefLayerChromaPhaseYPlus1				= 1;
	//memset(&pShExt->sScaledRefLayer, 0, sizeof(SPosOffset));

	pShExt->iScaledRefLayerPicWidthInSampleLuma	= pShExt->sSliceHeader.iMbWidth << 4;
	pShExt->iScaledRefLayerPicHeightInSampleLuma	= pShExt->sSliceHeader.iMbHeight << 4;

	pShExt->bSliceSkipFlag	= false;
	pShExt->bAdaptiveBaseModeFlag	= false;
	pShExt->bDefaultBaseModeFlag	= false;
	pShExt->bAdaptiveMotionPredFlag	= false;
	pShExt->bDefaultMotionPredFlag	= false;
	pShExt->bAdaptiveResidualPredFlag	= false;
	pShExt->bDefaultResidualPredFlag	= false;
	pShExt->bTCoeffLevelPredFlag		= false;
	pShExt->uiScanIdxStart				= 0;
	pShExt->uiScanIdxEnd				= 15;

	return true;
}

/*
 * WelsInitMemory
 * Memory request for new introduced data
 * Especially for:
 * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache.
 * return:
 *	0 - success; otherwise returned error_no defined in error_no.h.
*/
int32_t WelsInitMemory( PWelsDecoderContext pCtx )
{
	if (pCtx == NULL){
		return ERR_INFO_INVALID_PTR;
	}

	if ( MemInitNalList( &pCtx->pAccessUnitList, MAX_NAL_UNIT_NUM_IN_AU ) != 0 )
		return ERR_INFO_OUT_OF_MEMORY;	

	if ( ( pCtx->sRawData.pHead = static_cast<uint8_t*> (WelsMalloc( MAX_ACCESS_UINT_CAPACITY, "pCtx->sRawData->pHead" )) ) == NULL )
	{
		return ERR_INFO_OUT_OF_MEMORY;
	}
	pCtx->sRawData.pStartPos               =
	pCtx->sRawData.pCurPos                 = pCtx->sRawData.pHead;
	pCtx->sRawData.pEnd                     = pCtx->sRawData.pHead + MAX_ACCESS_UINT_CAPACITY;	
	
	pCtx->uiTargetDqId			= (uint8_t)-1;
	pCtx->bEndOfStreamFlag	= false;
	pCtx->iImgWidthInPixel	= 0;
	pCtx->iImgHeightInPixel	= 0;	
	
	return ERR_NONE;
}

/*
 * WelsFreeMemory
 * Free memory introduced in WelsInitMemory at destruction of decoder.
 * 
 */
void_t WelsFreeMemory( PWelsDecoderContext pCtx )
{
	if ( pCtx == NULL )
		return;

	if ( NULL != pCtx->pParam )
	{
		WelsFree( pCtx->pParam, "pCtx->pParam" );

		pCtx->pParam = NULL;
	}

	MemFreeNalList( &pCtx->pAccessUnitList );
			
	if ( pCtx->sRawData.pHead )
	{
		WelsFree(pCtx->sRawData.pHead, "pCtx->sRawData->pHead");		
	}
	pCtx->sRawData.pHead                = NULL;
	pCtx->sRawData.pEnd                 = NULL;
	pCtx->sRawData.pStartPos	        = NULL;
	pCtx->sRawData.pCurPos             = NULL;	
}

/*
 *	DecodeNalHeaderExt
 *	Trigger condition: NAL_UNIT_TYPE = NAL_UNIT_PREFIX or NAL_UNIT_CODED_SLICE_EXT
 *	Parameter:
 *	pNal:	target NALUnit ptr
 *	pSrc:	NAL Unit bitstream
 */
void_t DecodeNalHeaderExt( PNalUnit pNal, uint8_t* pSrc )
{
	PNalUnitHeaderExt pHeaderExt = &pNal->sNalHeaderExt;	

	uint8_t uiCurByte = *pSrc;	
	pHeaderExt->bIdrFlag				 = !!(uiCurByte & 0x40);
	pHeaderExt->uiPriorityId			 = uiCurByte & 0x3F;

	uiCurByte = *(++pSrc);
	pHeaderExt->iNoInterLayerPredFlag = uiCurByte >> 7;
	pHeaderExt->uiDependencyId			 = (uiCurByte & 0x70) >> 4;
	pHeaderExt->uiQualityId				 = uiCurByte & 0x0F;
	uiCurByte = *(++pSrc);
	pHeaderExt->uiTemporalId			 = uiCurByte >> 5;
	pHeaderExt->bUseRefBasePicFlag	     = !!(uiCurByte & 0x10);
	pHeaderExt->bDiscardableFlag		 = !!(uiCurByte & 0x08);
	pHeaderExt->bOutputFlag				 = !!(uiCurByte & 0x04);
	pHeaderExt->uiReservedThree2Bits	 = uiCurByte & 0x03;	
	pHeaderExt->uiLayerDqId				 = (pHeaderExt->uiDependencyId << 4) | pHeaderExt->uiQualityId;
}


#ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_ID
int32_t CheckPpsId( PWelsDecoderContext pCtx, PPps* ppPps, uint32_t uiPpsId )
{
	PPps pPpsList = pCtx->sPpsBuffer;
	int32_t iPpsNum = pCtx->iPpsTotalNum;
	int32_t i = 0;

	if ( iPpsNum <= 0 )
	{
		pCtx->iErrorCode |= dsNoParamSets;
		
		WelsLog( pCtx, WELS_LOG_WARNING, "CheckPpsId():::::PPS list is empty...NO PPS!!!\n" );
		return dsNoParamSets;
	}

	while ( i < iPpsNum )
	{
		if ( uiPpsId == pPpsList[i].iPpsId )
		{
			*ppPps = &pPpsList[i];
			break;
		}
		else
		{
			++i;
		}
	}

	if ( i == iPpsNum )
	{
		pCtx->iErrorCode |= dsNoParamSets;
		
		WelsLog( pCtx, WELS_LOG_WARNING, "CheckPpsId()::::::CAN NOT find the matching from the PPS List.  iPpsId:%d\n", uiPpsId );
		return dsNoParamSets;
	}

	return 0;
}

int32_t CheckSpsId( PWelsDecoderContext pCtx, PSubsetSps* ppSubsetSps, PSps* ppSps, int32_t iSpsId, bool_t bExtensionFlag )
{
	PSps pSpsList = pCtx->sSpsBuffer;
	PSubsetSps pSubspsList = pCtx->sSubsetSpsBuffer;

	int32_t iSpsNum    = pCtx->iSpsTotalNum;
	int32_t iSubspsNum = pCtx->iSubspsTotalNum;
	int32_t i = 0;

	if ( bExtensionFlag )
	{
		if ( iSubspsNum <= 0 )
		{
			pCtx->iErrorCode |= dsNoParamSets;
			
			WelsLog( pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SUBSPS list is empty....NO SUBSPS\n" );
			return dsNoParamSets;
		}
		while ( i < iSubspsNum )
		{
			if ( iSpsId == pSubspsList[i].sSps.iSpsId )
			{
				*ppSubsetSps = &pSubspsList[i];
				*ppSps       = &pSubspsList[i].sSps;
				break;
			}
			else
			{
				++i;
			}
		}
		if ( i == iSubspsNum )
		{
			pCtx->iErrorCode |= dsNoParamSets;
			
			WelsLog( pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SUBSPS List.  iSpsId:%d\n", iSpsId );
			return dsNoParamSets;
		}
	}
	else
	{
		if ( iSpsNum <= 0 )
		{
			pCtx->iErrorCode |= dsNoParamSets;
			
			WelsLog( pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SPS list is empty....NO SPS\n" );
			return dsNoParamSets;
		}
		while ( i < iSpsNum )
		{
			if ( iSpsId == pSpsList[i].iSpsId )
			{
				*ppSubsetSps = NULL;
				*ppSps       = &pSpsList[i];
				break;
			}
			else
			{
				++i;
			}
		}
		if ( i == iSpsNum )
		{
			pCtx->iErrorCode |= dsNoParamSets;
			
			WelsLog( pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SPS List.  iSpsId:%d\n", iSpsId );
			return dsNoParamSets;
		}
	}
	
	return 0;
}

#endif
/*
 *	decode_slice_header_avc
 *	Parse slice header of bitstream in avc for storing data structure
 */
int32_t ParseSliceHeaderSyntaxs ( PWelsDecoderContext pCtx, PBitStringAux pBs, const bool_t kbExtensionFlag )
{
	PNalUnit const kpCurNal				= pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiAvailUnitsNum-1];
	
	PNalUnitHeaderExt pNalHeaderExt	= NULL;
	PSliceHeader pSliceHead			= NULL;
	PSliceHeaderExt pSliceHeadExt	= NULL;
	PSubsetSps pSubsetSps				= NULL;
	PSps pSps							= NULL;
	PPps pPps							= NULL;
	ENalUnitType eNalType				= static_cast<ENalUnitType> (0);
	int32_t iPpsId						= 0;
	int32_t iRet						= ERR_NONE;
	uint8_t uiSliceType				= 0;
	uint8_t uiQualityId					= BASE_QUALITY_ID;
	bool_t	bIdrFlag					= false;
	bool_t	bSgChangeCycleInvolved	= false;	// involved slice group change cycle ?
		
	if (kpCurNal == NULL)
	{	
		return ERR_INFO_OUT_OF_MEMORY;
	}
	
	pNalHeaderExt	= &kpCurNal->sNalHeaderExt;
	pSliceHead		= &kpCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader;
	eNalType		= pNalHeaderExt->sNalUnitHeader.eNalUnitType;
	
	pSliceHeadExt	= &kpCurNal->sNalData.sVclNal.sSliceHeaderExt;

	if ( pSliceHeadExt ){
		SRefBasePicMarking sBaseMarking;
		const bool_t kbStoreRefBaseFlag = pSliceHeadExt->bStoreRefBasePicFlag;
		memcpy(&sBaseMarking, &pSliceHeadExt->sRefBasePicMarking, sizeof(SRefBasePicMarking));//confirmed_safe_unsafe_usage
		memset(pSliceHeadExt, 0, sizeof(SSliceHeaderExt));
		pSliceHeadExt->bStoreRefBasePicFlag	= kbStoreRefBaseFlag;
		memcpy(&pSliceHeadExt->sRefBasePicMarking, &sBaseMarking, sizeof(SRefBasePicMarking));//confirmed_safe_unsafe_usage
	}
	
	kpCurNal->sNalData.sVclNal.bSliceHeaderExtFlag	= kbExtensionFlag;

	pSliceHead->iFirstMbInSlice	= BsGetUe( pBs );

    uiSliceType= BsGetUe( pBs );
    if(uiSliceType > 9)
	{
		WelsLog( pCtx, WELS_LOG_WARNING, "slice type too large (%d) at first_mb(%d)\n", uiSliceType, pSliceHead->iFirstMbInSlice);
		return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE);
    }
    if(uiSliceType > 4)
		uiSliceType -= 5;
	
	if ( kbExtensionFlag ){	
		if (uiSliceType > 2){
			WelsLog( pCtx, WELS_LOG_WARNING, "Invalid slice type(%d).\n", uiSliceType);
			return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE);
		}
	}
	
	pSliceHead->eSliceType	= static_cast <ESliceType> (uiSliceType);

    iPpsId= BsGetUe( pBs );
    
	if(iPpsId >= MAX_PPS_COUNT){
		WelsLog( pCtx, WELS_LOG_WARNING, "iPpsId out of range\n");
        return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_PPS_ID_OVERFLOW);
    }

#ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_ID
	if ( CheckPpsId( pCtx, &pPps, iPpsId ) )
	{
		return dsNoParamSets;
	}
#else
	pPps    = &pCtx->sPpsBuffer[iPpsId];
#endif //MOSAIC_AVOID_BASED_ON_SPS_PPS_ID

	if (pPps->uiNumSliceGroups == 0){
		WelsLog( pCtx, WELS_LOG_WARNING, "non existing PPS referenced\n");
        return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS);
    }

	if (pPps->iSpsId >= MAX_SPS_COUNT){
		WelsLog( pCtx, WELS_LOG_WARNING, "iSpsId out of range\n");
        return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_SPS_ID_OVERFLOW);
	}

	
#ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_ID
	if ( CheckSpsId( pCtx, &pSubsetSps, &pSps, pPps->iSpsId, kExtensionFlag ) )
	{
		return dsNoParamSets;
	}
#else	
	if ( kbExtensionFlag )
	{
		pSubsetSps	= &pCtx->sSubsetSpsBuffer[pPps->iSpsId];
		pSps		= &pSubsetSps->sSps;
	}
	else
	{
		pSps		= &pCtx->sSpsBuffer[pPps->iSpsId];
	}
	pCtx->pSps			= pSps;
#endif //MOSAIC_AVOID_BASED_ON_SPS_PPS_ID
	pSliceHead->iPpsId = iPpsId;
	pSliceHead->iSpsId = pPps->iSpsId; 
	pSliceHead->pPps   = pPps;
	pSliceHead->pSps   = pSps;

	pSliceHeadExt->pSubsetSps = pSubsetSps;
	
	bIdrFlag = (!kbExtensionFlag && eNalType == NAL_UNIT_CODED_SLICE_IDR) || (kbExtensionFlag && pNalHeaderExt->bIdrFlag);

    if(pSps->uiLog2MaxFrameNum == 0){
		WelsLog( pCtx, WELS_LOG_WARNING, "non existing SPS referenced\n");
        return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS);
    }
	pSliceHead->iFrameNum = BsGetBits(pBs, pSps->uiLog2MaxFrameNum);	

	pSliceHead->bFieldPicFlag		= false;
	pSliceHead->bBottomFiledFlag	= false;
	if( !pSps->bFrameMbsOnlyFlag ){
        WelsLog( pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): frame_mbs_only_flag = %d not supported. \n", pSps->bFrameMbsOnlyFlag );
        return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MBAFF);
	}
	pSliceHead->iMbWidth	= pSps->iMbWidth;
	pSliceHead->iMbHeight	= pSps->iMbHeight / (1 + pSliceHead->bFieldPicFlag);
	
	if ( bIdrFlag ){
		if ( pSliceHead->iFrameNum != 0 ){
			WelsLog( pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(), invaild frame number: %d due to IDR frame introduced!\n", pSliceHead->iFrameNum);
			return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FRAME_NUM);
		}
		pSliceHead->uiIdrPicId	= BsGetUe(pBs); /* uiIdrPicId */
#ifdef LONG_TERM_REF
		pCtx->uiCurIdrPicId      = pSliceHead->uiIdrPicId;
#endif
	}
	
	pSliceHead->iDeltaPicOrderCntBottom	= 0;
	pSliceHead->iDeltaPicOrderCnt[0]		=
	pSliceHead->iDeltaPicOrderCnt[1]		= 0;
	if(pSps->uiPocType == 0){
		pSliceHead->iPicOrderCntLsb	= BsGetBits(pBs, pSps->iLog2MaxPocLsb);	
		if( pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag ){
			pSliceHead->iDeltaPicOrderCntBottom	= BsGetSe(pBs);
		}
	}
	else if(pSps->uiPocType == 1 && !pSps->bDeltaPicOrderAlwaysZeroFlag ){
		pSliceHead->iDeltaPicOrderCnt[0]	= BsGetSe(pBs);
		if( pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag )
			pSliceHead->iDeltaPicOrderCnt[1]= BsGetSe(pBs);
	}
	
	pSliceHead->iRedundantPicCnt	= 0;
	if( pPps->bRedundantPicCntPresentFlag ){
		pSliceHead->iRedundantPicCnt = BsGetUe(pBs);
	}

    //set defaults, might be overriden a few line later
	pSliceHead->uiRefCount[0]	= pPps->uiNumRefIdxL0Active;
	pSliceHead->uiRefCount[1]	= pPps->uiNumRefIdxL1Active;
	if ( kbExtensionFlag ){
		uiQualityId = pNalHeaderExt->uiQualityId;
		if ( BASE_QUALITY_ID == uiQualityId && (EP_SLICE == uiSliceType || EB_SLICE == uiSliceType) ){
			const bool_t kbBipredFlag = (EB_SLICE == uiSliceType);
			if ( kbBipredFlag )
            {
                WelsLog ( pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): kbBipredFlag = 1 not supported.\n");
                return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_BIPRED);
            }
			pSliceHead->bNumRefIdxActiveOverrideFlag	= !!BsGetOneBit(pBs);
			if ( pSliceHead->bNumRefIdxActiveOverrideFlag ){
				pSliceHead->uiRefCount[0]	= 1 + BsGetUe(pBs);
			}
		}
	}
	else if(uiSliceType == P_SLICE || uiSliceType == SP_SLICE || uiSliceType == B_SLICE){
		const bool_t kbBipredFlag = (B_SLICE == uiSliceType);
        if( kbBipredFlag ){
            WelsLog ( pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): kbBipredFlag = 1 not supported.\n");
            return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_BIPRED);
        }
		pSliceHead->bNumRefIdxActiveOverrideFlag	= !!BsGetOneBit(pBs);
		if( pSliceHead->bNumRefIdxActiveOverrideFlag ){
			pSliceHead->uiRefCount[0]	= 1 + BsGetUe(pBs);
		}
    }

	if( pSliceHead->uiRefCount[0] > MAX_REF_PIC_COUNT || pSliceHead->uiRefCount[1] > MAX_REF_PIC_COUNT){
		WelsLog( pCtx, WELS_LOG_WARNING, "reference overflow\n");
		return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_REF_COUNT_OVERFLOW);
	}

	if ( BASE_QUALITY_ID == uiQualityId ){
		iRet = ParseRefPicListReordering(pBs, pSliceHead);
		if (iRet != ERR_NONE){
			WelsLog( pCtx, WELS_LOG_WARNING, "invalid ref pPic list reordering syntaxs!\n");
			return iRet;
		}

		if ( kbExtensionFlag ){
			if ( pNalHeaderExt->iNoInterLayerPredFlag || pNalHeaderExt->uiQualityId > 0 )
				pSliceHeadExt->bBasePredWeightTableFlag	= false;
			else
				pSliceHeadExt->bBasePredWeightTableFlag	= true;
		}

		if( kpCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc != 0 ){
			iRet = ParseDecRefPicMarking(pCtx, pBs, pSliceHead, pSps, bIdrFlag );
			if (iRet != ERR_NONE){
				return iRet;
			}

			if ( kbExtensionFlag && !pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag ){
				pSliceHeadExt->bStoreRefBasePicFlag	= !!BsGetOneBit(pBs);
				if ( (pNalHeaderExt->bUseRefBasePicFlag || pSliceHeadExt->bStoreRefBasePicFlag) && !bIdrFlag ){
                    WelsLog( pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): bUseRefBasePicFlag or bStoreRefBasePicFlag = 1 not supported.\n" );
                    return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP);
				}
			}
		}
	}
	
	if ( pPps->bEntropyCodingModeFlag ){
        WelsLog( pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): CABAC in Enhancement layer not supported.\n" );
        return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_CABAC_EL);
	}	
	
	pSliceHead->iSliceQpDelta	= BsGetSe(pBs);
	pSliceHead->iSliceQp		= pPps->iPicInitQp + pSliceHead->iSliceQpDelta;	
    if( pSliceHead->iSliceQp < 0 || pSliceHead->iSliceQp > 51 ){
        WelsLog( pCtx, WELS_LOG_WARNING, "QP %d out of range\n", pSliceHead->iSliceQp);
        return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_QP);
    }
	
    //FIXME qscale / qp ... stuff
	if ( !kbExtensionFlag ){
        if( uiSliceType == SP_SLICE || uiSliceType == SI_SLICE )
        {
            WelsLog( pCtx, WELS_LOG_WARNING, "SP/SI not supported\n");
            return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_SPSI);
        }
	}

	pSliceHead->uiDisableDeblockingFilterIdc	= 0;
	pSliceHead->iSliceAlphaC0Offset			= 0;
	pSliceHead->iSliceBetaOffset				= 0;
	if ( pPps->bDeblockingFilterControlPresentFlag ){
		pSliceHead->uiDisableDeblockingFilterIdc	= BsGetUe(pBs);
		//refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20
		if ( pSliceHead->uiDisableDeblockingFilterIdc > 6 )
		{
			WelsLog( pCtx, WELS_LOG_WARNING, "disable_deblock_filter_idc (%d) out of range [0, 6]\n", pSliceHead->uiDisableDeblockingFilterIdc );
			return ERR_INFO_INVALID_DBLOCKING_IDC;
		}
		if (pSliceHead->uiDisableDeblockingFilterIdc != 1){
			pSliceHead->iSliceAlphaC0Offset	= BsGetSe(pBs) << 1;	// slice_alpha_c0_offset_div2
			pSliceHead->iSliceBetaOffset		= BsGetSe(pBs) << 1;	// iSliceBetaOffset
		}
	}
	
	bSgChangeCycleInvolved	= (pPps->uiNumSliceGroups > 1 && pPps->uiSliceGroupMapType >= 3 && pPps->uiSliceGroupMapType <= 5);
	if ( kbExtensionFlag && bSgChangeCycleInvolved )
		bSgChangeCycleInvolved= (bSgChangeCycleInvolved && (uiQualityId == BASE_QUALITY_ID));
	if ( bSgChangeCycleInvolved ){
		if ( pPps->uiSliceGroupChangeRate > 0 ){
			const int32_t kiNumBits = (int32_t)WELS_CEIL(log(static_cast<double>(1 + pPps->uiPicSizeInMapUnits / pPps->uiSliceGroupChangeRate)));
			pSliceHead->iSliceGroupChangeCycle	= BsGetBits(pBs, kiNumBits);	// For FMO extra types
		}
		else
			pSliceHead->iSliceGroupChangeCycle	= 0;
	}   

	if ( !kbExtensionFlag ){
		FillDefaultSliceHeaderExt ( pSliceHeadExt, pNalHeaderExt );
	}
	else{
		/* Extra syntax elements newly introduced */
		pSliceHeadExt->pSubsetSps	= pSubsetSps;
		
		if ( !pNalHeaderExt->iNoInterLayerPredFlag && BASE_QUALITY_ID == uiQualityId ){
            //the following should be deleted for CODE_CLEAN
			pSliceHeadExt->uiRefLayerDqId	= BsGetUe(pBs);
			if ( pSubsetSps->sSpsSvcExt.bInterLayerDeblockingFilterCtrlPresentFlag )
			{
				pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc	= BsGetUe(pBs);
				//refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20
				if ( pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc > 6 ) 
				{
					WelsLog( pCtx, WELS_LOG_WARNING, "disable_inter_layer_deblock_filter_idc (%d) out of range [0, 6]\n", pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc );
					return ERR_INFO_INVALID_DBLOCKING_IDC;
				}
				if ( pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc != 1 ){
					pSliceHeadExt->iInterLayerSliceAlphaC0Offset	= BsGetSe(pBs) << 1;
					pSliceHeadExt->iInterLayerSliceBetaOffset		= BsGetSe(pBs) << 1;
				}
			}

			pSliceHeadExt->uiRefLayerChromaPhaseXPlus1Flag	= pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseXPlus1Flag;
			pSliceHeadExt->uiRefLayerChromaPhaseYPlus1		= pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseYPlus1;

			pSliceHeadExt->bConstrainedIntraResamplingFlag	= !!BsGetOneBit(pBs);

            {
                SPosOffset pos;
			    pos.iLeftOffset	= pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iLeftOffset;
			    pos.iTopOffset	= pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iTopOffset * (2 - pSps->bFrameMbsOnlyFlag);
			    pos.iRightOffset= pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iRightOffset;
			    pos.iBottomOffset=pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iBottomOffset * (2 - pSps->bFrameMbsOnlyFlag);				
			    //memcpy(&pSliceHeadExt->sScaledRefLayer, &pos, sizeof(SPosOffset));//confirmed_safe_unsafe_usage
			    pSliceHeadExt->iScaledRefLayerPicWidthInSampleLuma	= (pSliceHead->iMbWidth << 4) - (pos.iLeftOffset+pos.iRightOffset);
			    pSliceHeadExt->iScaledRefLayerPicHeightInSampleLuma	= (pSliceHead->iMbHeight << 4) - (pos.iTopOffset+pos.iBottomOffset) / (1 + pSliceHead->bFieldPicFlag);
            }
		}
		else if (uiQualityId > BASE_QUALITY_ID){
            WelsLog( pCtx, WELS_LOG_WARNING, "MGS not supported.\n" );
            return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS);
			pSliceHeadExt->uiRefLayerDqId	= pNalHeaderExt->uiLayerDqId - 1;
		}
		else{
			pSliceHeadExt->uiRefLayerDqId	= (uint8_t)-1;
		}

		pSliceHeadExt->bSliceSkipFlag	= false;
		pSliceHeadExt->bAdaptiveBaseModeFlag	= false;
		pSliceHeadExt->bDefaultBaseModeFlag	= false;
		pSliceHeadExt->bAdaptiveMotionPredFlag	= false;
		pSliceHeadExt->bDefaultMotionPredFlag	= false;
		pSliceHeadExt->bAdaptiveResidualPredFlag	= false;
		pSliceHeadExt->bDefaultResidualPredFlag	= false;
		if ( pNalHeaderExt->iNoInterLayerPredFlag )
			pSliceHeadExt->bTCoeffLevelPredFlag	= false;
		else
			pSliceHeadExt->bTCoeffLevelPredFlag	= pSubsetSps->sSpsSvcExt.bSeqTCoeffLevelPredFlag;

		if ( !pNalHeaderExt->iNoInterLayerPredFlag ){
			pSliceHeadExt->bSliceSkipFlag	= !!BsGetOneBit(pBs);
			if ( pSliceHeadExt->bSliceSkipFlag ){
				pSliceHeadExt->uiNumMbsInSlice	= 1 + BsGetUe(pBs);
			}
			else{
				pSliceHeadExt->bAdaptiveBaseModeFlag	= !!BsGetOneBit(pBs);
				if ( !pSliceHeadExt->bAdaptiveBaseModeFlag ){
					pSliceHeadExt->bDefaultBaseModeFlag	= !!BsGetOneBit(pBs);
				}
				if ( !pSliceHeadExt->bDefaultBaseModeFlag ){
					pSliceHeadExt->bAdaptiveMotionPredFlag	= !!BsGetOneBit(pBs);
					if ( !pSliceHeadExt->bAdaptiveMotionPredFlag )
						pSliceHeadExt->bDefaultMotionPredFlag	= !!BsGetOneBit(pBs);
				}

				pSliceHeadExt->bAdaptiveResidualPredFlag	= !!BsGetOneBit(pBs);
				if ( !pSliceHeadExt->bAdaptiveResidualPredFlag ){
					pSliceHeadExt->bDefaultResidualPredFlag = !!BsGetOneBit(pBs);
				}
			}
			if ( pSubsetSps->sSpsSvcExt.bAdaptiveTCoeffLevelPredFlag )
				pSliceHeadExt->bTCoeffLevelPredFlag	= !!BsGetOneBit(pBs);
		}

		if ( !pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag )
		{
			pSliceHeadExt->uiScanIdxStart	= BsGetBits(pBs, 4);
			pSliceHeadExt->uiScanIdxEnd	= BsGetBits(pBs, 4);
            if( pSliceHeadExt->uiScanIdxStart != 0 || pSliceHeadExt->uiScanIdxEnd != 15 )
            {
                WelsLog( pCtx, WELS_LOG_WARNING, "uiScanIdxStart (%d) != 0 and uiScanIdxEnd (%d) !=15 not supported here\n", pSliceHeadExt->uiScanIdxStart, pSliceHeadExt->uiScanIdxEnd );
                return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS);
            }
		}
		else{
			pSliceHeadExt->uiScanIdxStart	= 0;
			pSliceHeadExt->uiScanIdxEnd	= 15;
		}
	}

	return ERR_NONE;
}

/*
 *	Copy relative syntax elements of NALUnitHeaderExt, sRefPicBaseMarking and bStoreRefBasePicFlag in prefix nal unit.
 *	pSrc:	mark as decoded prefix NAL
 *	ppDst:	succeeded VCL NAL based AVC (I/P Slice)
 */
bool_t PrefetchNalHeaderExtSyntax ( PWelsDecoderContext pCtx, PNalUnit const kppDst, PNalUnit const kpSrc)
{
	PNalUnitHeaderExt pNalHdrExtD	= NULL, pNalHdrExtS = NULL;
	PSliceHeaderExt pShExtD = NULL;
	PPrefixNalUnit pPrefixS = NULL;
	PSps pSps = NULL;
	int32_t iIdx = 0;
	
	if ( kppDst == NULL || kpSrc == NULL )
		return false;	
	
	pNalHdrExtD	= &kppDst->sNalHeaderExt;
	pNalHdrExtS	= &kpSrc->sNalHeaderExt;
	pShExtD		= &kppDst->sNalData.sVclNal.sSliceHeaderExt;
	pPrefixS		= &kpSrc->sNalData.sPrefixNal;
	pSps			= &pCtx->sSpsBuffer[pCtx->sPpsBuffer[pShExtD->sSliceHeader.iPpsId].iSpsId];
	
	pNalHdrExtD->uiDependencyId	    = pNalHdrExtS->uiDependencyId;
	pNalHdrExtD->uiQualityId		= pNalHdrExtS->uiQualityId;
	pNalHdrExtD->uiTemporalId		= pNalHdrExtS->uiTemporalId;
	pNalHdrExtD->uiPriorityId		= pNalHdrExtS->uiPriorityId;
	pNalHdrExtD->bIdrFlag			= pNalHdrExtS->bIdrFlag;
	pNalHdrExtD->iNoInterLayerPredFlag	= pNalHdrExtS->iNoInterLayerPredFlag;
	pNalHdrExtD->bDiscardableFlag			= pNalHdrExtS->bDiscardableFlag;
	pNalHdrExtD->bOutputFlag				= pNalHdrExtS->bOutputFlag;
	pNalHdrExtD->bUseRefBasePicFlag	= pNalHdrExtS->bUseRefBasePicFlag;
	pNalHdrExtD->uiLayerDqId				= pNalHdrExtS->uiLayerDqId;
	
	pShExtD->bStoreRefBasePicFlag		= pPrefixS->bStoreRefBasePicFlag;
	memcpy(&pShExtD->sRefBasePicMarking, &pPrefixS->sRefPicBaseMarking, sizeof(SRefBasePicMarking));//confirmed_safe_unsafe_usage
	if (pShExtD->sRefBasePicMarking.bAdaptiveRefBasePicMarkingModeFlag){
		PRefBasePicMarking pRefBasePicMarking = &pShExtD->sRefBasePicMarking;
		iIdx = 0;
		do {
			if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_END)
				break;
			if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_SHORT2UNUSED)
				pRefBasePicMarking->mmco_base[iIdx].iShortFrameNum = (pShExtD->sSliceHeader.iFrameNum-pRefBasePicMarking->mmco_base[iIdx].uiDiffOfPicNums) & ((1<<pSps->uiLog2MaxFrameNum)-1);
			++ iIdx;
		} while(iIdx < MAX_MMCO_COUNT);
	}
	
	return true;
}



int32_t UpdateAccessUnit ( PWelsDecoderContext pCtx )
{
	PAccessUnit pCurAu	= pCtx->pAccessUnitList;	
	int32_t iIdx         = pCurAu->uiEndPos;
	
	// Conversed iterator
	pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iIdx]->sNalHeaderExt.uiLayerDqId;
	pCurAu->uiActualUnitsNum  = iIdx + 1;
	pCurAu->bCompletedAuFlag = true;	

	// Added for mosaic avoidance, 11/19/2009
#ifdef LONG_TERM_REF
	if ( pCtx->bParamSetsLostFlag )
#else
	if ( pCtx->bReferenceLostAtT0Flag )
#endif 
	{
		uint32_t uiActualIdx = 0;
		while ( uiActualIdx < pCurAu->uiActualUnitsNum ) {
			PNalUnit nal = pCurAu->pNalUnitsList[uiActualIdx];

			if ( nal->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR || nal->sNalHeaderExt.bIdrFlag )
			{
				break;
			}
			++ uiActualIdx;
		}
		if ( uiActualIdx == pCurAu->uiActualUnitsNum )	// no found IDR nal within incoming AU, need exit to avoid mosaic issue, 11/19/2009
		{
			WelsLog( pCtx, WELS_LOG_WARNING, "UpdateAccessUnit():::::Key frame lost.....CAN NOT find IDR from current AU.\n" );
#ifdef LONG_TERM_REF
			pCtx->iErrorCode |= dsNoParamSets;
			return dsNoParamSets;
#else
			pCtx->iErrorCode |= dsRefLost;
			return ERR_INFO_REFERENCE_PIC_LOST;
#endif			
		}
	}		
	
	return ERR_NONE;
}

int32_t InitialDqLayersContext ( PWelsDecoderContext pCtx, const int32_t kiMaxWidth, const int32_t kiMaxHeight )
{
	const int32_t kiPicStride		= ((kiMaxWidth + 15) & 0xfffff0) + (PADDING_LENGTH<<1);
	const int32_t kiPicLines		= ((kiMaxHeight + 15) & 0xfffff0);
		
	int32_t i = 0;

	WELS_VERIFY_RETURN_IF( ERR_INFO_INVALID_PARAM, ( NULL == pCtx || kiMaxWidth <= 0 || kiMaxHeight <= 0 ) )
	pCtx->sMb.iMbWidth		= (kiMaxWidth + 15) >> 4;
	pCtx->sMb.iMbHeight		= (kiMaxHeight + 15) >> 4;

	if ( pCtx->bInitialDqLayersMem && kiMaxWidth <= pCtx->iPicWidthReq && kiMaxHeight <= pCtx->iPicHeightReq )	// have same dimension memory, skipped
		return ERR_NONE;

	
		UninitialDqLayersContext( pCtx );
	
		do {
		PDqLayer pDq = (PDqLayer )WelsMalloc(sizeof(SDqLayer), "PDqLayer");

		int32_t iPlaneIdx = 0;

		if ( pDq == NULL )
			return ERR_INFO_OUT_OF_MEMORY;
		
		memset(pDq, 0, sizeof(SDqLayer));
		if(pCtx->iDecoderMode == SW_MODE)
		{
		
		do {
			const int32_t kiHshift	= iPlaneIdx ? 1 : 0;
			const int32_t kiVshift	= kiHshift;
			const int32_t kiStride	= WELS_ALIGN( (kiPicStride >> kiHshift), (16 << (1-kiHshift)) );
			const int32_t kiLine	= (kiPicLines + (PADDING_LENGTH<<1)) >> kiVshift;
			const int32_t kiSize	= kiStride * kiLine;

			pCtx->pCsListXchg[i][iPlaneIdx]	= (uint8_t *)WelsMalloc( kiSize * sizeof(uint8_t), "pCtx->pCsListXchg[][]" );

			WELS_VERIFY_RETURN_IF( ERR_INFO_OUT_OF_MEMORY, (NULL == pCtx->pCsListXchg[i][iPlaneIdx]) )
			pCtx->iCsStride[iPlaneIdx]	= kiStride;


			pCtx->pRsListXchg[i][iPlaneIdx]	= (int16_t *)WelsMalloc( kiSize * sizeof(int16_t), "pCtx->pRsListXchg[][]" );

			WELS_VERIFY_RETURN_IF( ERR_INFO_OUT_OF_MEMORY , (NULL == pCtx->pRsListXchg[i][iPlaneIdx]) )
			pCtx->iRsStride[iPlaneIdx]	= kiStride;
	
			++ iPlaneIdx;
		} while(iPlaneIdx < 3);


		pCtx->sMb.pMbType[i] = (int8_t *)WelsMalloc( pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight *sizeof(int8_t), "pCtx->sMb.pMbType[]" );
		pCtx->sMb.pMv[i][0] = (int16_t (*)[16][2])WelsMalloc( pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMv[][]"); 
		pCtx->sMb.pRefIndex[i][0] = (int8_t (*)[MB_BLOCK4x4_NUM])WelsMalloc( pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pRefIndex[][]");
		pCtx->sMb.pLumaQp[i] = (int8_t *)WelsMalloc( pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t), "pCtx->sMb.pLumaQp[]");
		pCtx->sMb.pChromaQp[i] = (int8_t *)WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t), "pCtx->sMb.pChromaQp[]");
        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, "pCtx->sMb.pNzcRs[]");
		pCtx->sMb.pScaledTCoeff[i] = (int16_t (*)[MB_COEFF_LIST_SIZE])WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int16_t) * MB_COEFF_LIST_SIZE, "pCtx->sMb.pScaledTCoeff[]"); 
		pCtx->sMb.pIntraPredMode[i] = (int8_t (*)[8])WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t) * 8, "pCtx->sMb.pIntraPredMode[]");
		pCtx->sMb.pIntra4x4FinalMode[i] = (int8_t (*)[MB_BLOCK4x4_NUM])WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pIntra4x4FinalMode[]");	
		pCtx->sMb.pChromaPredMode[i] = (int8_t *)WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t), "pCtx->sMb.pChromaPredMode[]");
		pCtx->sMb.pCbp[i] = (int8_t *)WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight *sizeof(int8_t), "pCtx->sMb.pCbp[]");
		pCtx->sMb.pSubMbType[i] = (int8_t (*)[MB_PARTITION_SIZE])WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t) * MB_PARTITION_SIZE, "pCtx->sMb.pSubMbType[]");
		pCtx->sMb.pSliceIdc[i] = (int32_t *) WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int32_t), "pCtx->sMb.pSliceIdc[]");	// using int32_t for slice_idc, 4/21/2010
		if ( pCtx->sMb.pSliceIdc[i] != NULL )
			memset(pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int32_t)) );
		pCtx->sMb.pResidualPredFlag[i] = (int8_t *) WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t), "pCtx->sMb.pResidualPredFlag[]");
		//pCtx->sMb.pMotionPredFlag[i] = (uint8_t *) WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(uint8_t), "pCtx->sMb.pMotionPredFlag[]");
		pCtx->sMb.pInterPredictionDoneFlag[i] = (int8_t *) WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int8_t), "pCtx->sMb.pInterPredictionDoneFlag[]");

		// check memory block valid due above allocated..
		WELS_VERIFY_RETURN_IF	(	ERR_INFO_OUT_OF_MEMORY,
                   			       ( (NULL == pCtx->sMb.pMbType[i]) ||
								     (NULL == pCtx->sMb.pMv[i][0]) ||
									 (NULL == pCtx->sMb.pRefIndex[i][0]) ||
									 (NULL == pCtx->sMb.pLumaQp[i]) ||
									 (NULL == pCtx->sMb.pChromaQp[i]) ||
									 (NULL == pCtx->sMb.pNzc[i]) ||
									 (NULL == pCtx->sMb.pNzcRs[i]) ||
									 (NULL == pCtx->sMb.pScaledTCoeff[i]) ||
									 (NULL == pCtx->sMb.pIntraPredMode[i]) ||
									 (NULL == pCtx->sMb.pIntra4x4FinalMode[i]) ||
									 (NULL == pCtx->sMb.pChromaPredMode[i]) ||
									 (NULL == pCtx->sMb.pCbp[i]) ||
									 (NULL == pCtx->sMb.pSubMbType[i]) ||
									 (NULL == pCtx->sMb.pSliceIdc[i]) ||
									 (NULL == pCtx->sMb.pResidualPredFlag[i]) ||
									 (NULL == pCtx->sMb.pInterPredictionDoneFlag[i])
									)
								)
		} // end of if(pCtx->iDecoderMode == SW_MODE)
		
		pCtx->pDqLayersList[i] = pDq;
		++ i;
	} while( i < LAYER_NUM_EXCHANGEABLE );
	

	pCtx->bInitialDqLayersMem	= true;
	pCtx->iPicWidthReq			= kiMaxWidth;
	pCtx->iPicHeightReq			= kiMaxHeight;
	
	return ERR_NONE;
}

void_t UninitialDqLayersContext ( PWelsDecoderContext pCtx )
{
	int32_t i = 0;
	int32_t j = 0;
	
	do {
		PDqLayer pDq = pCtx->pDqLayersList[i];		
		if ( pDq == NULL ){
			++ i;
			continue;
		}
		
		if ( pCtx->pCsListXchg[i] ){	// cs picture
			j = 0;
			do {
				if ( NULL != pCtx->pCsListXchg[i][j] )
				{
					WelsFree( pCtx->pCsListXchg[i][j], "pCtx->pCsListXchg[][]" );

					pCtx->pCsListXchg[i][j] = NULL;
				}
				pCtx->iCsStride[j]	= 0;
				++ j;
			} while( j < 3 );			
			
			pDq->pCsData[i]		= NULL;	// for safe
			pDq->iCsStride[i]	= 0;
		}
		if ( pCtx->pRsListXchg[i] ){			
			j = 0;
			do {
				if ( NULL != pCtx->pRsListXchg[i][j] )
				{
					WelsFree( pCtx->pRsListXchg[i][j], "pCtx->pRsListXchg[][]" );

					pCtx->pRsListXchg[i][j]	= NULL;
				}
				pCtx->iRsStride[j]	= 0;
				++ j;
			} while(j < 3);
		}

		if (pCtx->sMb.pMbType[i])
		{	
			WelsFree( pCtx->sMb.pMbType[i], "pCtx->sMb.pMbType[]");

			pCtx->sMb.pMbType[i] = NULL;	
		}
		
		if (pCtx->sMb.pMv[i][0])
		{
			WelsFree( pCtx->sMb.pMv[i][0], "pCtx->sMb.pMv[][]" );

			pCtx->sMb.pMv[i][0] = NULL;
		}

		if (pCtx->sMb.pRefIndex[i][0])
		{
			WelsFree( pCtx->sMb.pRefIndex[i][0], "pCtx->sMb.pRefIndex[][]" );

			pCtx->sMb.pRefIndex[i][0] = NULL;
		}

		if (pCtx->sMb.pLumaQp[i])
		{
			WelsFree(pCtx->sMb.pLumaQp[i], "pCtx->sMb.pLumaQp[]");

			pCtx->sMb.pLumaQp[i] = NULL;
		}

		if (pCtx->sMb.pChromaQp[i])
		{
			WelsFree(pCtx->sMb.pChromaQp[i], "pCtx->sMb.pChromaQp[]");

			pCtx->sMb.pChromaQp[i] = NULL;
		}
		
		if (pCtx->sMb.pNzc[i])
		{
			WelsFree(pCtx->sMb.pNzc[i], "pCtx->sMb.pNzc[]");

			pCtx->sMb.pNzc[i] = NULL;
		}

		if (pCtx->sMb.pNzcRs[i])
		{
			WelsFree(pCtx->sMb.pNzcRs[i], "pCtx->sMb.pNzcRs[]");

			pCtx->sMb.pNzcRs[i] = NULL;
		}		

		if (pCtx->sMb.pScaledTCoeff[i])
		{
			WelsFree(pCtx->sMb.pScaledTCoeff[i], "pCtx->sMb.pScaledTCoeff[]");

			pCtx->sMb.pScaledTCoeff[i] = NULL;
		}

		if (pCtx->sMb.pIntraPredMode[i])
		{
			WelsFree(pCtx->sMb.pIntraPredMode[i], "pCtx->sMb.pIntraPredMode[]");

			pCtx->sMb.pIntraPredMode[i] = NULL;
		}

		if (pCtx->sMb.pIntra4x4FinalMode[i])
		{
			WelsFree(pCtx->sMb.pIntra4x4FinalMode[i], "pCtx->sMb.pIntra4x4FinalMode[]");

			pCtx->sMb.pIntra4x4FinalMode[i] = NULL;
		}			

		if (pCtx->sMb.pChromaPredMode[i])
		{
			WelsFree(pCtx->sMb.pChromaPredMode[i], "pCtx->sMb.pChromaPredMode[]");

			pCtx->sMb.pChromaPredMode[i] = NULL;
		}
	
		if (pCtx->sMb.pCbp[i])
		{
			WelsFree( pCtx->sMb.pCbp[i], "pCtx->sMb.pCbp[]" );

			pCtx->sMb.pCbp[i] = NULL;
		}

  //      if (pCtx->sMb.pMotionPredFlag[i])
		//{
		//	WelsFree( pCtx->sMb.pMotionPredFlag[i], "pCtx->sMb.pMotionPredFlag[]" );

		//	pCtx->sMb.pMotionPredFlag[i] = NULL;
		//}

		if (pCtx->sMb.pSubMbType[i])
		{
			WelsFree(pCtx->sMb.pSubMbType[i], "pCtx->sMb.pSubMbType[]");

			pCtx->sMb.pSubMbType[i] = NULL;
		}

		if (pCtx->sMb.pSliceIdc[i])
		{
			WelsFree( pCtx->sMb.pSliceIdc[i], "pCtx->sMb.pSliceIdc[]" );

			pCtx->sMb.pSliceIdc[i] = NULL;
		}

       if (pCtx->sMb.pResidualPredFlag[i])
		{
			WelsFree( pCtx->sMb.pResidualPredFlag[i], "pCtx->sMb.pResidualPredFlag[]" );

			pCtx->sMb.pResidualPredFlag[i] = NULL;
		}

		if (pCtx->sMb.pInterPredictionDoneFlag[i])
		{
			WelsFree( pCtx->sMb.pInterPredictionDoneFlag[i], "pCtx->sMb.pInterPredictionDoneFlag[]" );

			pCtx->sMb.pInterPredictionDoneFlag[i] = NULL;
		}
		WelsFree( pDq, "pDq" );

		pDq = NULL;
		pCtx->pDqLayersList[i] = NULL;
		
		++ i;
	} while( i < LAYER_NUM_EXCHANGEABLE );
	
	pCtx->iPicWidthReq			= 0;
	pCtx->iPicHeightReq			= 0;
	pCtx->bInitialDqLayersMem	= false;
}

void_t ResetCurrentAccessUnit ( PWelsDecoderContext pCtx )
{
	PAccessUnit pCurAu = pCtx->pAccessUnitList;
	
	pCurAu->uiEndPos		= 0;
	pCurAu->bCompletedAuFlag	= false;
	if (pCurAu->uiActualUnitsNum > 0){
		uint32_t iIdx = 0;
		const uint32_t kuiActualNum = pCurAu->uiActualUnitsNum;		
		// a more simpler method to do nal units list management prefered here		
		const uint32_t kuiAvailNum	= pCurAu->uiAvailUnitsNum;
		const uint32_t kuiLeftNum	= kuiAvailNum - kuiActualNum;		
		
		// Swapping active nal unit nodes of succeeding AU with leading of list
		while (iIdx < kuiLeftNum)
		{
			PNalUnit t = pCurAu->pNalUnitsList[kuiActualNum+iIdx];
			pCurAu->pNalUnitsList[kuiActualNum+iIdx] = pCurAu->pNalUnitsList[iIdx];
			pCurAu->pNalUnitsList[iIdx] = t;
			++ iIdx;
		}
		pCurAu->uiActualUnitsNum = pCurAu->uiAvailUnitsNum	= kuiLeftNum;
	}
}

/*!
 * \brief	Force reset current Acess Unit Nal list in case error parsing/decoding in current AU
 * \author
 * \history	11/16/2009
 */
void_t ForceResetCurrentAccessUnit( PAccessUnit pAu )
{
	uint32_t uiSucAuIdx	= pAu->uiEndPos + 1;
	uint32_t uiCurAuIdx	= 0;

	// swap the succeeding AU's nal units to the front
	while(uiSucAuIdx < pAu->uiAvailUnitsNum)
	{
		PNalUnit t = pAu->pNalUnitsList[uiSucAuIdx];
		pAu->pNalUnitsList[uiSucAuIdx]	= pAu->pNalUnitsList[uiCurAuIdx];
		pAu->pNalUnitsList[uiCurAuIdx]	= t;
		++ uiSucAuIdx;
		++ uiCurAuIdx;
	}

	// Update avail/actual units num accordingly for next AU parsing
	if ( pAu->uiAvailUnitsNum > pAu->uiEndPos )
		pAu->uiAvailUnitsNum	-= (pAu->uiEndPos+1);
	else
		pAu->uiAvailUnitsNum	= 0;
	pAu->uiActualUnitsNum	= 0;
	pAu->uiEndPos		= 0;
	pAu->bCompletedAuFlag	= false;	
}

//clear current corrupted NAL from pNalUnitsList
void_t ForceClearCurrentNal( PAccessUnit pAu )
{	
	if (pAu->uiAvailUnitsNum > 0)
		-- pAu->uiAvailUnitsNum;
}


void_t CheckAvailNalUnitsListContinuity( PWelsDecoderContext pCtx, int32_t iStartIdx, int32_t iEndIdx )
{
	PAccessUnit pCurAu = pCtx->pAccessUnitList;

	uint8_t uiLastNuDependencyId, uiLastNuLayerDqId;
	uint8_t uiCurNuDependencyId, uiCurNuQualityId, uiCurNuLayerDqId, uiCurNuRefLayerDqId;

	int32_t iCurNalUnitIdx = 0;	
	
	//check the continuity of pNalUnitsList forwards (from pIdxNoInterLayerPred to end_postion)	
	uiLastNuDependencyId = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiDependencyId;//starting nal unit
	uiLastNuLayerDqId   = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiLayerDqId;//starting nal unit
	iCurNalUnitIdx = iStartIdx + 1;//current nal unit
	while ( iCurNalUnitIdx <= iEndIdx )
	{
		uiCurNuDependencyId   = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiDependencyId;
		uiCurNuQualityId      = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiQualityId;
		uiCurNuLayerDqId     = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId;
		uiCurNuRefLayerDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalData.sVclNal.sSliceHeaderExt.uiRefLayerDqId;
		
		if ( uiCurNuDependencyId == uiLastNuDependencyId ) 
		{
			uiLastNuLayerDqId = uiCurNuLayerDqId;
			++ iCurNalUnitIdx;
		}
		else //uiCurNuDependencyId != uiLastNuDependencyId, new dependency arrive
		{
			if ( uiCurNuQualityId == 0 ) 
			{
				uiLastNuDependencyId = uiCurNuDependencyId;
				if ( uiCurNuRefLayerDqId == uiLastNuLayerDqId )					
				{
					uiLastNuLayerDqId = uiCurNuLayerDqId;
					++ iCurNalUnitIdx;
				}
				else //cur_nu_layer_id != next_nu_ref_layer_dq_id, the chain is broken at this point
				{
					break;
				}
			}
			else //new dependency arrive, but no base quality layer, so we must stop in this point
			{
				break;
			}
		}
	}
	
	-- iCurNalUnitIdx;
	pCurAu->uiEndPos = iCurNalUnitIdx;
	pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId;	
}

//main purpose: to support multi-slice and to include all slice which have the same uiDependencyId, uiQualityId and frame_num
//for single slice, pIdxNoInterLayerPred SHOULD NOT be modified
void_t RefineIdxNoInterLayerPred( PAccessUnit pCurAu, int32_t* pIdxNoInterLayerPred )
{
	int32_t iLastNalDependId  = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiDependencyId;
	int32_t iLastNalQualityId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiQualityId;
	uint8_t uiLastNalTId       = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiTemporalId;
	int32_t iLastNalFrameNum  = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum;
	int32_t iLastNalPoc        = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb;
	int32_t iLastNalFirstMb   = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice;
	int32_t iCurNalDependId, iCurNalQualityId, iCurNalTId, iCurNalFrameNum, iCurNalPoc, iCurNalFirstMb, iCurIdx, iFinalIdxNoInterLayerPred;

	bool_t  bMultiSliceFind = false;
	
	iFinalIdxNoInterLayerPred = 0;
	iCurIdx = *pIdxNoInterLayerPred - 1;
	while ( iCurIdx >= 0 )
	{
		if ( pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.iNoInterLayerPredFlag )
		{
			iCurNalDependId  = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId;
			iCurNalQualityId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId;
			iCurNalTId       = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId;
			iCurNalFrameNum  = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum;
			iCurNalPoc        = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb;
			iCurNalFirstMb   = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice;
			
			if ( iCurNalDependId == iLastNalDependId  && 
				iCurNalQualityId == iLastNalQualityId && 
				iCurNalTId       == uiLastNalTId       &&
				iCurNalFrameNum  == iLastNalFrameNum  && 
				iCurNalPoc        == iLastNalPoc        &&
				iCurNalFirstMb   != iLastNalFirstMb ) 
			{
				bMultiSliceFind = true;
				iFinalIdxNoInterLayerPred = iCurIdx;
				--iCurIdx;
				continue;
			}
			else
			{
				break;
			}
		}
		--iCurIdx;
	}

	if ( bMultiSliceFind && *pIdxNoInterLayerPred != iFinalIdxNoInterLayerPred )
	{
		*pIdxNoInterLayerPred = iFinalIdxNoInterLayerPred;
	}
}

bool_t CheckPocOfCurValidNalUnits( PAccessUnit pCurAu, int32_t pIdxNoInterLayerPred )
{	 
	int32_t iEndIdx    = pCurAu->uiEndPos;
	int32_t iCurAuPoc = pCurAu->pNalUnitsList[pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb;
	int32_t iTmpPoc, i;
	for ( i = pIdxNoInterLayerPred+1; i < iEndIdx; i++ )
	{
		iTmpPoc = pCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb;
		if ( iTmpPoc != iCurAuPoc )
		{
			return false;
		}
	}

	return true;
}

bool_t CheckIntegrityNalUnitsList( PWelsDecoderContext pCtx )
{
	PAccessUnit pCurAu = pCtx->pAccessUnitList;
	const int32_t kiEndPos = pCurAu->uiEndPos;
	int32_t iIdxNoInterLayerPred = 0;
	int32_t iCurNalUnitIdx = kiEndPos;

	ESliceType eSliceType = static_cast<ESliceType> (0);//EC 2009.11.12
	
	if ( !pCurAu->bCompletedAuFlag )
		return false;

	eSliceType = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.eSliceType;

	if ( I_SLICE == eSliceType )
	{
		pCurAu->uiStartPos = 0;
		//step1: search the pNalUnit whose iNoInterLayerPredFlag equal to 1 backwards (from uiEndPos to 0)
		iIdxNoInterLayerPred = kiEndPos;
		while ( iIdxNoInterLayerPred >= 0 ) 
		{
			if ( pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag ) 
			{
				break;
			}
			--iIdxNoInterLayerPred;
		}
		if ( iIdxNoInterLayerPred < 0 )
		{
			//can not find the Nal Unit whose no_inter_pred_falg equal to 1, MUST STOP decode
			return false;
		}		
		
		//step2: support multi-slice, to include all base layer slice
		RefineIdxNoInterLayerPred( pCurAu, &iIdxNoInterLayerPred );		
		pCurAu->uiStartPos = iIdxNoInterLayerPred;
		CheckAvailNalUnitsListContinuity( pCtx, iIdxNoInterLayerPred, kiEndPos );

		if ( !CheckPocOfCurValidNalUnits( pCurAu, iIdxNoInterLayerPred ) ) 
		{
			return false;
		}
		
		pCtx->iCurSeqIntervalTargetDependId = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalHeaderExt.uiDependencyId;
		pCtx->iCurSeqIntervalMaxPicWidth  = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbWidth << 4;
		pCtx->iCurSeqIntervalMaxPicHeight = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbHeight << 4;
	}
	else //P_SLICE
	{
		//step 1: search uiDependencyId equal to pCtx->cur_seq_interval_target_dependency_id
		bool_t bGetDependId = false;
		int32_t iIdxDependId = 0;

		iIdxDependId = kiEndPos;
		while ( iIdxDependId >= 0 ) 
		{
			if ( pCtx->iCurSeqIntervalTargetDependId == pCurAu->pNalUnitsList[iIdxDependId]->sNalHeaderExt.uiDependencyId )
			{
				bGetDependId = true;
				break;
			}
			else
			{
				--iIdxDependId;
			}
		}
		
		//step 2: switch according to whether or not find the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId
		if ( bGetDependId ) //get the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId
		{
			bool_t bGetNoInterPredFront = false;
			//step 2a: search iNoInterLayerPredFlag [0....iIdxDependId]
			iIdxNoInterLayerPred = iIdxDependId;
			while ( iIdxNoInterLayerPred >= 0 )
			{
				if ( pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag )
				{
					bGetNoInterPredFront = true;
					break;
				}
				--iIdxNoInterLayerPred;
			}
			//step 2b: switch, whether or not find the NAL unit whose no_inter_pred_flag equal to 1 among [0....iIdxDependId] 
			if ( bGetNoInterPredFront ) //YES
			{
				RefineIdxNoInterLayerPred( pCurAu, &iIdxNoInterLayerPred );
				pCurAu->uiStartPos = iIdxNoInterLayerPred;
				CheckAvailNalUnitsListContinuity( pCtx, iIdxNoInterLayerPred, iIdxDependId );
				
				if ( !CheckPocOfCurValidNalUnits( pCurAu, iIdxNoInterLayerPred ) ) 
				{
					return false;
				}
			}
			else //NO, should find the NAL unit whose no_inter_pred_flag equal to 1 among [iIdxDependId....uiEndPos]
			{
				iIdxNoInterLayerPred = iIdxDependId;
				while ( iIdxNoInterLayerPred <= kiEndPos )
				{
					if ( pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag )
					{
						break;
					}					
					++iIdxNoInterLayerPred;
				}

				if ( iIdxNoInterLayerPred > kiEndPos )
				{
					return false; //cann't find the index of pNalUnit whose no_inter_pred_flag = 1
				}

				RefineIdxNoInterLayerPred( pCurAu, &iIdxNoInterLayerPred );			
				pCurAu->uiStartPos = iIdxNoInterLayerPred;
				CheckAvailNalUnitsListContinuity( pCtx, iIdxNoInterLayerPred, kiEndPos );
				
				if ( !CheckPocOfCurValidNalUnits( pCurAu, iIdxNoInterLayerPred ) ) 
				{
					return false;
				}				
			}
		}
		else //without the index of pNalUnit, should process this AU as common case
		{
			iIdxNoInterLayerPred = kiEndPos;
			while (iIdxNoInterLayerPred >= 0)
			{
				if ( pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag ) 
				{
					break;
				}
				--iIdxNoInterLayerPred;
			}
			if (iIdxNoInterLayerPred < 0) 
			{
				return false; //cann't find the index of pNalUnit whose iNoInterLayerPredFlag = 1
			}

			RefineIdxNoInterLayerPred( pCurAu, &iIdxNoInterLayerPred );	
			pCurAu->uiStartPos = iIdxNoInterLayerPred;
			CheckAvailNalUnitsListContinuity( pCtx, iIdxNoInterLayerPred, kiEndPos );

			if ( !CheckPocOfCurValidNalUnits( pCurAu, iIdxNoInterLayerPred ) ) 
			{
				return false;
			}
		}
	}	

	return true;	
}

void_t CheckOnlyOneLayerInAu( PWelsDecoderContext pCtx )
{
	PAccessUnit pCurAu = pCtx->pAccessUnitList;

	int32_t iEndIdx = pCurAu->uiEndPos;	
	int32_t iCurIdx = pCurAu->uiStartPos;
	uint8_t uiDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId;
	uint8_t uiQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId;
	uint8_t uiTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId;

	uint8_t uiCurDId, uiCurQId, uiCurTId;	

	pCtx->bOnlyOneLayerInCurAuFlag = true;

	if ( iEndIdx == iCurIdx ) //only one NAL in pNalUnitsList
	{
		return;
	}

	++iCurIdx;
	while ( iCurIdx <= iEndIdx )
	{
		uiCurDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId;
		uiCurQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId;
		uiCurTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId;

		if ( uiDId != uiCurDId || uiQId != uiCurQId || uiTId != uiCurTId )
		{
			pCtx->bOnlyOneLayerInCurAuFlag = false;
			return;
		}

		++iCurIdx;
	}
}

int32_t WelsDecodeAccessUnitStart ( PWelsDecoderContext pCtx )
{
	// Roll back NAL units not being belong to current access unit list for proceeded access unit
	int32_t iRet = UpdateAccessUnit ( pCtx );
	if ( iRet != ERR_NONE )
		return iRet;

	pCtx->pAccessUnitList->uiStartPos = 0;
	if ( !pCtx->bAvcBasedFlag && !CheckIntegrityNalUnitsList( pCtx ) ) 
	{
		pCtx->iErrorCode |= dsBitstreamError;
		return dsBitstreamError;
	}

	//check current AU has only one layer or not
	//If YES, can use deblocking based on AVC
	if ( !pCtx->bAvcBasedFlag )
	{
		CheckOnlyOneLayerInAu( pCtx );
	}

	return ERR_NONE;
}

void_t WelsDecodeAccessUnitEnd ( PWelsDecoderContext pCtx )
{
	// uninitialize context of current access unit and rbsp buffer clean
	ResetCurrentAccessUnit ( pCtx );	
}


int32_t CheckBSBound(int32_t iWidth, int32_t iHeight, int32_t sliceNum, int32_t ppsId)
{
	int32_t iRet = 0;
	
#if defined(WIN32)	
	iRet = ((iWidth == 80) && (iHeight = 45) && (sliceNum < 60));
	
#elif defined(MACOS)	
	iRet = ((iWidth == 80) && (iHeight = 45) && (ppsId < 57));
	
#elif defined(ANDROID)
	iRet = ((iWidth == 40) && (iHeight = 22));
	
#endif
	
	return iRet;
	
}



/*
 * ConstructAccessUnit
 * construct an access unit for given input bitstream, maybe partial NAL Unit, one or more Units are involved to
 * joint a collective access unit.
 * parameter\
 *	buf:		bitstream data buffer
 *	bit_len:	size in bit length of data
 *	buf_len:	size in byte length of data
 *	coded_au:	mark an Access Unit decoding finished
 * return:
 *	0 - success; otherwise returned error_no defined in error_no.h
 */
int32_t ConstructAccessUnit( PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo *pDstInfo)
{
	int32_t iErr;
	int32_t iWidth;
	int32_t iHeight;
	int32_t iStride[2] = { 0 };

	PAccessUnit pCurAu = pCtx->pAccessUnitList;

	pCtx->bAuReadyFlag = false;
    pCtx->bLastHasMmco5 = false;

	iErr = WelsDecodeAccessUnitStart( pCtx );
	GetVclNalTemporalId( pCtx );
	
	if ( ERR_NONE != iErr )
	{
		ForceResetCurrentAccessUnit( pCtx->pAccessUnitList );
		pDstInfo->iBufferStatus = 0;
		return iErr;
	}
	
	pCtx->pSps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
	pCtx->pPps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pPps;
	
	//try to allocate or relocate DPB memory only when IDR arrival.
	if ( NAL_UNIT_CODED_SLICE_IDR == pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalHeaderExt.sNalUnitHeader.eNalUnitType ||
		pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalHeaderExt.bIdrFlag )
	{
		WelsResetRefPic(pCtx); //clear ref pPic when IDR NAL
		iErr = SyncPictureResolutionExt( pCtx, (pCtx->iMaxWidthInSps+15)>>4, (pCtx->iMaxHeightInSps+15)>>4 );		

		if( ERR_NONE != iErr ){
            WelsLog(pCtx, WELS_LOG_WARNING, "sync picture resolution ext failed,  the error is %d", iErr);
			return iErr;
		}		
	}
	
	
	pDstInfo->eBufferProperty = (EBufferProperty)pCtx->iDecoderOutputProperty;
	
	iErr = DecodeCurrentAccessUnit( pCtx, ppDst, iStride, &iWidth, &iHeight, pDstInfo );
	
	WelsDecodeAccessUnitEnd( pCtx );
	
	if ( ERR_NONE != iErr )
	{
		WelsLog( pCtx, WELS_LOG_INFO, "returned error from decoding:[0x%x]\n", iErr);
		
		pDstInfo->iBufferStatus = 0;
		return iErr;
	}
	
	return 0;
}

static inline void_t InitDqLayerInfo( PDqLayer pDqLayer, PLayerInfo pLayerInfo, PNalUnit pNalUnit, PPicture pPicDec )
{
	PNalUnitHeaderExt pNalHdrExt    = &pNalUnit->sNalHeaderExt;
	PSliceHeaderExt pShExt			= &pNalUnit->sNalData.sVclNal.sSliceHeaderExt;
	PSliceHeader        pSh			= &pShExt->sSliceHeader;
	const uint8_t kuiQualityId		= pNalHdrExt->uiQualityId;
	
	memcpy(&pDqLayer->sLayerInfo, pLayerInfo, sizeof(SLayerInfo));//confirmed_safe_unsafe_usage
	
	pDqLayer->pDec		= pPicDec;
	pDqLayer->iMbWidth	= pSh->iMbWidth;	// MB width of this picture
	pDqLayer->iMbHeight	= pSh->iMbHeight;// MB height of this picture			

	pDqLayer->iSliceIdcBackup = (pSh->iFirstMbInSlice << 7) | (pNalHdrExt->uiDependencyId << 4) | (pNalHdrExt->uiQualityId);
	
	/* Common syntax elements across all slices of a DQLayer */			
	pDqLayer->uiPpsId									= pLayerInfo->pPps->iPpsId;
	pDqLayer->uiDisableInterLayerDeblockingFilterIdc	= pShExt->uiDisableInterLayerDeblockingFilterIdc;
	pDqLayer->iInterLayerSliceAlphaC0Offset			    = pShExt->iInterLayerSliceAlphaC0Offset;
	pDqLayer->iInterLayerSliceBetaOffset				= pShExt->iInterLayerSliceBetaOffset;	
	pDqLayer->iSliceGroupChangeCycle					= pSh->iSliceGroupChangeCycle;
	pDqLayer->bStoreRefBasePicFlag					    = pShExt->bStoreRefBasePicFlag;
	pDqLayer->bTCoeffLevelPredFlag					    = pShExt->bTCoeffLevelPredFlag;
	pDqLayer->bConstrainedIntraResamplingFlag			= pShExt->bConstrainedIntraResamplingFlag;
	pDqLayer->uiRefLayerDqId							= pShExt->uiRefLayerDqId;
	pDqLayer->uiRefLayerChromaPhaseXPlus1Flag		    = pShExt->uiRefLayerChromaPhaseXPlus1Flag;
	pDqLayer->uiRefLayerChromaPhaseYPlus1				= pShExt->uiRefLayerChromaPhaseYPlus1;
	//memcpy(&pDqLayer->sScaledRefLayer, &pShExt->sScaledRefLayer, sizeof(SPosOffset));//confirmed_safe_unsafe_usage
	
	if ( kuiQualityId == BASE_QUALITY_ID ){
		pDqLayer->pRefPicListReordering		= &pSh->pRefPicListReordering;
		pDqLayer->pRefPicMarking		= &pSh->sRefMarking;
		pDqLayer->pRefPicBaseMarking	= &pShExt->sRefBasePicMarking;
	}	
	
	pDqLayer->uiLayerDqId			= pNalHdrExt->uiLayerDqId;	// dq_id of current layer
	pDqLayer->bUseRefBasePicFlag	= pNalHdrExt->bUseRefBasePicFlag;
}

void_t WelsDqLayerDecodeStart ( PWelsDecoderContext pCtx, PNalUnit pCurNal, PSps pSps, PPps pPps )
{		
	SNalUnitHeader *pNalHdr = &pCurNal->sNalHeaderExt.sNalUnitHeader;
	PSliceHeader pSh = &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader;
			
	pCtx->eSliceType			= pSh->eSliceType;	
	pCtx->pSliceHeader			= pSh;

	pCtx->iFrameNum			= pSh->iFrameNum;

	if ((pNalHdr->eNalUnitType == NAL_UNIT_CODED_SLICE_IDR || 
		(pCurNal->sNalHeaderExt.uiQualityId == BASE_QUALITY_ID && pCurNal->sNalHeaderExt.bIdrFlag)) &&
		 pSh->iFrameNum == 0) //pSh->iFrameNum == 0 this condition can deleted??????
	{
		WelsResetRefPic ( pCtx );	// Reset decoded picture buffer lists due to an IDR frame incomes
	}
}

int32_t InitRefPicList ( PWelsDecoderContext pCtx, const uint8_t kuiNRi, const bool_t kbFirstSlice, int32_t iPoc)
{
	int32_t iRet = ERR_NONE;
    if( kbFirstSlice)
        iRet = WelsInitRefList( pCtx, iPoc );
	if ( (pCtx->eSliceType!=I_SLICE && pCtx->eSliceType!=SI_SLICE) && kbFirstSlice ){
		iRet = WelsReorderRefList ( pCtx );
	}
	
	return iRet;
}

void_t InitCurDqLayerData( PWelsDecoderContext pCtx, PDqLayer pCurDq )
{
	if ( NULL != pCtx && NULL != pCurDq )
	{
		pCurDq->pCsData[0]		= pCtx->pCsListXchg[0][0];
		pCurDq->pCsData[1]		= pCtx->pCsListXchg[0][1];
		pCurDq->pCsData[2]		= pCtx->pCsListXchg[0][2];
		pCurDq->iCsStride[0]	= pCtx->iCsStride[0];
		pCurDq->iCsStride[1]	= pCtx->iCsStride[1];
		pCurDq->iCsStride[2]	= pCtx->iCsStride[2];
	
		pCurDq->pMbType			= pCtx->sMb.pMbType[0];
		pCurDq->pSliceIdc		= pCtx->sMb.pSliceIdc[0];
		pCurDq->pMv[0]			= pCtx->sMb.pMv[0][0];
		pCurDq->pRefIndex[0]    = pCtx->sMb.pRefIndex[0][0];
		pCurDq->pLumaQp         = pCtx->sMb.pLumaQp[0];
		pCurDq->pChromaQp       = pCtx->sMb.pChromaQp[0];
		pCurDq->pNzc			= pCtx->sMb.pNzc[0];
		pCurDq->pNzcRs			= pCtx->sMb.pNzcRs[0];
		pCurDq->pScaledTCoeff   = pCtx->sMb.pScaledTCoeff[0];
		pCurDq->pIntraPredMode  = pCtx->sMb.pIntraPredMode[0];
		pCurDq->pIntra4x4FinalMode = pCtx->sMb.pIntra4x4FinalMode[0];
		pCurDq->pChromaPredMode = pCtx->sMb.pChromaPredMode[0];
		pCurDq->pCbp            = pCtx->sMb.pCbp[0];
		pCurDq->pSubMbType      = pCtx->sMb.pSubMbType[0];
		pCurDq->pInterPredictionDoneFlag = pCtx->sMb.pInterPredictionDoneFlag[0];
		pCurDq->pResidualPredFlag = pCtx->sMb.pResidualPredFlag[0];
	}
}

// added to reset state of parameter sets to waiting successive incoming IDR, 6/4/2010
// It will be called in case packets lost/ broken and decoded failed at temporal level 0
void_t ResetParameterSetsState( PWelsDecoderContext pCtx )
{
	pCtx->bSpsExistAheadFlag	   = false;
	pCtx->bSubspsExistAheadFlag = false;
	pCtx->bPpsExistAheadFlag	   = false;
}

/*
 * DecodeCurrentAccessUnit
 * Decode current access unit when current AU is completed.
 */
int32_t DecodeCurrentAccessUnit( PWelsDecoderContext pCtx, uint8_t **ppDst, int32_t *pDstLen, int32_t *pWidth, int32_t *pHeight, SBufferInfo *pDstInfo )
{	
	int32_t iRefCount[LIST_A];	
	PNalUnit pNalCur = NULL;
	PAccessUnit pCurAu = pCtx->pAccessUnitList;

	int32_t iIdx = pCurAu->uiStartPos;
	int32_t iEndIdx = pCurAu->uiEndPos;
	
	int32_t iPpsId = 0;
	int32_t iRet = ERR_NONE;

	const uint8_t kuiTargetLayerDqId = GetTargetDqId(pCtx->uiTargetDqId, pCtx->pParam); 
	const uint8_t kuiDependencyIdMax = (kuiTargetLayerDqId & 0x7F) >> 4;
	int16_t iLastIdD = -1, iLastIdQ = -1;
	int16_t iCurrIdD = 0, iCurrIdQ = 0;
	uint8_t uiNalRefIdc = 0;
	bool_t	bFreshSliceAvailable = true;	// Another fresh slice comingup for given dq layer, for multiple slices in case of header parts of slices sometimes loss over error-prone channels, 8/14/2008
	PPicture  pStoreBasePic = NULL;	

	//update pCurDqLayer at the starting of AU decoding
	if ( pCtx->bInitialDqLayersMem )
	{		
		pCtx->pCurDqLayer				= pCtx->pDqLayersList[0];
	}

	InitCurDqLayerData( pCtx, pCtx->pCurDqLayer );

	pNalCur = pCurAu->pNalUnitsList[iIdx];	
	while ( iIdx <= iEndIdx )
	{
		PDqLayer dq_cur							= pCtx->pCurDqLayer;
		SLayerInfo pLayerInfo;
		PSliceHeaderExt pShExt					= NULL;
		PSliceHeader pSh							= NULL;		
	
		if( pCtx->pDec == NULL ){
			pCtx->pDec = PrefetchPic(pCtx->pPicBuff[0]);

			if( NULL == pCtx->pDec ){
				WelsLog( pCtx, WELS_LOG_ERROR, "DecodeCurrentAccessUnit()::::::PrefetchPic ERROR, pSps->iNumRefFrames:%d.\n", 
					pCtx->pSps->iNumRefFrames );
				pCtx->iErrorCode |= dsOutOfMemory;
				return ERR_INFO_REF_COUNT_OVERFLOW;
			}
		}

#ifdef NO_WAITING_AU
		//For fixing the nal lossing issue
		if ((pCtx->pDec->iTotalNumMbRec != 0)&&
			(CheckAccessUnitBoundaryExt(&pCtx->sLastNalHdrExt, &pNalCur->sNalHeaderExt, &pCtx->sLastSliceHeader,  &pNalCur->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader)))
		{
             pCtx->pDec->iTotalNumMbRec = 0;	
        }
#else
		//initialize at the starting of AU.
		pCtx->pDec->iTotalNumMbRec = 0;			
#endif
        if(pCtx->pDec->iTotalNumMbRec == 0) //Picture start to decode
        {
            for( int32_t i = 0; i < LAYER_NUM_EXCHANGEABLE; ++ i)
                memset(pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(int32_t)) );
        }
		GetI4LumaIChromaAddrTable(pCtx->iDecBlockOffsetArray, pCtx->pDec->iLinesize[0], pCtx->pDec->iLinesize[1]);

		if ( pNalCur->sNalHeaderExt.uiLayerDqId > kuiTargetLayerDqId ) {
			break;	// Per formance it need not to decode the remaining bits any more due to given uiLayerDqId required, 9/2/2009
		}

		memset(&pLayerInfo, 0, sizeof(SLayerInfo));
		
		/*
		 *	Loop decoding for slices (even FMO and/ multiple slices) within a dq layer
		 */
		while ( iIdx <= iEndIdx )
		{	
		    BOOL_T         bReconstructSlice;
			iCurrIdQ	= pNalCur->sNalHeaderExt.uiQualityId;
			iCurrIdD	= pNalCur->sNalHeaderExt.uiDependencyId;
			pSh		= &pNalCur->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader;
			pShExt	= &pNalCur->sNalData.sVclNal.sSliceHeaderExt;

			bReconstructSlice = CheckSliceNeedReconstruct(iCurrIdD, iCurrIdQ, pShExt->bStoreRefBasePicFlag, 
				kuiDependencyIdMax, pNalCur->sNalHeaderExt.uiLayerDqId, kuiTargetLayerDqId);

			memcpy(&pLayerInfo.sNalHeaderExt, &pNalCur->sNalHeaderExt, sizeof(SNalUnitHeaderExt));//confirmed_safe_unsafe_usage

			pCtx->pDec->iFrameNum = pSh->iFrameNum;		

			memcpy(&pLayerInfo.sSliceInLayer.sSliceHeaderExt, pShExt, sizeof(SSliceHeaderExt));//confirmed_safe_unsafe_usage
			pLayerInfo.sSliceInLayer.bSliceHeaderExtFlag	= pNalCur->sNalData.sVclNal.bSliceHeaderExtFlag;
			pLayerInfo.sSliceInLayer.eSliceType			= pSh->eSliceType;
			pLayerInfo.sSliceInLayer.iLastMbQp			= pSh->iSliceQp;
				dq_cur->pBitStringAux	= &pNalCur->sNalData.sVclNal.sSliceBitsRead;
			
			uiNalRefIdc	= pNalCur->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc;	

			iPpsId	= pSh->iPpsId;

			pLayerInfo.pPps = pSh->pPps;
			pLayerInfo.pSps = pSh->pSps;
			pLayerInfo.pSubsetSps = pShExt->pSubsetSps;				

			pCtx->pFmo = &pCtx->sFmoList[iPpsId];
			if ( !FmoParamUpdate( pCtx->pFmo, pLayerInfo.pSps, pLayerInfo.pPps, &pCtx->iActiveFmoNum ) ) {
				pCtx->iErrorCode |= dsBitstreamError;
				WelsLog( pCtx, WELS_LOG_WARNING, "DecodeCurrentAccessUnit(), FmoParamUpdate failed, eSliceType: %d.\n", pSh->eSliceType);
				return GENERATE_ERROR_NO(ERR_LEVEL_SLICE_HEADER, ERR_INFO_FMO_INIT_FAIL);
			}

			bFreshSliceAvailable	= (iCurrIdD != iLastIdD || iCurrIdQ != iLastIdQ);	// do not need condition of (first_mb == 0) due multiple slices might be disorder
			
			WelsDqLayerDecodeStart ( pCtx, pNalCur, pLayerInfo.pSps, pLayerInfo.pPps );

			if ( iCurrIdQ == BASE_QUALITY_ID )
			{
				ST64(iRefCount, LD64(pLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiRefCount));
			}
			
			if ( (iLastIdD < 0) || //case 1: first layer
				( iLastIdD == iCurrIdD) ) //case 2: same uiDId
			{
				InitDqLayerInfo( dq_cur, &pLayerInfo, pNalCur, pCtx->pDec );

				if ( !dq_cur->sLayerInfo.pSps->bGapsInFrameNumValueAllowedFlag )
				{
					const bool_t kbIdrFlag = dq_cur->sLayerInfo.sNalHeaderExt.bIdrFlag || (dq_cur->sLayerInfo.sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR);
					// Subclause 8.2.5.2 Decoding process for gaps in frame_num
					if (	!kbIdrFlag  && 
						pSh->iFrameNum != pCtx->iPrevFrameNum &&
						pSh->iFrameNum != ((pCtx->iPrevFrameNum+1) & ((1<<dq_cur->sLayerInfo.pSps->uiLog2MaxFrameNum)-1))	)
					{
						WelsLog( pCtx, WELS_LOG_WARNING, "referencing pictures lost due frame gaps exist, prev_frame_num: %d, curr_frame_num: %d\n", pCtx->iPrevFrameNum, pSh->iFrameNum);

#ifdef LONG_TERM_REF
						pCtx->bParamSetsLostFlag = true;
#else
						pCtx->bReferenceLostAtT0Flag = true;
#endif
						ResetParameterSetsState( pCtx );				

						pCtx->iErrorCode |= dsRefLost;
						return ERR_INFO_REFERENCE_PIC_LOST;
					}
				}

				if ( iCurrIdD == kuiDependencyIdMax && iCurrIdQ == BASE_QUALITY_ID )
				{
					iRet = InitRefPicList ( pCtx, uiNalRefIdc, bFreshSliceAvailable, pSh->iPicOrderCntLsb);
					if ( iRet )
					{
						HandleReferenceLost(pCtx, pNalCur);
						WelsLog( pCtx, WELS_LOG_WARNING, "reference picture introduced by this frame is lost during transmission! uiTId: %d\n", pNalCur->sNalHeaderExt.uiTemporalId );
						return iRet;
					}
				}

				iRet = WelsDecodeSlice ( pCtx, bFreshSliceAvailable, pNalCur );

				//Output good store_base reconstruction when enhancement quality layer occurred error for MGS key picture case
				if ( iRet != ERR_NONE )
				{
					WelsLog( pCtx, WELS_LOG_WARNING, "DecodeCurrentAccessUnit() failed (%d) in frame: %d uiDId: %d uiQId: %d\n",
						iRet, pSh->iFrameNum, iCurrIdD, iCurrIdQ);
					HandleReferenceLostL0(pCtx, pNalCur);
					return iRet;
				}
				if( bReconstructSlice )	{					
					if( WelsDecodeConstructSlice(pCtx, pNalCur) ){
						return -1;
					}
				}				
			}
#if defined (_DEBUG) &&  !defined (CODEC_FOR_TESTBED)
			fprintf( stderr, "cur_frame : %d	iCurrIdD : %d\n ", 
				dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFrameNum, iCurrIdD );
#endif//#if !CODEC_FOR_TESTBED
			iLastIdD	= iCurrIdD;
			iLastIdQ	= iCurrIdQ;		
	
			//pNalUnitsList overflow.
			++ iIdx;
			if (iIdx <= iEndIdx)
			{				
				pNalCur	= pCurAu->pNalUnitsList[iIdx];
			}
			else
			{
				pNalCur	= NULL;
			}

			if ( pNalCur == NULL ||
				iLastIdD != pNalCur->sNalHeaderExt.uiDependencyId || 
				iLastIdQ != pNalCur->sNalHeaderExt.uiQualityId )
				break;
		} 

		// A dq layer decoded here
#if defined (_DEBUG) &&  !defined (CODEC_FOR_TESTBED)
#undef fprintf
		fprintf(stderr, "POC: #%d, FRAME: #%d, D: %d, Q: %d, T: %d, P: %d,	%d\n",
			pSh->iPicOrderCntLsb, pSh->iFrameNum, iCurrIdD, iCurrIdQ, dq_cur->sLayerInfo.sNalHeaderExt.uiTemporalId, dq_cur->sLayerInfo.sNalHeaderExt.uiPriorityId,dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceQp);
#endif//#if !CODEC_FOR_TESTBED

        if( dq_cur->uiLayerDqId == kuiTargetLayerDqId ){
		    if( DecodeFrameConstruction( pCtx, ppDst, pDstLen, pWidth, pHeight, pDstInfo) ){
#ifdef NO_WAITING_AU
                memcpy(&pCtx->sLastNalHdrExt, &pCurAu->pNalUnitsList[iIdx-1]->sNalHeaderExt, sizeof(SNalUnitHeaderExt));
                memcpy(&pCtx->sLastSliceHeader, &pCurAu->pNalUnitsList[iIdx-1]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader, sizeof(SSliceHeader));
				return ERR_NONE;
#else
				pCtx->iErrorCode |= dsBitstreamError;
				return -1;
#endif
				
		    }
			if( (uiNalRefIdc > 0) && ( iCurrIdQ || (!dq_cur->bStoreRefBasePicFlag) ) ){
				WelsMarkAsRef(pCtx, false);
                ExpandReferencingPicture(pCtx->pDec, pCtx->sExpandPicFunc.pExpandLumaPicture, pCtx->sExpandPicFunc.pExpandChromaPicture);
				pCtx->pDec = NULL;
			}
        }

		if( (iCurrIdD == kuiDependencyIdMax) && (iCurrIdQ == BASE_QUALITY_ID) && (dq_cur->bStoreRefBasePicFlag) ){
			pStoreBasePic = pCtx->pDec;

			if( uiNalRefIdc > 0 ){
				WelsMarkAsRef(pCtx, true);
                ExpandReferencingPicture(pCtx->pDec, pCtx->sExpandPicFunc.pExpandLumaPicture, pCtx->sExpandPicFunc.pExpandChromaPicture);
				pCtx->pDec = NULL;
			}
		}		
		// need update frame_num due current frame is well decoded
		pCtx->iPrevFrameNum	= pSh->iFrameNum;
        if( pCtx->bLastHasMmco5 )   
            pCtx->iPrevFrameNum = 0;
	} 

	return ERR_NONE;
}

} // namespace WelsDec