Skip to content

Commit

Permalink
Fix glitch occurs when multiple scene changes happen in a short time.
Browse files Browse the repository at this point in the history
Previously, when more than 2 frame sequences exist in the reordering
buffer, the reordering does not work correctly. This is because the
management based on bLastPOC flag does not work in this case.
Instead, this patch introduces frame sequence number (iSeqNum) to
distingish frames belonging to each sequence and drops bLastPOC flag.
  • Loading branch information
tyan0 committed Dec 18, 2023
1 parent 493a0cf commit eb0e1d8
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 89 deletions.
6 changes: 4 additions & 2 deletions codec/decoder/core/inc/decoder_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,15 @@ typedef struct tagPictInfo {
int32_t iPOC;
int32_t iPicBuffIdx;
uint32_t uiDecodingTimeStamp;
bool bLastGOP;
int32_t iSeqNum;
} SPictInfo, *PPictInfo;

typedef struct tagPictReoderingStatus {
int32_t iPictInfoIndex;
int32_t iMinSeqNum;
int32_t iMinPOC;
int32_t iNumOfPicts;
int32_t iLastGOPRemainPicts;
int32_t iLastWrittenSeqNum;
int32_t iLastWrittenPOC;
int32_t iLargestBufferedPicIndex;
bool bHasBSlice;
Expand Down Expand Up @@ -431,6 +432,7 @@ typedef struct TagWelsDecoderContext {
#endif
bool bNewSeqBegin;
bool bNextNewSeqBegin;
int32_t iSeqNum;

//for Parse only
bool bFramePending;
Expand Down
3 changes: 1 addition & 2 deletions codec/decoder/core/src/decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,9 @@ void ResetReorderingPictureBuffers (PPictReoderingStatus pPictReoderingStatus, P
pPictReoderingStatus->iPictInfoIndex = 0;
pPictReoderingStatus->iMinPOC = IMinInt32;
pPictReoderingStatus->iNumOfPicts = 0;
pPictReoderingStatus->iLastGOPRemainPicts = 0;
pPictReoderingStatus->iLastWrittenPOC = IMinInt32;
pPictReoderingStatus->iLargestBufferedPicIndex = 0;
for (int32_t i = 0; i < pictInfoListCount; ++i) {
pPictInfo[i].bLastGOP = false;
pPictInfo[i].iPOC = IMinInt32;
}
pPictInfo->sBufferInfo.iBufferStatus = 0;
Expand Down Expand Up @@ -623,6 +621,7 @@ int32_t WelsOpenDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
pCtx->bPrintFrameErrorTraceFlag = true;
pCtx->iIgnoredErrorInfoPacketCount = 0;
pCtx->bFrameFinish = true;
pCtx->iSeqNum = 0;
return iRet;
}

Expand Down
2 changes: 2 additions & 0 deletions codec/decoder/core/src/decoder_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2261,6 +2261,8 @@ int32_t WelsDecodeInitAccessUnitStart (PWelsDecoderContext pCtx, SBufferInfo* pD
pCtx->bAuReadyFlag = false;
pCtx->pLastDecPicInfo->bLastHasMmco5 = false;
bool bTmpNewSeqBegin = CheckNewSeqBeginAndUpdateActiveLayerSps (pCtx);
if (bTmpNewSeqBegin)
pCtx->iSeqNum++;
pCtx->bNewSeqBegin = pCtx->bNewSeqBegin || bTmpNewSeqBegin;
iErr = WelsDecodeAccessUnitStart (pCtx);
GetVclNalTemporalId (pCtx);
Expand Down
100 changes: 15 additions & 85 deletions codec/decoder/plus/src/welsDecoderExt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,46 +993,17 @@ void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned cha
if (pCtx->pSliceHeader->eSliceType == B_SLICE) {
m_sReoderingStatus.bHasBSlice = true;
}
if (m_sReoderingStatus.iNumOfPicts && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb
&& pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin) {
m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts;

for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
if (m_sPictInfoList[i].iPOC > IMinInt32) {
m_sPictInfoList[i].bLastGOP = true;
}
}
} else {
if (m_sReoderingStatus.iNumOfPicts > 0) {
//This can happen when decoder moves to next GOP without being able to decoder first picture PicOrderCntLsb = 0
bool hasGOPChanged = false;
for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
if (m_sPictInfoList[i].iPOC == pCtx->pSliceHeader->iPicOrderCntLsb) {
hasGOPChanged = true;
break;
}
}
if (hasGOPChanged) {
m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts;
for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
if (m_sPictInfoList[i].iPOC > IMinInt32) {
m_sPictInfoList[i].bLastGOP = true;
}
}
}
}
}
}
for (int32_t i = 0; i < 16; ++i) {
if (m_sPictInfoList[i].iPOC == IMinInt32) {
memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb;
m_sPictInfoList[i].iSeqNum = pCtx->iSeqNum;
m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp;
if (pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb != NULL) {
m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount;
}
m_sPictInfoList[i].bLastGOP = false;
m_iLastBufferedIdx = i;
pDstInfo->iBufferStatus = 0;
++m_sReoderingStatus.iNumOfPicts;
Expand All @@ -1050,67 +1021,24 @@ void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx,
if (pCtx == NULL && m_iThreadCount <= 1) {
pCtx = m_pDecThrCtx[0].pCtx;
}
if (m_sReoderingStatus.iLastGOPRemainPicts > 0) {
m_sReoderingStatus.iMinPOC = IMinInt32;
int32_t firstValidIdx = -1;
for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) {
m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
m_sReoderingStatus.iPictInfoIndex = i;
firstValidIdx = i;
break;
}
}
for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
if (i == firstValidIdx) continue;
if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC
&& m_sPictInfoList[i].bLastGOP) {
m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
m_sReoderingStatus.iPictInfoIndex = i;
}
}
m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
#if defined (_DEBUG)
#ifdef _MOTION_VECTOR_DUMP_
fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
#endif
#endif
memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
ppDst[0] = pDstInfo->pDst[0];
ppDst[1] = pDstInfo->pDst[1];
ppDst[2] = pDstInfo->pDst[2];
m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
if (pPicBuff != NULL) {
PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
--pPic->iRefCount;
if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
pPic->pSetUnRef(pPic);
}
m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
m_sReoderingStatus.iMinPOC = IMinInt32;
--m_sReoderingStatus.iNumOfPicts;
--m_sReoderingStatus.iLastGOPRemainPicts;
if (m_sReoderingStatus.iLastGOPRemainPicts == 0) {
m_sReoderingStatus.iLastWrittenPOC = IMinInt32;
}
return;
}
if (m_sReoderingStatus.iNumOfPicts > 0) {
m_sReoderingStatus.iMinPOC = IMinInt32;
int32_t firstValidIdx = -1;
for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
m_sReoderingStatus.iMinSeqNum = m_sPictInfoList[i].iSeqNum;
m_sReoderingStatus.iPictInfoIndex = i;
firstValidIdx = i;
break;
}
}
for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
if (i == firstValidIdx) continue;
if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) {
if (m_sPictInfoList[i].iPOC > IMinInt32
&& ((m_sPictInfoList[i].iSeqNum == m_sReoderingStatus.iMinSeqNum) ? (m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) : (m_sPictInfoList[i].iSeqNum - m_sReoderingStatus.iMinSeqNum < 0))) {
m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
m_sReoderingStatus.iMinSeqNum = m_sPictInfoList[i].iSeqNum;
m_sReoderingStatus.iPictInfoIndex = i;
}
}
Expand All @@ -1119,12 +1047,15 @@ void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx,
bool isReady = true;
if (!isFlush) {
int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC;
int32_t iLastSeqNum = pCtx != NULL ? pCtx->iSeqNum : m_sPictInfoList[m_iLastBufferedIdx].iSeqNum;
isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32
&& m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1)
|| m_sReoderingStatus.iMinPOC < iLastPOC;
|| m_sReoderingStatus.iMinPOC < iLastPOC
|| m_sReoderingStatus.iMinSeqNum - iLastSeqNum < 0;
}
if (isReady) {
m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
m_sReoderingStatus.iLastWrittenSeqNum = m_sReoderingStatus.iMinSeqNum;
#if defined (_DEBUG)
#ifdef _MOTION_VECTOR_DUMP_
fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
Expand All @@ -1146,7 +1077,6 @@ void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx,
pPic->pSetUnRef(pPic);
}
}
m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
m_sReoderingStatus.iMinPOC = IMinInt32;
--m_sReoderingStatus.iNumOfPicts;
}
Expand Down Expand Up @@ -1182,6 +1112,7 @@ void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx
#endif
#endif
m_sReoderingStatus.iLastWrittenPOC = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC;
m_sReoderingStatus.iLastWrittenSeqNum = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iSeqNum;
memcpy(pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof(SBufferInfo));
ppDst[0] = pDstInfo->pDst[0];
ppDst[1] = pDstInfo->pDst[1];
Expand All @@ -1194,10 +1125,6 @@ void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx
if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
pPic->pSetUnRef(pPic);
}
if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP) {
--m_sReoderingStatus.iLastGOPRemainPicts;
m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
}
--m_sReoderingStatus.iNumOfPicts;
}
return;
Expand All @@ -1210,9 +1137,12 @@ DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay(PWelsDecoderContext pDecCo
m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83;
if (!m_bIsBaseline) {
if (pDstInfo->iBufferStatus == 1) {
if (m_sReoderingStatus.iLastGOPRemainPicts == 0 && pDecContext->pSliceHeader->eSliceType == B_SLICE &&
pDecContext->pSliceHeader->iPicOrderCntLsb <= m_sReoderingStatus.iLastWrittenPOC + 2) {
if (pDecContext->pSliceHeader->eSliceType == B_SLICE &&
((pDecContext->iSeqNum == m_sReoderingStatus.iLastWrittenSeqNum) ?
(pDecContext->pSliceHeader->iPicOrderCntLsb <= m_sReoderingStatus.iLastWrittenPOC + 2) :
(pDecContext->iSeqNum - m_sReoderingStatus.iLastWrittenSeqNum == 1 && pDecContext->pSliceHeader->iPicOrderCntLsb == 0))) {
m_sReoderingStatus.iLastWrittenPOC = pDecContext->pSliceHeader->iPicOrderCntLsb;
m_sReoderingStatus.iLastWrittenSeqNum = pDecContext->iSeqNum;
//issue #3478, use b-slice type to determine correct picture order as the first priority as POC order is not as reliable as based on b-slice
ppDst[0] = pDstInfo->pDst[0];
ppDst[1] = pDstInfo->pDst[1];
Expand Down

0 comments on commit eb0e1d8

Please sign in to comment.