/*! * \copy * Copyright (c) 2008-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. * * * Abstract * current slice decoding * * History * 07/10/2008 Created * 08/09/2013 Modified * *****************************************************************************/ #include "deblocking.h" #include "decode_slice.h" #include "parse_mb_syn_cavlc.h"#include "rec_mb.h"#include "mv_pred.h" #include "cpu_core.h" namespace WelsDec { int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx) { int32_t iPreQP = 0; PDqLayer pCurLayer = pCtx->pCurDqLayer; PSlice pCurSlice = &pCurLayer->sLayerInfo.sSliceInLayer; PSliceHeader pSliceHeader = &pCurSlice->sSliceHeaderExt.sSliceHeader; int32_t iTotalMbTargetLayer = pSliceHeader->pSps->uiTotalMbCount; int32_t iCurLayerWidth = pCurLayer->iMbWidth << 4; int32_t iCurLayerHeight = pCurLayer->iMbHeight << 4; int32_t iNextMbXyIndex = 0; PFmo pFmo = pCtx->pFmo; int32_t iTotalNumMb = pCurSlice->iTotalMbInCurSlice; int32_t iCountNumMb = 0; PDeblockingFilterMbFunc pDeblockMb; if (!pCtx->bAvcBasedFlag && iCurLayerWidth != pCtx->iCurSeqIntervalMaxPicWidth) { return -1; } iNextMbXyIndex = pSliceHeader->iFirstMbInSlice; pCurLayer->iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; pCurLayer->iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; pCurLayer->iMbXyIndex = iNextMbXyIndex; if (0 == iNextMbXyIndex) { pCurLayer->pDec->iSpsId = pSliceHeader->iSpsId; pCurLayer->pDec->iPpsId = pSliceHeader->iPpsId; pCurLayer->pDec->uiQualityId = pCurLayer->sLayerInfo.sNalHeaderExt.uiQualityId; } do { iPreQP = pCurLayer->pLumaQp[pCurLayer->iMbXyIndex]; if (WelsTargetMbConstruction (pCtx)) { WelsLog (pCtx, WELS_LOG_WARNING, "WelsTargetSliceConstruction():::MB(%d, %d) construction error. pCurSlice_type:%d\n", pCurLayer->iMbX, pCurLayer->iMbY, pCurSlice->eSliceType); return -1; } ++iCountNumMb; ++pCurLayer->pDec->iTotalNumMbRec; if (iCountNumMb >= iTotalNumMb) { break; } if (pCurLayer->pDec->iTotalNumMbRec > iTotalMbTargetLayer) { WelsLog (pCtx, WELS_LOG_WARNING, "WelsTargetSliceConstruction():::fdec->iTotalNumMbRec:%d, iTotalMbTargetLayer:%d\n", pCurLayer->pDec->iTotalNumMbRec, iTotalMbTargetLayer); return -1; } if (pSliceHeader->pPps->uiNumSliceGroups > 1) { iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex); } else { ++iNextMbXyIndex; } if (-1 == iNextMbXyIndex || iNextMbXyIndex >= iTotalMbTargetLayer) { // slice group boundary or end of a frame break; } pCurLayer->iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; pCurLayer->iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; pCurLayer->iMbXyIndex = iNextMbXyIndex; } while (1); pCtx->pDec->iWidthInPixel = iCurLayerWidth; pCtx->pDec->iHeightInPixel = iCurLayerHeight; if ((pCurSlice->eSliceType != I_SLICE) && (pCurSlice->eSliceType != P_SLICE)) return 0; pDeblockMb = WelsDeblockingMb; if (1 == pSliceHeader->uiDisableDeblockingFilterIdc) { return 0;//NO_SUPPORTED_FILTER_IDX } else { WelsDeblockingFilterSlice (pCtx, pDeblockMb); } // any other filter_idc not supported here, 7/22/2010 return 0;} int32_t WelsMbInterSampleConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, uint8_t* pDstY, uint8_t* pDstU, uint8_t* pDstV, int32_t iStrideL, int32_t iStrideC) { int32_t iMbXy = pCurLayer->iMbXyIndex; int32_t i, iIndex, iOffset; WelsChromaDcIdct (pCurLayer->pScaledTCoeff[iMbXy] + 256); // 256 = 16*16 WelsChromaDcIdct (pCurLayer->pScaledTCoeff[iMbXy] + 320); // 320 = 16*16 + 16*4 for (i = 0; i < 16; i++) { //luma iIndex = g_kuiMbNonZeroCountIdx[i]; if (pCurLayer->pNzc[iMbXy][iIndex]) { iOffset = ((iIndex >> 2) << 2) * iStrideL + ((iIndex % 4) << 2); pCtx->pIdctResAddPredFunc (pDstY + iOffset, iStrideL, pCurLayer->pScaledTCoeff[iMbXy] + (i << 4)); } } for (i = 0; i < 4; i++) { //chroma iIndex = g_kuiMbNonZeroCountIdx[i + 16]; //Cb if (pCurLayer->pNzc[iMbXy][iIndex] || * (pCurLayer->pScaledTCoeff[iMbXy] + ((i + 16) << 4))) { iOffset = (((iIndex - 16) >> 2) << 2) * iStrideC + (((iIndex - 16) % 4) << 2); pCtx->pIdctResAddPredFunc (pDstU + iOffset, iStrideC, pCurLayer->pScaledTCoeff[iMbXy] + ((i + 16) << 4)); } iIndex = g_kuiMbNonZeroCountIdx[i + 20]; //Cr if (pCurLayer->pNzc[iMbXy][iIndex] || * (pCurLayer->pScaledTCoeff[iMbXy] + ((i + 20) << 4))) { iOffset = (((iIndex - 18) >> 2) << 2) * iStrideC + (((iIndex - 18) % 4) << 2); pCtx->pIdctResAddPredFunc (pDstV + iOffset, iStrideC , pCurLayer->pScaledTCoeff[iMbXy] + ((i + 20) << 4)); } } return 0;}int32_t WelsMbInterConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer) { int32_t iMbX = pCurLayer->iMbX; int32_t iMbY = pCurLayer->iMbY; uint8_t* pDstY, *pDstCb, *pDstCr; int32_t iLumaStride = pCtx->pDec->iLinesize[0]; int32_t iChromaStride = pCtx->pDec->iLinesize[1]; pDstY = pCurLayer->pDec->pData[0] + ((iMbY * iLumaStride + iMbX) << 4); pDstCb = pCurLayer->pDec->pData[1] + ((iMbY * iChromaStride + iMbX) << 3); pDstCr = pCurLayer->pDec->pData[2] + ((iMbY * iChromaStride + iMbX) << 3); GetInterPred (pDstY, pDstCb, pDstCr, pCtx); WelsMbInterSampleConstruction (pCtx, pCurLayer, pDstY, pDstCb, pDstCr, iLumaStride, iChromaStride); pCtx->sBlockFunc.pWelsSetNonZeroCountFunc (NULL, pCurLayer->pNzc[pCurLayer->iMbXyIndex]); // set all none-zero nzc to 1; dbk can be opti! return 0;} void WelsLumaDcDequantIdct (int16_t* pBlock, int32_t iQp) { const int32_t kiQMul = g_kuiDequantCoeff[iQp][0];#define STRIDE 16 int32_t i; int32_t iTemp[16]; //FIXME check if this is a good idea int16_t* pBlk = pBlock; static const int32_t kiXOffset[4] = {0, STRIDE, STRIDE << 2, 5 * STRIDE}; static const int32_t kiYOffset[4] = {0, STRIDE << 1, STRIDE << 3, 10 * STRIDE}; for (i = 0; i < 4; i++) { const int32_t kiOffset = kiYOffset[i]; const int32_t kiX1 = kiOffset + kiXOffset[2]; const int32_t kiX2 = STRIDE + kiOffset; const int32_t kiX3 = kiOffset + kiXOffset[3]; const int32_t kiI4 = i << 2; // 4*i const int32_t kiZ0 = pBlk[kiOffset] + pBlk[kiX1]; const int32_t kiZ1 = pBlk[kiOffset] - pBlk[kiX1]; const int32_t kiZ2 = pBlk[kiX2] - pBlk[kiX3]; const int32_t kiZ3 = pBlk[kiX2] + pBlk[kiX3]; iTemp[kiI4] = kiZ0 + kiZ3; iTemp[1 + kiI4] = kiZ1 + kiZ2; iTemp[2 + kiI4] = kiZ1 - kiZ2; iTemp[3 + kiI4] = kiZ0 - kiZ3; } for (i = 0; i < 4; i++) { const int32_t kiOffset = kiXOffset[i]; const int32_t kiI4 = 4 + i; const int32_t kiZ0 = iTemp[i] + iTemp[4 + kiI4]; const int32_t kiZ1 = iTemp[i] - iTemp[4 + kiI4]; const int32_t kiZ2 = iTemp[kiI4] - iTemp[8 + kiI4]; const int32_t kiZ3 = iTemp[kiI4] + iTemp[8 + kiI4]; pBlk[kiOffset] = ((kiZ0 + kiZ3) * kiQMul + 2) >> 2; //FIXME think about merging this into decode_resdual pBlk[kiYOffset[1] + kiOffset] = ((kiZ1 + kiZ2) * kiQMul + 2) >> 2; pBlk[kiYOffset[2] + kiOffset] = ((kiZ1 - kiZ2) * kiQMul + 2) >> 2; pBlk[kiYOffset[3] + kiOffset] = ((kiZ0 - kiZ3) * kiQMul + 2) >> 2; }#undef STRIDE} int32_t WelsMbIntraPredictionConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, bool bOutput) {//seems IPCM should not enter this path int32_t iMbXy = pCurLayer->iMbXyIndex; WelsFillRecNeededMbInfo (pCtx, bOutput, pCurLayer); if (IS_INTRA16x16 (pCurLayer->pMbType[iMbXy])) { WelsLumaDcDequantIdct (pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy]); RecI16x16Mb (iMbXy, pCtx, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer); return 0; } if (IS_INTRA4x4 (pCurLayer->pMbType[iMbXy])) RecI4x4Mb (iMbXy, pCtx, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer); return 0;} int32_t WelsMbInterPrediction (PWelsDecoderContext pCtx, PDqLayer pCurLayer) { int32_t iMbX = pCurLayer->iMbX; int32_t iMbY = pCurLayer->iMbY; uint8_t* pDstY, *pDstCb, *pDstCr; int32_t iLumaStride = pCtx->pDec->iLinesize[0]; int32_t iChromaStride = pCtx->pDec->iLinesize[1]; pDstY = pCurLayer->pDec->pData[0] + ((iMbY * iLumaStride + iMbX) << 4); pDstCb = pCurLayer->pDec->pData[1] + ((iMbY * iChromaStride + iMbX) << 3); pDstCr = pCurLayer->pDec->pData[2] + ((iMbY * iChromaStride + iMbX) << 3); GetInterPred (pDstY, pDstCb, pDstCr, pCtx); return 0;} void WelsMbCopy (uint8_t* pDst, int32_t iStrideDst, uint8_t* pSrc, int32_t iStrideSrc, int32_t iHeight, int32_t iWidth) { int32_t i; int32_t iOffsetDst = 0, iOffsetSrc = 0; for (i = 0; i < iHeight; i++) { memcpy (pDst + iOffsetDst, pSrc + iOffsetSrc, iWidth); iOffsetDst += iStrideDst; iOffsetSrc += iStrideSrc; }} int32_t WelsTargetMbConstruction (PWelsDecoderContext pCtx) { PDqLayer pCurLayer = pCtx->pCurDqLayer; if (MB_TYPE_INTRA_PCM == pCurLayer->pMbType[pCurLayer->iMbXyIndex]) { //copy cs into fdec int32_t iCsStrideL = pCurLayer->iCsStride[0]; int32_t iCsStrideC = pCurLayer->iCsStride[1]; int32_t iDecStrideL = pCurLayer->pDec->iLinesize[0]; int32_t iDecStrideC = pCurLayer->pDec->iLinesize[1]; int32_t iCsOffsetL = (pCurLayer->iMbX + pCurLayer->iMbY * iCsStrideL) << 4; int32_t iCsOffsetC = (pCurLayer->iMbX + pCurLayer->iMbY * iCsStrideC) << 3; int32_t iDecOffsetL = (pCurLayer->iMbX + pCurLayer->iMbY * iDecStrideL) << 4; int32_t iDecOffsetC = (pCurLayer->iMbX + pCurLayer->iMbY * iDecStrideC) << 3; uint8_t* pSrcY = pCurLayer->pCsData[0] + iCsOffsetL; uint8_t* pSrcU = pCurLayer->pCsData[1] + iCsOffsetC; uint8_t* pSrcV = pCurLayer->pCsData[2] + iCsOffsetC; uint8_t* pDecY = pCurLayer->pDec->pData[0] + iDecOffsetL; uint8_t* pDecU = pCurLayer->pDec->pData[1] + iDecOffsetC; uint8_t* pDecV = pCurLayer->pDec->pData[2] + iDecOffsetC; WelsMbCopy (pDecY, iDecStrideL, pSrcY, iCsStrideL, 16, 16); WelsMbCopy (pDecU, iDecStrideC, pSrcU, iCsStrideC, 8, 8); WelsMbCopy (pDecV, iDecStrideC, pSrcV, iCsStrideC, 8, 8); return 0; } else if (IS_INTRA (pCurLayer->pMbType[pCurLayer->iMbXyIndex])) { WelsMbIntraPredictionConstruction (pCtx, pCurLayer, 1); } else if (IS_INTER (pCurLayer->pMbType[pCurLayer->iMbXyIndex])) { //InterMB if (0 == pCurLayer->pCbp[pCurLayer->iMbXyIndex]) { //uiCbp==0 include SKIP WelsMbInterPrediction (pCtx, pCurLayer); } else { WelsMbInterConstruction (pCtx, pCurLayer); } } else { WelsLog (pCtx, WELS_LOG_WARNING, "WelsTargetMbConstruction():::::Unknown MB type: %d\n", pCurLayer->pMbType[pCurLayer->iMbXyIndex]); return -1; } return 0;} void WelsChromaDcIdct (int16_t* pBlock) { int32_t iStride = 32; int32_t iXStride = 16; int32_t iStride1 = iXStride + iStride; int16_t* pBlk = pBlock; int32_t iA, iB, iC, iD, iE; iA = pBlk[0]; iB = pBlk[iXStride]; iC = pBlk[iStride]; iD = pBlk[iStride1]; iE = iA - iB; iA += iB; iB = iC - iD; iC += iD; pBlk[0] = (iA + iC) >> 1; pBlk[iXStride] = (iE + iB) >> 1; pBlk[iStride] = (iA - iC) >> 1; pBlk[iStride1] = (iE - iB) >> 1;} int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur) { PDqLayer pCurLayer = pCtx->pCurDqLayer; PFmo pFmo = pCtx->pFmo; int32_t i, iRet; int32_t iNextMbXyIndex, iSliceIdc; PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer; PSliceHeaderExt pSliceHeaderExt = &pSlice->sSliceHeaderExt; PSliceHeader pSliceHeader = &pSliceHeaderExt->sSliceHeader; int32_t iMbX, iMbY; const int32_t kiCountNumMb = pSliceHeader->pSps->uiTotalMbCount; //need to be correct when fmo or multi slice PBitStringAux pBs = pCurLayer->pBitStringAux; int32_t iUsedBits = 0; PWelsDecMbCavlcFunc pDecMbCavlcFunc; pSlice->iTotalMbInCurSlice = 0; //initialize at the starting of slice decoding. if (P_SLICE == pSliceHeader->eSliceType) { pDecMbCavlcFunc = WelsDecodeMbCavlcPSlice; } else { //I_SLICE pDecMbCavlcFunc = WelsDecodeMbCavlcISlice; } if (pSliceHeader->pPps->bConstainedIntraPredFlag) { pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain1Intra4x4; pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain1; pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain1; } else { pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain0Intra4x4; pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain0; pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain0; } pCtx->eSliceType = pSliceHeader->eSliceType; if (pCurLayer->sLayerInfo.pPps->bEntropyCodingModeFlag == 1) { //CABAC encoding is unsupported yet! return -1; } iNextMbXyIndex = pSliceHeader->iFirstMbInSlice; if ((iNextMbXyIndex < 0) || (iNextMbXyIndex >= kiCountNumMb)) { WelsLog (pCtx, WELS_LOG_ERROR, "WelsDecodeSlice()::iFirstMbInSlice(%d) > pSps->kiTotalMb(%d). ERROR!!! resolution change....\n", iNextMbXyIndex, kiCountNumMb); pCtx->iErrorCode |= dsNoParamSets; return dsNoParamSets; } iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; // error is introduced by multiple slices case, 11/23/2009 pSlice->iMbSkipRun = -1; iSliceIdc = (pSliceHeader->iFirstMbInSlice << 7) + pCurLayer->uiLayerDqId; pCurLayer->iMbX = iMbX; pCurLayer->iMbY = iMbY; pCurLayer->iMbXyIndex = iNextMbXyIndex; if (pSliceHeaderExt->bSliceSkipFlag == 1) { for (i = 0; i < (int32_t)pSliceHeaderExt->uiNumMbsInSlice; i++) { pCurLayer->pSliceIdc[iNextMbXyIndex] = iSliceIdc; pCurLayer->pResidualPredFlag[iNextMbXyIndex] = 1; if (pSliceHeaderExt->sSliceHeader.pPps->uiNumSliceGroups > 1) { iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex); } else { ++iNextMbXyIndex; } iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; iMbY = iNextMbXyIndex % pCurLayer->iMbHeight; pCurLayer->iMbX = iMbX; pCurLayer->iMbY = iMbY; pCurLayer->iMbXyIndex = iNextMbXyIndex; } return 0; } do { pCurLayer->pSliceIdc[iNextMbXyIndex] = iSliceIdc; iRet = pDecMbCavlcFunc (pCtx, pNalCur); if (iRet != ERR_NONE) { return iRet; } ++pSlice->iTotalMbInCurSlice; if (pSliceHeader->pPps->uiNumSliceGroups > 1) { iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex); } else { ++iNextMbXyIndex; } if ((-1 == iNextMbXyIndex) || (iNextMbXyIndex >= kiCountNumMb)) { // slice group boundary or end of a frame break; } // check whether there is left bits to read next time in case multiple slices iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits); if (iUsedBits == pBs->iBits && 0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun) { // slice boundary break; } if (iUsedBits > pBs->iBits) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash. WelsLog (pCtx, WELS_LOG_WARNING, "WelsDecodeSlice()::::pBs incomplete, iUsedBits:%d > pBs->iBits:%d, MUST stop decoding.\n", iUsedBits, pBs->iBits); return -1; } iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; pCurLayer->iMbX = iMbX; pCurLayer->iMbY = iMbY; pCurLayer->iMbXyIndex = iNextMbXyIndex; } while (1); return ERR_NONE;} int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) { SVlcTable* pVlcTable = &pCtx->sVlcTable; PDqLayer pCurLayer = pCtx->pCurDqLayer; PBitStringAux pBs = pCurLayer->pBitStringAux; PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer; PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; SNeighAvail sNeighAvail; int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart; int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd; int32_t iMbX = pCurLayer->iMbX; int32_t iMbY = pCurLayer->iMbY; int32_t iMbXy = pCurLayer->iMbXyIndex; int32_t iNMbMode, i; uint32_t uiMbType = 0, uiCbp = 0, uiCbpL = 0, uiCbpC = 0; ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16); pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0; pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag; uiMbType = BsGetUe (pBs);Lines 1–500 of 1154. Load more
/*! * \copy * Copyright (c) 2008-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. * * * Abstract * current slice decoding * * History * 07/10/2008 Created * 08/09/2013 Modified * *****************************************************************************/ #include "deblocking.h" #include "decode_slice.h" #include "parse_mb_syn_cavlc.h" #include "rec_mb.h" #include "mv_pred.h" #include "cpu_core.h" namespace WelsDec { int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx) { int32_t iPreQP = 0; PDqLayer pCurLayer = pCtx->pCurDqLayer; PSlice pCurSlice = &pCurLayer->sLayerInfo.sSliceInLayer; PSliceHeader pSliceHeader = &pCurSlice->sSliceHeaderExt.sSliceHeader; int32_t iTotalMbTargetLayer = pSliceHeader->pSps->uiTotalMbCount; int32_t iCurLayerWidth = pCurLayer->iMbWidth << 4; int32_t iCurLayerHeight = pCurLayer->iMbHeight << 4; int32_t iNextMbXyIndex = 0; PFmo pFmo = pCtx->pFmo; int32_t iTotalNumMb = pCurSlice->iTotalMbInCurSlice; int32_t iCountNumMb = 0; PDeblockingFilterMbFunc pDeblockMb; if (!pCtx->bAvcBasedFlag && iCurLayerWidth != pCtx->iCurSeqIntervalMaxPicWidth) { return -1; } iNextMbXyIndex = pSliceHeader->iFirstMbInSlice; pCurLayer->iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; pCurLayer->iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; pCurLayer->iMbXyIndex = iNextMbXyIndex; if (0 == iNextMbXyIndex) { pCurLayer->pDec->iSpsId = pSliceHeader->iSpsId; pCurLayer->pDec->iPpsId = pSliceHeader->iPpsId; pCurLayer->pDec->uiQualityId = pCurLayer->sLayerInfo.sNalHeaderExt.uiQualityId; } do { iPreQP = pCurLayer->pLumaQp[pCurLayer->iMbXyIndex]; if (WelsTargetMbConstruction (pCtx)) { WelsLog (pCtx, WELS_LOG_WARNING, "WelsTargetSliceConstruction():::MB(%d, %d) construction error. pCurSlice_type:%d\n", pCurLayer->iMbX, pCurLayer->iMbY, pCurSlice->eSliceType); return -1; } ++iCountNumMb; ++pCurLayer->pDec->iTotalNumMbRec; if (iCountNumMb >= iTotalNumMb) { break; } if (pCurLayer->pDec->iTotalNumMbRec > iTotalMbTargetLayer) { WelsLog (pCtx, WELS_LOG_WARNING, "WelsTargetSliceConstruction():::fdec->iTotalNumMbRec:%d, iTotalMbTargetLayer:%d\n", pCurLayer->pDec->iTotalNumMbRec, iTotalMbTargetLayer); return -1; } if (pSliceHeader->pPps->uiNumSliceGroups > 1) { iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex); } else { ++iNextMbXyIndex; } if (-1 == iNextMbXyIndex || iNextMbXyIndex >= iTotalMbTargetLayer) { // slice group boundary or end of a frame break; } pCurLayer->iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; pCurLayer->iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; pCurLayer->iMbXyIndex = iNextMbXyIndex; } while (1); pCtx->pDec->iWidthInPixel = iCurLayerWidth; pCtx->pDec->iHeightInPixel = iCurLayerHeight; if ((pCurSlice->eSliceType != I_SLICE) && (pCurSlice->eSliceType != P_SLICE)) return 0; pDeblockMb = WelsDeblockingMb; if (1 == pSliceHeader->uiDisableDeblockingFilterIdc) { return 0;//NO_SUPPORTED_FILTER_IDX } else { WelsDeblockingFilterSlice (pCtx, pDeblockMb); } // any other filter_idc not supported here, 7/22/2010 return 0; } int32_t WelsMbInterSampleConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, uint8_t* pDstY, uint8_t* pDstU, uint8_t* pDstV, int32_t iStrideL, int32_t iStrideC) { int32_t iMbXy = pCurLayer->iMbXyIndex; int32_t i, iIndex, iOffset; WelsChromaDcIdct (pCurLayer->pScaledTCoeff[iMbXy] + 256); // 256 = 16*16 WelsChromaDcIdct (pCurLayer->pScaledTCoeff[iMbXy] + 320); // 320 = 16*16 + 16*4 for (i = 0; i < 16; i++) { //luma iIndex = g_kuiMbNonZeroCountIdx[i]; if (pCurLayer->pNzc[iMbXy][iIndex]) { iOffset = ((iIndex >> 2) << 2) * iStrideL + ((iIndex % 4) << 2); pCtx->pIdctResAddPredFunc (pDstY + iOffset, iStrideL, pCurLayer->pScaledTCoeff[iMbXy] + (i << 4)); } } for (i = 0; i < 4; i++) { //chroma iIndex = g_kuiMbNonZeroCountIdx[i + 16]; //Cb if (pCurLayer->pNzc[iMbXy][iIndex] || * (pCurLayer->pScaledTCoeff[iMbXy] + ((i + 16) << 4))) { iOffset = (((iIndex - 16) >> 2) << 2) * iStrideC + (((iIndex - 16) % 4) << 2); pCtx->pIdctResAddPredFunc (pDstU + iOffset, iStrideC, pCurLayer->pScaledTCoeff[iMbXy] + ((i + 16) << 4)); } iIndex = g_kuiMbNonZeroCountIdx[i + 20]; //Cr if (pCurLayer->pNzc[iMbXy][iIndex] || * (pCurLayer->pScaledTCoeff[iMbXy] + ((i + 20) << 4))) { iOffset = (((iIndex - 18) >> 2) << 2) * iStrideC + (((iIndex - 18) % 4) << 2); pCtx->pIdctResAddPredFunc (pDstV + iOffset, iStrideC , pCurLayer->pScaledTCoeff[iMbXy] + ((i + 20) << 4)); } } return 0; } int32_t WelsMbInterConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer) { int32_t iMbX = pCurLayer->iMbX; int32_t iMbY = pCurLayer->iMbY; uint8_t* pDstY, *pDstCb, *pDstCr; int32_t iLumaStride = pCtx->pDec->iLinesize[0]; int32_t iChromaStride = pCtx->pDec->iLinesize[1]; pDstY = pCurLayer->pDec->pData[0] + ((iMbY * iLumaStride + iMbX) << 4); pDstCb = pCurLayer->pDec->pData[1] + ((iMbY * iChromaStride + iMbX) << 3); pDstCr = pCurLayer->pDec->pData[2] + ((iMbY * iChromaStride + iMbX) << 3); GetInterPred (pDstY, pDstCb, pDstCr, pCtx); WelsMbInterSampleConstruction (pCtx, pCurLayer, pDstY, pDstCb, pDstCr, iLumaStride, iChromaStride); pCtx->sBlockFunc.pWelsSetNonZeroCountFunc (NULL, pCurLayer->pNzc[pCurLayer->iMbXyIndex]); // set all none-zero nzc to 1; dbk can be opti! return 0; } void WelsLumaDcDequantIdct (int16_t* pBlock, int32_t iQp) { const int32_t kiQMul = g_kuiDequantCoeff[iQp][0]; #define STRIDE 16 int32_t i; int32_t iTemp[16]; //FIXME check if this is a good idea int16_t* pBlk = pBlock; static const int32_t kiXOffset[4] = {0, STRIDE, STRIDE << 2, 5 * STRIDE}; static const int32_t kiYOffset[4] = {0, STRIDE << 1, STRIDE << 3, 10 * STRIDE}; for (i = 0; i < 4; i++) { const int32_t kiOffset = kiYOffset[i]; const int32_t kiX1 = kiOffset + kiXOffset[2]; const int32_t kiX2 = STRIDE + kiOffset; const int32_t kiX3 = kiOffset + kiXOffset[3]; const int32_t kiI4 = i << 2; // 4*i const int32_t kiZ0 = pBlk[kiOffset] + pBlk[kiX1]; const int32_t kiZ1 = pBlk[kiOffset] - pBlk[kiX1]; const int32_t kiZ2 = pBlk[kiX2] - pBlk[kiX3]; const int32_t kiZ3 = pBlk[kiX2] + pBlk[kiX3]; iTemp[kiI4] = kiZ0 + kiZ3; iTemp[1 + kiI4] = kiZ1 + kiZ2; iTemp[2 + kiI4] = kiZ1 - kiZ2; iTemp[3 + kiI4] = kiZ0 - kiZ3; } for (i = 0; i < 4; i++) { const int32_t kiOffset = kiXOffset[i]; const int32_t kiI4 = 4 + i; const int32_t kiZ0 = iTemp[i] + iTemp[4 + kiI4]; const int32_t kiZ1 = iTemp[i] - iTemp[4 + kiI4]; const int32_t kiZ2 = iTemp[kiI4] - iTemp[8 + kiI4]; const int32_t kiZ3 = iTemp[kiI4] + iTemp[8 + kiI4]; pBlk[kiOffset] = ((kiZ0 + kiZ3) * kiQMul + 2) >> 2; //FIXME think about merging this into decode_resdual pBlk[kiYOffset[1] + kiOffset] = ((kiZ1 + kiZ2) * kiQMul + 2) >> 2; pBlk[kiYOffset[2] + kiOffset] = ((kiZ1 - kiZ2) * kiQMul + 2) >> 2; pBlk[kiYOffset[3] + kiOffset] = ((kiZ0 - kiZ3) * kiQMul + 2) >> 2; } #undef STRIDE } int32_t WelsMbIntraPredictionConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, bool bOutput) { //seems IPCM should not enter this path int32_t iMbXy = pCurLayer->iMbXyIndex; WelsFillRecNeededMbInfo (pCtx, bOutput, pCurLayer); if (IS_INTRA16x16 (pCurLayer->pMbType[iMbXy])) { WelsLumaDcDequantIdct (pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy]); RecI16x16Mb (iMbXy, pCtx, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer); return 0; } if (IS_INTRA4x4 (pCurLayer->pMbType[iMbXy])) RecI4x4Mb (iMbXy, pCtx, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer); return 0; } int32_t WelsMbInterPrediction (PWelsDecoderContext pCtx, PDqLayer pCurLayer) { int32_t iMbX = pCurLayer->iMbX; int32_t iMbY = pCurLayer->iMbY; uint8_t* pDstY, *pDstCb, *pDstCr; int32_t iLumaStride = pCtx->pDec->iLinesize[0]; int32_t iChromaStride = pCtx->pDec->iLinesize[1]; pDstY = pCurLayer->pDec->pData[0] + ((iMbY * iLumaStride + iMbX) << 4); pDstCb = pCurLayer->pDec->pData[1] + ((iMbY * iChromaStride + iMbX) << 3); pDstCr = pCurLayer->pDec->pData[2] + ((iMbY * iChromaStride + iMbX) << 3); GetInterPred (pDstY, pDstCb, pDstCr, pCtx); return 0; } void WelsMbCopy (uint8_t* pDst, int32_t iStrideDst, uint8_t* pSrc, int32_t iStrideSrc, int32_t iHeight, int32_t iWidth) { int32_t i; int32_t iOffsetDst = 0, iOffsetSrc = 0; for (i = 0; i < iHeight; i++) { memcpy (pDst + iOffsetDst, pSrc + iOffsetSrc, iWidth); iOffsetDst += iStrideDst; iOffsetSrc += iStrideSrc; } } int32_t WelsTargetMbConstruction (PWelsDecoderContext pCtx) { PDqLayer pCurLayer = pCtx->pCurDqLayer; if (MB_TYPE_INTRA_PCM == pCurLayer->pMbType[pCurLayer->iMbXyIndex]) { //copy cs into fdec int32_t iCsStrideL = pCurLayer->iCsStride[0]; int32_t iCsStrideC = pCurLayer->iCsStride[1]; int32_t iDecStrideL = pCurLayer->pDec->iLinesize[0]; int32_t iDecStrideC = pCurLayer->pDec->iLinesize[1]; int32_t iCsOffsetL = (pCurLayer->iMbX + pCurLayer->iMbY * iCsStrideL) << 4; int32_t iCsOffsetC = (pCurLayer->iMbX + pCurLayer->iMbY * iCsStrideC) << 3; int32_t iDecOffsetL = (pCurLayer->iMbX + pCurLayer->iMbY * iDecStrideL) << 4; int32_t iDecOffsetC = (pCurLayer->iMbX + pCurLayer->iMbY * iDecStrideC) << 3; uint8_t* pSrcY = pCurLayer->pCsData[0] + iCsOffsetL; uint8_t* pSrcU = pCurLayer->pCsData[1] + iCsOffsetC; uint8_t* pSrcV = pCurLayer->pCsData[2] + iCsOffsetC; uint8_t* pDecY = pCurLayer->pDec->pData[0] + iDecOffsetL; uint8_t* pDecU = pCurLayer->pDec->pData[1] + iDecOffsetC; uint8_t* pDecV = pCurLayer->pDec->pData[2] + iDecOffsetC; WelsMbCopy (pDecY, iDecStrideL, pSrcY, iCsStrideL, 16, 16); WelsMbCopy (pDecU, iDecStrideC, pSrcU, iCsStrideC, 8, 8); WelsMbCopy (pDecV, iDecStrideC, pSrcV, iCsStrideC, 8, 8); return 0; } else if (IS_INTRA (pCurLayer->pMbType[pCurLayer->iMbXyIndex])) { WelsMbIntraPredictionConstruction (pCtx, pCurLayer, 1); } else if (IS_INTER (pCurLayer->pMbType[pCurLayer->iMbXyIndex])) { //InterMB if (0 == pCurLayer->pCbp[pCurLayer->iMbXyIndex]) { //uiCbp==0 include SKIP WelsMbInterPrediction (pCtx, pCurLayer); } else { WelsMbInterConstruction (pCtx, pCurLayer); } } else { WelsLog (pCtx, WELS_LOG_WARNING, "WelsTargetMbConstruction():::::Unknown MB type: %d\n", pCurLayer->pMbType[pCurLayer->iMbXyIndex]); return -1; } return 0; } void WelsChromaDcIdct (int16_t* pBlock) { int32_t iStride = 32; int32_t iXStride = 16; int32_t iStride1 = iXStride + iStride; int16_t* pBlk = pBlock; int32_t iA, iB, iC, iD, iE; iA = pBlk[0]; iB = pBlk[iXStride]; iC = pBlk[iStride]; iD = pBlk[iStride1]; iE = iA - iB; iA += iB; iB = iC - iD; iC += iD; pBlk[0] = (iA + iC) >> 1; pBlk[iXStride] = (iE + iB) >> 1; pBlk[iStride] = (iA - iC) >> 1; pBlk[iStride1] = (iE - iB) >> 1; } int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur) { PDqLayer pCurLayer = pCtx->pCurDqLayer; PFmo pFmo = pCtx->pFmo; int32_t i, iRet; int32_t iNextMbXyIndex, iSliceIdc; PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer; PSliceHeaderExt pSliceHeaderExt = &pSlice->sSliceHeaderExt; PSliceHeader pSliceHeader = &pSliceHeaderExt->sSliceHeader; int32_t iMbX, iMbY; const int32_t kiCountNumMb = pSliceHeader->pSps->uiTotalMbCount; //need to be correct when fmo or multi slice PBitStringAux pBs = pCurLayer->pBitStringAux; int32_t iUsedBits = 0; PWelsDecMbCavlcFunc pDecMbCavlcFunc; pSlice->iTotalMbInCurSlice = 0; //initialize at the starting of slice decoding. if (P_SLICE == pSliceHeader->eSliceType) { pDecMbCavlcFunc = WelsDecodeMbCavlcPSlice; } else { //I_SLICE pDecMbCavlcFunc = WelsDecodeMbCavlcISlice; } if (pSliceHeader->pPps->bConstainedIntraPredFlag) { pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain1Intra4x4; pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain1; pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain1; } else { pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain0Intra4x4; pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain0; pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain0; } pCtx->eSliceType = pSliceHeader->eSliceType; if (pCurLayer->sLayerInfo.pPps->bEntropyCodingModeFlag == 1) { //CABAC encoding is unsupported yet! return -1; } iNextMbXyIndex = pSliceHeader->iFirstMbInSlice; if ((iNextMbXyIndex < 0) || (iNextMbXyIndex >= kiCountNumMb)) { WelsLog (pCtx, WELS_LOG_ERROR, "WelsDecodeSlice()::iFirstMbInSlice(%d) > pSps->kiTotalMb(%d). ERROR!!! resolution change....\n", iNextMbXyIndex, kiCountNumMb); pCtx->iErrorCode |= dsNoParamSets; return dsNoParamSets; } iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; // error is introduced by multiple slices case, 11/23/2009 pSlice->iMbSkipRun = -1; iSliceIdc = (pSliceHeader->iFirstMbInSlice << 7) + pCurLayer->uiLayerDqId; pCurLayer->iMbX = iMbX; pCurLayer->iMbY = iMbY; pCurLayer->iMbXyIndex = iNextMbXyIndex; if (pSliceHeaderExt->bSliceSkipFlag == 1) { for (i = 0; i < (int32_t)pSliceHeaderExt->uiNumMbsInSlice; i++) { pCurLayer->pSliceIdc[iNextMbXyIndex] = iSliceIdc; pCurLayer->pResidualPredFlag[iNextMbXyIndex] = 1; if (pSliceHeaderExt->sSliceHeader.pPps->uiNumSliceGroups > 1) { iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex); } else { ++iNextMbXyIndex; } iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; iMbY = iNextMbXyIndex % pCurLayer->iMbHeight; pCurLayer->iMbX = iMbX; pCurLayer->iMbY = iMbY; pCurLayer->iMbXyIndex = iNextMbXyIndex; } return 0; } do { pCurLayer->pSliceIdc[iNextMbXyIndex] = iSliceIdc; iRet = pDecMbCavlcFunc (pCtx, pNalCur); if (iRet != ERR_NONE) { return iRet; } ++pSlice->iTotalMbInCurSlice; if (pSliceHeader->pPps->uiNumSliceGroups > 1) { iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex); } else { ++iNextMbXyIndex; } if ((-1 == iNextMbXyIndex) || (iNextMbXyIndex >= kiCountNumMb)) { // slice group boundary or end of a frame break; } // check whether there is left bits to read next time in case multiple slices iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits); if (iUsedBits == pBs->iBits && 0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun) { // slice boundary break; } if (iUsedBits > pBs->iBits) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash. WelsLog (pCtx, WELS_LOG_WARNING, "WelsDecodeSlice()::::pBs incomplete, iUsedBits:%d > pBs->iBits:%d, MUST stop decoding.\n", iUsedBits, pBs->iBits); return -1; } iMbX = iNextMbXyIndex % pCurLayer->iMbWidth; iMbY = iNextMbXyIndex / pCurLayer->iMbWidth; pCurLayer->iMbX = iMbX; pCurLayer->iMbY = iMbY; pCurLayer->iMbXyIndex = iNextMbXyIndex; } while (1); return ERR_NONE; } int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) { SVlcTable* pVlcTable = &pCtx->sVlcTable; PDqLayer pCurLayer = pCtx->pCurDqLayer; PBitStringAux pBs = pCurLayer->pBitStringAux; PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer; PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; SNeighAvail sNeighAvail; int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart; int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd; int32_t iMbX = pCurLayer->iMbX; int32_t iMbY = pCurLayer->iMbY; int32_t iMbXy = pCurLayer->iMbXyIndex; int32_t iNMbMode, i; uint32_t uiMbType = 0, uiCbp = 0, uiCbpL = 0, uiCbpC = 0; ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16); pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0; pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag; uiMbType = BsGetUe (pBs);