Merge pull request #896 from ruil2/enc_rc_4

fix vlc overflow
This commit is contained in:
dongzha 2014-05-27 13:53:35 +08:00
commit 36c7b556e3
10 changed files with 97 additions and 39 deletions

View File

@ -66,8 +66,6 @@ enum {
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,

View File

@ -79,8 +79,8 @@ void InitCoeffFunc (const uint32_t uiCpuFlag);
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" {

View File

@ -95,6 +95,7 @@ typedef struct TagDynamicSlicingStack {
int32_t iBsStackLeftBits;
int32_t iMbSkipRunStack;
uint8_t uiLastMbQp;
} SDynamicSlicingStack;
/*!

View File

@ -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);

View File

@ -202,6 +202,7 @@ enum {
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

View File

@ -928,7 +928,7 @@ void WelsRcPictureInitDisable (void* pCtx) {
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 WelsRcPictureInfoUpdateDisable (void* pCtx, int32_t layer_size) {
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;

View File

@ -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 @@ int32_t CavlcParamCal_c (int16_t* pCoffLevel, uint8_t* pRun, int16_t* pLevel, in
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 @@ void WriteBlockResidualCavlc (int16_t* pCoffLevel, int32_t iEndIdx, int32_t iCa
CAVLC_BS_WRITE (n, iValue);
CAVLC_BS_UNINIT (pBs);
return;
return ENC_RETURN_SUCCESS;
}
/* Step 4: */
@ -152,7 +153,9 @@ void WriteBlockResidualCavlc (int16_t* pCoffLevel, int32_t iEndIdx, int32_t iCa
} 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 @@ void WriteBlockResidualCavlc (int16_t* pCoffLevel, int32_t iEndIdx, int32_t iCa
}
CAVLC_BS_UNINIT (pBs);
return ENC_RETURN_SUCCESS;
}

View File

@ -460,7 +460,25 @@ void OutputPMbWithoutConstructCsRsNoCopy (sWelsEncCtx* pCtx, SDqLayer* pDq, SSli
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 @@ int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encodin
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);
sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
TRY_REENCODING:
sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
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 @@ int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encodin
pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, sMd.iCostLuma, pSlice);
++iNumMbCoded;
iNextMbIdx = WelsGetNextMbOfSlice (pSliceCtx, iCurMbIdx);
if (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {
break;
@ -540,24 +566,27 @@ int32_t WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd +
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) {
pCurMb->uiLumaQp = pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].iMaxQp;
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
}
sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
TRY_REENCODING:
sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
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,18 +955,22 @@ int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,
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);
//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 @@ int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,
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 @@ int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice,
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 @@ int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice,
//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 @@ int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice,
//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 @@ int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice,
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;
}

View File

@ -244,7 +244,8 @@ int32_t WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb
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 @@ int32_t WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb
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 @@ void WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pB
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 @@ void WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pB
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 @@ void WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pB
}
}
}
return 0;
}
} // namespace WelsSVCEnc

View File

@ -67,8 +67,15 @@ WELSVP_NAMESPACE_BEGIN
#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 */