/*! * \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; } } 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->iNalLenInByte[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 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->iNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen; pCtx->iNalLenInByte[pCtx->iNalNum ++] = pSpsBs->uiSpsBsLen; pDstBuf += pSpsBs->uiSpsBsLen; memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen); pParser->iNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen; pDstBuf += pPpsBs->uiPpsBsLen; pCtx->bFrameFinish = false; } } //then VCL data re-write while (iIdx <= iEndIdx) { pCurNal = pCurAu->pNalUnitsList [iIdx ++]; iNalLen = pCurNal->sNalData.sVclNal.iNalLength; pNalBs = pCurNal->sNalData.sVclNal.pNalPos; pParser->iNalLenInByte [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. \n", (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY); 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 = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; pDstInfo->iBufferStatus = 1; bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) || (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."); } } pCtx->iMbEcedNum = pPic->iMbEcedNum; pCtx->iMbNum = pPic->iMbNum; pCtx->iMbEcedPropNum = pPic->iMbEcedPropNum; 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; } 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; } while (iList < LIST_1);//TODO: SUPPORT LIST_A return ERR_NONE;} /* * 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;} int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps, const bool kbIdrFlag) { PRefPicMarking const kpRefMarking = &pSh->sRefMarking; uint32_t uiCode; if (kbIdrFlag) { WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //no_output_of_prior_pics_flag kpRefMarking->bNoOutputOfPriorPicsFlag = !!uiCode; WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //long_term_reference_flag kpRefMarking->bLongTermRefFlag = !!uiCode; } else { WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_ref_pic_marking_mode_flag kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!uiCode; if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) { int32_t iIdx = 0; do { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //memory_management_control_operation const uint32_t kuiMmco = uiCode; kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kuiMmco; if (kuiMmco == MMCO_END) break; if (kuiMmco == MMCO_SHORT2UNUSED || kuiMmco == MMCO_SHORT2LONG) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //difference_of_pic_nums_minus1 kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + uiCode; kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & (( 1 << pSps->uiLog2MaxFrameNum) - 1); } else if (kuiMmco == MMCO_LONG2UNUSED) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = uiCode; } if (kuiMmco == MMCO_SHORT2LONG || kuiMmco == MMCO_LONG) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_frame_idx kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = uiCode; } else if (kuiMmco == MMCO_SET_MAX_LONG) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //max_long_term_frame_idx_plus1 kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + uiCode; } ++ iIdx; } while (iIdx < MAX_MMCO_COUNT); } } return ERR_NONE;} bool FillDefaultSliceHeaderExt (PSliceHeaderExt pShExt, PNalUnitHeaderExt pNalExt) { if (pShExt == NULL || pNalExt == NULL) return false; if (pNalExt->iNoInterLayerPredFlag || pNalExt->uiQualityId > 0) pShExt->bBasePredWeightTableFlag = false; else pShExt->bBasePredWeightTableFlag = true; pShExt->uiRefLayerDqId = (uint8_t) - 1; pShExt->uiDisableInterLayerDeblockingFilterIdc = 0; pShExt->iInterLayerSliceAlphaC0Offset = 0; pShExt->iInterLayerSliceBetaOffset = 0; pShExt->bConstrainedIntraResamplingFlag = false; pShExt->uiRefLayerChromaPhaseXPlus1Flag = 0; pShExt->uiRefLayerChromaPhaseYPlus1 = 1; //memset(&pShExt->sScaledRefLayer, 0, sizeof(SPosOffset)); pShExt->iScaledRefLayerPicWidthInSampleLuma = pShExt->sSliceHeader.iMbWidth << 4; pShExt->iScaledRefLayerPicHeightInSampleLuma = pShExt->sSliceHeader.iMbHeight << 4; pShExt->bSliceSkipFlag = false; pShExt->bAdaptiveBaseModeFlag = false; pShExt->bDefaultBaseModeFlag = false; pShExt->bAdaptiveMotionPredFlag = false; pShExt->bDefaultMotionPredFlag = false; pShExt->bAdaptiveResidualPredFlag = false; pShExt->bDefaultResidualPredFlag = false; pShExt->bTCoeffLevelPredFlag = false; pShExt->uiScanIdxStart = 0; pShExt->uiScanIdxEnd = 15; return true;} int32_t InitBsBuffer (PWelsDecoderContext pCtx) { if (pCtx == NULL) return ERR_INFO_INVALID_PTR; CMemoryAlign* pMa = pCtx->pMemAlign; pCtx->iMaxBsBufferSizeInByte = MIN_ACCESS_UNIT_CAPACITY * MAX_BUFFERED_NUM; if ((pCtx->sRawData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte, "pCtx->sRawData.pHead"))) == NULL) { return ERR_INFO_OUT_OF_MEMORY; } pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead; pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte; if (pCtx->pParam->bParseOnly) { pCtx->pParserBsInfo = static_cast<SParserBsInfo*> (pMa->WelsMallocz (sizeof (SParserBsInfo), "pCtx->pParserBsInfo")); if (pCtx->pParserBsInfo == NULL) { return ERR_INFO_OUT_OF_MEMORY; } memset (pCtx->pParserBsInfo, 0, sizeof (SParserBsInfo)); pCtx->pParserBsInfo->pDstBuff = static_cast<uint8_t*> (pMa->WelsMallocz (MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t), "pCtx->pParserBsInfo->pDstBuff")); if (pCtx->pParserBsInfo->pDstBuff == NULL) { return ERR_INFO_OUT_OF_MEMORY; } memset (pCtx->pParserBsInfo->pDstBuff, 0, MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t)); if ((pCtx->sSavedData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte,Lines 1–500 of 2537. 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; } } 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->iNalLenInByte[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 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->iNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen; pCtx->iNalLenInByte[pCtx->iNalNum ++] = pSpsBs->uiSpsBsLen; pDstBuf += pSpsBs->uiSpsBsLen; memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen); pParser->iNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen; pDstBuf += pPpsBs->uiPpsBsLen; pCtx->bFrameFinish = false; } } //then VCL data re-write while (iIdx <= iEndIdx) { pCurNal = pCurAu->pNalUnitsList [iIdx ++]; iNalLen = pCurNal->sNalData.sVclNal.iNalLength; pNalBs = pCurNal->sNalData.sVclNal.pNalPos; pParser->iNalLenInByte [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. \n", (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY); 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 = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; pDstInfo->iBufferStatus = 1; bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) || (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."); } } pCtx->iMbEcedNum = pPic->iMbEcedNum; pCtx->iMbNum = pPic->iMbNum; pCtx->iMbEcedPropNum = pPic->iMbEcedPropNum; 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; } 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; } while (iList < LIST_1);//TODO: SUPPORT LIST_A return ERR_NONE; } /* * 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; } int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps, const bool kbIdrFlag) { PRefPicMarking const kpRefMarking = &pSh->sRefMarking; uint32_t uiCode; if (kbIdrFlag) { WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //no_output_of_prior_pics_flag kpRefMarking->bNoOutputOfPriorPicsFlag = !!uiCode; WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //long_term_reference_flag kpRefMarking->bLongTermRefFlag = !!uiCode; } else { WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_ref_pic_marking_mode_flag kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!uiCode; if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) { int32_t iIdx = 0; do { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //memory_management_control_operation const uint32_t kuiMmco = uiCode; kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kuiMmco; if (kuiMmco == MMCO_END) break; if (kuiMmco == MMCO_SHORT2UNUSED || kuiMmco == MMCO_SHORT2LONG) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //difference_of_pic_nums_minus1 kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + uiCode; kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & (( 1 << pSps->uiLog2MaxFrameNum) - 1); } else if (kuiMmco == MMCO_LONG2UNUSED) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = uiCode; } if (kuiMmco == MMCO_SHORT2LONG || kuiMmco == MMCO_LONG) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_frame_idx kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = uiCode; } else if (kuiMmco == MMCO_SET_MAX_LONG) { WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //max_long_term_frame_idx_plus1 kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + uiCode; } ++ iIdx; } while (iIdx < MAX_MMCO_COUNT); } } return ERR_NONE; } bool FillDefaultSliceHeaderExt (PSliceHeaderExt pShExt, PNalUnitHeaderExt pNalExt) { if (pShExt == NULL || pNalExt == NULL) return false; if (pNalExt->iNoInterLayerPredFlag || pNalExt->uiQualityId > 0) pShExt->bBasePredWeightTableFlag = false; else pShExt->bBasePredWeightTableFlag = true; pShExt->uiRefLayerDqId = (uint8_t) - 1; pShExt->uiDisableInterLayerDeblockingFilterIdc = 0; pShExt->iInterLayerSliceAlphaC0Offset = 0; pShExt->iInterLayerSliceBetaOffset = 0; pShExt->bConstrainedIntraResamplingFlag = false; pShExt->uiRefLayerChromaPhaseXPlus1Flag = 0; pShExt->uiRefLayerChromaPhaseYPlus1 = 1; //memset(&pShExt->sScaledRefLayer, 0, sizeof(SPosOffset)); pShExt->iScaledRefLayerPicWidthInSampleLuma = pShExt->sSliceHeader.iMbWidth << 4; pShExt->iScaledRefLayerPicHeightInSampleLuma = pShExt->sSliceHeader.iMbHeight << 4; pShExt->bSliceSkipFlag = false; pShExt->bAdaptiveBaseModeFlag = false; pShExt->bDefaultBaseModeFlag = false; pShExt->bAdaptiveMotionPredFlag = false; pShExt->bDefaultMotionPredFlag = false; pShExt->bAdaptiveResidualPredFlag = false; pShExt->bDefaultResidualPredFlag = false; pShExt->bTCoeffLevelPredFlag = false; pShExt->uiScanIdxStart = 0; pShExt->uiScanIdxEnd = 15; return true; } int32_t InitBsBuffer (PWelsDecoderContext pCtx) { if (pCtx == NULL) return ERR_INFO_INVALID_PTR; CMemoryAlign* pMa = pCtx->pMemAlign; pCtx->iMaxBsBufferSizeInByte = MIN_ACCESS_UNIT_CAPACITY * MAX_BUFFERED_NUM; if ((pCtx->sRawData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte, "pCtx->sRawData.pHead"))) == NULL) { return ERR_INFO_OUT_OF_MEMORY; } pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead; pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte; if (pCtx->pParam->bParseOnly) { pCtx->pParserBsInfo = static_cast<SParserBsInfo*> (pMa->WelsMallocz (sizeof (SParserBsInfo), "pCtx->pParserBsInfo")); if (pCtx->pParserBsInfo == NULL) { return ERR_INFO_OUT_OF_MEMORY; } memset (pCtx->pParserBsInfo, 0, sizeof (SParserBsInfo)); pCtx->pParserBsInfo->pDstBuff = static_cast<uint8_t*> (pMa->WelsMallocz (MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t), "pCtx->pParserBsInfo->pDstBuff")); if (pCtx->pParserBsInfo->pDstBuff == NULL) { return ERR_INFO_OUT_OF_MEMORY; } memset (pCtx->pParserBsInfo->pDstBuff, 0, MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t)); if ((pCtx->sSavedData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte,