/*! * \copy * Copyright (c) 2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * decoder_core.c: Wels decoder framework core implementation */ #include "decoder_core.h"#include "error_code.h"#include "memmgr_nal_unit.h"#include "au_parser.h"#include "decode_slice.h"#include "manage_dec_ref.h"#include "expand_pic.h"#include "decoder.h"#include "decode_mb_aux.h"#include "memory_align.h"#include "error_concealment.h" namespace WelsDec {static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { PDqLayer pCurDq = pCtx->pCurDqLayer; PPicture pPic = pCtx->pDec; const int32_t kiWidth = pCurDq->iMbWidth << 4; const int32_t kiHeight = pCurDq->iMbHeight << 4; const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight; bool bFrameCompleteFlag = true; if (pPic->bNewSeqBegin) { memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), sizeof (SPosOffset)); //confirmed_safe_unsafe_usage#ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = false;#else pCtx->bReferenceLostAtT0Flag = false; // need initialize it due new seq, 6/4/2010#endif //LONG_TERM_REF if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { pCtx->bPrintFrameErrorTraceFlag = true; WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction(): will output first frame of new sequence, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d, ignored error packet:%d.", kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, pCtx->sFrameCrop.iBottomOffset, pCtx->iIgnoredErrorInfoPacketCount); pCtx->iIgnoredErrorInfoPacketCount = 0; } } const int32_t kiActualWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; const int32_t kiActualHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { if ((pCtx->pDecoderStatistics->uiWidth != (unsigned int) kiActualWidth) || (pCtx->pDecoderStatistics->uiHeight != (unsigned int) kiActualHeight)) { pCtx->pDecoderStatistics->uiResolutionChangeTimes++; pCtx->pDecoderStatistics->uiWidth = kiActualWidth; pCtx->pDecoderStatistics->uiHeight = kiActualHeight; } UpdateDecStatNoFreezingInfo (pCtx); } if (pCtx->pParam->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo PAccessUnit pCurAu = pCtx->pAccessUnitList; if (dsErrorFree == pCtx->iErrorCode) { //correct decoding, add to data buffer SParserBsInfo* pParser = pCtx->pParserBsInfo; SNalUnit* pCurNal = NULL; int32_t iTotalNalLen = 0; int32_t iNalLen = 0; int32_t iNum = 0; while (iNum < pParser->iNalNum) { iTotalNalLen += pParser->pNalLenInByte[iNum++]; } uint8_t* pDstBuf = pParser->pDstBuff + iTotalNalLen; int32_t iIdx = pCurAu->uiStartPos; int32_t iEndIdx = pCurAu->uiEndPos; uint8_t* pNalBs = NULL; pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0; //pParser->iNalNum = 0; pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4) - ((pCtx->pSps->sFrameCrop.iLeftOffset + pCtx->pSps->sFrameCrop.iRightOffset) << 1); pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4) - ((pCtx->pSps->sFrameCrop.iTopOffset + pCtx->pSps->sFrameCrop.iBottomOffset) << 1); if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR if (pCtx->bFrameFinish) { //add required sps/pps if (pParser->iNalNum > pCtx->iMaxNalNum - 2) { //2 reserved for sps+pps WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction(): current NAL num (%d) plus sps & pps exceeds permitted num (%d). Will expand", pParser->iNalNum, pCtx->iMaxNalNum); WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + 2)) } bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType); SSpsBsInfo* pSpsBs = NULL; SPpsBsInfo* pPpsBs = NULL; int32_t iSpsId = pCtx->pSps->iSpsId; int32_t iPpsId = pCtx->pPps->iPpsId; pCtx->bParamSetsLostFlag = false; //find required sps, pps and write into dst buff pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId]; pPpsBs = &pCtx->sPpsBsInfo [iPpsId]; if (pDstBuf - pParser->pDstBuff + pSpsBs->uiSpsBsLen + pPpsBs->uiPpsBsLen >= MAX_ACCESS_UNIT_CAPACITY) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "DecodeFrameConstruction(): sps pps size: (%d %d) too large. Failed to parse. \n", pSpsBs->uiSpsBsLen, pPpsBs->uiPpsBsLen); pCtx->iErrorCode |= dsOutOfMemory; pCtx->pParserBsInfo->iNalNum = 0; return ERR_INFO_OUT_OF_MEMORY; } memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen); pParser->pNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen; pDstBuf += pSpsBs->uiSpsBsLen; memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen); pParser->pNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen; pDstBuf += pPpsBs->uiPpsBsLen; pCtx->bFrameFinish = false; } } //then VCL data re-write if (pParser->iNalNum + iEndIdx - iIdx + 1 > pCtx->iMaxNalNum) { //calculate total NAL num WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction(): current NAL num (%d) exceeds permitted num (%d). Will expand", pParser->iNalNum + iEndIdx - iIdx + 1, pCtx->iMaxNalNum); WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + iEndIdx - iIdx + 1)) } while (iIdx <= iEndIdx) { pCurNal = pCurAu->pNalUnitsList [iIdx ++]; iNalLen = pCurNal->sNalData.sVclNal.iNalLength; pNalBs = pCurNal->sNalData.sVclNal.pNalPos; pParser->pNalLenInByte [pParser->iNalNum ++] = iNalLen; if (pDstBuf - pParser->pDstBuff + iNalLen >= MAX_ACCESS_UNIT_CAPACITY) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "DecodeFrameConstruction(): composed output size (%ld) exceeds (%d). Failed to parse. current data pos %d out of %d:, previously accumulated num: %d, total num: %d, previously accumulated len: %d, current len: %d, current buf pos: %p, header buf pos: %p \n", (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY, iIdx, iEndIdx, iNum, pParser->iNalNum, iTotalNalLen, iNalLen, pDstBuf, pParser->pDstBuff); pCtx->iErrorCode |= dsOutOfMemory; pCtx->pParserBsInfo->iNalNum = 0; return ERR_INFO_OUT_OF_MEMORY; } memcpy (pDstBuf, pNalBs, iNalLen); pDstBuf += iNalLen; } if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { //frame complete pCtx->iTotalNumMbRec = 0; pCtx->bFramePending = false; pCtx->bFrameFinish = true; //finish current frame and mark it } else if (pCtx->iTotalNumMbRec != 0) { //frame incomplete pCtx->bFramePending = true; pCtx->pDec->bIsComplete = false; pCtx->bFrameFinish = false; //current frame not finished pCtx->iErrorCode |= dsFramePending; return ERR_INFO_PARSEONLY_PENDING; //pCtx->pParserBsInfo->iNalNum = 0; } } else { //error pCtx->pParserBsInfo->uiOutBsTimeStamp = 0; pCtx->pParserBsInfo->iNalNum = 0; pCtx->pParserBsInfo->iSpsWidthInPixel = 0; pCtx->pParserBsInfo->iSpsHeightInPixel = 0; return ERR_INFO_PARSEONLY_ERROR; } return ERR_NONE; } if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "DecodeFrameConstruction(): iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ", pCtx->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight); bFrameCompleteFlag = false; //return later after output buffer is done if (pCtx->bInstantDecFlag) { //no-delay decoding, wait for new slice return ERR_INFO_MB_NUM_INADEQUATE; } } else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag && (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done pCtx->pDec->bIsComplete = true; pCtx->bFreezeOutput = false; } pCtx->iTotalNumMbRec = 0; //////output:::normal path pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp; ppDst[0] = pPic->pData[0]; ppDst[1] = pPic->pData[1]; ppDst[2] = pPic->pData[2]; pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420; pDstInfo->UsrData.sSystemBuffer.iWidth = kiActualWidth; pDstInfo->UsrData.sSystemBuffer.iHeight = kiActualHeight; pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; for (int i = 0; i < 3; ++i) { pDstInfo->pDst[i] = ppDst[i]; } pDstInfo->iBufferStatus = 1; if (GetThreadCount (pCtx) > 1 && pPic->bIsComplete == false) { pPic->bIsComplete = true; } if (GetThreadCount (pCtx) > 1) { uint32_t uiMbHeight = (pCtx->pDec->iHeightInPixel + 15) >> 4; for (uint32_t i = 0; i < uiMbHeight; ++i) { SET_EVENT (&pCtx->pDec->pReadyEvent[i]); } } bool bOutResChange = false; if (GetThreadCount (pCtx) <= 1 || pCtx->pLastThreadCtx == NULL) { bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) || (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight); } else { if (pCtx->pLastThreadCtx != NULL) { PWelsDecoderThreadCTX pLastThreadCtx = (PWelsDecoderThreadCTX) (pCtx->pLastThreadCtx); bOutResChange = (pLastThreadCtx->pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) || (pLastThreadCtx->pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight); } } pCtx->iLastImgWidthInPixel = pDstInfo->UsrData.sSystemBuffer.iWidth; pCtx->iLastImgHeightInPixel = pDstInfo->UsrData.sSystemBuffer.iHeight; if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag && pPic->bIsComplete); // When EC disable, ECed picture not output else if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE || pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) && pCtx->iErrorCode && bOutResChange) pCtx->bFreezeOutput = true; if (pDstInfo->iBufferStatus == 0) { if (!bFrameCompleteFlag) pCtx->iErrorCode |= dsBitstreamError; return ERR_INFO_MB_NUM_INADEQUATE; } if (pCtx->bFreezeOutput) { pDstInfo->iBufferStatus = 0; if (pPic->bNewSeqBegin) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction():New sequence detected, but freezed, correct MBs (%d) out of whole MBs (%d).", kiTotalNumMbInCurLayer - pCtx->iMbEcedNum, kiTotalNumMbInCurLayer); } } pCtx->iMbEcedNum = pPic->iMbEcedNum; pCtx->iMbNum = pPic->iMbNum; pCtx->iMbEcedPropNum = pPic->iMbEcedPropNum; if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) { if (pDstInfo->iBufferStatus && ((pCtx->pDecoderStatistics->uiWidth != (unsigned int) kiActualWidth) || (pCtx->pDecoderStatistics->uiHeight != (unsigned int) kiActualHeight))) { pCtx->pDecoderStatistics->uiResolutionChangeTimes++; pCtx->pDecoderStatistics->uiWidth = kiActualWidth; pCtx->pDecoderStatistics->uiHeight = kiActualHeight; } UpdateDecStat (pCtx, pDstInfo->iBufferStatus != 0); } return ERR_NONE;} inline bool CheckSliceNeedReconstruct (uint8_t uiLayerDqId, uint8_t uiTargetDqId) { return (uiLayerDqId == uiTargetDqId); // target layer} inline uint8_t GetTargetDqId (uint8_t uiTargetDqId, SDecodingParam* psParam) { uint8_t uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255; return WELS_MIN (uiTargetDqId, uiRequiredDqId);} inline void HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if (0 == pCurNal->sNalHeaderExt.uiTemporalId) { pCtx->bReferenceLostAtT0Flag = true; } pCtx->iErrorCode |= dsBitstreamError;} inline void HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) { pCtx->bReferenceLostAtT0Flag = true; } pCtx->iErrorCode |= dsRefLost;} inline int32_t WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) { int32_t iRet = WelsTargetSliceConstruction (pCtx); if (iRet) { HandleReferenceLostL0 (pCtx, pCurNal); } return iRet;} int32_t ParsePredWeightedTable (PBitStringAux pBs, PSliceHeader pSh) { uint32_t uiCode; int32_t iList = 0; int32_t iCode; WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "luma_log2_weight_denom", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_LOG2_WEIGHT_DENOM)); pSh->sPredWeightTable.uiLumaLog2WeightDenom = uiCode; if (pSh->pSps->uiChromaArrayType != 0) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "chroma_log2_weight_denom", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_LOG2_WEIGHT_DENOM)); pSh->sPredWeightTable.uiChromaLog2WeightDenom = uiCode; } if ((pSh->sPredWeightTable.uiLumaLog2WeightDenom | pSh->sPredWeightTable.uiChromaLog2WeightDenom) > 7) return ERR_NONE; do { for (int i = 0; i < pSh->uiRefCount[iList]; i++) { //luma WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); if (!!uiCode) { WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_weight", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_WEIGHT)); pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = iCode; WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_offset", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_OFFSET)); pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = iCode; } else { pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = 1 << (pSh->sPredWeightTable.uiLumaLog2WeightDenom); pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = 0; } //chroma if (pSh->pSps->uiChromaArrayType == 0) continue; WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); if (!!uiCode) { for (int j = 0; j < 2; j++) { WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_weight", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_WEIGHT)); pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = iCode; WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_offset", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_OFFSET)); pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = iCode; } } else { for (int j = 0; j < 2; j++) { pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = 1 << (pSh->sPredWeightTable.uiChromaLog2WeightDenom); pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = 0; } } } ++iList; if (pSh->eSliceType != B_SLICE) { break; } } while (iList < LIST_A);//TODO: SUPPORT LIST_A return ERR_NONE;} void CreateImplicitWeightTable (PWelsDecoderContext pCtx) { PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer; PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; PDqLayer pCurDqLayer = pCtx->pCurDqLayer; if (pCurDqLayer->bUseWeightedBiPredIdc && pSliceHeader->pPps->uiWeightedBipredIdc == 2) { int32_t iPoc = pSliceHeader->iPicOrderCntLsb; //fix Bugzilla 1485229 check if pointers are NULL if (pCtx->sRefPic.pRefList[LIST_0][0] && pCtx->sRefPic.pRefList[LIST_1][0]) { if (pSliceHeader->uiRefCount[0] == 1 && pSliceHeader->uiRefCount[1] == 1 && pCtx->sRefPic.pRefList[LIST_0][0]->iFramePoc + pCtx->sRefPic.pRefList[LIST_1][0]->iFramePoc == 2 * iPoc) { pCurDqLayer->bUseWeightedBiPredIdc = false; return; } } pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom = 5; pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom = 5; for (int32_t iRef0 = 0; iRef0 < pSliceHeader->uiRefCount[0]; iRef0++) { if (pCtx->sRefPic.pRefList[LIST_0][iRef0]) { const int32_t iPoc0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->iFramePoc; bool bIsLongRef0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->bIsLongRef; for (int32_t iRef1 = 0; iRef1 < pSliceHeader->uiRefCount[1]; iRef1++) { if (pCtx->sRefPic.pRefList[LIST_1][iRef1]) { const int32_t iPoc1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->iFramePoc; bool bIsLongRef1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->bIsLongRef; pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 32; if (!bIsLongRef0 && !bIsLongRef1) { const int32_t iTd = WELS_CLIP3 (iPoc1 - iPoc0, -128, 127); if (iTd) { int32_t iTb = WELS_CLIP3 (iPoc - iPoc0, -128, 127); int32_t iTx = (16384 + (WELS_ABS (iTd) >> 1)) / iTd; int32_t iDistScaleFactor = (iTb * iTx + 32) >> 8; if (iDistScaleFactor >= -64 && iDistScaleFactor <= 128) { pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 64 - iDistScaleFactor; } } } } } } } } return;} /* * Predeclared function routines .. */int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) { int32_t iList = 0; const EWelsSliceType keSt = pSh->eSliceType; PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering; PSps pSps = pSh->pSps; uint32_t uiCode; if (keSt == I_SLICE || keSt == SI_SLICE) return ERR_NONE; // Common syntaxs for P or B slices: list0, list1 followed if B slices used. do { WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //ref_pic_list_modification_flag_l0 pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!uiCode; if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) { int32_t iIdx = 0; do { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //modification_of_pic_nums_idc const uint32_t kuiIdc = uiCode; //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)--- if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) { return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); } pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc = kuiIdc; if (kuiIdc == 3) break; if (iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT) return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); if (kuiIdc == 0 || kuiIdc == 1) { // abs_diff_pic_num_minus1 should be in range 0 to MaxPicNum-1, MaxPicNum is derived as // 2^(4+log2_max_frame_num_minus4) WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //abs_diff_pic_num_minus1 WELS_CHECK_SE_UPPER_ERROR_NOLOG (uiCode, (uint32_t) (1 << pSps->uiLog2MaxFrameNum), "abs_diff_pic_num_minus1", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING)); pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = uiCode; // uiAbsDiffPicNumMinus1 } else if (kuiIdc == 2) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = uiCode; } ++ iIdx; } while (true); } if (keSt != B_SLICE) break; ++ iList; } while (iList < LIST_A); return ERR_NONE;} Lines 1–500 of 2995. Load more
/*! * \copy * Copyright (c) 2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * decoder_core.c: Wels decoder framework core implementation */ #include "decoder_core.h" #include "error_code.h" #include "memmgr_nal_unit.h" #include "au_parser.h" #include "decode_slice.h" #include "manage_dec_ref.h" #include "expand_pic.h" #include "decoder.h" #include "decode_mb_aux.h" #include "memory_align.h" #include "error_concealment.h" namespace WelsDec { static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { PDqLayer pCurDq = pCtx->pCurDqLayer; PPicture pPic = pCtx->pDec; const int32_t kiWidth = pCurDq->iMbWidth << 4; const int32_t kiHeight = pCurDq->iMbHeight << 4; const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight; bool bFrameCompleteFlag = true; if (pPic->bNewSeqBegin) { memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), sizeof (SPosOffset)); //confirmed_safe_unsafe_usage #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = false; #else pCtx->bReferenceLostAtT0Flag = false; // need initialize it due new seq, 6/4/2010 #endif //LONG_TERM_REF if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { pCtx->bPrintFrameErrorTraceFlag = true; WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction(): will output first frame of new sequence, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d, ignored error packet:%d.", kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, pCtx->sFrameCrop.iBottomOffset, pCtx->iIgnoredErrorInfoPacketCount); pCtx->iIgnoredErrorInfoPacketCount = 0; } } const int32_t kiActualWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; const int32_t kiActualHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { if ((pCtx->pDecoderStatistics->uiWidth != (unsigned int) kiActualWidth) || (pCtx->pDecoderStatistics->uiHeight != (unsigned int) kiActualHeight)) { pCtx->pDecoderStatistics->uiResolutionChangeTimes++; pCtx->pDecoderStatistics->uiWidth = kiActualWidth; pCtx->pDecoderStatistics->uiHeight = kiActualHeight; } UpdateDecStatNoFreezingInfo (pCtx); } if (pCtx->pParam->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo PAccessUnit pCurAu = pCtx->pAccessUnitList; if (dsErrorFree == pCtx->iErrorCode) { //correct decoding, add to data buffer SParserBsInfo* pParser = pCtx->pParserBsInfo; SNalUnit* pCurNal = NULL; int32_t iTotalNalLen = 0; int32_t iNalLen = 0; int32_t iNum = 0; while (iNum < pParser->iNalNum) { iTotalNalLen += pParser->pNalLenInByte[iNum++]; } uint8_t* pDstBuf = pParser->pDstBuff + iTotalNalLen; int32_t iIdx = pCurAu->uiStartPos; int32_t iEndIdx = pCurAu->uiEndPos; uint8_t* pNalBs = NULL; pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0; //pParser->iNalNum = 0; pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4) - ((pCtx->pSps->sFrameCrop.iLeftOffset + pCtx->pSps->sFrameCrop.iRightOffset) << 1); pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4) - ((pCtx->pSps->sFrameCrop.iTopOffset + pCtx->pSps->sFrameCrop.iBottomOffset) << 1); if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR if (pCtx->bFrameFinish) { //add required sps/pps if (pParser->iNalNum > pCtx->iMaxNalNum - 2) { //2 reserved for sps+pps WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction(): current NAL num (%d) plus sps & pps exceeds permitted num (%d). Will expand", pParser->iNalNum, pCtx->iMaxNalNum); WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + 2)) } bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType); SSpsBsInfo* pSpsBs = NULL; SPpsBsInfo* pPpsBs = NULL; int32_t iSpsId = pCtx->pSps->iSpsId; int32_t iPpsId = pCtx->pPps->iPpsId; pCtx->bParamSetsLostFlag = false; //find required sps, pps and write into dst buff pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId]; pPpsBs = &pCtx->sPpsBsInfo [iPpsId]; if (pDstBuf - pParser->pDstBuff + pSpsBs->uiSpsBsLen + pPpsBs->uiPpsBsLen >= MAX_ACCESS_UNIT_CAPACITY) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "DecodeFrameConstruction(): sps pps size: (%d %d) too large. Failed to parse. \n", pSpsBs->uiSpsBsLen, pPpsBs->uiPpsBsLen); pCtx->iErrorCode |= dsOutOfMemory; pCtx->pParserBsInfo->iNalNum = 0; return ERR_INFO_OUT_OF_MEMORY; } memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen); pParser->pNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen; pDstBuf += pSpsBs->uiSpsBsLen; memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen); pParser->pNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen; pDstBuf += pPpsBs->uiPpsBsLen; pCtx->bFrameFinish = false; } } //then VCL data re-write if (pParser->iNalNum + iEndIdx - iIdx + 1 > pCtx->iMaxNalNum) { //calculate total NAL num WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction(): current NAL num (%d) exceeds permitted num (%d). Will expand", pParser->iNalNum + iEndIdx - iIdx + 1, pCtx->iMaxNalNum); WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + iEndIdx - iIdx + 1)) } while (iIdx <= iEndIdx) { pCurNal = pCurAu->pNalUnitsList [iIdx ++]; iNalLen = pCurNal->sNalData.sVclNal.iNalLength; pNalBs = pCurNal->sNalData.sVclNal.pNalPos; pParser->pNalLenInByte [pParser->iNalNum ++] = iNalLen; if (pDstBuf - pParser->pDstBuff + iNalLen >= MAX_ACCESS_UNIT_CAPACITY) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "DecodeFrameConstruction(): composed output size (%ld) exceeds (%d). Failed to parse. current data pos %d out of %d:, previously accumulated num: %d, total num: %d, previously accumulated len: %d, current len: %d, current buf pos: %p, header buf pos: %p \n", (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY, iIdx, iEndIdx, iNum, pParser->iNalNum, iTotalNalLen, iNalLen, pDstBuf, pParser->pDstBuff); pCtx->iErrorCode |= dsOutOfMemory; pCtx->pParserBsInfo->iNalNum = 0; return ERR_INFO_OUT_OF_MEMORY; } memcpy (pDstBuf, pNalBs, iNalLen); pDstBuf += iNalLen; } if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { //frame complete pCtx->iTotalNumMbRec = 0; pCtx->bFramePending = false; pCtx->bFrameFinish = true; //finish current frame and mark it } else if (pCtx->iTotalNumMbRec != 0) { //frame incomplete pCtx->bFramePending = true; pCtx->pDec->bIsComplete = false; pCtx->bFrameFinish = false; //current frame not finished pCtx->iErrorCode |= dsFramePending; return ERR_INFO_PARSEONLY_PENDING; //pCtx->pParserBsInfo->iNalNum = 0; } } else { //error pCtx->pParserBsInfo->uiOutBsTimeStamp = 0; pCtx->pParserBsInfo->iNalNum = 0; pCtx->pParserBsInfo->iSpsWidthInPixel = 0; pCtx->pParserBsInfo->iSpsHeightInPixel = 0; return ERR_INFO_PARSEONLY_ERROR; } return ERR_NONE; } if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "DecodeFrameConstruction(): iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ", pCtx->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight); bFrameCompleteFlag = false; //return later after output buffer is done if (pCtx->bInstantDecFlag) { //no-delay decoding, wait for new slice return ERR_INFO_MB_NUM_INADEQUATE; } } else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag && (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done pCtx->pDec->bIsComplete = true; pCtx->bFreezeOutput = false; } pCtx->iTotalNumMbRec = 0; //////output:::normal path pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp; ppDst[0] = pPic->pData[0]; ppDst[1] = pPic->pData[1]; ppDst[2] = pPic->pData[2]; pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420; pDstInfo->UsrData.sSystemBuffer.iWidth = kiActualWidth; pDstInfo->UsrData.sSystemBuffer.iHeight = kiActualHeight; pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; for (int i = 0; i < 3; ++i) { pDstInfo->pDst[i] = ppDst[i]; } pDstInfo->iBufferStatus = 1; if (GetThreadCount (pCtx) > 1 && pPic->bIsComplete == false) { pPic->bIsComplete = true; } if (GetThreadCount (pCtx) > 1) { uint32_t uiMbHeight = (pCtx->pDec->iHeightInPixel + 15) >> 4; for (uint32_t i = 0; i < uiMbHeight; ++i) { SET_EVENT (&pCtx->pDec->pReadyEvent[i]); } } bool bOutResChange = false; if (GetThreadCount (pCtx) <= 1 || pCtx->pLastThreadCtx == NULL) { bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) || (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight); } else { if (pCtx->pLastThreadCtx != NULL) { PWelsDecoderThreadCTX pLastThreadCtx = (PWelsDecoderThreadCTX) (pCtx->pLastThreadCtx); bOutResChange = (pLastThreadCtx->pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) || (pLastThreadCtx->pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight); } } pCtx->iLastImgWidthInPixel = pDstInfo->UsrData.sSystemBuffer.iWidth; pCtx->iLastImgHeightInPixel = pDstInfo->UsrData.sSystemBuffer.iHeight; if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag && pPic->bIsComplete); // When EC disable, ECed picture not output else if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE || pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) && pCtx->iErrorCode && bOutResChange) pCtx->bFreezeOutput = true; if (pDstInfo->iBufferStatus == 0) { if (!bFrameCompleteFlag) pCtx->iErrorCode |= dsBitstreamError; return ERR_INFO_MB_NUM_INADEQUATE; } if (pCtx->bFreezeOutput) { pDstInfo->iBufferStatus = 0; if (pPic->bNewSeqBegin) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction():New sequence detected, but freezed, correct MBs (%d) out of whole MBs (%d).", kiTotalNumMbInCurLayer - pCtx->iMbEcedNum, kiTotalNumMbInCurLayer); } } pCtx->iMbEcedNum = pPic->iMbEcedNum; pCtx->iMbNum = pPic->iMbNum; pCtx->iMbEcedPropNum = pPic->iMbEcedPropNum; if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) { if (pDstInfo->iBufferStatus && ((pCtx->pDecoderStatistics->uiWidth != (unsigned int) kiActualWidth) || (pCtx->pDecoderStatistics->uiHeight != (unsigned int) kiActualHeight))) { pCtx->pDecoderStatistics->uiResolutionChangeTimes++; pCtx->pDecoderStatistics->uiWidth = kiActualWidth; pCtx->pDecoderStatistics->uiHeight = kiActualHeight; } UpdateDecStat (pCtx, pDstInfo->iBufferStatus != 0); } return ERR_NONE; } inline bool CheckSliceNeedReconstruct (uint8_t uiLayerDqId, uint8_t uiTargetDqId) { return (uiLayerDqId == uiTargetDqId); // target layer } inline uint8_t GetTargetDqId (uint8_t uiTargetDqId, SDecodingParam* psParam) { uint8_t uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255; return WELS_MIN (uiTargetDqId, uiRequiredDqId); } inline void HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if (0 == pCurNal->sNalHeaderExt.uiTemporalId) { pCtx->bReferenceLostAtT0Flag = true; } pCtx->iErrorCode |= dsBitstreamError; } inline void HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) { pCtx->bReferenceLostAtT0Flag = true; } pCtx->iErrorCode |= dsRefLost; } inline int32_t WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) { int32_t iRet = WelsTargetSliceConstruction (pCtx); if (iRet) { HandleReferenceLostL0 (pCtx, pCurNal); } return iRet; } int32_t ParsePredWeightedTable (PBitStringAux pBs, PSliceHeader pSh) { uint32_t uiCode; int32_t iList = 0; int32_t iCode; WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "luma_log2_weight_denom", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_LOG2_WEIGHT_DENOM)); pSh->sPredWeightTable.uiLumaLog2WeightDenom = uiCode; if (pSh->pSps->uiChromaArrayType != 0) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "chroma_log2_weight_denom", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_LOG2_WEIGHT_DENOM)); pSh->sPredWeightTable.uiChromaLog2WeightDenom = uiCode; } if ((pSh->sPredWeightTable.uiLumaLog2WeightDenom | pSh->sPredWeightTable.uiChromaLog2WeightDenom) > 7) return ERR_NONE; do { for (int i = 0; i < pSh->uiRefCount[iList]; i++) { //luma WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); if (!!uiCode) { WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_weight", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_WEIGHT)); pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = iCode; WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_offset", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_OFFSET)); pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = iCode; } else { pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = 1 << (pSh->sPredWeightTable.uiLumaLog2WeightDenom); pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = 0; } //chroma if (pSh->pSps->uiChromaArrayType == 0) continue; WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); if (!!uiCode) { for (int j = 0; j < 2; j++) { WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_weight", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_WEIGHT)); pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = iCode; WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_offset", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_OFFSET)); pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = iCode; } } else { for (int j = 0; j < 2; j++) { pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = 1 << (pSh->sPredWeightTable.uiChromaLog2WeightDenom); pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = 0; } } } ++iList; if (pSh->eSliceType != B_SLICE) { break; } } while (iList < LIST_A);//TODO: SUPPORT LIST_A return ERR_NONE; } void CreateImplicitWeightTable (PWelsDecoderContext pCtx) { PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer; PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; PDqLayer pCurDqLayer = pCtx->pCurDqLayer; if (pCurDqLayer->bUseWeightedBiPredIdc && pSliceHeader->pPps->uiWeightedBipredIdc == 2) { int32_t iPoc = pSliceHeader->iPicOrderCntLsb; //fix Bugzilla 1485229 check if pointers are NULL if (pCtx->sRefPic.pRefList[LIST_0][0] && pCtx->sRefPic.pRefList[LIST_1][0]) { if (pSliceHeader->uiRefCount[0] == 1 && pSliceHeader->uiRefCount[1] == 1 && pCtx->sRefPic.pRefList[LIST_0][0]->iFramePoc + pCtx->sRefPic.pRefList[LIST_1][0]->iFramePoc == 2 * iPoc) { pCurDqLayer->bUseWeightedBiPredIdc = false; return; } } pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom = 5; pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom = 5; for (int32_t iRef0 = 0; iRef0 < pSliceHeader->uiRefCount[0]; iRef0++) { if (pCtx->sRefPic.pRefList[LIST_0][iRef0]) { const int32_t iPoc0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->iFramePoc; bool bIsLongRef0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->bIsLongRef; for (int32_t iRef1 = 0; iRef1 < pSliceHeader->uiRefCount[1]; iRef1++) { if (pCtx->sRefPic.pRefList[LIST_1][iRef1]) { const int32_t iPoc1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->iFramePoc; bool bIsLongRef1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->bIsLongRef; pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 32; if (!bIsLongRef0 && !bIsLongRef1) { const int32_t iTd = WELS_CLIP3 (iPoc1 - iPoc0, -128, 127); if (iTd) { int32_t iTb = WELS_CLIP3 (iPoc - iPoc0, -128, 127); int32_t iTx = (16384 + (WELS_ABS (iTd) >> 1)) / iTd; int32_t iDistScaleFactor = (iTb * iTx + 32) >> 8; if (iDistScaleFactor >= -64 && iDistScaleFactor <= 128) { pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 64 - iDistScaleFactor; } } } } } } } } return; } /* * Predeclared function routines .. */ int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) { int32_t iList = 0; const EWelsSliceType keSt = pSh->eSliceType; PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering; PSps pSps = pSh->pSps; uint32_t uiCode; if (keSt == I_SLICE || keSt == SI_SLICE) return ERR_NONE; // Common syntaxs for P or B slices: list0, list1 followed if B slices used. do { WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //ref_pic_list_modification_flag_l0 pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!uiCode; if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) { int32_t iIdx = 0; do { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //modification_of_pic_nums_idc const uint32_t kuiIdc = uiCode; //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)--- if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) { return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); } pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc = kuiIdc; if (kuiIdc == 3) break; if (iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT) return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); if (kuiIdc == 0 || kuiIdc == 1) { // abs_diff_pic_num_minus1 should be in range 0 to MaxPicNum-1, MaxPicNum is derived as // 2^(4+log2_max_frame_num_minus4) WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //abs_diff_pic_num_minus1 WELS_CHECK_SE_UPPER_ERROR_NOLOG (uiCode, (uint32_t) (1 << pSps->uiLog2MaxFrameNum), "abs_diff_pic_num_minus1", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING)); pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = uiCode; // uiAbsDiffPicNumMinus1 } else if (kuiIdc == 2) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = uiCode; } ++ iIdx; } while (true); } if (keSt != B_SLICE) break; ++ iList; } while (iList < LIST_A); return ERR_NONE; }