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