/*! * \copy * Copyright (c) 2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * decoder_core.c: Wels decoder framework core implementation */ #include "decoder_core.h"#include "error_code.h"#include "memmgr_nal_unit.h"#include "au_parser.h"#include "decode_slice.h"#include "manage_dec_ref.h"#include "expand_pic.h"#include "decoder.h"#include "decode_mb_aux.h"#include "mem_align.h" namespace WelsDec { static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, int32_t* pDstLen, int32_t* pWidth, int32_t* pHeight, SBufferInfo* pDstInfo) { PDqLayer pCurDq = pCtx->pCurDqLayer; PPicture pPic = pCtx->pDec; const int32_t kiWidth = pCurDq->iMbWidth << 4; const int32_t kiHeight = pCurDq->iMbHeight << 4; const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight; if (pPic->iTotalNumMbRec != kiTotalNumMbInCurLayer) { WelsLog (pCtx, WELS_LOG_WARNING, "DecodeFrameConstruction():::iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d \n", pPic->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight); return -1; }#ifdef NO_WAITING_AU pPic->iTotalNumMbRec = 0;#endif if (I_SLICE == pCurDq->sLayerInfo.sSliceInLayer.eSliceType) { memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), sizeof (SPosOffset)); //confirmed_safe_unsafe_usage#ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = false;#else pCtx->bReferenceLostAtT0Flag = false; // need initialize it due I_SLICE, 6/4/2010#endif //LONG_TERM_REF WelsLog (pCtx, WELS_LOG_INFO, "DecodeFrameConstruction()::::output good I frame, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d.\n", kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, pCtx->sFrameCrop.iBottomOffset); WelsLog (pCtx, WELS_LOG_INFO, "After decoding, set_mode:[%s], eWorkMode:[%s], eBufferProperty:[%s]\n", DECODER_MODE_NAME (pCtx->iSetMode), DECODER_MODE_NAME (pCtx->iDecoderMode), OUTPUT_PROPERTY_NAME (pDstInfo->eBufferProperty)); } //////output:::normal path ppDst[0] = pPic->pData[0]; ppDst[1] = pPic->pData[1]; ppDst[2] = pPic->pData[2]; *pDstLen = pPic->iLinesize[0]; * (pDstLen + 1) = pPic->iLinesize[1]; *pWidth = kiWidth; *pHeight = kiHeight; pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420; pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; pDstInfo->eBufferProperty = BUFFER_HOST; pDstInfo->iBufferStatus = 1; return 0;} inline bool_t CheckSliceNeedReconstruct (int16_t iCurDid, int16_t iCurQid, bool_t bStoreRefBasePicFlag, uint8_t uiDidMax, uint8_t uiLayerDqId, uint8_t uiTargetDqId) { return ((iCurDid == uiDidMax) && (iCurQid == BASE_QUALITY_ID) && (bStoreRefBasePicFlag)) // store base || (uiLayerDqId == uiTargetDqId); // target layer} inline uint8_t GetTargetDqId (uint8_t uiTargetDqId, SDecodingParam* psParam) { uint8_t uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255; return WELS_MIN (uiTargetDqId, uiRequiredDqId);} inline void_t HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if (0 == pCurNal->sNalHeaderExt.uiTemporalId) { pCtx->bReferenceLostAtT0Flag = true; }#ifndef LONG_TERM_REF if (pCtx->bReferenceLostAtT0Flag) { ResetParameterSetsState (pCtx); }#endif pCtx->iErrorCode |= dsBitstreamError;} inline void_t HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) { pCtx->bReferenceLostAtT0Flag = true; }#ifndef LONG_TERM_REF if (pCtx->bReferenceLostAtT0Flag) { ResetParameterSetsState (pCtx); }#endif pCtx->iErrorCode |= dsRefLost;} inline int32_t WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) { int32_t iRet = WelsTargetSliceConstruction (pCtx); if (iRet) { HandleReferenceLostL0 (pCtx, pCurNal); } return iRet;} /* * Predeclared function routines .. */int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) { int32_t iList = 0; const ESliceType keSt = pSh->eSliceType; PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering; if (keSt == I_SLICE || keSt == SI_SLICE) return ERR_NONE; // Common syntaxs for P or B slices: list0, list1 followed if B slices used. do { pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!BsGetOneBit (pBs); if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) { int32_t iIdx = 0; do { const uint8_t kuiIdc = BsGetUe (pBs); //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)--- if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) { return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); } pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc = kuiIdc; if (kuiIdc == 3) break; if (iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT) return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); if (kuiIdc == 0 || kuiIdc == 1) { pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = BsGetUe (pBs); // uiAbsDiffPicNumMinus1 } else if (kuiIdc == 2) { pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = BsGetUe (pBs); } ++ iIdx; } while (true); } if (keSt != B_SLICE) break; ++ iList; } while (iList < LIST_A); return ERR_NONE;} int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps, const bool_t kbIdrFlag) { PRefPicMarking const kpRefMarking = &pSh->sRefMarking; if (kbIdrFlag) { kpRefMarking->bNoOutputOfPriorPicsFlag = !!BsGetOneBit (pBs); kpRefMarking->bLongTermRefFlag = !!BsGetOneBit (pBs); } else { kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!BsGetOneBit (pBs); if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) { int32_t iIdx = 0; do { const int32_t kiMmco = BsGetUe (pBs); kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kiMmco; if (kiMmco == MMCO_END) break; if (kiMmco == MMCO_SHORT2UNUSED || kiMmco == MMCO_SHORT2LONG) { kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + BsGetUe (pBs); kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & (( 1 << pSps->uiLog2MaxFrameNum) - 1); } else if (kiMmco == MMCO_LONG2UNUSED) kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = BsGetUe (pBs); if (kiMmco == MMCO_SHORT2LONG || kiMmco == MMCO_LONG) { kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = BsGetUe (pBs); } else if (kiMmco == MMCO_SET_MAX_LONG) kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + BsGetUe (pBs); ++ iIdx; } while (iIdx < MAX_MMCO_COUNT); } } return ERR_NONE;} bool_t FillDefaultSliceHeaderExt (PSliceHeaderExt pShExt, PNalUnitHeaderExt pNalExt) { if (pShExt == NULL || pNalExt == NULL) return false; if (pNalExt->iNoInterLayerPredFlag || pNalExt->uiQualityId > 0) pShExt->bBasePredWeightTableFlag = false; else pShExt->bBasePredWeightTableFlag = true; pShExt->uiRefLayerDqId = (uint8_t) - 1; pShExt->uiDisableInterLayerDeblockingFilterIdc = 0; pShExt->iInterLayerSliceAlphaC0Offset = 0; pShExt->iInterLayerSliceBetaOffset = 0; pShExt->bConstrainedIntraResamplingFlag = false; pShExt->uiRefLayerChromaPhaseXPlus1Flag = 0; pShExt->uiRefLayerChromaPhaseYPlus1 = 1; //memset(&pShExt->sScaledRefLayer, 0, sizeof(SPosOffset)); pShExt->iScaledRefLayerPicWidthInSampleLuma = pShExt->sSliceHeader.iMbWidth << 4; pShExt->iScaledRefLayerPicHeightInSampleLuma = pShExt->sSliceHeader.iMbHeight << 4; pShExt->bSliceSkipFlag = false; pShExt->bAdaptiveBaseModeFlag = false; pShExt->bDefaultBaseModeFlag = false; pShExt->bAdaptiveMotionPredFlag = false; pShExt->bDefaultMotionPredFlag = false; pShExt->bAdaptiveResidualPredFlag = false; pShExt->bDefaultResidualPredFlag = false; pShExt->bTCoeffLevelPredFlag = false; pShExt->uiScanIdxStart = 0; pShExt->uiScanIdxEnd = 15; return true;} /* * WelsInitMemory * Memory request for new introduced data * Especially for: * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache. * return: * 0 - success; otherwise returned error_no defined in error_no.h.*/int32_t WelsInitMemory (PWelsDecoderContext pCtx) { if (pCtx == NULL) { return ERR_INFO_INVALID_PTR; } if (MemInitNalList (&pCtx->pAccessUnitList, MAX_NAL_UNIT_NUM_IN_AU) != 0) return ERR_INFO_OUT_OF_MEMORY; if ((pCtx->sRawData.pHead = static_cast<uint8_t*> (WelsMalloc (MAX_ACCESS_UNIT_CAPACITY, "pCtx->sRawData->pHead"))) == NULL) { return ERR_INFO_OUT_OF_MEMORY; } pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead; pCtx->sRawData.pEnd = pCtx->sRawData.pHead + MAX_ACCESS_UNIT_CAPACITY; pCtx->uiTargetDqId = (uint8_t) - 1; pCtx->bEndOfStreamFlag = false; pCtx->iImgWidthInPixel = 0; pCtx->iImgHeightInPixel = 0; return ERR_NONE;} /* * WelsFreeMemory * Free memory introduced in WelsInitMemory at destruction of decoder. * */void_t WelsFreeMemory (PWelsDecoderContext pCtx) { if (pCtx == NULL) return; if (NULL != pCtx->pParam) { WelsFree (pCtx->pParam, "pCtx->pParam"); pCtx->pParam = NULL; } MemFreeNalList (&pCtx->pAccessUnitList); if (pCtx->sRawData.pHead) { WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData->pHead"); } pCtx->sRawData.pHead = NULL; pCtx->sRawData.pEnd = NULL; pCtx->sRawData.pStartPos = NULL; pCtx->sRawData.pCurPos = NULL;} /* * DecodeNalHeaderExt * Trigger condition: NAL_UNIT_TYPE = NAL_UNIT_PREFIX or NAL_UNIT_CODED_SLICE_EXT * Parameter: * pNal: target NALUnit ptr * pSrc: NAL Unit bitstream */void_t DecodeNalHeaderExt (PNalUnit pNal, uint8_t* pSrc) { PNalUnitHeaderExt pHeaderExt = &pNal->sNalHeaderExt; uint8_t uiCurByte = *pSrc; pHeaderExt->bIdrFlag = !! (uiCurByte & 0x40); pHeaderExt->uiPriorityId = uiCurByte & 0x3F; uiCurByte = * (++pSrc); pHeaderExt->iNoInterLayerPredFlag = uiCurByte >> 7; pHeaderExt->uiDependencyId = (uiCurByte & 0x70) >> 4; pHeaderExt->uiQualityId = uiCurByte & 0x0F; uiCurByte = * (++pSrc); pHeaderExt->uiTemporalId = uiCurByte >> 5; pHeaderExt->bUseRefBasePicFlag = !! (uiCurByte & 0x10); pHeaderExt->bDiscardableFlag = !! (uiCurByte & 0x08); pHeaderExt->bOutputFlag = !! (uiCurByte & 0x04); pHeaderExt->uiReservedThree2Bits = uiCurByte & 0x03; pHeaderExt->uiLayerDqId = (pHeaderExt->uiDependencyId << 4) | pHeaderExt->uiQualityId;} #ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_IDint32_t CheckPpsId (PWelsDecoderContext pCtx, PPps* ppPps, uint32_t uiPpsId) { PPps pPpsList = pCtx->sPpsBuffer; int32_t iPpsNum = pCtx->iPpsTotalNum; int32_t i = 0; if (iPpsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckPpsId():::::PPS list is empty...NO PPS!!!\n"); return dsNoParamSets; } while (i < iPpsNum) { if (uiPpsId == pPpsList[i].iPpsId) { *ppPps = &pPpsList[i]; break; } else { ++i; } } if (i == iPpsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckPpsId()::::::CAN NOT find the matching from the PPS List. iPpsId:%d\n", uiPpsId); return dsNoParamSets; } return 0;} int32_t CheckSpsId (PWelsDecoderContext pCtx, PSubsetSps* ppSubsetSps, PSps* ppSps, int32_t iSpsId, bool_t bExtensionFlag) { PSps pSpsList = pCtx->sSpsBuffer; PSubsetSps pSubspsList = pCtx->sSubsetSpsBuffer; int32_t iSpsNum = pCtx->iSpsTotalNum; int32_t iSubspsNum = pCtx->iSubspsTotalNum; int32_t i = 0; if (bExtensionFlag) { if (iSubspsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SUBSPS list is empty....NO SUBSPS\n"); return dsNoParamSets; } while (i < iSubspsNum) { if (iSpsId == pSubspsList[i].sSps.iSpsId) { *ppSubsetSps = &pSubspsList[i]; *ppSps = &pSubspsList[i].sSps; break; } else { ++i; } } if (i == iSubspsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SUBSPS List. iSpsId:%d\n", iSpsId); return dsNoParamSets; } } else { if (iSpsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SPS list is empty....NO SPS\n"); return dsNoParamSets; } while (i < iSpsNum) { if (iSpsId == pSpsList[i].iSpsId) { *ppSubsetSps = NULL; *ppSps = &pSpsList[i]; break; } else { ++i; } } if (i == iSpsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SPS List. iSpsId:%d\n", iSpsId); return dsNoParamSets; } } return 0;} #endif/* * decode_slice_header_avc * Parse slice header of bitstream in avc for storing data structure */int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, const bool_t kbExtensionFlag) { PNalUnit const kpCurNal = pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiAvailUnitsNum - 1]; PNalUnitHeaderExt pNalHeaderExt = NULL; PSliceHeader pSliceHead = NULL; PSliceHeaderExt pSliceHeadExt = NULL; PSubsetSps pSubsetSps = NULL; PSps pSps = NULL; PPps pPps = NULL; ENalUnitType eNalType = static_cast<ENalUnitType> (0); int32_t iPpsId = 0; int32_t iRet = ERR_NONE; uint8_t uiSliceType = 0; uint8_t uiQualityId = BASE_QUALITY_ID; bool_t bIdrFlag = false; bool_t bSgChangeCycleInvolved = false; // involved slice group change cycle ? if (kpCurNal == NULL) { return ERR_INFO_OUT_OF_MEMORY; } pNalHeaderExt = &kpCurNal->sNalHeaderExt; pSliceHead = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; eNalType = pNalHeaderExt->sNalUnitHeader.eNalUnitType; pSliceHeadExt = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt; if (pSliceHeadExt) { SRefBasePicMarking sBaseMarking; const bool_t kbStoreRefBaseFlag = pSliceHeadExt->bStoreRefBasePicFlag; memcpy (&sBaseMarking, &pSliceHeadExt->sRefBasePicMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage memset (pSliceHeadExt, 0, sizeof (SSliceHeaderExt)); pSliceHeadExt->bStoreRefBasePicFlag = kbStoreRefBaseFlag; memcpy (&pSliceHeadExt->sRefBasePicMarking, &sBaseMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage } kpCurNal->sNalData.sVclNal.bSliceHeaderExtFlag = kbExtensionFlag; pSliceHead->iFirstMbInSlice = BsGetUe (pBs); uiSliceType = BsGetUe (pBs); if (uiSliceType > 9) { WelsLog (pCtx, WELS_LOG_WARNING, "slice type too large (%d) at first_mb(%d)\n", uiSliceType,Lines 1–500 of 1942. Load more
/*! * \copy * Copyright (c) 2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * decoder_core.c: Wels decoder framework core implementation */ #include "decoder_core.h" #include "error_code.h" #include "memmgr_nal_unit.h" #include "au_parser.h" #include "decode_slice.h" #include "manage_dec_ref.h" #include "expand_pic.h" #include "decoder.h" #include "decode_mb_aux.h" #include "mem_align.h" namespace WelsDec { static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, int32_t* pDstLen, int32_t* pWidth, int32_t* pHeight, SBufferInfo* pDstInfo) { PDqLayer pCurDq = pCtx->pCurDqLayer; PPicture pPic = pCtx->pDec; const int32_t kiWidth = pCurDq->iMbWidth << 4; const int32_t kiHeight = pCurDq->iMbHeight << 4; const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight; if (pPic->iTotalNumMbRec != kiTotalNumMbInCurLayer) { WelsLog (pCtx, WELS_LOG_WARNING, "DecodeFrameConstruction():::iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d \n", pPic->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight); return -1; } #ifdef NO_WAITING_AU pPic->iTotalNumMbRec = 0; #endif if (I_SLICE == pCurDq->sLayerInfo.sSliceInLayer.eSliceType) { memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), sizeof (SPosOffset)); //confirmed_safe_unsafe_usage #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = false; #else pCtx->bReferenceLostAtT0Flag = false; // need initialize it due I_SLICE, 6/4/2010 #endif //LONG_TERM_REF WelsLog (pCtx, WELS_LOG_INFO, "DecodeFrameConstruction()::::output good I frame, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d.\n", kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset, pCtx->sFrameCrop.iBottomOffset); WelsLog (pCtx, WELS_LOG_INFO, "After decoding, set_mode:[%s], eWorkMode:[%s], eBufferProperty:[%s]\n", DECODER_MODE_NAME (pCtx->iSetMode), DECODER_MODE_NAME (pCtx->iDecoderMode), OUTPUT_PROPERTY_NAME (pDstInfo->eBufferProperty)); } //////output:::normal path ppDst[0] = pPic->pData[0]; ppDst[1] = pPic->pData[1]; ppDst[2] = pPic->pData[2]; *pDstLen = pPic->iLinesize[0]; * (pDstLen + 1) = pPic->iLinesize[1]; *pWidth = kiWidth; *pHeight = kiHeight; pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420; pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2; pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0]; pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1]; ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2; ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset; pDstInfo->eBufferProperty = BUFFER_HOST; pDstInfo->iBufferStatus = 1; return 0; } inline bool_t CheckSliceNeedReconstruct (int16_t iCurDid, int16_t iCurQid, bool_t bStoreRefBasePicFlag, uint8_t uiDidMax, uint8_t uiLayerDqId, uint8_t uiTargetDqId) { return ((iCurDid == uiDidMax) && (iCurQid == BASE_QUALITY_ID) && (bStoreRefBasePicFlag)) // store base || (uiLayerDqId == uiTargetDqId); // target layer } inline uint8_t GetTargetDqId (uint8_t uiTargetDqId, SDecodingParam* psParam) { uint8_t uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255; return WELS_MIN (uiTargetDqId, uiRequiredDqId); } inline void_t HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if (0 == pCurNal->sNalHeaderExt.uiTemporalId) { pCtx->bReferenceLostAtT0Flag = true; } #ifndef LONG_TERM_REF if (pCtx->bReferenceLostAtT0Flag) { ResetParameterSetsState (pCtx); } #endif pCtx->iErrorCode |= dsBitstreamError; } inline void_t HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) { if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) { pCtx->bReferenceLostAtT0Flag = true; } #ifndef LONG_TERM_REF if (pCtx->bReferenceLostAtT0Flag) { ResetParameterSetsState (pCtx); } #endif pCtx->iErrorCode |= dsRefLost; } inline int32_t WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) { int32_t iRet = WelsTargetSliceConstruction (pCtx); if (iRet) { HandleReferenceLostL0 (pCtx, pCurNal); } return iRet; } /* * Predeclared function routines .. */ int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) { int32_t iList = 0; const ESliceType keSt = pSh->eSliceType; PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering; if (keSt == I_SLICE || keSt == SI_SLICE) return ERR_NONE; // Common syntaxs for P or B slices: list0, list1 followed if B slices used. do { pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!BsGetOneBit (pBs); if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) { int32_t iIdx = 0; do { const uint8_t kuiIdc = BsGetUe (pBs); //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)--- if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) { return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); } pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc = kuiIdc; if (kuiIdc == 3) break; if (iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT) return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING); if (kuiIdc == 0 || kuiIdc == 1) { pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = BsGetUe (pBs); // uiAbsDiffPicNumMinus1 } else if (kuiIdc == 2) { pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = BsGetUe (pBs); } ++ iIdx; } while (true); } if (keSt != B_SLICE) break; ++ iList; } while (iList < LIST_A); return ERR_NONE; } int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps, const bool_t kbIdrFlag) { PRefPicMarking const kpRefMarking = &pSh->sRefMarking; if (kbIdrFlag) { kpRefMarking->bNoOutputOfPriorPicsFlag = !!BsGetOneBit (pBs); kpRefMarking->bLongTermRefFlag = !!BsGetOneBit (pBs); } else { kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!BsGetOneBit (pBs); if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) { int32_t iIdx = 0; do { const int32_t kiMmco = BsGetUe (pBs); kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kiMmco; if (kiMmco == MMCO_END) break; if (kiMmco == MMCO_SHORT2UNUSED || kiMmco == MMCO_SHORT2LONG) { kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + BsGetUe (pBs); kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & (( 1 << pSps->uiLog2MaxFrameNum) - 1); } else if (kiMmco == MMCO_LONG2UNUSED) kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = BsGetUe (pBs); if (kiMmco == MMCO_SHORT2LONG || kiMmco == MMCO_LONG) { kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = BsGetUe (pBs); } else if (kiMmco == MMCO_SET_MAX_LONG) kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + BsGetUe (pBs); ++ iIdx; } while (iIdx < MAX_MMCO_COUNT); } } return ERR_NONE; } bool_t FillDefaultSliceHeaderExt (PSliceHeaderExt pShExt, PNalUnitHeaderExt pNalExt) { if (pShExt == NULL || pNalExt == NULL) return false; if (pNalExt->iNoInterLayerPredFlag || pNalExt->uiQualityId > 0) pShExt->bBasePredWeightTableFlag = false; else pShExt->bBasePredWeightTableFlag = true; pShExt->uiRefLayerDqId = (uint8_t) - 1; pShExt->uiDisableInterLayerDeblockingFilterIdc = 0; pShExt->iInterLayerSliceAlphaC0Offset = 0; pShExt->iInterLayerSliceBetaOffset = 0; pShExt->bConstrainedIntraResamplingFlag = false; pShExt->uiRefLayerChromaPhaseXPlus1Flag = 0; pShExt->uiRefLayerChromaPhaseYPlus1 = 1; //memset(&pShExt->sScaledRefLayer, 0, sizeof(SPosOffset)); pShExt->iScaledRefLayerPicWidthInSampleLuma = pShExt->sSliceHeader.iMbWidth << 4; pShExt->iScaledRefLayerPicHeightInSampleLuma = pShExt->sSliceHeader.iMbHeight << 4; pShExt->bSliceSkipFlag = false; pShExt->bAdaptiveBaseModeFlag = false; pShExt->bDefaultBaseModeFlag = false; pShExt->bAdaptiveMotionPredFlag = false; pShExt->bDefaultMotionPredFlag = false; pShExt->bAdaptiveResidualPredFlag = false; pShExt->bDefaultResidualPredFlag = false; pShExt->bTCoeffLevelPredFlag = false; pShExt->uiScanIdxStart = 0; pShExt->uiScanIdxEnd = 15; return true; } /* * WelsInitMemory * Memory request for new introduced data * Especially for: * rbsp_au_buffer, cur_dq_layer_ptr and ref_dq_layer_ptr in MB info cache. * return: * 0 - success; otherwise returned error_no defined in error_no.h. */ int32_t WelsInitMemory (PWelsDecoderContext pCtx) { if (pCtx == NULL) { return ERR_INFO_INVALID_PTR; } if (MemInitNalList (&pCtx->pAccessUnitList, MAX_NAL_UNIT_NUM_IN_AU) != 0) return ERR_INFO_OUT_OF_MEMORY; if ((pCtx->sRawData.pHead = static_cast<uint8_t*> (WelsMalloc (MAX_ACCESS_UNIT_CAPACITY, "pCtx->sRawData->pHead"))) == NULL) { return ERR_INFO_OUT_OF_MEMORY; } pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead; pCtx->sRawData.pEnd = pCtx->sRawData.pHead + MAX_ACCESS_UNIT_CAPACITY; pCtx->uiTargetDqId = (uint8_t) - 1; pCtx->bEndOfStreamFlag = false; pCtx->iImgWidthInPixel = 0; pCtx->iImgHeightInPixel = 0; return ERR_NONE; } /* * WelsFreeMemory * Free memory introduced in WelsInitMemory at destruction of decoder. * */ void_t WelsFreeMemory (PWelsDecoderContext pCtx) { if (pCtx == NULL) return; if (NULL != pCtx->pParam) { WelsFree (pCtx->pParam, "pCtx->pParam"); pCtx->pParam = NULL; } MemFreeNalList (&pCtx->pAccessUnitList); if (pCtx->sRawData.pHead) { WelsFree (pCtx->sRawData.pHead, "pCtx->sRawData->pHead"); } pCtx->sRawData.pHead = NULL; pCtx->sRawData.pEnd = NULL; pCtx->sRawData.pStartPos = NULL; pCtx->sRawData.pCurPos = NULL; } /* * DecodeNalHeaderExt * Trigger condition: NAL_UNIT_TYPE = NAL_UNIT_PREFIX or NAL_UNIT_CODED_SLICE_EXT * Parameter: * pNal: target NALUnit ptr * pSrc: NAL Unit bitstream */ void_t DecodeNalHeaderExt (PNalUnit pNal, uint8_t* pSrc) { PNalUnitHeaderExt pHeaderExt = &pNal->sNalHeaderExt; uint8_t uiCurByte = *pSrc; pHeaderExt->bIdrFlag = !! (uiCurByte & 0x40); pHeaderExt->uiPriorityId = uiCurByte & 0x3F; uiCurByte = * (++pSrc); pHeaderExt->iNoInterLayerPredFlag = uiCurByte >> 7; pHeaderExt->uiDependencyId = (uiCurByte & 0x70) >> 4; pHeaderExt->uiQualityId = uiCurByte & 0x0F; uiCurByte = * (++pSrc); pHeaderExt->uiTemporalId = uiCurByte >> 5; pHeaderExt->bUseRefBasePicFlag = !! (uiCurByte & 0x10); pHeaderExt->bDiscardableFlag = !! (uiCurByte & 0x08); pHeaderExt->bOutputFlag = !! (uiCurByte & 0x04); pHeaderExt->uiReservedThree2Bits = uiCurByte & 0x03; pHeaderExt->uiLayerDqId = (pHeaderExt->uiDependencyId << 4) | pHeaderExt->uiQualityId; } #ifdef MOSAIC_AVOID_BASED_ON_SPS_PPS_ID int32_t CheckPpsId (PWelsDecoderContext pCtx, PPps* ppPps, uint32_t uiPpsId) { PPps pPpsList = pCtx->sPpsBuffer; int32_t iPpsNum = pCtx->iPpsTotalNum; int32_t i = 0; if (iPpsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckPpsId():::::PPS list is empty...NO PPS!!!\n"); return dsNoParamSets; } while (i < iPpsNum) { if (uiPpsId == pPpsList[i].iPpsId) { *ppPps = &pPpsList[i]; break; } else { ++i; } } if (i == iPpsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckPpsId()::::::CAN NOT find the matching from the PPS List. iPpsId:%d\n", uiPpsId); return dsNoParamSets; } return 0; } int32_t CheckSpsId (PWelsDecoderContext pCtx, PSubsetSps* ppSubsetSps, PSps* ppSps, int32_t iSpsId, bool_t bExtensionFlag) { PSps pSpsList = pCtx->sSpsBuffer; PSubsetSps pSubspsList = pCtx->sSubsetSpsBuffer; int32_t iSpsNum = pCtx->iSpsTotalNum; int32_t iSubspsNum = pCtx->iSubspsTotalNum; int32_t i = 0; if (bExtensionFlag) { if (iSubspsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SUBSPS list is empty....NO SUBSPS\n"); return dsNoParamSets; } while (i < iSubspsNum) { if (iSpsId == pSubspsList[i].sSps.iSpsId) { *ppSubsetSps = &pSubspsList[i]; *ppSps = &pSubspsList[i].sSps; break; } else { ++i; } } if (i == iSubspsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SUBSPS List. iSpsId:%d\n", iSpsId); return dsNoParamSets; } } else { if (iSpsNum <= 0) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::SPS list is empty....NO SPS\n"); return dsNoParamSets; } while (i < iSpsNum) { if (iSpsId == pSpsList[i].iSpsId) { *ppSubsetSps = NULL; *ppSps = &pSpsList[i]; break; } else { ++i; } } if (i == iSpsNum) { pCtx->iErrorCode |= dsNoParamSets; WelsLog (pCtx, WELS_LOG_WARNING, "CheckSpsId()::::::CAN NOT find the matching from the SPS List. iSpsId:%d\n", iSpsId); return dsNoParamSets; } } return 0; } #endif /* * decode_slice_header_avc * Parse slice header of bitstream in avc for storing data structure */ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, const bool_t kbExtensionFlag) { PNalUnit const kpCurNal = pCtx->pAccessUnitList->pNalUnitsList[pCtx->pAccessUnitList->uiAvailUnitsNum - 1]; PNalUnitHeaderExt pNalHeaderExt = NULL; PSliceHeader pSliceHead = NULL; PSliceHeaderExt pSliceHeadExt = NULL; PSubsetSps pSubsetSps = NULL; PSps pSps = NULL; PPps pPps = NULL; ENalUnitType eNalType = static_cast<ENalUnitType> (0); int32_t iPpsId = 0; int32_t iRet = ERR_NONE; uint8_t uiSliceType = 0; uint8_t uiQualityId = BASE_QUALITY_ID; bool_t bIdrFlag = false; bool_t bSgChangeCycleInvolved = false; // involved slice group change cycle ? if (kpCurNal == NULL) { return ERR_INFO_OUT_OF_MEMORY; } pNalHeaderExt = &kpCurNal->sNalHeaderExt; pSliceHead = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; eNalType = pNalHeaderExt->sNalUnitHeader.eNalUnitType; pSliceHeadExt = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt; if (pSliceHeadExt) { SRefBasePicMarking sBaseMarking; const bool_t kbStoreRefBaseFlag = pSliceHeadExt->bStoreRefBasePicFlag; memcpy (&sBaseMarking, &pSliceHeadExt->sRefBasePicMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage memset (pSliceHeadExt, 0, sizeof (SSliceHeaderExt)); pSliceHeadExt->bStoreRefBasePicFlag = kbStoreRefBaseFlag; memcpy (&pSliceHeadExt->sRefBasePicMarking, &sBaseMarking, sizeof (SRefBasePicMarking)); //confirmed_safe_unsafe_usage } kpCurNal->sNalData.sVclNal.bSliceHeaderExtFlag = kbExtensionFlag; pSliceHead->iFirstMbInSlice = BsGetUe (pBs); uiSliceType = BsGetUe (pBs); if (uiSliceType > 9) { WelsLog (pCtx, WELS_LOG_WARNING, "slice type too large (%d) at first_mb(%d)\n", uiSliceType,