/*! * \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 svc_encode_slice.c * * \brief svc encoding slice * * \date 2009.07.27 Created * ************************************************************************************* */ #include "ls_defines.h"#include "svc_encode_slice.h"#include "svc_enc_golomb.h"#include "svc_base_layer_md.h"#include "svc_encode_mb.h"#include "svc_set_mb_syn.h"#include "decode_mb_aux.h"#include "svc_mode_decision.h" namespace WelsEnc {//#define ENC_TRACE typedef int32_t (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice);typedef void (*PWelsSliceHeaderWriteFunc) (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta); void UpdateNonZeroCountCache (SMB* pMb, SMbCache* pMbCache) { ST32 (&pMbCache->iNonZeroCoeffCount[9], LD32 (&pMb->pNonZeroCount[ 0])); ST32 (&pMbCache->iNonZeroCoeffCount[17], LD32 (&pMb->pNonZeroCount[ 4])); ST32 (&pMbCache->iNonZeroCoeffCount[25], LD32 (&pMb->pNonZeroCount[ 8])); ST32 (&pMbCache->iNonZeroCoeffCount[33], LD32 (&pMb->pNonZeroCount[12])); ST16 (&pMbCache->iNonZeroCoeffCount[14], LD16 (&pMb->pNonZeroCount[16])); ST16 (&pMbCache->iNonZeroCoeffCount[38], LD16 (&pMb->pNonZeroCount[18])); ST16 (&pMbCache->iNonZeroCoeffCount[22], LD16 (&pMb->pNonZeroCount[20])); ST16 (&pMbCache->iNonZeroCoeffCount[46], LD16 (&pMb->pNonZeroCount[22]));} void WelsSliceHeaderScalExtInit (SDqLayer* pCurLayer, SSlice* pSlice) { SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt; SNalUnitHeaderExt* pNalHeadExt = &pCurLayer->sLayerInfo.sNalHeaderExt; uint8_t uiDependencyId = pNalHeadExt->uiDependencyId; pSliceHeadExt->bSliceSkipFlag = false; if (uiDependencyId > 0) { //spatial EL //bothe adaptive and default flags should equal to 0. pSliceHeadExt->bAdaptiveBaseModeFlag = pSliceHeadExt->bAdaptiveMotionPredFlag = pSliceHeadExt->bAdaptiveResidualPredFlag = false; pSliceHeadExt->bDefaultBaseModeFlag = pSliceHeadExt->bDefaultMotionPredFlag = pSliceHeadExt->bDefaultResidualPredFlag = false; }} void WelsSliceHeaderExtInit (sWelsEncCtx* pEncCtx, SDqLayer* pCurLayer, SSlice* pSlice) { SSliceHeaderExt* pCurSliceExt = &pSlice->sSliceHeaderExt; SSliceHeader* pCurSliceHeader = &pCurSliceExt->sSliceHeader; pCurSliceHeader->eSliceType = pEncCtx->eSliceType; pCurSliceExt->bStoreRefBasePicFlag = false; pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice (pCurLayer->pSliceEncCtx, pSlice->uiSliceIdx); pCurSliceHeader->iFrameNum = pEncCtx->iFrameNum; pCurSliceHeader->uiIdrPicId = pEncCtx->sPSOVector.uiIdrPicId; //?? pCurSliceHeader->iPicOrderCntLsb = pEncCtx->pEncPic->iFramePoc; // 0 if (P_SLICE == pEncCtx->eSliceType) { pCurSliceHeader->uiNumRefIdxL0Active = 1; if (pCurSliceHeader->uiRefCount > 0 && pCurSliceHeader->uiRefCount < pCurLayer->sLayerInfo.pSpsP->iNumRefFrames) { pCurSliceHeader->bNumRefIdxActiveOverrideFlag = true; pCurSliceHeader->uiNumRefIdxL0Active = pCurSliceHeader->uiRefCount; } //to solve mismatch between debug&release else { pCurSliceHeader->bNumRefIdxActiveOverrideFlag = false; } } pCurSliceHeader->iSliceQpDelta = pEncCtx->iGlobalQp - pCurLayer->sLayerInfo.pPpsP->iPicInitQp; //for deblocking initial pCurSliceHeader->uiDisableDeblockingFilterIdc = pCurLayer->iLoopFilterDisableIdc; pCurSliceHeader->iSliceAlphaC0Offset = pCurLayer->iLoopFilterAlphaC0Offset; // need update iSliceAlphaC0Offset & iSliceBetaOffset for pSlice-header if loop_filter_idc != 1 pCurSliceHeader->iSliceBetaOffset = pCurLayer->iLoopFilterBetaOffset; pCurSliceExt->uiDisableInterLayerDeblockingFilterIdc = pCurLayer->uiDisableInterLayerDeblockingFilterIdc; if (pSlice->bSliceHeaderExtFlag) { WelsSliceHeaderScalExtInit (pCurLayer, pSlice); } else { //both adaptive and default flags should equal to 0. pCurSliceExt->bAdaptiveBaseModeFlag = pCurSliceExt->bAdaptiveMotionPredFlag = pCurSliceExt->bAdaptiveResidualPredFlag = false; pCurSliceExt->bDefaultBaseModeFlag = pCurSliceExt->bDefaultMotionPredFlag = pCurSliceExt->bDefaultResidualPredFlag = false; }} /* count MB types if enabled FRAME_INFO_OUTPUT*/#if defined(MB_TYPES_CHECK)void WelsCountMbType (int32_t (*iMbCount)[18], const EWelsSliceType keSt, const SMB* kpMb) { if (NULL == iMbCount) return; switch (kpMb->uiMbType) { case MB_TYPE_INTRA4x4: ++ iMbCount[keSt][Intra4x4]; break; case MB_TYPE_INTRA16x16: ++ iMbCount[keSt][Intra16x16]; break; case MB_TYPE_SKIP: ++ iMbCount[keSt][PSkip]; break; case MB_TYPE_16x16: ++ iMbCount[keSt][Inter16x16]; break; case MB_TYPE_16x8: ++ iMbCount[keSt][Inter16x8]; break; case MB_TYPE_8x16: ++ iMbCount[eSt][Inter8x16]; break; case MB_TYPE_8x8: ++ iMbCount[keSt][Inter8x8]; break; case MB_TYPE_INTRA_BL: ++ iMbCount[keSt][7]; break; default: break; }}#endif//MB_TYPES_CHECK /*!* \brief write reference picture list on reordering syntax in Slice header*/void WriteReferenceReorder (SBitStringAux* pBs, SSliceHeader* sSliceHeader) { SRefPicListReorderSyntax* pRefOrdering = &sSliceHeader->sRefReordering; uint8_t eSliceType = sSliceHeader->eSliceType % 5; int16_t n = 0; if (I_SLICE != eSliceType && SI_SLICE != eSliceType) { // !I && !SI BsWriteOneBit (pBs, true);// { uint16_t uiReorderingOfPicNumsIdc; do { uiReorderingOfPicNumsIdc = pRefOrdering->SReorderingSyntax[n].uiReorderingOfPicNumsIdc; BsWriteUE (pBs, uiReorderingOfPicNumsIdc); if (0 == uiReorderingOfPicNumsIdc || 1 == uiReorderingOfPicNumsIdc) BsWriteUE (pBs, pRefOrdering->SReorderingSyntax[n].uiAbsDiffPicNumMinus1); else if (2 == uiReorderingOfPicNumsIdc) BsWriteUE (pBs, pRefOrdering->SReorderingSyntax[n].iLongTermPicNum); n ++; } while (3 != uiReorderingOfPicNumsIdc);// } }} /*!* \brief write reference picture marking syntax in pSlice header*/void WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUnitHeaderExt* pNalHdrExt) { SRefPicMarking* sRefMarking = &pSliceHeader->sRefMarking; int16_t n = 0; if (pNalHdrExt->bIdrFlag) { BsWriteOneBit (pBs, sRefMarking->bNoOutputOfPriorPicsFlag); BsWriteOneBit (pBs, sRefMarking->bLongTermRefFlag); } else { BsWriteOneBit (pBs, sRefMarking->bAdaptiveRefPicMarkingModeFlag); if (sRefMarking->bAdaptiveRefPicMarkingModeFlag) { int32_t iMmcoType; do { iMmcoType = sRefMarking->SMmcoRef[n].iMmcoType; BsWriteUE (pBs, iMmcoType); if (1 == iMmcoType || 3 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iDiffOfPicNum - 1); if (2 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iLongTermPicNum); if (3 == iMmcoType || 6 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iLongTermFrameIdx); if (4 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iMaxLongTermFrameIdx + 1); n ++; } while (0 != iMmcoType); } }} void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) { SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP; SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP; SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt; BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice); BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */ BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId]); BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum); if (pNalHead->bIdrFlag) { /* NAL IDR */ BsWriteUE (pBs, pSliceHeader->uiIdrPicId); } BsWriteBits (pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb); if (P_SLICE == pSliceHeader->eSliceType) { BsWriteOneBit (pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag); if (pSliceHeader->bNumRefIdxActiveOverrideFlag) { BsWriteUE (pBs, pSliceHeader->uiNumRefIdxL0Active - 1); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalHeader.uiNalRefIdc) { WriteRefPicMarking (pBs, pSliceHeader, pNalHead); } if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) { BsWriteUE (pBs, pSlice->iCabacInitIdc); } BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */ if (pPps->bDeblockingFilterControlPresentFlag) { switch (pSliceHeader->uiDisableDeblockingFilterIdc) { case 0: case 3: case 4: case 6: BsWriteUE (pBs, 0); break; case 1: BsWriteUE (pBs, 1); break; case 2: case 5: BsWriteUE (pBs, 2); break; default: WelsLog(&pCtx->sLogCtx, WELS_LOG_ERROR, "Invalid uiDisableDeblockingFilterIdc %d", pSliceHeader->uiDisableDeblockingFilterIdc); break; } if (1 != pSliceHeader->uiDisableDeblockingFilterIdc) { BsWriteSE (pBs, pSliceHeader->iSliceAlphaC0Offset >> 1); BsWriteSE (pBs, pSliceHeader->iSliceBetaOffset >> 1); } }} void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) { SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP; SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP; SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP; SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt; SSliceHeader* pSliceHeader = &pSliceHeadExt->sSliceHeader; SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt; BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice); BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */ BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId]); BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum); if (pNalHead->bIdrFlag) { /* NAL IDR */ BsWriteUE (pBs, pSliceHeader->uiIdrPicId); } BsWriteBits (pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb);// { if (P_SLICE == pSliceHeader->eSliceType) { BsWriteOneBit (pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag); if (pSliceHeader->bNumRefIdxActiveOverrideFlag) { BsWriteUE (pBs, pSliceHeader->uiNumRefIdxL0Active - 1); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalHeader.uiNalRefIdc) { WriteRefPicMarking (pBs, pSliceHeader, pNalHead); if (!pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { BsWriteOneBit (pBs, pSliceHeadExt->bStoreRefBasePicFlag); } }// } if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) { BsWriteUE (pBs, pSlice->iCabacInitIdc); } BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */ if (pPps->bDeblockingFilterControlPresentFlag) { BsWriteUE (pBs, pSliceHeader->uiDisableDeblockingFilterIdc); if (1 != pSliceHeader->uiDisableDeblockingFilterIdc) { BsWriteSE (pBs, pSliceHeader->iSliceAlphaC0Offset >> 1); BsWriteSE (pBs, pSliceHeader->iSliceBetaOffset >> 1); } } #if !defined(DISABLE_FMO_FEATURE) if (pPps->uiNumSliceGroups > 1 && pPps->uiSliceGroupMapType >= 3 && pPps->uiSliceGroupMapType <= 5) { int32_t iNumBits; if (pPps->uiSliceGroupChangeRate) { iNumBits = WELS_CEILLOG2 (1 + pPps->uiPicSizeInMapUnits / pPps->uiSliceGroupChangeRate); BsWriteBits (pBs, iNumBits, pSliceHeader->iSliceGroupChangeCycle); } }#endif//!DISABLE_FMO_FEATURE if (false) { BsWriteOneBit (pBs, pSliceHeadExt->bSliceSkipFlag); if (pSliceHeadExt->bSliceSkipFlag) { BsWriteUE (pBs, pSliceHeadExt->uiNumMbsInSlice - 1); } else { BsWriteOneBit (pBs, pSliceHeadExt->bAdaptiveBaseModeFlag); if (!pSliceHeadExt->bAdaptiveBaseModeFlag) { BsWriteOneBit (pBs, pSliceHeadExt->bDefaultBaseModeFlag); } if (!pSliceHeadExt->bDefaultBaseModeFlag) { BsWriteOneBit (pBs, 0); BsWriteOneBit (pBs, 0); } BsWriteOneBit (pBs, pSliceHeadExt->bAdaptiveResidualPredFlag); if (!pSliceHeadExt->bAdaptiveResidualPredFlag) { BsWriteOneBit (pBs, 0); } } if (1 == pSubSps->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag) { BsWriteOneBit (pBs, pSliceHeadExt->bTcoeffLevelPredFlag); } } if (!pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { BsWriteBits (pBs, 4, 0); BsWriteBits (pBs, 4, 15); }} //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.//only for inter partvoid WelsInterMbEncode (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) { SMbCache* pMbCache = &pSlice->sMbCacheInfo; WelsDctMb (pMbCache->pCoeffLevel, pMbCache->SPicData.pEncMb[0], pEncCtx->pCurDqLayer->iEncStride[0], pMbCache->pMemPredLuma, pEncCtx->pFuncList->pfDctFourT4); WelsEncInterY (pEncCtx->pFuncList, pCurMb, pMbCache);} //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.//only for I SSlicevoid WelsIMbChromaEncode (sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache* pMbCache) { SWelsFuncPtrList* pFunc = pEncCtx->pFuncList; SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; const int32_t kiEncStride = pCurLayer->iEncStride[1]; const int32_t kiCsStride = pCurLayer->iCsStride[1]; int16_t* pCurRS = pMbCache->pCoeffLevel; uint8_t* pBestPred = pMbCache->pBestPredIntraChroma; uint8_t* pCsCb = pMbCache->SPicData.pCsMb[1]; uint8_t* pCsCr = pMbCache->SPicData.pCsMb[2]; //cb pFunc->pfDctFourT4 (pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS, 1); pFunc->pfIDctFourT4 (pCsCb, kiCsStride, pBestPred, 8, pCurRS); //cr pFunc->pfDctFourT4 (pCurRS + 64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred + 64, 8); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS + 64, 2); pFunc->pfIDctFourT4 (pCsCr, kiCsStride, pBestPred + 64, 8, pCurRS + 64);} //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.//for P SSlice (intra part + inter part)void WelsPMbChromaEncode (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) { SWelsFuncPtrList* pFunc = pEncCtx->pFuncList; SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; const int32_t kiEncStride = pCurLayer->iEncStride[1]; SMbCache* pMbCache = &pSlice->sMbCacheInfo; int16_t* pCurRS = pMbCache->pCoeffLevel + 256; uint8_t* pBestPred = pMbCache->pMemPredChroma; pFunc->pfDctFourT4 (pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8); pFunc->pfDctFourT4 (pCurRS + 64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred + 64, 8); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS, 1); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS + 64, 2);} void OutputPMbWithoutConstructCsRsNoCopy (sWelsEncCtx* pCtx, SDqLayer* pDq, SSlice* pSlice, SMB* pMb) { if (IS_INTER (pMb->uiMbType) || IS_I_BL (pMb->uiMbType)) { //intra have been reconstructed, NO COPY from CS to pDecPic-- SMbCache* pMbCache = &pSlice->sMbCacheInfo; uint8_t* pDecY = pMbCache->SPicData.pDecMb[0]; uint8_t* pDecU = pMbCache->SPicData.pDecMb[1]; uint8_t* pDecV = pMbCache->SPicData.pDecMb[2]; int16_t* pScaledTcoeff = pMbCache->pCoeffLevel; const int32_t kiDecStrideLuma = pDq->pDecPic->iLineSize[0]; const int32_t kiDecStrideChroma = pDq->pDecPic->iLineSize[1]; PIDctFunc pfIdctFour4x4 = pCtx->pFuncList->pfIDctFourT4; WelsIDctT4RecOnMb (pDecY, kiDecStrideLuma, pDecY, kiDecStrideLuma, pScaledTcoeff, pfIdctFour4x4); pfIdctFour4x4 (pDecU, kiDecStrideChroma, pDecU, kiDecStrideChroma, pScaledTcoeff + 256); pfIdctFour4x4 (pDecV, kiDecStrideChroma, pDecV, kiDecStrideChroma, pScaledTcoeff + 320); }} void UpdateQpForOverflow (SMB* pCurMb, uint8_t kuiChromaQpIndexOffset) { pCurMb->uiLumaQp += DELTA_QP; pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];}// for intra non-dynamic pSlice//encapsulate two kinds of reconstruction://first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)//second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer)int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; SSliceCtx* pSliceCtx = pCurLayer->pSliceEncCtx; SMbCache* pMbCache = &pSlice->sMbCacheInfo; SSliceHeaderExt* pSliceHdExt = &pSlice->sSliceHeaderExt; SMB* pMbList = pCurLayer->sMbDataP; SMB* pCurMb = NULL; const int32_t kiSliceFirstMbXY = pSliceHdExt->sSliceHeader.iFirstMbInSlice; int32_t iNextMbIdx = kiSliceFirstMbXY; const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight; int32_t iCurMbIdx = 0, iNumMbCoded = 0; const int32_t kiSliceIdx = pSlice->uiSliceIdx; const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset; SWelsMD sMd; int32_t iEncReturn = ENC_RETURN_SUCCESS; SDynamicSlicingStack sDss; if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) { WelsInitSliceCabac (pEncCtx, pSlice); } for (; ;) {Lines 1–500 of 1144. Load more
/*! * \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 svc_encode_slice.c * * \brief svc encoding slice * * \date 2009.07.27 Created * ************************************************************************************* */ #include "ls_defines.h" #include "svc_encode_slice.h" #include "svc_enc_golomb.h" #include "svc_base_layer_md.h" #include "svc_encode_mb.h" #include "svc_set_mb_syn.h" #include "decode_mb_aux.h" #include "svc_mode_decision.h" namespace WelsEnc { //#define ENC_TRACE typedef int32_t (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice); typedef void (*PWelsSliceHeaderWriteFunc) (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta); void UpdateNonZeroCountCache (SMB* pMb, SMbCache* pMbCache) { ST32 (&pMbCache->iNonZeroCoeffCount[9], LD32 (&pMb->pNonZeroCount[ 0])); ST32 (&pMbCache->iNonZeroCoeffCount[17], LD32 (&pMb->pNonZeroCount[ 4])); ST32 (&pMbCache->iNonZeroCoeffCount[25], LD32 (&pMb->pNonZeroCount[ 8])); ST32 (&pMbCache->iNonZeroCoeffCount[33], LD32 (&pMb->pNonZeroCount[12])); ST16 (&pMbCache->iNonZeroCoeffCount[14], LD16 (&pMb->pNonZeroCount[16])); ST16 (&pMbCache->iNonZeroCoeffCount[38], LD16 (&pMb->pNonZeroCount[18])); ST16 (&pMbCache->iNonZeroCoeffCount[22], LD16 (&pMb->pNonZeroCount[20])); ST16 (&pMbCache->iNonZeroCoeffCount[46], LD16 (&pMb->pNonZeroCount[22])); } void WelsSliceHeaderScalExtInit (SDqLayer* pCurLayer, SSlice* pSlice) { SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt; SNalUnitHeaderExt* pNalHeadExt = &pCurLayer->sLayerInfo.sNalHeaderExt; uint8_t uiDependencyId = pNalHeadExt->uiDependencyId; pSliceHeadExt->bSliceSkipFlag = false; if (uiDependencyId > 0) { //spatial EL //bothe adaptive and default flags should equal to 0. pSliceHeadExt->bAdaptiveBaseModeFlag = pSliceHeadExt->bAdaptiveMotionPredFlag = pSliceHeadExt->bAdaptiveResidualPredFlag = false; pSliceHeadExt->bDefaultBaseModeFlag = pSliceHeadExt->bDefaultMotionPredFlag = pSliceHeadExt->bDefaultResidualPredFlag = false; } } void WelsSliceHeaderExtInit (sWelsEncCtx* pEncCtx, SDqLayer* pCurLayer, SSlice* pSlice) { SSliceHeaderExt* pCurSliceExt = &pSlice->sSliceHeaderExt; SSliceHeader* pCurSliceHeader = &pCurSliceExt->sSliceHeader; pCurSliceHeader->eSliceType = pEncCtx->eSliceType; pCurSliceExt->bStoreRefBasePicFlag = false; pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice (pCurLayer->pSliceEncCtx, pSlice->uiSliceIdx); pCurSliceHeader->iFrameNum = pEncCtx->iFrameNum; pCurSliceHeader->uiIdrPicId = pEncCtx->sPSOVector.uiIdrPicId; //?? pCurSliceHeader->iPicOrderCntLsb = pEncCtx->pEncPic->iFramePoc; // 0 if (P_SLICE == pEncCtx->eSliceType) { pCurSliceHeader->uiNumRefIdxL0Active = 1; if (pCurSliceHeader->uiRefCount > 0 && pCurSliceHeader->uiRefCount < pCurLayer->sLayerInfo.pSpsP->iNumRefFrames) { pCurSliceHeader->bNumRefIdxActiveOverrideFlag = true; pCurSliceHeader->uiNumRefIdxL0Active = pCurSliceHeader->uiRefCount; } //to solve mismatch between debug&release else { pCurSliceHeader->bNumRefIdxActiveOverrideFlag = false; } } pCurSliceHeader->iSliceQpDelta = pEncCtx->iGlobalQp - pCurLayer->sLayerInfo.pPpsP->iPicInitQp; //for deblocking initial pCurSliceHeader->uiDisableDeblockingFilterIdc = pCurLayer->iLoopFilterDisableIdc; pCurSliceHeader->iSliceAlphaC0Offset = pCurLayer->iLoopFilterAlphaC0Offset; // need update iSliceAlphaC0Offset & iSliceBetaOffset for pSlice-header if loop_filter_idc != 1 pCurSliceHeader->iSliceBetaOffset = pCurLayer->iLoopFilterBetaOffset; pCurSliceExt->uiDisableInterLayerDeblockingFilterIdc = pCurLayer->uiDisableInterLayerDeblockingFilterIdc; if (pSlice->bSliceHeaderExtFlag) { WelsSliceHeaderScalExtInit (pCurLayer, pSlice); } else { //both adaptive and default flags should equal to 0. pCurSliceExt->bAdaptiveBaseModeFlag = pCurSliceExt->bAdaptiveMotionPredFlag = pCurSliceExt->bAdaptiveResidualPredFlag = false; pCurSliceExt->bDefaultBaseModeFlag = pCurSliceExt->bDefaultMotionPredFlag = pCurSliceExt->bDefaultResidualPredFlag = false; } } /* count MB types if enabled FRAME_INFO_OUTPUT*/ #if defined(MB_TYPES_CHECK) void WelsCountMbType (int32_t (*iMbCount)[18], const EWelsSliceType keSt, const SMB* kpMb) { if (NULL == iMbCount) return; switch (kpMb->uiMbType) { case MB_TYPE_INTRA4x4: ++ iMbCount[keSt][Intra4x4]; break; case MB_TYPE_INTRA16x16: ++ iMbCount[keSt][Intra16x16]; break; case MB_TYPE_SKIP: ++ iMbCount[keSt][PSkip]; break; case MB_TYPE_16x16: ++ iMbCount[keSt][Inter16x16]; break; case MB_TYPE_16x8: ++ iMbCount[keSt][Inter16x8]; break; case MB_TYPE_8x16: ++ iMbCount[eSt][Inter8x16]; break; case MB_TYPE_8x8: ++ iMbCount[keSt][Inter8x8]; break; case MB_TYPE_INTRA_BL: ++ iMbCount[keSt][7]; break; default: break; } } #endif//MB_TYPES_CHECK /*! * \brief write reference picture list on reordering syntax in Slice header */ void WriteReferenceReorder (SBitStringAux* pBs, SSliceHeader* sSliceHeader) { SRefPicListReorderSyntax* pRefOrdering = &sSliceHeader->sRefReordering; uint8_t eSliceType = sSliceHeader->eSliceType % 5; int16_t n = 0; if (I_SLICE != eSliceType && SI_SLICE != eSliceType) { // !I && !SI BsWriteOneBit (pBs, true); // { uint16_t uiReorderingOfPicNumsIdc; do { uiReorderingOfPicNumsIdc = pRefOrdering->SReorderingSyntax[n].uiReorderingOfPicNumsIdc; BsWriteUE (pBs, uiReorderingOfPicNumsIdc); if (0 == uiReorderingOfPicNumsIdc || 1 == uiReorderingOfPicNumsIdc) BsWriteUE (pBs, pRefOrdering->SReorderingSyntax[n].uiAbsDiffPicNumMinus1); else if (2 == uiReorderingOfPicNumsIdc) BsWriteUE (pBs, pRefOrdering->SReorderingSyntax[n].iLongTermPicNum); n ++; } while (3 != uiReorderingOfPicNumsIdc); // } } } /*! * \brief write reference picture marking syntax in pSlice header */ void WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUnitHeaderExt* pNalHdrExt) { SRefPicMarking* sRefMarking = &pSliceHeader->sRefMarking; int16_t n = 0; if (pNalHdrExt->bIdrFlag) { BsWriteOneBit (pBs, sRefMarking->bNoOutputOfPriorPicsFlag); BsWriteOneBit (pBs, sRefMarking->bLongTermRefFlag); } else { BsWriteOneBit (pBs, sRefMarking->bAdaptiveRefPicMarkingModeFlag); if (sRefMarking->bAdaptiveRefPicMarkingModeFlag) { int32_t iMmcoType; do { iMmcoType = sRefMarking->SMmcoRef[n].iMmcoType; BsWriteUE (pBs, iMmcoType); if (1 == iMmcoType || 3 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iDiffOfPicNum - 1); if (2 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iLongTermPicNum); if (3 == iMmcoType || 6 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iLongTermFrameIdx); if (4 == iMmcoType) BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iMaxLongTermFrameIdx + 1); n ++; } while (0 != iMmcoType); } } } void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) { SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP; SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP; SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt; BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice); BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */ BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId]); BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum); if (pNalHead->bIdrFlag) { /* NAL IDR */ BsWriteUE (pBs, pSliceHeader->uiIdrPicId); } BsWriteBits (pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb); if (P_SLICE == pSliceHeader->eSliceType) { BsWriteOneBit (pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag); if (pSliceHeader->bNumRefIdxActiveOverrideFlag) { BsWriteUE (pBs, pSliceHeader->uiNumRefIdxL0Active - 1); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalHeader.uiNalRefIdc) { WriteRefPicMarking (pBs, pSliceHeader, pNalHead); } if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) { BsWriteUE (pBs, pSlice->iCabacInitIdc); } BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */ if (pPps->bDeblockingFilterControlPresentFlag) { switch (pSliceHeader->uiDisableDeblockingFilterIdc) { case 0: case 3: case 4: case 6: BsWriteUE (pBs, 0); break; case 1: BsWriteUE (pBs, 1); break; case 2: case 5: BsWriteUE (pBs, 2); break; default: WelsLog(&pCtx->sLogCtx, WELS_LOG_ERROR, "Invalid uiDisableDeblockingFilterIdc %d", pSliceHeader->uiDisableDeblockingFilterIdc); break; } if (1 != pSliceHeader->uiDisableDeblockingFilterIdc) { BsWriteSE (pBs, pSliceHeader->iSliceAlphaC0Offset >> 1); BsWriteSE (pBs, pSliceHeader->iSliceBetaOffset >> 1); } } } void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) { SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP; SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP; SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP; SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt; SSliceHeader* pSliceHeader = &pSliceHeadExt->sSliceHeader; SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt; BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice); BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */ BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId]); BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum); if (pNalHead->bIdrFlag) { /* NAL IDR */ BsWriteUE (pBs, pSliceHeader->uiIdrPicId); } BsWriteBits (pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb); // { if (P_SLICE == pSliceHeader->eSliceType) { BsWriteOneBit (pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag); if (pSliceHeader->bNumRefIdxActiveOverrideFlag) { BsWriteUE (pBs, pSliceHeader->uiNumRefIdxL0Active - 1); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalHeader.uiNalRefIdc) { WriteRefPicMarking (pBs, pSliceHeader, pNalHead); if (!pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { BsWriteOneBit (pBs, pSliceHeadExt->bStoreRefBasePicFlag); } } // } if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) { BsWriteUE (pBs, pSlice->iCabacInitIdc); } BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */ if (pPps->bDeblockingFilterControlPresentFlag) { BsWriteUE (pBs, pSliceHeader->uiDisableDeblockingFilterIdc); if (1 != pSliceHeader->uiDisableDeblockingFilterIdc) { BsWriteSE (pBs, pSliceHeader->iSliceAlphaC0Offset >> 1); BsWriteSE (pBs, pSliceHeader->iSliceBetaOffset >> 1); } } #if !defined(DISABLE_FMO_FEATURE) if (pPps->uiNumSliceGroups > 1 && pPps->uiSliceGroupMapType >= 3 && pPps->uiSliceGroupMapType <= 5) { int32_t iNumBits; if (pPps->uiSliceGroupChangeRate) { iNumBits = WELS_CEILLOG2 (1 + pPps->uiPicSizeInMapUnits / pPps->uiSliceGroupChangeRate); BsWriteBits (pBs, iNumBits, pSliceHeader->iSliceGroupChangeCycle); } } #endif//!DISABLE_FMO_FEATURE if (false) { BsWriteOneBit (pBs, pSliceHeadExt->bSliceSkipFlag); if (pSliceHeadExt->bSliceSkipFlag) { BsWriteUE (pBs, pSliceHeadExt->uiNumMbsInSlice - 1); } else { BsWriteOneBit (pBs, pSliceHeadExt->bAdaptiveBaseModeFlag); if (!pSliceHeadExt->bAdaptiveBaseModeFlag) { BsWriteOneBit (pBs, pSliceHeadExt->bDefaultBaseModeFlag); } if (!pSliceHeadExt->bDefaultBaseModeFlag) { BsWriteOneBit (pBs, 0); BsWriteOneBit (pBs, 0); } BsWriteOneBit (pBs, pSliceHeadExt->bAdaptiveResidualPredFlag); if (!pSliceHeadExt->bAdaptiveResidualPredFlag) { BsWriteOneBit (pBs, 0); } } if (1 == pSubSps->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag) { BsWriteOneBit (pBs, pSliceHeadExt->bTcoeffLevelPredFlag); } } if (!pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { BsWriteBits (pBs, 4, 0); BsWriteBits (pBs, 4, 15); } } //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc. //only for inter part void WelsInterMbEncode (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) { SMbCache* pMbCache = &pSlice->sMbCacheInfo; WelsDctMb (pMbCache->pCoeffLevel, pMbCache->SPicData.pEncMb[0], pEncCtx->pCurDqLayer->iEncStride[0], pMbCache->pMemPredLuma, pEncCtx->pFuncList->pfDctFourT4); WelsEncInterY (pEncCtx->pFuncList, pCurMb, pMbCache); } //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc. //only for I SSlice void WelsIMbChromaEncode (sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache* pMbCache) { SWelsFuncPtrList* pFunc = pEncCtx->pFuncList; SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; const int32_t kiEncStride = pCurLayer->iEncStride[1]; const int32_t kiCsStride = pCurLayer->iCsStride[1]; int16_t* pCurRS = pMbCache->pCoeffLevel; uint8_t* pBestPred = pMbCache->pBestPredIntraChroma; uint8_t* pCsCb = pMbCache->SPicData.pCsMb[1]; uint8_t* pCsCr = pMbCache->SPicData.pCsMb[2]; //cb pFunc->pfDctFourT4 (pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS, 1); pFunc->pfIDctFourT4 (pCsCb, kiCsStride, pBestPred, 8, pCurRS); //cr pFunc->pfDctFourT4 (pCurRS + 64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred + 64, 8); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS + 64, 2); pFunc->pfIDctFourT4 (pCsCr, kiCsStride, pBestPred + 64, 8, pCurRS + 64); } //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc. //for P SSlice (intra part + inter part) void WelsPMbChromaEncode (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) { SWelsFuncPtrList* pFunc = pEncCtx->pFuncList; SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; const int32_t kiEncStride = pCurLayer->iEncStride[1]; SMbCache* pMbCache = &pSlice->sMbCacheInfo; int16_t* pCurRS = pMbCache->pCoeffLevel + 256; uint8_t* pBestPred = pMbCache->pMemPredChroma; pFunc->pfDctFourT4 (pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8); pFunc->pfDctFourT4 (pCurRS + 64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred + 64, 8); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS, 1); WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS + 64, 2); } void OutputPMbWithoutConstructCsRsNoCopy (sWelsEncCtx* pCtx, SDqLayer* pDq, SSlice* pSlice, SMB* pMb) { if (IS_INTER (pMb->uiMbType) || IS_I_BL (pMb->uiMbType)) { //intra have been reconstructed, NO COPY from CS to pDecPic-- SMbCache* pMbCache = &pSlice->sMbCacheInfo; uint8_t* pDecY = pMbCache->SPicData.pDecMb[0]; uint8_t* pDecU = pMbCache->SPicData.pDecMb[1]; uint8_t* pDecV = pMbCache->SPicData.pDecMb[2]; int16_t* pScaledTcoeff = pMbCache->pCoeffLevel; const int32_t kiDecStrideLuma = pDq->pDecPic->iLineSize[0]; const int32_t kiDecStrideChroma = pDq->pDecPic->iLineSize[1]; PIDctFunc pfIdctFour4x4 = pCtx->pFuncList->pfIDctFourT4; WelsIDctT4RecOnMb (pDecY, kiDecStrideLuma, pDecY, kiDecStrideLuma, pScaledTcoeff, pfIdctFour4x4); pfIdctFour4x4 (pDecU, kiDecStrideChroma, pDecU, kiDecStrideChroma, pScaledTcoeff + 256); pfIdctFour4x4 (pDecV, kiDecStrideChroma, pDecV, kiDecStrideChroma, pScaledTcoeff + 320); } } void UpdateQpForOverflow (SMB* pCurMb, uint8_t kuiChromaQpIndexOffset) { pCurMb->uiLumaQp += DELTA_QP; pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)]; } // for intra non-dynamic pSlice //encapsulate two kinds of reconstruction: //first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction) //second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer) int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; SSliceCtx* pSliceCtx = pCurLayer->pSliceEncCtx; SMbCache* pMbCache = &pSlice->sMbCacheInfo; SSliceHeaderExt* pSliceHdExt = &pSlice->sSliceHeaderExt; SMB* pMbList = pCurLayer->sMbDataP; SMB* pCurMb = NULL; const int32_t kiSliceFirstMbXY = pSliceHdExt->sSliceHeader.iFirstMbInSlice; int32_t iNextMbIdx = kiSliceFirstMbXY; const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight; int32_t iCurMbIdx = 0, iNumMbCoded = 0; const int32_t kiSliceIdx = pSlice->uiSliceIdx; const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset; SWelsMD sMd; int32_t iEncReturn = ENC_RETURN_SUCCESS; SDynamicSlicingStack sDss; if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) { WelsInitSliceCabac (pEncCtx, pSlice); } for (; ;) {