ref: 36c7b556e330886377f257b1232e06b80e64947c
parent: 3c3d4ef64b0f1cab1d510bc88a8d4718a5bd14d7
parent: db11ba7a34d1e7e984596325a63d74191259e003
author: dongzha <[email protected]>
date: Tue May 27 09:53:35 EDT 2014
Merge pull request #896 from ruil2/enc_rc_4 fix vlc overflow
--- a/codec/encoder/core/inc/rc.h
+++ b/codec/encoder/core/inc/rc.h
@@ -66,8 +66,6 @@
VGOP_SIZE = 8,
//qp information
- FIX_MIN_QP_MODE = 10, //qp <10 will cause level code overflow in cavlc coding which isn't suppored in baseline profile
- FIX_MAX_QP_MODE = 51,
GOM_MIN_QP_MODE = 12,
GOM_MAX_QP_MODE = 36,
MAX_LOW_BR_QP = 42,
--- a/codec/encoder/core/inc/set_mb_syn_cavlc.h
+++ b/codec/encoder/core/inc/set_mb_syn_cavlc.h
@@ -79,8 +79,8 @@
void InitCavlcTable();
-void WriteBlockResidualCavlc (int16_t* pCoffLevel, int32_t iEndIdx, int32_t iCalRunLevelFlag,
- int32_t iResidualProperty, int8_t iNC, SBitStringAux* pBs);
+int32_t WriteBlockResidualCavlc (int16_t* pCoffLevel, int32_t iEndIdx, int32_t iCalRunLevelFlag,
+ int32_t iResidualProperty, int8_t iNC, SBitStringAux* pBs);
#if defined(__cplusplus)
extern "C" {
--- a/codec/encoder/core/inc/svc_enc_slice_segment.h
+++ b/codec/encoder/core/inc/svc_enc_slice_segment.h
@@ -95,6 +95,7 @@
int32_t iBsStackLeftBits;
int32_t iMbSkipRunStack;
+ uint8_t uiLastMbQp;
} SDynamicSlicingStack;
/*!
--- a/codec/encoder/core/inc/svc_set_mb_syn_cavlc.h
+++ b/codec/encoder/core/inc/svc_set_mb_syn_cavlc.h
@@ -50,7 +50,7 @@
namespace WelsSVCEnc {
-void WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs);
+int32_t WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs);
void WelsSpatialWriteSubMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
--- a/codec/encoder/core/inc/wels_const.h
+++ b/codec/encoder/core/inc/wels_const.h
@@ -202,6 +202,7 @@
ENC_RETURN_CORRECTED = 0x08, //unexpected value but corrected by encoder
ENC_RETURN_INVALIDINPUT = 0x10, //invalid input
ENC_RETURN_MEMOVERFLOWFOUND = 0x20,
+ ENC_RETURN_VLCOVERFLOWFOUND = 0x40
};
//TODO: need to complete the return checking in encoder and fill in more types if needed
--- a/codec/encoder/core/src/ratectl.cpp
+++ b/codec/encoder/core/src/ratectl.cpp
@@ -928,7 +928,7 @@
pEncCtx->iGlobalQp = WELS_CLIP3 (WELS_ROUND (pEncCtx->iGlobalQp -
pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp), GOM_MIN_QP_MODE, GOM_MAX_QP_MODE);
} else {
- pEncCtx->iGlobalQp = WELS_CLIP3 (pEncCtx->iGlobalQp, FIX_MIN_QP_MODE, FIX_MAX_QP_MODE);
+ pEncCtx->iGlobalQp = WELS_CLIP3 (pEncCtx->iGlobalQp, 0, 51);
}
pWelsSvcRc->iAverageFrameQp = pEncCtx->iGlobalQp;
@@ -940,14 +940,16 @@
void WelsRcMbInitDisable (void* pCtx, SMB* pCurMb, SSlice* pSlice) {
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
int32_t iLumaQp = pEncCtx->iGlobalQp;
+
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
+
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant && (pEncCtx->eSliceType == P_SLICE)) {
iLumaQp = (int8_t)WELS_CLIP3 (iLumaQp +
pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], GOM_MIN_QP_MODE, 51);
} else {
- iLumaQp = WELS_CLIP3 (iLumaQp, FIX_MIN_QP_MODE, FIX_MAX_QP_MODE);
+ iLumaQp = WELS_CLIP3 (iLumaQp, 0, 51);
}
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (iLumaQp + kuiChromaQpIndexOffset)];
pCurMb->uiLumaQp = iLumaQp;
--- a/codec/encoder/core/src/set_mb_syn_cavlc.cpp
+++ b/codec/encoder/core/src/set_mb_syn_cavlc.cpp
@@ -41,6 +41,7 @@
#include "set_mb_syn_cavlc.h"
#include "vlc_encoder.h"
#include "cpu_core.h"
+#include "wels_const.h"
namespace WelsSVCEnc {
SCoeffFunc sCoeffFunc;
@@ -77,8 +78,8 @@
return iTotalZeros;
}
-void WriteBlockResidualCavlc (int16_t* pCoffLevel, int32_t iEndIdx, int32_t iCalRunLevelFlag,
- int32_t iResidualProperty, int8_t iNC, SBitStringAux* pBs) {
+int32_t WriteBlockResidualCavlc (int16_t* pCoffLevel, int32_t iEndIdx, int32_t iCalRunLevelFlag,
+ int32_t iResidualProperty, int8_t iNC, SBitStringAux* pBs) {
ENFORCE_STACK_ALIGN_1D (int16_t, iLevel, 16, 16)
ENFORCE_STACK_ALIGN_1D (uint8_t, uiRun, 16, 16)
@@ -121,7 +122,7 @@
CAVLC_BS_WRITE (n, iValue);
CAVLC_BS_UNINIT (pBs);
- return;
+ return ENC_RETURN_SUCCESS;
}
/* Step 4: */
@@ -152,7 +153,9 @@
} else if (iLevelPrefix >= 15) {
iLevelPrefix = 15;
iLevelSuffix = iLevelCode - (iLevelPrefix << uiSuffixLength);
-
+ //for baseline profile,overflow when the length of iLevelSuffix is larger than 11.
+ if (iLevelSuffix >> 11)
+ return ENC_RETURN_VLCOVERFLOWFOUND;
if (uiSuffixLength == 0) {
iLevelSuffix -= 15;
}
@@ -197,6 +200,7 @@
}
CAVLC_BS_UNINIT (pBs);
+ return ENC_RETURN_SUCCESS;
}
--- a/codec/encoder/core/src/svc_encode_slice.cpp
+++ b/codec/encoder/core/src/svc_encode_slice.cpp
@@ -460,7 +460,25 @@
pfIdctFour4x4 (pDecV, kiDecStrideChroma, pDecV, kiDecStrideChroma, pScaledTcoeff + 320);
}
}
-
+inline void StashMBStatus (SDynamicSlicingStack* pDss, SBitStringAux* pBs, SSlice* pSlice, int32_t iMbSkipRun = 0) {
+ pDss->pBsStackBufPtr = pBs->pBufPtr;
+ pDss->uiBsStackCurBits = pBs->uiCurBits;
+ pDss->iBsStackLeftBits = pBs->iLeftBits;
+ pDss->uiLastMbQp = pSlice->uiLastMbQp;
+ pDss->iMbSkipRunStack = iMbSkipRun;
+}
+void StashPopMBStatus (SDynamicSlicingStack* pDss, SBitStringAux* pBs, SSlice* pSlice, int32_t* pMbSkipRun = 0) {
+ pBs->pBufPtr = pDss->pBsStackBufPtr;
+ pBs->uiCurBits = pDss->uiBsStackCurBits;
+ pBs->iLeftBits = pDss->iBsStackLeftBits;
+ pSlice->uiLastMbQp = pDss->uiLastMbQp;
+ if(pMbSkipRun)
+ *pMbSkipRun = pDss->iMbSkipRunStack;
+}
+void UpdateQpForOverflow (SMB* pCurMb, uint8_t kuiChromaQpIndexOffset) {
+ pCurMb->uiLumaQp += DELTA_QP;
+ pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
+}
// for intra non-dynamic pSlice
//encapsulate two kinds of reconstruction:
//first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)
@@ -477,22 +495,31 @@
const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
int32_t iCurMbIdx = 0, iNumMbCoded = 0;
const int32_t kiSliceIdx = pSlice->uiSliceIdx;
+ const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
SWelsMD sMd;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
-
+ SBitStringAux* pBs = pSlice->pSliceBsa;
+ SDynamicSlicingStack sDss;
for (; ;) {
+ StashMBStatus (&sDss, pBs, pSlice);
iCurMbIdx = iNextMbIdx;
pCurMb = &pMbList[ iCurMbIdx ];
+
pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
+ WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
+TRY_REENCODING:
sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
-
- WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
WelsMdIntraMb (pEncCtx, &sMd, pCurMb, pMbCache);
UpdateNonZeroCountCache (pCurMb, pMbCache);
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
+ if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
+ StashPopMBStatus (&sDss, pBs, pSlice);
+ UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
+ goto TRY_REENCODING;
+ }
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
@@ -505,7 +532,6 @@
pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, sMd.iCostLuma, pSlice);
++iNumMbCoded;
-
iNextMbIdx = WelsGetNextMbOfSlice (pSliceCtx, iCurMbIdx);
if (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {
break;
@@ -540,6 +566,8 @@
for (; ;) {
iCurMbIdx = iNextMbIdx;
pCurMb = &pMbList[ iCurMbIdx ];
+
+ StashMBStatus (&sDss, pBs, pSlice);
pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
// if already reaches the largest number of slices, set QPs to the upper bound
if (pSlice->bDynamicSlicingSliceSizeCtrlFlag) {
@@ -546,18 +574,19 @@
pCurMb->uiLumaQp = pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].iMaxQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
}
+ WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
+TRY_REENCODING:
sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
-
- WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
WelsMdIntraMb (pEncCtx, &sMd, pCurMb, pMbCache);
UpdateNonZeroCountCache (pCurMb, pMbCache);
- //stack pBs pointer
- sDss.pBsStackBufPtr = pBs->pBufPtr;
- sDss.uiBsStackCurBits = pBs->uiCurBits;
- sDss.iBsStackLeftBits = pBs->iLeftBits;
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
+ if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
+ StashPopMBStatus (&sDss, pBs, pSlice);
+ UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
+ goto TRY_REENCODING;
+ }
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
@@ -926,12 +955,14 @@
const int32_t kiSliceIdx = pSlice->uiSliceIdx;
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
-
+ SDynamicSlicingStack sDss;
for (;;) {
+ StashMBStatus (&sDss, pBs, pSlice, iMbSkipRun);
//point to current pMb
iCurMbIdx = iNextMbIdx;
pCurMb = &pMbList[ iCurMbIdx ];
+
//step(1): set QP for the current MB
pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
@@ -938,6 +969,8 @@
//step (2). save some vale for future use, initial pWelsMd
WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
WelsMdInterInit (pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);
+
+TRY_REENCODING:
WelsInitInterMDStruc (pCurMb, pMvdCostTableInter, kiMvdInterTableStride, pMd);
pEncCtx->pFuncList->pfInterMd (pEncCtx, pMd, pSlice, pCurMb, pMbCache);
//mb_qp
@@ -961,6 +994,11 @@
BsWriteUE (pBs, iMbSkipRun);
iMbSkipRun = 0;
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
+ if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
+ StashPopMBStatus (&sDss, pBs, pSlice, &iMbSkipRun);
+ UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
+ goto TRY_REENCODING;
+ }
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
}
@@ -1018,6 +1056,10 @@
SDynamicSlicingStack sDss;
sDss.iStartPos = BsGetBitsPos (pBs);
for (;;) {
+ //DYNAMIC_SLICING_ONE_THREAD - MultiD
+ //stack pBs pointer
+ StashMBStatus (&sDss, pBs, pSlice, iMbSkipRun);
+
//point to current pMb
iCurMbIdx = iNextMbIdx;
pCurMb = &pMbList[ iCurMbIdx ];
@@ -1036,6 +1078,8 @@
//step (2). save some vale for future use, initial pWelsMd
WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
WelsMdInterInit (pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);
+
+TRY_REENCODING:
WelsInitInterMDStruc (pCurMb, pMvdCostTableInter, kiMvdInterTableStride, pMd);
pEncCtx->pFuncList->pfInterMd (pEncCtx, pMd, pSlice, pCurMb, pMbCache);
//mb_qp
@@ -1051,15 +1095,6 @@
//step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
- //DYNAMIC_SLICING_ONE_THREAD - MultiD
- //stack pBs pointer
- sDss.pBsStackBufPtr = pBs->pBufPtr;
- sDss.uiBsStackCurBits = pBs->uiCurBits;
- sDss.iBsStackLeftBits = pBs->iLeftBits;
- //stack Pskip status
- sDss.iMbSkipRunStack = iMbSkipRun;
- //DYNAMIC_SLICING_ONE_THREAD - MultiD
-
if (IS_SKIP (pCurMb->uiMbType)) {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
@@ -1069,6 +1104,11 @@
BsWriteUE (pBs, iMbSkipRun);
iMbSkipRun = 0;
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
+ if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) {
+ StashPopMBStatus (&sDss, pBs, pSlice, &iMbSkipRun);
+ UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
+ goto TRY_REENCODING;
+ }
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
}
--- a/codec/encoder/core/src/svc_set_mb_syn_cavlc.cpp
+++ b/codec/encoder/core/src/svc_set_mb_syn_cavlc.cpp
@@ -244,7 +244,8 @@
pSlice->uiLastMbQp = pCurMb->uiLumaQp;
BsWriteSE (pBs, kiDeltaQp);
- WelsWriteMbResidual (pMbCache, pCurMb, pBs);
+ if (WelsWriteMbResidual (pMbCache, pCurMb, pBs))
+ return ENC_RETURN_VLCOVERFLOWFOUND;
} else {
pCurMb->uiLumaQp = pSlice->uiLastMbQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp +
@@ -255,7 +256,7 @@
return CheckBitstreamBuffer (pSlice->uiSliceIdx, pEncCtx, pBs);
}
-void WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs) {
+int32_t WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs) {
int32_t i;
Mb_Type uiMbType = pCurMb->uiMbType;
const int32_t kiCbpChroma = pCurMb->uiCbp >> 4;
@@ -269,7 +270,8 @@
iA = pNonZeroCoeffCount[8];
iB = pNonZeroCoeffCount[ 1];
WELS_NON_ZERO_COUNT_AVERAGE (iC, iA, iB);
- WriteBlockResidualCavlc (sMbCacheInfo->pDct->iLumaI16x16Dc, 15, 1, LUMA_4x4, iC, pBs);
+ if (WriteBlockResidualCavlc (sMbCacheInfo->pDct->iLumaI16x16Dc, 15, 1, LUMA_4x4, iC, pBs))
+ return ENC_RETURN_VLCOVERFLOWFOUND;
/* AC Luma */
if (kiCbpLuma) {
@@ -324,10 +326,12 @@
if (kiCbpChroma) {
/* Chroma DC residual present */
pBlock = sMbCacheInfo->pDct->iChromaDc[0]; // Cb
- WriteBlockResidualCavlc (pBlock, 3, 1, CHROMA_DC, CHROMA_DC_NC_OFFSET, pBs);
+ if (WriteBlockResidualCavlc (pBlock, 3, 1, CHROMA_DC, CHROMA_DC_NC_OFFSET, pBs))
+ return ENC_RETURN_VLCOVERFLOWFOUND;
pBlock += 4; // Cr
- WriteBlockResidualCavlc (pBlock, 3, 1, CHROMA_DC, CHROMA_DC_NC_OFFSET, pBs);
+ if (WriteBlockResidualCavlc (pBlock, 3, 1, CHROMA_DC, CHROMA_DC_NC_OFFSET, pBs))
+ return ENC_RETURN_VLCOVERFLOWFOUND;
/* Chroma AC residual present */
if (kiCbpChroma & 0x02) {
@@ -355,6 +359,7 @@
}
}
}
+ return 0;
}
} // namespace WelsSVCEnc
--- a/codec/processing/src/common/util.h
+++ b/codec/processing/src/common/util.h
@@ -67,8 +67,15 @@
#define WELS_MAX(x, y) ((x) > (y) ? (x) : (y))
#define WELS_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#ifndef WELS_SIGN
#define WELS_SIGN(a) ((int32_t)(a) >> 31)
+#endif
+
+#ifndef WELS_ABS
#define WELS_ABS(a) ((WELS_SIGN(a) ^ (int32_t)(a)) - WELS_SIGN(a))
+#endif
+
#define WELS_CLAMP(x, minv, maxv) WELS_MIN(WELS_MAX(x, minv), maxv)
#define ALIGNBYTES (16) /* Worst case is requiring alignment to an 16 byte boundary */