/*! * \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, IWelsParametersetStrategy* pParametersetStrategy); 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; SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; pCurSliceHeader->eSliceType = pEncCtx->eSliceType; pCurSliceExt->bStoreRefBasePicFlag = false; pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice (pCurLayer->sLayerInfo.pSliceInLayer, pSlice->uiSliceIdx); pCurSliceHeader->iFrameNum = pParamInternal->iFrameNum; pCurSliceHeader->uiIdrPicId = pEncCtx->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; }} void UpdateMbNeighbor (SDqLayer* pCurDq, SMB* pMb, const int32_t kiMbWidth, uint16_t uiSliceIdc) { uint32_t uiNeighborAvailFlag = 0; const int32_t kiMbXY = pMb->iMbXY; const int32_t kiMbX = pMb->iMbX; const int32_t kiMbY = pMb->iMbY; bool bLeft; bool bTop; bool bLeftTop; bool bRightTop; int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; pMb->uiSliceIdc = uiSliceIdc; iLeftXY = kiMbXY - 1; iTopXY = kiMbXY - kiMbWidth; iLeftTopXY = iTopXY - 1; iRightTopXY = iTopXY + 1; bLeft = (kiMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iLeftXY)); bTop = (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iTopXY)); bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iLeftTopXY)); bRightTop = (kiMbX < (kiMbWidth - 1)) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iRightTopXY)); if (bLeft) { uiNeighborAvailFlag |= LEFT_MB_POS; } if (bTop) { uiNeighborAvailFlag |= TOP_MB_POS; } if (bLeftTop) { uiNeighborAvailFlag |= TOPLEFT_MB_POS; } if (bRightTop) { uiNeighborAvailFlag |= TOPRIGHT_MB_POS; } pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag;} /* 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[keSt][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, IWelsParametersetStrategy* pParametersetStrategy) { 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 + pParametersetStrategy->GetPpsIdOffset (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, WELS_CLIP3 (pSliceHeader->uiNumRefIdxL0Active - 1, 0, MAX_REF_PIC_COUNT)); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalUnitHeader.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, IWelsParametersetStrategy* pParametersetStrategy) { 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 + pParametersetStrategy->GetPpsIdOffset (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, WELS_CLIP3 (pSliceHeader->uiNumRefIdxL0Active - 1, 0, MAX_REF_PIC_COUNT)); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalUnitHeader.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_SKIP (pMb->uiMbType)) || IS_I_BL (pMb->uiMbType)) { //intra have been reconstructed, NO COPY from CS to pDecPic-- SMbCache* pMbCache = &pSlice->sMbCacheInfo;Lines 1–500 of 1307. 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, IWelsParametersetStrategy* pParametersetStrategy); 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; SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; pCurSliceHeader->eSliceType = pEncCtx->eSliceType; pCurSliceExt->bStoreRefBasePicFlag = false; pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice (pCurLayer->sLayerInfo.pSliceInLayer, pSlice->uiSliceIdx); pCurSliceHeader->iFrameNum = pParamInternal->iFrameNum; pCurSliceHeader->uiIdrPicId = pEncCtx->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; } } void UpdateMbNeighbor (SDqLayer* pCurDq, SMB* pMb, const int32_t kiMbWidth, uint16_t uiSliceIdc) { uint32_t uiNeighborAvailFlag = 0; const int32_t kiMbXY = pMb->iMbXY; const int32_t kiMbX = pMb->iMbX; const int32_t kiMbY = pMb->iMbY; bool bLeft; bool bTop; bool bLeftTop; bool bRightTop; int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; pMb->uiSliceIdc = uiSliceIdc; iLeftXY = kiMbXY - 1; iTopXY = kiMbXY - kiMbWidth; iLeftTopXY = iTopXY - 1; iRightTopXY = iTopXY + 1; bLeft = (kiMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iLeftXY)); bTop = (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iTopXY)); bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iLeftTopXY)); bRightTop = (kiMbX < (kiMbWidth - 1)) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iRightTopXY)); if (bLeft) { uiNeighborAvailFlag |= LEFT_MB_POS; } if (bTop) { uiNeighborAvailFlag |= TOP_MB_POS; } if (bLeftTop) { uiNeighborAvailFlag |= TOPLEFT_MB_POS; } if (bRightTop) { uiNeighborAvailFlag |= TOPRIGHT_MB_POS; } pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag; } /* 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[keSt][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, IWelsParametersetStrategy* pParametersetStrategy) { 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 + pParametersetStrategy->GetPpsIdOffset (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, WELS_CLIP3 (pSliceHeader->uiNumRefIdxL0Active - 1, 0, MAX_REF_PIC_COUNT)); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalUnitHeader.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, IWelsParametersetStrategy* pParametersetStrategy) { 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 + pParametersetStrategy->GetPpsIdOffset (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, WELS_CLIP3 (pSliceHeader->uiNumRefIdxL0Active - 1, 0, MAX_REF_PIC_COUNT)); } } if (!pNalHead->bIdrFlag) WriteReferenceReorder (pBs, pSliceHeader); if (pNalHead->sNalUnitHeader.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_SKIP (pMb->uiMbType)) || IS_I_BL (pMb->uiMbType)) { //intra have been reconstructed, NO COPY from CS to pDecPic-- SMbCache* pMbCache = &pSlice->sMbCacheInfo;