Showing the changes to codec/decoder/core/src/decoder_core.cpp (1 of 55 files). Show all
Unified · Split
| @@ -1,2639 +1,2772 @@ | ||
| 1 | −/*! | |
| 2 | − * \copy | |
| 3 | − * Copyright (c) 2013, Cisco Systems | |
| 4 | − * All rights reserved. | |
| 5 | − * | |
| 6 | − * Redistribution and use in source and binary forms, with or without | |
| 7 | − * modification, are permitted provided that the following conditions | |
| 8 | − * are met: | |
| 9 | − * | |
| 10 | − * * Redistributions of source code must retain the above copyright | |
| 11 | − * notice, this list of conditions and the following disclaimer. | |
| 12 | − * | |
| 13 | − * * Redistributions in binary form must reproduce the above copyright | |
| 14 | − * notice, this list of conditions and the following disclaimer in | |
| 15 | − * the documentation and/or other materials provided with the | |
| 16 | − * distribution. | |
| 17 | − * | |
| 18 | − * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 | − * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 | − * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 21 | − * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 22 | − * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 23 | − * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 24 | − * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 25 | − * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| 26 | − * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 27 | − * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
| 28 | − * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 29 | − * POSSIBILITY OF SUCH DAMAGE. | |
| 30 | − * | |
| 31 | − * decoder_core.c: Wels decoder framework core implementation | |
| 32 | − */ | |
| 33 | − | |
| 34 | −#include "decoder_core.h" | |
| 35 | −#include "error_code.h" | |
| 36 | −#include "memmgr_nal_unit.h" | |
| 37 | −#include "au_parser.h" | |
| 38 | −#include "decode_slice.h" | |
| 39 | −#include "manage_dec_ref.h" | |
| 40 | −#include "expand_pic.h" | |
| 41 | −#include "decoder.h" | |
| 42 | −#include "decode_mb_aux.h" | |
| 43 | −#include "memory_align.h" | |
| 44 | −#include "error_concealment.h" | |
| 45 | − | |
| 46 | −namespace WelsDec { | |
| 47 | −static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { | |
| 48 | − PDqLayer pCurDq = pCtx->pCurDqLayer; | |
| 49 | − PPicture pPic = pCtx->pDec; | |
| 50 | − | |
| 51 | − const int32_t kiWidth = pCurDq->iMbWidth << 4; | |
| 52 | − const int32_t kiHeight = pCurDq->iMbHeight << 4; | |
| 53 | − | |
| 54 | − const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight; | |
| 55 | − bool bFrameCompleteFlag = true; | |
| 56 | − | |
| 57 | − if (pPic->bNewSeqBegin) { | |
| 58 | − memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), | |
| 59 | − sizeof (SPosOffset)); //confirmed_safe_unsafe_usage | |
| 60 | −#ifdef LONG_TERM_REF | |
| 61 | − pCtx->bParamSetsLostFlag = false; | |
| 62 | −#else | |
| 63 | − pCtx->bReferenceLostAtT0Flag = false; // need initialize it due new seq, 6/4/2010 | |
| 64 | −#endif //LONG_TERM_REF | |
| 65 | − if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { | |
| 66 | − pCtx->bPrintFrameErrorTraceFlag = true; | |
| 67 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 68 | − "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.", | |
| 69 | − kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, | |
| 70 | − pCtx->sFrameCrop.iBottomOffset, pCtx->iIgnoredErrorInfoPacketCount); | |
| 71 | − pCtx->iIgnoredErrorInfoPacketCount = 0; | |
| 72 | − } | |
| 73 | − } | |
| 74 | − | |
| 75 | − const int32_t kiActualWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; | |
| 76 | − const int32_t kiActualHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; | |
| 77 | − | |
| 78 | − | |
| 79 | − if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 80 | − if ((pCtx->sDecoderStatistics.uiWidth != (unsigned int) kiActualWidth) | |
| 81 | − || (pCtx->sDecoderStatistics.uiHeight != (unsigned int) kiActualHeight)) { | |
| 82 | − pCtx->sDecoderStatistics.uiResolutionChangeTimes++; | |
| 83 | − pCtx->sDecoderStatistics.uiWidth = kiActualWidth; | |
| 84 | − pCtx->sDecoderStatistics.uiHeight = kiActualHeight; | |
| 85 | − } | |
| 86 | − UpdateDecStatNoFreezingInfo (pCtx); | |
| 87 | − } | |
| 88 | − | |
| 89 | − if (pCtx->pParam->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo | |
| 90 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 91 | − if (dsErrorFree == pCtx->iErrorCode) { //correct decoding, add to data buffer | |
| 92 | − SParserBsInfo* pParser = pCtx->pParserBsInfo; | |
| 93 | − SNalUnit* pCurNal = NULL; | |
| 94 | − int32_t iTotalNalLen = 0; | |
| 95 | − int32_t iNalLen = 0; | |
| 96 | − int32_t iNum = 0; | |
| 97 | − while (iNum < pParser->iNalNum) { | |
| 98 | − iTotalNalLen += pParser->pNalLenInByte[iNum++]; | |
| 99 | − } | |
| 100 | − uint8_t* pDstBuf = pParser->pDstBuff + iTotalNalLen; | |
| 101 | − int32_t iIdx = pCurAu->uiStartPos; | |
| 102 | − int32_t iEndIdx = pCurAu->uiEndPos; | |
| 103 | − uint8_t* pNalBs = NULL; | |
| 104 | − pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0; | |
| 105 | − //pParser->iNalNum = 0; | |
| 106 | − pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4) - ((pCtx->pSps->sFrameCrop.iLeftOffset + | |
| 107 | − pCtx->pSps->sFrameCrop.iRightOffset) << 1); | |
| 108 | − pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4) - ((pCtx->pSps->sFrameCrop.iTopOffset + | |
| 109 | − pCtx->pSps->sFrameCrop.iBottomOffset) << 1); | |
| 110 | − | |
| 111 | − if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR | |
| 112 | − if (pCtx->bFrameFinish) { //add required sps/pps | |
| 113 | − if (pParser->iNalNum > pCtx->iMaxNalNum - 2) { //2 reserved for sps+pps | |
| 114 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 115 | − "DecodeFrameConstruction(): current NAL num (%d) plus sps & pps exceeds permitted num (%d). Will expand", | |
| 116 | − pParser->iNalNum, pCtx->iMaxNalNum); | |
| 117 | − WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + 2)) | |
| 118 | − } | |
| 119 | − bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType); | |
| 120 | − SSpsBsInfo* pSpsBs = NULL; | |
| 121 | − SPpsBsInfo* pPpsBs = NULL; | |
| 122 | − int32_t iSpsId = pCtx->pSps->iSpsId; | |
| 123 | − int32_t iPpsId = pCtx->pPps->iPpsId; | |
| 124 | − pCtx->bParamSetsLostFlag = false; | |
| 125 | − //find required sps, pps and write into dst buff | |
| 126 | − pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId]; | |
| 127 | − pPpsBs = &pCtx->sPpsBsInfo [iPpsId]; | |
| 128 | − if (pDstBuf - pParser->pDstBuff + pSpsBs->uiSpsBsLen + pPpsBs->uiPpsBsLen >= MAX_ACCESS_UNIT_CAPACITY) { | |
| 129 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, | |
| 130 | − "DecodeFrameConstruction(): sps pps size: (%d %d) too large. Failed to parse. \n", pSpsBs->uiSpsBsLen, | |
| 131 | − pPpsBs->uiPpsBsLen); | |
| 132 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 133 | − pCtx->pParserBsInfo->iNalNum = 0; | |
| 134 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 135 | − } | |
| 136 | − memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen); | |
| 137 | − pParser->pNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen; | |
| 138 | − pDstBuf += pSpsBs->uiSpsBsLen; | |
| 139 | − memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen); | |
| 140 | − pParser->pNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen; | |
| 141 | − pDstBuf += pPpsBs->uiPpsBsLen; | |
| 142 | − pCtx->bFrameFinish = false; | |
| 143 | − } | |
| 144 | − } | |
| 145 | − //then VCL data re-write | |
| 146 | − if (pParser->iNalNum + iEndIdx - iIdx + 1 > pCtx->iMaxNalNum) { //calculate total NAL num | |
| 147 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 148 | − "DecodeFrameConstruction(): current NAL num (%d) exceeds permitted num (%d). Will expand", | |
| 149 | − pParser->iNalNum + iEndIdx - iIdx + 1, pCtx->iMaxNalNum); | |
| 150 | − WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + iEndIdx - iIdx + 1)) | |
| 151 | − } | |
| 152 | − while (iIdx <= iEndIdx) { | |
| 153 | − pCurNal = pCurAu->pNalUnitsList [iIdx ++]; | |
| 154 | − iNalLen = pCurNal->sNalData.sVclNal.iNalLength; | |
| 155 | − pNalBs = pCurNal->sNalData.sVclNal.pNalPos; | |
| 156 | − pParser->pNalLenInByte [pParser->iNalNum ++] = iNalLen; | |
| 157 | − if (pDstBuf - pParser->pDstBuff + iNalLen >= MAX_ACCESS_UNIT_CAPACITY) { | |
| 158 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, | |
| 159 | − "DecodeFrameConstruction(): composed output size (%ld) exceeds (%d). Failed to parse. current data pos %d out of %d:, previously accumulated num: %d, total num: %d, previously accumulated len: %d, current len: %d, current buf pos: %p, header buf pos: %p \n", | |
| 160 | − (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY, iIdx, iEndIdx, iNum, pParser->iNalNum, | |
| 161 | − iTotalNalLen, iNalLen, pDstBuf, pParser->pDstBuff); | |
| 162 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 163 | − pCtx->pParserBsInfo->iNalNum = 0; | |
| 164 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 165 | − } | |
| 166 | − | |
| 167 | − memcpy (pDstBuf, pNalBs, iNalLen); | |
| 168 | − pDstBuf += iNalLen; | |
| 169 | − } | |
| 170 | − if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { //frame complete | |
| 171 | − pCtx->iTotalNumMbRec = 0; | |
| 172 | − pCtx->bFramePending = false; | |
| 173 | − pCtx->bFrameFinish = true; //finish current frame and mark it | |
| 174 | − } else if (pCtx->iTotalNumMbRec != 0) { //frame incomplete | |
| 175 | − pCtx->bFramePending = true; | |
| 176 | − pCtx->pDec->bIsComplete = false; | |
| 177 | − pCtx->bFrameFinish = false; //current frame not finished | |
| 178 | − pCtx->iErrorCode |= dsFramePending; | |
| 179 | − return ERR_INFO_PARSEONLY_PENDING; | |
| 180 | − //pCtx->pParserBsInfo->iNalNum = 0; | |
| 181 | − } | |
| 182 | − } else { //error | |
| 183 | − pCtx->pParserBsInfo->uiOutBsTimeStamp = 0; | |
| 184 | − pCtx->pParserBsInfo->iNalNum = 0; | |
| 185 | − pCtx->pParserBsInfo->iSpsWidthInPixel = 0; | |
| 186 | − pCtx->pParserBsInfo->iSpsHeightInPixel = 0; | |
| 187 | − return ERR_INFO_PARSEONLY_ERROR; | |
| 188 | − } | |
| 189 | − return ERR_NONE; | |
| 190 | − } | |
| 191 | − | |
| 192 | − if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) { | |
| 193 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, | |
| 194 | − "DecodeFrameConstruction(): iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ", | |
| 195 | − pCtx->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight); | |
| 196 | − bFrameCompleteFlag = false; //return later after output buffer is done | |
| 197 | − if (pCtx->bInstantDecFlag) //no-delay decoding, wait for new slice | |
| 198 | − return ERR_INFO_MB_NUM_INADEQUATE; | |
| 199 | − } else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag | |
| 200 | − && (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done | |
| 201 | − pCtx->pDec->bIsComplete = true; | |
| 202 | − pCtx->bFreezeOutput = false; | |
| 203 | − } | |
| 204 | − | |
| 205 | − pCtx->iTotalNumMbRec = 0; | |
| 206 | − | |
| 207 | − //////output:::normal path | |
| 208 | − pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp; | |
| 209 | − ppDst[0] = pPic->pData[0]; | |
| 210 | − ppDst[1] = pPic->pData[1]; | |
| 211 | − ppDst[2] = pPic->pData[2]; | |
| 212 | − | |
| 213 | − pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420; | |
| 214 | − | |
| 215 | − pDstInfo->UsrData.sSystemBuffer.iWidth = kiActualWidth; | |
| 216 | − pDstInfo->UsrData.sSystemBuffer.iHeight = kiActualHeight; | |
| 217 | − pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; | |
| 218 | − pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; | |
| 219 | − ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; | |
| 220 | − ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; | |
| 221 | − ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; | |
| 222 | − pDstInfo->iBufferStatus = 1; | |
| 223 | − | |
| 224 | − bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) | |
| 225 | − || (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight); | |
| 226 | − pCtx->iLastImgWidthInPixel = pDstInfo->UsrData.sSystemBuffer.iWidth; | |
| 227 | − pCtx->iLastImgHeightInPixel = pDstInfo->UsrData.sSystemBuffer.iHeight; | |
| 228 | − if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete | |
| 229 | − pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag | |
| 230 | − && pPic->bIsComplete); // When EC disable, ECed picture not output | |
| 231 | − else if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE | |
| 232 | − || pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) | |
| 233 | − && pCtx->iErrorCode && bOutResChange) | |
| 234 | − pCtx->bFreezeOutput = true; | |
| 235 | − | |
| 236 | − if (pDstInfo->iBufferStatus == 0) { | |
| 237 | − if (!bFrameCompleteFlag) | |
| 238 | − pCtx->iErrorCode |= dsBitstreamError; | |
| 239 | − return ERR_INFO_MB_NUM_INADEQUATE; | |
| 240 | − } | |
| 241 | − if (pCtx->bFreezeOutput) { | |
| 242 | − pDstInfo->iBufferStatus = 0; | |
| 243 | − if (pPic->bNewSeqBegin) { | |
| 244 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 245 | − "DecodeFrameConstruction():New sequence detected, but freezed, correct MBs (%d) out of whole MBs (%d).", | |
| 246 | − kiTotalNumMbInCurLayer - pCtx->iMbEcedNum, kiTotalNumMbInCurLayer); | |
| 247 | − } | |
| 248 | − } | |
| 249 | − pCtx->iMbEcedNum = pPic->iMbEcedNum; | |
| 250 | − pCtx->iMbNum = pPic->iMbNum; | |
| 251 | − pCtx->iMbEcedPropNum = pPic->iMbEcedPropNum; | |
| 252 | − if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) { | |
| 253 | − if (pDstInfo->iBufferStatus && ((pCtx->sDecoderStatistics.uiWidth != (unsigned int) kiActualWidth) | |
| 254 | − || (pCtx->sDecoderStatistics.uiHeight != (unsigned int) kiActualHeight))) { | |
| 255 | − pCtx->sDecoderStatistics.uiResolutionChangeTimes++; | |
| 256 | − pCtx->sDecoderStatistics.uiWidth = kiActualWidth; | |
| 257 | − pCtx->sDecoderStatistics.uiHeight = kiActualHeight; | |
| 258 | − } | |
| 259 | − UpdateDecStat (pCtx, pDstInfo->iBufferStatus != 0); | |
| 260 | − } | |
| 261 | − return ERR_NONE; | |
| 262 | −} | |
| 263 | − | |
| 264 | −inline bool CheckSliceNeedReconstruct (uint8_t uiLayerDqId, uint8_t uiTargetDqId) { | |
| 265 | − return (uiLayerDqId == uiTargetDqId); // target layer | |
| 266 | −} | |
| 267 | − | |
| 268 | −inline uint8_t GetTargetDqId (uint8_t uiTargetDqId, SDecodingParam* psParam) { | |
| 269 | − uint8_t uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255; | |
| 270 | − | |
| 271 | − return WELS_MIN (uiTargetDqId, uiRequiredDqId); | |
| 272 | −} | |
| 273 | − | |
| 274 | − | |
| 275 | −inline void HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) { | |
| 276 | − if (0 == pCurNal->sNalHeaderExt.uiTemporalId) { | |
| 277 | − pCtx->bReferenceLostAtT0Flag = true; | |
| 278 | − } | |
| 279 | − pCtx->iErrorCode |= dsBitstreamError; | |
| 280 | −} | |
| 281 | − | |
| 282 | −inline void HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) { | |
| 283 | − if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) { | |
| 284 | − pCtx->bReferenceLostAtT0Flag = true; | |
| 285 | − } | |
| 286 | − pCtx->iErrorCode |= dsRefLost; | |
| 287 | −} | |
| 288 | − | |
| 289 | −inline int32_t WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) { | |
| 290 | − int32_t iRet = WelsTargetSliceConstruction (pCtx); | |
| 291 | − | |
| 292 | − if (iRet) { | |
| 293 | − HandleReferenceLostL0 (pCtx, pCurNal); | |
| 294 | − } | |
| 295 | − | |
| 296 | − return iRet; | |
| 297 | −} | |
| 298 | − | |
| 299 | −int32_t ParsePredWeightedTable (PBitStringAux pBs, PSliceHeader pSh) { | |
| 300 | − uint32_t uiCode; | |
| 301 | − int32_t iList = 0; | |
| 302 | − int32_t iCode; | |
| 303 | − | |
| 304 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); | |
| 305 | − WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "luma_log2_weight_denom", | |
| 306 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_LOG2_WEIGHT_DENOM)); | |
| 307 | − pSh->sPredWeightTable.uiLumaLog2WeightDenom = uiCode; | |
| 308 | − if (pSh->pSps->uiChromaArrayType != 0) { | |
| 309 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); | |
| 310 | − WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "chroma_log2_weight_denom", | |
| 311 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_LOG2_WEIGHT_DENOM)); | |
| 312 | − pSh->sPredWeightTable.uiChromaLog2WeightDenom = uiCode; | |
| 313 | − } | |
| 314 | − | |
| 315 | − | |
| 316 | − do { | |
| 317 | − | |
| 318 | − for (int i = 0; i < pSh->uiRefCount[iList]; i++) { | |
| 319 | − //luma | |
| 320 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); | |
| 321 | − if (!!uiCode) { | |
| 322 | − | |
| 323 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 324 | − WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_weight", | |
| 325 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_WEIGHT)); | |
| 326 | − pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = iCode; | |
| 327 | − | |
| 328 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 329 | − WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_offset", | |
| 330 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_OFFSET)); | |
| 331 | − pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = iCode; | |
| 332 | − } else { | |
| 333 | − pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = 1 << (pSh->sPredWeightTable.uiLumaLog2WeightDenom); | |
| 334 | − pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = 0; | |
| 335 | − | |
| 336 | − } | |
| 337 | − //chroma | |
| 338 | − if (pSh->pSps->uiChromaArrayType == 0) | |
| 339 | − continue; | |
| 340 | − | |
| 341 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); | |
| 342 | − if (!!uiCode) { | |
| 343 | − for (int j = 0; j < 2; j++) { | |
| 344 | − | |
| 345 | − | |
| 346 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 347 | − WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_weight", | |
| 348 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_WEIGHT)); | |
| 349 | − pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = iCode; | |
| 350 | − | |
| 351 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 352 | − WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_offset", | |
| 353 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_OFFSET)); | |
| 354 | − pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = iCode; | |
| 355 | − } | |
| 356 | − } else { | |
| 357 | − for (int j = 0; j < 2; j++) { | |
| 358 | − | |
| 359 | − | |
| 360 | − pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = 1 << (pSh->sPredWeightTable.uiChromaLog2WeightDenom); | |
| 361 | − pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = 0; | |
| 362 | − } | |
| 363 | − } | |
| 364 | − | |
| 365 | − } | |
| 366 | − ++iList; | |
| 367 | − } while (iList < LIST_1);//TODO: SUPPORT LIST_A | |
| 368 | − return ERR_NONE; | |
| 369 | −} | |
| 370 | − | |
| 371 | −/* | |
| 372 | − * Predeclared function routines .. | |
| 373 | − */ | |
| 374 | −int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) { | |
| 375 | − int32_t iList = 0; | |
| 376 | − const EWelsSliceType keSt = pSh->eSliceType; | |
| 377 | − PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering; | |
| 378 | − PSps pSps = pSh->pSps; | |
| 379 | − uint32_t uiCode; | |
| 380 | − if (keSt == I_SLICE || keSt == SI_SLICE) | |
| 381 | − return ERR_NONE; | |
| 382 | − | |
| 383 | − // Common syntaxs for P or B slices: list0, list1 followed if B slices used. | |
| 384 | − do { | |
| 385 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //ref_pic_list_modification_flag_l0 | |
| 386 | − pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!uiCode; | |
| 387 | − | |
| 388 | − if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) { | |
| 389 | − int32_t iIdx = 0; | |
| 390 | − do { | |
| 391 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //modification_of_pic_nums_idc | |
| 392 | − const uint32_t kuiIdc = uiCode; | |
| 393 | − | |
| 394 | − //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)--- | |
| 395 | − if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) { | |
| 396 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); | |
| 397 | − } | |
| 398 | − pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc = kuiIdc; | |
| 399 | − if (kuiIdc == 3) | |
| 400 | − break; | |
| 401 | − | |
| 402 | − if (iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT) | |
| 403 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); | |
| 404 | − | |
| 405 | − if (kuiIdc == 0 || kuiIdc == 1) { | |
| 406 | − // abs_diff_pic_num_minus1 should be in range 0 to MaxPicNum-1, MaxPicNum is derived as | |
| 407 | − // 2^(4+log2_max_frame_num_minus4) | |
| 408 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //abs_diff_pic_num_minus1 | |
| 409 | − WELS_CHECK_SE_UPPER_ERROR_NOLOG (uiCode, (uint32_t) (1 << pSps->uiLog2MaxFrameNum), "abs_diff_pic_num_minus1", | |
| 410 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING)); | |
| 411 | − pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = uiCode; // uiAbsDiffPicNumMinus1 | |
| 412 | − } else if (kuiIdc == 2) { | |
| 413 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num | |
| 414 | − pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = uiCode; | |
| 415 | − } | |
| 416 | − | |
| 417 | − ++ iIdx; | |
| 418 | − } while (true); | |
| 419 | − } | |
| 420 | − if (keSt != B_SLICE) | |
| 421 | − break; | |
| 422 | − ++ iList; | |
| 423 | − } while (iList < LIST_A); | |
| 424 | − | |
| 425 | − return ERR_NONE; | |
| 426 | −} | |
| 427 | − | |
| 428 | −int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps, | |
| 429 | − const bool kbIdrFlag) { | |
| 430 | − PRefPicMarking const kpRefMarking = &pSh->sRefMarking; | |
| 431 | − uint32_t uiCode; | |
| 432 | − if (kbIdrFlag) { | |
| 433 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //no_output_of_prior_pics_flag | |
| 434 | − kpRefMarking->bNoOutputOfPriorPicsFlag = !!uiCode; | |
| 435 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //long_term_reference_flag | |
| 436 | − kpRefMarking->bLongTermRefFlag = !!uiCode; | |
| 437 | − } else { | |
| 438 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_ref_pic_marking_mode_flag | |
| 439 | − kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!uiCode; | |
| 440 | − if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) { | |
| 441 | − int32_t iIdx = 0; | |
| 442 | − bool bAllowMmco5 = true, bMmco4Exist = false, bMmco5Exist = false, bMmco6Exist = false; | |
| 443 | − do { | |
| 444 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //memory_management_control_operation | |
| 445 | − const uint32_t kuiMmco = uiCode; | |
| 446 | − | |
| 447 | − kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kuiMmco; | |
| 448 | − if (kuiMmco == MMCO_END) | |
| 449 | − break; | |
| 450 | − | |
| 451 | − if (kuiMmco == MMCO_SHORT2UNUSED || kuiMmco == MMCO_SHORT2LONG) { | |
| 452 | − bAllowMmco5 = false; | |
| 453 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //difference_of_pic_nums_minus1 | |
| 454 | − kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + uiCode; | |
| 455 | − kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & (( | |
| 456 | − 1 << pSps->uiLog2MaxFrameNum) - 1); | |
| 457 | − } else if (kuiMmco == MMCO_LONG2UNUSED) { | |
| 458 | − bAllowMmco5 = false; | |
| 459 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num | |
| 460 | − kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = uiCode; | |
| 461 | − } | |
| 462 | − if (kuiMmco == MMCO_SHORT2LONG || kuiMmco == MMCO_LONG) { | |
| 463 | − if (kuiMmco == MMCO_LONG) { | |
| 464 | − WELS_VERIFY_RETURN_IF (-1, bMmco6Exist); | |
| 465 | − bMmco6Exist = true; | |
| 466 | − } | |
| 467 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_frame_idx | |
| 468 | − kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = uiCode; | |
| 469 | − } else if (kuiMmco == MMCO_SET_MAX_LONG) { | |
| 470 | − WELS_VERIFY_RETURN_IF (-1, bMmco4Exist); | |
| 471 | − bMmco4Exist = true; | |
| 472 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //max_long_term_frame_idx_plus1 | |
| 473 | − kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + uiCode; | |
| 474 | − } else if (kuiMmco == MMCO_RESET) { | |
| 475 | − WELS_VERIFY_RETURN_IF (-1, (!bAllowMmco5 || bMmco5Exist)); | |
| 476 | − bMmco5Exist = true; | |
| 477 | − } | |
| 478 | − ++ iIdx; | |
| 479 | − | |
| 480 | − } while (iIdx < MAX_MMCO_COUNT); | |
| 481 | − } | |
| 482 | − } | |
| 483 | − | |
| 484 | − return ERR_NONE; | |
| 485 | −} | |
| 486 | − | |
| 487 | −bool FillDefaultSliceHeaderExt (PSliceHeaderExt pShExt, PNalUnitHeaderExt pNalExt) { | |
| 488 | − if (pShExt == NULL || pNalExt == NULL) | |
| 489 | − return false; | |
| 490 | − | |
| 491 | − if (pNalExt->iNoInterLayerPredFlag || pNalExt->uiQualityId > 0) | |
| 492 | − pShExt->bBasePredWeightTableFlag = false; | |
| 493 | − else | |
| 494 | − pShExt->bBasePredWeightTableFlag = true; | |
| 495 | − pShExt->uiRefLayerDqId = (uint8_t) - 1; | |
| 496 | − pShExt->uiDisableInterLayerDeblockingFilterIdc = 0; | |
| 497 | − pShExt->iInterLayerSliceAlphaC0Offset = 0; | |
| 498 | − pShExt->iInterLayerSliceBetaOffset = 0; | |
| 499 | − pShExt->bConstrainedIntraResamplingFlag = false; | |
| 500 | − pShExt->uiRefLayerChromaPhaseXPlus1Flag = 0; | |
| 501 | − pShExt->uiRefLayerChromaPhaseYPlus1 = 1; | |
| 502 | − //memset(&pShExt->sScaledRefLayer, 0, sizeof(SPosOffset)); | |
| 503 | − | |
| 504 | − pShExt->iScaledRefLayerPicWidthInSampleLuma = pShExt->sSliceHeader.iMbWidth << 4; | |
| 505 | − pShExt->iScaledRefLayerPicHeightInSampleLuma = pShExt->sSliceHeader.iMbHeight << 4; | |
| 506 | − | |
| 507 | − pShExt->bSliceSkipFlag = false; | |
| 508 | − pShExt->bAdaptiveBaseModeFlag = false; | |
| 509 | − pShExt->bDefaultBaseModeFlag = false; | |
| 510 | − pShExt->bAdaptiveMotionPredFlag = false; | |
| 511 | − pShExt->bDefaultMotionPredFlag = false; | |
| 512 | − pShExt->bAdaptiveResidualPredFlag = false; | |
| 513 | − pShExt->bDefaultResidualPredFlag = false; | |
| 514 | − pShExt->bTCoeffLevelPredFlag = false; | |
| 515 | − pShExt->uiScanIdxStart = 0; | |
| 516 | − pShExt->uiScanIdxEnd = 15; | |
| 517 | − | |
| 518 | − return true; | |
| 519 | −} | |
| 520 | − | |
| 521 | −int32_t InitBsBuffer (PWelsDecoderContext pCtx) { | |
| 522 | − if (pCtx == NULL) | |
| 523 | − return ERR_INFO_INVALID_PTR; | |
| 524 | − | |
| 525 | − CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 526 | − | |
| 527 | − pCtx->iMaxBsBufferSizeInByte = MIN_ACCESS_UNIT_CAPACITY * MAX_BUFFERED_NUM; | |
| 528 | − if ((pCtx->sRawData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte, | |
| 529 | − "pCtx->sRawData.pHead"))) == NULL) { | |
| 530 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 531 | − } | |
| 532 | − pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead; | |
| 533 | − pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte; | |
| 534 | − if (pCtx->pParam->bParseOnly) { | |
| 535 | − pCtx->pParserBsInfo = static_cast<SParserBsInfo*> (pMa->WelsMallocz (sizeof (SParserBsInfo), "pCtx->pParserBsInfo")); | |
| 536 | − if (pCtx->pParserBsInfo == NULL) { | |
| 537 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 538 | − } | |
| 539 | − memset (pCtx->pParserBsInfo, 0, sizeof (SParserBsInfo)); | |
| 540 | − pCtx->pParserBsInfo->pDstBuff = static_cast<uint8_t*> (pMa->WelsMallocz (MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t), | |
| 541 | − "pCtx->pParserBsInfo->pDstBuff")); | |
| 542 | − if (pCtx->pParserBsInfo->pDstBuff == NULL) { | |
| 543 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 544 | − } | |
| 545 | − memset (pCtx->pParserBsInfo->pDstBuff, 0, MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t)); | |
| 546 | − | |
| 547 | − if ((pCtx->sSavedData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte, | |
| 548 | − "pCtx->sSavedData.pHead"))) == NULL) { | |
| 549 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 550 | − } | |
| 551 | − pCtx->sSavedData.pStartPos = pCtx->sSavedData.pCurPos = pCtx->sSavedData.pHead; | |
| 552 | − pCtx->sSavedData.pEnd = pCtx->sSavedData.pHead + pCtx->iMaxBsBufferSizeInByte; | |
| 553 | − | |
| 554 | − pCtx->iMaxNalNum = MAX_NAL_UNITS_IN_LAYER + 2; //2 reserved for SPS+PPS | |
| 555 | − pCtx->pParserBsInfo->pNalLenInByte = static_cast<int*> (pMa->WelsMallocz (pCtx->iMaxNalNum * sizeof (int), | |
| 556 | − "pCtx->pParserBsInfo->pNalLenInByte")); | |
| 557 | − if (pCtx->pParserBsInfo->pNalLenInByte == NULL) { | |
| 558 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 559 | − } | |
| 560 | − } | |
| 561 | − return ERR_NONE; | |
| 562 | −} | |
| 563 | − | |
| 564 | −int32_t ExpandBsBuffer (PWelsDecoderContext pCtx, const int32_t kiSrcLen) { | |
| 565 | − if (pCtx == NULL) | |
| 566 | − return ERR_INFO_INVALID_PTR; | |
| 567 | − int32_t iExpandStepShift = 1; | |
| 568 | − int32_t iNewBuffLen = WELS_MAX ((kiSrcLen * MAX_BUFFERED_NUM), (pCtx->iMaxBsBufferSizeInByte << iExpandStepShift)); | |
| 569 | − //allocate new bs buffer | |
| 570 | − CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 571 | − | |
| 572 | − //Realloc sRawData | |
| 573 | − uint8_t* pNewBsBuff = static_cast<uint8_t*> (pMa->WelsMallocz (iNewBuffLen, "pCtx->sRawData.pHead")); | |
| 574 | − if (pNewBsBuff == NULL) { | |
| 575 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "ExpandBsBuffer() Failed for malloc pNewBsBuff (%d)", iNewBuffLen); | |
| 576 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 577 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 578 | − } | |
| 579 | − | |
| 580 | − //Calculate and set the bs start and end position | |
| 581 | − for (uint32_t i = 0; i <= pCtx->pAccessUnitList->uiActualUnitsNum; i++) { | |
| 582 | − PBitStringAux pSliceBitsRead = &pCtx->pAccessUnitList->pNalUnitsList[i]->sNalData.sVclNal.sSliceBitsRead; | |
| 583 | − pSliceBitsRead->pStartBuf = pSliceBitsRead->pStartBuf - pCtx->sRawData.pHead + pNewBsBuff; | |
| 584 | − pSliceBitsRead->pEndBuf = pSliceBitsRead->pEndBuf - pCtx->sRawData.pHead + pNewBsBuff; | |
| 585 | − pSliceBitsRead->pCurBuf = pSliceBitsRead->pCurBuf - pCtx->sRawData.pHead + pNewBsBuff; | |
| 586 | − } | |
| 587 | − | |
| 588 | − //Copy current buffer status to new buffer | |
| 589 | − memcpy (pNewBsBuff, pCtx->sRawData.pHead, pCtx->iMaxBsBufferSizeInByte); | |
| 590 | − pCtx->sRawData.pStartPos = pNewBsBuff + (pCtx->sRawData.pStartPos - pCtx->sRawData.pHead); | |
| 591 | − pCtx->sRawData.pCurPos = pNewBsBuff + (pCtx->sRawData.pCurPos - pCtx->sRawData.pHead); | |
| 592 | − pCtx->sRawData.pEnd = pNewBsBuff + iNewBuffLen; | |
| 593 | − pMa->WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData.pHead"); | |
| 594 | − pCtx->sRawData.pHead = pNewBsBuff; | |
| 595 | − | |
| 596 | − if (pCtx->pParam->bParseOnly) { | |
| 597 | − //Realloc sSavedData | |
| 598 | − uint8_t* pNewSavedBsBuff = static_cast<uint8_t*> (pMa->WelsMallocz (iNewBuffLen, "pCtx->sSavedData.pHead")); | |
| 599 | − if (pNewSavedBsBuff == NULL) { | |
| 600 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "ExpandBsBuffer() Failed for malloc pNewSavedBsBuff (%d)", iNewBuffLen); | |
| 601 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 602 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 603 | − } | |
| 604 | − | |
| 605 | − //Copy current buffer status to new buffer | |
| 606 | − memcpy (pNewSavedBsBuff, pCtx->sSavedData.pHead, pCtx->iMaxBsBufferSizeInByte); | |
| 607 | − pCtx->sSavedData.pStartPos = pNewSavedBsBuff + (pCtx->sSavedData.pStartPos - pCtx->sSavedData.pHead); | |
| 608 | − pCtx->sSavedData.pCurPos = pNewSavedBsBuff + (pCtx->sSavedData.pCurPos - pCtx->sSavedData.pHead); | |
| 609 | − pCtx->sSavedData.pEnd = pNewSavedBsBuff + iNewBuffLen; | |
| 610 | − pMa->WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData.pHead"); | |
| 611 | − pCtx->sSavedData.pHead = pNewSavedBsBuff; | |
| 612 | − } | |
| 613 | − | |
| 614 | − pCtx->iMaxBsBufferSizeInByte = iNewBuffLen; | |
| 615 | − return ERR_NONE; | |
| 616 | −} | |
| 617 | − | |
| 618 | −int32_t ExpandBsLenBuffer (PWelsDecoderContext pCtx, const int32_t kiCurrLen) { | |
| 619 | − SParserBsInfo* pParser = pCtx->pParserBsInfo; | |
| 620 | − if (!pParser->pNalLenInByte) | |
| 621 | − return ERR_INFO_INVALID_ACCESS; | |
| 622 | − | |
| 623 | − int iNewLen = kiCurrLen; | |
| 624 | − if (kiCurrLen >= MAX_MB_SIZE + 2) { //exceeds the max MB number of level 5.2 | |
| 625 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "Current nal num (%d) exceededs %d.", kiCurrLen, MAX_MB_SIZE); | |
| 626 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 627 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 628 | − } else { | |
| 629 | − iNewLen = kiCurrLen << 1; | |
| 630 | − iNewLen = WELS_MIN (iNewLen, MAX_MB_SIZE + 2); | |
| 631 | − } | |
| 632 | − | |
| 633 | − CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 634 | − int* pNewLenBuffer = static_cast<int*> (pMa->WelsMallocz (iNewLen * sizeof (int), | |
| 635 | − "pCtx->pParserBsInfo->pNalLenInByte")); | |
| 636 | − if (pNewLenBuffer == NULL) { | |
| 637 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 638 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 639 | − } | |
| 640 | − | |
| 641 | − //copy existing data from old length buffer to new | |
| 642 | − memcpy (pNewLenBuffer, pParser->pNalLenInByte, pCtx->iMaxNalNum * sizeof (int)); | |
| 643 | − pMa->WelsFree (pParser->pNalLenInByte, "pCtx->pParserBsInfo->pNalLenInByte"); | |
| 644 | − pParser->pNalLenInByte = pNewLenBuffer; | |
| 645 | − pCtx->iMaxNalNum = iNewLen; | |
| 646 | − return ERR_NONE; | |
| 647 | −} | |
| 648 | − | |
| 649 | −int32_t CheckBsBuffer (PWelsDecoderContext pCtx, const int32_t kiSrcLen) { | |
| 650 | − if (kiSrcLen > MAX_ACCESS_UNIT_CAPACITY) { //exceeds max allowed data | |
| 651 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "Max AU size exceeded. Allowed size = %d, current size = %d", | |
| 652 | − MAX_ACCESS_UNIT_CAPACITY, | |
| 653 | − kiSrcLen); | |
| 654 | − pCtx->iErrorCode |= dsBitstreamError; | |
| 655 | − return ERR_INFO_INVALID_ACCESS; | |
| 656 | − } else if (kiSrcLen > pCtx->iMaxBsBufferSizeInByte / | |
| 657 | − MAX_BUFFERED_NUM) { //may lead to buffer overwrite, prevent it by expanding buffer | |
| 658 | − if (ExpandBsBuffer (pCtx, kiSrcLen)) { | |
| 659 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 660 | − } | |
| 661 | − } | |
| 662 | − | |
| 663 | − return ERR_NONE; | |
| 664 | −} | |
| 665 | − | |
| 666 | −/* | |
| 667 | − * WelsInitStaticMemory | |
| 668 | − * Memory request for new introduced data | |
| 669 | − * Especially for: | |
| 670 | − * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache. | |
| 671 | − * return: | |
| 672 | − * 0 - success; otherwise returned error_no defined in error_no.h. | |
| 673 | −*/ | |
| 674 | −int32_t WelsInitStaticMemory (PWelsDecoderContext pCtx) { | |
| 675 | − if (pCtx == NULL) { | |
| 676 | − return ERR_INFO_INVALID_PTR; | |
| 677 | − } | |
| 678 | − | |
| 679 | − if (MemInitNalList (&pCtx->pAccessUnitList, MAX_NAL_UNIT_NUM_IN_AU, pCtx->pMemAlign) != 0) | |
| 680 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 681 | − | |
| 682 | − if (InitBsBuffer (pCtx) != 0) | |
| 683 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 684 | − | |
| 685 | − pCtx->uiTargetDqId = (uint8_t) - 1; | |
| 686 | − pCtx->bEndOfStreamFlag = false; | |
| 687 | − | |
| 688 | − return ERR_NONE; | |
| 689 | −} | |
| 690 | − | |
| 691 | −/* | |
| 692 | − * WelsFreeStaticMemory | |
| 693 | − * Free memory introduced in WelsInitStaticMemory at destruction of decoder. | |
| 694 | − * | |
| 695 | − */ | |
| 696 | −void WelsFreeStaticMemory (PWelsDecoderContext pCtx) { | |
| 697 | − if (pCtx == NULL) | |
| 698 | − return; | |
| 699 | − | |
| 700 | − CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 701 | − | |
| 702 | − MemFreeNalList (&pCtx->pAccessUnitList, pMa); | |
| 703 | − | |
| 704 | − if (pCtx->sRawData.pHead) { | |
| 705 | − pMa->WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData->pHead"); | |
| 706 | − } | |
| 707 | − pCtx->sRawData.pHead = NULL; | |
| 708 | − pCtx->sRawData.pEnd = NULL; | |
| 709 | − pCtx->sRawData.pStartPos = NULL; | |
| 710 | − pCtx->sRawData.pCurPos = NULL; | |
| 711 | − if (pCtx->pParam->bParseOnly) { | |
| 712 | − if (pCtx->sSavedData.pHead) { | |
| 713 | − pMa->WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData->pHead"); | |
| 714 | − } | |
| 715 | − pCtx->sSavedData.pHead = NULL; | |
| 716 | − pCtx->sSavedData.pEnd = NULL; | |
| 717 | − pCtx->sSavedData.pStartPos = NULL; | |
| 718 | − pCtx->sSavedData.pCurPos = NULL; | |
| 719 | − if (pCtx->pParserBsInfo) { | |
| 720 | − if (pCtx->pParserBsInfo->pNalLenInByte) { | |
| 721 | − pMa->WelsFree (pCtx->pParserBsInfo->pNalLenInByte, "pCtx->pParserBsInfo->pNalLenInByte"); | |
| 722 | − pCtx->pParserBsInfo->pNalLenInByte = NULL; | |
| 723 | − pCtx->iMaxNalNum = 0; | |
| 724 | − } | |
| 725 | − if (pCtx->pParserBsInfo->pDstBuff) { | |
| 726 | − pMa->WelsFree (pCtx->pParserBsInfo->pDstBuff, "pCtx->pParserBsInfo->pDstBuff"); | |
| 727 | − pCtx->pParserBsInfo->pDstBuff = NULL; | |
| 728 | − } | |
| 729 | − pMa->WelsFree (pCtx->pParserBsInfo, "pCtx->pParserBsInfo"); | |
| 730 | − pCtx->pParserBsInfo = NULL; | |
| 731 | − } | |
| 732 | − } | |
| 733 | − | |
| 734 | − if (NULL != pCtx->pParam) { | |
| 735 | − pMa->WelsFree (pCtx->pParam, "pCtx->pParam"); | |
| 736 | − | |
| 737 | − pCtx->pParam = NULL; | |
| 738 | − } | |
| 739 | −} | |
| 740 | −/* | |
| 741 | − * DecodeNalHeaderExt | |
| 742 | − * Trigger condition: NAL_UNIT_TYPE = NAL_UNIT_PREFIX or NAL_UNIT_CODED_SLICE_EXT | |
| 743 | − * Parameter: | |
| 744 | − * pNal: target NALUnit ptr | |
| 745 | − * pSrc: NAL Unit bitstream | |
| 746 | − */ | |
| 747 | −void DecodeNalHeaderExt (PNalUnit pNal, uint8_t* pSrc) { | |
| 748 | − PNalUnitHeaderExt pHeaderExt = &pNal->sNalHeaderExt; | |
| 749 | − | |
| 750 | − uint8_t uiCurByte = *pSrc; | |
| 751 | − pHeaderExt->bIdrFlag = !! (uiCurByte & 0x40); | |
| 752 | − pHeaderExt->uiPriorityId = uiCurByte & 0x3F; | |
| 753 | − | |
| 754 | − uiCurByte = * (++pSrc); | |
| 755 | − pHeaderExt->iNoInterLayerPredFlag = uiCurByte >> 7; | |
| 756 | − pHeaderExt->uiDependencyId = (uiCurByte & 0x70) >> 4; | |
| 757 | − pHeaderExt->uiQualityId = uiCurByte & 0x0F; | |
| 758 | − uiCurByte = * (++pSrc); | |
| 759 | − pHeaderExt->uiTemporalId = uiCurByte >> 5; | |
| 760 | − pHeaderExt->bUseRefBasePicFlag = !! (uiCurByte & 0x10); | |
| 761 | − pHeaderExt->bDiscardableFlag = !! (uiCurByte & 0x08); | |
| 762 | − pHeaderExt->bOutputFlag = !! (uiCurByte & 0x04); | |
| 763 | − pHeaderExt->uiReservedThree2Bits = uiCurByte & 0x03; | |
| 764 | − pHeaderExt->uiLayerDqId = (pHeaderExt->uiDependencyId << 4) | pHeaderExt->uiQualityId; | |
| 765 | −} | |
| 766 | − | |
| 767 | − | |
| 768 | −void UpdateDecoderStatisticsForActiveParaset (SDecoderStatistics* pDecoderStatistics, | |
| 769 | − PSps pSps, PPps pPps) { | |
| 770 | − pDecoderStatistics->iCurrentActiveSpsId = pSps->iSpsId; | |
| 771 | − | |
| 772 | − pDecoderStatistics->iCurrentActivePpsId = pPps->iPpsId; | |
| 773 | − pDecoderStatistics->uiProfile = static_cast<unsigned int> (pSps->uiProfileIdc); | |
| 774 | − pDecoderStatistics->uiLevel = pSps->uiLevelIdc; | |
| 775 | −} | |
| 776 | − | |
| 777 | −#define SLICE_HEADER_IDR_PIC_ID_MAX 65535 | |
| 778 | −#define SLICE_HEADER_REDUNDANT_PIC_CNT_MAX 127 | |
| 779 | −#define SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN -12 | |
| 780 | −#define SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX 12 | |
| 781 | −#define SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN -12 | |
| 782 | −#define SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX 12 | |
| 783 | −#define MAX_NUM_REF_IDX_L0_ACTIVE_MINUS1 15 | |
| 784 | −#define SLICE_HEADER_CABAC_INIT_IDC_MAX 2 | |
| 785 | −/* | |
| 786 | − * decode_slice_header_avc | |
| 787 | − * Parse slice header of bitstream in avc for storing data structure | |
| 788 | − */ | |
| 789 | −int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, const bool kbExtensionFlag) { | |
| 790 | − PNalUnit const kpCurNal = pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiAvailUnitsNum - | |
| 791 | − 1]; | |
| 792 | − | |
| 793 | − PNalUnitHeaderExt pNalHeaderExt = NULL; | |
| 794 | − PSliceHeader pSliceHead = NULL; | |
| 795 | − PSliceHeaderExt pSliceHeadExt = NULL; | |
| 796 | − PSubsetSps pSubsetSps = NULL; | |
| 797 | − PSps pSps = NULL; | |
| 798 | − PPps pPps = NULL; | |
| 799 | − EWelsNalUnitType eNalType = static_cast<EWelsNalUnitType> (0); | |
| 800 | − int32_t iPpsId = 0; | |
| 801 | − int32_t iRet = ERR_NONE; | |
| 802 | − uint8_t uiSliceType = 0; | |
| 803 | − uint8_t uiQualityId = BASE_QUALITY_ID; | |
| 804 | − bool bIdrFlag = false; | |
| 805 | − bool bSgChangeCycleInvolved = false; // involved slice group change cycle ? | |
| 806 | − uint32_t uiCode; | |
| 807 | − int32_t iCode; | |
| 808 | − SLogContext* pLogCtx = & (pCtx->sLogCtx); | |
| 809 | − | |
| 810 | − if (kpCurNal == NULL) { | |
| 811 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 812 | − } | |
| 813 | − | |
| 814 | − pNalHeaderExt = &kpCurNal->sNalHeaderExt; | |
| 815 | − pSliceHead = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; | |
| 816 | − eNalType = pNalHeaderExt->sNalUnitHeader.eNalUnitType; | |
| 817 | − | |
| 818 | − pSliceHeadExt = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt; | |
| 819 | − | |
| 820 | − if (pSliceHeadExt) { | |
| 821 | − SRefBasePicMarking sBaseMarking; | |
| 822 | − const bool kbStoreRefBaseFlag = pSliceHeadExt->bStoreRefBasePicFlag; | |
| 823 | − memcpy (&sBaseMarking, &pSliceHeadExt->sRefBasePicMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage | |
| 824 | − memset (pSliceHeadExt, 0, sizeof (SSliceHeaderExt)); | |
| 825 | − pSliceHeadExt->bStoreRefBasePicFlag = kbStoreRefBaseFlag; | |
| 826 | − memcpy (&pSliceHeadExt->sRefBasePicMarking, &sBaseMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage | |
| 827 | − } | |
| 828 | − | |
| 829 | − kpCurNal->sNalData.sVclNal.bSliceHeaderExtFlag = kbExtensionFlag; | |
| 830 | − | |
| 831 | − // first_mb_in_slice | |
| 832 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //first_mb_in_slice | |
| 833 | − WELS_CHECK_SE_UPPER_ERROR (uiCode, 36863u, "first_mb_in_slice", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 834 | − ERR_INFO_INVALID_FIRST_MB_IN_SLICE)); | |
| 835 | − pSliceHead->iFirstMbInSlice = uiCode; | |
| 836 | − | |
| 837 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //slice_type | |
| 838 | − uiSliceType = uiCode; | |
| 839 | − if (uiSliceType > 9) { | |
| 840 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "slice type too large (%d) at first_mb(%d)", uiSliceType, | |
| 841 | − pSliceHead->iFirstMbInSlice); | |
| 842 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 843 | − } | |
| 844 | − if (uiSliceType > 4) | |
| 845 | − uiSliceType -= 5; | |
| 846 | − | |
| 847 | − if (B_SLICE == uiSliceType) { | |
| 848 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): B slice not supported."); | |
| 849 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_BIPRED); | |
| 850 | − } | |
| 851 | − if ((NAL_UNIT_CODED_SLICE_IDR == eNalType) && (I_SLICE != uiSliceType)) { | |
| 852 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "Invalid slice type(%d) in IDR picture. ", uiSliceType); | |
| 853 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 854 | − } | |
| 855 | − | |
| 856 | − if (kbExtensionFlag) { | |
| 857 | − if (uiSliceType > 2) { | |
| 858 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "Invalid slice type(%d).", uiSliceType); | |
| 859 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 860 | − } | |
| 861 | − } | |
| 862 | − | |
| 863 | − pSliceHead->eSliceType = static_cast <EWelsSliceType> (uiSliceType); | |
| 864 | − | |
| 865 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //pic_parameter_set_id | |
| 866 | − WELS_CHECK_SE_UPPER_ERROR (uiCode, (MAX_PPS_COUNT - 1), "iPpsId out of range", | |
| 867 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 868 | − ERR_INFO_PPS_ID_OVERFLOW)); | |
| 869 | − iPpsId = uiCode; | |
| 870 | − | |
| 871 | − //add check PPS available here | |
| 872 | − if (pCtx->bPpsAvailFlags[iPpsId] == false) { | |
| 873 | − pCtx->sDecoderStatistics.iPpsReportErrorNum++; | |
| 874 | − if (pCtx->iPPSLastInvalidId != iPpsId) { | |
| 875 | − WelsLog (pLogCtx, WELS_LOG_ERROR, "PPS id (%d) is invalid, previous id (%d) error ignored (%d)!", iPpsId, | |
| 876 | − pCtx->iPPSLastInvalidId, pCtx->iPPSInvalidNum); | |
| 877 | − pCtx->iPPSLastInvalidId = iPpsId; | |
| 878 | − pCtx->iPPSInvalidNum = 0; | |
| 879 | − } else { | |
| 880 | − pCtx->iPPSInvalidNum++; | |
| 881 | − } | |
| 882 | − pCtx->iErrorCode |= dsNoParamSets; | |
| 883 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_PPS_ID); | |
| 884 | − } | |
| 885 | − pCtx->iPPSLastInvalidId = -1; | |
| 886 | − | |
| 887 | − pPps = &pCtx->sPpsBuffer[iPpsId]; | |
| 888 | − | |
| 889 | − if (pPps->uiNumSliceGroups == 0) { | |
| 890 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "Invalid PPS referenced"); | |
| 891 | − pCtx->iErrorCode |= dsNoParamSets; | |
| 892 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS); | |
| 893 | − } | |
| 894 | − | |
| 895 | − if (kbExtensionFlag) { | |
| 896 | − pSubsetSps = &pCtx->sSubsetSpsBuffer[pPps->iSpsId]; | |
| 897 | − pSps = &pSubsetSps->sSps; | |
| 898 | − if (pCtx->bSubspsAvailFlags[pPps->iSpsId] == false) { | |
| 899 | − pCtx->sDecoderStatistics.iSubSpsReportErrorNum++; | |
| 900 | − if (pCtx->iSubSPSLastInvalidId != pPps->iSpsId) { | |
| 901 | − WelsLog (pLogCtx, WELS_LOG_ERROR, "Sub SPS id (%d) is invalid, previous id (%d) error ignored (%d)!", pPps->iSpsId, | |
| 902 | − pCtx->iSubSPSLastInvalidId, pCtx->iSubSPSInvalidNum); | |
| 903 | − pCtx->iSubSPSLastInvalidId = pPps->iSpsId; | |
| 904 | − pCtx->iSubSPSInvalidNum = 0; | |
| 905 | − } else { | |
| 906 | − pCtx->iSubSPSInvalidNum++; | |
| 907 | − } | |
| 908 | − pCtx->iErrorCode |= dsNoParamSets; | |
| 909 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SPS_ID); | |
| 910 | − } | |
| 911 | − pCtx->iSubSPSLastInvalidId = -1; | |
| 912 | − } else { | |
| 913 | − if (pCtx->bSpsAvailFlags[pPps->iSpsId] == false) { | |
| 914 | − pCtx->sDecoderStatistics.iSpsReportErrorNum++; | |
| 915 | − if (pCtx->iSPSLastInvalidId != pPps->iSpsId) { | |
| 916 | − WelsLog (pLogCtx, WELS_LOG_ERROR, "SPS id (%d) is invalid, previous id (%d) error ignored (%d)!", pPps->iSpsId, | |
| 917 | − pCtx->iSPSLastInvalidId, pCtx->iSPSInvalidNum); | |
| 918 | − pCtx->iSPSLastInvalidId = pPps->iSpsId; | |
| 919 | − pCtx->iSPSInvalidNum = 0; | |
| 920 | − } else { | |
| 921 | − pCtx->iSPSInvalidNum++; | |
| 922 | − } | |
| 923 | − pCtx->iErrorCode |= dsNoParamSets; | |
| 924 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SPS_ID); | |
| 925 | − } | |
| 926 | − pCtx->iSPSLastInvalidId = -1; | |
| 927 | − pSps = &pCtx->sSpsBuffer[pPps->iSpsId]; | |
| 928 | − } | |
| 929 | − pSliceHead->iPpsId = iPpsId; | |
| 930 | − pSliceHead->iSpsId = pPps->iSpsId; | |
| 931 | − pSliceHead->pPps = pPps; | |
| 932 | − pSliceHead->pSps = pSps; | |
| 933 | − | |
| 934 | − pSliceHeadExt->pSubsetSps = pSubsetSps; | |
| 935 | − | |
| 936 | − if (pSps->iNumRefFrames == 0) { | |
| 937 | − if ((uiSliceType != I_SLICE) && (uiSliceType != SI_SLICE)) { | |
| 938 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "slice_type (%d) not supported for num_ref_frames = 0.", uiSliceType); | |
| 939 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 940 | − } | |
| 941 | − } | |
| 942 | − | |
| 943 | − bIdrFlag = (!kbExtensionFlag && eNalType == NAL_UNIT_CODED_SLICE_IDR) || (kbExtensionFlag && pNalHeaderExt->bIdrFlag); | |
| 944 | − pSliceHead->bIdrFlag = bIdrFlag; | |
| 945 | − | |
| 946 | − if (pSps->uiLog2MaxFrameNum == 0) { | |
| 947 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "non existing SPS referenced"); | |
| 948 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS); | |
| 949 | − } | |
| 950 | − // check first_mb_in_slice | |
| 951 | − WELS_CHECK_SE_UPPER_ERROR ((uint32_t) (pSliceHead->iFirstMbInSlice), (pSps->uiTotalMbCount - 1), "first_mb_in_slice", | |
| 952 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FIRST_MB_IN_SLICE)); | |
| 953 | − WELS_READ_VERIFY (BsGetBits (pBs, pSps->uiLog2MaxFrameNum, &uiCode)); //frame_num | |
| 954 | − pSliceHead->iFrameNum = uiCode; | |
| 955 | − | |
| 956 | − pSliceHead->bFieldPicFlag = false; | |
| 957 | − pSliceHead->bBottomFiledFlag = false; | |
| 958 | − if (!pSps->bFrameMbsOnlyFlag) { | |
| 959 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): frame_mbs_only_flag = %d not supported. ", | |
| 960 | − pSps->bFrameMbsOnlyFlag); | |
| 961 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MBAFF); | |
| 962 | − } | |
| 963 | − pSliceHead->iMbWidth = pSps->iMbWidth; | |
| 964 | − pSliceHead->iMbHeight = pSps->iMbHeight / (1 + pSliceHead->bFieldPicFlag); | |
| 965 | − | |
| 966 | − if (bIdrFlag) { | |
| 967 | − if (pSliceHead->iFrameNum != 0) { | |
| 968 | − WelsLog (pLogCtx, WELS_LOG_WARNING, | |
| 969 | − "ParseSliceHeaderSyntaxs(), invaild frame number: %d due to IDR frame introduced!", | |
| 970 | − pSliceHead->iFrameNum); | |
| 971 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FRAME_NUM); | |
| 972 | − } | |
| 973 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //idr_pic_id | |
| 974 | − // standard 7.4.3 idr_pic_id should be in range 0 to 65535, inclusive. | |
| 975 | − WELS_CHECK_SE_UPPER_ERROR (uiCode, SLICE_HEADER_IDR_PIC_ID_MAX, "idr_pic_id", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 976 | − ERR_INFO_INVALID_IDR_PIC_ID)); | |
| 977 | − pSliceHead->uiIdrPicId = uiCode; /* uiIdrPicId */ | |
| 978 | −#ifdef LONG_TERM_REF | |
| 979 | − pCtx->uiCurIdrPicId = pSliceHead->uiIdrPicId; | |
| 980 | −#endif | |
| 981 | − } | |
| 982 | − | |
| 983 | − pSliceHead->iDeltaPicOrderCntBottom = 0; | |
| 984 | − pSliceHead->iDeltaPicOrderCnt[0] = | |
| 985 | − pSliceHead->iDeltaPicOrderCnt[1] = 0; | |
| 986 | − if (pSps->uiPocType == 0) { | |
| 987 | − WELS_READ_VERIFY (BsGetBits (pBs, pSps->iLog2MaxPocLsb, &uiCode)); //pic_order_cnt_lsb | |
| 988 | − pSliceHead->iPicOrderCntLsb = uiCode; | |
| 989 | − if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) { | |
| 990 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //delta_pic_order_cnt_bottom | |
| 991 | − pSliceHead->iDeltaPicOrderCntBottom = iCode; | |
| 992 | − } | |
| 993 | − } else if (pSps->uiPocType == 1 && !pSps->bDeltaPicOrderAlwaysZeroFlag) { | |
| 994 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //delta_pic_order_cnt[ 0 ] | |
| 995 | − pSliceHead->iDeltaPicOrderCnt[0] = iCode; | |
| 996 | − if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) { | |
| 997 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //delta_pic_order_cnt[ 1 ] | |
| 998 | − pSliceHead->iDeltaPicOrderCnt[1] = iCode; | |
| 999 | − } | |
| 1000 | − } | |
| 1001 | − | |
| 1002 | − pSliceHead->iRedundantPicCnt = 0; | |
| 1003 | − if (pPps->bRedundantPicCntPresentFlag) { | |
| 1004 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //redundant_pic_cnt | |
| 1005 | − // standard section 7.4.3, redundant_pic_cnt should be in range 0 to 127, inclusive. | |
| 1006 | − WELS_CHECK_SE_UPPER_ERROR (uiCode, SLICE_HEADER_REDUNDANT_PIC_CNT_MAX, "redundant_pic_cnt", | |
| 1007 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REDUNDANT_PIC_CNT)); | |
| 1008 | − pSliceHead->iRedundantPicCnt = uiCode; | |
| 1009 | − if (pSliceHead->iRedundantPicCnt > 0) { | |
| 1010 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "Redundant picture not supported!"); | |
| 1011 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REDUNDANT_PIC_CNT); | |
| 1012 | − } | |
| 1013 | − } | |
| 1014 | − | |
| 1015 | − //set defaults, might be overriden a few line later | |
| 1016 | − pSliceHead->uiRefCount[0] = pPps->uiNumRefIdxL0Active; | |
| 1017 | − pSliceHead->uiRefCount[1] = pPps->uiNumRefIdxL1Active; | |
| 1018 | − | |
| 1019 | − bool bReadNumRefFlag = (P_SLICE == uiSliceType); | |
| 1020 | − if (kbExtensionFlag) { | |
| 1021 | − bReadNumRefFlag &= (BASE_QUALITY_ID == pNalHeaderExt->uiQualityId); | |
| 1022 | − } | |
| 1023 | − if (bReadNumRefFlag) { | |
| 1024 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //num_ref_idx_active_override_flag | |
| 1025 | − pSliceHead->bNumRefIdxActiveOverrideFlag = !!uiCode; | |
| 1026 | − if (pSliceHead->bNumRefIdxActiveOverrideFlag) { | |
| 1027 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //num_ref_idx_l0_active_minus1 | |
| 1028 | − WELS_CHECK_SE_UPPER_ERROR (uiCode, MAX_NUM_REF_IDX_L0_ACTIVE_MINUS1, "num_ref_idx_l0_active_minus1", | |
| 1029 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_NUM_REF_IDX_L0_ACTIVE_MINUS1)); | |
| 1030 | − pSliceHead->uiRefCount[0] = 1 + uiCode; | |
| 1031 | − } | |
| 1032 | − } | |
| 1033 | − | |
| 1034 | − if (pSliceHead->uiRefCount[0] > MAX_REF_PIC_COUNT || pSliceHead->uiRefCount[1] > MAX_REF_PIC_COUNT) { | |
| 1035 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "reference overflow"); | |
| 1036 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_REF_COUNT_OVERFLOW); | |
| 1037 | − } | |
| 1038 | − | |
| 1039 | − if (BASE_QUALITY_ID == uiQualityId) { | |
| 1040 | − iRet = ParseRefPicListReordering (pBs, pSliceHead); | |
| 1041 | − if (iRet != ERR_NONE) { | |
| 1042 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "invalid ref pPic list reordering syntaxs!"); | |
| 1043 | − return iRet; | |
| 1044 | − } | |
| 1045 | − | |
| 1046 | − if (pPps->bWeightedPredFlag && (uiSliceType == P_SLICE)) { | |
| 1047 | − iRet = ParsePredWeightedTable (pBs, pSliceHead); | |
| 1048 | − if (iRet != ERR_NONE) { | |
| 1049 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "invalid weighted prediction syntaxs!"); | |
| 1050 | − return iRet; | |
| 1051 | − } | |
| 1052 | − } | |
| 1053 | − | |
| 1054 | − if (kbExtensionFlag) { | |
| 1055 | − if (pNalHeaderExt->iNoInterLayerPredFlag || pNalHeaderExt->uiQualityId > 0) | |
| 1056 | − pSliceHeadExt->bBasePredWeightTableFlag = false; | |
| 1057 | − else | |
| 1058 | − pSliceHeadExt->bBasePredWeightTableFlag = true; | |
| 1059 | − } | |
| 1060 | − | |
| 1061 | − if (kpCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc != 0) { | |
| 1062 | − iRet = ParseDecRefPicMarking (pCtx, pBs, pSliceHead, pSps, bIdrFlag); | |
| 1063 | − if (iRet != ERR_NONE) { | |
| 1064 | − return iRet; | |
| 1065 | − } | |
| 1066 | − | |
| 1067 | − if (kbExtensionFlag && !pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { | |
| 1068 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //store_ref_base_pic_flag | |
| 1069 | − pSliceHeadExt->bStoreRefBasePicFlag = !!uiCode; | |
| 1070 | − if ((pNalHeaderExt->bUseRefBasePicFlag || pSliceHeadExt->bStoreRefBasePicFlag) && !bIdrFlag) { | |
| 1071 | − WelsLog (pLogCtx, WELS_LOG_WARNING, | |
| 1072 | − "ParseSliceHeaderSyntaxs(): bUseRefBasePicFlag or bStoreRefBasePicFlag = 1 not supported."); | |
| 1073 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP); | |
| 1074 | − } | |
| 1075 | − } | |
| 1076 | − } | |
| 1077 | − } | |
| 1078 | − | |
| 1079 | − if (pPps->bEntropyCodingModeFlag) { | |
| 1080 | − if (pSliceHead->eSliceType != I_SLICE && pSliceHead->eSliceType != SI_SLICE) { | |
| 1081 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); | |
| 1082 | − WELS_CHECK_SE_UPPER_ERROR (uiCode, SLICE_HEADER_CABAC_INIT_IDC_MAX, "cabac_init_idc", ERR_INFO_INVALID_CABAC_INIT_IDC); | |
| 1083 | − pSliceHead->iCabacInitIdc = uiCode; | |
| 1084 | − } else | |
| 1085 | − pSliceHead->iCabacInitIdc = 0; | |
| 1086 | − } | |
| 1087 | − | |
| 1088 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_qp_delta | |
| 1089 | − pSliceHead->iSliceQpDelta = iCode; | |
| 1090 | − pSliceHead->iSliceQp = pPps->iPicInitQp + pSliceHead->iSliceQpDelta; | |
| 1091 | − if (pSliceHead->iSliceQp < 0 || pSliceHead->iSliceQp > 51) { | |
| 1092 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "QP %d out of range", pSliceHead->iSliceQp); | |
| 1093 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_QP); | |
| 1094 | − } | |
| 1095 | − | |
| 1096 | − //FIXME qscale / qp ... stuff | |
| 1097 | − if (!kbExtensionFlag) { | |
| 1098 | − if (uiSliceType == SP_SLICE || uiSliceType == SI_SLICE) { | |
| 1099 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "SP/SI not supported"); | |
| 1100 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_SPSI); | |
| 1101 | − } | |
| 1102 | − } | |
| 1103 | − | |
| 1104 | − pSliceHead->uiDisableDeblockingFilterIdc = 0; | |
| 1105 | − pSliceHead->iSliceAlphaC0Offset = 0; | |
| 1106 | − pSliceHead->iSliceBetaOffset = 0; | |
| 1107 | − if (pPps->bDeblockingFilterControlPresentFlag) { | |
| 1108 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //disable_deblocking_filter_idc | |
| 1109 | − pSliceHead->uiDisableDeblockingFilterIdc = uiCode; | |
| 1110 | − //refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20 | |
| 1111 | − if (pSliceHead->uiDisableDeblockingFilterIdc > 6) { | |
| 1112 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "disable_deblock_filter_idc (%d) out of range [0, 6]", | |
| 1113 | − pSliceHead->uiDisableDeblockingFilterIdc); | |
| 1114 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_DBLOCKING_IDC); | |
| 1115 | − } | |
| 1116 | − if (pSliceHead->uiDisableDeblockingFilterIdc != 1) { | |
| 1117 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_alpha_c0_offset_div2 | |
| 1118 | − pSliceHead->iSliceAlphaC0Offset = iCode * 2; | |
| 1119 | − WELS_CHECK_SE_BOTH_ERROR (pSliceHead->iSliceAlphaC0Offset, SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN, | |
| 1120 | − SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX, "slice_alpha_c0_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 1121 | − ERR_INFO_INVALID_SLICE_ALPHA_C0_OFFSET_DIV2)); | |
| 1122 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_beta_offset_div2 | |
| 1123 | − pSliceHead->iSliceBetaOffset = iCode * 2; | |
| 1124 | − WELS_CHECK_SE_BOTH_ERROR (pSliceHead->iSliceBetaOffset, SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN, | |
| 1125 | − SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX, "slice_beta_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 1126 | − ERR_INFO_INVALID_SLICE_BETA_OFFSET_DIV2)); | |
| 1127 | − } | |
| 1128 | − } | |
| 1129 | − | |
| 1130 | − bSgChangeCycleInvolved = (pPps->uiNumSliceGroups > 1 && pPps->uiSliceGroupMapType >= 3 | |
| 1131 | − && pPps->uiSliceGroupMapType <= 5); | |
| 1132 | − if (kbExtensionFlag && bSgChangeCycleInvolved) | |
| 1133 | − bSgChangeCycleInvolved = (bSgChangeCycleInvolved && (uiQualityId == BASE_QUALITY_ID)); | |
| 1134 | − if (bSgChangeCycleInvolved) { | |
| 1135 | − if (pPps->uiSliceGroupChangeRate > 0) { | |
| 1136 | − const int32_t kiNumBits = (int32_t)WELS_CEIL (log (static_cast<double> (1 + pPps->uiPicSizeInMapUnits / | |
| 1137 | − pPps->uiSliceGroupChangeRate))); | |
| 1138 | − WELS_READ_VERIFY (BsGetBits (pBs, kiNumBits, &uiCode)); //lice_group_change_cycle | |
| 1139 | − pSliceHead->iSliceGroupChangeCycle = uiCode; | |
| 1140 | − } else | |
| 1141 | − pSliceHead->iSliceGroupChangeCycle = 0; | |
| 1142 | − } | |
| 1143 | − | |
| 1144 | − if (!kbExtensionFlag) { | |
| 1145 | − FillDefaultSliceHeaderExt (pSliceHeadExt, pNalHeaderExt); | |
| 1146 | − } else { | |
| 1147 | − /* Extra syntax elements newly introduced */ | |
| 1148 | − pSliceHeadExt->pSubsetSps = pSubsetSps; | |
| 1149 | − | |
| 1150 | − if (!pNalHeaderExt->iNoInterLayerPredFlag && BASE_QUALITY_ID == uiQualityId) { | |
| 1151 | − //the following should be deleted for CODE_CLEAN | |
| 1152 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //ref_layer_dq_id | |
| 1153 | − pSliceHeadExt->uiRefLayerDqId = uiCode; | |
| 1154 | − if (pSubsetSps->sSpsSvcExt.bInterLayerDeblockingFilterCtrlPresentFlag) { | |
| 1155 | − WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //disable_inter_layer_deblocking_filter_idc | |
| 1156 | − pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc = uiCode; | |
| 1157 | − //refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20 | |
| 1158 | − if (pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc > 6) { | |
| 1159 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "disable_inter_layer_deblock_filter_idc (%d) out of range [0, 6]", | |
| 1160 | − pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc); | |
| 1161 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_DBLOCKING_IDC); | |
| 1162 | − } | |
| 1163 | − if (pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc != 1) { | |
| 1164 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //inter_layer_slice_alpha_c0_offset_div2 | |
| 1165 | − pSliceHeadExt->iInterLayerSliceAlphaC0Offset = iCode * 2; | |
| 1166 | − WELS_CHECK_SE_BOTH_ERROR (pSliceHeadExt->iInterLayerSliceAlphaC0Offset, | |
| 1167 | − SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN, SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX, | |
| 1168 | − "inter_layer_alpha_c0_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 1169 | − ERR_INFO_INVALID_SLICE_ALPHA_C0_OFFSET_DIV2)); | |
| 1170 | − WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //inter_layer_slice_beta_offset_div2 | |
| 1171 | − pSliceHeadExt->iInterLayerSliceBetaOffset = iCode * 2; | |
| 1172 | − WELS_CHECK_SE_BOTH_ERROR (pSliceHeadExt->iInterLayerSliceBetaOffset, SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN, | |
| 1173 | − SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX, "inter_layer_slice_beta_offset_div2 * 2", | |
| 1174 | − GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_BETA_OFFSET_DIV2)); | |
| 1175 | − } | |
| 1176 | − } | |
| 1177 | − | |
| 1178 | − pSliceHeadExt->uiRefLayerChromaPhaseXPlus1Flag = pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseXPlus1Flag; | |
| 1179 | − pSliceHeadExt->uiRefLayerChromaPhaseYPlus1 = pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseYPlus1; | |
| 1180 | − | |
| 1181 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //constrained_intra_resampling_flag | |
| 1182 | − pSliceHeadExt->bConstrainedIntraResamplingFlag = !!uiCode; | |
| 1183 | − | |
| 1184 | − { | |
| 1185 | − SPosOffset pos; | |
| 1186 | − pos.iLeftOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iLeftOffset; | |
| 1187 | − pos.iTopOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iTopOffset * (2 - pSps->bFrameMbsOnlyFlag); | |
| 1188 | − pos.iRightOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iRightOffset; | |
| 1189 | − pos.iBottomOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iBottomOffset * (2 - pSps->bFrameMbsOnlyFlag); | |
| 1190 | − //memcpy(&pSliceHeadExt->sScaledRefLayer, &pos, sizeof(SPosOffset));//confirmed_safe_unsafe_usage | |
| 1191 | − pSliceHeadExt->iScaledRefLayerPicWidthInSampleLuma = (pSliceHead->iMbWidth << 4) - | |
| 1192 | − (pos.iLeftOffset + pos.iRightOffset); | |
| 1193 | − pSliceHeadExt->iScaledRefLayerPicHeightInSampleLuma = (pSliceHead->iMbHeight << 4) - | |
| 1194 | − (pos.iTopOffset + pos.iBottomOffset) / (1 + pSliceHead->bFieldPicFlag); | |
| 1195 | − } | |
| 1196 | − } else if (uiQualityId > BASE_QUALITY_ID) { | |
| 1197 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "MGS not supported."); | |
| 1198 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS); | |
| 1199 | − } else { | |
| 1200 | − pSliceHeadExt->uiRefLayerDqId = (uint8_t) - 1; | |
| 1201 | − } | |
| 1202 | − | |
| 1203 | − pSliceHeadExt->bSliceSkipFlag = false; | |
| 1204 | − pSliceHeadExt->bAdaptiveBaseModeFlag = false; | |
| 1205 | − pSliceHeadExt->bDefaultBaseModeFlag = false; | |
| 1206 | − pSliceHeadExt->bAdaptiveMotionPredFlag = false; | |
| 1207 | − pSliceHeadExt->bDefaultMotionPredFlag = false; | |
| 1208 | − pSliceHeadExt->bAdaptiveResidualPredFlag = false; | |
| 1209 | − pSliceHeadExt->bDefaultResidualPredFlag = false; | |
| 1210 | − if (pNalHeaderExt->iNoInterLayerPredFlag) | |
| 1211 | − pSliceHeadExt->bTCoeffLevelPredFlag = false; | |
| 1212 | − else | |
| 1213 | − pSliceHeadExt->bTCoeffLevelPredFlag = pSubsetSps->sSpsSvcExt.bSeqTCoeffLevelPredFlag; | |
| 1214 | − | |
| 1215 | − if (!pNalHeaderExt->iNoInterLayerPredFlag) { | |
| 1216 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //slice_skip_flag | |
| 1217 | − pSliceHeadExt->bSliceSkipFlag = !!uiCode; | |
| 1218 | − if (pSliceHeadExt->bSliceSkipFlag) { | |
| 1219 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "bSliceSkipFlag == 1 not supported."); | |
| 1220 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_SLICESKIP); | |
| 1221 | − } else { | |
| 1222 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_base_mode_flag | |
| 1223 | − pSliceHeadExt->bAdaptiveBaseModeFlag = !!uiCode; | |
| 1224 | − if (!pSliceHeadExt->bAdaptiveBaseModeFlag) { | |
| 1225 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //default_base_mode_flag | |
| 1226 | − pSliceHeadExt->bDefaultBaseModeFlag = !!uiCode; | |
| 1227 | − } | |
| 1228 | − if (!pSliceHeadExt->bDefaultBaseModeFlag) { | |
| 1229 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_motion_prediction_flag | |
| 1230 | − pSliceHeadExt->bAdaptiveMotionPredFlag = !!uiCode; | |
| 1231 | − if (!pSliceHeadExt->bAdaptiveMotionPredFlag) { | |
| 1232 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //default_motion_prediction_flag | |
| 1233 | − pSliceHeadExt->bDefaultMotionPredFlag = !!uiCode; | |
| 1234 | − } | |
| 1235 | − } | |
| 1236 | − | |
| 1237 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_residual_prediction_flag | |
| 1238 | − pSliceHeadExt->bAdaptiveResidualPredFlag = !!uiCode; | |
| 1239 | − if (!pSliceHeadExt->bAdaptiveResidualPredFlag) { | |
| 1240 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //default_residual_prediction_flag | |
| 1241 | − pSliceHeadExt->bDefaultResidualPredFlag = !!uiCode; | |
| 1242 | − } | |
| 1243 | − } | |
| 1244 | − if (pSubsetSps->sSpsSvcExt.bAdaptiveTCoeffLevelPredFlag) { | |
| 1245 | − WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //tcoeff_level_prediction_flag | |
| 1246 | − pSliceHeadExt->bTCoeffLevelPredFlag = !!uiCode; | |
| 1247 | − } | |
| 1248 | − } | |
| 1249 | − | |
| 1250 | − if (!pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { | |
| 1251 | − WELS_READ_VERIFY (BsGetBits (pBs, 4, &uiCode)); //scan_idx_start | |
| 1252 | − pSliceHeadExt->uiScanIdxStart = uiCode; | |
| 1253 | − WELS_READ_VERIFY (BsGetBits (pBs, 4, &uiCode)); //scan_idx_end | |
| 1254 | − pSliceHeadExt->uiScanIdxEnd = uiCode; | |
| 1255 | − if (pSliceHeadExt->uiScanIdxStart != 0 || pSliceHeadExt->uiScanIdxEnd != 15) { | |
| 1256 | − WelsLog (pLogCtx, WELS_LOG_WARNING, "uiScanIdxStart (%d) != 0 and uiScanIdxEnd (%d) !=15 not supported here", | |
| 1257 | − pSliceHeadExt->uiScanIdxStart, pSliceHeadExt->uiScanIdxEnd); | |
| 1258 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS); | |
| 1259 | − } | |
| 1260 | − } else { | |
| 1261 | − pSliceHeadExt->uiScanIdxStart = 0; | |
| 1262 | − pSliceHeadExt->uiScanIdxEnd = 15; | |
| 1263 | − } | |
| 1264 | − } | |
| 1265 | − | |
| 1266 | − return ERR_NONE; | |
| 1267 | −} | |
| 1268 | − | |
| 1269 | −/* | |
| 1270 | − * Copy relative syntax elements of NALUnitHeaderExt, sRefPicBaseMarking and bStoreRefBasePicFlag in prefix nal unit. | |
| 1271 | − * pSrc: mark as decoded prefix NAL | |
| 1272 | − * ppDst: succeeded VCL NAL based AVC (I/P Slice) | |
| 1273 | − */ | |
| 1274 | −bool PrefetchNalHeaderExtSyntax (PWelsDecoderContext pCtx, PNalUnit const kppDst, PNalUnit const kpSrc) { | |
| 1275 | − PNalUnitHeaderExt pNalHdrExtD = NULL, pNalHdrExtS = NULL; | |
| 1276 | − PSliceHeaderExt pShExtD = NULL; | |
| 1277 | − PPrefixNalUnit pPrefixS = NULL; | |
| 1278 | − PSps pSps = NULL; | |
| 1279 | − int32_t iIdx = 0; | |
| 1280 | − | |
| 1281 | − if (kppDst == NULL || kpSrc == NULL) | |
| 1282 | − return false; | |
| 1283 | − | |
| 1284 | − pNalHdrExtD = &kppDst->sNalHeaderExt; | |
| 1285 | − pNalHdrExtS = &kpSrc->sNalHeaderExt; | |
| 1286 | − pShExtD = &kppDst->sNalData.sVclNal.sSliceHeaderExt; | |
| 1287 | − pPrefixS = &kpSrc->sNalData.sPrefixNal; | |
| 1288 | − pSps = &pCtx->sSpsBuffer[pCtx->sPpsBuffer[pShExtD->sSliceHeader.iPpsId].iSpsId]; | |
| 1289 | − | |
| 1290 | − pNalHdrExtD->uiDependencyId = pNalHdrExtS->uiDependencyId; | |
| 1291 | − pNalHdrExtD->uiQualityId = pNalHdrExtS->uiQualityId; | |
| 1292 | − pNalHdrExtD->uiTemporalId = pNalHdrExtS->uiTemporalId; | |
| 1293 | − pNalHdrExtD->uiPriorityId = pNalHdrExtS->uiPriorityId; | |
| 1294 | − pNalHdrExtD->bIdrFlag = pNalHdrExtS->bIdrFlag; | |
| 1295 | − pNalHdrExtD->iNoInterLayerPredFlag = pNalHdrExtS->iNoInterLayerPredFlag; | |
| 1296 | − pNalHdrExtD->bDiscardableFlag = pNalHdrExtS->bDiscardableFlag; | |
| 1297 | − pNalHdrExtD->bOutputFlag = pNalHdrExtS->bOutputFlag; | |
| 1298 | − pNalHdrExtD->bUseRefBasePicFlag = pNalHdrExtS->bUseRefBasePicFlag; | |
| 1299 | − pNalHdrExtD->uiLayerDqId = pNalHdrExtS->uiLayerDqId; | |
| 1300 | − | |
| 1301 | − pShExtD->bStoreRefBasePicFlag = pPrefixS->bStoreRefBasePicFlag; | |
| 1302 | − memcpy (&pShExtD->sRefBasePicMarking, &pPrefixS->sRefPicBaseMarking, | |
| 1303 | − sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage | |
| 1304 | − if (pShExtD->sRefBasePicMarking.bAdaptiveRefBasePicMarkingModeFlag) { | |
| 1305 | − PRefBasePicMarking pRefBasePicMarking = &pShExtD->sRefBasePicMarking; | |
| 1306 | − iIdx = 0; | |
| 1307 | − do { | |
| 1308 | − if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_END) | |
| 1309 | − break; | |
| 1310 | − if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_SHORT2UNUSED) | |
| 1311 | − pRefBasePicMarking->mmco_base[iIdx].iShortFrameNum = (pShExtD->sSliceHeader.iFrameNum - | |
| 1312 | − pRefBasePicMarking->mmco_base[iIdx].uiDiffOfPicNums) & ((1 << pSps->uiLog2MaxFrameNum) - 1); | |
| 1313 | − ++ iIdx; | |
| 1314 | − } while (iIdx < MAX_MMCO_COUNT); | |
| 1315 | − } | |
| 1316 | − | |
| 1317 | − return true; | |
| 1318 | −} | |
| 1319 | − | |
| 1320 | − | |
| 1321 | − | |
| 1322 | −int32_t UpdateAccessUnit (PWelsDecoderContext pCtx) { | |
| 1323 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1324 | − int32_t iIdx = pCurAu->uiEndPos; | |
| 1325 | − | |
| 1326 | − // Conversed iterator | |
| 1327 | − pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iIdx]->sNalHeaderExt.uiLayerDqId; | |
| 1328 | − pCurAu->uiActualUnitsNum = iIdx + 1; | |
| 1329 | − pCurAu->bCompletedAuFlag = true; | |
| 1330 | − | |
| 1331 | − // Added for mosaic avoidance, 11/19/2009 | |
| 1332 | −#ifdef LONG_TERM_REF | |
| 1333 | − if (pCtx->bParamSetsLostFlag || pCtx->bNewSeqBegin) | |
| 1334 | −#else | |
| 1335 | − if (pCtx->bReferenceLostAtT0Flag || pCtx->bNewSeqBegin) | |
| 1336 | −#endif | |
| 1337 | − { | |
| 1338 | − uint32_t uiActualIdx = 0; | |
| 1339 | − while (uiActualIdx < pCurAu->uiActualUnitsNum) { | |
| 1340 | − PNalUnit nal = pCurAu->pNalUnitsList[uiActualIdx]; | |
| 1341 | − | |
| 1342 | − if (nal->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR || nal->sNalHeaderExt.bIdrFlag) { | |
| 1343 | − break; | |
| 1344 | − } | |
| 1345 | − ++ uiActualIdx; | |
| 1346 | − } | |
| 1347 | − if (uiActualIdx == | |
| 1348 | − pCurAu->uiActualUnitsNum) { // no found IDR nal within incoming AU, need exit to avoid mosaic issue, 11/19/2009 | |
| 1349 | − | |
| 1350 | − pCtx->sDecoderStatistics.uiIDRLostNum++; | |
| 1351 | − if (!pCtx->bParamSetsLostFlag) | |
| 1352 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, | |
| 1353 | − "UpdateAccessUnit():::::Key frame lost.....CAN NOT find IDR from current AU."); | |
| 1354 | − pCtx->iErrorCode |= dsRefLost; | |
| 1355 | − if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 1356 | −#ifdef LONG_TERM_REF | |
| 1357 | − pCtx->iErrorCode |= dsNoParamSets; | |
| 1358 | − return dsNoParamSets; | |
| 1359 | −#else | |
| 1360 | − pCtx->iErrorCode |= dsRefLost; | |
| 1361 | − return ERR_INFO_REFERENCE_PIC_LOST; | |
| 1362 | −#endif | |
| 1363 | − } | |
| 1364 | − } | |
| 1365 | − } | |
| 1366 | − | |
| 1367 | − return ERR_NONE; | |
| 1368 | −} | |
| 1369 | − | |
| 1370 | −int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWidth, const int32_t kiMaxHeight) { | |
| 1371 | − int32_t i = 0; | |
| 1372 | − | |
| 1373 | − WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiMaxWidth <= 0 || kiMaxHeight <= 0)) | |
| 1374 | − pCtx->sMb.iMbWidth = (kiMaxWidth + 15) >> 4; | |
| 1375 | − pCtx->sMb.iMbHeight = (kiMaxHeight + 15) >> 4; | |
| 1376 | − | |
| 1377 | − if (pCtx->bInitialDqLayersMem && kiMaxWidth <= pCtx->iPicWidthReq | |
| 1378 | − && kiMaxHeight <= pCtx->iPicHeightReq) // have same dimension memory, skipped | |
| 1379 | − return ERR_NONE; | |
| 1380 | − | |
| 1381 | − CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 1382 | − | |
| 1383 | − UninitialDqLayersContext (pCtx); | |
| 1384 | − | |
| 1385 | − do { | |
| 1386 | − PDqLayer pDq = (PDqLayer)pMa->WelsMallocz (sizeof (SDqLayer), "PDqLayer"); | |
| 1387 | − | |
| 1388 | − if (pDq == NULL) | |
| 1389 | − return ERR_INFO_OUT_OF_MEMORY; | |
| 1390 | − | |
| 1391 | − pCtx->pDqLayersList[i] = pDq; //to keep consistence with in UninitialDqLayersContext() | |
| 1392 | − memset (pDq, 0, sizeof (SDqLayer)); | |
| 1393 | − | |
| 1394 | − pCtx->sMb.pMbType[i] = (int16_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int16_t), | |
| 1395 | − "pCtx->sMb.pMbType[]"); | |
| 1396 | − pCtx->sMb.pMv[i][0] = (int16_t (*)[16][2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1397 | − int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMv[][]"); | |
| 1398 | − pCtx->sMb.pRefIndex[i][0] = (int8_t (*)[MB_BLOCK4x4_NUM])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * | |
| 1399 | − sizeof ( | |
| 1400 | − int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pRefIndex[][]"); | |
| 1401 | − pCtx->sMb.pLumaQp[i] = (int8_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1402 | − "pCtx->sMb.pLumaQp[]"); | |
| 1403 | − pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i] = (bool*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * | |
| 1404 | − sizeof ( | |
| 1405 | − bool), | |
| 1406 | − "pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[]"); | |
| 1407 | − pCtx->sMb.pTransformSize8x8Flag[i] = (bool*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (bool), | |
| 1408 | − "pCtx->sMb.pTransformSize8x8Flag[]"); | |
| 1409 | − pCtx->sMb.pChromaQp[i] = (int8_t (*)[2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1410 | − int8_t) * 2, | |
| 1411 | − "pCtx->sMb.pChromaQp[]"); | |
| 1412 | − pCtx->sMb.pMvd[i][0] = (int16_t (*)[16][2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1413 | − int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMvd[][]"); | |
| 1414 | − pCtx->sMb.pCbfDc[i] = (uint16_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (uint16_t), | |
| 1415 | − "pCtx->sMb.pCbfDc[]"); | |
| 1416 | − pCtx->sMb.pNzc[i] = (int8_t (*)[24])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24, | |
| 1417 | − "pCtx->sMb.pNzc[]"); | |
| 1418 | − pCtx->sMb.pNzcRs[i] = (int8_t (*)[24])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24, | |
| 1419 | − "pCtx->sMb.pNzcRs[]"); | |
| 1420 | − pCtx->sMb.pScaledTCoeff[i] = (int16_t (*)[MB_COEFF_LIST_SIZE])pMa->WelsMallocz (pCtx->sMb.iMbWidth * | |
| 1421 | − pCtx->sMb.iMbHeight * | |
| 1422 | − sizeof (int16_t) * MB_COEFF_LIST_SIZE, "pCtx->sMb.pScaledTCoeff[]"); | |
| 1423 | − pCtx->sMb.pIntraPredMode[i] = (int8_t (*)[8])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1424 | − int8_t) * 8, | |
| 1425 | − "pCtx->sMb.pIntraPredMode[]"); | |
| 1426 | − pCtx->sMb.pIntra4x4FinalMode[i] = (int8_t (*)[MB_BLOCK4x4_NUM])pMa->WelsMallocz (pCtx->sMb.iMbWidth * | |
| 1427 | − pCtx->sMb.iMbHeight * | |
| 1428 | − sizeof (int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pIntra4x4FinalMode[]"); | |
| 1429 | − pCtx->sMb.pIntraNxNAvailFlag[i] = (uint8_t (*))pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1430 | − int8_t), | |
| 1431 | − "pCtx->sMb.pIntraNxNAvailFlag"); | |
| 1432 | − pCtx->sMb.pChromaPredMode[i] = (int8_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1433 | − "pCtx->sMb.pChromaPredMode[]"); | |
| 1434 | − pCtx->sMb.pCbp[i] = (int8_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1435 | − "pCtx->sMb.pCbp[]"); | |
| 1436 | − pCtx->sMb.pSubMbType[i] = (int8_t (*)[MB_PARTITION_SIZE])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * | |
| 1437 | − sizeof ( | |
| 1438 | − int8_t) * MB_PARTITION_SIZE, "pCtx->sMb.pSubMbType[]"); | |
| 1439 | − pCtx->sMb.pSliceIdc[i] = (int32_t*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t), | |
| 1440 | − "pCtx->sMb.pSliceIdc[]"); // using int32_t for slice_idc, 4/21/2010 | |
| 1441 | − pCtx->sMb.pResidualPredFlag[i] = (int8_t*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1442 | − "pCtx->sMb.pResidualPredFlag[]"); | |
| 1443 | − pCtx->sMb.pInterPredictionDoneFlag[i] = (int8_t*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1444 | − int8_t), "pCtx->sMb.pInterPredictionDoneFlag[]"); | |
| 1445 | − | |
| 1446 | − pCtx->sMb.pMbCorrectlyDecodedFlag[i] = (bool*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1447 | − bool), | |
| 1448 | − "pCtx->sMb.pMbCorrectlyDecodedFlag[]"); | |
| 1449 | − pCtx->sMb.pMbRefConcealedFlag[i] = (bool*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (bool), | |
| 1450 | − "pCtx->pMbRefConcealedFlag[]"); | |
| 1451 | − | |
| 1452 | − // check memory block valid due above allocated.. | |
| 1453 | − WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, | |
| 1454 | − ((NULL == pCtx->sMb.pMbType[i]) || | |
| 1455 | − (NULL == pCtx->sMb.pMv[i][0]) || | |
| 1456 | − (NULL == pCtx->sMb.pRefIndex[i][0]) || | |
| 1457 | − (NULL == pCtx->sMb.pLumaQp[i]) || | |
| 1458 | − (NULL == pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i]) || | |
| 1459 | − (NULL == pCtx->sMb.pTransformSize8x8Flag[i]) || | |
| 1460 | − (NULL == pCtx->sMb.pChromaQp[i]) || | |
| 1461 | − (NULL == pCtx->sMb.pMvd[i][0]) || | |
| 1462 | − (NULL == pCtx->sMb.pCbfDc[i]) || | |
| 1463 | − (NULL == pCtx->sMb.pNzc[i]) || | |
| 1464 | − (NULL == pCtx->sMb.pNzcRs[i]) || | |
| 1465 | − (NULL == pCtx->sMb.pScaledTCoeff[i]) || | |
| 1466 | − (NULL == pCtx->sMb.pIntraPredMode[i]) || | |
| 1467 | − (NULL == pCtx->sMb.pIntra4x4FinalMode[i]) || | |
| 1468 | − (NULL == pCtx->sMb.pIntraNxNAvailFlag[i]) || | |
| 1469 | − (NULL == pCtx->sMb.pChromaPredMode[i]) || | |
| 1470 | − (NULL == pCtx->sMb.pCbp[i]) || | |
| 1471 | − (NULL == pCtx->sMb.pSubMbType[i]) || | |
| 1472 | − (NULL == pCtx->sMb.pSliceIdc[i]) || | |
| 1473 | − (NULL == pCtx->sMb.pResidualPredFlag[i]) || | |
| 1474 | − (NULL == pCtx->sMb.pInterPredictionDoneFlag[i]) || | |
| 1475 | − (NULL == pCtx->sMb.pMbRefConcealedFlag[i]) || | |
| 1476 | − (NULL == pCtx->sMb.pMbCorrectlyDecodedFlag[i]) | |
| 1477 | − ) | |
| 1478 | − ) | |
| 1479 | − | |
| 1480 | − memset (pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t))); | |
| 1481 | − | |
| 1482 | − ++ i; | |
| 1483 | − } while (i < LAYER_NUM_EXCHANGEABLE); | |
| 1484 | − | |
| 1485 | − pCtx->bInitialDqLayersMem = true; | |
| 1486 | − pCtx->iPicWidthReq = kiMaxWidth; | |
| 1487 | − pCtx->iPicHeightReq = kiMaxHeight; | |
| 1488 | − | |
| 1489 | − return ERR_NONE; | |
| 1490 | −} | |
| 1491 | − | |
| 1492 | −void UninitialDqLayersContext (PWelsDecoderContext pCtx) { | |
| 1493 | − int32_t i = 0; | |
| 1494 | − CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 1495 | − | |
| 1496 | − do { | |
| 1497 | − PDqLayer pDq = pCtx->pDqLayersList[i]; | |
| 1498 | − if (pDq == NULL) { | |
| 1499 | − ++ i; | |
| 1500 | − continue; | |
| 1501 | − } | |
| 1502 | − | |
| 1503 | − if (pCtx->sMb.pMbType[i]) { | |
| 1504 | − pMa->WelsFree (pCtx->sMb.pMbType[i], "pCtx->sMb.pMbType[]"); | |
| 1505 | − | |
| 1506 | − pCtx->sMb.pMbType[i] = NULL; | |
| 1507 | − } | |
| 1508 | − | |
| 1509 | − if (pCtx->sMb.pMv[i][0]) { | |
| 1510 | − pMa->WelsFree (pCtx->sMb.pMv[i][0], "pCtx->sMb.pMv[][]"); | |
| 1511 | − | |
| 1512 | − pCtx->sMb.pMv[i][0] = NULL; | |
| 1513 | − } | |
| 1514 | − | |
| 1515 | − if (pCtx->sMb.pRefIndex[i][0]) { | |
| 1516 | − pMa->WelsFree (pCtx->sMb.pRefIndex[i][0], "pCtx->sMb.pRefIndex[][]"); | |
| 1517 | − | |
| 1518 | − pCtx->sMb.pRefIndex[i][0] = NULL; | |
| 1519 | − } | |
| 1520 | − | |
| 1521 | − if (pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i]) { | |
| 1522 | − pMa->WelsFree (pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i], "pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[]"); | |
| 1523 | − | |
| 1524 | − pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i] = NULL; | |
| 1525 | − } | |
| 1526 | − | |
| 1527 | − if (pCtx->sMb.pTransformSize8x8Flag[i]) { | |
| 1528 | − pMa->WelsFree (pCtx->sMb.pTransformSize8x8Flag[i], "pCtx->sMb.pTransformSize8x8Flag[]"); | |
| 1529 | − | |
| 1530 | − pCtx->sMb.pTransformSize8x8Flag[i] = NULL; | |
| 1531 | − } | |
| 1532 | − | |
| 1533 | − if (pCtx->sMb.pLumaQp[i]) { | |
| 1534 | − pMa->WelsFree (pCtx->sMb.pLumaQp[i], "pCtx->sMb.pLumaQp[]"); | |
| 1535 | − | |
| 1536 | − pCtx->sMb.pLumaQp[i] = NULL; | |
| 1537 | − } | |
| 1538 | − | |
| 1539 | − if (pCtx->sMb.pChromaQp[i]) { | |
| 1540 | − pMa->WelsFree (pCtx->sMb.pChromaQp[i], "pCtx->sMb.pChromaQp[]"); | |
| 1541 | − | |
| 1542 | − pCtx->sMb.pChromaQp[i] = NULL; | |
| 1543 | − } | |
| 1544 | − | |
| 1545 | − if (pCtx->sMb.pMvd[i][0]) { | |
| 1546 | − pMa->WelsFree (pCtx->sMb.pMvd[i][0], "pCtx->sMb.pMvd[][]"); | |
| 1547 | − pCtx->sMb.pMvd[i][0] = NULL; | |
| 1548 | − } | |
| 1549 | − | |
| 1550 | − if (pCtx->sMb.pCbfDc[i]) { | |
| 1551 | − pMa->WelsFree (pCtx->sMb.pCbfDc[i], "pCtx->sMb.pCbfDc[]"); | |
| 1552 | − pCtx->sMb.pCbfDc[i] = NULL; | |
| 1553 | − } | |
| 1554 | − | |
| 1555 | − if (pCtx->sMb.pNzc[i]) { | |
| 1556 | − pMa->WelsFree (pCtx->sMb.pNzc[i], "pCtx->sMb.pNzc[]"); | |
| 1557 | − | |
| 1558 | − pCtx->sMb.pNzc[i] = NULL; | |
| 1559 | − } | |
| 1560 | − | |
| 1561 | − if (pCtx->sMb.pNzcRs[i]) { | |
| 1562 | − pMa->WelsFree (pCtx->sMb.pNzcRs[i], "pCtx->sMb.pNzcRs[]"); | |
| 1563 | − | |
| 1564 | − pCtx->sMb.pNzcRs[i] = NULL; | |
| 1565 | − } | |
| 1566 | − | |
| 1567 | − if (pCtx->sMb.pScaledTCoeff[i]) { | |
| 1568 | − pMa->WelsFree (pCtx->sMb.pScaledTCoeff[i], "pCtx->sMb.pScaledTCoeff[]"); | |
| 1569 | − | |
| 1570 | − pCtx->sMb.pScaledTCoeff[i] = NULL; | |
| 1571 | − } | |
| 1572 | − | |
| 1573 | − if (pCtx->sMb.pIntraPredMode[i]) { | |
| 1574 | − pMa->WelsFree (pCtx->sMb.pIntraPredMode[i], "pCtx->sMb.pIntraPredMode[]"); | |
| 1575 | − | |
| 1576 | − pCtx->sMb.pIntraPredMode[i] = NULL; | |
| 1577 | − } | |
| 1578 | − | |
| 1579 | − if (pCtx->sMb.pIntra4x4FinalMode[i]) { | |
| 1580 | − pMa->WelsFree (pCtx->sMb.pIntra4x4FinalMode[i], "pCtx->sMb.pIntra4x4FinalMode[]"); | |
| 1581 | − | |
| 1582 | − pCtx->sMb.pIntra4x4FinalMode[i] = NULL; | |
| 1583 | − } | |
| 1584 | − | |
| 1585 | − if (pCtx->sMb.pIntraNxNAvailFlag[i]) { | |
| 1586 | − pMa->WelsFree (pCtx->sMb.pIntraNxNAvailFlag[i], "pCtx->sMb.pIntraNxNAvailFlag"); | |
| 1587 | − | |
| 1588 | − pCtx->sMb.pIntraNxNAvailFlag[i] = NULL; | |
| 1589 | − } | |
| 1590 | − | |
| 1591 | − if (pCtx->sMb.pChromaPredMode[i]) { | |
| 1592 | − pMa->WelsFree (pCtx->sMb.pChromaPredMode[i], "pCtx->sMb.pChromaPredMode[]"); | |
| 1593 | − | |
| 1594 | − pCtx->sMb.pChromaPredMode[i] = NULL; | |
| 1595 | − } | |
| 1596 | − | |
| 1597 | − if (pCtx->sMb.pCbp[i]) { | |
| 1598 | − pMa->WelsFree (pCtx->sMb.pCbp[i], "pCtx->sMb.pCbp[]"); | |
| 1599 | − | |
| 1600 | − pCtx->sMb.pCbp[i] = NULL; | |
| 1601 | − } | |
| 1602 | − | |
| 1603 | − // if (pCtx->sMb.pMotionPredFlag[i]) | |
| 1604 | − //{ | |
| 1605 | − // pMa->WelsFree( pCtx->sMb.pMotionPredFlag[i], "pCtx->sMb.pMotionPredFlag[]" ); | |
| 1606 | − | |
| 1607 | − // pCtx->sMb.pMotionPredFlag[i] = NULL; | |
| 1608 | − //} | |
| 1609 | − | |
| 1610 | − if (pCtx->sMb.pSubMbType[i]) { | |
| 1611 | − pMa->WelsFree (pCtx->sMb.pSubMbType[i], "pCtx->sMb.pSubMbType[]"); | |
| 1612 | − | |
| 1613 | − pCtx->sMb.pSubMbType[i] = NULL; | |
| 1614 | − } | |
| 1615 | − | |
| 1616 | − if (pCtx->sMb.pSliceIdc[i]) { | |
| 1617 | − pMa->WelsFree (pCtx->sMb.pSliceIdc[i], "pCtx->sMb.pSliceIdc[]"); | |
| 1618 | − | |
| 1619 | − pCtx->sMb.pSliceIdc[i] = NULL; | |
| 1620 | − } | |
| 1621 | − | |
| 1622 | − if (pCtx->sMb.pResidualPredFlag[i]) { | |
| 1623 | − pMa->WelsFree (pCtx->sMb.pResidualPredFlag[i], "pCtx->sMb.pResidualPredFlag[]"); | |
| 1624 | − | |
| 1625 | − pCtx->sMb.pResidualPredFlag[i] = NULL; | |
| 1626 | − } | |
| 1627 | − | |
| 1628 | − if (pCtx->sMb.pInterPredictionDoneFlag[i]) { | |
| 1629 | − pMa->WelsFree (pCtx->sMb.pInterPredictionDoneFlag[i], "pCtx->sMb.pInterPredictionDoneFlag[]"); | |
| 1630 | − | |
| 1631 | − pCtx->sMb.pInterPredictionDoneFlag[i] = NULL; | |
| 1632 | − } | |
| 1633 | − | |
| 1634 | − if (pCtx->sMb.pMbCorrectlyDecodedFlag[i]) { | |
| 1635 | − pMa->WelsFree (pCtx->sMb.pMbCorrectlyDecodedFlag[i], "pCtx->sMb.pMbCorrectlyDecodedFlag[]"); | |
| 1636 | − pCtx->sMb.pMbCorrectlyDecodedFlag[i] = NULL; | |
| 1637 | − } | |
| 1638 | − | |
| 1639 | − if (pCtx->sMb.pMbRefConcealedFlag[i]) { | |
| 1640 | − pMa->WelsFree (pCtx->sMb.pMbRefConcealedFlag[i], "pCtx->sMb.pMbRefConcealedFlag[]"); | |
| 1641 | − pCtx->sMb.pMbRefConcealedFlag[i] = NULL; | |
| 1642 | − } | |
| 1643 | − pMa->WelsFree (pDq, "pDq"); | |
| 1644 | − | |
| 1645 | − pDq = NULL; | |
| 1646 | − pCtx->pDqLayersList[i] = NULL; | |
| 1647 | − | |
| 1648 | − ++ i; | |
| 1649 | − } while (i < LAYER_NUM_EXCHANGEABLE); | |
| 1650 | − | |
| 1651 | − pCtx->iPicWidthReq = 0; | |
| 1652 | − pCtx->iPicHeightReq = 0; | |
| 1653 | − pCtx->bInitialDqLayersMem = false; | |
| 1654 | −} | |
| 1655 | − | |
| 1656 | −void ResetCurrentAccessUnit (PWelsDecoderContext pCtx) { | |
| 1657 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1658 | − pCurAu->uiStartPos = 0; | |
| 1659 | − pCurAu->uiEndPos = 0; | |
| 1660 | − pCurAu->bCompletedAuFlag = false; | |
| 1661 | − if (pCurAu->uiActualUnitsNum > 0) { | |
| 1662 | − uint32_t iIdx = 0; | |
| 1663 | − const uint32_t kuiActualNum = pCurAu->uiActualUnitsNum; | |
| 1664 | − // a more simpler method to do nal units list management prefered here | |
| 1665 | − const uint32_t kuiAvailNum = pCurAu->uiAvailUnitsNum; | |
| 1666 | − const uint32_t kuiLeftNum = kuiAvailNum - kuiActualNum; | |
| 1667 | − | |
| 1668 | − // Swapping active nal unit nodes of succeeding AU with leading of list | |
| 1669 | − while (iIdx < kuiLeftNum) { | |
| 1670 | − PNalUnit t = pCurAu->pNalUnitsList[kuiActualNum + iIdx]; | |
| 1671 | − pCurAu->pNalUnitsList[kuiActualNum + iIdx] = pCurAu->pNalUnitsList[iIdx]; | |
| 1672 | − pCurAu->pNalUnitsList[iIdx] = t; | |
| 1673 | − ++ iIdx; | |
| 1674 | − } | |
| 1675 | − pCurAu->uiActualUnitsNum = pCurAu->uiAvailUnitsNum = kuiLeftNum; | |
| 1676 | − } | |
| 1677 | −} | |
| 1678 | − | |
| 1679 | −/*! | |
| 1680 | − * \brief Force reset current Acess Unit Nal list in case error parsing/decoding in current AU | |
| 1681 | − * \author | |
| 1682 | − * \history 11/16/2009 | |
| 1683 | − */ | |
| 1684 | −void ForceResetCurrentAccessUnit (PAccessUnit pAu) { | |
| 1685 | − uint32_t uiSucAuIdx = pAu->uiEndPos + 1; | |
| 1686 | − uint32_t uiCurAuIdx = 0; | |
| 1687 | − | |
| 1688 | − // swap the succeeding AU's nal units to the front | |
| 1689 | − while (uiSucAuIdx < pAu->uiAvailUnitsNum) { | |
| 1690 | − PNalUnit t = pAu->pNalUnitsList[uiSucAuIdx]; | |
| 1691 | − pAu->pNalUnitsList[uiSucAuIdx] = pAu->pNalUnitsList[uiCurAuIdx]; | |
| 1692 | − pAu->pNalUnitsList[uiCurAuIdx] = t; | |
| 1693 | − ++ uiSucAuIdx; | |
| 1694 | − ++ uiCurAuIdx; | |
| 1695 | − } | |
| 1696 | − | |
| 1697 | − // Update avail/actual units num accordingly for next AU parsing | |
| 1698 | − if (pAu->uiAvailUnitsNum > pAu->uiEndPos) | |
| 1699 | − pAu->uiAvailUnitsNum -= (pAu->uiEndPos + 1); | |
| 1700 | − else | |
| 1701 | − pAu->uiAvailUnitsNum = 0; | |
| 1702 | − pAu->uiActualUnitsNum = 0; | |
| 1703 | − pAu->uiStartPos = 0; | |
| 1704 | − pAu->uiEndPos = 0; | |
| 1705 | − pAu->bCompletedAuFlag = false; | |
| 1706 | −} | |
| 1707 | − | |
| 1708 | −//clear current corrupted NAL from pNalUnitsList | |
| 1709 | −void ForceClearCurrentNal (PAccessUnit pAu) { | |
| 1710 | − if (pAu->uiAvailUnitsNum > 0) | |
| 1711 | − -- pAu->uiAvailUnitsNum; | |
| 1712 | −} | |
| 1713 | − | |
| 1714 | −void ForceResetParaSetStatusAndAUList (PWelsDecoderContext pCtx) { | |
| 1715 | − pCtx->bSpsExistAheadFlag = false; | |
| 1716 | − pCtx->bSubspsExistAheadFlag = false; | |
| 1717 | − pCtx->bPpsExistAheadFlag = false; | |
| 1718 | − | |
| 1719 | − // Force clear the AU list | |
| 1720 | − pCtx->pAccessUnitList->uiAvailUnitsNum = 0; | |
| 1721 | − pCtx->pAccessUnitList->uiActualUnitsNum = 0; | |
| 1722 | − pCtx->pAccessUnitList->uiStartPos = 0; | |
| 1723 | − pCtx->pAccessUnitList->uiEndPos = 0; | |
| 1724 | − pCtx->pAccessUnitList->bCompletedAuFlag = false; | |
| 1725 | −} | |
| 1726 | − | |
| 1727 | −void CheckAvailNalUnitsListContinuity (PWelsDecoderContext pCtx, int32_t iStartIdx, int32_t iEndIdx) { | |
| 1728 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1729 | − | |
| 1730 | − uint8_t uiLastNuDependencyId, uiLastNuLayerDqId; | |
| 1731 | − uint8_t uiCurNuDependencyId, uiCurNuQualityId, uiCurNuLayerDqId, uiCurNuRefLayerDqId; | |
| 1732 | − | |
| 1733 | − int32_t iCurNalUnitIdx = 0; | |
| 1734 | − | |
| 1735 | − //check the continuity of pNalUnitsList forwards (from pIdxNoInterLayerPred to end_postion) | |
| 1736 | − uiLastNuDependencyId = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiDependencyId;//starting nal unit | |
| 1737 | − uiLastNuLayerDqId = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiLayerDqId;//starting nal unit | |
| 1738 | − iCurNalUnitIdx = iStartIdx + 1;//current nal unit | |
| 1739 | − while (iCurNalUnitIdx <= iEndIdx) { | |
| 1740 | − uiCurNuDependencyId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiDependencyId; | |
| 1741 | − uiCurNuQualityId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiQualityId; | |
| 1742 | − uiCurNuLayerDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId; | |
| 1743 | − uiCurNuRefLayerDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalData.sVclNal.sSliceHeaderExt.uiRefLayerDqId; | |
| 1744 | − | |
| 1745 | − if (uiCurNuDependencyId == uiLastNuDependencyId) { | |
| 1746 | − uiLastNuLayerDqId = uiCurNuLayerDqId; | |
| 1747 | − ++ iCurNalUnitIdx; | |
| 1748 | − } else { //uiCurNuDependencyId != uiLastNuDependencyId, new dependency arrive | |
| 1749 | − if (uiCurNuQualityId == 0) { | |
| 1750 | − uiLastNuDependencyId = uiCurNuDependencyId; | |
| 1751 | − if (uiCurNuRefLayerDqId == uiLastNuLayerDqId) { | |
| 1752 | − uiLastNuLayerDqId = uiCurNuLayerDqId; | |
| 1753 | − ++ iCurNalUnitIdx; | |
| 1754 | − } else { //cur_nu_layer_id != next_nu_ref_layer_dq_id, the chain is broken at this point | |
| 1755 | − break; | |
| 1756 | − } | |
| 1757 | − } else { //new dependency arrive, but no base quality layer, so we must stop in this point | |
| 1758 | − break; | |
| 1759 | − } | |
| 1760 | − } | |
| 1761 | − } | |
| 1762 | − | |
| 1763 | − -- iCurNalUnitIdx; | |
| 1764 | − pCurAu->uiEndPos = iCurNalUnitIdx; | |
| 1765 | − pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId; | |
| 1766 | −} | |
| 1767 | − | |
| 1768 | −//main purpose: to support multi-slice and to include all slice which have the same uiDependencyId, uiQualityId and frame_num | |
| 1769 | −//for single slice, pIdxNoInterLayerPred SHOULD NOT be modified | |
| 1770 | −void RefineIdxNoInterLayerPred (PAccessUnit pCurAu, int32_t* pIdxNoInterLayerPred) { | |
| 1771 | − int32_t iLastNalDependId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiDependencyId; | |
| 1772 | − int32_t iLastNalQualityId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiQualityId; | |
| 1773 | − uint8_t uiLastNalTId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiTemporalId; | |
| 1774 | − int32_t iLastNalFrameNum = | |
| 1775 | − pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum; | |
| 1776 | − int32_t iLastNalPoc = | |
| 1777 | − pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1778 | − int32_t iLastNalFirstMb = | |
| 1779 | − pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice; | |
| 1780 | − int32_t iCurNalDependId, iCurNalQualityId, iCurNalTId, iCurNalFrameNum, iCurNalPoc, iCurNalFirstMb, iCurIdx, | |
| 1781 | − iFinalIdxNoInterLayerPred; | |
| 1782 | − | |
| 1783 | − bool bMultiSliceFind = false; | |
| 1784 | − | |
| 1785 | − iFinalIdxNoInterLayerPred = 0; | |
| 1786 | − iCurIdx = *pIdxNoInterLayerPred - 1; | |
| 1787 | − while (iCurIdx >= 0) { | |
| 1788 | − if (pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 1789 | − iCurNalDependId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; | |
| 1790 | − iCurNalQualityId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; | |
| 1791 | − iCurNalTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; | |
| 1792 | − iCurNalFrameNum = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum; | |
| 1793 | − iCurNalPoc = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1794 | − iCurNalFirstMb = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice; | |
| 1795 | − | |
| 1796 | − if (iCurNalDependId == iLastNalDependId && | |
| 1797 | − iCurNalQualityId == iLastNalQualityId && | |
| 1798 | − iCurNalTId == uiLastNalTId && | |
| 1799 | − iCurNalFrameNum == iLastNalFrameNum && | |
| 1800 | − iCurNalPoc == iLastNalPoc && | |
| 1801 | − iCurNalFirstMb != iLastNalFirstMb) { | |
| 1802 | − bMultiSliceFind = true; | |
| 1803 | − iFinalIdxNoInterLayerPred = iCurIdx; | |
| 1804 | − --iCurIdx; | |
| 1805 | − continue; | |
| 1806 | − } else { | |
| 1807 | − break; | |
| 1808 | − } | |
| 1809 | − } | |
| 1810 | − --iCurIdx; | |
| 1811 | − } | |
| 1812 | − | |
| 1813 | − if (bMultiSliceFind && *pIdxNoInterLayerPred != iFinalIdxNoInterLayerPred) { | |
| 1814 | − *pIdxNoInterLayerPred = iFinalIdxNoInterLayerPred; | |
| 1815 | − } | |
| 1816 | −} | |
| 1817 | − | |
| 1818 | −bool CheckPocOfCurValidNalUnits (PAccessUnit pCurAu, int32_t pIdxNoInterLayerPred) { | |
| 1819 | − int32_t iEndIdx = pCurAu->uiEndPos; | |
| 1820 | − int32_t iCurAuPoc = | |
| 1821 | − pCurAu->pNalUnitsList[pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1822 | − int32_t iTmpPoc, i; | |
| 1823 | − for (i = pIdxNoInterLayerPred + 1; i < iEndIdx; i++) { | |
| 1824 | − iTmpPoc = pCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1825 | − if (iTmpPoc != iCurAuPoc) { | |
| 1826 | − return false; | |
| 1827 | − } | |
| 1828 | − } | |
| 1829 | − | |
| 1830 | − return true; | |
| 1831 | −} | |
| 1832 | − | |
| 1833 | −bool CheckIntegrityNalUnitsList (PWelsDecoderContext pCtx) { | |
| 1834 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1835 | − const int32_t kiEndPos = pCurAu->uiEndPos; | |
| 1836 | − int32_t iIdxNoInterLayerPred = 0; | |
| 1837 | − | |
| 1838 | − if (!pCurAu->bCompletedAuFlag) | |
| 1839 | − return false; | |
| 1840 | − | |
| 1841 | − if (pCtx->bNewSeqBegin) { | |
| 1842 | − pCurAu->uiStartPos = 0; | |
| 1843 | − //step1: search the pNalUnit whose iNoInterLayerPredFlag equal to 1 backwards (from uiEndPos to 0) | |
| 1844 | − iIdxNoInterLayerPred = kiEndPos; | |
| 1845 | − while (iIdxNoInterLayerPred >= 0) { | |
| 1846 | − if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 1847 | − break; | |
| 1848 | − } | |
| 1849 | − --iIdxNoInterLayerPred; | |
| 1850 | − } | |
| 1851 | − if (iIdxNoInterLayerPred < 0) { | |
| 1852 | − //can not find the Nal Unit whose no_inter_pred_falg equal to 1, MUST STOP decode | |
| 1853 | − return false; | |
| 1854 | − } | |
| 1855 | − | |
| 1856 | − //step2: support multi-slice, to include all base layer slice | |
| 1857 | − RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 1858 | − pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 1859 | − CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); | |
| 1860 | − | |
| 1861 | − if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 1862 | − return false; | |
| 1863 | − } | |
| 1864 | − | |
| 1865 | − pCtx->iCurSeqIntervalTargetDependId = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalHeaderExt.uiDependencyId; | |
| 1866 | − pCtx->iCurSeqIntervalMaxPicWidth = | |
| 1867 | − pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbWidth << 4; | |
| 1868 | − pCtx->iCurSeqIntervalMaxPicHeight = | |
| 1869 | − pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbHeight << 4; | |
| 1870 | − } else { //P_SLICE | |
| 1871 | − //step 1: search uiDependencyId equal to pCtx->cur_seq_interval_target_dependency_id | |
| 1872 | − bool bGetDependId = false; | |
| 1873 | − int32_t iIdxDependId = 0; | |
| 1874 | − | |
| 1875 | − iIdxDependId = kiEndPos; | |
| 1876 | − while (iIdxDependId >= 0) { | |
| 1877 | − if (pCtx->iCurSeqIntervalTargetDependId == pCurAu->pNalUnitsList[iIdxDependId]->sNalHeaderExt.uiDependencyId) { | |
| 1878 | − bGetDependId = true; | |
| 1879 | − break; | |
| 1880 | − } else { | |
| 1881 | − --iIdxDependId; | |
| 1882 | − } | |
| 1883 | − } | |
| 1884 | − | |
| 1885 | − //step 2: switch according to whether or not find the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId | |
| 1886 | − if (bGetDependId) { //get the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId | |
| 1887 | − bool bGetNoInterPredFront = false; | |
| 1888 | − //step 2a: search iNoInterLayerPredFlag [0....iIdxDependId] | |
| 1889 | − iIdxNoInterLayerPred = iIdxDependId; | |
| 1890 | − while (iIdxNoInterLayerPred >= 0) { | |
| 1891 | − if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 1892 | − bGetNoInterPredFront = true; | |
| 1893 | − break; | |
| 1894 | − } | |
| 1895 | − --iIdxNoInterLayerPred; | |
| 1896 | − } | |
| 1897 | − //step 2b: switch, whether or not find the NAL unit whose no_inter_pred_flag equal to 1 among [0....iIdxDependId] | |
| 1898 | − if (bGetNoInterPredFront) { //YES | |
| 1899 | − RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 1900 | − pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 1901 | − CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, iIdxDependId); | |
| 1902 | − | |
| 1903 | − if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 1904 | − return false; | |
| 1905 | − } | |
| 1906 | − } else { //NO, should find the NAL unit whose no_inter_pred_flag equal to 1 among [iIdxDependId....uiEndPos] | |
| 1907 | − iIdxNoInterLayerPred = iIdxDependId; | |
| 1908 | − while (iIdxNoInterLayerPred <= kiEndPos) { | |
| 1909 | − if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 1910 | − break; | |
| 1911 | − } | |
| 1912 | − ++iIdxNoInterLayerPred; | |
| 1913 | − } | |
| 1914 | − | |
| 1915 | − if (iIdxNoInterLayerPred > kiEndPos) { | |
| 1916 | − return false; //cann't find the index of pNalUnit whose no_inter_pred_flag = 1 | |
| 1917 | − } | |
| 1918 | − | |
| 1919 | − RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 1920 | − pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 1921 | − CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); | |
| 1922 | − | |
| 1923 | − if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 1924 | − return false; | |
| 1925 | − } | |
| 1926 | − } | |
| 1927 | − } else { //without the index of pNalUnit, should process this AU as common case | |
| 1928 | − iIdxNoInterLayerPred = kiEndPos; | |
| 1929 | − while (iIdxNoInterLayerPred >= 0) { | |
| 1930 | − if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 1931 | − break; | |
| 1932 | − } | |
| 1933 | − --iIdxNoInterLayerPred; | |
| 1934 | − } | |
| 1935 | − if (iIdxNoInterLayerPred < 0) { | |
| 1936 | − return false; //cann't find the index of pNalUnit whose iNoInterLayerPredFlag = 1 | |
| 1937 | − } | |
| 1938 | − | |
| 1939 | − RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 1940 | − pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 1941 | − CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); | |
| 1942 | − | |
| 1943 | − if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 1944 | − return false; | |
| 1945 | − } | |
| 1946 | − } | |
| 1947 | − } | |
| 1948 | − | |
| 1949 | − return true; | |
| 1950 | −} | |
| 1951 | − | |
| 1952 | −void CheckOnlyOneLayerInAu (PWelsDecoderContext pCtx) { | |
| 1953 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1954 | − | |
| 1955 | − int32_t iEndIdx = pCurAu->uiEndPos; | |
| 1956 | − int32_t iCurIdx = pCurAu->uiStartPos; | |
| 1957 | − uint8_t uiDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; | |
| 1958 | − uint8_t uiQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; | |
| 1959 | − uint8_t uiTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; | |
| 1960 | − | |
| 1961 | − uint8_t uiCurDId, uiCurQId, uiCurTId; | |
| 1962 | − | |
| 1963 | − pCtx->bOnlyOneLayerInCurAuFlag = true; | |
| 1964 | − | |
| 1965 | − if (iEndIdx == iCurIdx) { //only one NAL in pNalUnitsList | |
| 1966 | − return; | |
| 1967 | − } | |
| 1968 | − | |
| 1969 | − ++iCurIdx; | |
| 1970 | − while (iCurIdx <= iEndIdx) { | |
| 1971 | − uiCurDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; | |
| 1972 | − uiCurQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; | |
| 1973 | − uiCurTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; | |
| 1974 | − | |
| 1975 | − if (uiDId != uiCurDId || uiQId != uiCurQId || uiTId != uiCurTId) { | |
| 1976 | − pCtx->bOnlyOneLayerInCurAuFlag = false; | |
| 1977 | − return; | |
| 1978 | − } | |
| 1979 | − | |
| 1980 | − ++iCurIdx; | |
| 1981 | − } | |
| 1982 | −} | |
| 1983 | − | |
| 1984 | −int32_t WelsDecodeAccessUnitStart (PWelsDecoderContext pCtx) { | |
| 1985 | − // Roll back NAL units not being belong to current access unit list for proceeded access unit | |
| 1986 | − int32_t iRet = UpdateAccessUnit (pCtx); | |
| 1987 | − if (iRet != ERR_NONE) | |
| 1988 | − return iRet; | |
| 1989 | − | |
| 1990 | − pCtx->pAccessUnitList->uiStartPos = 0; | |
| 1991 | − if (!pCtx->bAvcBasedFlag && !CheckIntegrityNalUnitsList (pCtx)) { | |
| 1992 | − pCtx->iErrorCode |= dsBitstreamError; | |
| 1993 | − return dsBitstreamError; | |
| 1994 | − } | |
| 1995 | − | |
| 1996 | − //check current AU has only one layer or not | |
| 1997 | − //If YES, can use deblocking based on AVC | |
| 1998 | − if (!pCtx->bAvcBasedFlag) { | |
| 1999 | − CheckOnlyOneLayerInAu (pCtx); | |
| 2000 | − } | |
| 2001 | − | |
| 2002 | − return ERR_NONE; | |
| 2003 | −} | |
| 2004 | − | |
| 2005 | −void WelsDecodeAccessUnitEnd (PWelsDecoderContext pCtx) { | |
| 2006 | − //save previous header info | |
| 2007 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2008 | − PNalUnit pCurNal = pCurAu->pNalUnitsList[pCurAu->uiEndPos]; | |
| 2009 | − memcpy (&pCtx->sLastNalHdrExt, &pCurNal->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); | |
| 2010 | − memcpy (&pCtx->sLastSliceHeader, | |
| 2011 | − &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader, sizeof (SSliceHeader)); | |
| 2012 | − // uninitialize context of current access unit and rbsp buffer clean | |
| 2013 | − ResetCurrentAccessUnit (pCtx); | |
| 2014 | −} | |
| 2015 | − | |
| 2016 | −/* CheckNewSeqBeginAndUpdateActiveLayerSps | |
| 2017 | − * return: | |
| 2018 | − * true - the AU to be construct is the start of new sequence; false - not | |
| 2019 | − */ | |
| 2020 | −static bool CheckNewSeqBeginAndUpdateActiveLayerSps (PWelsDecoderContext pCtx) { | |
| 2021 | − bool bNewSeq = false; | |
| 2022 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2023 | − PSps pTmpLayerSps[MAX_LAYER_NUM]; | |
| 2024 | − for (int i = 0; i < MAX_LAYER_NUM; i++) { | |
| 2025 | − pTmpLayerSps[i] = NULL; | |
| 2026 | − } | |
| 2027 | − // track the layer sps for the current au | |
| 2028 | − for (unsigned int i = pCurAu->uiStartPos; i <= pCurAu->uiEndPos; i++) { | |
| 2029 | − uint32_t uiDid = pCurAu->pNalUnitsList[i]->sNalHeaderExt.uiDependencyId; | |
| 2030 | − pTmpLayerSps[uiDid] = pCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps; | |
| 2031 | − if ((pCurAu->pNalUnitsList[i]->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR) | |
| 2032 | − || (pCurAu->pNalUnitsList[i]->sNalHeaderExt.bIdrFlag)) | |
| 2033 | − bNewSeq = true; | |
| 2034 | − } | |
| 2035 | − int iMaxActiveLayer = 0, iMaxCurrentLayer = 0; | |
| 2036 | − for (int i = MAX_LAYER_NUM - 1; i >= 0; i--) { | |
| 2037 | − if (pCtx->pActiveLayerSps[i] != NULL) { | |
| 2038 | − iMaxActiveLayer = i; | |
| 2039 | − break; | |
| 2040 | − } | |
| 2041 | − } | |
| 2042 | − for (int i = MAX_LAYER_NUM - 1; i >= 0; i--) { | |
| 2043 | − if (pTmpLayerSps[i] != NULL) { | |
| 2044 | − iMaxCurrentLayer = i; | |
| 2045 | − break; | |
| 2046 | − } | |
| 2047 | − } | |
| 2048 | − if ((iMaxCurrentLayer != iMaxActiveLayer) | |
| 2049 | − || (pTmpLayerSps[iMaxCurrentLayer] != pCtx->pActiveLayerSps[iMaxActiveLayer])) { | |
| 2050 | − bNewSeq = true; | |
| 2051 | − } | |
| 2052 | − // fill active sps if the current sps is not null while active layer is null | |
| 2053 | − if (!bNewSeq) { | |
| 2054 | − for (int i = 0; i < MAX_LAYER_NUM; i++) { | |
| 2055 | − if (pCtx->pActiveLayerSps[i] == NULL && pTmpLayerSps[i] != NULL) { | |
| 2056 | − pCtx->pActiveLayerSps[i] = pTmpLayerSps[i]; | |
| 2057 | − } | |
| 2058 | − } | |
| 2059 | − } else { | |
| 2060 | − // UpdateActiveLayerSps if new sequence start | |
| 2061 | − memcpy (&pCtx->pActiveLayerSps[0], &pTmpLayerSps[0], MAX_LAYER_NUM * sizeof (PSps)); | |
| 2062 | − } | |
| 2063 | − return bNewSeq; | |
| 2064 | −} | |
| 2065 | − | |
| 2066 | −static void WriteBackActiveParameters (PWelsDecoderContext pCtx) { | |
| 2067 | − if (pCtx->iOverwriteFlags & OVERWRITE_PPS) { | |
| 2068 | − memcpy (&pCtx->sPpsBuffer[pCtx->sPpsBuffer[MAX_PPS_COUNT].iPpsId], &pCtx->sPpsBuffer[MAX_PPS_COUNT], sizeof (SPps)); | |
| 2069 | − } | |
| 2070 | − if (pCtx->iOverwriteFlags & OVERWRITE_SPS) { | |
| 2071 | − memcpy (&pCtx->sSpsBuffer[pCtx->sSpsBuffer[MAX_SPS_COUNT].iSpsId], &pCtx->sSpsBuffer[MAX_SPS_COUNT], sizeof (SSps)); | |
| 2072 | − pCtx->bNewSeqBegin = true; | |
| 2073 | − } | |
| 2074 | − if (pCtx->iOverwriteFlags & OVERWRITE_SUBSETSPS) { | |
| 2075 | − memcpy (&pCtx->sSubsetSpsBuffer[pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT].sSps.iSpsId], | |
| 2076 | − &pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT], sizeof (SSubsetSps)); | |
| 2077 | − pCtx->bNewSeqBegin = true; | |
| 2078 | − } | |
| 2079 | − pCtx->iOverwriteFlags = OVERWRITE_NONE; | |
| 2080 | −} | |
| 2081 | − | |
| 2082 | −/* | |
| 2083 | − * DecodeFinishUpdate | |
| 2084 | − * decoder finish decoding, update active parameter sets and new seq status | |
| 2085 | − * | |
| 2086 | − */ | |
| 2087 | − | |
| 2088 | −void DecodeFinishUpdate (PWelsDecoderContext pCtx) { | |
| 2089 | − pCtx->bNewSeqBegin = false; | |
| 2090 | − WriteBackActiveParameters (pCtx); | |
| 2091 | − pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || pCtx->bNextNewSeqBegin; | |
| 2092 | − pCtx->bNextNewSeqBegin = false; // reset it | |
| 2093 | − if (pCtx->bNewSeqBegin) | |
| 2094 | − ResetActiveSPSForEachLayer (pCtx); | |
| 2095 | −} | |
| 2096 | − | |
| 2097 | −/* | |
| 2098 | − * ConstructAccessUnit | |
| 2099 | − * construct an access unit for given input bitstream, maybe partial NAL Unit, one or more Units are involved to | |
| 2100 | − * joint a collective access unit. | |
| 2101 | − * parameter\ | |
| 2102 | − * buf: bitstream data buffer | |
| 2103 | − * bit_len: size in bit length of data | |
| 2104 | − * buf_len: size in byte length of data | |
| 2105 | − * coded_au: mark an Access Unit decoding finished | |
| 2106 | − * return: | |
| 2107 | − * 0 - success; otherwise returned error_no defined in error_no.h | |
| 2108 | − */ | |
| 2109 | −int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { | |
| 2110 | − int32_t iErr; | |
| 2111 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2112 | − pCtx->bAuReadyFlag = false; | |
| 2113 | − pCtx->bLastHasMmco5 = false; | |
| 2114 | − bool bTmpNewSeqBegin = CheckNewSeqBeginAndUpdateActiveLayerSps (pCtx); | |
| 2115 | − pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || bTmpNewSeqBegin; | |
| 2116 | − iErr = WelsDecodeAccessUnitStart (pCtx); | |
| 2117 | − GetVclNalTemporalId (pCtx); | |
| 2118 | − | |
| 2119 | − if (ERR_NONE != iErr) { | |
| 2120 | − ForceResetCurrentAccessUnit (pCtx->pAccessUnitList); | |
| 2121 | − if (!pCtx->pParam->bParseOnly) | |
| 2122 | − pDstInfo->iBufferStatus = 0; | |
| 2123 | − pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || pCtx->bNextNewSeqBegin; | |
| 2124 | − pCtx->bNextNewSeqBegin = false; // reset it | |
| 2125 | − if (pCtx->bNewSeqBegin) | |
| 2126 | − ResetActiveSPSForEachLayer (pCtx); | |
| 2127 | − return iErr; | |
| 2128 | − } | |
| 2129 | − | |
| 2130 | − pCtx->pSps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps; | |
| 2131 | − pCtx->pPps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pPps; | |
| 2132 | − | |
| 2133 | − //try to allocate or relocate DPB memory only when new sequence is coming. | |
| 2134 | − if (pCtx->bNewSeqBegin) { | |
| 2135 | − WelsResetRefPic (pCtx); //clear ref pPic when IDR NAL | |
| 2136 | − iErr = SyncPictureResolutionExt (pCtx, pCtx->pSps->iMbWidth, pCtx->pSps->iMbHeight); | |
| 2137 | − | |
| 2138 | − if (ERR_NONE != iErr) { | |
| 2139 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "sync picture resolution ext failed, the error is %d", iErr); | |
| 2140 | − return iErr; | |
| 2141 | − } | |
| 2142 | − } | |
| 2143 | − | |
| 2144 | − iErr = DecodeCurrentAccessUnit (pCtx, ppDst, pDstInfo); | |
| 2145 | − | |
| 2146 | − WelsDecodeAccessUnitEnd (pCtx); | |
| 2147 | − | |
| 2148 | − if (ERR_NONE != iErr) { | |
| 2149 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "returned error from decoding:[0x%x]", iErr); | |
| 2150 | − return iErr; | |
| 2151 | − } | |
| 2152 | − | |
| 2153 | − return ERR_NONE; | |
| 2154 | −} | |
| 2155 | − | |
| 2156 | −static inline void InitDqLayerInfo (PDqLayer pDqLayer, PLayerInfo pLayerInfo, PNalUnit pNalUnit, PPicture pPicDec) { | |
| 2157 | − PNalUnitHeaderExt pNalHdrExt = &pNalUnit->sNalHeaderExt; | |
| 2158 | − PSliceHeaderExt pShExt = &pNalUnit->sNalData.sVclNal.sSliceHeaderExt; | |
| 2159 | − PSliceHeader pSh = &pShExt->sSliceHeader; | |
| 2160 | − const uint8_t kuiQualityId = pNalHdrExt->uiQualityId; | |
| 2161 | − | |
| 2162 | − memcpy (&pDqLayer->sLayerInfo, pLayerInfo, sizeof (SLayerInfo)); //confirmed_safe_unsafe_usage | |
| 2163 | − | |
| 2164 | − pDqLayer->pDec = pPicDec; | |
| 2165 | − pDqLayer->iMbWidth = pSh->iMbWidth; // MB width of this picture | |
| 2166 | − pDqLayer->iMbHeight = pSh->iMbHeight;// MB height of this picture | |
| 2167 | − | |
| 2168 | − pDqLayer->iSliceIdcBackup = (pSh->iFirstMbInSlice << 7) | (pNalHdrExt->uiDependencyId << 4) | (pNalHdrExt->uiQualityId); | |
| 2169 | − | |
| 2170 | − /* Common syntax elements across all slices of a DQLayer */ | |
| 2171 | − pDqLayer->uiPpsId = pLayerInfo->pPps->iPpsId; | |
| 2172 | − pDqLayer->uiDisableInterLayerDeblockingFilterIdc = pShExt->uiDisableInterLayerDeblockingFilterIdc; | |
| 2173 | − pDqLayer->iInterLayerSliceAlphaC0Offset = pShExt->iInterLayerSliceAlphaC0Offset; | |
| 2174 | − pDqLayer->iInterLayerSliceBetaOffset = pShExt->iInterLayerSliceBetaOffset; | |
| 2175 | − pDqLayer->iSliceGroupChangeCycle = pSh->iSliceGroupChangeCycle; | |
| 2176 | − pDqLayer->bStoreRefBasePicFlag = pShExt->bStoreRefBasePicFlag; | |
| 2177 | − pDqLayer->bTCoeffLevelPredFlag = pShExt->bTCoeffLevelPredFlag; | |
| 2178 | − pDqLayer->bConstrainedIntraResamplingFlag = pShExt->bConstrainedIntraResamplingFlag; | |
| 2179 | − pDqLayer->uiRefLayerDqId = pShExt->uiRefLayerDqId; | |
| 2180 | − pDqLayer->uiRefLayerChromaPhaseXPlus1Flag = pShExt->uiRefLayerChromaPhaseXPlus1Flag; | |
| 2181 | − pDqLayer->uiRefLayerChromaPhaseYPlus1 = pShExt->uiRefLayerChromaPhaseYPlus1; | |
| 2182 | − //memcpy(&pDqLayer->sScaledRefLayer, &pShExt->sScaledRefLayer, sizeof(SPosOffset));//confirmed_safe_unsafe_usage | |
| 2183 | − | |
| 2184 | − if (kuiQualityId == BASE_QUALITY_ID) { | |
| 2185 | − pDqLayer->pRefPicListReordering = &pSh->pRefPicListReordering; | |
| 2186 | − pDqLayer->pRefPicMarking = &pSh->sRefMarking; | |
| 2187 | − | |
| 2188 | − if (pSh->pPps->bWeightedPredFlag) { | |
| 2189 | − pDqLayer->bUseWeightPredictionFlag = true; | |
| 2190 | − pDqLayer->pPredWeightTable = &pSh->sPredWeightTable; | |
| 2191 | − | |
| 2192 | − } else | |
| 2193 | − pDqLayer->bUseWeightPredictionFlag = false; | |
| 2194 | − | |
| 2195 | − pDqLayer->pRefPicBaseMarking = &pShExt->sRefBasePicMarking; | |
| 2196 | − } | |
| 2197 | − | |
| 2198 | − pDqLayer->uiLayerDqId = pNalHdrExt->uiLayerDqId; // dq_id of current layer | |
| 2199 | − pDqLayer->bUseRefBasePicFlag = pNalHdrExt->bUseRefBasePicFlag; | |
| 2200 | −} | |
| 2201 | − | |
| 2202 | −void WelsDqLayerDecodeStart (PWelsDecoderContext pCtx, PNalUnit pCurNal, PSps pSps, PPps pPps) { | |
| 2203 | − PSliceHeader pSh = &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; | |
| 2204 | − | |
| 2205 | − pCtx->eSliceType = pSh->eSliceType; | |
| 2206 | − pCtx->pSliceHeader = pSh; | |
| 2207 | − | |
| 2208 | − pCtx->iFrameNum = pSh->iFrameNum; | |
| 2209 | − | |
| 2210 | − UpdateDecoderStatisticsForActiveParaset (& (pCtx->sDecoderStatistics), | |
| 2211 | − pSps, pPps); | |
| 2212 | −} | |
| 2213 | − | |
| 2214 | −int32_t InitRefPicList (PWelsDecoderContext pCtx, const uint8_t kuiNRi, int32_t iPoc) { | |
| 2215 | − int32_t iRet = ERR_NONE; | |
| 2216 | − iRet = WelsInitRefList (pCtx, iPoc); | |
| 2217 | − if ((pCtx->eSliceType != I_SLICE && pCtx->eSliceType != SI_SLICE)) { | |
| 2218 | − iRet = WelsReorderRefList (pCtx); | |
| 2219 | − } | |
| 2220 | − | |
| 2221 | − return iRet; | |
| 2222 | −} | |
| 2223 | − | |
| 2224 | −void InitCurDqLayerData (PWelsDecoderContext pCtx, PDqLayer pCurDq) { | |
| 2225 | − if (NULL != pCtx && NULL != pCurDq) { | |
| 2226 | − pCurDq->pMbType = pCtx->sMb.pMbType[0]; | |
| 2227 | − pCurDq->pSliceIdc = pCtx->sMb.pSliceIdc[0]; | |
| 2228 | − pCurDq->pMv[0] = pCtx->sMb.pMv[0][0]; | |
| 2229 | − pCurDq->pRefIndex[0] = pCtx->sMb.pRefIndex[0][0]; | |
| 2230 | − pCurDq->pNoSubMbPartSizeLessThan8x8Flag = pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[0]; | |
| 2231 | − pCurDq->pTransformSize8x8Flag = pCtx->sMb.pTransformSize8x8Flag[0]; | |
| 2232 | − pCurDq->pLumaQp = pCtx->sMb.pLumaQp[0]; | |
| 2233 | − pCurDq->pChromaQp = pCtx->sMb.pChromaQp[0]; | |
| 2234 | − pCurDq->pMvd[0] = pCtx->sMb.pMvd[0][0]; | |
| 2235 | − pCurDq->pCbfDc = pCtx->sMb.pCbfDc[0]; | |
| 2236 | − pCurDq->pNzc = pCtx->sMb.pNzc[0]; | |
| 2237 | − pCurDq->pNzcRs = pCtx->sMb.pNzcRs[0]; | |
| 2238 | − pCurDq->pScaledTCoeff = pCtx->sMb.pScaledTCoeff[0]; | |
| 2239 | − pCurDq->pIntraPredMode = pCtx->sMb.pIntraPredMode[0]; | |
| 2240 | − pCurDq->pIntra4x4FinalMode = pCtx->sMb.pIntra4x4FinalMode[0]; | |
| 2241 | − pCurDq->pIntraNxNAvailFlag = pCtx->sMb.pIntraNxNAvailFlag[0]; | |
| 2242 | − pCurDq->pChromaPredMode = pCtx->sMb.pChromaPredMode[0]; | |
| 2243 | − pCurDq->pCbp = pCtx->sMb.pCbp[0]; | |
| 2244 | − pCurDq->pSubMbType = pCtx->sMb.pSubMbType[0]; | |
| 2245 | − pCurDq->pInterPredictionDoneFlag = pCtx->sMb.pInterPredictionDoneFlag[0]; | |
| 2246 | − pCurDq->pResidualPredFlag = pCtx->sMb.pResidualPredFlag[0]; | |
| 2247 | − pCurDq->pMbCorrectlyDecodedFlag = pCtx->sMb.pMbCorrectlyDecodedFlag[0]; | |
| 2248 | − pCurDq->pMbRefConcealedFlag = pCtx->sMb.pMbRefConcealedFlag[0]; | |
| 2249 | − } | |
| 2250 | −} | |
| 2251 | − | |
| 2252 | −/* | |
| 2253 | − * DecodeCurrentAccessUnit | |
| 2254 | − * Decode current access unit when current AU is completed. | |
| 2255 | − */ | |
| 2256 | −int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { | |
| 2257 | − int32_t iRefCount[LIST_A]; | |
| 2258 | − PNalUnit pNalCur = NULL; | |
| 2259 | − PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2260 | − | |
| 2261 | − int32_t iIdx = pCurAu->uiStartPos; | |
| 2262 | − int32_t iEndIdx = pCurAu->uiEndPos; | |
| 2263 | − | |
| 2264 | − int32_t iPpsId = 0; | |
| 2265 | − int32_t iRet = ERR_NONE; | |
| 2266 | − | |
| 2267 | − bool bAllRefComplete = true; // Assume default all ref picutres are complete | |
| 2268 | − | |
| 2269 | − const uint8_t kuiTargetLayerDqId = GetTargetDqId (pCtx->uiTargetDqId, pCtx->pParam); | |
| 2270 | − const uint8_t kuiDependencyIdMax = (kuiTargetLayerDqId & 0x7F) >> 4; | |
| 2271 | − int16_t iLastIdD = -1, iLastIdQ = -1; | |
| 2272 | − int16_t iCurrIdD = 0, iCurrIdQ = 0; | |
| 2273 | − uint8_t uiNalRefIdc = 0; | |
| 2274 | − bool bFreshSliceAvailable = | |
| 2275 | − 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 | |
| 2276 | − | |
| 2277 | − //update pCurDqLayer at the starting of AU decoding | |
| 2278 | − if (pCtx->bInitialDqLayersMem) { | |
| 2279 | − pCtx->pCurDqLayer = pCtx->pDqLayersList[0]; | |
| 2280 | − } | |
| 2281 | − | |
| 2282 | − InitCurDqLayerData (pCtx, pCtx->pCurDqLayer); | |
| 2283 | − | |
| 2284 | − pNalCur = pCurAu->pNalUnitsList[iIdx]; | |
| 2285 | − while (iIdx <= iEndIdx) { | |
| 2286 | − PDqLayer dq_cur = pCtx->pCurDqLayer; | |
| 2287 | − SLayerInfo pLayerInfo; | |
| 2288 | − PSliceHeaderExt pShExt = NULL; | |
| 2289 | − PSliceHeader pSh = NULL; | |
| 2290 | − | |
| 2291 | − if (pCtx->pDec == NULL) { | |
| 2292 | − pCtx->pDec = PrefetchPic (pCtx->pPicBuff[0]); | |
| 2293 | − if (pCtx->iTotalNumMbRec != 0) | |
| 2294 | − pCtx->iTotalNumMbRec = 0; | |
| 2295 | − | |
| 2296 | − if (NULL == pCtx->pDec) { | |
| 2297 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, | |
| 2298 | − "DecodeCurrentAccessUnit()::::::PrefetchPic ERROR, pSps->iNumRefFrames:%d.", | |
| 2299 | − pCtx->pSps->iNumRefFrames); | |
| 2300 | − // The error code here need to be separated from the dsOutOfMemory | |
| 2301 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 2302 | − return ERR_INFO_REF_COUNT_OVERFLOW; | |
| 2303 | − } | |
| 2304 | − pCtx->pDec->bNewSeqBegin = pCtx->bNewSeqBegin; //set flag for start decoding | |
| 2305 | − } else if (pCtx->iTotalNumMbRec == 0) { //pDec != NULL, already start | |
| 2306 | − pCtx->pDec->bNewSeqBegin = pCtx->bNewSeqBegin; //set flag for start decoding | |
| 2307 | − } | |
| 2308 | − pCtx->pDec->uiTimeStamp = pNalCur->uiTimeStamp; | |
| 2309 | − | |
| 2310 | − if (pCtx->iTotalNumMbRec == 0) { //Picture start to decode | |
| 2311 | − for (int32_t i = 0; i < LAYER_NUM_EXCHANGEABLE; ++ i) | |
| 2312 | − memset (pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t))); | |
| 2313 | − memset (pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag, 0, pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight * sizeof (bool)); | |
| 2314 | − memset (pCtx->pCurDqLayer->pMbRefConcealedFlag, 0, pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight * sizeof (bool)); | |
| 2315 | − pCtx->pDec->iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight; | |
| 2316 | − pCtx->pDec->iMbEcedNum = 0; | |
| 2317 | − pCtx->pDec->iMbEcedPropNum = 0; | |
| 2318 | − } | |
| 2319 | − pCtx->bRPLRError = false; | |
| 2320 | − GetI4LumaIChromaAddrTable (pCtx->iDecBlockOffsetArray, pCtx->pDec->iLinesize[0], pCtx->pDec->iLinesize[1]); | |
| 2321 | − | |
| 2322 | − if (pNalCur->sNalHeaderExt.uiLayerDqId > kuiTargetLayerDqId) { // confirmed pNalCur will never be NULL | |
| 2323 | − break; // Per formance it need not to decode the remaining bits any more due to given uiLayerDqId required, 9/2/2009 | |
| 2324 | − } | |
| 2325 | − | |
| 2326 | − memset (&pLayerInfo, 0, sizeof (SLayerInfo)); | |
| 2327 | − | |
| 2328 | − /* | |
| 2329 | − * Loop decoding for slices (even FMO and/ multiple slices) within a dq layer | |
| 2330 | − */ | |
| 2331 | − while (iIdx <= iEndIdx) { | |
| 2332 | − bool bReconstructSlice; | |
| 2333 | − iCurrIdQ = pNalCur->sNalHeaderExt.uiQualityId; | |
| 2334 | − iCurrIdD = pNalCur->sNalHeaderExt.uiDependencyId; | |
| 2335 | − pSh = &pNalCur->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; | |
| 2336 | − pShExt = &pNalCur->sNalData.sVclNal.sSliceHeaderExt; | |
| 2337 | − pCtx->bRPLRError = false; | |
| 2338 | − bReconstructSlice = CheckSliceNeedReconstruct (pNalCur->sNalHeaderExt.uiLayerDqId, kuiTargetLayerDqId); | |
| 2339 | − | |
| 2340 | − memcpy (&pLayerInfo.sNalHeaderExt, &pNalCur->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); //confirmed_safe_unsafe_usage | |
| 2341 | − | |
| 2342 | − pCtx->pDec->iFrameNum = pSh->iFrameNum; | |
| 2343 | − pCtx->pDec->iFramePoc = pSh->iPicOrderCntLsb; // still can not obtain correct, because current do not support POCtype 2 | |
| 2344 | − pCtx->pDec->bIdrFlag = pNalCur->sNalHeaderExt.bIdrFlag; | |
| 2345 | − | |
| 2346 | − memcpy (&pLayerInfo.sSliceInLayer.sSliceHeaderExt, pShExt, sizeof (SSliceHeaderExt)); //confirmed_safe_unsafe_usage | |
| 2347 | − pLayerInfo.sSliceInLayer.bSliceHeaderExtFlag = pNalCur->sNalData.sVclNal.bSliceHeaderExtFlag; | |
| 2348 | − pLayerInfo.sSliceInLayer.eSliceType = pSh->eSliceType; | |
| 2349 | − pLayerInfo.sSliceInLayer.iLastMbQp = pSh->iSliceQp; | |
| 2350 | − dq_cur->pBitStringAux = &pNalCur->sNalData.sVclNal.sSliceBitsRead; | |
| 2351 | − | |
| 2352 | − uiNalRefIdc = pNalCur->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc; | |
| 2353 | − | |
| 2354 | − iPpsId = pSh->iPpsId; | |
| 2355 | − | |
| 2356 | − pLayerInfo.pPps = pSh->pPps; | |
| 2357 | − pLayerInfo.pSps = pSh->pSps; | |
| 2358 | − pLayerInfo.pSubsetSps = pShExt->pSubsetSps; | |
| 2359 | − | |
| 2360 | − pCtx->pFmo = &pCtx->sFmoList[iPpsId]; | |
| 2361 | − iRet = FmoParamUpdate (pCtx->pFmo, pLayerInfo.pSps, pLayerInfo.pPps, &pCtx->iActiveFmoNum, pCtx->pMemAlign); | |
| 2362 | − if (ERR_NONE != iRet) { | |
| 2363 | − if (iRet == ERR_INFO_OUT_OF_MEMORY) { | |
| 2364 | − pCtx->iErrorCode |= dsOutOfMemory; | |
| 2365 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "DecodeCurrentAccessUnit(), Fmo param alloc failed"); | |
| 2366 | − } else { | |
| 2367 | − pCtx->iErrorCode |= dsBitstreamError; | |
| 2368 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "DecodeCurrentAccessUnit(), FmoParamUpdate failed, eSliceType: %d.", | |
| 2369 | − pSh->eSliceType); | |
| 2370 | − } | |
| 2371 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_FMO_INIT_FAIL); | |
| 2372 | − } | |
| 2373 | − | |
| 2374 | − bFreshSliceAvailable = (iCurrIdD != iLastIdD | |
| 2375 | − || iCurrIdQ != iLastIdQ); // do not need condition of (first_mb == 0) due multiple slices might be disorder | |
| 2376 | − | |
| 2377 | − WelsDqLayerDecodeStart (pCtx, pNalCur, pLayerInfo.pSps, pLayerInfo.pPps); | |
| 2378 | − | |
| 2379 | − if (iCurrIdQ == BASE_QUALITY_ID) { | |
| 2380 | − ST64 (iRefCount, LD64 (pLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiRefCount)); | |
| 2381 | − } | |
| 2382 | − | |
| 2383 | − if ((iLastIdD < 0) || //case 1: first layer | |
| 2384 | − (iLastIdD == iCurrIdD)) { //case 2: same uiDId | |
| 2385 | − InitDqLayerInfo (dq_cur, &pLayerInfo, pNalCur, pCtx->pDec); | |
| 2386 | − | |
| 2387 | − if (!dq_cur->sLayerInfo.pSps->bGapsInFrameNumValueAllowedFlag) { | |
| 2388 | − const bool kbIdrFlag = dq_cur->sLayerInfo.sNalHeaderExt.bIdrFlag | |
| 2389 | − || (dq_cur->sLayerInfo.sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR); | |
| 2390 | − // Subclause 8.2.5.2 Decoding process for gaps in frame_num | |
| 2391 | − if (!kbIdrFlag && | |
| 2392 | − pSh->iFrameNum != pCtx->iPrevFrameNum && | |
| 2393 | − pSh->iFrameNum != ((pCtx->iPrevFrameNum + 1) & ((1 << dq_cur->sLayerInfo.pSps->uiLog2MaxFrameNum) - 1))) { | |
| 2394 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, | |
| 2395 | − "referencing pictures lost due frame gaps exist, prev_frame_num: %d, curr_frame_num: %d", pCtx->iPrevFrameNum, | |
| 2396 | − pSh->iFrameNum); | |
| 2397 | − | |
| 2398 | − bAllRefComplete = false; | |
| 2399 | − pCtx->iErrorCode |= dsRefLost; | |
| 2400 | − if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 2401 | −#ifdef LONG_TERM_REF | |
| 2402 | − pCtx->bParamSetsLostFlag = true; | |
| 2403 | −#else | |
| 2404 | − pCtx->bReferenceLostAtT0Flag = true; | |
| 2405 | −#endif | |
| 2406 | − return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_REFERENCE_PIC_LOST); | |
| 2407 | − } | |
| 2408 | − } | |
| 2409 | − } | |
| 2410 | − | |
| 2411 | − if (iCurrIdD == kuiDependencyIdMax && iCurrIdQ == BASE_QUALITY_ID) { | |
| 2412 | − iRet = InitRefPicList (pCtx, uiNalRefIdc, pSh->iPicOrderCntLsb); | |
| 2413 | − if (iRet) { | |
| 2414 | − pCtx->bRPLRError = true; | |
| 2415 | − bAllRefComplete = false; // RPLR error, set ref pictures complete flag false | |
| 2416 | − HandleReferenceLost (pCtx, pNalCur); | |
| 2417 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, | |
| 2418 | − "reference picture introduced by this frame is lost during transmission! uiTId: %d", | |
| 2419 | − pNalCur->sNalHeaderExt.uiTemporalId); | |
| 2420 | − if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 2421 | − if (pCtx->iTotalNumMbRec == 0) | |
| 2422 | − pCtx->pDec = NULL; | |
| 2423 | − return iRet; | |
| 2424 | − } | |
| 2425 | − } | |
| 2426 | − } | |
| 2427 | − | |
| 2428 | − iRet = WelsDecodeSlice (pCtx, bFreshSliceAvailable, pNalCur); | |
| 2429 | − | |
| 2430 | − //Output good store_base reconstruction when enhancement quality layer occurred error for MGS key picture case | |
| 2431 | − if (iRet != ERR_NONE) { | |
| 2432 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, | |
| 2433 | − "DecodeCurrentAccessUnit() failed (%d) in frame: %d uiDId: %d uiQId: %d", | |
| 2434 | − iRet, pSh->iFrameNum, iCurrIdD, iCurrIdQ); | |
| 2435 | − bAllRefComplete = false; | |
| 2436 | − HandleReferenceLostL0 (pCtx, pNalCur); | |
| 2437 | − if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 2438 | − if (pCtx->iTotalNumMbRec == 0) | |
| 2439 | − pCtx->pDec = NULL; | |
| 2440 | − return iRet; | |
| 2441 | − } | |
| 2442 | − } | |
| 2443 | − | |
| 2444 | − if (bReconstructSlice) { | |
| 2445 | − if ((iRet = WelsDecodeConstructSlice (pCtx, pNalCur)) != ERR_NONE) { | |
| 2446 | − pCtx->pDec->bIsComplete = false; // reconstruction error, directly set the flag false | |
| 2447 | − return iRet; | |
| 2448 | − } | |
| 2449 | − } | |
| 2450 | − if (bAllRefComplete && pCtx->eSliceType != I_SLICE) { | |
| 2451 | − if (pCtx->sRefPic.uiRefCount[LIST_0] > 0) { | |
| 2452 | − bAllRefComplete &= CheckRefPicturesComplete (pCtx); | |
| 2453 | − } else { | |
| 2454 | − bAllRefComplete = false; | |
| 2455 | − } | |
| 2456 | − } | |
| 2457 | − } | |
| 2458 | −#if defined (_DEBUG) && !defined (CODEC_FOR_TESTBED) | |
| 2459 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "cur_frame : %d\tiCurrIdD : %d\n ", | |
| 2460 | − dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFrameNum, iCurrIdD); | |
| 2461 | −#endif//#if !CODEC_FOR_TESTBED | |
| 2462 | − iLastIdD = iCurrIdD; | |
| 2463 | − iLastIdQ = iCurrIdQ; | |
| 2464 | − | |
| 2465 | − //pNalUnitsList overflow. | |
| 2466 | − ++ iIdx; | |
| 2467 | − if (iIdx <= iEndIdx) { | |
| 2468 | − pNalCur = pCurAu->pNalUnitsList[iIdx]; | |
| 2469 | − } else { | |
| 2470 | − pNalCur = NULL; | |
| 2471 | − } | |
| 2472 | − | |
| 2473 | − if (pNalCur == NULL || | |
| 2474 | − iLastIdD != pNalCur->sNalHeaderExt.uiDependencyId || | |
| 2475 | − iLastIdQ != pNalCur->sNalHeaderExt.uiQualityId) | |
| 2476 | − break; | |
| 2477 | − } | |
| 2478 | − | |
| 2479 | − // Set the current dec picture complete flag. The flag will be reset when current picture need do ErrorCon. | |
| 2480 | − pCtx->pDec->bIsComplete = bAllRefComplete; | |
| 2481 | − if (!pCtx->pDec->bIsComplete) { // Ref pictures ECed, result in ECed | |
| 2482 | − pCtx->iErrorCode |= dsDataErrorConcealed; | |
| 2483 | − } | |
| 2484 | − | |
| 2485 | − // A dq layer decoded here | |
| 2486 | −#if defined (_DEBUG) && !defined (CODEC_FOR_TESTBED) | |
| 2487 | −#undef fprintf | |
| 2488 | − WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "POC: #%d, FRAME: #%d, D: %d, Q: %d, T: %d, P: %d, %d\n", | |
| 2489 | − pSh->iPicOrderCntLsb, pSh->iFrameNum, iCurrIdD, iCurrIdQ, dq_cur->sLayerInfo.sNalHeaderExt.uiTemporalId, | |
| 2490 | − dq_cur->sLayerInfo.sNalHeaderExt.uiPriorityId, dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceQp); | |
| 2491 | −#endif//#if !CODEC_FOR_TESTBED | |
| 2492 | − | |
| 2493 | − if (dq_cur->uiLayerDqId == kuiTargetLayerDqId) { | |
| 2494 | − if (!pCtx->bInstantDecFlag) { | |
| 2495 | − if (!pCtx->pParam->bParseOnly) { | |
| 2496 | − //Do error concealment here | |
| 2497 | − if ((NeedErrorCon (pCtx)) && (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE)) { | |
| 2498 | − ImplementErrorCon (pCtx); | |
| 2499 | − pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight; | |
| 2500 | − pCtx->pDec->iSpsId = pCtx->pSps->iSpsId; | |
| 2501 | − pCtx->pDec->iPpsId = pCtx->pPps->iPpsId; | |
| 2502 | − } | |
| 2503 | − } | |
| 2504 | − } | |
| 2505 | − | |
| 2506 | − iRet = DecodeFrameConstruction (pCtx, ppDst, pDstInfo); | |
| 2507 | − if (iRet) | |
| 2508 | − return iRet; | |
| 2509 | − | |
| 2510 | − pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //store latest decoded picture for EC | |
| 2511 | − if (uiNalRefIdc > 0) { | |
| 2512 | − iRet = WelsMarkAsRef (pCtx); | |
| 2513 | − if (iRet != ERR_NONE) { | |
| 2514 | − if (iRet == ERR_INFO_DUPLICATE_FRAME_NUM) | |
| 2515 | − pCtx->iErrorCode |= dsBitstreamError; | |
| 2516 | − if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 2517 | − pCtx->pDec = NULL; | |
| 2518 | − return iRet; | |
| 2519 | − } | |
| 2520 | − } | |
| 2521 | − if (!pCtx->pParam->bParseOnly) | |
| 2522 | − ExpandReferencingPicture (pCtx->pDec->pData, pCtx->pDec->iWidthInPixel, pCtx->pDec->iHeightInPixel, | |
| 2523 | − pCtx->pDec->iLinesize, | |
| 2524 | − pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture); | |
| 2525 | − } | |
| 2526 | − pCtx->pDec = NULL; //after frame decoding, always set to NULL | |
| 2527 | − } | |
| 2528 | − | |
| 2529 | − // need update frame_num due current frame is well decoded | |
| 2530 | − if (pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc > 0) | |
| 2531 | − pCtx->iPrevFrameNum = pSh->iFrameNum; | |
| 2532 | − if (pCtx->bLastHasMmco5) | |
| 2533 | − pCtx->iPrevFrameNum = 0; | |
| 2534 | − } | |
| 2535 | − | |
| 2536 | − return ERR_NONE; | |
| 2537 | −} | |
| 2538 | − | |
| 2539 | −bool CheckAndFinishLastPic (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { | |
| 2540 | − PAccessUnit pAu = pCtx->pAccessUnitList; | |
| 2541 | − bool bAuBoundaryFlag = false; | |
| 2542 | − if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) { //VCL data, AU list should have data | |
| 2543 | − PNalUnit pCurNal = pAu->pNalUnitsList[pAu->uiEndPos]; | |
| 2544 | − bAuBoundaryFlag = (pCtx->iTotalNumMbRec != 0) | |
| 2545 | − && (CheckAccessUnitBoundaryExt (&pCtx->sLastNalHdrExt, &pCurNal->sNalHeaderExt, &pCtx->sLastSliceHeader, | |
| 2546 | − &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader)); | |
| 2547 | − } else { //non VCL | |
| 2548 | − if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_AU_DELIMITER) { | |
| 2549 | − bAuBoundaryFlag = true; | |
| 2550 | − } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_SEI) { | |
| 2551 | − bAuBoundaryFlag = true; | |
| 2552 | − } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_SPS) { | |
| 2553 | − bAuBoundaryFlag = !! (pCtx->iOverwriteFlags & OVERWRITE_SPS); | |
| 2554 | − } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_SUBSET_SPS) { | |
| 2555 | − bAuBoundaryFlag = !! (pCtx->iOverwriteFlags & OVERWRITE_SUBSETSPS); | |
| 2556 | − } else if (pCtx->sCurNalHead.eNalUnitType == NAL_UNIT_PPS) { | |
| 2557 | − bAuBoundaryFlag = !! (pCtx->iOverwriteFlags & OVERWRITE_PPS); | |
| 2558 | − } | |
| 2559 | − if (bAuBoundaryFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) { //Construct remaining data first | |
| 2560 | − ConstructAccessUnit (pCtx, ppDst, pDstInfo); | |
| 2561 | − } | |
| 2562 | − } | |
| 2563 | − | |
| 2564 | − //Do Error Concealment here | |
| 2565 | − if (bAuBoundaryFlag && (pCtx->iTotalNumMbRec != 0) && NeedErrorCon (pCtx)) { //AU ready but frame not completely reconed | |
| 2566 | − if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) { | |
| 2567 | − ImplementErrorCon (pCtx); | |
| 2568 | − pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight; | |
| 2569 | − pCtx->pDec->iSpsId = pCtx->pSps->iSpsId; | |
| 2570 | − pCtx->pDec->iPpsId = pCtx->pPps->iPpsId; | |
| 2571 | − | |
| 2572 | − DecodeFrameConstruction (pCtx, ppDst, pDstInfo); | |
| 2573 | − pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future use | |
| 2574 | − if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) { | |
| 2575 | − MarkECFrameAsRef (pCtx); | |
| 2576 | − } | |
| 2577 | − } else if (pCtx->pParam->bParseOnly) { //clear parse only internal data status | |
| 2578 | − pCtx->pParserBsInfo->iNalNum = 0; | |
| 2579 | − pCtx->bFrameFinish = true; //clear frame pending status here! | |
| 2580 | − } else { | |
| 2581 | − if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) { | |
| 2582 | − if ((pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) && (pCtx->sLastNalHdrExt.uiTemporalId == 0)) | |
| 2583 | − pCtx->iErrorCode |= dsNoParamSets; | |
| 2584 | − else | |
| 2585 | − pCtx->iErrorCode |= dsBitstreamError; | |
| 2586 | − pCtx->pDec = NULL; | |
| 2587 | − return false; | |
| 2588 | − } | |
| 2589 | − } | |
| 2590 | − pCtx->pDec = NULL; | |
| 2591 | − if (pAu->pNalUnitsList[pAu->uiStartPos]->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc > 0) | |
| 2592 | − pCtx->iPrevFrameNum = pCtx->sLastSliceHeader.iFrameNum; //save frame_num | |
| 2593 | − if (pCtx->bLastHasMmco5) | |
| 2594 | − pCtx->iPrevFrameNum = 0; | |
| 2595 | − } | |
| 2596 | − return ERR_NONE; | |
| 2597 | −} | |
| 2598 | − | |
| 2599 | −bool CheckRefPicturesComplete (PWelsDecoderContext pCtx) { | |
| 2600 | − // Multi Reference, RefIdx may differ | |
| 2601 | − bool bAllRefComplete = true; | |
| 2602 | − int32_t iRealMbIdx = pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice; | |
| 2603 | − for (int32_t iMbIdx = 0; bAllRefComplete | |
| 2604 | − && iMbIdx < pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; iMbIdx++) { | |
| 2605 | − switch (pCtx->pCurDqLayer->pMbType[iRealMbIdx]) { | |
| 2606 | − case MB_TYPE_SKIP: | |
| 2607 | − case MB_TYPE_16x16: | |
| 2608 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete; | |
| 2609 | − break; | |
| 2610 | − | |
| 2611 | − case MB_TYPE_16x8: | |
| 2612 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete; | |
| 2613 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][8] ]->bIsComplete; | |
| 2614 | − break; | |
| 2615 | − | |
| 2616 | − case MB_TYPE_8x16: | |
| 2617 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete; | |
| 2618 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][2] ]->bIsComplete; | |
| 2619 | − break; | |
| 2620 | − | |
| 2621 | − case MB_TYPE_8x8: | |
| 2622 | − case MB_TYPE_8x8_REF0: | |
| 2623 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete; | |
| 2624 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][2] ]->bIsComplete; | |
| 2625 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][8] ]->bIsComplete; | |
| 2626 | − bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][10] ]->bIsComplete; | |
| 2627 | − break; | |
| 2628 | − | |
| 2629 | − default: | |
| 2630 | − break; | |
| 2631 | − } | |
| 2632 | − iRealMbIdx = (pCtx->pPps->uiNumSliceGroups > 1) ? FmoNextMb (pCtx->pFmo, iRealMbIdx) : | |
| 2633 | − (pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice + iMbIdx); | |
| 2634 | − if (iRealMbIdx == -1) //caused by abnormal return of FmoNextMb() | |
| 2635 | − return false; | |
| 2636 | − } | |
| 2637 | − return bAllRefComplete; | |
| 2638 | −} | |
| 2639 | −} // namespace WelsDec | |
| 1 | +/*! | |
| 2 | + * \copy | |
| 3 | + * Copyright (c) 2013, Cisco Systems | |
| 4 | + * All rights reserved. | |
| 5 | + * | |
| 6 | + * Redistribution and use in source and binary forms, with or without | |
| 7 | + * modification, are permitted provided that the following conditions | |
| 8 | + * are met: | |
| 9 | + * | |
| 10 | + * * Redistributions of source code must retain the above copyright | |
| 11 | + * notice, this list of conditions and the following disclaimer. | |
| 12 | + * | |
| 13 | + * * Redistributions in binary form must reproduce the above copyright | |
| 14 | + * notice, this list of conditions and the following disclaimer in | |
| 15 | + * the documentation and/or other materials provided with the | |
| 16 | + * distribution. | |
| 17 | + * | |
| 18 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 21 | + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 22 | + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 23 | + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 24 | + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 25 | + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| 26 | + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 27 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
| 28 | + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 29 | + * POSSIBILITY OF SUCH DAMAGE. | |
| 30 | + * | |
| 31 | + * decoder_core.c: Wels decoder framework core implementation | |
| 32 | + */ | |
| 33 | + | |
| 34 | +#include "decoder_core.h" | |
| 35 | +#include "error_code.h" | |
| 36 | +#include "memmgr_nal_unit.h" | |
| 37 | +#include "au_parser.h" | |
| 38 | +#include "decode_slice.h" | |
| 39 | +#include "manage_dec_ref.h" | |
| 40 | +#include "expand_pic.h" | |
| 41 | +#include "decoder.h" | |
| 42 | +#include "decode_mb_aux.h" | |
| 43 | +#include "memory_align.h" | |
| 44 | +#include "error_concealment.h" | |
| 45 | + | |
| 46 | +namespace WelsDec { | |
| 47 | +static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { | |
| 48 | + PDqLayer pCurDq = pCtx->pCurDqLayer; | |
| 49 | + PPicture pPic = pCtx->pDec; | |
| 50 | + | |
| 51 | + const int32_t kiWidth = pCurDq->iMbWidth << 4; | |
| 52 | + const int32_t kiHeight = pCurDq->iMbHeight << 4; | |
| 53 | + | |
| 54 | + const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight; | |
| 55 | + bool bFrameCompleteFlag = true; | |
| 56 | + | |
| 57 | + if (pPic->bNewSeqBegin) { | |
| 58 | + memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), | |
| 59 | + sizeof (SPosOffset)); //confirmed_safe_unsafe_usage | |
| 60 | +#ifdef LONG_TERM_REF | |
| 61 | + pCtx->bParamSetsLostFlag = false; | |
| 62 | +#else | |
| 63 | + pCtx->bReferenceLostAtT0Flag = false; // need initialize it due new seq, 6/4/2010 | |
| 64 | +#endif //LONG_TERM_REF | |
| 65 | + if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { | |
| 66 | + pCtx->bPrintFrameErrorTraceFlag = true; | |
| 67 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 68 | + "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.", | |
| 69 | + kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, | |
| 70 | + pCtx->sFrameCrop.iBottomOffset, pCtx->iIgnoredErrorInfoPacketCount); | |
| 71 | + pCtx->iIgnoredErrorInfoPacketCount = 0; | |
| 72 | + } | |
| 73 | + } | |
| 74 | + | |
| 75 | + const int32_t kiActualWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; | |
| 76 | + const int32_t kiActualHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; | |
| 77 | + | |
| 78 | + | |
| 79 | + if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 80 | + if ((pCtx->sDecoderStatistics.uiWidth != (unsigned int) kiActualWidth) | |
| 81 | + || (pCtx->sDecoderStatistics.uiHeight != (unsigned int) kiActualHeight)) { | |
| 82 | + pCtx->sDecoderStatistics.uiResolutionChangeTimes++; | |
| 83 | + pCtx->sDecoderStatistics.uiWidth = kiActualWidth; | |
| 84 | + pCtx->sDecoderStatistics.uiHeight = kiActualHeight; | |
| 85 | + } | |
| 86 | + UpdateDecStatNoFreezingInfo (pCtx); | |
| 87 | + } | |
| 88 | + | |
| 89 | + if (pCtx->pParam->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo | |
| 90 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 91 | + if (dsErrorFree == pCtx->iErrorCode) { //correct decoding, add to data buffer | |
| 92 | + SParserBsInfo* pParser = pCtx->pParserBsInfo; | |
| 93 | + SNalUnit* pCurNal = NULL; | |
| 94 | + int32_t iTotalNalLen = 0; | |
| 95 | + int32_t iNalLen = 0; | |
| 96 | + int32_t iNum = 0; | |
| 97 | + while (iNum < pParser->iNalNum) { | |
| 98 | + iTotalNalLen += pParser->pNalLenInByte[iNum++]; | |
| 99 | + } | |
| 100 | + uint8_t* pDstBuf = pParser->pDstBuff + iTotalNalLen; | |
| 101 | + int32_t iIdx = pCurAu->uiStartPos; | |
| 102 | + int32_t iEndIdx = pCurAu->uiEndPos; | |
| 103 | + uint8_t* pNalBs = NULL; | |
| 104 | + pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0; | |
| 105 | + //pParser->iNalNum = 0; | |
| 106 | + pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4) - ((pCtx->pSps->sFrameCrop.iLeftOffset + | |
| 107 | + pCtx->pSps->sFrameCrop.iRightOffset) << 1); | |
| 108 | + pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4) - ((pCtx->pSps->sFrameCrop.iTopOffset + | |
| 109 | + pCtx->pSps->sFrameCrop.iBottomOffset) << 1); | |
| 110 | + | |
| 111 | + if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR | |
| 112 | + if (pCtx->bFrameFinish) { //add required sps/pps | |
| 113 | + if (pParser->iNalNum > pCtx->iMaxNalNum - 2) { //2 reserved for sps+pps | |
| 114 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 115 | + "DecodeFrameConstruction(): current NAL num (%d) plus sps & pps exceeds permitted num (%d). Will expand", | |
| 116 | + pParser->iNalNum, pCtx->iMaxNalNum); | |
| 117 | + WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + 2)) | |
| 118 | + } | |
| 119 | + bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType); | |
| 120 | + SSpsBsInfo* pSpsBs = NULL; | |
| 121 | + SPpsBsInfo* pPpsBs = NULL; | |
| 122 | + int32_t iSpsId = pCtx->pSps->iSpsId; | |
| 123 | + int32_t iPpsId = pCtx->pPps->iPpsId; | |
| 124 | + pCtx->bParamSetsLostFlag = false; | |
| 125 | + //find required sps, pps and write into dst buff | |
| 126 | + pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId]; | |
| 127 | + pPpsBs = &pCtx->sPpsBsInfo [iPpsId]; | |
| 128 | + if (pDstBuf - pParser->pDstBuff + pSpsBs->uiSpsBsLen + pPpsBs->uiPpsBsLen >= MAX_ACCESS_UNIT_CAPACITY) { | |
| 129 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, | |
| 130 | + "DecodeFrameConstruction(): sps pps size: (%d %d) too large. Failed to parse. \n", pSpsBs->uiSpsBsLen, | |
| 131 | + pPpsBs->uiPpsBsLen); | |
| 132 | + pCtx->iErrorCode |= dsOutOfMemory; | |
| 133 | + pCtx->pParserBsInfo->iNalNum = 0; | |
| 134 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 135 | + } | |
| 136 | + memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen); | |
| 137 | + pParser->pNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen; | |
| 138 | + pDstBuf += pSpsBs->uiSpsBsLen; | |
| 139 | + memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen); | |
| 140 | + pParser->pNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen; | |
| 141 | + pDstBuf += pPpsBs->uiPpsBsLen; | |
| 142 | + pCtx->bFrameFinish = false; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + //then VCL data re-write | |
| 146 | + if (pParser->iNalNum + iEndIdx - iIdx + 1 > pCtx->iMaxNalNum) { //calculate total NAL num | |
| 147 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 148 | + "DecodeFrameConstruction(): current NAL num (%d) exceeds permitted num (%d). Will expand", | |
| 149 | + pParser->iNalNum + iEndIdx - iIdx + 1, pCtx->iMaxNalNum); | |
| 150 | + WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + iEndIdx - iIdx + 1)) | |
| 151 | + } | |
| 152 | + while (iIdx <= iEndIdx) { | |
| 153 | + pCurNal = pCurAu->pNalUnitsList [iIdx ++]; | |
| 154 | + iNalLen = pCurNal->sNalData.sVclNal.iNalLength; | |
| 155 | + pNalBs = pCurNal->sNalData.sVclNal.pNalPos; | |
| 156 | + pParser->pNalLenInByte [pParser->iNalNum ++] = iNalLen; | |
| 157 | + if (pDstBuf - pParser->pDstBuff + iNalLen >= MAX_ACCESS_UNIT_CAPACITY) { | |
| 158 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, | |
| 159 | + "DecodeFrameConstruction(): composed output size (%ld) exceeds (%d). Failed to parse. current data pos %d out of %d:, previously accumulated num: %d, total num: %d, previously accumulated len: %d, current len: %d, current buf pos: %p, header buf pos: %p \n", | |
| 160 | + (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY, iIdx, iEndIdx, iNum, pParser->iNalNum, | |
| 161 | + iTotalNalLen, iNalLen, pDstBuf, pParser->pDstBuff); | |
| 162 | + pCtx->iErrorCode |= dsOutOfMemory; | |
| 163 | + pCtx->pParserBsInfo->iNalNum = 0; | |
| 164 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 165 | + } | |
| 166 | + | |
| 167 | + memcpy (pDstBuf, pNalBs, iNalLen); | |
| 168 | + pDstBuf += iNalLen; | |
| 169 | + } | |
| 170 | + if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { //frame complete | |
| 171 | + pCtx->iTotalNumMbRec = 0; | |
| 172 | + pCtx->bFramePending = false; | |
| 173 | + pCtx->bFrameFinish = true; //finish current frame and mark it | |
| 174 | + } else if (pCtx->iTotalNumMbRec != 0) { //frame incomplete | |
| 175 | + pCtx->bFramePending = true; | |
| 176 | + pCtx->pDec->bIsComplete = false; | |
| 177 | + pCtx->bFrameFinish = false; //current frame not finished | |
| 178 | + pCtx->iErrorCode |= dsFramePending; | |
| 179 | + return ERR_INFO_PARSEONLY_PENDING; | |
| 180 | + //pCtx->pParserBsInfo->iNalNum = 0; | |
| 181 | + } | |
| 182 | + } else { //error | |
| 183 | + pCtx->pParserBsInfo->uiOutBsTimeStamp = 0; | |
| 184 | + pCtx->pParserBsInfo->iNalNum = 0; | |
| 185 | + pCtx->pParserBsInfo->iSpsWidthInPixel = 0; | |
| 186 | + pCtx->pParserBsInfo->iSpsHeightInPixel = 0; | |
| 187 | + return ERR_INFO_PARSEONLY_ERROR; | |
| 188 | + } | |
| 189 | + return ERR_NONE; | |
| 190 | + } | |
| 191 | + | |
| 192 | + if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) { | |
| 193 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, | |
| 194 | + "DecodeFrameConstruction(): iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ", | |
| 195 | + pCtx->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight); | |
| 196 | + bFrameCompleteFlag = false; //return later after output buffer is done | |
| 197 | + if (pCtx->bInstantDecFlag) //no-delay decoding, wait for new slice | |
| 198 | + return ERR_INFO_MB_NUM_INADEQUATE; | |
| 199 | + } else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag | |
| 200 | + && (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done | |
| 201 | + pCtx->pDec->bIsComplete = true; | |
| 202 | + pCtx->bFreezeOutput = false; | |
| 203 | + } | |
| 204 | + | |
| 205 | + pCtx->iTotalNumMbRec = 0; | |
| 206 | + | |
| 207 | + //////output:::normal path | |
| 208 | + pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp; | |
| 209 | + ppDst[0] = pPic->pData[0]; | |
| 210 | + ppDst[1] = pPic->pData[1]; | |
| 211 | + ppDst[2] = pPic->pData[2]; | |
| 212 | + | |
| 213 | + pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420; | |
| 214 | + | |
| 215 | + pDstInfo->UsrData.sSystemBuffer.iWidth = kiActualWidth; | |
| 216 | + pDstInfo->UsrData.sSystemBuffer.iHeight = kiActualHeight; | |
| 217 | + pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; | |
| 218 | + pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; | |
| 219 | + ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; | |
| 220 | + ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; | |
| 221 | + ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; | |
| 222 | + pDstInfo->iBufferStatus = 1; | |
| 223 | + | |
| 224 | + bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth) | |
| 225 | + || (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight); | |
| 226 | + pCtx->iLastImgWidthInPixel = pDstInfo->UsrData.sSystemBuffer.iWidth; | |
| 227 | + pCtx->iLastImgHeightInPixel = pDstInfo->UsrData.sSystemBuffer.iHeight; | |
| 228 | + if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete | |
| 229 | + pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag | |
| 230 | + && pPic->bIsComplete); // When EC disable, ECed picture not output | |
| 231 | + else if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE | |
| 232 | + || pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) | |
| 233 | + && pCtx->iErrorCode && bOutResChange) | |
| 234 | + pCtx->bFreezeOutput = true; | |
| 235 | + | |
| 236 | + if (pDstInfo->iBufferStatus == 0) { | |
| 237 | + if (!bFrameCompleteFlag) | |
| 238 | + pCtx->iErrorCode |= dsBitstreamError; | |
| 239 | + return ERR_INFO_MB_NUM_INADEQUATE; | |
| 240 | + } | |
| 241 | + if (pCtx->bFreezeOutput) { | |
| 242 | + pDstInfo->iBufferStatus = 0; | |
| 243 | + if (pPic->bNewSeqBegin) { | |
| 244 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, | |
| 245 | + "DecodeFrameConstruction():New sequence detected, but freezed, correct MBs (%d) out of whole MBs (%d).", | |
| 246 | + kiTotalNumMbInCurLayer - pCtx->iMbEcedNum, kiTotalNumMbInCurLayer); | |
| 247 | + } | |
| 248 | + } | |
| 249 | + pCtx->iMbEcedNum = pPic->iMbEcedNum; | |
| 250 | + pCtx->iMbNum = pPic->iMbNum; | |
| 251 | + pCtx->iMbEcedPropNum = pPic->iMbEcedPropNum; | |
| 252 | + if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) { | |
| 253 | + if (pDstInfo->iBufferStatus && ((pCtx->sDecoderStatistics.uiWidth != (unsigned int) kiActualWidth) | |
| 254 | + || (pCtx->sDecoderStatistics.uiHeight != (unsigned int) kiActualHeight))) { | |
| 255 | + pCtx->sDecoderStatistics.uiResolutionChangeTimes++; | |
| 256 | + pCtx->sDecoderStatistics.uiWidth = kiActualWidth; | |
| 257 | + pCtx->sDecoderStatistics.uiHeight = kiActualHeight; | |
| 258 | + } | |
| 259 | + UpdateDecStat (pCtx, pDstInfo->iBufferStatus != 0); | |
| 260 | + } | |
| 261 | + return ERR_NONE; | |
| 262 | +} | |
| 263 | + | |
| 264 | +inline bool CheckSliceNeedReconstruct (uint8_t uiLayerDqId, uint8_t uiTargetDqId) { | |
| 265 | + return (uiLayerDqId == uiTargetDqId); // target layer | |
| 266 | +} | |
| 267 | + | |
| 268 | +inline uint8_t GetTargetDqId (uint8_t uiTargetDqId, SDecodingParam* psParam) { | |
| 269 | + uint8_t uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255; | |
| 270 | + | |
| 271 | + return WELS_MIN (uiTargetDqId, uiRequiredDqId); | |
| 272 | +} | |
| 273 | + | |
| 274 | + | |
| 275 | +inline void HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) { | |
| 276 | + if (0 == pCurNal->sNalHeaderExt.uiTemporalId) { | |
| 277 | + pCtx->bReferenceLostAtT0Flag = true; | |
| 278 | + } | |
| 279 | + pCtx->iErrorCode |= dsBitstreamError; | |
| 280 | +} | |
| 281 | + | |
| 282 | +inline void HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) { | |
| 283 | + if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) { | |
| 284 | + pCtx->bReferenceLostAtT0Flag = true; | |
| 285 | + } | |
| 286 | + pCtx->iErrorCode |= dsRefLost; | |
| 287 | +} | |
| 288 | + | |
| 289 | +inline int32_t WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) { | |
| 290 | + int32_t iRet = WelsTargetSliceConstruction (pCtx); | |
| 291 | + | |
| 292 | + if (iRet) { | |
| 293 | + HandleReferenceLostL0 (pCtx, pCurNal); | |
| 294 | + } | |
| 295 | + | |
| 296 | + return iRet; | |
| 297 | +} | |
| 298 | + | |
| 299 | +int32_t ParsePredWeightedTable (PBitStringAux pBs, PSliceHeader pSh) { | |
| 300 | + uint32_t uiCode; | |
| 301 | + int32_t iList = 0; | |
| 302 | + int32_t iCode; | |
| 303 | + | |
| 304 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); | |
| 305 | + WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "luma_log2_weight_denom", | |
| 306 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_LOG2_WEIGHT_DENOM)); | |
| 307 | + pSh->sPredWeightTable.uiLumaLog2WeightDenom = uiCode; | |
| 308 | + if (pSh->pSps->uiChromaArrayType != 0) { | |
| 309 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); | |
| 310 | + WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "chroma_log2_weight_denom", | |
| 311 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_LOG2_WEIGHT_DENOM)); | |
| 312 | + pSh->sPredWeightTable.uiChromaLog2WeightDenom = uiCode; | |
| 313 | + } | |
| 314 | + | |
| 315 | + if ((pSh->sPredWeightTable.uiLumaLog2WeightDenom | pSh->sPredWeightTable.uiChromaLog2WeightDenom) > 7) | |
| 316 | + return ERR_NONE; | |
| 317 | + | |
| 318 | + do { | |
| 319 | + | |
| 320 | + for (int i = 0; i < pSh->uiRefCount[iList]; i++) { | |
| 321 | + //luma | |
| 322 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); | |
| 323 | + if (!!uiCode) { | |
| 324 | + | |
| 325 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 326 | + WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_weight", | |
| 327 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_WEIGHT)); | |
| 328 | + pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = iCode; | |
| 329 | + | |
| 330 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 331 | + WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_offset", | |
| 332 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_OFFSET)); | |
| 333 | + pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = iCode; | |
| 334 | + } else { | |
| 335 | + pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = 1 << (pSh->sPredWeightTable.uiLumaLog2WeightDenom); | |
| 336 | + pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = 0; | |
| 337 | + | |
| 338 | + } | |
| 339 | + //chroma | |
| 340 | + if (pSh->pSps->uiChromaArrayType == 0) | |
| 341 | + continue; | |
| 342 | + | |
| 343 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); | |
| 344 | + if (!!uiCode) { | |
| 345 | + for (int j = 0; j < 2; j++) { | |
| 346 | + | |
| 347 | + | |
| 348 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 349 | + WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_weight", | |
| 350 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_WEIGHT)); | |
| 351 | + pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = iCode; | |
| 352 | + | |
| 353 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); | |
| 354 | + WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_offset", | |
| 355 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_OFFSET)); | |
| 356 | + pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = iCode; | |
| 357 | + } | |
| 358 | + } else { | |
| 359 | + for (int j = 0; j < 2; j++) { | |
| 360 | + | |
| 361 | + | |
| 362 | + pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = 1 << (pSh->sPredWeightTable.uiChromaLog2WeightDenom); | |
| 363 | + pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = 0; | |
| 364 | + } | |
| 365 | + } | |
| 366 | + | |
| 367 | + } | |
| 368 | + ++iList; | |
| 369 | + if (pSh->eSliceType != B_SLICE) { | |
| 370 | + break; | |
| 371 | + } | |
| 372 | + } while (iList < LIST_A);//TODO: SUPPORT LIST_A | |
| 373 | + return ERR_NONE; | |
| 374 | +} | |
| 375 | + | |
| 376 | +void CreateImplicitWeightTable (PWelsDecoderContext pCtx) { | |
| 377 | + | |
| 378 | + PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer; | |
| 379 | + PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader; | |
| 380 | + PDqLayer pCurDqLayer = pCtx->pCurDqLayer; | |
| 381 | + if (pCurDqLayer->bUseWeightedBiPredIdc && pSliceHeader->pPps->uiWeightedBipredIdc == 2) { | |
| 382 | + int32_t iPoc = pSliceHeader->iPicOrderCntLsb; | |
| 383 | + | |
| 384 | + if (pSliceHeader->uiRefCount[0] == 1 && pSliceHeader->uiRefCount[1] == 1 | |
| 385 | + && pCtx->sRefPic.pRefList[LIST_0][0]->iFramePoc + pCtx->sRefPic.pRefList[LIST_1][0]->iFramePoc == 2 * iPoc) { | |
| 386 | + pCurDqLayer->bUseWeightedBiPredIdc = false; | |
| 387 | + return; | |
| 388 | + } | |
| 389 | + | |
| 390 | + pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom = 5; | |
| 391 | + pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom = 5; | |
| 392 | + for (int32_t iRef0 = 0; iRef0 < pSliceHeader->uiRefCount[0]; iRef0++) { | |
| 393 | + if (pCtx->sRefPic.pRefList[LIST_0][iRef0]) { | |
| 394 | + const int32_t iPoc0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->iFramePoc; | |
| 395 | + bool bIsLongRef0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->bIsLongRef; | |
| 396 | + for (int32_t iRef1 = 0; iRef1 < pSliceHeader->uiRefCount[1]; iRef1++) { | |
| 397 | + if (pCtx->sRefPic.pRefList[LIST_1][iRef1]) { | |
| 398 | + const int32_t iPoc1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->iFramePoc; | |
| 399 | + bool bIsLongRef1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->bIsLongRef; | |
| 400 | + pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 32; | |
| 401 | + if (!bIsLongRef0 && !bIsLongRef1) { | |
| 402 | + const int32_t iTd = WELS_CLIP3 (iPoc1 - iPoc0, -128, 127); | |
| 403 | + if (iTd) { | |
| 404 | + int32_t iTb = WELS_CLIP3 (iPoc - iPoc0, -128, 127); | |
| 405 | + int32_t iTx = (16384 + (WELS_ABS (iTd) >> 1)) / iTd; | |
| 406 | + int32_t iDistScaleFactor = (iTb * iTx + 32) >> 8; | |
| 407 | + if (iDistScaleFactor >= -64 && iDistScaleFactor <= 128) { | |
| 408 | + pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 64 - iDistScaleFactor; | |
| 409 | + } | |
| 410 | + } | |
| 411 | + } | |
| 412 | + } | |
| 413 | + } | |
| 414 | + } | |
| 415 | + } | |
| 416 | + } | |
| 417 | + return; | |
| 418 | +} | |
| 419 | + | |
| 420 | +/* | |
| 421 | + * Predeclared function routines .. | |
| 422 | + */ | |
| 423 | +int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) { | |
| 424 | + int32_t iList = 0; | |
| 425 | + const EWelsSliceType keSt = pSh->eSliceType; | |
| 426 | + PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering; | |
| 427 | + PSps pSps = pSh->pSps; | |
| 428 | + uint32_t uiCode; | |
| 429 | + if (keSt == I_SLICE || keSt == SI_SLICE) | |
| 430 | + return ERR_NONE; | |
| 431 | + | |
| 432 | + // Common syntaxs for P or B slices: list0, list1 followed if B slices used. | |
| 433 | + do { | |
| 434 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //ref_pic_list_modification_flag_l0 | |
| 435 | + pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!uiCode; | |
| 436 | + | |
| 437 | + if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) { | |
| 438 | + int32_t iIdx = 0; | |
| 439 | + do { | |
| 440 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //modification_of_pic_nums_idc | |
| 441 | + const uint32_t kuiIdc = uiCode; | |
| 442 | + | |
| 443 | + //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)--- | |
| 444 | + if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) { | |
| 445 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); | |
| 446 | + } | |
| 447 | + pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc = kuiIdc; | |
| 448 | + if (kuiIdc == 3) | |
| 449 | + break; | |
| 450 | + | |
| 451 | + if (iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT) | |
| 452 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); | |
| 453 | + | |
| 454 | + if (kuiIdc == 0 || kuiIdc == 1) { | |
| 455 | + // abs_diff_pic_num_minus1 should be in range 0 to MaxPicNum-1, MaxPicNum is derived as | |
| 456 | + // 2^(4+log2_max_frame_num_minus4) | |
| 457 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //abs_diff_pic_num_minus1 | |
| 458 | + WELS_CHECK_SE_UPPER_ERROR_NOLOG (uiCode, (uint32_t) (1 << pSps->uiLog2MaxFrameNum), "abs_diff_pic_num_minus1", | |
| 459 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING)); | |
| 460 | + pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = uiCode; // uiAbsDiffPicNumMinus1 | |
| 461 | + } else if (kuiIdc == 2) { | |
| 462 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num | |
| 463 | + pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = uiCode; | |
| 464 | + } | |
| 465 | + | |
| 466 | + ++ iIdx; | |
| 467 | + } while (true); | |
| 468 | + } | |
| 469 | + if (keSt != B_SLICE) | |
| 470 | + break; | |
| 471 | + ++ iList; | |
| 472 | + } while (iList < LIST_A); | |
| 473 | + | |
| 474 | + return ERR_NONE; | |
| 475 | +} | |
| 476 | + | |
| 477 | +int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps, | |
| 478 | + const bool kbIdrFlag) { | |
| 479 | + PRefPicMarking const kpRefMarking = &pSh->sRefMarking; | |
| 480 | + uint32_t uiCode; | |
| 481 | + if (kbIdrFlag) { | |
| 482 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //no_output_of_prior_pics_flag | |
| 483 | + kpRefMarking->bNoOutputOfPriorPicsFlag = !!uiCode; | |
| 484 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //long_term_reference_flag | |
| 485 | + kpRefMarking->bLongTermRefFlag = !!uiCode; | |
| 486 | + } else { | |
| 487 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_ref_pic_marking_mode_flag | |
| 488 | + kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!uiCode; | |
| 489 | + if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) { | |
| 490 | + int32_t iIdx = 0; | |
| 491 | + bool bAllowMmco5 = true, bMmco4Exist = false, bMmco5Exist = false, bMmco6Exist = false; | |
| 492 | + do { | |
| 493 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //memory_management_control_operation | |
| 494 | + const uint32_t kuiMmco = uiCode; | |
| 495 | + | |
| 496 | + kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kuiMmco; | |
| 497 | + if (kuiMmco == MMCO_END) | |
| 498 | + break; | |
| 499 | + | |
| 500 | + if (kuiMmco == MMCO_SHORT2UNUSED || kuiMmco == MMCO_SHORT2LONG) { | |
| 501 | + bAllowMmco5 = false; | |
| 502 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //difference_of_pic_nums_minus1 | |
| 503 | + kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + uiCode; | |
| 504 | + kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & (( | |
| 505 | + 1 << pSps->uiLog2MaxFrameNum) - 1); | |
| 506 | + } else if (kuiMmco == MMCO_LONG2UNUSED) { | |
| 507 | + bAllowMmco5 = false; | |
| 508 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num | |
| 509 | + kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = uiCode; | |
| 510 | + } | |
| 511 | + if (kuiMmco == MMCO_SHORT2LONG || kuiMmco == MMCO_LONG) { | |
| 512 | + if (kuiMmco == MMCO_LONG) { | |
| 513 | + WELS_VERIFY_RETURN_IF (-1, bMmco6Exist); | |
| 514 | + bMmco6Exist = true; | |
| 515 | + } | |
| 516 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_frame_idx | |
| 517 | + kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = uiCode; | |
| 518 | + } else if (kuiMmco == MMCO_SET_MAX_LONG) { | |
| 519 | + WELS_VERIFY_RETURN_IF (-1, bMmco4Exist); | |
| 520 | + bMmco4Exist = true; | |
| 521 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //max_long_term_frame_idx_plus1 | |
| 522 | + kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + uiCode; | |
| 523 | + } else if (kuiMmco == MMCO_RESET) { | |
| 524 | + WELS_VERIFY_RETURN_IF (-1, (!bAllowMmco5 || bMmco5Exist)); | |
| 525 | + bMmco5Exist = true; | |
| 526 | + | |
| 527 | + pCtx->iPrevPicOrderCntLsb = 0; | |
| 528 | + pCtx->iPrevPicOrderCntMsb = 0; | |
| 529 | + pCtx->pSliceHeader->iPicOrderCntLsb = 0; | |
| 530 | + } | |
| 531 | + ++ iIdx; | |
| 532 | + | |
| 533 | + } while (iIdx < MAX_MMCO_COUNT); | |
| 534 | + } | |
| 535 | + } | |
| 536 | + | |
| 537 | + return ERR_NONE; | |
| 538 | +} | |
| 539 | + | |
| 540 | +bool FillDefaultSliceHeaderExt (PSliceHeaderExt pShExt, PNalUnitHeaderExt pNalExt) { | |
| 541 | + if (pShExt == NULL || pNalExt == NULL) | |
| 542 | + return false; | |
| 543 | + | |
| 544 | + if (pNalExt->iNoInterLayerPredFlag || pNalExt->uiQualityId > 0) | |
| 545 | + pShExt->bBasePredWeightTableFlag = false; | |
| 546 | + else | |
| 547 | + pShExt->bBasePredWeightTableFlag = true; | |
| 548 | + pShExt->uiRefLayerDqId = (uint8_t) - 1; | |
| 549 | + pShExt->uiDisableInterLayerDeblockingFilterIdc = 0; | |
| 550 | + pShExt->iInterLayerSliceAlphaC0Offset = 0; | |
| 551 | + pShExt->iInterLayerSliceBetaOffset = 0; | |
| 552 | + pShExt->bConstrainedIntraResamplingFlag = false; | |
| 553 | + pShExt->uiRefLayerChromaPhaseXPlus1Flag = 0; | |
| 554 | + pShExt->uiRefLayerChromaPhaseYPlus1 = 1; | |
| 555 | + //memset(&pShExt->sScaledRefLayer, 0, sizeof(SPosOffset)); | |
| 556 | + | |
| 557 | + pShExt->iScaledRefLayerPicWidthInSampleLuma = pShExt->sSliceHeader.iMbWidth << 4; | |
| 558 | + pShExt->iScaledRefLayerPicHeightInSampleLuma = pShExt->sSliceHeader.iMbHeight << 4; | |
| 559 | + | |
| 560 | + pShExt->bSliceSkipFlag = false; | |
| 561 | + pShExt->bAdaptiveBaseModeFlag = false; | |
| 562 | + pShExt->bDefaultBaseModeFlag = false; | |
| 563 | + pShExt->bAdaptiveMotionPredFlag = false; | |
| 564 | + pShExt->bDefaultMotionPredFlag = false; | |
| 565 | + pShExt->bAdaptiveResidualPredFlag = false; | |
| 566 | + pShExt->bDefaultResidualPredFlag = false; | |
| 567 | + pShExt->bTCoeffLevelPredFlag = false; | |
| 568 | + pShExt->uiScanIdxStart = 0; | |
| 569 | + pShExt->uiScanIdxEnd = 15; | |
| 570 | + | |
| 571 | + return true; | |
| 572 | +} | |
| 573 | + | |
| 574 | +int32_t InitBsBuffer (PWelsDecoderContext pCtx) { | |
| 575 | + if (pCtx == NULL) | |
| 576 | + return ERR_INFO_INVALID_PTR; | |
| 577 | + | |
| 578 | + CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 579 | + | |
| 580 | + pCtx->iMaxBsBufferSizeInByte = MIN_ACCESS_UNIT_CAPACITY * MAX_BUFFERED_NUM; | |
| 581 | + if ((pCtx->sRawData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte, | |
| 582 | + "pCtx->sRawData.pHead"))) == NULL) { | |
| 583 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 584 | + } | |
| 585 | + pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead; | |
| 586 | + pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte; | |
| 587 | + if (pCtx->pParam->bParseOnly) { | |
| 588 | + pCtx->pParserBsInfo = static_cast<SParserBsInfo*> (pMa->WelsMallocz (sizeof (SParserBsInfo), "pCtx->pParserBsInfo")); | |
| 589 | + if (pCtx->pParserBsInfo == NULL) { | |
| 590 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 591 | + } | |
| 592 | + memset (pCtx->pParserBsInfo, 0, sizeof (SParserBsInfo)); | |
| 593 | + pCtx->pParserBsInfo->pDstBuff = static_cast<uint8_t*> (pMa->WelsMallocz (MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t), | |
| 594 | + "pCtx->pParserBsInfo->pDstBuff")); | |
| 595 | + if (pCtx->pParserBsInfo->pDstBuff == NULL) { | |
| 596 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 597 | + } | |
| 598 | + memset (pCtx->pParserBsInfo->pDstBuff, 0, MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t)); | |
| 599 | + | |
| 600 | + if ((pCtx->sSavedData.pHead = static_cast<uint8_t*> (pMa->WelsMallocz (pCtx->iMaxBsBufferSizeInByte, | |
| 601 | + "pCtx->sSavedData.pHead"))) == NULL) { | |
| 602 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 603 | + } | |
| 604 | + pCtx->sSavedData.pStartPos = pCtx->sSavedData.pCurPos = pCtx->sSavedData.pHead; | |
| 605 | + pCtx->sSavedData.pEnd = pCtx->sSavedData.pHead + pCtx->iMaxBsBufferSizeInByte; | |
| 606 | + | |
| 607 | + pCtx->iMaxNalNum = MAX_NAL_UNITS_IN_LAYER + 2; //2 reserved for SPS+PPS | |
| 608 | + pCtx->pParserBsInfo->pNalLenInByte = static_cast<int*> (pMa->WelsMallocz (pCtx->iMaxNalNum * sizeof (int), | |
| 609 | + "pCtx->pParserBsInfo->pNalLenInByte")); | |
| 610 | + if (pCtx->pParserBsInfo->pNalLenInByte == NULL) { | |
| 611 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 612 | + } | |
| 613 | + } | |
| 614 | + return ERR_NONE; | |
| 615 | +} | |
| 616 | + | |
| 617 | +int32_t ExpandBsBuffer (PWelsDecoderContext pCtx, const int kiSrcLen) { | |
| 618 | + if (pCtx == NULL) | |
| 619 | + return ERR_INFO_INVALID_PTR; | |
| 620 | + int32_t iExpandStepShift = 1; | |
| 621 | + int32_t iNewBuffLen = WELS_MAX ((kiSrcLen * MAX_BUFFERED_NUM), (pCtx->iMaxBsBufferSizeInByte << iExpandStepShift)); | |
| 622 | + //allocate new bs buffer | |
| 623 | + CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 624 | + | |
| 625 | + //Realloc sRawData | |
| 626 | + uint8_t* pNewBsBuff = static_cast<uint8_t*> (pMa->WelsMallocz (iNewBuffLen, "pCtx->sRawData.pHead")); | |
| 627 | + if (pNewBsBuff == NULL) { | |
| 628 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "ExpandBsBuffer() Failed for malloc pNewBsBuff (%d)", iNewBuffLen); | |
| 629 | + pCtx->iErrorCode |= dsOutOfMemory; | |
| 630 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 631 | + } | |
| 632 | + | |
| 633 | + //Calculate and set the bs start and end position | |
| 634 | + for (uint32_t i = 0; i <= pCtx->pAccessUnitList->uiActualUnitsNum; i++) { | |
| 635 | + PBitStringAux pSliceBitsRead = &pCtx->pAccessUnitList->pNalUnitsList[i]->sNalData.sVclNal.sSliceBitsRead; | |
| 636 | + pSliceBitsRead->pStartBuf = pSliceBitsRead->pStartBuf - pCtx->sRawData.pHead + pNewBsBuff; | |
| 637 | + pSliceBitsRead->pEndBuf = pSliceBitsRead->pEndBuf - pCtx->sRawData.pHead + pNewBsBuff; | |
| 638 | + pSliceBitsRead->pCurBuf = pSliceBitsRead->pCurBuf - pCtx->sRawData.pHead + pNewBsBuff; | |
| 639 | + } | |
| 640 | + | |
| 641 | + //Copy current buffer status to new buffer | |
| 642 | + memcpy (pNewBsBuff, pCtx->sRawData.pHead, pCtx->iMaxBsBufferSizeInByte); | |
| 643 | + pCtx->sRawData.pStartPos = pNewBsBuff + (pCtx->sRawData.pStartPos - pCtx->sRawData.pHead); | |
| 644 | + pCtx->sRawData.pCurPos = pNewBsBuff + (pCtx->sRawData.pCurPos - pCtx->sRawData.pHead); | |
| 645 | + pCtx->sRawData.pEnd = pNewBsBuff + iNewBuffLen; | |
| 646 | + pMa->WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData.pHead"); | |
| 647 | + pCtx->sRawData.pHead = pNewBsBuff; | |
| 648 | + | |
| 649 | + if (pCtx->pParam->bParseOnly) { | |
| 650 | + //Realloc sSavedData | |
| 651 | + uint8_t* pNewSavedBsBuff = static_cast<uint8_t*> (pMa->WelsMallocz (iNewBuffLen, "pCtx->sSavedData.pHead")); | |
| 652 | + if (pNewSavedBsBuff == NULL) { | |
| 653 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "ExpandBsBuffer() Failed for malloc pNewSavedBsBuff (%d)", iNewBuffLen); | |
| 654 | + pCtx->iErrorCode |= dsOutOfMemory; | |
| 655 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 656 | + } | |
| 657 | + | |
| 658 | + //Copy current buffer status to new buffer | |
| 659 | + memcpy (pNewSavedBsBuff, pCtx->sSavedData.pHead, pCtx->iMaxBsBufferSizeInByte); | |
| 660 | + pCtx->sSavedData.pStartPos = pNewSavedBsBuff + (pCtx->sSavedData.pStartPos - pCtx->sSavedData.pHead); | |
| 661 | + pCtx->sSavedData.pCurPos = pNewSavedBsBuff + (pCtx->sSavedData.pCurPos - pCtx->sSavedData.pHead); | |
| 662 | + pCtx->sSavedData.pEnd = pNewSavedBsBuff + iNewBuffLen; | |
| 663 | + pMa->WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData.pHead"); | |
| 664 | + pCtx->sSavedData.pHead = pNewSavedBsBuff; | |
| 665 | + } | |
| 666 | + | |
| 667 | + pCtx->iMaxBsBufferSizeInByte = iNewBuffLen; | |
| 668 | + return ERR_NONE; | |
| 669 | +} | |
| 670 | + | |
| 671 | +int32_t ExpandBsLenBuffer (PWelsDecoderContext pCtx, const int kiCurrLen) { | |
| 672 | + SParserBsInfo* pParser = pCtx->pParserBsInfo; | |
| 673 | + if (!pParser->pNalLenInByte) | |
| 674 | + return ERR_INFO_INVALID_ACCESS; | |
| 675 | + | |
| 676 | + int iNewLen = kiCurrLen; | |
| 677 | + if (kiCurrLen >= MAX_MB_SIZE + 2) { //exceeds the max MB number of level 5.2 | |
| 678 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "Current nal num (%d) exceededs %d.", kiCurrLen, MAX_MB_SIZE); | |
| 679 | + pCtx->iErrorCode |= dsOutOfMemory; | |
| 680 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 681 | + } else { | |
| 682 | + iNewLen = kiCurrLen << 1; | |
| 683 | + iNewLen = WELS_MIN (iNewLen, MAX_MB_SIZE + 2); | |
| 684 | + } | |
| 685 | + | |
| 686 | + CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 687 | + int* pNewLenBuffer = static_cast<int*> (pMa->WelsMallocz (iNewLen * sizeof (int), | |
| 688 | + "pCtx->pParserBsInfo->pNalLenInByte")); | |
| 689 | + if (pNewLenBuffer == NULL) { | |
| 690 | + pCtx->iErrorCode |= dsOutOfMemory; | |
| 691 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 692 | + } | |
| 693 | + | |
| 694 | + //copy existing data from old length buffer to new | |
| 695 | + memcpy (pNewLenBuffer, pParser->pNalLenInByte, pCtx->iMaxNalNum * sizeof (int)); | |
| 696 | + pMa->WelsFree (pParser->pNalLenInByte, "pCtx->pParserBsInfo->pNalLenInByte"); | |
| 697 | + pParser->pNalLenInByte = pNewLenBuffer; | |
| 698 | + pCtx->iMaxNalNum = iNewLen; | |
| 699 | + return ERR_NONE; | |
| 700 | +} | |
| 701 | + | |
| 702 | +int32_t CheckBsBuffer (PWelsDecoderContext pCtx, const int32_t kiSrcLen) { | |
| 703 | + if (kiSrcLen > MAX_ACCESS_UNIT_CAPACITY) { //exceeds max allowed data | |
| 704 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "Max AU size exceeded. Allowed size = %d, current size = %d", | |
| 705 | + MAX_ACCESS_UNIT_CAPACITY, | |
| 706 | + kiSrcLen); | |
| 707 | + pCtx->iErrorCode |= dsBitstreamError; | |
| 708 | + return ERR_INFO_INVALID_ACCESS; | |
| 709 | + } else if (kiSrcLen > pCtx->iMaxBsBufferSizeInByte / | |
| 710 | + MAX_BUFFERED_NUM) { //may lead to buffer overwrite, prevent it by expanding buffer | |
| 711 | + if (ExpandBsBuffer (pCtx, kiSrcLen)) { | |
| 712 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 713 | + } | |
| 714 | + } | |
| 715 | + | |
| 716 | + return ERR_NONE; | |
| 717 | +} | |
| 718 | + | |
| 719 | +/* | |
| 720 | + * WelsInitStaticMemory | |
| 721 | + * Memory request for new introduced data | |
| 722 | + * Especially for: | |
| 723 | + * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache. | |
| 724 | + * return: | |
| 725 | + * 0 - success; otherwise returned error_no defined in error_no.h. | |
| 726 | +*/ | |
| 727 | +int32_t WelsInitStaticMemory (PWelsDecoderContext pCtx) { | |
| 728 | + if (pCtx == NULL) { | |
| 729 | + return ERR_INFO_INVALID_PTR; | |
| 730 | + } | |
| 731 | + | |
| 732 | + if (MemInitNalList (&pCtx->pAccessUnitList, MAX_NAL_UNIT_NUM_IN_AU, pCtx->pMemAlign) != 0) | |
| 733 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 734 | + | |
| 735 | + if (InitBsBuffer (pCtx) != 0) | |
| 736 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 737 | + | |
| 738 | + pCtx->uiTargetDqId = (uint8_t) - 1; | |
| 739 | + pCtx->bEndOfStreamFlag = false; | |
| 740 | + | |
| 741 | + return ERR_NONE; | |
| 742 | +} | |
| 743 | + | |
| 744 | +/* | |
| 745 | + * WelsFreeStaticMemory | |
| 746 | + * Free memory introduced in WelsInitStaticMemory at destruction of decoder. | |
| 747 | + * | |
| 748 | + */ | |
| 749 | +void WelsFreeStaticMemory (PWelsDecoderContext pCtx) { | |
| 750 | + if (pCtx == NULL) | |
| 751 | + return; | |
| 752 | + | |
| 753 | + CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 754 | + | |
| 755 | + MemFreeNalList (&pCtx->pAccessUnitList, pMa); | |
| 756 | + | |
| 757 | + if (pCtx->sRawData.pHead) { | |
| 758 | + pMa->WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData->pHead"); | |
| 759 | + } | |
| 760 | + pCtx->sRawData.pHead = NULL; | |
| 761 | + pCtx->sRawData.pEnd = NULL; | |
| 762 | + pCtx->sRawData.pStartPos = NULL; | |
| 763 | + pCtx->sRawData.pCurPos = NULL; | |
| 764 | + if (pCtx->pParam->bParseOnly) { | |
| 765 | + if (pCtx->sSavedData.pHead) { | |
| 766 | + pMa->WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData->pHead"); | |
| 767 | + } | |
| 768 | + pCtx->sSavedData.pHead = NULL; | |
| 769 | + pCtx->sSavedData.pEnd = NULL; | |
| 770 | + pCtx->sSavedData.pStartPos = NULL; | |
| 771 | + pCtx->sSavedData.pCurPos = NULL; | |
| 772 | + if (pCtx->pParserBsInfo) { | |
| 773 | + if (pCtx->pParserBsInfo->pNalLenInByte) { | |
| 774 | + pMa->WelsFree (pCtx->pParserBsInfo->pNalLenInByte, "pCtx->pParserBsInfo->pNalLenInByte"); | |
| 775 | + pCtx->pParserBsInfo->pNalLenInByte = NULL; | |
| 776 | + pCtx->iMaxNalNum = 0; | |
| 777 | + } | |
| 778 | + if (pCtx->pParserBsInfo->pDstBuff) { | |
| 779 | + pMa->WelsFree (pCtx->pParserBsInfo->pDstBuff, "pCtx->pParserBsInfo->pDstBuff"); | |
| 780 | + pCtx->pParserBsInfo->pDstBuff = NULL; | |
| 781 | + } | |
| 782 | + pMa->WelsFree (pCtx->pParserBsInfo, "pCtx->pParserBsInfo"); | |
| 783 | + pCtx->pParserBsInfo = NULL; | |
| 784 | + } | |
| 785 | + } | |
| 786 | + | |
| 787 | + if (NULL != pCtx->pParam) { | |
| 788 | + pMa->WelsFree (pCtx->pParam, "pCtx->pParam"); | |
| 789 | + | |
| 790 | + pCtx->pParam = NULL; | |
| 791 | + } | |
| 792 | +} | |
| 793 | +/* | |
| 794 | + * DecodeNalHeaderExt | |
| 795 | + * Trigger condition: NAL_UNIT_TYPE = NAL_UNIT_PREFIX or NAL_UNIT_CODED_SLICE_EXT | |
| 796 | + * Parameter: | |
| 797 | + * pNal: target NALUnit ptr | |
| 798 | + * pSrc: NAL Unit bitstream | |
| 799 | + */ | |
| 800 | +void DecodeNalHeaderExt (PNalUnit pNal, uint8_t* pSrc) { | |
| 801 | + PNalUnitHeaderExt pHeaderExt = &pNal->sNalHeaderExt; | |
| 802 | + | |
| 803 | + uint8_t uiCurByte = *pSrc; | |
| 804 | + pHeaderExt->bIdrFlag = !! (uiCurByte & 0x40); | |
| 805 | + pHeaderExt->uiPriorityId = uiCurByte & 0x3F; | |
| 806 | + | |
| 807 | + uiCurByte = * (++pSrc); | |
| 808 | + pHeaderExt->iNoInterLayerPredFlag = uiCurByte >> 7; | |
| 809 | + pHeaderExt->uiDependencyId = (uiCurByte & 0x70) >> 4; | |
| 810 | + pHeaderExt->uiQualityId = uiCurByte & 0x0F; | |
| 811 | + uiCurByte = * (++pSrc); | |
| 812 | + pHeaderExt->uiTemporalId = uiCurByte >> 5; | |
| 813 | + pHeaderExt->bUseRefBasePicFlag = !! (uiCurByte & 0x10); | |
| 814 | + pHeaderExt->bDiscardableFlag = !! (uiCurByte & 0x08); | |
| 815 | + pHeaderExt->bOutputFlag = !! (uiCurByte & 0x04); | |
| 816 | + pHeaderExt->uiReservedThree2Bits = uiCurByte & 0x03; | |
| 817 | + pHeaderExt->uiLayerDqId = (pHeaderExt->uiDependencyId << 4) | pHeaderExt->uiQualityId; | |
| 818 | +} | |
| 819 | + | |
| 820 | + | |
| 821 | +void UpdateDecoderStatisticsForActiveParaset (SDecoderStatistics* pDecoderStatistics, | |
| 822 | + PSps pSps, PPps pPps) { | |
| 823 | + pDecoderStatistics->iCurrentActiveSpsId = pSps->iSpsId; | |
| 824 | + | |
| 825 | + pDecoderStatistics->iCurrentActivePpsId = pPps->iPpsId; | |
| 826 | + pDecoderStatistics->uiProfile = static_cast<unsigned int> (pSps->uiProfileIdc); | |
| 827 | + pDecoderStatistics->uiLevel = pSps->uiLevelIdc; | |
| 828 | +} | |
| 829 | + | |
| 830 | +#define SLICE_HEADER_IDR_PIC_ID_MAX 65535 | |
| 831 | +#define SLICE_HEADER_REDUNDANT_PIC_CNT_MAX 127 | |
| 832 | +#define SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN -12 | |
| 833 | +#define SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX 12 | |
| 834 | +#define SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN -12 | |
| 835 | +#define SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX 12 | |
| 836 | +#define MAX_NUM_REF_IDX_L0_ACTIVE_MINUS1 15 | |
| 837 | +#define MAX_NUM_REF_IDX_L1_ACTIVE_MINUS1 15 | |
| 838 | +#define SLICE_HEADER_CABAC_INIT_IDC_MAX 2 | |
| 839 | +/* | |
| 840 | + * decode_slice_header_avc | |
| 841 | + * Parse slice header of bitstream in avc for storing data structure | |
| 842 | + */ | |
| 843 | +int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, const bool kbExtensionFlag) { | |
| 844 | + PNalUnit const kpCurNal = pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiAvailUnitsNum - | |
| 845 | + 1]; | |
| 846 | + | |
| 847 | + PNalUnitHeaderExt pNalHeaderExt = NULL; | |
| 848 | + PSliceHeader pSliceHead = NULL; | |
| 849 | + PSliceHeaderExt pSliceHeadExt = NULL; | |
| 850 | + PSubsetSps pSubsetSps = NULL; | |
| 851 | + PSps pSps = NULL; | |
| 852 | + PPps pPps = NULL; | |
| 853 | + EWelsNalUnitType eNalType = static_cast<EWelsNalUnitType> (0); | |
| 854 | + int32_t iPpsId = 0; | |
| 855 | + int32_t iRet = ERR_NONE; | |
| 856 | + uint8_t uiSliceType = 0; | |
| 857 | + uint8_t uiQualityId = BASE_QUALITY_ID; | |
| 858 | + bool bIdrFlag = false; | |
| 859 | + bool bSgChangeCycleInvolved = false; // involved slice group change cycle ? | |
| 860 | + uint32_t uiCode; | |
| 861 | + int32_t iCode; | |
| 862 | + SLogContext* pLogCtx = & (pCtx->sLogCtx); | |
| 863 | + | |
| 864 | + if (kpCurNal == NULL) { | |
| 865 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 866 | + } | |
| 867 | + | |
| 868 | + pNalHeaderExt = &kpCurNal->sNalHeaderExt; | |
| 869 | + pSliceHead = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; | |
| 870 | + eNalType = pNalHeaderExt->sNalUnitHeader.eNalUnitType; | |
| 871 | + | |
| 872 | + pSliceHeadExt = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt; | |
| 873 | + | |
| 874 | + if (pSliceHeadExt) { | |
| 875 | + SRefBasePicMarking sBaseMarking; | |
| 876 | + const bool kbStoreRefBaseFlag = pSliceHeadExt->bStoreRefBasePicFlag; | |
| 877 | + memcpy (&sBaseMarking, &pSliceHeadExt->sRefBasePicMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage | |
| 878 | + memset (pSliceHeadExt, 0, sizeof (SSliceHeaderExt)); | |
| 879 | + pSliceHeadExt->bStoreRefBasePicFlag = kbStoreRefBaseFlag; | |
| 880 | + memcpy (&pSliceHeadExt->sRefBasePicMarking, &sBaseMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage | |
| 881 | + } | |
| 882 | + | |
| 883 | + kpCurNal->sNalData.sVclNal.bSliceHeaderExtFlag = kbExtensionFlag; | |
| 884 | + | |
| 885 | + // first_mb_in_slice | |
| 886 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //first_mb_in_slice | |
| 887 | + WELS_CHECK_SE_UPPER_ERROR (uiCode, 36863u, "first_mb_in_slice", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 888 | + ERR_INFO_INVALID_FIRST_MB_IN_SLICE)); | |
| 889 | + pSliceHead->iFirstMbInSlice = uiCode; | |
| 890 | + | |
| 891 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //slice_type | |
| 892 | + uiSliceType = uiCode; | |
| 893 | + if (uiSliceType > 9) { | |
| 894 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "slice type too large (%d) at first_mb(%d)", uiSliceType, | |
| 895 | + pSliceHead->iFirstMbInSlice); | |
| 896 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 897 | + } | |
| 898 | + if (uiSliceType > 4) | |
| 899 | + uiSliceType -= 5; | |
| 900 | + | |
| 901 | + if ((NAL_UNIT_CODED_SLICE_IDR == eNalType) && (I_SLICE != uiSliceType)) { | |
| 902 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "Invalid slice type(%d) in IDR picture. ", uiSliceType); | |
| 903 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 904 | + } | |
| 905 | + | |
| 906 | + if (kbExtensionFlag) { | |
| 907 | + if (uiSliceType > 2) { | |
| 908 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "Invalid slice type(%d).", uiSliceType); | |
| 909 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 910 | + } | |
| 911 | + } | |
| 912 | + | |
| 913 | + pSliceHead->eSliceType = static_cast <EWelsSliceType> (uiSliceType); | |
| 914 | + | |
| 915 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //pic_parameter_set_id | |
| 916 | + WELS_CHECK_SE_UPPER_ERROR (uiCode, (MAX_PPS_COUNT - 1), "iPpsId out of range", | |
| 917 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 918 | + ERR_INFO_PPS_ID_OVERFLOW)); | |
| 919 | + iPpsId = uiCode; | |
| 920 | + | |
| 921 | + //add check PPS available here | |
| 922 | + if (pCtx->bPpsAvailFlags[iPpsId] == false) { | |
| 923 | + pCtx->sDecoderStatistics.iPpsReportErrorNum++; | |
| 924 | + if (pCtx->iPPSLastInvalidId != iPpsId) { | |
| 925 | + WelsLog (pLogCtx, WELS_LOG_ERROR, "PPS id (%d) is invalid, previous id (%d) error ignored (%d)!", iPpsId, | |
| 926 | + pCtx->iPPSLastInvalidId, pCtx->iPPSInvalidNum); | |
| 927 | + pCtx->iPPSLastInvalidId = iPpsId; | |
| 928 | + pCtx->iPPSInvalidNum = 0; | |
| 929 | + } else { | |
| 930 | + pCtx->iPPSInvalidNum++; | |
| 931 | + } | |
| 932 | + pCtx->iErrorCode |= dsNoParamSets; | |
| 933 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_PPS_ID); | |
| 934 | + } | |
| 935 | + pCtx->iPPSLastInvalidId = -1; | |
| 936 | + | |
| 937 | + pPps = &pCtx->sPpsBuffer[iPpsId]; | |
| 938 | + | |
| 939 | + if (pPps->uiNumSliceGroups == 0) { | |
| 940 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "Invalid PPS referenced"); | |
| 941 | + pCtx->iErrorCode |= dsNoParamSets; | |
| 942 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS); | |
| 943 | + } | |
| 944 | + | |
| 945 | + if (kbExtensionFlag) { | |
| 946 | + pSubsetSps = &pCtx->sSubsetSpsBuffer[pPps->iSpsId]; | |
| 947 | + pSps = &pSubsetSps->sSps; | |
| 948 | + if (pCtx->bSubspsAvailFlags[pPps->iSpsId] == false) { | |
| 949 | + pCtx->sDecoderStatistics.iSubSpsReportErrorNum++; | |
| 950 | + if (pCtx->iSubSPSLastInvalidId != pPps->iSpsId) { | |
| 951 | + WelsLog (pLogCtx, WELS_LOG_ERROR, "Sub SPS id (%d) is invalid, previous id (%d) error ignored (%d)!", pPps->iSpsId, | |
| 952 | + pCtx->iSubSPSLastInvalidId, pCtx->iSubSPSInvalidNum); | |
| 953 | + pCtx->iSubSPSLastInvalidId = pPps->iSpsId; | |
| 954 | + pCtx->iSubSPSInvalidNum = 0; | |
| 955 | + } else { | |
| 956 | + pCtx->iSubSPSInvalidNum++; | |
| 957 | + } | |
| 958 | + pCtx->iErrorCode |= dsNoParamSets; | |
| 959 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SPS_ID); | |
| 960 | + } | |
| 961 | + pCtx->iSubSPSLastInvalidId = -1; | |
| 962 | + } else { | |
| 963 | + if (pCtx->bSpsAvailFlags[pPps->iSpsId] == false) { | |
| 964 | + pCtx->sDecoderStatistics.iSpsReportErrorNum++; | |
| 965 | + if (pCtx->iSPSLastInvalidId != pPps->iSpsId) { | |
| 966 | + WelsLog (pLogCtx, WELS_LOG_ERROR, "SPS id (%d) is invalid, previous id (%d) error ignored (%d)!", pPps->iSpsId, | |
| 967 | + pCtx->iSPSLastInvalidId, pCtx->iSPSInvalidNum); | |
| 968 | + pCtx->iSPSLastInvalidId = pPps->iSpsId; | |
| 969 | + pCtx->iSPSInvalidNum = 0; | |
| 970 | + } else { | |
| 971 | + pCtx->iSPSInvalidNum++; | |
| 972 | + } | |
| 973 | + pCtx->iErrorCode |= dsNoParamSets; | |
| 974 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SPS_ID); | |
| 975 | + } | |
| 976 | + pCtx->iSPSLastInvalidId = -1; | |
| 977 | + pSps = &pCtx->sSpsBuffer[pPps->iSpsId]; | |
| 978 | + } | |
| 979 | + pSliceHead->iPpsId = iPpsId; | |
| 980 | + pSliceHead->iSpsId = pPps->iSpsId; | |
| 981 | + pSliceHead->pPps = pPps; | |
| 982 | + pSliceHead->pSps = pSps; | |
| 983 | + | |
| 984 | + pSliceHeadExt->pSubsetSps = pSubsetSps; | |
| 985 | + | |
| 986 | + if (pSps->iNumRefFrames == 0) { | |
| 987 | + if ((uiSliceType != I_SLICE) && (uiSliceType != SI_SLICE)) { | |
| 988 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "slice_type (%d) not supported for num_ref_frames = 0.", uiSliceType); | |
| 989 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE); | |
| 990 | + } | |
| 991 | + } | |
| 992 | + | |
| 993 | + bIdrFlag = (!kbExtensionFlag && eNalType == NAL_UNIT_CODED_SLICE_IDR) || (kbExtensionFlag && pNalHeaderExt->bIdrFlag); | |
| 994 | + pSliceHead->bIdrFlag = bIdrFlag; | |
| 995 | + | |
| 996 | + if (pSps->uiLog2MaxFrameNum == 0) { | |
| 997 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "non existing SPS referenced"); | |
| 998 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS); | |
| 999 | + } | |
| 1000 | + // check first_mb_in_slice | |
| 1001 | + WELS_CHECK_SE_UPPER_ERROR ((uint32_t) (pSliceHead->iFirstMbInSlice), (pSps->uiTotalMbCount - 1), "first_mb_in_slice", | |
| 1002 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FIRST_MB_IN_SLICE)); | |
| 1003 | + WELS_READ_VERIFY (BsGetBits (pBs, pSps->uiLog2MaxFrameNum, &uiCode)); //frame_num | |
| 1004 | + pSliceHead->iFrameNum = uiCode; | |
| 1005 | + | |
| 1006 | + pSliceHead->bFieldPicFlag = false; | |
| 1007 | + pSliceHead->bBottomFiledFlag = false; | |
| 1008 | + if (!pSps->bFrameMbsOnlyFlag) { | |
| 1009 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): frame_mbs_only_flag = %d not supported. ", | |
| 1010 | + pSps->bFrameMbsOnlyFlag); | |
| 1011 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MBAFF); | |
| 1012 | + } | |
| 1013 | + pSliceHead->iMbWidth = pSps->iMbWidth; | |
| 1014 | + pSliceHead->iMbHeight = pSps->iMbHeight / (1 + pSliceHead->bFieldPicFlag); | |
| 1015 | + | |
| 1016 | + if (bIdrFlag) { | |
| 1017 | + if (pSliceHead->iFrameNum != 0) { | |
| 1018 | + WelsLog (pLogCtx, WELS_LOG_WARNING, | |
| 1019 | + "ParseSliceHeaderSyntaxs(), invaild frame number: %d due to IDR frame introduced!", | |
| 1020 | + pSliceHead->iFrameNum); | |
| 1021 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FRAME_NUM); | |
| 1022 | + } | |
| 1023 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //idr_pic_id | |
| 1024 | + // standard 7.4.3 idr_pic_id should be in range 0 to 65535, inclusive. | |
| 1025 | + WELS_CHECK_SE_UPPER_ERROR (uiCode, SLICE_HEADER_IDR_PIC_ID_MAX, "idr_pic_id", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 1026 | + ERR_INFO_INVALID_IDR_PIC_ID)); | |
| 1027 | + pSliceHead->uiIdrPicId = uiCode; /* uiIdrPicId */ | |
| 1028 | +#ifdef LONG_TERM_REF | |
| 1029 | + pCtx->uiCurIdrPicId = pSliceHead->uiIdrPicId; | |
| 1030 | +#endif | |
| 1031 | + } | |
| 1032 | + | |
| 1033 | + pSliceHead->iDeltaPicOrderCntBottom = 0; | |
| 1034 | + pSliceHead->iDeltaPicOrderCnt[0] = | |
| 1035 | + pSliceHead->iDeltaPicOrderCnt[1] = 0; | |
| 1036 | + if (pSps->uiPocType == 0) { | |
| 1037 | + WELS_READ_VERIFY (BsGetBits (pBs, pSps->iLog2MaxPocLsb, &uiCode)); //pic_order_cnt_lsb | |
| 1038 | + const int32_t iMaxPocLsb = 1 << (pSps->iLog2MaxPocLsb); | |
| 1039 | + pSliceHead->iPicOrderCntLsb = uiCode; | |
| 1040 | + if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) { | |
| 1041 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //delta_pic_order_cnt_bottom | |
| 1042 | + pSliceHead->iDeltaPicOrderCntBottom = iCode; | |
| 1043 | + } | |
| 1044 | + //Calculate poc if necessary | |
| 1045 | + int32_t pocLsb = pSliceHead->iPicOrderCntLsb; | |
| 1046 | + if (pSliceHead->bIdrFlag || kpCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR) { | |
| 1047 | + pCtx->iPrevPicOrderCntMsb = 0; | |
| 1048 | + pCtx->iPrevPicOrderCntLsb = 0; | |
| 1049 | + } | |
| 1050 | + int32_t pocMsb; | |
| 1051 | + if (pocLsb < pCtx->iPrevPicOrderCntLsb && pCtx->iPrevPicOrderCntLsb - pocLsb >= iMaxPocLsb / 2) | |
| 1052 | + pocMsb = pCtx->iPrevPicOrderCntMsb + iMaxPocLsb; | |
| 1053 | + else if (pocLsb > pCtx->iPrevPicOrderCntLsb && pocLsb - pCtx->iPrevPicOrderCntLsb > iMaxPocLsb / 2) | |
| 1054 | + pocMsb = pCtx->iPrevPicOrderCntMsb - iMaxPocLsb; | |
| 1055 | + else | |
| 1056 | + pocMsb = pCtx->iPrevPicOrderCntMsb; | |
| 1057 | + pSliceHead->iPicOrderCntLsb = pocMsb + pocLsb; | |
| 1058 | + | |
| 1059 | + if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) { | |
| 1060 | + pSliceHead->iPicOrderCntLsb += pSliceHead->iDeltaPicOrderCntBottom; | |
| 1061 | + } | |
| 1062 | + | |
| 1063 | + if (kpCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc != 0) { | |
| 1064 | + pCtx->iPrevPicOrderCntLsb = pocLsb; | |
| 1065 | + pCtx->iPrevPicOrderCntMsb = pocMsb; | |
| 1066 | + } | |
| 1067 | + //End of Calculating poc | |
| 1068 | + } else if (pSps->uiPocType == 1 && !pSps->bDeltaPicOrderAlwaysZeroFlag) { | |
| 1069 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //delta_pic_order_cnt[ 0 ] | |
| 1070 | + pSliceHead->iDeltaPicOrderCnt[0] = iCode; | |
| 1071 | + if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) { | |
| 1072 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //delta_pic_order_cnt[ 1 ] | |
| 1073 | + pSliceHead->iDeltaPicOrderCnt[1] = iCode; | |
| 1074 | + } | |
| 1075 | + } | |
| 1076 | + pSliceHead->iRedundantPicCnt = 0; | |
| 1077 | + if (pPps->bRedundantPicCntPresentFlag) { | |
| 1078 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //redundant_pic_cnt | |
| 1079 | + // standard section 7.4.3, redundant_pic_cnt should be in range 0 to 127, inclusive. | |
| 1080 | + WELS_CHECK_SE_UPPER_ERROR (uiCode, SLICE_HEADER_REDUNDANT_PIC_CNT_MAX, "redundant_pic_cnt", | |
| 1081 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REDUNDANT_PIC_CNT)); | |
| 1082 | + pSliceHead->iRedundantPicCnt = uiCode; | |
| 1083 | + if (pSliceHead->iRedundantPicCnt > 0) { | |
| 1084 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "Redundant picture not supported!"); | |
| 1085 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REDUNDANT_PIC_CNT); | |
| 1086 | + } | |
| 1087 | + } | |
| 1088 | + | |
| 1089 | + if (B_SLICE == uiSliceType) { | |
| 1090 | + //fix me: it needs to use the this flag somewhere for B-Sclice | |
| 1091 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //direct_spatial_mv_pred_flag | |
| 1092 | + pSliceHead->iDirectSpatialMvPredFlag = uiCode; | |
| 1093 | + } | |
| 1094 | + | |
| 1095 | + //set defaults, might be overriden a few line later | |
| 1096 | + pSliceHead->uiRefCount[0] = pPps->uiNumRefIdxL0Active; | |
| 1097 | + pSliceHead->uiRefCount[1] = pPps->uiNumRefIdxL1Active; | |
| 1098 | + | |
| 1099 | + bool bReadNumRefFlag = (P_SLICE == uiSliceType || B_SLICE == uiSliceType); | |
| 1100 | + if (kbExtensionFlag) { | |
| 1101 | + bReadNumRefFlag &= (BASE_QUALITY_ID == pNalHeaderExt->uiQualityId); | |
| 1102 | + } | |
| 1103 | + if (bReadNumRefFlag) { | |
| 1104 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //num_ref_idx_active_override_flag | |
| 1105 | + pSliceHead->bNumRefIdxActiveOverrideFlag = !!uiCode; | |
| 1106 | + if (pSliceHead->bNumRefIdxActiveOverrideFlag) { | |
| 1107 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //num_ref_idx_l0_active_minus1 | |
| 1108 | + WELS_CHECK_SE_UPPER_ERROR (uiCode, MAX_NUM_REF_IDX_L0_ACTIVE_MINUS1, "num_ref_idx_l0_active_minus1", | |
| 1109 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_NUM_REF_IDX_L0_ACTIVE_MINUS1)); | |
| 1110 | + pSliceHead->uiRefCount[0] = 1 + uiCode; | |
| 1111 | + if (B_SLICE == uiSliceType) { | |
| 1112 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //num_ref_idx_l1_active_minus1 | |
| 1113 | + WELS_CHECK_SE_UPPER_ERROR (uiCode, MAX_NUM_REF_IDX_L1_ACTIVE_MINUS1, "num_ref_idx_l1_active_minus1", | |
| 1114 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_NUM_REF_IDX_L1_ACTIVE_MINUS1)); | |
| 1115 | + pSliceHead->uiRefCount[1] = 1 + uiCode; | |
| 1116 | + } | |
| 1117 | + } | |
| 1118 | + } | |
| 1119 | + | |
| 1120 | + if (pSliceHead->uiRefCount[0] > MAX_REF_PIC_COUNT || pSliceHead->uiRefCount[1] > MAX_REF_PIC_COUNT) { | |
| 1121 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "reference overflow"); | |
| 1122 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_REF_COUNT_OVERFLOW); | |
| 1123 | + } | |
| 1124 | + | |
| 1125 | + if (BASE_QUALITY_ID == uiQualityId) { | |
| 1126 | + iRet = ParseRefPicListReordering (pBs, pSliceHead); | |
| 1127 | + if (iRet != ERR_NONE) { | |
| 1128 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "invalid ref pPic list reordering syntaxs!"); | |
| 1129 | + return iRet; | |
| 1130 | + } | |
| 1131 | + | |
| 1132 | + if ((pPps->bWeightedPredFlag && uiSliceType == P_SLICE) || (pPps->uiWeightedBipredIdc == 1 && uiSliceType == B_SLICE)) { | |
| 1133 | + iRet = ParsePredWeightedTable (pBs, pSliceHead); | |
| 1134 | + if (iRet != ERR_NONE) { | |
| 1135 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "invalid weighted prediction syntaxs!"); | |
| 1136 | + return iRet; | |
| 1137 | + } | |
| 1138 | + } | |
| 1139 | + | |
| 1140 | + if (kbExtensionFlag) { | |
| 1141 | + if (pNalHeaderExt->iNoInterLayerPredFlag || pNalHeaderExt->uiQualityId > 0) | |
| 1142 | + pSliceHeadExt->bBasePredWeightTableFlag = false; | |
| 1143 | + else | |
| 1144 | + pSliceHeadExt->bBasePredWeightTableFlag = true; | |
| 1145 | + } | |
| 1146 | + | |
| 1147 | + if (kpCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc != 0) { | |
| 1148 | + iRet = ParseDecRefPicMarking (pCtx, pBs, pSliceHead, pSps, bIdrFlag); | |
| 1149 | + if (iRet != ERR_NONE) { | |
| 1150 | + return iRet; | |
| 1151 | + } | |
| 1152 | + | |
| 1153 | + if (kbExtensionFlag && !pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { | |
| 1154 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //store_ref_base_pic_flag | |
| 1155 | + pSliceHeadExt->bStoreRefBasePicFlag = !!uiCode; | |
| 1156 | + if ((pNalHeaderExt->bUseRefBasePicFlag || pSliceHeadExt->bStoreRefBasePicFlag) && !bIdrFlag) { | |
| 1157 | + WelsLog (pLogCtx, WELS_LOG_WARNING, | |
| 1158 | + "ParseSliceHeaderSyntaxs(): bUseRefBasePicFlag or bStoreRefBasePicFlag = 1 not supported."); | |
| 1159 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP); | |
| 1160 | + } | |
| 1161 | + } | |
| 1162 | + } | |
| 1163 | + } | |
| 1164 | + | |
| 1165 | + if (pPps->bEntropyCodingModeFlag) { | |
| 1166 | + if (pSliceHead->eSliceType != I_SLICE && pSliceHead->eSliceType != SI_SLICE) { | |
| 1167 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); | |
| 1168 | + WELS_CHECK_SE_UPPER_ERROR (uiCode, SLICE_HEADER_CABAC_INIT_IDC_MAX, "cabac_init_idc", ERR_INFO_INVALID_CABAC_INIT_IDC); | |
| 1169 | + pSliceHead->iCabacInitIdc = uiCode; | |
| 1170 | + } else | |
| 1171 | + pSliceHead->iCabacInitIdc = 0; | |
| 1172 | + } | |
| 1173 | + | |
| 1174 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_qp_delta | |
| 1175 | + pSliceHead->iSliceQpDelta = iCode; | |
| 1176 | + pSliceHead->iSliceQp = pPps->iPicInitQp + pSliceHead->iSliceQpDelta; | |
| 1177 | + if (pSliceHead->iSliceQp < 0 || pSliceHead->iSliceQp > 51) { | |
| 1178 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "QP %d out of range", pSliceHead->iSliceQp); | |
| 1179 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_QP); | |
| 1180 | + } | |
| 1181 | + | |
| 1182 | + //FIXME qscale / qp ... stuff | |
| 1183 | + if (!kbExtensionFlag) { | |
| 1184 | + if (uiSliceType == SP_SLICE || uiSliceType == SI_SLICE) { | |
| 1185 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "SP/SI not supported"); | |
| 1186 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_SPSI); | |
| 1187 | + } | |
| 1188 | + } | |
| 1189 | + | |
| 1190 | + pSliceHead->uiDisableDeblockingFilterIdc = 0; | |
| 1191 | + pSliceHead->iSliceAlphaC0Offset = 0; | |
| 1192 | + pSliceHead->iSliceBetaOffset = 0; | |
| 1193 | + if (pPps->bDeblockingFilterControlPresentFlag) { | |
| 1194 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //disable_deblocking_filter_idc | |
| 1195 | + pSliceHead->uiDisableDeblockingFilterIdc = uiCode; | |
| 1196 | + //refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20 | |
| 1197 | + if (pSliceHead->uiDisableDeblockingFilterIdc > 6) { | |
| 1198 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "disable_deblock_filter_idc (%d) out of range [0, 6]", | |
| 1199 | + pSliceHead->uiDisableDeblockingFilterIdc); | |
| 1200 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_DBLOCKING_IDC); | |
| 1201 | + } | |
| 1202 | + if (pSliceHead->uiDisableDeblockingFilterIdc != 1) { | |
| 1203 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_alpha_c0_offset_div2 | |
| 1204 | + pSliceHead->iSliceAlphaC0Offset = iCode * 2; | |
| 1205 | + WELS_CHECK_SE_BOTH_ERROR (pSliceHead->iSliceAlphaC0Offset, SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN, | |
| 1206 | + SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX, "slice_alpha_c0_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 1207 | + ERR_INFO_INVALID_SLICE_ALPHA_C0_OFFSET_DIV2)); | |
| 1208 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_beta_offset_div2 | |
| 1209 | + pSliceHead->iSliceBetaOffset = iCode * 2; | |
| 1210 | + WELS_CHECK_SE_BOTH_ERROR (pSliceHead->iSliceBetaOffset, SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN, | |
| 1211 | + SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX, "slice_beta_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 1212 | + ERR_INFO_INVALID_SLICE_BETA_OFFSET_DIV2)); | |
| 1213 | + } | |
| 1214 | + } | |
| 1215 | + | |
| 1216 | + bSgChangeCycleInvolved = (pPps->uiNumSliceGroups > 1 && pPps->uiSliceGroupMapType >= 3 | |
| 1217 | + && pPps->uiSliceGroupMapType <= 5); | |
| 1218 | + if (kbExtensionFlag && bSgChangeCycleInvolved) | |
| 1219 | + bSgChangeCycleInvolved = (bSgChangeCycleInvolved && (uiQualityId == BASE_QUALITY_ID)); | |
| 1220 | + if (bSgChangeCycleInvolved) { | |
| 1221 | + if (pPps->uiSliceGroupChangeRate > 0) { | |
| 1222 | + const int32_t kiNumBits = (int32_t)WELS_CEIL (log (static_cast<double> (1 + pPps->uiPicSizeInMapUnits / | |
| 1223 | + pPps->uiSliceGroupChangeRate))); | |
| 1224 | + WELS_READ_VERIFY (BsGetBits (pBs, kiNumBits, &uiCode)); //lice_group_change_cycle | |
| 1225 | + pSliceHead->iSliceGroupChangeCycle = uiCode; | |
| 1226 | + } else | |
| 1227 | + pSliceHead->iSliceGroupChangeCycle = 0; | |
| 1228 | + } | |
| 1229 | + | |
| 1230 | + if (!kbExtensionFlag) { | |
| 1231 | + FillDefaultSliceHeaderExt (pSliceHeadExt, pNalHeaderExt); | |
| 1232 | + } else { | |
| 1233 | + /* Extra syntax elements newly introduced */ | |
| 1234 | + pSliceHeadExt->pSubsetSps = pSubsetSps; | |
| 1235 | + | |
| 1236 | + if (!pNalHeaderExt->iNoInterLayerPredFlag && BASE_QUALITY_ID == uiQualityId) { | |
| 1237 | + //the following should be deleted for CODE_CLEAN | |
| 1238 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //ref_layer_dq_id | |
| 1239 | + pSliceHeadExt->uiRefLayerDqId = uiCode; | |
| 1240 | + if (pSubsetSps->sSpsSvcExt.bInterLayerDeblockingFilterCtrlPresentFlag) { | |
| 1241 | + WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //disable_inter_layer_deblocking_filter_idc | |
| 1242 | + pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc = uiCode; | |
| 1243 | + //refer to JVT-X201wcm1.doc G.7.4.3.4--2010.4.20 | |
| 1244 | + if (pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc > 6) { | |
| 1245 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "disable_inter_layer_deblock_filter_idc (%d) out of range [0, 6]", | |
| 1246 | + pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc); | |
| 1247 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_DBLOCKING_IDC); | |
| 1248 | + } | |
| 1249 | + if (pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc != 1) { | |
| 1250 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //inter_layer_slice_alpha_c0_offset_div2 | |
| 1251 | + pSliceHeadExt->iInterLayerSliceAlphaC0Offset = iCode * 2; | |
| 1252 | + WELS_CHECK_SE_BOTH_ERROR (pSliceHeadExt->iInterLayerSliceAlphaC0Offset, | |
| 1253 | + SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN, SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX, | |
| 1254 | + "inter_layer_alpha_c0_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, | |
| 1255 | + ERR_INFO_INVALID_SLICE_ALPHA_C0_OFFSET_DIV2)); | |
| 1256 | + WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //inter_layer_slice_beta_offset_div2 | |
| 1257 | + pSliceHeadExt->iInterLayerSliceBetaOffset = iCode * 2; | |
| 1258 | + WELS_CHECK_SE_BOTH_ERROR (pSliceHeadExt->iInterLayerSliceBetaOffset, SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN, | |
| 1259 | + SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX, "inter_layer_slice_beta_offset_div2 * 2", | |
| 1260 | + GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_BETA_OFFSET_DIV2)); | |
| 1261 | + } | |
| 1262 | + } | |
| 1263 | + | |
| 1264 | + pSliceHeadExt->uiRefLayerChromaPhaseXPlus1Flag = pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseXPlus1Flag; | |
| 1265 | + pSliceHeadExt->uiRefLayerChromaPhaseYPlus1 = pSubsetSps->sSpsSvcExt.uiSeqRefLayerChromaPhaseYPlus1; | |
| 1266 | + | |
| 1267 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //constrained_intra_resampling_flag | |
| 1268 | + pSliceHeadExt->bConstrainedIntraResamplingFlag = !!uiCode; | |
| 1269 | + | |
| 1270 | + { | |
| 1271 | + SPosOffset pos; | |
| 1272 | + pos.iLeftOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iLeftOffset; | |
| 1273 | + pos.iTopOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iTopOffset * (2 - pSps->bFrameMbsOnlyFlag); | |
| 1274 | + pos.iRightOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iRightOffset; | |
| 1275 | + pos.iBottomOffset = pSubsetSps->sSpsSvcExt.sSeqScaledRefLayer.iBottomOffset * (2 - pSps->bFrameMbsOnlyFlag); | |
| 1276 | + //memcpy(&pSliceHeadExt->sScaledRefLayer, &pos, sizeof(SPosOffset));//confirmed_safe_unsafe_usage | |
| 1277 | + pSliceHeadExt->iScaledRefLayerPicWidthInSampleLuma = (pSliceHead->iMbWidth << 4) - | |
| 1278 | + (pos.iLeftOffset + pos.iRightOffset); | |
| 1279 | + pSliceHeadExt->iScaledRefLayerPicHeightInSampleLuma = (pSliceHead->iMbHeight << 4) - | |
| 1280 | + (pos.iTopOffset + pos.iBottomOffset) / (1 + pSliceHead->bFieldPicFlag); | |
| 1281 | + } | |
| 1282 | + } else if (uiQualityId > BASE_QUALITY_ID) { | |
| 1283 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "MGS not supported."); | |
| 1284 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS); | |
| 1285 | + } else { | |
| 1286 | + pSliceHeadExt->uiRefLayerDqId = (uint8_t) - 1; | |
| 1287 | + } | |
| 1288 | + | |
| 1289 | + pSliceHeadExt->bSliceSkipFlag = false; | |
| 1290 | + pSliceHeadExt->bAdaptiveBaseModeFlag = false; | |
| 1291 | + pSliceHeadExt->bDefaultBaseModeFlag = false; | |
| 1292 | + pSliceHeadExt->bAdaptiveMotionPredFlag = false; | |
| 1293 | + pSliceHeadExt->bDefaultMotionPredFlag = false; | |
| 1294 | + pSliceHeadExt->bAdaptiveResidualPredFlag = false; | |
| 1295 | + pSliceHeadExt->bDefaultResidualPredFlag = false; | |
| 1296 | + if (pNalHeaderExt->iNoInterLayerPredFlag) | |
| 1297 | + pSliceHeadExt->bTCoeffLevelPredFlag = false; | |
| 1298 | + else | |
| 1299 | + pSliceHeadExt->bTCoeffLevelPredFlag = pSubsetSps->sSpsSvcExt.bSeqTCoeffLevelPredFlag; | |
| 1300 | + | |
| 1301 | + if (!pNalHeaderExt->iNoInterLayerPredFlag) { | |
| 1302 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //slice_skip_flag | |
| 1303 | + pSliceHeadExt->bSliceSkipFlag = !!uiCode; | |
| 1304 | + if (pSliceHeadExt->bSliceSkipFlag) { | |
| 1305 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "bSliceSkipFlag == 1 not supported."); | |
| 1306 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_SLICESKIP); | |
| 1307 | + } else { | |
| 1308 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_base_mode_flag | |
| 1309 | + pSliceHeadExt->bAdaptiveBaseModeFlag = !!uiCode; | |
| 1310 | + if (!pSliceHeadExt->bAdaptiveBaseModeFlag) { | |
| 1311 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //default_base_mode_flag | |
| 1312 | + pSliceHeadExt->bDefaultBaseModeFlag = !!uiCode; | |
| 1313 | + } | |
| 1314 | + if (!pSliceHeadExt->bDefaultBaseModeFlag) { | |
| 1315 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_motion_prediction_flag | |
| 1316 | + pSliceHeadExt->bAdaptiveMotionPredFlag = !!uiCode; | |
| 1317 | + if (!pSliceHeadExt->bAdaptiveMotionPredFlag) { | |
| 1318 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //default_motion_prediction_flag | |
| 1319 | + pSliceHeadExt->bDefaultMotionPredFlag = !!uiCode; | |
| 1320 | + } | |
| 1321 | + } | |
| 1322 | + | |
| 1323 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_residual_prediction_flag | |
| 1324 | + pSliceHeadExt->bAdaptiveResidualPredFlag = !!uiCode; | |
| 1325 | + if (!pSliceHeadExt->bAdaptiveResidualPredFlag) { | |
| 1326 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //default_residual_prediction_flag | |
| 1327 | + pSliceHeadExt->bDefaultResidualPredFlag = !!uiCode; | |
| 1328 | + } | |
| 1329 | + } | |
| 1330 | + if (pSubsetSps->sSpsSvcExt.bAdaptiveTCoeffLevelPredFlag) { | |
| 1331 | + WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //tcoeff_level_prediction_flag | |
| 1332 | + pSliceHeadExt->bTCoeffLevelPredFlag = !!uiCode; | |
| 1333 | + } | |
| 1334 | + } | |
| 1335 | + | |
| 1336 | + if (!pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) { | |
| 1337 | + WELS_READ_VERIFY (BsGetBits (pBs, 4, &uiCode)); //scan_idx_start | |
| 1338 | + pSliceHeadExt->uiScanIdxStart = uiCode; | |
| 1339 | + WELS_READ_VERIFY (BsGetBits (pBs, 4, &uiCode)); //scan_idx_end | |
| 1340 | + pSliceHeadExt->uiScanIdxEnd = uiCode; | |
| 1341 | + if (pSliceHeadExt->uiScanIdxStart != 0 || pSliceHeadExt->uiScanIdxEnd != 15) { | |
| 1342 | + WelsLog (pLogCtx, WELS_LOG_WARNING, "uiScanIdxStart (%d) != 0 and uiScanIdxEnd (%d) !=15 not supported here", | |
| 1343 | + pSliceHeadExt->uiScanIdxStart, pSliceHeadExt->uiScanIdxEnd); | |
| 1344 | + return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_MGS); | |
| 1345 | + } | |
| 1346 | + } else { | |
| 1347 | + pSliceHeadExt->uiScanIdxStart = 0; | |
| 1348 | + pSliceHeadExt->uiScanIdxEnd = 15; | |
| 1349 | + } | |
| 1350 | + } | |
| 1351 | + | |
| 1352 | + return ERR_NONE; | |
| 1353 | +} | |
| 1354 | + | |
| 1355 | +/* | |
| 1356 | + * Copy relative syntax elements of NALUnitHeaderExt, sRefPicBaseMarking and bStoreRefBasePicFlag in prefix nal unit. | |
| 1357 | + * pSrc: mark as decoded prefix NAL | |
| 1358 | + * ppDst: succeeded VCL NAL based AVC (I/P Slice) | |
| 1359 | + */ | |
| 1360 | +bool PrefetchNalHeaderExtSyntax (PWelsDecoderContext pCtx, PNalUnit const kppDst, PNalUnit const kpSrc) { | |
| 1361 | + PNalUnitHeaderExt pNalHdrExtD = NULL, pNalHdrExtS = NULL; | |
| 1362 | + PSliceHeaderExt pShExtD = NULL; | |
| 1363 | + PPrefixNalUnit pPrefixS = NULL; | |
| 1364 | + PSps pSps = NULL; | |
| 1365 | + int32_t iIdx = 0; | |
| 1366 | + | |
| 1367 | + if (kppDst == NULL || kpSrc == NULL) | |
| 1368 | + return false; | |
| 1369 | + | |
| 1370 | + pNalHdrExtD = &kppDst->sNalHeaderExt; | |
| 1371 | + pNalHdrExtS = &kpSrc->sNalHeaderExt; | |
| 1372 | + pShExtD = &kppDst->sNalData.sVclNal.sSliceHeaderExt; | |
| 1373 | + pPrefixS = &kpSrc->sNalData.sPrefixNal; | |
| 1374 | + pSps = &pCtx->sSpsBuffer[pCtx->sPpsBuffer[pShExtD->sSliceHeader.iPpsId].iSpsId]; | |
| 1375 | + | |
| 1376 | + pNalHdrExtD->uiDependencyId = pNalHdrExtS->uiDependencyId; | |
| 1377 | + pNalHdrExtD->uiQualityId = pNalHdrExtS->uiQualityId; | |
| 1378 | + pNalHdrExtD->uiTemporalId = pNalHdrExtS->uiTemporalId; | |
| 1379 | + pNalHdrExtD->uiPriorityId = pNalHdrExtS->uiPriorityId; | |
| 1380 | + pNalHdrExtD->bIdrFlag = pNalHdrExtS->bIdrFlag; | |
| 1381 | + pNalHdrExtD->iNoInterLayerPredFlag = pNalHdrExtS->iNoInterLayerPredFlag; | |
| 1382 | + pNalHdrExtD->bDiscardableFlag = pNalHdrExtS->bDiscardableFlag; | |
| 1383 | + pNalHdrExtD->bOutputFlag = pNalHdrExtS->bOutputFlag; | |
| 1384 | + pNalHdrExtD->bUseRefBasePicFlag = pNalHdrExtS->bUseRefBasePicFlag; | |
| 1385 | + pNalHdrExtD->uiLayerDqId = pNalHdrExtS->uiLayerDqId; | |
| 1386 | + | |
| 1387 | + pShExtD->bStoreRefBasePicFlag = pPrefixS->bStoreRefBasePicFlag; | |
| 1388 | + memcpy (&pShExtD->sRefBasePicMarking, &pPrefixS->sRefPicBaseMarking, | |
| 1389 | + sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage | |
| 1390 | + if (pShExtD->sRefBasePicMarking.bAdaptiveRefBasePicMarkingModeFlag) { | |
| 1391 | + PRefBasePicMarking pRefBasePicMarking = &pShExtD->sRefBasePicMarking; | |
| 1392 | + iIdx = 0; | |
| 1393 | + do { | |
| 1394 | + if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_END) | |
| 1395 | + break; | |
| 1396 | + if (pRefBasePicMarking->mmco_base[iIdx].uiMmcoType == MMCO_SHORT2UNUSED) | |
| 1397 | + pRefBasePicMarking->mmco_base[iIdx].iShortFrameNum = (pShExtD->sSliceHeader.iFrameNum - | |
| 1398 | + pRefBasePicMarking->mmco_base[iIdx].uiDiffOfPicNums) & ((1 << pSps->uiLog2MaxFrameNum) - 1); | |
| 1399 | + ++ iIdx; | |
| 1400 | + } while (iIdx < MAX_MMCO_COUNT); | |
| 1401 | + } | |
| 1402 | + | |
| 1403 | + return true; | |
| 1404 | +} | |
| 1405 | + | |
| 1406 | + | |
| 1407 | + | |
| 1408 | +int32_t UpdateAccessUnit (PWelsDecoderContext pCtx) { | |
| 1409 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1410 | + int32_t iIdx = pCurAu->uiEndPos; | |
| 1411 | + | |
| 1412 | + // Conversed iterator | |
| 1413 | + pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iIdx]->sNalHeaderExt.uiLayerDqId; | |
| 1414 | + pCurAu->uiActualUnitsNum = iIdx + 1; | |
| 1415 | + pCurAu->bCompletedAuFlag = true; | |
| 1416 | + | |
| 1417 | + // Added for mosaic avoidance, 11/19/2009 | |
| 1418 | +#ifdef LONG_TERM_REF | |
| 1419 | + if (pCtx->bParamSetsLostFlag || pCtx->bNewSeqBegin) | |
| 1420 | +#else | |
| 1421 | + if (pCtx->bReferenceLostAtT0Flag || pCtx->bNewSeqBegin) | |
| 1422 | +#endif | |
| 1423 | + { | |
| 1424 | + uint32_t uiActualIdx = 0; | |
| 1425 | + while (uiActualIdx < pCurAu->uiActualUnitsNum) { | |
| 1426 | + PNalUnit nal = pCurAu->pNalUnitsList[uiActualIdx]; | |
| 1427 | + | |
| 1428 | + if (nal->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR || nal->sNalHeaderExt.bIdrFlag) { | |
| 1429 | + break; | |
| 1430 | + } | |
| 1431 | + ++ uiActualIdx; | |
| 1432 | + } | |
| 1433 | + if (uiActualIdx == | |
| 1434 | + pCurAu->uiActualUnitsNum) { // no found IDR nal within incoming AU, need exit to avoid mosaic issue, 11/19/2009 | |
| 1435 | + | |
| 1436 | + pCtx->sDecoderStatistics.uiIDRLostNum++; | |
| 1437 | + if (!pCtx->bParamSetsLostFlag) | |
| 1438 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, | |
| 1439 | + "UpdateAccessUnit():::::Key frame lost.....CAN NOT find IDR from current AU."); | |
| 1440 | + pCtx->iErrorCode |= dsRefLost; | |
| 1441 | + if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 1442 | +#ifdef LONG_TERM_REF | |
| 1443 | + pCtx->iErrorCode |= dsNoParamSets; | |
| 1444 | + return dsNoParamSets; | |
| 1445 | +#else | |
| 1446 | + pCtx->iErrorCode |= dsRefLost; | |
| 1447 | + return ERR_INFO_REFERENCE_PIC_LOST; | |
| 1448 | +#endif | |
| 1449 | + } | |
| 1450 | + } | |
| 1451 | + } | |
| 1452 | + | |
| 1453 | + return ERR_NONE; | |
| 1454 | +} | |
| 1455 | + | |
| 1456 | +int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWidth, const int32_t kiMaxHeight) { | |
| 1457 | + int32_t i = 0; | |
| 1458 | + | |
| 1459 | + WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiMaxWidth <= 0 || kiMaxHeight <= 0)) | |
| 1460 | + pCtx->sMb.iMbWidth = (kiMaxWidth + 15) >> 4; | |
| 1461 | + pCtx->sMb.iMbHeight = (kiMaxHeight + 15) >> 4; | |
| 1462 | + | |
| 1463 | + if (pCtx->bInitialDqLayersMem && kiMaxWidth <= pCtx->iPicWidthReq | |
| 1464 | + && kiMaxHeight <= pCtx->iPicHeightReq) // have same dimension memory, skipped | |
| 1465 | + return ERR_NONE; | |
| 1466 | + | |
| 1467 | + CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 1468 | + | |
| 1469 | + UninitialDqLayersContext (pCtx); | |
| 1470 | + | |
| 1471 | + do { | |
| 1472 | + PDqLayer pDq = (PDqLayer)pMa->WelsMallocz (sizeof (SDqLayer), "PDqLayer"); | |
| 1473 | + | |
| 1474 | + if (pDq == NULL) | |
| 1475 | + return ERR_INFO_OUT_OF_MEMORY; | |
| 1476 | + | |
| 1477 | + pCtx->pDqLayersList[i] = pDq; //to keep consistence with in UninitialDqLayersContext() | |
| 1478 | + memset (pDq, 0, sizeof (SDqLayer)); | |
| 1479 | + | |
| 1480 | + pCtx->sMb.pMbType[i] = (uint32_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (uint32_t), | |
| 1481 | + "pCtx->sMb.pMbType[]"); | |
| 1482 | + pCtx->sMb.pMv[i][LIST_0] = (int16_t (*)[16][2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1483 | + int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMv[][]"); | |
| 1484 | + pCtx->sMb.pMv[i][LIST_1] = (int16_t (*)[16][2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1485 | + int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMv[][]"); | |
| 1486 | + | |
| 1487 | + pCtx->sMb.pRefIndex[i][LIST_0] = (int8_t (*)[MB_BLOCK4x4_NUM])pMa->WelsMallocz (pCtx->sMb.iMbWidth * | |
| 1488 | + pCtx->sMb.iMbHeight * | |
| 1489 | + sizeof ( | |
| 1490 | + int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pRefIndex[][]"); | |
| 1491 | + pCtx->sMb.pRefIndex[i][LIST_1] = (int8_t (*)[MB_BLOCK4x4_NUM])pMa->WelsMallocz (pCtx->sMb.iMbWidth * | |
| 1492 | + pCtx->sMb.iMbHeight * | |
| 1493 | + sizeof ( | |
| 1494 | + int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pRefIndex[][]"); | |
| 1495 | + pCtx->sMb.pDirect[i] = (int8_t (*)[MB_BLOCK4x4_NUM])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * | |
| 1496 | + sizeof ( | |
| 1497 | + int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pDirect[]"); | |
| 1498 | + pCtx->sMb.pLumaQp[i] = (int8_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1499 | + "pCtx->sMb.pLumaQp[]"); | |
| 1500 | + pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i] = (bool*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * | |
| 1501 | + sizeof ( | |
| 1502 | + bool), | |
| 1503 | + "pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[]"); | |
| 1504 | + pCtx->sMb.pTransformSize8x8Flag[i] = (bool*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (bool), | |
| 1505 | + "pCtx->sMb.pTransformSize8x8Flag[]"); | |
| 1506 | + pCtx->sMb.pChromaQp[i] = (int8_t (*)[2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1507 | + int8_t) * 2, | |
| 1508 | + "pCtx->sMb.pChromaQp[]"); | |
| 1509 | + pCtx->sMb.pMvd[i][LIST_0] = (int16_t (*)[16][2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1510 | + int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMvd[][]"); | |
| 1511 | + pCtx->sMb.pMvd[i][LIST_1] = (int16_t (*)[16][2])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1512 | + int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMvd[][]"); | |
| 1513 | + pCtx->sMb.pCbfDc[i] = (uint16_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (uint16_t), | |
| 1514 | + "pCtx->sMb.pCbfDc[]"); | |
| 1515 | + pCtx->sMb.pNzc[i] = (int8_t (*)[24])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24, | |
| 1516 | + "pCtx->sMb.pNzc[]"); | |
| 1517 | + pCtx->sMb.pNzcRs[i] = (int8_t (*)[24])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24, | |
| 1518 | + "pCtx->sMb.pNzcRs[]"); | |
| 1519 | + pCtx->sMb.pScaledTCoeff[i] = (int16_t (*)[MB_COEFF_LIST_SIZE])pMa->WelsMallocz (pCtx->sMb.iMbWidth * | |
| 1520 | + pCtx->sMb.iMbHeight * | |
| 1521 | + sizeof (int16_t) * MB_COEFF_LIST_SIZE, "pCtx->sMb.pScaledTCoeff[]"); | |
| 1522 | + pCtx->sMb.pIntraPredMode[i] = (int8_t (*)[8])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1523 | + int8_t) * 8, | |
| 1524 | + "pCtx->sMb.pIntraPredMode[]"); | |
| 1525 | + pCtx->sMb.pIntra4x4FinalMode[i] = (int8_t (*)[MB_BLOCK4x4_NUM])pMa->WelsMallocz (pCtx->sMb.iMbWidth * | |
| 1526 | + pCtx->sMb.iMbHeight * | |
| 1527 | + sizeof (int8_t) * MB_BLOCK4x4_NUM, "pCtx->sMb.pIntra4x4FinalMode[]"); | |
| 1528 | + pCtx->sMb.pIntraNxNAvailFlag[i] = (uint8_t (*))pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1529 | + int8_t), | |
| 1530 | + "pCtx->sMb.pIntraNxNAvailFlag"); | |
| 1531 | + pCtx->sMb.pChromaPredMode[i] = (int8_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1532 | + "pCtx->sMb.pChromaPredMode[]"); | |
| 1533 | + pCtx->sMb.pCbp[i] = (int8_t*)pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1534 | + "pCtx->sMb.pCbp[]"); | |
| 1535 | + pCtx->sMb.pSubMbType[i] = (uint32_t (*)[MB_PARTITION_SIZE])pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * | |
| 1536 | + sizeof ( | |
| 1537 | + uint32_t) * MB_PARTITION_SIZE, "pCtx->sMb.pSubMbType[]"); | |
| 1538 | + pCtx->sMb.pSliceIdc[i] = (int32_t*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t), | |
| 1539 | + "pCtx->sMb.pSliceIdc[]"); // using int32_t for slice_idc, 4/21/2010 | |
| 1540 | + pCtx->sMb.pResidualPredFlag[i] = (int8_t*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t), | |
| 1541 | + "pCtx->sMb.pResidualPredFlag[]"); | |
| 1542 | + pCtx->sMb.pInterPredictionDoneFlag[i] = (int8_t*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1543 | + int8_t), "pCtx->sMb.pInterPredictionDoneFlag[]"); | |
| 1544 | + | |
| 1545 | + pCtx->sMb.pMbCorrectlyDecodedFlag[i] = (bool*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof ( | |
| 1546 | + bool), | |
| 1547 | + "pCtx->sMb.pMbCorrectlyDecodedFlag[]"); | |
| 1548 | + pCtx->sMb.pMbRefConcealedFlag[i] = (bool*) pMa->WelsMallocz (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (bool), | |
| 1549 | + "pCtx->pMbRefConcealedFlag[]"); | |
| 1550 | + | |
| 1551 | + // check memory block valid due above allocated.. | |
| 1552 | + WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, | |
| 1553 | + ((NULL == pCtx->sMb.pMbType[i]) || | |
| 1554 | + (NULL == pCtx->sMb.pMv[i][LIST_0]) || | |
| 1555 | + (NULL == pCtx->sMb.pMv[i][LIST_1]) || | |
| 1556 | + (NULL == pCtx->sMb.pRefIndex[i][LIST_0]) || | |
| 1557 | + (NULL == pCtx->sMb.pRefIndex[i][LIST_1]) || | |
| 1558 | + (NULL == pCtx->sMb.pDirect[i]) || | |
| 1559 | + (NULL == pCtx->sMb.pLumaQp[i]) || | |
| 1560 | + (NULL == pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i]) || | |
| 1561 | + (NULL == pCtx->sMb.pTransformSize8x8Flag[i]) || | |
| 1562 | + (NULL == pCtx->sMb.pChromaQp[i]) || | |
| 1563 | + (NULL == pCtx->sMb.pMvd[i][LIST_0]) || | |
| 1564 | + (NULL == pCtx->sMb.pMvd[i][LIST_1]) || | |
| 1565 | + (NULL == pCtx->sMb.pCbfDc[i]) || | |
| 1566 | + (NULL == pCtx->sMb.pNzc[i]) || | |
| 1567 | + (NULL == pCtx->sMb.pNzcRs[i]) || | |
| 1568 | + (NULL == pCtx->sMb.pScaledTCoeff[i]) || | |
| 1569 | + (NULL == pCtx->sMb.pIntraPredMode[i]) || | |
| 1570 | + (NULL == pCtx->sMb.pIntra4x4FinalMode[i]) || | |
| 1571 | + (NULL == pCtx->sMb.pIntraNxNAvailFlag[i]) || | |
| 1572 | + (NULL == pCtx->sMb.pChromaPredMode[i]) || | |
| 1573 | + (NULL == pCtx->sMb.pCbp[i]) || | |
| 1574 | + (NULL == pCtx->sMb.pSubMbType[i]) || | |
| 1575 | + (NULL == pCtx->sMb.pSliceIdc[i]) || | |
| 1576 | + (NULL == pCtx->sMb.pResidualPredFlag[i]) || | |
| 1577 | + (NULL == pCtx->sMb.pInterPredictionDoneFlag[i]) || | |
| 1578 | + (NULL == pCtx->sMb.pMbRefConcealedFlag[i]) || | |
| 1579 | + (NULL == pCtx->sMb.pMbCorrectlyDecodedFlag[i]) | |
| 1580 | + ) | |
| 1581 | + ) | |
| 1582 | + | |
| 1583 | + memset (pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t))); | |
| 1584 | + | |
| 1585 | + ++ i; | |
| 1586 | + } while (i < LAYER_NUM_EXCHANGEABLE); | |
| 1587 | + | |
| 1588 | + pCtx->bInitialDqLayersMem = true; | |
| 1589 | + pCtx->iPicWidthReq = kiMaxWidth; | |
| 1590 | + pCtx->iPicHeightReq = kiMaxHeight; | |
| 1591 | + | |
| 1592 | + return ERR_NONE; | |
| 1593 | +} | |
| 1594 | + | |
| 1595 | +void UninitialDqLayersContext (PWelsDecoderContext pCtx) { | |
| 1596 | + int32_t i = 0; | |
| 1597 | + CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 1598 | + | |
| 1599 | + do { | |
| 1600 | + PDqLayer pDq = pCtx->pDqLayersList[i]; | |
| 1601 | + if (pDq == NULL) { | |
| 1602 | + ++ i; | |
| 1603 | + continue; | |
| 1604 | + } | |
| 1605 | + | |
| 1606 | + if (pCtx->sMb.pMbType[i]) { | |
| 1607 | + pMa->WelsFree (pCtx->sMb.pMbType[i], "pCtx->sMb.pMbType[]"); | |
| 1608 | + | |
| 1609 | + pCtx->sMb.pMbType[i] = NULL; | |
| 1610 | + } | |
| 1611 | + | |
| 1612 | + for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) { | |
| 1613 | + if (pCtx->sMb.pMv[i][listIdx]) { | |
| 1614 | + pMa->WelsFree (pCtx->sMb.pMv[i][listIdx], "pCtx->sMb.pMv[][]"); | |
| 1615 | + pCtx->sMb.pMv[i][listIdx] = NULL; | |
| 1616 | + } | |
| 1617 | + | |
| 1618 | + if (pCtx->sMb.pRefIndex[i][listIdx]) { | |
| 1619 | + pMa->WelsFree (pCtx->sMb.pRefIndex[i][listIdx], "pCtx->sMb.pRefIndex[][]"); | |
| 1620 | + pCtx->sMb.pRefIndex[i][listIdx] = NULL; | |
| 1621 | + } | |
| 1622 | + | |
| 1623 | + if (pCtx->sMb.pDirect[i]) { | |
| 1624 | + pMa->WelsFree (pCtx->sMb.pDirect[i], "pCtx->sMb.pDirect[]"); | |
| 1625 | + pCtx->sMb.pDirect[i] = NULL; | |
| 1626 | + } | |
| 1627 | + | |
| 1628 | + if (pCtx->sMb.pMvd[i][listIdx]) { | |
| 1629 | + pMa->WelsFree (pCtx->sMb.pMvd[i][listIdx], "pCtx->sMb.pMvd[][]"); | |
| 1630 | + pCtx->sMb.pMvd[i][listIdx] = NULL; | |
| 1631 | + } | |
| 1632 | + } | |
| 1633 | + | |
| 1634 | + if (pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i]) { | |
| 1635 | + pMa->WelsFree (pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i], "pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[]"); | |
| 1636 | + | |
| 1637 | + pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[i] = NULL; | |
| 1638 | + } | |
| 1639 | + | |
| 1640 | + if (pCtx->sMb.pTransformSize8x8Flag[i]) { | |
| 1641 | + pMa->WelsFree (pCtx->sMb.pTransformSize8x8Flag[i], "pCtx->sMb.pTransformSize8x8Flag[]"); | |
| 1642 | + | |
| 1643 | + pCtx->sMb.pTransformSize8x8Flag[i] = NULL; | |
| 1644 | + } | |
| 1645 | + | |
| 1646 | + if (pCtx->sMb.pLumaQp[i]) { | |
| 1647 | + pMa->WelsFree (pCtx->sMb.pLumaQp[i], "pCtx->sMb.pLumaQp[]"); | |
| 1648 | + | |
| 1649 | + pCtx->sMb.pLumaQp[i] = NULL; | |
| 1650 | + } | |
| 1651 | + | |
| 1652 | + if (pCtx->sMb.pChromaQp[i]) { | |
| 1653 | + pMa->WelsFree (pCtx->sMb.pChromaQp[i], "pCtx->sMb.pChromaQp[]"); | |
| 1654 | + | |
| 1655 | + pCtx->sMb.pChromaQp[i] = NULL; | |
| 1656 | + } | |
| 1657 | + | |
| 1658 | + if (pCtx->sMb.pCbfDc[i]) { | |
| 1659 | + pMa->WelsFree (pCtx->sMb.pCbfDc[i], "pCtx->sMb.pCbfDc[]"); | |
| 1660 | + pCtx->sMb.pCbfDc[i] = NULL; | |
| 1661 | + } | |
| 1662 | + | |
| 1663 | + if (pCtx->sMb.pNzc[i]) { | |
| 1664 | + pMa->WelsFree (pCtx->sMb.pNzc[i], "pCtx->sMb.pNzc[]"); | |
| 1665 | + | |
| 1666 | + pCtx->sMb.pNzc[i] = NULL; | |
| 1667 | + } | |
| 1668 | + | |
| 1669 | + if (pCtx->sMb.pNzcRs[i]) { | |
| 1670 | + pMa->WelsFree (pCtx->sMb.pNzcRs[i], "pCtx->sMb.pNzcRs[]"); | |
| 1671 | + | |
| 1672 | + pCtx->sMb.pNzcRs[i] = NULL; | |
| 1673 | + } | |
| 1674 | + | |
| 1675 | + if (pCtx->sMb.pScaledTCoeff[i]) { | |
| 1676 | + pMa->WelsFree (pCtx->sMb.pScaledTCoeff[i], "pCtx->sMb.pScaledTCoeff[]"); | |
| 1677 | + | |
| 1678 | + pCtx->sMb.pScaledTCoeff[i] = NULL; | |
| 1679 | + } | |
| 1680 | + | |
| 1681 | + if (pCtx->sMb.pIntraPredMode[i]) { | |
| 1682 | + pMa->WelsFree (pCtx->sMb.pIntraPredMode[i], "pCtx->sMb.pIntraPredMode[]"); | |
| 1683 | + | |
| 1684 | + pCtx->sMb.pIntraPredMode[i] = NULL; | |
| 1685 | + } | |
| 1686 | + | |
| 1687 | + if (pCtx->sMb.pIntra4x4FinalMode[i]) { | |
| 1688 | + pMa->WelsFree (pCtx->sMb.pIntra4x4FinalMode[i], "pCtx->sMb.pIntra4x4FinalMode[]"); | |
| 1689 | + | |
| 1690 | + pCtx->sMb.pIntra4x4FinalMode[i] = NULL; | |
| 1691 | + } | |
| 1692 | + | |
| 1693 | + if (pCtx->sMb.pIntraNxNAvailFlag[i]) { | |
| 1694 | + pMa->WelsFree (pCtx->sMb.pIntraNxNAvailFlag[i], "pCtx->sMb.pIntraNxNAvailFlag"); | |
| 1695 | + | |
| 1696 | + pCtx->sMb.pIntraNxNAvailFlag[i] = NULL; | |
| 1697 | + } | |
| 1698 | + | |
| 1699 | + if (pCtx->sMb.pChromaPredMode[i]) { | |
| 1700 | + pMa->WelsFree (pCtx->sMb.pChromaPredMode[i], "pCtx->sMb.pChromaPredMode[]"); | |
| 1701 | + | |
| 1702 | + pCtx->sMb.pChromaPredMode[i] = NULL; | |
| 1703 | + } | |
| 1704 | + | |
| 1705 | + if (pCtx->sMb.pCbp[i]) { | |
| 1706 | + pMa->WelsFree (pCtx->sMb.pCbp[i], "pCtx->sMb.pCbp[]"); | |
| 1707 | + | |
| 1708 | + pCtx->sMb.pCbp[i] = NULL; | |
| 1709 | + } | |
| 1710 | + | |
| 1711 | + // if (pCtx->sMb.pMotionPredFlag[i]) | |
| 1712 | + //{ | |
| 1713 | + // pMa->WelsFree( pCtx->sMb.pMotionPredFlag[i], "pCtx->sMb.pMotionPredFlag[]" ); | |
| 1714 | + | |
| 1715 | + // pCtx->sMb.pMotionPredFlag[i] = NULL; | |
| 1716 | + //} | |
| 1717 | + | |
| 1718 | + if (pCtx->sMb.pSubMbType[i]) { | |
| 1719 | + pMa->WelsFree (pCtx->sMb.pSubMbType[i], "pCtx->sMb.pSubMbType[]"); | |
| 1720 | + | |
| 1721 | + pCtx->sMb.pSubMbType[i] = NULL; | |
| 1722 | + } | |
| 1723 | + | |
| 1724 | + if (pCtx->sMb.pSliceIdc[i]) { | |
| 1725 | + pMa->WelsFree (pCtx->sMb.pSliceIdc[i], "pCtx->sMb.pSliceIdc[]"); | |
| 1726 | + | |
| 1727 | + pCtx->sMb.pSliceIdc[i] = NULL; | |
| 1728 | + } | |
| 1729 | + | |
| 1730 | + if (pCtx->sMb.pResidualPredFlag[i]) { | |
| 1731 | + pMa->WelsFree (pCtx->sMb.pResidualPredFlag[i], "pCtx->sMb.pResidualPredFlag[]"); | |
| 1732 | + | |
| 1733 | + pCtx->sMb.pResidualPredFlag[i] = NULL; | |
| 1734 | + } | |
| 1735 | + | |
| 1736 | + if (pCtx->sMb.pInterPredictionDoneFlag[i]) { | |
| 1737 | + pMa->WelsFree (pCtx->sMb.pInterPredictionDoneFlag[i], "pCtx->sMb.pInterPredictionDoneFlag[]"); | |
| 1738 | + | |
| 1739 | + pCtx->sMb.pInterPredictionDoneFlag[i] = NULL; | |
| 1740 | + } | |
| 1741 | + | |
| 1742 | + if (pCtx->sMb.pMbCorrectlyDecodedFlag[i]) { | |
| 1743 | + pMa->WelsFree (pCtx->sMb.pMbCorrectlyDecodedFlag[i], "pCtx->sMb.pMbCorrectlyDecodedFlag[]"); | |
| 1744 | + pCtx->sMb.pMbCorrectlyDecodedFlag[i] = NULL; | |
| 1745 | + } | |
| 1746 | + | |
| 1747 | + if (pCtx->sMb.pMbRefConcealedFlag[i]) { | |
| 1748 | + pMa->WelsFree (pCtx->sMb.pMbRefConcealedFlag[i], "pCtx->sMb.pMbRefConcealedFlag[]"); | |
| 1749 | + pCtx->sMb.pMbRefConcealedFlag[i] = NULL; | |
| 1750 | + } | |
| 1751 | + pMa->WelsFree (pDq, "pDq"); | |
| 1752 | + | |
| 1753 | + pDq = NULL; | |
| 1754 | + pCtx->pDqLayersList[i] = NULL; | |
| 1755 | + | |
| 1756 | + ++ i; | |
| 1757 | + } while (i < LAYER_NUM_EXCHANGEABLE); | |
| 1758 | + | |
| 1759 | + pCtx->iPicWidthReq = 0; | |
| 1760 | + pCtx->iPicHeightReq = 0; | |
| 1761 | + pCtx->bInitialDqLayersMem = false; | |
| 1762 | +} | |
| 1763 | + | |
| 1764 | +void ResetCurrentAccessUnit (PWelsDecoderContext pCtx) { | |
| 1765 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1766 | + pCurAu->uiStartPos = 0; | |
| 1767 | + pCurAu->uiEndPos = 0; | |
| 1768 | + pCurAu->bCompletedAuFlag = false; | |
| 1769 | + if (pCurAu->uiActualUnitsNum > 0) { | |
| 1770 | + uint32_t iIdx = 0; | |
| 1771 | + const uint32_t kuiActualNum = pCurAu->uiActualUnitsNum; | |
| 1772 | + // a more simpler method to do nal units list management prefered here | |
| 1773 | + const uint32_t kuiAvailNum = pCurAu->uiAvailUnitsNum; | |
| 1774 | + const uint32_t kuiLeftNum = kuiAvailNum - kuiActualNum; | |
| 1775 | + | |
| 1776 | + // Swapping active nal unit nodes of succeeding AU with leading of list | |
| 1777 | + while (iIdx < kuiLeftNum) { | |
| 1778 | + PNalUnit t = pCurAu->pNalUnitsList[kuiActualNum + iIdx]; | |
| 1779 | + pCurAu->pNalUnitsList[kuiActualNum + iIdx] = pCurAu->pNalUnitsList[iIdx]; | |
| 1780 | + pCurAu->pNalUnitsList[iIdx] = t; | |
| 1781 | + ++ iIdx; | |
| 1782 | + } | |
| 1783 | + pCurAu->uiActualUnitsNum = pCurAu->uiAvailUnitsNum = kuiLeftNum; | |
| 1784 | + } | |
| 1785 | +} | |
| 1786 | + | |
| 1787 | +/*! | |
| 1788 | + * \brief Force reset current Acess Unit Nal list in case error parsing/decoding in current AU | |
| 1789 | + * \author | |
| 1790 | + * \history 11/16/2009 | |
| 1791 | + */ | |
| 1792 | +void ForceResetCurrentAccessUnit (PAccessUnit pAu) { | |
| 1793 | + uint32_t uiSucAuIdx = pAu->uiEndPos + 1; | |
| 1794 | + uint32_t uiCurAuIdx = 0; | |
| 1795 | + | |
| 1796 | + // swap the succeeding AU's nal units to the front | |
| 1797 | + while (uiSucAuIdx < pAu->uiAvailUnitsNum) { | |
| 1798 | + PNalUnit t = pAu->pNalUnitsList[uiSucAuIdx]; | |
| 1799 | + pAu->pNalUnitsList[uiSucAuIdx] = pAu->pNalUnitsList[uiCurAuIdx]; | |
| 1800 | + pAu->pNalUnitsList[uiCurAuIdx] = t; | |
| 1801 | + ++ uiSucAuIdx; | |
| 1802 | + ++ uiCurAuIdx; | |
| 1803 | + } | |
| 1804 | + | |
| 1805 | + // Update avail/actual units num accordingly for next AU parsing | |
| 1806 | + if (pAu->uiAvailUnitsNum > pAu->uiEndPos) | |
| 1807 | + pAu->uiAvailUnitsNum -= (pAu->uiEndPos + 1); | |
| 1808 | + else | |
| 1809 | + pAu->uiAvailUnitsNum = 0; | |
| 1810 | + pAu->uiActualUnitsNum = 0; | |
| 1811 | + pAu->uiStartPos = 0; | |
| 1812 | + pAu->uiEndPos = 0; | |
| 1813 | + pAu->bCompletedAuFlag = false; | |
| 1814 | +} | |
| 1815 | + | |
| 1816 | +//clear current corrupted NAL from pNalUnitsList | |
| 1817 | +void ForceClearCurrentNal (PAccessUnit pAu) { | |
| 1818 | + if (pAu->uiAvailUnitsNum > 0) | |
| 1819 | + -- pAu->uiAvailUnitsNum; | |
| 1820 | +} | |
| 1821 | + | |
| 1822 | +void ForceResetParaSetStatusAndAUList (PWelsDecoderContext pCtx) { | |
| 1823 | + pCtx->bSpsExistAheadFlag = false; | |
| 1824 | + pCtx->bSubspsExistAheadFlag = false; | |
| 1825 | + pCtx->bPpsExistAheadFlag = false; | |
| 1826 | + | |
| 1827 | + // Force clear the AU list | |
| 1828 | + pCtx->pAccessUnitList->uiAvailUnitsNum = 0; | |
| 1829 | + pCtx->pAccessUnitList->uiActualUnitsNum = 0; | |
| 1830 | + pCtx->pAccessUnitList->uiStartPos = 0; | |
| 1831 | + pCtx->pAccessUnitList->uiEndPos = 0; | |
| 1832 | + pCtx->pAccessUnitList->bCompletedAuFlag = false; | |
| 1833 | +} | |
| 1834 | + | |
| 1835 | +void CheckAvailNalUnitsListContinuity (PWelsDecoderContext pCtx, int32_t iStartIdx, int32_t iEndIdx) { | |
| 1836 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1837 | + | |
| 1838 | + uint8_t uiLastNuDependencyId, uiLastNuLayerDqId; | |
| 1839 | + uint8_t uiCurNuDependencyId, uiCurNuQualityId, uiCurNuLayerDqId, uiCurNuRefLayerDqId; | |
| 1840 | + | |
| 1841 | + int32_t iCurNalUnitIdx = 0; | |
| 1842 | + | |
| 1843 | + //check the continuity of pNalUnitsList forwards (from pIdxNoInterLayerPred to end_postion) | |
| 1844 | + uiLastNuDependencyId = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiDependencyId;//starting nal unit | |
| 1845 | + uiLastNuLayerDqId = pCurAu->pNalUnitsList[iStartIdx]->sNalHeaderExt.uiLayerDqId;//starting nal unit | |
| 1846 | + iCurNalUnitIdx = iStartIdx + 1;//current nal unit | |
| 1847 | + while (iCurNalUnitIdx <= iEndIdx) { | |
| 1848 | + uiCurNuDependencyId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiDependencyId; | |
| 1849 | + uiCurNuQualityId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiQualityId; | |
| 1850 | + uiCurNuLayerDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId; | |
| 1851 | + uiCurNuRefLayerDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalData.sVclNal.sSliceHeaderExt.uiRefLayerDqId; | |
| 1852 | + | |
| 1853 | + if (uiCurNuDependencyId == uiLastNuDependencyId) { | |
| 1854 | + uiLastNuLayerDqId = uiCurNuLayerDqId; | |
| 1855 | + ++ iCurNalUnitIdx; | |
| 1856 | + } else { //uiCurNuDependencyId != uiLastNuDependencyId, new dependency arrive | |
| 1857 | + if (uiCurNuQualityId == 0) { | |
| 1858 | + uiLastNuDependencyId = uiCurNuDependencyId; | |
| 1859 | + if (uiCurNuRefLayerDqId == uiLastNuLayerDqId) { | |
| 1860 | + uiLastNuLayerDqId = uiCurNuLayerDqId; | |
| 1861 | + ++ iCurNalUnitIdx; | |
| 1862 | + } else { //cur_nu_layer_id != next_nu_ref_layer_dq_id, the chain is broken at this point | |
| 1863 | + break; | |
| 1864 | + } | |
| 1865 | + } else { //new dependency arrive, but no base quality layer, so we must stop in this point | |
| 1866 | + break; | |
| 1867 | + } | |
| 1868 | + } | |
| 1869 | + } | |
| 1870 | + | |
| 1871 | + -- iCurNalUnitIdx; | |
| 1872 | + pCurAu->uiEndPos = iCurNalUnitIdx; | |
| 1873 | + pCtx->uiTargetDqId = pCurAu->pNalUnitsList[iCurNalUnitIdx]->sNalHeaderExt.uiLayerDqId; | |
| 1874 | +} | |
| 1875 | + | |
| 1876 | +//main purpose: to support multi-slice and to include all slice which have the same uiDependencyId, uiQualityId and frame_num | |
| 1877 | +//for single slice, pIdxNoInterLayerPred SHOULD NOT be modified | |
| 1878 | +void RefineIdxNoInterLayerPred (PAccessUnit pCurAu, int32_t* pIdxNoInterLayerPred) { | |
| 1879 | + int32_t iLastNalDependId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiDependencyId; | |
| 1880 | + int32_t iLastNalQualityId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiQualityId; | |
| 1881 | + uint8_t uiLastNalTId = pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalHeaderExt.uiTemporalId; | |
| 1882 | + int32_t iLastNalFrameNum = | |
| 1883 | + pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum; | |
| 1884 | + int32_t iLastNalPoc = | |
| 1885 | + pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1886 | + int32_t iLastNalFirstMb = | |
| 1887 | + pCurAu->pNalUnitsList[*pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice; | |
| 1888 | + int32_t iCurNalDependId, iCurNalQualityId, iCurNalTId, iCurNalFrameNum, iCurNalPoc, iCurNalFirstMb, iCurIdx, | |
| 1889 | + iFinalIdxNoInterLayerPred; | |
| 1890 | + | |
| 1891 | + bool bMultiSliceFind = false; | |
| 1892 | + | |
| 1893 | + iFinalIdxNoInterLayerPred = 0; | |
| 1894 | + iCurIdx = *pIdxNoInterLayerPred - 1; | |
| 1895 | + while (iCurIdx >= 0) { | |
| 1896 | + if (pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 1897 | + iCurNalDependId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; | |
| 1898 | + iCurNalQualityId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; | |
| 1899 | + iCurNalTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; | |
| 1900 | + iCurNalFrameNum = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFrameNum; | |
| 1901 | + iCurNalPoc = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1902 | + iCurNalFirstMb = pCurAu->pNalUnitsList[iCurIdx]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice; | |
| 1903 | + | |
| 1904 | + if (iCurNalDependId == iLastNalDependId && | |
| 1905 | + iCurNalQualityId == iLastNalQualityId && | |
| 1906 | + iCurNalTId == uiLastNalTId && | |
| 1907 | + iCurNalFrameNum == iLastNalFrameNum && | |
| 1908 | + iCurNalPoc == iLastNalPoc && | |
| 1909 | + iCurNalFirstMb != iLastNalFirstMb) { | |
| 1910 | + bMultiSliceFind = true; | |
| 1911 | + iFinalIdxNoInterLayerPred = iCurIdx; | |
| 1912 | + --iCurIdx; | |
| 1913 | + continue; | |
| 1914 | + } else { | |
| 1915 | + break; | |
| 1916 | + } | |
| 1917 | + } | |
| 1918 | + --iCurIdx; | |
| 1919 | + } | |
| 1920 | + | |
| 1921 | + if (bMultiSliceFind && *pIdxNoInterLayerPred != iFinalIdxNoInterLayerPred) { | |
| 1922 | + *pIdxNoInterLayerPred = iFinalIdxNoInterLayerPred; | |
| 1923 | + } | |
| 1924 | +} | |
| 1925 | + | |
| 1926 | +bool CheckPocOfCurValidNalUnits (PAccessUnit pCurAu, int32_t pIdxNoInterLayerPred) { | |
| 1927 | + int32_t iEndIdx = pCurAu->uiEndPos; | |
| 1928 | + int32_t iCurAuPoc = | |
| 1929 | + pCurAu->pNalUnitsList[pIdxNoInterLayerPred]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1930 | + int32_t iTmpPoc, i; | |
| 1931 | + for (i = pIdxNoInterLayerPred + 1; i < iEndIdx; i++) { | |
| 1932 | + iTmpPoc = pCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iPicOrderCntLsb; | |
| 1933 | + if (iTmpPoc != iCurAuPoc) { | |
| 1934 | + return false; | |
| 1935 | + } | |
| 1936 | + } | |
| 1937 | + | |
| 1938 | + return true; | |
| 1939 | +} | |
| 1940 | + | |
| 1941 | +bool CheckIntegrityNalUnitsList (PWelsDecoderContext pCtx) { | |
| 1942 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 1943 | + const int32_t kiEndPos = pCurAu->uiEndPos; | |
| 1944 | + int32_t iIdxNoInterLayerPred = 0; | |
| 1945 | + | |
| 1946 | + if (!pCurAu->bCompletedAuFlag) | |
| 1947 | + return false; | |
| 1948 | + | |
| 1949 | + if (pCtx->bNewSeqBegin) { | |
| 1950 | + pCurAu->uiStartPos = 0; | |
| 1951 | + //step1: search the pNalUnit whose iNoInterLayerPredFlag equal to 1 backwards (from uiEndPos to 0) | |
| 1952 | + iIdxNoInterLayerPred = kiEndPos; | |
| 1953 | + while (iIdxNoInterLayerPred >= 0) { | |
| 1954 | + if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 1955 | + break; | |
| 1956 | + } | |
| 1957 | + --iIdxNoInterLayerPred; | |
| 1958 | + } | |
| 1959 | + if (iIdxNoInterLayerPred < 0) { | |
| 1960 | + //can not find the Nal Unit whose no_inter_pred_falg equal to 1, MUST STOP decode | |
| 1961 | + return false; | |
| 1962 | + } | |
| 1963 | + | |
| 1964 | + //step2: support multi-slice, to include all base layer slice | |
| 1965 | + RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 1966 | + pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 1967 | + CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); | |
| 1968 | + | |
| 1969 | + if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 1970 | + return false; | |
| 1971 | + } | |
| 1972 | + | |
| 1973 | + pCtx->iCurSeqIntervalTargetDependId = pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalHeaderExt.uiDependencyId; | |
| 1974 | + pCtx->iCurSeqIntervalMaxPicWidth = | |
| 1975 | + pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbWidth << 4; | |
| 1976 | + pCtx->iCurSeqIntervalMaxPicHeight = | |
| 1977 | + pCurAu->pNalUnitsList[pCurAu->uiEndPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.iMbHeight << 4; | |
| 1978 | + } else { //P_SLICE | |
| 1979 | + //step 1: search uiDependencyId equal to pCtx->cur_seq_interval_target_dependency_id | |
| 1980 | + bool bGetDependId = false; | |
| 1981 | + int32_t iIdxDependId = 0; | |
| 1982 | + | |
| 1983 | + iIdxDependId = kiEndPos; | |
| 1984 | + while (iIdxDependId >= 0) { | |
| 1985 | + if (pCtx->iCurSeqIntervalTargetDependId == pCurAu->pNalUnitsList[iIdxDependId]->sNalHeaderExt.uiDependencyId) { | |
| 1986 | + bGetDependId = true; | |
| 1987 | + break; | |
| 1988 | + } else { | |
| 1989 | + --iIdxDependId; | |
| 1990 | + } | |
| 1991 | + } | |
| 1992 | + | |
| 1993 | + //step 2: switch according to whether or not find the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId | |
| 1994 | + if (bGetDependId) { //get the index of pNalUnit whose uiDependencyId equal to iCurSeqIntervalTargetDependId | |
| 1995 | + bool bGetNoInterPredFront = false; | |
| 1996 | + //step 2a: search iNoInterLayerPredFlag [0....iIdxDependId] | |
| 1997 | + iIdxNoInterLayerPred = iIdxDependId; | |
| 1998 | + while (iIdxNoInterLayerPred >= 0) { | |
| 1999 | + if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 2000 | + bGetNoInterPredFront = true; | |
| 2001 | + break; | |
| 2002 | + } | |
| 2003 | + --iIdxNoInterLayerPred; | |
| 2004 | + } | |
| 2005 | + //step 2b: switch, whether or not find the NAL unit whose no_inter_pred_flag equal to 1 among [0....iIdxDependId] | |
| 2006 | + if (bGetNoInterPredFront) { //YES | |
| 2007 | + RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 2008 | + pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 2009 | + CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, iIdxDependId); | |
| 2010 | + | |
| 2011 | + if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 2012 | + return false; | |
| 2013 | + } | |
| 2014 | + } else { //NO, should find the NAL unit whose no_inter_pred_flag equal to 1 among [iIdxDependId....uiEndPos] | |
| 2015 | + iIdxNoInterLayerPred = iIdxDependId; | |
| 2016 | + while (iIdxNoInterLayerPred <= kiEndPos) { | |
| 2017 | + if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 2018 | + break; | |
| 2019 | + } | |
| 2020 | + ++iIdxNoInterLayerPred; | |
| 2021 | + } | |
| 2022 | + | |
| 2023 | + if (iIdxNoInterLayerPred > kiEndPos) { | |
| 2024 | + return false; //cann't find the index of pNalUnit whose no_inter_pred_flag = 1 | |
| 2025 | + } | |
| 2026 | + | |
| 2027 | + RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 2028 | + pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 2029 | + CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); | |
| 2030 | + | |
| 2031 | + if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 2032 | + return false; | |
| 2033 | + } | |
| 2034 | + } | |
| 2035 | + } else { //without the index of pNalUnit, should process this AU as common case | |
| 2036 | + iIdxNoInterLayerPred = kiEndPos; | |
| 2037 | + while (iIdxNoInterLayerPred >= 0) { | |
| 2038 | + if (pCurAu->pNalUnitsList[iIdxNoInterLayerPred]->sNalHeaderExt.iNoInterLayerPredFlag) { | |
| 2039 | + break; | |
| 2040 | + } | |
| 2041 | + --iIdxNoInterLayerPred; | |
| 2042 | + } | |
| 2043 | + if (iIdxNoInterLayerPred < 0) { | |
| 2044 | + return false; //cann't find the index of pNalUnit whose iNoInterLayerPredFlag = 1 | |
| 2045 | + } | |
| 2046 | + | |
| 2047 | + RefineIdxNoInterLayerPred (pCurAu, &iIdxNoInterLayerPred); | |
| 2048 | + pCurAu->uiStartPos = iIdxNoInterLayerPred; | |
| 2049 | + CheckAvailNalUnitsListContinuity (pCtx, iIdxNoInterLayerPred, kiEndPos); | |
| 2050 | + | |
| 2051 | + if (!CheckPocOfCurValidNalUnits (pCurAu, iIdxNoInterLayerPred)) { | |
| 2052 | + return false; | |
| 2053 | + } | |
| 2054 | + } | |
| 2055 | + } | |
| 2056 | + | |
| 2057 | + return true; | |
| 2058 | +} | |
| 2059 | + | |
| 2060 | +void CheckOnlyOneLayerInAu (PWelsDecoderContext pCtx) { | |
| 2061 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2062 | + | |
| 2063 | + int32_t iEndIdx = pCurAu->uiEndPos; | |
| 2064 | + int32_t iCurIdx = pCurAu->uiStartPos; | |
| 2065 | + uint8_t uiDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; | |
| 2066 | + uint8_t uiQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; | |
| 2067 | + uint8_t uiTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; | |
| 2068 | + | |
| 2069 | + uint8_t uiCurDId, uiCurQId, uiCurTId; | |
| 2070 | + | |
| 2071 | + pCtx->bOnlyOneLayerInCurAuFlag = true; | |
| 2072 | + | |
| 2073 | + if (iEndIdx == iCurIdx) { //only one NAL in pNalUnitsList | |
| 2074 | + return; | |
| 2075 | + } | |
| 2076 | + | |
| 2077 | + ++iCurIdx; | |
| 2078 | + while (iCurIdx <= iEndIdx) { | |
| 2079 | + uiCurDId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiDependencyId; | |
| 2080 | + uiCurQId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiQualityId; | |
| 2081 | + uiCurTId = pCurAu->pNalUnitsList[iCurIdx]->sNalHeaderExt.uiTemporalId; | |
| 2082 | + | |
| 2083 | + if (uiDId != uiCurDId || uiQId != uiCurQId || uiTId != uiCurTId) { | |
| 2084 | + pCtx->bOnlyOneLayerInCurAuFlag = false; | |
| 2085 | + return; | |
| 2086 | + } | |
| 2087 | + | |
| 2088 | + ++iCurIdx; | |
| 2089 | + } | |
| 2090 | +} | |
| 2091 | + | |
| 2092 | +int32_t WelsDecodeAccessUnitStart (PWelsDecoderContext pCtx) { | |
| 2093 | + // Roll back NAL units not being belong to current access unit list for proceeded access unit | |
| 2094 | + int32_t iRet = UpdateAccessUnit (pCtx); | |
| 2095 | + if (iRet != ERR_NONE) | |
| 2096 | + return iRet; | |
| 2097 | + | |
| 2098 | + pCtx->pAccessUnitList->uiStartPos = 0; | |
| 2099 | + if (!pCtx->bAvcBasedFlag && !CheckIntegrityNalUnitsList (pCtx)) { | |
| 2100 | + pCtx->iErrorCode |= dsBitstreamError; | |
| 2101 | + return dsBitstreamError; | |
| 2102 | + } | |
| 2103 | + | |
| 2104 | + //check current AU has only one layer or not | |
| 2105 | + //If YES, can use deblocking based on AVC | |
| 2106 | + if (!pCtx->bAvcBasedFlag) { | |
| 2107 | + CheckOnlyOneLayerInAu (pCtx); | |
| 2108 | + } | |
| 2109 | + | |
| 2110 | + return ERR_NONE; | |
| 2111 | +} | |
| 2112 | + | |
| 2113 | +void WelsDecodeAccessUnitEnd (PWelsDecoderContext pCtx) { | |
| 2114 | + //save previous header info | |
| 2115 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2116 | + PNalUnit pCurNal = pCurAu->pNalUnitsList[pCurAu->uiEndPos]; | |
| 2117 | + memcpy (&pCtx->sLastNalHdrExt, &pCurNal->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); | |
| 2118 | + memcpy (&pCtx->sLastSliceHeader, | |
| 2119 | + &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader, sizeof (SSliceHeader)); | |
| 2120 | + // uninitialize context of current access unit and rbsp buffer clean | |
| 2121 | + ResetCurrentAccessUnit (pCtx); | |
| 2122 | +} | |
| 2123 | + | |
| 2124 | +/* CheckNewSeqBeginAndUpdateActiveLayerSps | |
| 2125 | + * return: | |
| 2126 | + * true - the AU to be construct is the start of new sequence; false - not | |
| 2127 | + */ | |
| 2128 | +static bool CheckNewSeqBeginAndUpdateActiveLayerSps (PWelsDecoderContext pCtx) { | |
| 2129 | + bool bNewSeq = false; | |
| 2130 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2131 | + PSps pTmpLayerSps[MAX_LAYER_NUM]; | |
| 2132 | + for (int i = 0; i < MAX_LAYER_NUM; i++) { | |
| 2133 | + pTmpLayerSps[i] = NULL; | |
| 2134 | + } | |
| 2135 | + // track the layer sps for the current au | |
| 2136 | + for (unsigned int i = pCurAu->uiStartPos; i <= pCurAu->uiEndPos; i++) { | |
| 2137 | + uint32_t uiDid = pCurAu->pNalUnitsList[i]->sNalHeaderExt.uiDependencyId; | |
| 2138 | + pTmpLayerSps[uiDid] = pCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps; | |
| 2139 | + if ((pCurAu->pNalUnitsList[i]->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR) | |
| 2140 | + || (pCurAu->pNalUnitsList[i]->sNalHeaderExt.bIdrFlag)) | |
| 2141 | + bNewSeq = true; | |
| 2142 | + } | |
| 2143 | + int iMaxActiveLayer = 0, iMaxCurrentLayer = 0; | |
| 2144 | + for (int i = MAX_LAYER_NUM - 1; i >= 0; i--) { | |
| 2145 | + if (pCtx->pActiveLayerSps[i] != NULL) { | |
| 2146 | + iMaxActiveLayer = i; | |
| 2147 | + break; | |
| 2148 | + } | |
| 2149 | + } | |
| 2150 | + for (int i = MAX_LAYER_NUM - 1; i >= 0; i--) { | |
| 2151 | + if (pTmpLayerSps[i] != NULL) { | |
| 2152 | + iMaxCurrentLayer = i; | |
| 2153 | + break; | |
| 2154 | + } | |
| 2155 | + } | |
| 2156 | + if ((iMaxCurrentLayer != iMaxActiveLayer) | |
| 2157 | + || (pTmpLayerSps[iMaxCurrentLayer] != pCtx->pActiveLayerSps[iMaxActiveLayer])) { | |
| 2158 | + bNewSeq = true; | |
| 2159 | + } | |
| 2160 | + // fill active sps if the current sps is not null while active layer is null | |
| 2161 | + if (!bNewSeq) { | |
| 2162 | + for (int i = 0; i < MAX_LAYER_NUM; i++) { | |
| 2163 | + if (pCtx->pActiveLayerSps[i] == NULL && pTmpLayerSps[i] != NULL) { | |
| 2164 | + pCtx->pActiveLayerSps[i] = pTmpLayerSps[i]; | |
| 2165 | + } | |
| 2166 | + } | |
| 2167 | + } else { | |
| 2168 | + // UpdateActiveLayerSps if new sequence start | |
| 2169 | + memcpy (&pCtx->pActiveLayerSps[0], &pTmpLayerSps[0], MAX_LAYER_NUM * sizeof (PSps)); | |
| 2170 | + } | |
| 2171 | + return bNewSeq; | |
| 2172 | +} | |
| 2173 | + | |
| 2174 | +static void WriteBackActiveParameters (PWelsDecoderContext pCtx) { | |
| 2175 | + if (pCtx->iOverwriteFlags & OVERWRITE_PPS) { | |
| 2176 | + memcpy (&pCtx->sPpsBuffer[pCtx->sPpsBuffer[MAX_PPS_COUNT].iPpsId], &pCtx->sPpsBuffer[MAX_PPS_COUNT], sizeof (SPps)); | |
| 2177 | + } | |
| 2178 | + if (pCtx->iOverwriteFlags & OVERWRITE_SPS) { | |
| 2179 | + memcpy (&pCtx->sSpsBuffer[pCtx->sSpsBuffer[MAX_SPS_COUNT].iSpsId], &pCtx->sSpsBuffer[MAX_SPS_COUNT], sizeof (SSps)); | |
| 2180 | + pCtx->bNewSeqBegin = true; | |
| 2181 | + } | |
| 2182 | + if (pCtx->iOverwriteFlags & OVERWRITE_SUBSETSPS) { | |
| 2183 | + memcpy (&pCtx->sSubsetSpsBuffer[pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT].sSps.iSpsId], | |
| 2184 | + &pCtx->sSubsetSpsBuffer[MAX_SPS_COUNT], sizeof (SSubsetSps)); | |
| 2185 | + pCtx->bNewSeqBegin = true; | |
| 2186 | + } | |
| 2187 | + pCtx->iOverwriteFlags = OVERWRITE_NONE; | |
| 2188 | +} | |
| 2189 | + | |
| 2190 | +/* | |
| 2191 | + * DecodeFinishUpdate | |
| 2192 | + * decoder finish decoding, update active parameter sets and new seq status | |
| 2193 | + * | |
| 2194 | + */ | |
| 2195 | + | |
| 2196 | +void DecodeFinishUpdate (PWelsDecoderContext pCtx) { | |
| 2197 | + pCtx->bNewSeqBegin = false; | |
| 2198 | + WriteBackActiveParameters (pCtx); | |
| 2199 | + pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || pCtx->bNextNewSeqBegin; | |
| 2200 | + pCtx->bNextNewSeqBegin = false; // reset it | |
| 2201 | + if (pCtx->bNewSeqBegin) | |
| 2202 | + ResetActiveSPSForEachLayer (pCtx); | |
| 2203 | +} | |
| 2204 | + | |
| 2205 | +/* | |
| 2206 | + * ConstructAccessUnit | |
| 2207 | + * construct an access unit for given input bitstream, maybe partial NAL Unit, one or more Units are involved to | |
| 2208 | + * joint a collective access unit. | |
| 2209 | + * parameter\ | |
| 2210 | + * buf: bitstream data buffer | |
| 2211 | + * bit_len: size in bit length of data | |
| 2212 | + * buf_len: size in byte length of data | |
| 2213 | + * coded_au: mark an Access Unit decoding finished | |
| 2214 | + * return: | |
| 2215 | + * 0 - success; otherwise returned error_no defined in error_no.h | |
| 2216 | + */ | |
| 2217 | +int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { | |
| 2218 | + int32_t iErr; | |
| 2219 | + PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
| 2220 | + pCtx->bAuReadyFlag = false; | |
| 2221 | + pCtx->bLastHasMmco5 = false; | |
| 2222 | + bool bTmpNewSeqBegin = CheckNewSeqBeginAndUpdateActiveLayerSps (pCtx); | |
| 2223 | + pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || bTmpNewSeqBegin; | |
| 2224 | + iErr = WelsDecodeAccessUnitStart (pCtx); | |
| 2225 | + GetVclNalTemporalId (pCtx); | |
| 2226 | + | |
| 2227 | + if (ERR_NONE != iErr) { | |
| 2228 | + ForceResetCurrentAccessUnit (pCtx->pAccessUnitList); | |
| 2229 | + if (!pCtx->pParam->bParseOnly) | |
| 2230 | + pDstInfo->iBufferStatus = 0; | |
| 2231 | + pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || pCtx->bNextNewSeqBegin; | |
| 2232 | + pCtx->bNextNewSeqBegin = false; // reset it | |
| 2233 | + if (pCtx->bNewSeqBegin) | |
| 2234 | + ResetActiveSPSForEachLayer (pCtx); | |
| 2235 | + return iErr; | |
| 2236 | + } | |
| 2237 | + | |
| 2238 | + pCtx->pSps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps; | |
| 2239 | + pCtx->pPps = pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pPps; | |
| 2240 | + | |
| 2241 | + //try to allocate or relocate DPB memory only when new sequence is coming. | |
| 2242 | + if (pCtx->bNewSeqBegin) { | |
| 2243 | + WelsResetRefPic (pCtx); //clear ref pPic when IDR NAL | |
| 2244 | + iErr = SyncPictureResolutionExt (pCtx, pCtx->pSps->iMbWidth, pCtx->pSps->iMbHeight); | |
| 2245 | + | |
| 2246 | + if (ERR_NONE != iErr) { | |
| 2247 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "sync picture resolution ext failed, the error is %d", iErr); | |
| 2248 | + return iErr; | |
| 2249 | + } | |
| 2250 | + } | |
| 2251 | + | |
| 2252 | + iErr = DecodeCurrentAccessUnit (pCtx, ppDst, pDstInfo); | |
| 2253 | + | |
| 2254 | + WelsDecodeAccessUnitEnd (pCtx); | |
| 2255 | + | |
| 2256 | + if (ERR_NONE != iErr) { | |
| 2257 | + WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "returned error from decoding:[0x%x]", iErr); | |
| 2258 | + return iErr; | |
| 2259 | + } | |
| 2260 | + | |
| 2261 | + return ERR_NONE; | |
| 2262 | +} | |
| 2263 | + | |
| 2264 | +static inline void InitDqLayerInfo (PDqLayer pDqLayer, PLayerInfo pLayerInfo, PNalUnit pNalUnit, PPicture pPicDec) { | |
| 2265 | + PNalUnitHeaderExt pNalHdrExt = &pNalUnit->sNalHeaderExt; | |
| 2266 | + PSliceHeaderExt pShExt = &pNalUnit->sNalData.sVclNal.sSliceHeaderExt; | |
| 2267 | + PSliceHeader pSh = &pShExt->sSliceHeader; | |
| 2268 | + const uint8_t kuiQualityId = pNalHdrExt->uiQualityId; | |
| 2269 | + | |
| 2270 | + memcpy (&pDqLayer->sLayerInfo, pLayerInfo, sizeof (SLayerInfo)); //confirmed_safe_unsafe_usage | |
| 2271 | + | |
| 2272 | + pDqLayer->pDec = pPicDec; | |
| 2273 | + pDqLayer->iMbWidth = pSh->iMbWidth; // MB width of this picture | |
| 2274 | + pDqLayer->iMbHeight = pSh->iMbHeight;// MB height of this picture | |
| 2275 | + | |
| 2276 | + pDqLayer->iSliceIdcBackup = (pSh->iFirstMbInSlice << 7) | (pNalHdrExt->uiDependencyId << 4) | (pNalHdrExt->uiQualityId); | |
| 2277 | + | |
| 2278 | + /* Common syntax elements across all slices of a DQLayer */ | |
| 2279 | + pDqLayer->uiPpsId = pLayerInfo->pPps->iPpsId; | |
| 2280 | + pDqLayer->uiDisableInterLayerDeblockingFilterIdc = pShExt->uiDisableInterLayerDeblockingFilterIdc; | |
| 2281 | + pDqLayer->iInterLayerSliceAlphaC0Offset = pShExt->iInterLayerSliceAlphaC0Offset; | |
| 2282 | + pDqLayer->iInterLayerSliceBetaOffset = pShExt->iInterLayerSliceBetaOffset; | |
| 2283 | + pDqLayer->iSliceGroupChangeCycle = pSh->iSliceGroupChangeCycle; | |
| 2284 | + pDqLayer->bStoreRefBasePicFlag = pShExt->bStoreRefBasePicFlag; | |
| 2285 | + pDqLayer->bTCoeffLevelPredFlag = pShExt->bTCoeffLevelPredFlag; | |
| 2286 | + pDqLayer->bConstrainedIntraResamplingFlag = pShExt->bConstrainedIntraResamplingFlag; | |
| 2287 | + pDqLayer->uiRefLayerDqId = pShExt->uiRefLayerDqId; | |
| 2288 | + pDqLayer->uiRefLayerChromaPhaseXPlus1Flag = pShExt->uiRefLayerChromaPhaseXPlus1Flag; | |
| 2289 | + pDqLayer->uiRefLayerChromaPhaseYPlus1 = pShExt->uiRefLayerChromaPhaseYPlus1; | |
| 2290 | + pDqLayer->bUseWeightPredictionFlag = false; | |
| 2291 | + pDqLayer->bUseWeightedBiPredIdc = false; | |
| 2292 | + //memcpy(&pDqLayer->sScaledRefLayer, &pShExt->sScaledRefLayer, sizeof(SPosOffset));//confirmed_safe_unsafe_usage | |
| 2293 | + | |
| 2294 | + if (kuiQualityId == BASE_QUALITY_ID) { | |
| 2295 | + pDqLayer->pRefPicListReordering = &pSh->pRefPicListReordering; | |
| 2296 | + pDqLayer->pRefPicMarking = &pSh->sRefMarking; | |
| 2297 | + | |
| 2298 | + pDqLayer->bUseWeightPredictionFlag = pSh->pPps->bWeightedPredFlag; | |
| 2299 | + pDqLayer->bUseWeightedBiPredIdc = pSh->pPps->uiWeightedBipredIdc != 0; | |
| 2300 | + if (pSh->pPps->bWeightedPredFlag || pSh->pPps->uiWeightedBipredIdc) { | |
| 2301 | + pDqLayer->pPredWeightTable = &pSh->sPredWeightTable; | |
| 2302 | + } | |
| 2303 | + pDqLayer->pRefPicBaseMarking = &pShExt->sRefBasePicMarking; | |
| 2304 | + } | |
| 2305 | + | |
| 2306 | + pDqLayer->uiLayerDqId = pNalHdrExt->uiLayerDqId; // dq_id of current layer | |
| 2307 | + pDqLayer->bUseRefBasePicFlag = pNalHdrExt->bUseRefBasePicFlag; | |
| 2308 | +} | |
| 2309 | + | |
| 2310 | +void WelsDqLayerDecodeStart (PWelsDecoderContext pCtx, PNalUnit pCurNal, PSps pSps, PPps pPps) { | |
| 2311 | + PSliceHeader pSh = &pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; | |
| 2312 | + | |
| 2313 | + pCtx->eSliceType = pSh->eSliceType; | |
| 2314 | + pCtx->pSliceHeader = pSh; | |
| 2315 | + pCtx->bUsedAsRef = false; | |
| 2316 | + | |
| 2317 | + pCtx->iFrameNum = pSh->iFrameNum; | |
| 2318 | + UpdateDecoderStatisticsForActiveParaset (& (pCtx->sDecoderStatistics), | |
| 2319 | + pSps, pPps); | |
| 2320 | +} | |
| 2321 | + | |
| 2322 | +int32_t InitRefPicList (PWelsDecoderContext pCtx, const uint8_t kuiNRi, int32_t iPoc) { | |
| 2323 | + int32_t iRet = ERR_NONE; | |
| 2324 | + if (pCtx->eSliceType == B_SLICE) { | |
| 2325 | + iRet = WelsInitBSliceRefList (pCtx, iPoc); | |
| 2326 | + CreateImplicitWeightTable (pCtx); | |
| 2327 | + } else | |
| 2328 | + iRet = WelsInitRefList (pCtx, iPoc); | |
| 2329 | + if ((pCtx->eSliceType != I_SLICE && pCtx->eSliceType != SI_SLICE)) { | |
| 2330 | + iRet = WelsReorderRefList (pCtx); | |
| 2331 | + } | |
| 2332 | + | |
| 2333 | + return iRet; | |
| 2334 | +} | |
| 2335 | + | |
| 2336 | +void InitCurDqLayerData (PWelsDecoderContext pCtx, PDqLayer pCurDq) { | |
| 2337 | + if (NULL != pCtx && NULL != pCurDq) { | |
| 2338 | + pCurDq->pMbType = pCtx->sMb.pMbType[0]; | |
| 2339 | + pCurDq->pSliceIdc = pCtx->sMb.pSliceIdc[0]; | |
| 2340 | + pCurDq->pMv[LIST_0] = pCtx->sMb.pMv[0][LIST_0]; | |
| 2341 | + pCurDq->pMv[LIST_1] = pCtx->sMb.pMv[0][LIST_1]; | |
| 2342 | + pCurDq->pRefIndex[LIST_0] = pCtx->sMb.pRefIndex[0][LIST_0]; | |
| 2343 | + pCurDq->pRefIndex[LIST_1] = pCtx->sMb.pRefIndex[0][LIST_1]; | |
| 2344 | + pCurDq->pDirect = pCtx->sMb.pDirect[0]; | |
| 2345 | + pCurDq->pNoSubMbPartSizeLessThan8x8Flag = pCtx->sMb.pNoSubMbPartSizeLessThan8x8Flag[0]; | |
| 2346 | + pCurDq->pTransformSize8x8Flag = pCtx->sMb.pTransformSize8x8Flag[0]; | |
| 2347 | + pCurDq->pLumaQp = pCtx->sMb.pLumaQp[0]; | |
| 2348 | + pCurDq->pChromaQp = pCtx->sMb.pChromaQp[0]; | |
| 2349 | + pCurDq->pMvd[LIST_0] = pCtx->sMb.pMvd[0][LIST_0]; | |
| 2350 | + pCurDq->pMvd[LIST_1] = pCtx->sMb.pMvd[0][LIST_1]; | |
| 2351 | + pCurDq->pCbfDc = pCtx->sMb.pCbfDc[0]; | |
| 2352 | + pCurDq->pNzc = pCtx->sMb.pNzc[0]; | |
| 2353 | + pCurDq->pNzcRs = pCtx->sMb.pNzcRs[0]; | |
| 2354 | + pCurDq->pScaledTCoeff = pCtx->sMb.pScaledTCoeff[0]; | |
| 2355 | + pCurDq->pIntraPredMode = pCtx->sMb.pIntraPredMode[0]; | |
| 2356 | + pCurDq->pIntra4x4FinalMode = pCtx->sMb.pIntra4x4FinalMode[0]; | |
| 2357 | + pCurDq->pIntraNxNAvailFlag = pCtx->sMb.pIntraNxNAvailFlag[0]; | |
| 2358 | + pCurDq->pChromaPredMode = pCtx->sMb.pChromaPredMode[0]; | |
| 2359 | + pCurDq->pCbp = pCtx->sMb.pCbp[0]; | |
| 2360 | + pCurDq->pSubMbType = pCtx->sMb.pSubMbType[0]; | |
412 more lines aren’t shown here.