ref: e307cbb6a1c426e2dbb23054d02d6ebdaaa559c7
dir: /codec/decoder/core/src/decoder_core.cpp/
/*! * \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 <string.h> #include "codec_def.h" #include "decoder_core.h" #include "typedefs.h" #include "wels_const.h" #include "wels_common_basis.h" #include "codec_app_def.h" #include "decoder_context.h" #include "dec_golomb.h" #include "bit_stream.h" #include "error_code.h" #include "parameter_sets.h" #include "fmo.h" #include "utils.h" #include "memmgr_nal_unit.h" #include "dec_frame.h" #include "au_parser.h" #include "pic_queue.h" #include "ls_defines.h" #include "decode_slice.h" #include "manage_dec_ref.h" #include "expand_pic.h" #include "decoder.h" #include "decode_mb_aux.h" #include "mem_align.h" namespace WelsDec { static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, int32_t* pDstLen, int32_t* pWidth, int32_t* pHeight, 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; if (pPic->iTotalNumMbRec != kiTotalNumMbInCurLayer) { WelsLog (pCtx, WELS_LOG_WARNING, "DecodeFrameConstruction():::iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d \n", pPic->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight); return -1; } #ifdef NO_WAITING_AU pPic->iTotalNumMbRec = 0; #endif if (I_SLICE == pCurDq->sLayerInfo.sSliceInLayer.eSliceType) { 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 I_SLICE, 6/4/2010 #endif //LONG_TERM_REF WelsLog (pCtx, WELS_LOG_INFO, "DecodeFrameConstruction()::::output good I frame, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d.\n", kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, pCtx->sFrameCrop.iBottomOffset); WelsLog (pCtx, WELS_LOG_INFO, "After decoding, set_mode:[%s], eWorkMode:[%s], eBufferProperty:[%s]\n", DECODER_MODE_NAME (pCtx->iSetMode), DECODER_MODE_NAME (pCtx->iDecoderMode), OUTPUT_PROPERTY_NAME (pDstInfo->eBufferProperty)); } //////output:::normal path ppDst[0] = pPic->pData[0]; ppDst[1] = pPic->pData[1]; ppDst[2] = pPic->pData[2]; *pDstLen = pPic->iLinesize[0]; * (pDstLen + 1) = pPic->iLinesize[1]; *pWidth = kiWidth; *pHeight = kiHeight; 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->eBufferProperty = BUFFER_HOST; pDstInfo->iBufferStatus = 1; return 0; } inline BOOL_T CheckSliceNeedReconstruct (int16_t iCurDid, int16_t iCurQid, bool_t bStoreRefBasePicFlag, uint8_t uiDidMax, uint8_t uiLayerDqId, uint8_t uiTargetDqId) { return ((iCurDid == uiDidMax) && (iCurQid == BASE_QUALITY_ID) && (bStoreRefBasePicFlag)) // store base || (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_t HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if (0 == pCurNal->sNalHeaderExt.uiTemporalId) { pCtx->bReferenceLostAtT0Flag = true; } #ifndef LONG_TERM_REF if (pCtx->bReferenceLostAtT0Flag) { ResetParameterSetsState (pCtx); } #endif pCtx->iErrorCode |= dsBitstreamError; } inline void_t HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) { pCtx->bReferenceLostAtT0Flag = true; } #ifndef LONG_TERM_REF if (pCtx->bReferenceLostAtT0Flag) { ResetParameterSetsState (pCtx); } #endif pCtx->iErrorCode |= dsRefLost; } inline int32_t WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) { int32_t iRet = WelsTargetSliceConstruction (pCtx); if (iRet) { HandleReferenceLostL0 (pCtx, pCurNal); } return iRet; } /* * Predeclared function routines .. */ int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) { int32_t iList = 0; const ESliceType keSt = pSh->eSliceType; PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering; 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 { pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!BsGetOneBit (pBs); if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) { int32_t iIdx = 0; do { const uint8_t kuiIdc = BsGetUe (pBs); //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) { pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = BsGetUe (pBs); // uiAbsDiffPicNumMinus1 } else if (kuiIdc == 2) { pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = BsGetUe (pBs); } ++ 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_t kbIdrFlag) { PRefPicMarking const kpRefMarking = &pSh->sRefMarking; if (kbIdrFlag) { kpRefMarking->bNoOutputOfPriorPicsFlag = !!BsGetOneBit (pBs); kpRefMarking->bLongTermRefFlag = !!BsGetOneBit (pBs); } else { kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!BsGetOneBit (pBs); if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) { int32_t iIdx = 0; do { const int32_t kiMmco = BsGetUe (pBs); kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kiMmco; if (kiMmco == MMCO_END) break; if (kiMmco == MMCO_SHORT2UNUSED || kiMmco == MMCO_SHORT2LONG) { kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + BsGetUe (pBs); kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & (( 1 << pSps->uiLog2MaxFrameNum) - 1); } else if (kiMmco == MMCO_LONG2UNUSED) kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = BsGetUe (pBs); if (kiMmco == MMCO_SHORT2LONG || kiMmco == MMCO_LONG) { kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = BsGetUe (pBs); } else if (kiMmco == MMCO_SET_MAX_LONG) kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + BsGetUe (pBs); ++ iIdx; } while (iIdx < MAX_MMCO_COUNT); } } return ERR_NONE; } bool_t 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; } /* * WelsInitMemory * Memory request for new introduced data * Especially for: * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache. * return: * 0 - success; otherwise returned error_no defined in error_no.h. */ int32_t WelsInitMemory (PWelsDecoderContext pCtx) { if (pCtx == NULL) { return ERR_INFO_INVALID_PTR; } if (MemInitNalList (&pCtx->pAccessUnitList, MAX_NAL_UNIT_NUM_IN_AU) != 0) return ERR_INFO_OUT_OF_MEMORY; if ((pCtx->sRawData.pHead = static_cast<uint8_t*> (WelsMalloc (MAX_ACCESS_UINT_CAPACITY, "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 + MAX_ACCESS_UINT_CAPACITY; pCtx->uiTargetDqId = (uint8_t) - 1; pCtx->bEndOfStreamFlag = false; pCtx->iImgWidthInPixel = 0; pCtx->iImgHeightInPixel = 0; return ERR_NONE; } /* * WelsFreeMemory * Free memory introduced in WelsInitMemory at destruction of decoder. * */ void_t WelsFreeMemory (PWelsDecoderContext pCtx) { if (pCtx == NULL) return; if (NULL != pCtx->pParam) { WelsFree (pCtx->pParam, "pCtx->pParam"); pCtx->pParam = NULL; } MemFreeNalList (&pCtx->pAccessUnitList); if (pCtx->sRawData.pHead) { WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData->pHead"); } pCtx->sRawData.pHead = NULL; pCtx->sRawData.pEnd = NULL; pCtx->sRawData.pStartPos = NULL; pCtx->sRawData.pCurPos = NULL; } /* * DecodeNalHeaderExt * Trigger condition: NAL_UNIT_TYPE = NAL_UNIT_PREFIX or NAL_UNIT_CODED_SLICE_EXT * Parameter: * pNal: target NALUnit ptr * pSrc: NAL Unit bitstream */ void_t DecodeNalHeaderExt (PNalUnit pNal, uint8_t* pSrc) { PNalUnitHeaderExt pHeaderExt = &pNal->sNalHeaderExt; uint8_t uiCurByte = *pSrc; pHeaderExt->bIdrFlag = !! (uiCurByte & 0x40); pHeaderExt->uiPriorityId = uiCurByte & 0x3F; uiCurByte = * (++pSrc); pHeaderExt->iNoInterLayerPredFlag = uiCurByte >> 7; pHeaderExt->uiDependencyId = (uiCurByte & 0x70) >> 4; pHeaderExt->uiQualityId = uiCurByte & 0x0F; uiCurByte = * (++pSrc); pHeaderExt->uiTemporalId = uiCurByte >> 5; pHeaderExt->bUseRefBasePicFlag = !! (uiCurByte & 0x10); pHeaderExt->bDiscardableFlag = !! (uiCurByte & 0x08); pHeaderExt->bOutputFlag = !! (uiCurByte & 0x04); pHeaderExt->uiReservedThree2Bits = uiCurByte & 0x03; pHeaderExt->uiLayerDqId = (pHeaderExt->uiDependencyId << 4) | pHeaderExt->uiQualityId; } #ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_ID int32_t CheckPpsId (PWelsDecoderContext pCtx, PPps* ppPps, uint32_t uiPpsId) { PPps pPpsList = pCtx->sPpsBuffer; int32_t iPpsNum = pCtx->iPpsTotalNum; int32_t i = 0; if (iPpsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckPpsId():::::PPS list is empty...NO PPS!!!\n"); return dsNoParamSets; } while (i < iPpsNum) { if (uiPpsId == pPpsList[i].iPpsId) { *ppPps = &pPpsList[i]; break; } else { ++i; } } if (i == iPpsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckPpsId()::::::CAN NOT find the matching from the PPS List. iPpsId:%d\n", uiPpsId); return dsNoParamSets; } return 0; } int32_t CheckSpsId (PWelsDecoderContext pCtx, PSubsetSps* ppSubsetSps, PSps* ppSps, int32_t iSpsId, bool_t bExtensionFlag) { PSps pSpsList = pCtx->sSpsBuffer; PSubsetSps pSubspsList = pCtx->sSubsetSpsBuffer; int32_t iSpsNum = pCtx->iSpsTotalNum; int32_t iSubspsNum = pCtx->iSubspsTotalNum; int32_t i = 0; if (bExtensionFlag) { if (iSubspsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SUBSPS list is empty....NO SUBSPS\n"); return dsNoParamSets; } while (i < iSubspsNum) { if (iSpsId == pSubspsList[i].sSps.iSpsId) { *ppSubsetSps = &pSubspsList[i]; *ppSps = &pSubspsList[i].sSps; break; } else { ++i; } } if (i == iSubspsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SUBSPS List. iSpsId:%d\n", iSpsId); return dsNoParamSets; } } else { if (iSpsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SPS list is empty....NO SPS\n"); return dsNoParamSets; } while (i < iSpsNum) { if (iSpsId == pSpsList[i].iSpsId) { *ppSubsetSps = NULL; *ppSps = &pSpsList[i]; break; } else { ++i; } } if (i == iSpsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SPS List. iSpsId:%d\n", iSpsId); return dsNoParamSets; } } return 0; } #endif /* * decode_slice_header_avc * Parse slice header of bitstream in avc for storing data structure */ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, const bool_t kbExtensionFlag) { PNalUnit const kpCurNal = pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiAvailUnitsNum - 1]; PNalUnitHeaderExt pNalHeaderExt = NULL; PSliceHeader pSliceHead = NULL; PSliceHeaderExt pSliceHeadExt = NULL; PSubsetSps pSubsetSps = NULL; PSps pSps = NULL; PPps pPps = NULL; ENalUnitType eNalType = static_cast<ENalUnitType> (0); int32_t iPpsId = 0; int32_t iRet = ERR_NONE; uint8_t uiSliceType = 0; uint8_t uiQualityId = BASE_QUALITY_ID; bool_t bIdrFlag = false; bool_t bSgChangeCycleInvolved = false; // involved slice group change cycle ? if (kpCurNal == NULL) { return ERR_INFO_OUT_OF_MEMORY; } pNalHeaderExt = &kpCurNal->sNalHeaderExt; pSliceHead = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; eNalType = pNalHeaderExt->sNalUnitHeader.eNalUnitType; pSliceHeadExt = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt; if (pSliceHeadExt) { SRefBasePicMarking sBaseMarking; const bool_t kbStoreRefBaseFlag = pSliceHeadExt->bStoreRefBasePicFlag; memcpy (&sBaseMarking, &pSliceHeadExt->sRefBasePicMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage memset (pSliceHeadExt, 0, sizeof (SSliceHeaderExt)); pSliceHeadExt->bStoreRefBasePicFlag = kbStoreRefBaseFlag; memcpy (&pSliceHeadExt->sRefBasePicMarking, &sBaseMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage } kpCurNal->sNalData.sVclNal.bSliceHeaderExtFlag = kbExtensionFlag; pSliceHead->iFirstMbInSlice = BsGetUe (pBs); uiSliceType = BsGetUe (pBs); if (uiSliceType > 9) { WelsLog (pCtx, WELS_LOG_WARNING, "slice type too large (%d) at first_mb(%d)\n", uiSliceType, pSliceHead->iFirstMbInSlice); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); } if (uiSliceType > 4) uiSliceType -= 5; if (kbExtensionFlag) { if (uiSliceType > 2) { WelsLog (pCtx, WELS_LOG_WARNING, "Invalid slice type(%d).\n", uiSliceType); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); } } pSliceHead->eSliceType = static_cast <ESliceType> (uiSliceType); iPpsId = BsGetUe (pBs); if (iPpsId >= MAX_PPS_COUNT) { WelsLog (pCtx, WELS_LOG_WARNING, "iPpsId out of range\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_PPS_ID_OVERFLOW); } #ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_ID if (CheckPpsId (pCtx, &pPps, iPpsId)) { return dsNoParamSets; } #else pPps = &pCtx->sPpsBuffer[iPpsId]; #endif //MOSAIC_AVOID_BASED_ON_SPS_PPS_ID if (pPps->uiNumSliceGroups == 0) { WelsLog (pCtx, WELS_LOG_WARNING, "non existing PPS referenced\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS); } if (pPps->iSpsId >= MAX_SPS_COUNT) { WelsLog (pCtx, WELS_LOG_WARNING, "iSpsId out of range\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_SPS_ID_OVERFLOW); } #ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_ID if (CheckSpsId (pCtx, &pSubsetSps, &pSps, pPps->iSpsId, kExtensionFlag)) { return dsNoParamSets; } #else if (kbExtensionFlag) { pSubsetSps = &pCtx->sSubsetSpsBuffer[pPps->iSpsId]; pSps = &pSubsetSps->sSps; } else { pSps = &pCtx->sSpsBuffer[pPps->iSpsId]; } pCtx->pSps = pSps; #endif //MOSAIC_AVOID_BASED_ON_SPS_PPS_ID pSliceHead->iPpsId = iPpsId; pSliceHead->iSpsId = pPps->iSpsId; pSliceHead->pPps = pPps; pSliceHead->pSps = pSps; pSliceHeadExt->pSubsetSps = pSubsetSps; bIdrFlag = (!kbExtensionFlag && eNalType == NAL_UNIT_CODED_SLICE_IDR) || (kbExtensionFlag && pNalHeaderExt->bIdrFlag); if (pSps->uiLog2MaxFrameNum == 0) { WelsLog (pCtx, WELS_LOG_WARNING, "non existing SPS referenced\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS); } pSliceHead->iFrameNum = BsGetBits (pBs, pSps->uiLog2MaxFrameNum); pSliceHead->bFieldPicFlag = false; pSliceHead->bBottomFiledFlag = false; if (!pSps->bFrameMbsOnlyFlag) { WelsLog (pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): frame_mbs_only_flag = %d not supported. \n", pSps->bFrameMbsOnlyFlag); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MBAFF); } pSliceHead->iMbWidth = pSps->iMbWidth; pSliceHead->iMbHeight = pSps->iMbHeight / (1 + pSliceHead->bFieldPicFlag); if (bIdrFlag) { if (pSliceHead->iFrameNum != 0) { WelsLog (pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(), invaild frame number: %d due to IDR frame introduced!\n", pSliceHead->iFrameNum); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FRAME_NUM); } pSliceHead->uiIdrPicId = BsGetUe (pBs); /* uiIdrPicId */ #ifdef LONG_TERM_REF pCtx->uiCurIdrPicId = pSliceHead->uiIdrPicId; #endif } pSliceHead->iDeltaPicOrderCntBottom = 0; pSliceHead->iDeltaPicOrderCnt[0] = pSliceHead->iDeltaPicOrderCnt[1] = 0; if (pSps->uiPocType == 0) { pSliceHead->iPicOrderCntLsb = BsGetBits (pBs, pSps->iLog2MaxPocLsb); if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) { pSliceHead->iDeltaPicOrderCntBottom = BsGetSe (pBs); } } else if (pSps->uiPocType == 1 && !pSps->bDeltaPicOrderAlwaysZeroFlag) { pSliceHead->iDeltaPicOrderCnt[0] = BsGetSe (pBs); if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) pSliceHead->iDeltaPicOrderCnt[1] = BsGetSe (pBs); } pSliceHead->iRedundantPicCnt = 0; if (pPps->bRedundantPicCntPresentFlag) { pSliceHead->iRedundantPicCnt = BsGetUe (pBs); } //set defaults, might be overriden a few line later pSliceHead->uiRefCount[0] = pPps->uiNumRefIdxL0Active; pSliceHead->uiRefCount[1] = pPps->uiNumRefIdxL1Active; if (kbExtensionFlag) { uiQualityId = pNalHeaderExt->uiQualityId; if (BASE_QUALITY_ID == uiQualityId && (EP_SLICE == uiSliceType || EB_SLICE == uiSliceType)) { const bool_t kbBipredFlag = (EB_SLICE == uiSliceType); if (kbBipredFlag) { WelsLog (pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): kbBipredFlag = 1 not supported.\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_BIPRED); } pSliceHead->bNumRefIdxActiveOverrideFlag = !!BsGetOneBit (pBs); if (pSliceHead->bNumRefIdxActiveOverrideFlag) { pSliceHead->uiRefCount[0] = 1 + BsGetUe (pBs); } } } else if (uiSliceType == P_SLICE || uiSliceType == SP_SLICE || uiSliceType == B_SLICE) { const bool_t kbBipredFlag = (B_SLICE == uiSliceType); if (kbBipredFlag) { WelsLog (pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): kbBipredFlag = 1 not supported.\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_BIPRED); } pSliceHead->bNumRefIdxActiveOverrideFlag = !!BsGetOneBit (pBs); if (pSliceHead->bNumRefIdxActiveOverrideFlag) { pSliceHead->uiRefCount[0] = 1 + BsGetUe (pBs); } } if (pSliceHead->uiRefCount[0] > MAX_REF_PIC_COUNT || pSliceHead->uiRefCount[1] > MAX_REF_PIC_COUNT) { WelsLog (pCtx, WELS_LOG_WARNING, "reference overflow\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_REF_COUNT_OVERFLOW); } if (BASE_QUALITY_ID == uiQualityId) { iRet = ParseRefPicListReordering (pBs, pSliceHead); if (iRet != ERR_NONE) { WelsLog (pCtx, WELS_LOG_WARNING, "invalid ref pPic list reordering syntaxs!\n"); return iRet; } if (kbExtensionFlag) { if (pNalHeaderExt->iNoInterLayerPredFlag || pNalHeaderExt->uiQualityId > 0) pSliceHeadExt->bBasePredWeightTableFlag = false; else pSliceHeadExt->bBasePredWeightTableFlag = true; } if (kpCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc != 0) { iRet = ParseDecRefPicMarking (pCtx, pBs, pSliceHead, pSps, bIdrFlag); if (iRet != ERR_NONE) { return iRet; } if (kbExtensionFlag && !pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { pSliceHeadExt->bStoreRefBasePicFlag = !!BsGetOneBit (pBs); if ((pNalHeaderExt->bUseRefBasePicFlag || pSliceHeadExt->bStoreRefBasePicFlag) && !bIdrFlag) { WelsLog (pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): bUseRefBasePicFlag or bStoreRefBasePicFlag = 1 not supported.\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP); } } } } if (pPps->bEntropyCodingModeFlag) { WelsLog (pCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): CABAC in Enhancement layer not supported.\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_CABAC_EL); } pSliceHead->iSliceQpDelta = BsGetSe (pBs); pSliceHead->iSliceQp = pPps->iPicInitQp + pSliceHead->iSliceQpDelta; if (pSliceHead->iSliceQp < 0 || pSliceHead->iSliceQp > 51) { WelsLog (pCtx, WELS_LOG_WARNING, "QP %d out of range\n", pSliceHead->iSliceQp); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_QP); } //FIXME qscale / qp ... stuff if (!kbExtensionFlag) { if (uiSliceType == SP_SLICE || uiSliceType == SI_SLICE) { WelsLog (pCtx, WELS_LOG_WARNING, "SP/SI not supported\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_SPSI); } } pSliceHead->uiDisableDeblockingFilterIdc = 0; pSliceHead->iSliceAlphaC0Offset = 0; pSliceHead->iSliceBetaOffset = 0; if (pPps->bDeblockingFilterControlPresentFlag) { pSliceHead->uiDisableDeblockingFilterIdc = BsGetUe (pBs); //refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20 if (pSliceHead->uiDisableDeblockingFilterIdc > 6) { WelsLog (pCtx, WELS_LOG_WARNING, "disable_deblock_filter_idc (%d) out of range [0, 6]\n", pSliceHead->uiDisableDeblockingFilterIdc); return ERR_INFO_INVALID_DBLOCKING_IDC; } if (pSliceHead->uiDisableDeblockingFilterIdc != 1) { pSliceHead->iSliceAlphaC0Offset = BsGetSe (pBs) << 1; // slice_alpha_c0_offset_div2 pSliceHead->iSliceBetaOffset = BsGetSe (pBs) << 1; // iSliceBetaOffset } } bSgChangeCycleInvolved = (pPps->uiNumSliceGroups > 1 && pPps->uiSliceGroupMapType >= 3 && pPps->uiSliceGroupMapType <= 5); if (kbExtensionFlag && bSgChangeCycleInvolved) bSgChangeCycleInvolved = (bSgChangeCycleInvolved && (uiQualityId == BASE_QUALITY_ID)); if (bSgChangeCycleInvolved) { if (pPps->uiSliceGroupChangeRate > 0) { const int32_t kiNumBits = (int32_t)WELS_CEIL (log (static_cast<double> (1 + pPps->uiPicSizeInMapUnits / pPps->uiSliceGroupChangeRate))); pSliceHead->iSliceGroupChangeCycle = BsGetBits (pBs, kiNumBits); // For FMO extra types } else pSliceHead->iSliceGroupChangeCycle = 0; } if (!kbExtensionFlag) { FillDefaultSliceHeaderExt (pSliceHeadExt, pNalHeaderExt); } else { /* Extra syntax elements newly introduced */ pSliceHeadExt->pSubsetSps = pSubsetSps; if (!pNalHeaderExt->iNoInterLayerPredFlag && BASE_QUALITY_ID == uiQualityId) { //the following should be deleted for CODE_CLEAN pSliceHeadExt->uiRefLayerDqId = BsGetUe (pBs); if (pSubsetSps->sSpsSvcExt.bInterLayerDeblockingFilterCtrlPresentFlag) { pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc = BsGetUe (pBs); //refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20 if (pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc > 6) { WelsLog (pCtx, WELS_LOG_WARNING, "disable_inter_layer_deblock_filter_idc (%d) out of range [0, 6]\n", pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc); return ERR_INFO_INVALID_DBLOCKING_IDC; } if (pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc != 1) { pSliceHeadExt->iInterLayerSliceAlphaC0Offset = BsGetSe (pBs) << 1; pSliceHeadExt->iInterLayerSliceBetaOffset = BsGetSe (pBs) << 1; } } pSliceHeadExt->uiRefLayerChromaPhaseXPlus1Flag = pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseXPlus1Flag; pSliceHeadExt->uiRefLayerChromaPhaseYPlus1 = pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseYPlus1; pSliceHeadExt->bConstrainedIntraResamplingFlag = !!BsGetOneBit (pBs); { SPosOffset pos; pos.iLeftOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iLeftOffset; pos.iTopOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iTopOffset * (2 - pSps->bFrameMbsOnlyFlag); pos.iRightOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iRightOffset; pos.iBottomOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iBottomOffset * (2 - pSps->bFrameMbsOnlyFlag); //memcpy(&pSliceHeadExt->sScaledRefLayer, &pos, sizeof(SPosOffset));//confirmed_safe_unsafe_usage pSliceHeadExt->iScaledRefLayerPicWidthInSampleLuma = (pSliceHead->iMbWidth << 4) - (pos.iLeftOffset + pos.iRightOffset); pSliceHeadExt->iScaledRefLayerPicHeightInSampleLuma = (pSliceHead->iMbHeight << 4) - (pos.iTopOffset + pos.iBottomOffset) / (1 + pSliceHead->bFieldPicFlag); } } else if (uiQualityId > BASE_QUALITY_ID) { WelsLog (pCtx, WELS_LOG_WARNING, "MGS not supported.\n"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS); pSliceHeadExt->uiRefLayerDqId = pNalHeaderExt->uiLayerDqId - 1; } else { pSliceHeadExt->uiRefLayerDqId = (uint8_t) - 1; } pSliceHeadExt->bSliceSkipFlag = false; pSliceHeadExt->bAdaptiveBaseModeFlag = false; pSliceHeadExt->bDefaultBaseModeFlag = false; pSliceHeadExt->bAdaptiveMotionPredFlag = false; pSliceHeadExt->bDefaultMotionPredFlag = false; pSliceHeadExt->bAdaptiveResidualPredFlag = false; pSliceHeadExt->bDefaultResidualPredFlag = false; if (pNalHeaderExt->iNoInterLayerPredFlag) pSliceHeadExt->bTCoeffLevelPredFlag = false; else pSliceHeadExt->bTCoeffLevelPredFlag = pSubsetSps->sSpsSvcExt.bSeqTCoeffLevelPredFlag; if (!pNalHeaderExt->iNoInterLayerPredFlag) { pSliceHeadExt->bSliceSkipFlag = !!BsGetOneBit (pBs); if (pSliceHeadExt->bSliceSkipFlag) { pSliceHeadExt->uiNumMbsInSlice = 1 + BsGetUe (pBs); } else { pSliceHeadExt->bAdaptiveBaseModeFlag = !!BsGetOneBit (pBs); if (!pSliceHeadExt->bAdaptiveBaseModeFlag) { pSliceHeadExt->bDefaultBaseModeFlag = !!BsGetOneBit (pBs); } if (!pSliceHeadExt->bDefaultBaseModeFlag) { pSliceHeadExt->bAdaptiveMotionPredFlag = !!BsGetOneBit (pBs); if (!pSliceHeadExt->bAdaptiveMotionPredFlag) pSliceHeadExt->bDefaultMotionPredFlag = !!BsGetOneBit (pBs); } pSliceHeadExt->bAdaptiveResidualPredFlag = !!BsGetOneBit (pBs); if (!pSliceHeadExt->bAdaptiveResidualPredFlag) { pSliceHeadExt->bDefaultResidualPredFlag = !!BsGetOneBit (pBs); } } if (pSubsetSps->sSpsSvcExt.bAdaptiveTCoeffLevelPredFlag) pSliceHeadExt->bTCoeffLevelPredFlag = !!BsGetOneBit (pBs); } if (!pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { pSliceHeadExt->uiScanIdxStart = BsGetBits (pBs, 4); pSliceHeadExt->uiScanIdxEnd = BsGetBits (pBs, 4); if (pSliceHeadExt->uiScanIdxStart != 0 || pSliceHeadExt->uiScanIdxEnd != 15) { WelsLog (pCtx, WELS_LOG_WARNING, "uiScanIdxStart (%d) != 0 and uiScanIdxEnd (%d) !=15 not supported here\n", pSliceHeadExt->uiScanIdxStart, pSliceHeadExt->uiScanIdxEnd); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS); } } else { pSliceHeadExt->uiScanIdxStart = 0; pSliceHeadExt->uiScanIdxEnd = 15; } } return ERR_NONE; } /* * Copy relative syntax elements of NALUnitHeaderExt, sRefPicBaseMarking and bStoreRefBasePicFlag in prefix nal unit. * pSrc: mark as decoded prefix NAL * ppDst: succeeded VCL NAL based AVC (I/P Slice) */ bool_t PrefetchNalHeaderExtSyntax (PWelsDecoderContext pCtx, PNalUnit const kppDst, PNalUnit const kpSrc) { PNalUnitHeaderExt pNalHdrExtD = NULL, pNalHdrExtS = NULL; PSliceHeaderExt pShExtD = NULL; PPrefixNalUnit pPrefixS = NULL; PSps pSps = NULL; int32_t iIdx = 0; if (kppDst == NULL || kpSrc == NULL) return false; pNalHdrExtD = &kppDst->sNalHeaderExt; pNalHdrExtS = &kpSrc->sNalHeaderExt; pShExtD = &kppDst->sNalData.sVclNal.sSliceHeaderExt; pPrefixS = &kpSrc->sNalData.sPrefixNal; pSps = &pCtx->sSpsBuffer[pCtx->sPpsBuffer[pShExtD->sSliceHeader.iPpsId].iSpsId]; pNalHdrExtD->uiDependencyId = pNalHdrExtS->uiDependencyId; pNalHdrExtD->uiQualityId = pNalHdrExtS->uiQualityId; pNalHdrExtD->uiTemporalId = pNalHdrExtS->uiTemporalId; pNalHdrExtD->uiPriorityId = pNalHdrExtS->uiPriorityId; pNalHdrExtD->bIdrFlag = pNalHdrExtS->bIdrFlag; pNalHdrExtD->iNoInterLayerPredFlag = pNalHdrExtS->iNoInterLayerPredFlag; pNalHdrExtD->bDiscardableFlag = pNalHdrExtS->bDiscardableFlag; pNalHdrExtD->bOutputFlag = pNalHdrExtS->bOutputFlag; pNalHdrExtD->bUseRefBasePicFlag = pNalHdrExtS->bUseRefBasePicFlag; pNalHdrExtD->uiLayerDqId = pNalHdrExtS->uiLayerDqId; pShExtD->bStoreRefBasePicFlag = pPrefixS->bStoreRefBasePicFlag; memcpy (&pShExtD->sRefBasePicMarking, &pPrefixS->sRefPicBaseMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage if (pShExtD->sRefBasePicMarking.bAdaptiveRefBasePicMarkingModeFlag) { PRefBasePicMarking pRefBasePicMarking = &pShExtD->sRefBasePicMarking; iIdx = 0; do { if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_END) break; if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_SHORT2UNUSED) pRefBasePicMarking->mmco_base[iIdx].iShortFrameNum = (pShExtD->sSliceHeader.iFrameNum - pRefBasePicMarking->mmco_base[iIdx].uiDiffOfPicNums) & ((1 << pSps->uiLog2MaxFrameNum) - 1); ++ iIdx; } while (iIdx < MAX_MMCO_COUNT); } return true; } int32_t UpdateAccessUnit (PWelsDecoderContext pCtx) { PAccessUnit pCurAu = pCtx->pAccessUnitList; int32_t iIdx = pCurAu->uiEndPos; // Conversed iterator pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iIdx]->sNalHeaderExt.uiLayerDqId; pCurAu->uiActualUnitsNum = iIdx + 1; pCurAu->bCompletedAuFlag = true; // Added for mosaic avoidance, 11/19/2009 #ifdef LONG_TERM_REF if (pCtx->bParamSetsLostFlag) #else if (pCtx->bReferenceLostAtT0Flag) #endif { uint32_t uiActualIdx = 0; while (uiActualIdx < pCurAu->uiActualUnitsNum) { PNalUnit nal = pCurAu->pNalUnitsList[uiActualIdx]; if (nal->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR || nal->sNalHeaderExt.bIdrFlag) { break; } ++ uiActualIdx; } if (uiActualIdx == pCurAu->uiActualUnitsNum) { // no found IDR nal within incoming AU, need exit to avoid mosaic issue, 11/19/2009 WelsLog (pCtx, WELS_LOG_WARNING, "UpdateAccessUnit():::::Key frame lost.....CAN NOT find IDR from current AU.\n"); #ifdef LONG_TERM_REF pCtx->iErrorCode |= dsNoParamSets; return dsNoParamSets; #else pCtx->iErrorCode |= dsRefLost; return ERR_INFO_REFERENCE_PIC_LOST; #endif } } return ERR_NONE; } int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWidth, const int32_t kiMaxHeight) { const int32_t kiPicStride = ((kiMaxWidth + 15) & 0xfffff0) + (PADDING_LENGTH << 1); const int32_t kiPicLines = ((kiMaxHeight + 15) & 0xfffff0); int32_t i = 0; WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiMaxWidth <= 0 || kiMaxHeight <= 0)) pCtx->sMb.iMbWidth = (kiMaxWidth + 15) >> 4; pCtx->sMb.iMbHeight = (kiMaxHeight + 15) >> 4; if (pCtx->bInitialDqLayersMem && kiMaxWidth <= pCtx->iPicWidthReq && kiMaxHeight <= pCtx->iPicHeightReq) // have same dimension memory, skipped return ERR_NONE; UninitialDqLayersContext (pCtx); do { PDqLayer pDq = (PDqLayer)WelsMalloc (sizeof (SDqLayer), "PDqLayer"); int32_t iPlaneIdx = 0; if (pDq == NULL) return ERR_INFO_OUT_OF_MEMORY; memset (pDq, 0, sizeof (SDqLayer)); if (pCtx->iDecoderMode == SW_MODE) { do { const int32_t kiHshift = iPlaneIdx ? 1 : 0; const int32_t kiVshift = kiHshift; const int32_t kiStride = WELS_ALIGN ((kiPicStride >> kiHshift), (16 << (1 - kiHshift))); const int32_t kiLine = (kiPicLines + (PADDING_LENGTH << 1)) >> kiVshift; const int32_t kiSize = kiStride * kiLine; pCtx->pCsListXchg[i][iPlaneIdx] = (uint8_t*)WelsMalloc (kiSize * sizeof (uint8_t), "pCtx->pCsListXchg[][]"); WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, (NULL == pCtx->pCsListXchg[i][iPlaneIdx])) pCtx->iCsStride[iPlaneIdx] = kiStride; pCtx->pRsListXchg[i][iPlaneIdx] = (int16_t*)WelsMalloc (kiSize * sizeof (int16_t), "pCtx->pRsListXchg[][]"); WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY , (NULL == pCtx->pRsListXchg[i][iPlaneIdx])) pCtx->iRsStride[iPlaneIdx] = kiStride; ++ iPlaneIdx; } while (iPlaneIdx < 3); pCtx->sMb.pMbType[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), "pCtx->sMb.pMbType[]"); pCtx->sMb.pMv[i][0] = (int16_t (*)[16][2])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMv[][]"); pCtx->sMb.pRefIndex[i][0] = (int8_t (*)[MB_BLOCK4x4_NUM])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pRefIndex[][]"); pCtx->sMb.pLumaQp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), "pCtx->sMb.pLumaQp[]"); pCtx->sMb.pChromaQp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), "pCtx->sMb.pChromaQp[]"); pCtx->sMb.pNzc[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24, "pCtx->sMb.pNzc[]"); pCtx->sMb.pNzcRs[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24, "pCtx->sMb.pNzcRs[]"); pCtx->sMb.pScaledTCoeff[i] = (int16_t (*)[MB_COEFF_LIST_SIZE])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int16_t) * MB_COEFF_LIST_SIZE, "pCtx->sMb.pScaledTCoeff[]"); pCtx->sMb.pIntraPredMode[i] = (int8_t (*)[8])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 8, "pCtx->sMb.pIntraPredMode[]"); pCtx->sMb.pIntra4x4FinalMode[i] = (int8_t (*)[MB_BLOCK4x4_NUM])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pIntra4x4FinalMode[]"); pCtx->sMb.pChromaPredMode[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), "pCtx->sMb.pChromaPredMode[]"); pCtx->sMb.pCbp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), "pCtx->sMb.pCbp[]"); pCtx->sMb.pSubMbType[i] = (int8_t (*)[MB_PARTITION_SIZE])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( int8_t) * MB_PARTITION_SIZE, "pCtx->sMb.pSubMbType[]"); pCtx->sMb.pSliceIdc[i] = (int32_t*) WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t), "pCtx->sMb.pSliceIdc[]"); // using int32_t for slice_idc, 4/21/2010 if (pCtx->sMb.pSliceIdc[i] != NULL) memset (pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t))); pCtx->sMb.pResidualPredFlag[i] = (int8_t*) WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), "pCtx->sMb.pResidualPredFlag[]"); //pCtx->sMb.pMotionPredFlag[i] = (uint8_t *) WelsMalloc(pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof(uint8_t), "pCtx->sMb.pMotionPredFlag[]"); pCtx->sMb.pInterPredictionDoneFlag[i] = (int8_t*) WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( int8_t), "pCtx->sMb.pInterPredictionDoneFlag[]"); // check memory block valid due above allocated.. WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ((NULL == pCtx->sMb.pMbType[i]) || (NULL == pCtx->sMb.pMv[i][0]) || (NULL == pCtx->sMb.pRefIndex[i][0]) || (NULL == pCtx->sMb.pLumaQp[i]) || (NULL == pCtx->sMb.pChromaQp[i]) || (NULL == pCtx->sMb.pNzc[i]) || (NULL == pCtx->sMb.pNzcRs[i]) || (NULL == pCtx->sMb.pScaledTCoeff[i]) || (NULL == pCtx->sMb.pIntraPredMode[i]) || (NULL == pCtx->sMb.pIntra4x4FinalMode[i]) || (NULL == pCtx->sMb.pChromaPredMode[i]) || (NULL == pCtx->sMb.pCbp[i]) || (NULL == pCtx->sMb.pSubMbType[i]) || (NULL == pCtx->sMb.pSliceIdc[i]) || (NULL == pCtx->sMb.pResidualPredFlag[i]) || (NULL == pCtx->sMb.pInterPredictionDoneFlag[i]) ) ) } // end of if(pCtx->iDecoderMode == SW_MODE) pCtx->pDqLayersList[i] = pDq; ++ i; } while (i < LAYER_NUM_EXCHANGEABLE); pCtx->bInitialDqLayersMem = true; pCtx->iPicWidthReq = kiMaxWidth; pCtx->iPicHeightReq = kiMaxHeight; return ERR_NONE; } void_t UninitialDqLayersContext (PWelsDecoderContext pCtx) { int32_t i = 0; int32_t j = 0; do { PDqLayer pDq = pCtx->pDqLayersList[i]; if (pDq == NULL) { ++ i; continue; } if (pCtx->pCsListXchg[i]) { // cs picture j = 0; do { if (NULL != pCtx->pCsListXchg[i][j]) { WelsFree (pCtx->pCsListXchg[i][j], "pCtx->pCsListXchg[][]"); pCtx->pCsListXchg[i][j] = NULL; } pCtx->iCsStride[j] = 0; ++ j; } while (j < 3); pDq->pCsData[i] = NULL; // for safe pDq->iCsStride[i] = 0; } if (pCtx->pRsListXchg[i]) { j = 0; do { if (NULL != pCtx->pRsListXchg[i][j]) { WelsFree (pCtx->pRsListXchg[i][j], "pCtx->pRsListXchg[][]"); pCtx->pRsListXchg[i][j] = NULL; } pCtx->iRsStride[j] = 0; ++ j; } while (j < 3); } if (pCtx->sMb.pMbType[i]) { WelsFree (pCtx->sMb.pMbType[i], "pCtx->sMb.pMbType[]"); pCtx->sMb.pMbType[i] = NULL; } if (pCtx->sMb.pMv[i][0]) { WelsFree (pCtx->sMb.pMv[i][0], "pCtx->sMb.pMv[][]"); pCtx->sMb.pMv[i][0] = NULL; } if (pCtx->sMb.pRefIndex[i][0]) { WelsFree (pCtx->sMb.pRefIndex[i][0], "pCtx->sMb.pRefIndex[][]"); pCtx->sMb.pRefIndex[i][0] = NULL; } if (pCtx->sMb.pLumaQp[i]) { WelsFree (pCtx->sMb.pLumaQp[i], "pCtx->sMb.pLumaQp[]"); pCtx->sMb.pLumaQp[i] = NULL; } if (pCtx->sMb.pChromaQp[i]) { WelsFree (pCtx->sMb.pChromaQp[i], "pCtx->sMb.pChromaQp[]"); pCtx->sMb.pChromaQp[i] = NULL; } if (pCtx->sMb.pNzc[i]) { WelsFree (pCtx->sMb.pNzc[i], "pCtx->sMb.pNzc[]"); pCtx->sMb.pNzc[i] = NULL; } if (pCtx->sMb.pNzcRs[i]) { WelsFree (pCtx->sMb.pNzcRs[i], "pCtx->sMb.pNzcRs[]"); pCtx->sMb.pNzcRs[i] = NULL; } if (pCtx->sMb.pScaledTCoeff[i]) { WelsFree (pCtx->sMb.pScaledTCoeff[i], "pCtx->sMb.pScaledTCoeff[]"); pCtx->sMb.pScaledTCoeff[i] = NULL; } if (pCtx->sMb.pIntraPredMode[i]) { WelsFree (pCtx->sMb.pIntraPredMode[i], "pCtx->sMb.pIntraPredMode[]"); pCtx->sMb.pIntraPredMode[i] = NULL; } if (pCtx->sMb.pIntra4x4FinalMode[i]) { WelsFree (pCtx->sMb.pIntra4x4FinalMode[i], "pCtx->sMb.pIntra4x4FinalMode[]"); pCtx->sMb.pIntra4x4FinalMode[i] = NULL; } if (pCtx->sMb.pChromaPredMode[i]) { WelsFree (pCtx->sMb.pChromaPredMode[i], "pCtx->sMb.pChromaPredMode[]"); pCtx->sMb.pChromaPredMode[i] = NULL; } if (pCtx->sMb.pCbp[i]) { WelsFree (pCtx->sMb.pCbp[i], "pCtx->sMb.pCbp[]"); pCtx->sMb.pCbp[i] = NULL; } // if (pCtx->sMb.pMotionPredFlag[i]) //{ // WelsFree( pCtx->sMb.pMotionPredFlag[i], "pCtx->sMb.pMotionPredFlag[]" ); // pCtx->sMb.pMotionPredFlag[i] = NULL; //} if (pCtx->sMb.pSubMbType[i]) { WelsFree (pCtx->sMb.pSubMbType[i], "pCtx->sMb.pSubMbType[]"); pCtx->sMb.pSubMbType[i] = NULL; } if (pCtx->sMb.pSliceIdc[i]) { WelsFree (pCtx->sMb.pSliceIdc[i], "pCtx->sMb.pSliceIdc[]"); pCtx->sMb.pSliceIdc[i] = NULL; } if (pCtx->sMb.pResidualPredFlag[i]) { WelsFree (pCtx->sMb.pResidualPredFlag[i], "pCtx->sMb.pResidualPredFlag[]"); pCtx->sMb.pResidualPredFlag[i] = NULL; } if (pCtx->sMb.pInterPredictionDoneFlag[i]) { WelsFree (pCtx->sMb.pInterPredictionDoneFlag[i], "pCtx->sMb.pInterPredictionDoneFlag[]"); pCtx->sMb.pInterPredictionDoneFlag[i] = NULL; } WelsFree (pDq, "pDq"); pDq = NULL; pCtx->pDqLayersList[i] = NULL; ++ i; } while (i < LAYER_NUM_EXCHANGEABLE); pCtx->iPicWidthReq = 0; pCtx->iPicHeightReq = 0; pCtx->bInitialDqLayersMem = false; } void_t ResetCurrentAccessUnit (PWelsDecoderContext pCtx) { PAccessUnit pCurAu = pCtx->pAccessUnitList; pCurAu->uiEndPos = 0; pCurAu->bCompletedAuFlag = false; if (pCurAu->uiActualUnitsNum > 0) { uint32_t iIdx = 0; const uint32_t kuiActualNum = pCurAu->uiActualUnitsNum; // a more simpler method to do nal units list management prefered here const uint32_t kuiAvailNum = pCurAu->uiAvailUnitsNum; const uint32_t kuiLeftNum = kuiAvailNum - kuiActualNum; // Swapping active nal unit nodes of succeeding AU with leading of list while (iIdx < kuiLeftNum) { PNalUnit t = pCurAu->pNalUnitsList[kuiActualNum + iIdx]; pCurAu->pNalUnitsList[kuiActualNum + iIdx] = pCurAu->pNalUnitsList[iIdx]; pCurAu->pNalUnitsList[iIdx] = t; ++ iIdx; } pCurAu->uiActualUnitsNum = pCurAu->uiAvailUnitsNum = kuiLeftNum; } } /*! * \brief Force reset current Acess Unit Nal list in case error parsing/decoding in current AU * \author * \history 11/16/2009 */ void_t ForceResetCurrentAccessUnit (PAccessUnit pAu) { uint32_t uiSucAuIdx = pAu->uiEndPos + 1; uint32_t uiCurAuIdx = 0; // swap the succeeding AU's nal units to the front while (uiSucAuIdx < pAu->uiAvailUnitsNum) { PNalUnit t = pAu->pNalUnitsList[uiSucAuIdx]; pAu->pNalUnitsList[uiSucAuIdx] = pAu->pNalUnitsList[uiCurAuIdx]; pAu->pNalUnitsList[uiCurAuIdx] = t; ++ uiSucAuIdx; ++ uiCurAuIdx; } // Update avail/actual units num accordingly for next AU parsing if (pAu->uiAvailUnitsNum > pAu->uiEndPos) pAu->uiAvailUnitsNum -= (pAu->uiEndPos + 1); else pAu->uiAvailUnitsNum = 0; pAu->uiActualUnitsNum = 0; pAu->uiEndPos = 0; pAu->bCompletedAuFlag = false; } //clear current corrupted NAL from pNalUnitsList void_t ForceClearCurrentNal (PAccessUnit pAu) { if (pAu->uiAvailUnitsNum > 0) -- pAu->uiAvailUnitsNum; } void_t CheckAvailNalUnitsListContinuity (PWelsDecoderContext pCtx, int32_t iStartIdx, int32_t iEndIdx) { PAccessUnit pCurAu = pCtx->pAccessUnitList; uint8_t uiLastNuDependencyId, uiLastNuLayerDqId; uint8_t uiCurNuDependencyId, uiCurNuQualityId, uiCurNuLayerDqId, uiCurNuRefLayerDqId; int32_t iCurNalUnitIdx = 0; //check the continuity of pNalUnitsList forwards (from pIdxNoInterLayerPred to end_postion) uiLastNuDependencyId = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiDependencyId;//starting nal unit uiLastNuLayerDqId = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiLayerDqId;//starting nal unit iCurNalUnitIdx = iStartIdx + 1;//current nal unit while (iCurNalUnitIdx <= iEndIdx) { uiCurNuDependencyId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiDependencyId; uiCurNuQualityId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiQualityId; uiCurNuLayerDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId; uiCurNuRefLayerDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalData.sVclNal.sSliceHeaderExt.uiRefLayerDqId; if (uiCurNuDependencyId == uiLastNuDependencyId) { uiLastNuLayerDqId = uiCurNuLayerDqId; ++ iCurNalUnitIdx; } else { //uiCurNuDependencyId != uiLastNuDependencyId, new dependency arrive if (uiCurNuQualityId == 0) { uiLastNuDependencyId = uiCurNuDependencyId; if (uiCurNuRefLayerDqId == uiLastNuLayerDqId) { uiLastNuLayerDqId = uiCurNuLayerDqId; ++ iCurNalUnitIdx; } else { //cur_nu_layer_id != next_nu_ref_layer_dq_id, the chain is broken at this point break; } } else { //new dependency arrive, but no base quality layer, so we must stop in this point break; } } } -- iCurNalUnitIdx; pCurAu->uiEndPos = iCurNalUnitIdx; pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId; } //main purpose: to support multi-slice and to include all slice which have the same uiDependencyId, uiQualityId and frame_num //for single slice, pIdxNoInterLayerPred SHOULD NOT be modified void_t RefineIdxNoInterLayerPred (PAccessUnit pCurAu, int32_t* pIdxNoInterLayerPred) { int32_t iLastNalDependId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiDependencyId; int32_t iLastNalQualityId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiQualityId; uint8_t uiLastNalTId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiTemporalId; int32_t iLastNalFrameNum = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum; int32_t iLastNalPoc = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; int32_t iLastNalFirstMb = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice; int32_t iCurNalDependId, iCurNalQualityId, iCurNalTId, iCurNalFrameNum, iCurNalPoc, iCurNalFirstMb, iCurIdx, iFinalIdxNoInterLayerPred; bool_t bMultiSliceFind = false; iFinalIdxNoInterLayerPred = 0; iCurIdx = *pIdxNoInterLayerPred - 1; while (iCurIdx >= 0) { if (pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.iNoInterLayerPredFlag) { iCurNalDependId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; iCurNalQualityId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; iCurNalTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; iCurNalFrameNum = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum; iCurNalPoc = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; iCurNalFirstMb = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice; if (iCurNalDependId == iLastNalDependId && iCurNalQualityId == iLastNalQualityId && iCurNalTId == uiLastNalTId && iCurNalFrameNum == iLastNalFrameNum && iCurNalPoc == iLastNalPoc && iCurNalFirstMb != iLastNalFirstMb) { bMultiSliceFind = true; iFinalIdxNoInterLayerPred = iCurIdx; --iCurIdx; continue; } else { break; } } --iCurIdx; } if (bMultiSliceFind && *pIdxNoInterLayerPred != iFinalIdxNoInterLayerPred) { *pIdxNoInterLayerPred = iFinalIdxNoInterLayerPred; } } bool_t CheckPocOfCurValidNalUnits (PAccessUnit pCurAu, int32_t pIdxNoInterLayerPred) { int32_t iEndIdx = pCurAu->uiEndPos; int32_t iCurAuPoc = pCurAu->pNalUnitsList[pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; int32_t iTmpPoc, i; for (i = pIdxNoInterLayerPred + 1; i < iEndIdx; i++) { iTmpPoc = pCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; if (iTmpPoc != iCurAuPoc) { return false; } } return true; } bool_t CheckIntegrityNalUnitsList (PWelsDecoderContext pCtx) { PAccessUnit pCurAu = pCtx->pAccessUnitList; const int32_t kiEndPos = pCurAu->uiEndPos; int32_t iIdxNoInterLayerPred = 0; int32_t iCurNalUnitIdx = kiEndPos; ESliceType eSliceType = static_cast<ESliceType> (0);//EC 2009.11.12 if (!pCurAu->bCompletedAuFlag) return false; eSliceType = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.eSliceType; if (I_SLICE == eSliceType) { pCurAu->uiStartPos = 0; //step1: search the pNalUnit whose iNoInterLayerPredFlag equal to 1 backwards (from uiEndPos to 0) iIdxNoInterLayerPred = kiEndPos; while (iIdxNoInterLayerPred >= 0) { if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { break; } --iIdxNoInterLayerPred; } if (iIdxNoInterLayerPred < 0) { //can not find the Nal Unit whose no_inter_pred_falg equal to 1, MUST STOP decode return false; } //step2: support multi-slice, to include all base layer slice RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); pCurAu->uiStartPos = iIdxNoInterLayerPred; CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { return false; } pCtx->iCurSeqIntervalTargetDependId = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalHeaderExt.uiDependencyId; pCtx->iCurSeqIntervalMaxPicWidth = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbWidth << 4; pCtx->iCurSeqIntervalMaxPicHeight = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbHeight << 4; } else { //P_SLICE //step 1: search uiDependencyId equal to pCtx->cur_seq_interval_target_dependency_id bool_t bGetDependId = false; int32_t iIdxDependId = 0; iIdxDependId = kiEndPos; while (iIdxDependId >= 0) { if (pCtx->iCurSeqIntervalTargetDependId == pCurAu->pNalUnitsList[iIdxDependId]->sNalHeaderExt.uiDependencyId) { bGetDependId = true; break; } else { --iIdxDependId; } } //step 2: switch according to whether or not find the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId if (bGetDependId) { //get the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId bool_t bGetNoInterPredFront = false; //step 2a: search iNoInterLayerPredFlag [0....iIdxDependId] iIdxNoInterLayerPred = iIdxDependId; while (iIdxNoInterLayerPred >= 0) { if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { bGetNoInterPredFront = true; break; } --iIdxNoInterLayerPred; } //step 2b: switch, whether or not find the NAL unit whose no_inter_pred_flag equal to 1 among [0....iIdxDependId] if (bGetNoInterPredFront) { //YES RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); pCurAu->uiStartPos = iIdxNoInterLayerPred; CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, iIdxDependId); if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { return false; } } else { //NO, should find the NAL unit whose no_inter_pred_flag equal to 1 among [iIdxDependId....uiEndPos] iIdxNoInterLayerPred = iIdxDependId; while (iIdxNoInterLayerPred <= kiEndPos) { if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { break; } ++iIdxNoInterLayerPred; } if (iIdxNoInterLayerPred > kiEndPos) { return false; //cann't find the index of pNalUnit whose no_inter_pred_flag = 1 } RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); pCurAu->uiStartPos = iIdxNoInterLayerPred; CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { return false; } } } else { //without the index of pNalUnit, should process this AU as common case iIdxNoInterLayerPred = kiEndPos; while (iIdxNoInterLayerPred >= 0) { if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { break; } --iIdxNoInterLayerPred; } if (iIdxNoInterLayerPred < 0) { return false; //cann't find the index of pNalUnit whose iNoInterLayerPredFlag = 1 } RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); pCurAu->uiStartPos = iIdxNoInterLayerPred; CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { return false; } } } return true; } void_t CheckOnlyOneLayerInAu (PWelsDecoderContext pCtx) { PAccessUnit pCurAu = pCtx->pAccessUnitList; int32_t iEndIdx = pCurAu->uiEndPos; int32_t iCurIdx = pCurAu->uiStartPos; uint8_t uiDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; uint8_t uiQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; uint8_t uiTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; uint8_t uiCurDId, uiCurQId, uiCurTId; pCtx->bOnlyOneLayerInCurAuFlag = true; if (iEndIdx == iCurIdx) { //only one NAL in pNalUnitsList return; } ++iCurIdx; while (iCurIdx <= iEndIdx) { uiCurDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; uiCurQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; uiCurTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; if (uiDId != uiCurDId || uiQId != uiCurQId || uiTId != uiCurTId) { pCtx->bOnlyOneLayerInCurAuFlag = false; return; } ++iCurIdx; } } int32_t WelsDecodeAccessUnitStart (PWelsDecoderContext pCtx) { // Roll back NAL units not being belong to current access unit list for proceeded access unit int32_t iRet = UpdateAccessUnit (pCtx); if (iRet != ERR_NONE) return iRet; pCtx->pAccessUnitList->uiStartPos = 0; if (!pCtx->bAvcBasedFlag && !CheckIntegrityNalUnitsList (pCtx)) { pCtx->iErrorCode |= dsBitstreamError; return dsBitstreamError; } //check current AU has only one layer or not //If YES, can use deblocking based on AVC if (!pCtx->bAvcBasedFlag) { CheckOnlyOneLayerInAu (pCtx); } return ERR_NONE; } void_t WelsDecodeAccessUnitEnd (PWelsDecoderContext pCtx) { // uninitialize context of current access unit and rbsp buffer clean ResetCurrentAccessUnit (pCtx); } int32_t CheckBSBound (int32_t iWidth, int32_t iHeight, int32_t sliceNum, int32_t ppsId) { int32_t iRet = 0; #if defined(_WIN32) iRet = ((iWidth == 80) && (iHeight = 45) && (sliceNum < 60)); #elif defined(MACOS) iRet = ((iWidth == 80) && (iHeight = 45) && (ppsId < 57)); #elif defined(ANDROID) iRet = ((iWidth == 40) && (iHeight = 22)); #endif return iRet; } /* * ConstructAccessUnit * construct an access unit for given input bitstream, maybe partial NAL Unit, one or more Units are involved to * joint a collective access unit. * parameter\ * buf: bitstream data buffer * bit_len: size in bit length of data * buf_len: size in byte length of data * coded_au: mark an Access Unit decoding finished * return: * 0 - success; otherwise returned error_no defined in error_no.h */ int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { int32_t iErr; int32_t iWidth; int32_t iHeight; int32_t iStride[2] = { 0 }; PAccessUnit pCurAu = pCtx->pAccessUnitList; pCtx->bAuReadyFlag = false; pCtx->bLastHasMmco5 = false; iErr = WelsDecodeAccessUnitStart (pCtx); GetVclNalTemporalId (pCtx); if (ERR_NONE != iErr) { ForceResetCurrentAccessUnit (pCtx->pAccessUnitList); pDstInfo->iBufferStatus = 0; return iErr; } pCtx->pSps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps; pCtx->pPps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pPps; //try to allocate or relocate DPB memory only when IDR arrival. if (NAL_UNIT_CODED_SLICE_IDR == pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalHeaderExt.sNalUnitHeader.eNalUnitType || pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalHeaderExt.bIdrFlag) { WelsResetRefPic (pCtx); //clear ref pPic when IDR NAL iErr = SyncPictureResolutionExt (pCtx, (pCtx->iMaxWidthInSps + 15) >> 4, (pCtx->iMaxHeightInSps + 15) >> 4); if (ERR_NONE != iErr) { WelsLog (pCtx, WELS_LOG_WARNING, "sync picture resolution ext failed, the error is %d", iErr); return iErr; } } pDstInfo->eBufferProperty = (EBufferProperty)pCtx->iDecoderOutputProperty; iErr = DecodeCurrentAccessUnit (pCtx, ppDst, iStride, &iWidth, &iHeight, pDstInfo); WelsDecodeAccessUnitEnd (pCtx); if (ERR_NONE != iErr) { WelsLog (pCtx, WELS_LOG_INFO, "returned error from decoding:[0x%x]\n", iErr); pDstInfo->iBufferStatus = 0; return iErr; } return 0; } static inline void_t InitDqLayerInfo (PDqLayer pDqLayer, PLayerInfo pLayerInfo, PNalUnit pNalUnit, PPicture pPicDec) { PNalUnitHeaderExt pNalHdrExt = &pNalUnit->sNalHeaderExt; PSliceHeaderExt pShExt = &pNalUnit->sNalData.sVclNal.sSliceHeaderExt; PSliceHeader pSh = &pShExt->sSliceHeader; const uint8_t kuiQualityId = pNalHdrExt->uiQualityId; memcpy (&pDqLayer->sLayerInfo, pLayerInfo, sizeof (SLayerInfo)); //confirmed_safe_unsafe_usage pDqLayer->pDec = pPicDec; pDqLayer->iMbWidth = pSh->iMbWidth; // MB width of this picture pDqLayer->iMbHeight = pSh->iMbHeight;// MB height of this picture pDqLayer->iSliceIdcBackup = (pSh->iFirstMbInSlice << 7) | (pNalHdrExt->uiDependencyId << 4) | (pNalHdrExt->uiQualityId); /* Common syntax elements across all slices of a DQLayer */ pDqLayer->uiPpsId = pLayerInfo->pPps->iPpsId; pDqLayer->uiDisableInterLayerDeblockingFilterIdc = pShExt->uiDisableInterLayerDeblockingFilterIdc; pDqLayer->iInterLayerSliceAlphaC0Offset = pShExt->iInterLayerSliceAlphaC0Offset; pDqLayer->iInterLayerSliceBetaOffset = pShExt->iInterLayerSliceBetaOffset; pDqLayer->iSliceGroupChangeCycle = pSh->iSliceGroupChangeCycle; pDqLayer->bStoreRefBasePicFlag = pShExt->bStoreRefBasePicFlag; pDqLayer->bTCoeffLevelPredFlag = pShExt->bTCoeffLevelPredFlag; pDqLayer->bConstrainedIntraResamplingFlag = pShExt->bConstrainedIntraResamplingFlag; pDqLayer->uiRefLayerDqId = pShExt->uiRefLayerDqId; pDqLayer->uiRefLayerChromaPhaseXPlus1Flag = pShExt->uiRefLayerChromaPhaseXPlus1Flag; pDqLayer->uiRefLayerChromaPhaseYPlus1 = pShExt->uiRefLayerChromaPhaseYPlus1; //memcpy(&pDqLayer->sScaledRefLayer, &pShExt->sScaledRefLayer, sizeof(SPosOffset));//confirmed_safe_unsafe_usage if (kuiQualityId == BASE_QUALITY_ID) { pDqLayer->pRefPicListReordering = &pSh->pRefPicListReordering; pDqLayer->pRefPicMarking = &pSh->sRefMarking; pDqLayer->pRefPicBaseMarking = &pShExt->sRefBasePicMarking; } pDqLayer->uiLayerDqId = pNalHdrExt->uiLayerDqId; // dq_id of current layer pDqLayer->bUseRefBasePicFlag = pNalHdrExt->bUseRefBasePicFlag; } void_t WelsDqLayerDecodeStart (PWelsDecoderContext pCtx, PNalUnit pCurNal, PSps pSps, PPps pPps) { SNalUnitHeader* pNalHdr = &pCurNal->sNalHeaderExt.sNalUnitHeader; PSliceHeader pSh = &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; pCtx->eSliceType = pSh->eSliceType; pCtx->pSliceHeader = pSh; pCtx->iFrameNum = pSh->iFrameNum; if ((pNalHdr->eNalUnitType == NAL_UNIT_CODED_SLICE_IDR || (pCurNal->sNalHeaderExt.uiQualityId == BASE_QUALITY_ID && pCurNal->sNalHeaderExt.bIdrFlag)) && pSh->iFrameNum == 0) { //pSh->iFrameNum == 0 this condition can deleted?????? WelsResetRefPic (pCtx); // Reset decoded picture buffer lists due to an IDR frame incomes } } int32_t InitRefPicList (PWelsDecoderContext pCtx, const uint8_t kuiNRi, const bool_t kbFirstSlice, int32_t iPoc) { int32_t iRet = ERR_NONE; if (kbFirstSlice) iRet = WelsInitRefList (pCtx, iPoc); if ((pCtx->eSliceType != I_SLICE && pCtx->eSliceType != SI_SLICE) && kbFirstSlice) { iRet = WelsReorderRefList (pCtx); } return iRet; } void_t InitCurDqLayerData (PWelsDecoderContext pCtx, PDqLayer pCurDq) { if (NULL != pCtx && NULL != pCurDq) { pCurDq->pCsData[0] = pCtx->pCsListXchg[0][0]; pCurDq->pCsData[1] = pCtx->pCsListXchg[0][1]; pCurDq->pCsData[2] = pCtx->pCsListXchg[0][2]; pCurDq->iCsStride[0] = pCtx->iCsStride[0]; pCurDq->iCsStride[1] = pCtx->iCsStride[1]; pCurDq->iCsStride[2] = pCtx->iCsStride[2]; pCurDq->pMbType = pCtx->sMb.pMbType[0]; pCurDq->pSliceIdc = pCtx->sMb.pSliceIdc[0]; pCurDq->pMv[0] = pCtx->sMb.pMv[0][0]; pCurDq->pRefIndex[0] = pCtx->sMb.pRefIndex[0][0]; pCurDq->pLumaQp = pCtx->sMb.pLumaQp[0]; pCurDq->pChromaQp = pCtx->sMb.pChromaQp[0]; pCurDq->pNzc = pCtx->sMb.pNzc[0]; pCurDq->pNzcRs = pCtx->sMb.pNzcRs[0]; pCurDq->pScaledTCoeff = pCtx->sMb.pScaledTCoeff[0]; pCurDq->pIntraPredMode = pCtx->sMb.pIntraPredMode[0]; pCurDq->pIntra4x4FinalMode = pCtx->sMb.pIntra4x4FinalMode[0]; pCurDq->pChromaPredMode = pCtx->sMb.pChromaPredMode[0]; pCurDq->pCbp = pCtx->sMb.pCbp[0]; pCurDq->pSubMbType = pCtx->sMb.pSubMbType[0]; pCurDq->pInterPredictionDoneFlag = pCtx->sMb.pInterPredictionDoneFlag[0]; pCurDq->pResidualPredFlag = pCtx->sMb.pResidualPredFlag[0]; } } // added to reset state of parameter sets to waiting successive incoming IDR, 6/4/2010 // It will be called in case packets lost/ broken and decoded failed at temporal level 0 void_t ResetParameterSetsState (PWelsDecoderContext pCtx) { pCtx->bSpsExistAheadFlag = false; pCtx->bSubspsExistAheadFlag = false; pCtx->bPpsExistAheadFlag = false; } /* * DecodeCurrentAccessUnit * Decode current access unit when current AU is completed. */ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, int32_t* pDstLen, int32_t* pWidth, int32_t* pHeight, SBufferInfo* pDstInfo) { int32_t iRefCount[LIST_A]; PNalUnit pNalCur = NULL; PAccessUnit pCurAu = pCtx->pAccessUnitList; int32_t iIdx = pCurAu->uiStartPos; int32_t iEndIdx = pCurAu->uiEndPos; int32_t iPpsId = 0; int32_t iRet = ERR_NONE; const uint8_t kuiTargetLayerDqId = GetTargetDqId (pCtx->uiTargetDqId, pCtx->pParam); const uint8_t kuiDependencyIdMax = (kuiTargetLayerDqId & 0x7F) >> 4; int16_t iLastIdD = -1, iLastIdQ = -1; int16_t iCurrIdD = 0, iCurrIdQ = 0; uint8_t uiNalRefIdc = 0; bool_t bFreshSliceAvailable = true; // Another fresh slice comingup for given dq layer, for multiple slices in case of header parts of slices sometimes loss over error-prone channels, 8/14/2008 PPicture pStoreBasePic = NULL; //update pCurDqLayer at the starting of AU decoding if (pCtx->bInitialDqLayersMem) { pCtx->pCurDqLayer = pCtx->pDqLayersList[0]; } InitCurDqLayerData (pCtx, pCtx->pCurDqLayer); pNalCur = pCurAu->pNalUnitsList[iIdx]; while (iIdx <= iEndIdx) { PDqLayer dq_cur = pCtx->pCurDqLayer; SLayerInfo pLayerInfo; PSliceHeaderExt pShExt = NULL; PSliceHeader pSh = NULL; if (pCtx->pDec == NULL) { pCtx->pDec = PrefetchPic (pCtx->pPicBuff[0]); if (NULL == pCtx->pDec) { WelsLog (pCtx, WELS_LOG_ERROR, "DecodeCurrentAccessUnit()::::::PrefetchPic ERROR, pSps->iNumRefFrames:%d.\n", pCtx->pSps->iNumRefFrames); pCtx->iErrorCode |= dsOutOfMemory; return ERR_INFO_REF_COUNT_OVERFLOW; } } #ifdef NO_WAITING_AU //For fixing the nal lossing issue if ((pCtx->pDec->iTotalNumMbRec != 0) && (CheckAccessUnitBoundaryExt (&pCtx->sLastNalHdrExt, &pNalCur->sNalHeaderExt, &pCtx->sLastSliceHeader, &pNalCur->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader))) { pCtx->pDec->iTotalNumMbRec = 0; } #else //initialize at the starting of AU. pCtx->pDec->iTotalNumMbRec = 0; #endif if (pCtx->pDec->iTotalNumMbRec == 0) { //Picture start to decode for (int32_t i = 0; i < LAYER_NUM_EXCHANGEABLE; ++ i) memset (pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t))); } GetI4LumaIChromaAddrTable (pCtx->iDecBlockOffsetArray, pCtx->pDec->iLinesize[0], pCtx->pDec->iLinesize[1]); if (pNalCur->sNalHeaderExt.uiLayerDqId > kuiTargetLayerDqId) { break; // Per formance it need not to decode the remaining bits any more due to given uiLayerDqId required, 9/2/2009 } memset (&pLayerInfo, 0, sizeof (SLayerInfo)); /* * Loop decoding for slices (even FMO and/ multiple slices) within a dq layer */ while (iIdx <= iEndIdx) { BOOL_T bReconstructSlice; iCurrIdQ = pNalCur->sNalHeaderExt.uiQualityId; iCurrIdD = pNalCur->sNalHeaderExt.uiDependencyId; pSh = &pNalCur->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; pShExt = &pNalCur->sNalData.sVclNal.sSliceHeaderExt; bReconstructSlice = CheckSliceNeedReconstruct (iCurrIdD, iCurrIdQ, pShExt->bStoreRefBasePicFlag, kuiDependencyIdMax, pNalCur->sNalHeaderExt.uiLayerDqId, kuiTargetLayerDqId); memcpy (&pLayerInfo.sNalHeaderExt, &pNalCur->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); //confirmed_safe_unsafe_usage pCtx->pDec->iFrameNum = pSh->iFrameNum; memcpy (&pLayerInfo.sSliceInLayer.sSliceHeaderExt, pShExt, sizeof (SSliceHeaderExt)); //confirmed_safe_unsafe_usage pLayerInfo.sSliceInLayer.bSliceHeaderExtFlag = pNalCur->sNalData.sVclNal.bSliceHeaderExtFlag; pLayerInfo.sSliceInLayer.eSliceType = pSh->eSliceType; pLayerInfo.sSliceInLayer.iLastMbQp = pSh->iSliceQp; dq_cur->pBitStringAux = &pNalCur->sNalData.sVclNal.sSliceBitsRead; uiNalRefIdc = pNalCur->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc; iPpsId = pSh->iPpsId; pLayerInfo.pPps = pSh->pPps; pLayerInfo.pSps = pSh->pSps; pLayerInfo.pSubsetSps = pShExt->pSubsetSps; pCtx->pFmo = &pCtx->sFmoList[iPpsId]; if (!FmoParamUpdate (pCtx->pFmo, pLayerInfo.pSps, pLayerInfo.pPps, &pCtx->iActiveFmoNum)) { pCtx->iErrorCode |= dsBitstreamError; WelsLog (pCtx, WELS_LOG_WARNING, "DecodeCurrentAccessUnit(), FmoParamUpdate failed, eSliceType: %d.\n", pSh->eSliceType); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_FMO_INIT_FAIL); } bFreshSliceAvailable = (iCurrIdD != iLastIdD || iCurrIdQ != iLastIdQ); // do not need condition of (first_mb == 0) due multiple slices might be disorder WelsDqLayerDecodeStart (pCtx, pNalCur, pLayerInfo.pSps, pLayerInfo.pPps); if (iCurrIdQ == BASE_QUALITY_ID) { ST64 (iRefCount, LD64 (pLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiRefCount)); } if ((iLastIdD < 0) || //case 1: first layer (iLastIdD == iCurrIdD)) { //case 2: same uiDId InitDqLayerInfo (dq_cur, &pLayerInfo, pNalCur, pCtx->pDec); if (!dq_cur->sLayerInfo.pSps->bGapsInFrameNumValueAllowedFlag) { const bool_t kbIdrFlag = dq_cur->sLayerInfo.sNalHeaderExt.bIdrFlag || (dq_cur->sLayerInfo.sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR); // Subclause 8.2.5.2 Decoding process for gaps in frame_num if (!kbIdrFlag && pSh->iFrameNum != pCtx->iPrevFrameNum && pSh->iFrameNum != ((pCtx->iPrevFrameNum + 1) & ((1 << dq_cur->sLayerInfo.pSps->uiLog2MaxFrameNum) - 1))) { WelsLog (pCtx, WELS_LOG_WARNING, "referencing pictures lost due frame gaps exist, prev_frame_num: %d, curr_frame_num: %d\n", pCtx->iPrevFrameNum, pSh->iFrameNum); #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif ResetParameterSetsState (pCtx); pCtx->iErrorCode |= dsRefLost; return ERR_INFO_REFERENCE_PIC_LOST; } } if (iCurrIdD == kuiDependencyIdMax && iCurrIdQ == BASE_QUALITY_ID) { iRet = InitRefPicList (pCtx, uiNalRefIdc, bFreshSliceAvailable, pSh->iPicOrderCntLsb); if (iRet) { HandleReferenceLost (pCtx, pNalCur); WelsLog (pCtx, WELS_LOG_WARNING, "reference picture introduced by this frame is lost during transmission! uiTId: %d\n", pNalCur->sNalHeaderExt.uiTemporalId); return iRet; } } iRet = WelsDecodeSlice (pCtx, bFreshSliceAvailable, pNalCur); //Output good store_base reconstruction when enhancement quality layer occurred error for MGS key picture case if (iRet != ERR_NONE) { WelsLog (pCtx, WELS_LOG_WARNING, "DecodeCurrentAccessUnit() failed (%d) in frame: %d uiDId: %d uiQId: %d\n", iRet, pSh->iFrameNum, iCurrIdD, iCurrIdQ); HandleReferenceLostL0 (pCtx, pNalCur); return iRet; } if (bReconstructSlice) { if (WelsDecodeConstructSlice (pCtx, pNalCur)) { return -1; } } } #if defined (_DEBUG) && !defined (CODEC_FOR_TESTBED) fprintf (stderr, "cur_frame : %d iCurrIdD : %d\n ", dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFrameNum, iCurrIdD); #endif//#if !CODEC_FOR_TESTBED iLastIdD = iCurrIdD; iLastIdQ = iCurrIdQ; //pNalUnitsList overflow. ++ iIdx; if (iIdx <= iEndIdx) { pNalCur = pCurAu->pNalUnitsList[iIdx]; } else { pNalCur = NULL; } if (pNalCur == NULL || iLastIdD != pNalCur->sNalHeaderExt.uiDependencyId || iLastIdQ != pNalCur->sNalHeaderExt.uiQualityId) break; } // A dq layer decoded here #if defined (_DEBUG) && !defined (CODEC_FOR_TESTBED) #undef fprintf fprintf (stderr, "POC: #%d, FRAME: #%d, D: %d, Q: %d, T: %d, P: %d, %d\n", pSh->iPicOrderCntLsb, pSh->iFrameNum, iCurrIdD, iCurrIdQ, dq_cur->sLayerInfo.sNalHeaderExt.uiTemporalId, dq_cur->sLayerInfo.sNalHeaderExt.uiPriorityId, dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceQp); #endif//#if !CODEC_FOR_TESTBED if (dq_cur->uiLayerDqId == kuiTargetLayerDqId) { if (DecodeFrameConstruction (pCtx, ppDst, pDstLen, pWidth, pHeight, pDstInfo)) { #ifdef NO_WAITING_AU memcpy (&pCtx->sLastNalHdrExt, &pCurAu->pNalUnitsList[iIdx - 1]->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); memcpy (&pCtx->sLastSliceHeader, &pCurAu->pNalUnitsList[iIdx - 1]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader, sizeof (SSliceHeader)); return ERR_NONE; #else pCtx->iErrorCode |= dsBitstreamError; return -1; #endif } if ((uiNalRefIdc > 0) && (iCurrIdQ || (!dq_cur->bStoreRefBasePicFlag))) { WelsMarkAsRef (pCtx, false); ExpandReferencingPicture (pCtx->pDec, pCtx->sExpandPicFunc.pExpandLumaPicture, pCtx->sExpandPicFunc.pExpandChromaPicture); pCtx->pDec = NULL; } } if ((iCurrIdD == kuiDependencyIdMax) && (iCurrIdQ == BASE_QUALITY_ID) && (dq_cur->bStoreRefBasePicFlag)) { pStoreBasePic = pCtx->pDec; if (uiNalRefIdc > 0) { WelsMarkAsRef (pCtx, true); ExpandReferencingPicture (pCtx->pDec, pCtx->sExpandPicFunc.pExpandLumaPicture, pCtx->sExpandPicFunc.pExpandChromaPicture); pCtx->pDec = NULL; } } // need update frame_num due current frame is well decoded pCtx->iPrevFrameNum = pSh->iFrameNum; if (pCtx->bLastHasMmco5) pCtx->iPrevFrameNum = 0; } return ERR_NONE; } } // namespace WelsDec