add DPB management if frame loss happens

This commit is contained in:
huili2 2014-04-20 08:20:12 -07:00
parent 1b1654e9c6
commit d031509474
2 changed files with 76 additions and 10 deletions

View File

@ -174,8 +174,8 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
fread (&iSliceSize, 1, sizeof (int32_t), fpTrack);
#else
for (i = 0; i < iFileSize; i++) {
if (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 &&
pBuf[iBufPos + i + 3] == 1 && i > 0) {
if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
&& i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) {
break;
}
}
@ -303,7 +303,7 @@ label_exit:
}
#if (defined(ANDROID_NDK)||defined(APPLE_IOS))
int32_t DecMain(int32_t iArgC, char* pArgV[]) {
int32_t DecMain (int32_t iArgC, char* pArgV[]) {
#else
int32_t main (int32_t iArgC, char* pArgV[]) {
#endif
@ -429,7 +429,8 @@ int32_t main (int32_t iArgC, char* pArgV[]) {
int32_t iHeight = 0;
H264DecodeInstance (pDecoder, strInputFile.c_str(), !strOutputFile.empty() ? strOutputFile.c_str() : NULL, iWidth, iHeight,
H264DecodeInstance (pDecoder, strInputFile.c_str(), !strOutputFile.empty() ? strOutputFile.c_str() : NULL, iWidth,
iHeight,
(!strOptionFile.empty() ? strOptionFile.c_str() : NULL));
if (sDecParam.pFileNameRestructed != NULL) {

View File

@ -57,6 +57,10 @@ static int32_t SlidingWindow (PWelsDecoderContext pCtx);
static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic);
static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx);
static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx);
#ifdef LONG_TERM_REF
int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum);
#endif
static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx);
static void SetUnRef (PPicture pRef) {
if (NULL != pRef) {
@ -211,7 +215,6 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
int32_t iRet = ERR_NONE;
pCtx->pDec->bUsedAsRef = true;
pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId;
pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId;
@ -232,8 +235,14 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
} else {
if (pRefPicMarking->bAdaptiveRefPicMarkingModeFlag) {
iRet = MMCO (pCtx, pRefPicMarking);
if (iRet != ERR_NONE)
return iRet;
if (iRet != ERR_NONE) {
if (pCtx->iErrorConMethod != ERROR_CON_DISABLE) {
iRet = RemainOneBufferInDpbForEC (pCtx);
} else {
return iRet;
}
}
if (pCtx->bLastHasMmco5) {
pCtx->pDec->iFrameNum = 0;
pCtx->pDec->iFramePoc = 0;
@ -241,14 +250,23 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
} else {
iRet = SlidingWindow (pCtx);
if (iRet != ERR_NONE)
return iRet;
if (iRet != ERR_NONE) {
if (pCtx->iErrorConMethod != ERROR_CON_DISABLE) {
iRet = RemainOneBufferInDpbForEC (pCtx);
} else {
return iRet;
}
}
}
}
if (!pCtx->pDec->bIsLongRef) {
if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX(1,pCtx->pSps->iNumRefFrames)) {
return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
if (pCtx->iErrorConMethod != ERROR_CON_DISABLE) {
iRet = RemainOneBufferInDpbForEC (pCtx);
} else {
return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
}
}
AddShortTermToList (pRefPic, pCtx->pDec);
}
@ -484,4 +502,51 @@ static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLong
return iRet;
}
#ifdef LONG_TERM_REF
int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum) {
int32_t iLTRFrameIndex = -1;
PPicture pPic;
for (int i = 0; i < pRefPic->uiLongRefCount[0]; ++i) {
pPic = pRefPic->pLongRefList[LIST_0][i];
if (pPic->iFrameNum == iAncLTRFrameNum) {
return (pPic->iLongTermFrameIdx);
}
}
return iLTRFrameIndex;
}
#endif
static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx) {
int32_t iRet = ERR_NONE;
PRefPic pRefPic = &pCtx->sRefPic;
if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] < pCtx->pSps->iNumRefFrames)
return iRet;
if (pRefPic->uiShortRefCount[0] > 0) {
iRet = SlidingWindow (pCtx);
} else { //all LTR, remove the smallest long_term_frame_idx
uint32_t uiLongTermFrameIdx = 0;
uint32_t uiMaxLongTermFrameIdx = pRefPic->iMaxLongTermFrameIdx;
#ifdef LONG_TERM_REF
uint32_t uiCurrLTRFrameIdx = GetLTRFrameIndex (pRefPic, pCtx->iFrameNumOfAuMarkedLtr);
#endif
while ((pRefPic->uiLongRefCount[0] >= pCtx->pSps->iNumRefFrames) && (uiLongTermFrameIdx <= uiMaxLongTermFrameIdx)) {
#ifdef LONG_TERM_REF
if (uiLongTermFrameIdx == uiCurrLTRFrameIdx) {
uiLongTermFrameIdx++;
continue;
}
#endif
WelsDelLongFromListSetUnref (pRefPic, uiLongTermFrameIdx);
uiLongTermFrameIdx++;
}
}
if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] >= pCtx->pSps->iNumRefFrames) { //fail to remain one empty buffer in DPB
WelsLog (pCtx, WELS_LOG_WARNING, "RemainOneBufferInDpbForEC(): empty one DPB failed for EC!\n");
iRet = ERR_INFO_REF_COUNT_OVERFLOW;
}
return iRet;
}
} // namespace WelsDec