-
-
Save Megawats777/9d4fc3757739c475936b5e3c6c3d12d8 to your computer and use it in GitHub Desktop.
DecodeCurrentAccessUnit-02
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* DecodeCurrentAccessUnit | |
* Decode current access unit when current AU is completed. | |
*/ | |
int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) { | |
PNalUnit pNalCur = pCtx->pNalCur = NULL; | |
PAccessUnit pCurAu = pCtx->pAccessUnitList; | |
int32_t iIdx = pCurAu->uiStartPos; | |
int32_t iEndIdx = pCurAu->uiEndPos; | |
//get current thread ctx | |
PWelsDecoderThreadCTX pThreadCtx = NULL; | |
if (pCtx->pThreadCtx != NULL) { | |
pThreadCtx = (PWelsDecoderThreadCTX)pCtx->pThreadCtx; | |
} | |
//get last thread ctx | |
PWelsDecoderThreadCTX pLastThreadCtx = NULL; | |
if (pCtx->pLastThreadCtx != NULL) { | |
pLastThreadCtx = (PWelsDecoderThreadCTX) (pCtx->pLastThreadCtx); | |
if (pLastThreadCtx->pDec == NULL) { | |
pLastThreadCtx->pDec = PrefetchLastPicForThread (pCtx->pPicBuff, | |
pLastThreadCtx->iPicBuffIdx); | |
} | |
} | |
int32_t iThreadCount = GetThreadCount (pCtx); | |
int32_t iPpsId = 0; | |
int32_t iRet = ERR_NONE; | |
bool bAllRefComplete = true; // Assume default all ref picutres are complete | |
const uint8_t kuiTargetLayerDqId = GetTargetDqId (pCtx->uiTargetDqId, pCtx->pParam); | |
const uint8_t kuiDependencyIdMax = (kuiTargetLayerDqId & 0x7F) >> 4; | |
int16_t iLastIdD = -1, iLastIdQ = -1; | |
int16_t iCurrIdD = 0, iCurrIdQ = 0; | |
pCtx->uiNalRefIdc = 0; | |
bool bFreshSliceAvailable = | |
true; // Another fresh slice comingup for given dq layer, for multiple slices in case of header parts of slices sometimes loss over error-prone channels, 8/14/2008 | |
//update pCurDqLayer at the starting of AU decoding | |
if (pCtx->bInitialDqLayersMem || pCtx->pCurDqLayer == NULL) { | |
pCtx->pCurDqLayer = pCtx->pDqLayersList[0]; | |
} | |
InitCurDqLayerData (pCtx, pCtx->pCurDqLayer); | |
pNalCur = pCurAu->pNalUnitsList[iIdx]; | |
while (iIdx <= iEndIdx) { | |
PDqLayer dq_cur = pCtx->pCurDqLayer; | |
SLayerInfo pLayerInfo; | |
PSliceHeaderExt pShExt = NULL; | |
PSliceHeader pSh = NULL; | |
if (pLastThreadCtx != NULL) { | |
pSh = &pNalCur->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; | |
if (pSh->iFirstMbInSlice == 0) { | |
if (pLastThreadCtx->pCtx->pDec != NULL && pLastThreadCtx->pCtx->pDec->bIsUngroupedMultiSlice) { | |
WAIT_EVENT (&pLastThreadCtx->sSliceDecodeFinish, WELS_DEC_THREAD_WAIT_INFINITE); | |
} | |
pCtx->pDec = NULL; | |
pCtx->iTotalNumMbRec = 0; | |
} else if (pLastThreadCtx->pCtx->pDec != NULL) { | |
if (pSh->iFrameNum == pLastThreadCtx->pCtx->pDec->iFrameNum | |
&& pSh->iPicOrderCntLsb == pLastThreadCtx->pCtx->pDec->iFramePoc) { | |
WAIT_EVENT (&pLastThreadCtx->sSliceDecodeFinish, WELS_DEC_THREAD_WAIT_INFINITE); | |
pCtx->pDec = pLastThreadCtx->pCtx->pDec; | |
pCtx->pDec->bIsUngroupedMultiSlice = true; | |
pCtx->sRefPic = pLastThreadCtx->pCtx->sRefPic; | |
pCtx->iTotalNumMbRec = pLastThreadCtx->pCtx->iTotalNumMbRec; | |
} | |
} | |
} | |
bool isNewFrame = true; | |
if (iThreadCount > 1) { | |
isNewFrame = pCtx->pDec == NULL; | |
} | |
if (pCtx->pDec == NULL) { | |
if (pLastThreadCtx != NULL) { | |
pLastThreadCtx->pDec->bUsedAsRef = pLastThreadCtx->pCtx->uiNalRefIdc > 0; | |
if (pLastThreadCtx->pDec->bUsedAsRef) { | |
for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) { | |
uint32_t i = 0; | |
while (i < MAX_DPB_COUNT && pLastThreadCtx->pCtx->sRefPic.pRefList[listIdx][i]) { | |
pLastThreadCtx->pDec->pRefPic[listIdx][i] = pLastThreadCtx->pCtx->sRefPic.pRefList[listIdx][i]; | |
++i; | |
} | |
} | |
pLastThreadCtx->pCtx->sTmpRefPic = pLastThreadCtx->pCtx->sRefPic; | |
WelsMarkAsRef (pLastThreadCtx->pCtx, pLastThreadCtx->pDec); | |
pCtx->sRefPic = pLastThreadCtx->pCtx->sTmpRefPic; | |
} else { | |
pCtx->sRefPic = pLastThreadCtx->pCtx->sRefPic; | |
} | |
} | |
pCtx->pDec = PrefetchPic (pCtx->pPicBuff); | |
if (pCtx->iTotalNumMbRec != 0) | |
pCtx->iTotalNumMbRec = 0; | |
if (NULL == pCtx->pDec) { | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, | |
"DecodeCurrentAccessUnit()::::::PrefetchPic ERROR, pSps->iNumRefFrames:%d.", | |
pCtx->pSps->iNumRefFrames); | |
// The error code here need to be separated from the dsOutOfMemory | |
pCtx->iErrorCode |= dsOutOfMemory; | |
return ERR_INFO_REF_COUNT_OVERFLOW; | |
} | |
if (pThreadCtx != NULL) { | |
pCtx->pDec->bIsUngroupedMultiSlice = false; | |
pThreadCtx->pDec = pCtx->pDec; | |
if (iThreadCount > 1) ++pCtx->pDec->iRefCount; | |
uint32_t uiMbHeight = (pCtx->pDec->iHeightInPixel + 15) >> 4; | |
for (uint32_t i = 0; i < uiMbHeight; ++i) { | |
RESET_EVENT (&pCtx->pDec->pReadyEvent[i]); | |
} | |
} | |
pCtx->pDec->bNewSeqBegin = pCtx->bNewSeqBegin; //set flag for start decoding | |
} else if (pCtx->iTotalNumMbRec == 0) { //pDec != NULL, already start | |
pCtx->pDec->bNewSeqBegin = pCtx->bNewSeqBegin; //set flag for start decoding | |
} | |
pCtx->pDec->uiTimeStamp = pNalCur->uiTimeStamp; | |
pCtx->pDec->uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp; | |
if (pThreadCtx != NULL) { | |
pThreadCtx->iPicBuffIdx = pCtx->pDec->iPicBuffIdx; | |
pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag = pCtx->pDec->pMbCorrectlyDecodedFlag; | |
} | |
if (pCtx->iTotalNumMbRec == 0) { //Picture start to decode | |
for (int32_t i = 0; i < LAYER_NUM_EXCHANGEABLE; ++ i) | |
memset (pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t))); | |
memset (pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag, 0, pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight * sizeof (bool)); | |
memset (pCtx->pCurDqLayer->pMbRefConcealedFlag, 0, pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight * sizeof (bool)); | |
memset (pCtx->pDec->pRefPic[LIST_0], 0, sizeof (PPicture) * MAX_DPB_COUNT); | |
memset (pCtx->pDec->pRefPic[LIST_1], 0, sizeof (PPicture) * MAX_DPB_COUNT); | |
pCtx->pDec->iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight; | |
pCtx->pDec->iMbEcedNum = 0; | |
pCtx->pDec->iMbEcedPropNum = 0; | |
} | |
pCtx->bRPLRError = false; | |
GetI4LumaIChromaAddrTable (pCtx->iDecBlockOffsetArray, pCtx->pDec->iLinesize[0], pCtx->pDec->iLinesize[1]); | |
if (pNalCur->sNalHeaderExt.uiLayerDqId > kuiTargetLayerDqId) { // confirmed pNalCur will never be NULL | |
break; // Per formance it need not to decode the remaining bits any more due to given uiLayerDqId required, 9/2/2009 | |
} | |
memset (&pLayerInfo, 0, sizeof (SLayerInfo)); | |
/* | |
* Loop decoding for slices (even FMO and/ multiple slices) within a dq layer | |
*/ | |
while (iIdx <= iEndIdx) { | |
bool bReconstructSlice; | |
iCurrIdQ = pNalCur->sNalHeaderExt.uiQualityId; | |
iCurrIdD = pNalCur->sNalHeaderExt.uiDependencyId; | |
pSh = &pNalCur->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader; | |
pShExt = &pNalCur->sNalData.sVclNal.sSliceHeaderExt; | |
pCtx->bRPLRError = false; | |
bReconstructSlice = CheckSliceNeedReconstruct (pNalCur->sNalHeaderExt.uiLayerDqId, kuiTargetLayerDqId); | |
memcpy (&pLayerInfo.sNalHeaderExt, &pNalCur->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); //confirmed_safe_unsafe_usage | |
pCtx->pDec->iFrameNum = pSh->iFrameNum; | |
pCtx->pDec->iFramePoc = pSh->iPicOrderCntLsb; // still can not obtain correct, because current do not support POCtype 2 | |
pCtx->pDec->bIdrFlag = pNalCur->sNalHeaderExt.bIdrFlag; | |
pCtx->pDec->eSliceType = pSh->eSliceType; | |
memcpy (&pLayerInfo.sSliceInLayer.sSliceHeaderExt, pShExt, sizeof (SSliceHeaderExt)); //confirmed_safe_unsafe_usage | |
pLayerInfo.sSliceInLayer.bSliceHeaderExtFlag = pNalCur->sNalData.sVclNal.bSliceHeaderExtFlag; | |
pLayerInfo.sSliceInLayer.eSliceType = pSh->eSliceType; | |
pLayerInfo.sSliceInLayer.iLastMbQp = pSh->iSliceQp; | |
dq_cur->pBitStringAux = &pNalCur->sNalData.sVclNal.sSliceBitsRead; | |
pCtx->uiNalRefIdc = pNalCur->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc; | |
iPpsId = pSh->iPpsId; | |
pLayerInfo.pPps = pSh->pPps; | |
pLayerInfo.pSps = pSh->pSps; | |
pLayerInfo.pSubsetSps = pShExt->pSubsetSps; | |
pCtx->pFmo = &pCtx->sFmoList[iPpsId]; | |
iRet = FmoParamUpdate (pCtx->pFmo, pLayerInfo.pSps, pLayerInfo.pPps, &pCtx->iActiveFmoNum, pCtx->pMemAlign); | |
if (ERR_NONE != iRet) { | |
if (iRet == ERR_INFO_OUT_OF_MEMORY) { | |
pCtx->iErrorCode |= dsOutOfMemory; | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "DecodeCurrentAccessUnit(), Fmo param alloc failed"); | |
} else { | |
pCtx->iErrorCode |= dsBitstreamError; | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "DecodeCurrentAccessUnit(), FmoParamUpdate failed, eSliceType: %d.", | |
pSh->eSliceType); | |
} | |
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_FMO_INIT_FAIL); | |
} | |
bFreshSliceAvailable = (iCurrIdD != iLastIdD | |
|| iCurrIdQ != iLastIdQ); // do not need condition of (first_mb == 0) due multiple slices might be disorder | |
WelsDqLayerDecodeStart (pCtx, pNalCur, pLayerInfo.pSps, pLayerInfo.pPps); | |
if ((iLastIdD < 0) || //case 1: first layer | |
(iLastIdD == iCurrIdD)) { //case 2: same uiDId | |
InitDqLayerInfo (dq_cur, &pLayerInfo, pNalCur, pCtx->pDec); | |
if (!dq_cur->sLayerInfo.pSps->bGapsInFrameNumValueAllowedFlag) { | |
const bool kbIdrFlag = dq_cur->sLayerInfo.sNalHeaderExt.bIdrFlag | |
|| (dq_cur->sLayerInfo.sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR); | |
// Subclause 8.2.5.2 Decoding process for gaps in frame_num | |
int32_t iPrevFrameNum = pCtx->pLastDecPicInfo->iPrevFrameNum; | |
if (pLastThreadCtx != NULL) { | |
if (pCtx->bNewSeqBegin) { | |
iPrevFrameNum = 0; | |
} else if (pLastThreadCtx->pDec != NULL) { | |
iPrevFrameNum = pLastThreadCtx->pDec->iFrameNum; | |
} else { | |
iPrevFrameNum = pCtx->bNewSeqBegin ? 0 : pLastThreadCtx->pCtx->iFrameNum; | |
} | |
} | |
if (!kbIdrFlag && | |
pSh->iFrameNum != iPrevFrameNum && | |
pSh->iFrameNum != ((iPrevFrameNum + 1) & ((1 << dq_cur->sLayerInfo.pSps->uiLog2MaxFrameNum) - | |
1))) { | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, | |
"referencing pictures lost due frame gaps exist, prev_frame_num: %d, curr_frame_num: %d", | |
iPrevFrameNum, | |
pSh->iFrameNum); | |
bAllRefComplete = false; | |
pCtx->iErrorCode |= dsRefLost; | |
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
#ifdef LONG_TERM_REF | |
pCtx->bParamSetsLostFlag = true; | |
#else | |
pCtx->bReferenceLostAtT0Flag = true; | |
#endif | |
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_REFERENCE_PIC_LOST); | |
} | |
} | |
} | |
if (iCurrIdD == kuiDependencyIdMax && iCurrIdQ == BASE_QUALITY_ID && isNewFrame) { | |
iRet = InitRefPicList (pCtx, pCtx->uiNalRefIdc, pSh->iPicOrderCntLsb); | |
if (iRet) { | |
pCtx->bRPLRError = true; | |
bAllRefComplete = false; // RPLR error, set ref pictures complete flag false | |
HandleReferenceLost (pCtx, pNalCur); | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, | |
"reference picture introduced by this frame is lost during transmission! uiTId: %d", | |
pNalCur->sNalHeaderExt.uiTemporalId); | |
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
if (pCtx->iTotalNumMbRec == 0) | |
pCtx->pDec = NULL; | |
return iRet; | |
} | |
} | |
} | |
//calculate Colocated mv scaling factor for temporal direct prediction | |
if (pSh->eSliceType == B_SLICE && !pSh->iDirectSpatialMvPredFlag) | |
ComputeColocatedTemporalScaling (pCtx); | |
if (iThreadCount > 1) { | |
memset (&pCtx->lastReadyHeightOffset[0][0], -1, LIST_A * MAX_REF_PIC_COUNT * sizeof (int16_t)); | |
SET_EVENT (&pThreadCtx->sSliceDecodeStart); | |
iRet = WelsDecodeAndConstructSlice (pCtx); | |
} else { | |
iRet = WelsDecodeSlice (pCtx, bFreshSliceAvailable, pNalCur); | |
} | |
//Output good store_base reconstruction when enhancement quality layer occurred error for MGS key picture case | |
if (iRet != ERR_NONE) { | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, | |
"DecodeCurrentAccessUnit() failed (%d) in frame: %d uiDId: %d uiQId: %d", | |
iRet, pSh->iFrameNum, iCurrIdD, iCurrIdQ); | |
bAllRefComplete = false; | |
HandleReferenceLostL0 (pCtx, pNalCur); | |
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
if (pCtx->iTotalNumMbRec == 0) | |
pCtx->pDec = NULL; | |
return iRet; | |
} | |
} | |
if (iThreadCount <= 1 && bReconstructSlice) { | |
if ((iRet = WelsDecodeConstructSlice (pCtx, pNalCur)) != ERR_NONE) { | |
pCtx->pDec->bIsComplete = false; // reconstruction error, directly set the flag false | |
return iRet; | |
} | |
} | |
if (bAllRefComplete && pCtx->eSliceType != I_SLICE) { | |
if (iThreadCount <= 1) { | |
if (pCtx->sRefPic.uiRefCount[LIST_0] > 0) { | |
bAllRefComplete &= CheckRefPicturesComplete (pCtx); | |
} else { | |
bAllRefComplete = false; | |
} | |
} | |
} | |
} | |
#if defined (_DEBUG) && !defined (CODEC_FOR_TESTBED) | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "cur_frame : %d\tiCurrIdD : %d\n ", | |
dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFrameNum, iCurrIdD); | |
#endif//#if !CODEC_FOR_TESTBED | |
iLastIdD = iCurrIdD; | |
iLastIdQ = iCurrIdQ; | |
//pNalUnitsList overflow. | |
++ iIdx; | |
if (iIdx <= iEndIdx) { | |
pNalCur = pCurAu->pNalUnitsList[iIdx]; | |
} else { | |
pNalCur = NULL; | |
} | |
if (pNalCur == NULL || | |
iLastIdD != pNalCur->sNalHeaderExt.uiDependencyId || | |
iLastIdQ != pNalCur->sNalHeaderExt.uiQualityId) | |
break; | |
} | |
// Set the current dec picture complete flag. The flag will be reset when current picture need do ErrorCon. | |
pCtx->pDec->bIsComplete = bAllRefComplete; | |
if (!pCtx->pDec->bIsComplete) { // Ref pictures ECed, result in ECed | |
pCtx->iErrorCode |= dsDataErrorConcealed; | |
} | |
// A dq layer decoded here | |
#if defined (_DEBUG) && !defined (CODEC_FOR_TESTBED) | |
#undef fprintf | |
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "POC: #%d, FRAME: #%d, D: %d, Q: %d, T: %d, P: %d, %d\n", | |
pSh->iPicOrderCntLsb, pSh->iFrameNum, iCurrIdD, iCurrIdQ, dq_cur->sLayerInfo.sNalHeaderExt.uiTemporalId, | |
dq_cur->sLayerInfo.sNalHeaderExt.uiPriorityId, dq_cur->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceQp); | |
#endif//#if !CODEC_FOR_TESTBED | |
if (dq_cur->uiLayerDqId == kuiTargetLayerDqId) { | |
if (!pCtx->bInstantDecFlag) { | |
if (!pCtx->pParam->bParseOnly) { | |
//Do error concealment here | |
if ((NeedErrorCon (pCtx)) && (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE)) { | |
ImplementErrorCon (pCtx); | |
pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight; | |
pCtx->pDec->iSpsId = pCtx->pSps->iSpsId; | |
pCtx->pDec->iPpsId = pCtx->pPps->iPpsId; | |
} | |
} | |
} | |
if (iThreadCount >= 1) { | |
int32_t id = pThreadCtx->sThreadInfo.uiThrNum; | |
for (int32_t i = 0; i < iThreadCount; ++i) { | |
if (i == id || pThreadCtx[i - id].pCtx->uiDecodingTimeStamp == 0) continue; | |
if (pThreadCtx[i - id].pCtx->uiDecodingTimeStamp < pCtx->uiDecodingTimeStamp) { | |
WAIT_EVENT (&pThreadCtx[i - id].sSliceDecodeFinish, WELS_DEC_THREAD_WAIT_INFINITE); | |
} | |
} | |
pCtx->pLastDecPicInfo->uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp; | |
} | |
iRet = DecodeFrameConstruction (pCtx, ppDst, pDstInfo); | |
if (iRet) { | |
if (iThreadCount > 1) { | |
SET_EVENT (&pThreadCtx->sSliceDecodeFinish); | |
} | |
return iRet; | |
} | |
pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb = pCtx->pDec; //store latest decoded picture for EC | |
pCtx->bUsedAsRef = pCtx->uiNalRefIdc > 0; | |
if (iThreadCount <= 1) { | |
if (pCtx->bUsedAsRef) { | |
for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) { | |
uint32_t i = 0; | |
while (i < MAX_DPB_COUNT && pCtx->sRefPic.pRefList[listIdx][i]) { | |
pCtx->pDec->pRefPic[listIdx][i] = pCtx->sRefPic.pRefList[listIdx][i]; | |
++i; | |
} | |
} | |
iRet = WelsMarkAsRef (pCtx); | |
if (iRet != ERR_NONE) { | |
if (iRet == ERR_INFO_DUPLICATE_FRAME_NUM) | |
pCtx->iErrorCode |= dsBitstreamError; | |
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
pCtx->pDec = NULL; | |
return iRet; | |
} | |
} | |
if (!pCtx->pParam->bParseOnly) | |
ExpandReferencingPicture (pCtx->pDec->pData, pCtx->pDec->iWidthInPixel, pCtx->pDec->iHeightInPixel, | |
pCtx->pDec->iLinesize, | |
pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture); | |
} | |
} else if (iThreadCount > 1) { | |
SET_EVENT (&pThreadCtx->sImageReady); | |
} | |
pCtx->pDec = NULL; //after frame decoding, always set to NULL | |
} | |
// need update frame_num due current frame is well decoded | |
if (pCurAu->pNalUnitsList[pCurAu->uiStartPos]->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc > 0) | |
pCtx->pLastDecPicInfo->iPrevFrameNum = pSh->iFrameNum; | |
if (pCtx->pLastDecPicInfo->bLastHasMmco5) | |
pCtx->pLastDecPicInfo->iPrevFrameNum = 0; | |
if (iThreadCount > 1) { | |
int32_t id = pThreadCtx->sThreadInfo.uiThrNum; | |
for (int32_t i = 0; i < iThreadCount; ++i) { | |
if (pThreadCtx[i - id].pCtx != NULL) { | |
unsigned long long uiTimeStamp = pThreadCtx[i - id].pCtx->uiTimeStamp; | |
if (uiTimeStamp > 0 && pThreadCtx[i - id].pCtx->sSpsPpsCtx.iSeqId > pCtx->sSpsPpsCtx.iSeqId) { | |
CopySpsPps (pThreadCtx[i - id].pCtx, pCtx); | |
if (pCtx->pPicBuff != pThreadCtx[i - id].pCtx->pPicBuff) { | |
pCtx->pPicBuff = pThreadCtx[i - id].pCtx->pPicBuff; | |
} | |
InitialDqLayersContext (pCtx, pCtx->pSps->iMbWidth << 4, pCtx->pSps->iMbHeight << 4); | |
break; | |
} | |
} | |
} | |
} | |
if (iThreadCount > 1) { | |
SET_EVENT (&pThreadCtx->sSliceDecodeFinish); | |
} | |
} | |
return ERR_NONE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment