Squashed merge from writenal_refactor2

This commit is contained in:
sijchen 2014-02-20 14:50:04 +08:00
parent a921bc6589
commit e45e859473
16 changed files with 436 additions and 268 deletions

View File

@ -292,6 +292,7 @@ typedef struct {
int iLayerNum;
SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME];
int eOutputFrameType;
} SFrameBSInfo, *PFrameBSInfo;
typedef struct Source_Picture_s {

View File

@ -194,6 +194,18 @@ return iY;
#define WELS_CLIP3(iX, iY, iZ) ((iX) < (iY) ? (iY) : ((iX) > (iZ) ? (iZ) : (iX)))
#endif //WELS_CLIP3
/*
* Description: to check variable validation and return the specified result
* iResult: value to be checked
* iExpected: the expected value
*/
#ifndef WELS_VERIFY_RETURN_IFNEQ
#define WELS_VERIFY_RETURN_IFNEQ(iResult, iExpected) \
if ( iResult != iExpected ){ \
return iResult; \
}
#endif//#if WELS_VERIFY_RETURN_IF
/*
* Description: to check variable validation and return the specified result
* iResult: value to be return

View File

@ -57,6 +57,13 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx);
*/
void FreeMemorySvc (sWelsEncCtx** ppCtx);
/*!
* \brief allocate or reallocate the output bs buffer
* \return: successful - 0; otherwise none 0 for failed
*/
int32_t AllocateBsOutputBuffer(CMemoryAlign*pMa, const int32_t iNeededLen, int32_t iOrigLen, const char* kpTag, uint8_t*& pOutputBuffer );
//TODO: to finish this function and call it
/*!
* \brief initialize function pointers that potentially used in Wels encoding
* \param pEncCtx sWelsEncCtx*

View File

@ -220,6 +220,11 @@ typedef struct TagWelsEncCtx {
SStatSliceInfo sPerInfo;
#endif//STAT_OUTPUT
int32_t iEncoderError;
#ifdef MT_ENABLED
WELS_MUTEX mutexEncoderError;
#endif
} sWelsEncCtx/*, *PWelsEncCtx*/;
}
#endif//sWelsEncCtx_H__

View File

@ -47,6 +47,7 @@
//SBitStringAux
namespace WelsSVCEnc {
#define NAL_HEADER_SIZE (4)
/*
* Raw payload pData for NAL unit, AVC/SVC compatible
*/
@ -56,6 +57,7 @@ int32_t iPayloadSize; // size of pRawNal pData
SNalUnitHeaderExt sNalExt; // NAL header information
int32_t iStartPos; //NAL start position in buffer
} SWelsNalRaw;
/*
@ -125,22 +127,9 @@ void WelsUnloadNalForSlice (SWelsSliceBs* pSliceBs);
* \param pDstLen length of pDst NAL output
* \param annexeb annexeb flag
* \param pRawNal pRawNal NAL pData
* \return length of pDst NAL
* \return ERR_CODE
*/
int32_t WelsEncodeNal (SWelsNalRaw* pRawNal, void* pDst, int32_t* pDstLen);
/*!
* \brief encode a nal into a pBuffer for any type of NAL, involved WelsEncodeNal introduced in AVC
*
* \param pDst pDst NAL pData
* \param pDstLen length of pDst NAL output
* \param annexeb annexeb flag
* \param pRawNal pRawNal NAL pData
* \param pNalHeaderExt pointer of SNalUnitHeaderExt
*
* \return length of pDst NAL
*/
int32_t WelsEncodeNalExt (SWelsNalRaw* pRawNal, void* pNalHeaderExt, void* pDst, int32_t* pDstLen);
int32_t WelsEncodeNal (SWelsNalRaw* pRawNal, void* pNalHeaderExt, const int32_t kiDstBufferLen, void* pDst, int32_t* pDstLen);
/*!
* \brief write prefix nal

View File

@ -80,7 +80,7 @@ int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam, con
void ReleaseMtResource (sWelsEncCtx** ppCtx);
int32_t AppendSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, const int32_t kiSliceCount);
int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer, const int32_t kiSliceIdx);
int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer, const int32_t iSliceIdx, int32_t& iSliceSize);
#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
#if defined(__GNUC__)

View File

@ -72,18 +72,18 @@ void WelsPMbChromaEncode (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
//===================MB-level encode====================//
//encapsulation func: store base rec, highest Dependency Layer(only one quality) rec, single layer rec
void WelsPSliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag);
void WelsPSliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag);
int32_t WelsPSliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag);
int32_t WelsPSliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag);
//encapsulation func: store base rec, highest Dependency Layer(only one quality) rec, single layer rec
void WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice); // for intra non-dynamic slice
void WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice); // for intra dynamic slice
int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice); // for intra non-dynamic slice
int32_t WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice); // for intra dynamic slice
void WelsCodePSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice);
void WelsCodePOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice);
int32_t WelsCodePSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice);
int32_t WelsCodePOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice);
void WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx,
const int32_t/*EWelsNalUnitType*/ keNalType/*, bool bNewLayer*/);
int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx,
const int32_t keNalType);
void WelsInitSliceEncodingFuncs (uint32_t uiCpuFlag);
@ -93,9 +93,9 @@ void UpdateMbNeighbourInfoForNextSlice (SSliceCtx* pSliceCtx,
const int32_t kiLastMbIdxInPartition);
void AddSliceBoundary (sWelsEncCtx* pEncCtx, SSlice* pCurSlice, SSliceCtx* pSliceCtx, SMB* pCurMb,
int32_t iNextSliceFirstMbIdx, const int32_t kiLastMbIdxInPartition);
void WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pMd,
int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pMd,
const int32_t kiSliceFirstMbXY); // for inter non-dynamic slice
void WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pMd,
int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pMd,
const int32_t kiSliceFirstMbXY); // for inter dynamic slice

View File

@ -52,13 +52,12 @@ namespace WelsSVCEnc {
void WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs);
//for Enhance Layer CAVLC writing
void WelsSpatialWriteSubMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
void WelsSpatialWriteMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
//for Base Layer CAVLC writing
void WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
int32_t WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb);
}
#endif

View File

@ -107,18 +107,7 @@
#define I420_PLANES 3
// Condition of fix unexpected coding violation in case actual compress ratio of coding is less than 2:1 (compress_ratio=i420_base_picture_size/actual_size_of_coded_bs).
// Coding picture resolution as SubQcif or above size compress ration using 2:1 by default, such normal case regards as ratio can meet 2:1 requirement.
// Per specific cases, i.e, 16x16 picture size, the compress ration usually less than 2:1, so which results in unexpected violation due not large enough of frame bs pBuffer size.
// Here SubQcif just like thredshold to distinguish between normal cases and abnormal cases by resolution size from products usage.
#define COMPRESS_RATION_NORMAL_THR (0.5f) // 0.5f, 0.375f, 0.25f
#define COMPRESS_RATION_ABNORMAL_THR (1.0f) // ensure (1.0f >= COMPRESS_RATION_ABNORMAL_THR > COMPRESS_RATION_NORMAL_THR)
#define RESOLUTION_NORMAL_CX_THR (128)
#define RESOLUTION_NORMAL_CY_THR (96)
#define COMPRESS_RATIO_DECIDED_BY_RESOLUTION(_cx, _cy) \
(((_cx) >= RESOLUTION_NORMAL_CX_THR && (_cy) >= RESOLUTION_NORMAL_CY_THR) ? \
COMPRESS_RATION_NORMAL_THR : \
COMPRESS_RATION_ABNORMAL_THR)
#define COMPRESS_RATIO_THR (1.0f) //set to size of the original data, which will be large enough considering MinCR
#if !defined(SSEI_BUFFER_SIZE)
#define SSEI_BUFFER_SIZE 128
@ -132,6 +121,9 @@
#define PPS_BUFFER_SIZE 16
#endif//PPS_BUFFER_SIZE
#if !defined(MAX_MACROBLOCK_SIZE_IN_BYTE)
#define MAX_MACROBLOCK_SIZE_IN_BYTE 800 //3200*2/8
#endif
#if defined(NUM_SPATIAL_LAYERS_CONSTRAINT)
#define MAX_DEPENDENCY_LAYER MAX_SPATIAL_LAYER_NUM // Maximal dependency layer
@ -189,4 +181,15 @@ enum {
NON_AVC_REWRITE_ENHANCE_MB = 2
};
enum {
ENC_RETURN_SUCCESS = 0,
ENC_RETURN_MEMALLOCERR = 0x01, //will free memory and uninit
ENC_RETURN_UNSUPPORTED_PARA = 0x02, //unsupported setting
ENC_RETURN_UNEXPECTED = 0x04, //unexpected value
ENC_RETURN_CORRECTED = 0x08, //unexpected value but corrected by encoder
ENC_RETURN_INVALIDINPUT = 0x10, //invalid input
ENC_RETURN_MEMOVERFLOWFOUND = 0x20,
};
//TODO: need to complete the return checking in encoder and fill in more types if needed
#endif//WELS_CONSTANCE_H__

View File

@ -151,7 +151,7 @@ void WelsInitBGDFunc (SWelsFuncPtrList* pFuncList, const bool kbEnableBackground
* \return successful - 0; otherwise none 0 for failed
*/
int32_t InitFunctionPointers (SWelsFuncPtrList* pFuncList, SWelsSvcCodingParam* pParam, uint32_t uiCpuFlag) {
int32_t iReturn = 0;
int32_t iReturn = ENC_RETURN_SUCCESS;
/* Functionality utilization of CPU instructions dependency */
pFuncList->pfSetMemZeroSize8 = WelsSetMemZero_c; // confirmed_safe_unsafe_usage

View File

@ -140,7 +140,7 @@ int32_t ParamValidationExt (void* pParam) {
assert (pCodingParam != NULL);
if (NULL == pCodingParam)
return 1;
return ENC_RETURN_INVALIDINPUT;
if (pCodingParam->iSpatialLayerNum < 1 || pCodingParam->iSpatialLayerNum > MAX_DEPENDENCY_LAYER) {
#if defined (_DEBUG)
@ -148,7 +148,7 @@ int32_t ParamValidationExt (void* pParam) {
pCodingParam->iSpatialLayerNum);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (pCodingParam->iTemporalLayerNum < 1 || pCodingParam->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) {
@ -156,14 +156,14 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->iTemporalLayerNum: %d!\n",
pCodingParam->iTemporalLayerNum);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE) {
#if defined (_DEBUG)
fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!\n", pCodingParam->uiGopSize);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
@ -173,7 +173,7 @@ int32_t ParamValidationExt (void* pParam) {
"ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!\n",
pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize - 1)) != 0) {
@ -181,7 +181,7 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!\n",
pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
@ -213,7 +213,7 @@ int32_t ParamValidationExt (void* pParam) {
#if defined (_DEBUG)
fprintf (stderr, "ParamValidationExt(), invalid %d x %d in dependency layer settings!\n", kiPicWidth, kiPicHeight);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if ((kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0) {
#if defined (_DEBUG)
@ -221,14 +221,14 @@ int32_t ParamValidationExt (void* pParam) {
"ParamValidationExt(), in layer #%d iWidth x iHeight(%d x %d) both should be multiple of 16, can not support with arbitrary size currently!\n",
i, kiPicWidth, kiPicHeight);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (fDlp->sSliceCfg.uiSliceMode >= SM_RESERVED) {
#if defined (_DEBUG)
fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", fDlp->sSliceCfg.uiSliceMode);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
//check pSlice settings under multi-pSlice
@ -257,7 +257,7 @@ int32_t ParamValidationExt (void* pParam) {
#if defined (_DEBUG)
fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sSliceCfg.sSliceArgument.uiSliceNum);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (fDlp->sSliceCfg.sSliceArgument.uiSliceNum == 1) {
#if defined (_DEBUG)
@ -281,7 +281,7 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
fDlp->sSliceCfg.sSliceArgument.uiSliceMbNum[0]);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
// considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) {
@ -303,7 +303,7 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
fDlp->sSliceCfg.sSliceArgument.uiSliceMbNum[0]);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (!CheckRasterMultiSliceSetting (iMbNumInFrame, &fDlp->sSliceCfg.sSliceArgument)) { // verify interleave mode settings
@ -311,7 +311,7 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
fDlp->sSliceCfg.sSliceArgument.uiSliceMbNum[0]);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (fDlp->sSliceCfg.sSliceArgument.uiSliceNum <= 0
|| fDlp->sSliceCfg.sSliceArgument.uiSliceNum > iMaxSliceNum) { // verify interleave mode settings
@ -319,7 +319,7 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!\n",
fDlp->sSliceCfg.sSliceArgument.uiSliceNum);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (fDlp->sSliceCfg.sSliceArgument.uiSliceNum == 1) {
#if defined (_DEBUG)
@ -353,7 +353,7 @@ int32_t ParamValidationExt (void* pParam) {
#if defined (_DEBUG)
fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX!\n", iMbHeight);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
fDlp->sSliceCfg.sSliceArgument.uiSliceNum = iMbHeight;
@ -361,14 +361,14 @@ int32_t ParamValidationExt (void* pParam) {
#if defined (_DEBUG)
fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sSliceCfg.sSliceArgument.uiSliceNum);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (!CheckRowMbMultiSliceSetting (iMbWidth, &fDlp->sSliceCfg.sSliceArgument)) { // verify interleave mode settings
#if defined (_DEBUG)
fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
fDlp->sSliceCfg.sSliceArgument.uiSliceMbNum[0]);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
}
break;
@ -380,7 +380,7 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), invalid iSliceSize (%d) settings!\n",
fDlp->sSliceCfg.sSliceArgument.uiSliceSizeConstraint);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
// considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
if (iMbWidth * iMbHeight <= MIN_NUM_MB_PER_SLICE) {
@ -396,7 +396,7 @@ int32_t ParamValidationExt (void* pParam) {
fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n",
pCodingParam->sDependencyLayers[0].sSliceCfg.uiSliceMode);
#endif//#if _DEBUG
return 1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
break;
@ -1322,7 +1322,7 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx) {
while (iIndex < pParam->iSpatialLayerNum) {
SDLayerParam* fDlp = &pParam->sDependencyLayers[iIndex];
fCompressRatioThr = COMPRESS_RATIO_DECIDED_BY_RESOLUTION (fDlp->iFrameWidth, fDlp->iFrameHeight);
fCompressRatioThr = COMPRESS_RATIO_THR;
iLayerBsSize = WELS_ROUND (((3 * fDlp->iFrameWidth * fDlp->iFrameHeight) >> 1) * fCompressRatioThr);
iLayerBsSize = WELS_ALIGN (iLayerBsSize, 4); // 4 bytes alinged
@ -1339,9 +1339,9 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx) {
// Output
(*ppCtx)->pOut = (SWelsEncoderOutput*)pMa->WelsMalloc (sizeof (SWelsEncoderOutput), "SWelsEncoderOutput");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pOut), FreeMemorySvc (ppCtx))
(*ppCtx)->pOut->pBsBuffer = (uint8_t*)pMa->WelsMalloc (iCountBsLen, "pOut->pBsBuffer");
(*ppCtx)->pOut->pBsBuffer = (uint8_t*)pMa->WelsMalloc (iCountBsLen, "pOut->pBsBuffer");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pOut->pBsBuffer), FreeMemorySvc (ppCtx))
(*ppCtx)->pOut->uiSize = iCountBsLen;
(*ppCtx)->pOut->uiSize = iCountBsLen;
(*ppCtx)->pOut->sNalList = (SWelsNalRaw*)pMa->WelsMalloc (iCountNals * sizeof (SWelsNalRaw), "pOut->sNalList");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pOut->sNalList), FreeMemorySvc (ppCtx))
(*ppCtx)->pOut->iCountNals = iCountNals;
@ -1349,10 +1349,10 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx) {
#ifdef MT_ENABLED
if (pParam->iMultipleThreadIdc > 1) {
(*ppCtx)->pFrameBs = (uint8_t*)pMa->WelsMalloc (iCountBsLen + (iTargetSpatialBsSize * ((*ppCtx)->iMaxSliceCount - 1)),
"pFrameBs");
const int32_t iTotalLength = iCountBsLen + (iTargetSpatialBsSize * ((*ppCtx)->iMaxSliceCount - 1));
(*ppCtx)->pFrameBs = (uint8_t*)pMa->WelsMalloc (iTotalLength, "pFrameBs");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pFrameBs), FreeMemorySvc (ppCtx))
(*ppCtx)->iFrameBsSize = iCountBsLen * (*ppCtx)->iMaxSliceCount;
(*ppCtx)->iFrameBsSize = iTotalLength;
} else
#endif//MT_ENABLED
{
@ -2081,7 +2081,7 @@ int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPar
#if defined(MEMORY_MONITOR)
WelsLog (pCtx, WELS_LOG_INFO, "WelsInitEncoderExt() exit, overall memory usage: %llu bytes\n",
static_cast<unsigned long long> (sizeof (sWelsEncCtx) /* requested size from malloc() or new operator */
+ pCtx->pMemAlign->WelsGetMemoryUsage()) /* requested size from CMemoryAlign::WelsMalloc() */
+ pCtx->pMemAlign->WelsGetMemoryUsage()) /* requested size from CMemoryAlign::WelsMalloc() */
);
#endif//MEMORY_MONITOR
@ -2749,7 +2749,7 @@ void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable,
/*!
* \brief write all parameter sets introduced in SVC extension
* \return size in bytes of bitstream wrote
* \return writing results, success or error
*/
int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal) {
int32_t iSize = 0;
@ -2757,9 +2757,11 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
int32_t iIdx = 0;
int32_t iId = 0;
int32_t iCountNal = 0;
int32_t iNalLength = 0;
int32_t iReturn = ENC_RETURN_SUCCESS;
if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal)
return 0;
return ENC_RETURN_UNEXPECTED;
/* write all SPS */
iIdx = 0;
@ -2804,11 +2806,15 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
WelsUnloadNal (pCtx->pOut);
}
pNalLen[iCountNal] = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer,
&pNalLen[iCountNal]);
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
pCtx->iFrameBsSize - pCtx->iPosBsBuffer,//available buffer to be written, so need to substract the used length
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&iNalLength);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
pNalLen[iCountNal] =iNalLength;
pCtx->iPosBsBuffer += pNalLen[iCountNal];
iSize += pNalLen[iCountNal];
pCtx->iPosBsBuffer += iNalLength;
iSize += iNalLength;
++ iIdx;
++ iCountNal;
@ -2829,11 +2835,14 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
WelsWritePpsSyntax (&pCtx->pPPSArray[iIdx], &pCtx->pOut->sBsWrite, & (pCtx->sPSOVector));
WelsUnloadNal (pCtx->pOut);
pNalLen[iCountNal] = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer,
&pNalLen[iCountNal]);
pCtx->iPosBsBuffer += pNalLen[iCountNal];
iSize += pNalLen[iCountNal];
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&iNalLength);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
pNalLen[iCountNal] = iNalLength;
pCtx->iPosBsBuffer += iNalLength;
iSize += iNalLength;
++ iIdx;
++ iCountNal;
@ -2841,7 +2850,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
*pNumNal = iCountNal;
return iSize;
return ENC_RETURN_SUCCESS;
}
static inline int32_t AddPrefixNal (sWelsEncCtx* pCtx,
@ -2849,8 +2858,10 @@ static inline int32_t AddPrefixNal (sWelsEncCtx* pCtx,
int32_t* pNalLen,
int32_t* pNalIdxInLayer,
const EWelsNalUnitType keNalType,
const EWelsNalRefIdc keNalRefIdc) {
int32_t iPayloadSize = 0;
const EWelsNalRefIdc keNalRefIdc,
int32_t& iPayloadSize) {
int32_t iReturn = ENC_RETURN_SUCCESS;
iPayloadSize = 0;
if (keNalRefIdc != NRI_PRI_LOWEST) {
WelsLoadNal (pCtx->pOut, NAL_UNIT_PREFIX, keNalRefIdc);
@ -2859,10 +2870,13 @@ static inline int32_t AddPrefixNal (sWelsEncCtx* pCtx,
WelsUnloadNal (pCtx->pOut);
iPayloadSize = WelsEncodeNalExt (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&pNalLen[*pNalIdxInLayer]);
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->iFrameBsSize-pCtx->iPosBsBuffer,
pCtx->pFrameBs+pCtx->iPosBsBuffer,
&pNalLen[*pNalIdxInLayer]);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
iPayloadSize = pNalLen[*pNalIdxInLayer];
pCtx->iPosBsBuffer += iPayloadSize;
pLayerBsInfo->iNalLengthInByte[*pNalIdxInLayer] = iPayloadSize;
@ -2873,10 +2887,13 @@ static inline int32_t AddPrefixNal (sWelsEncCtx* pCtx,
// No need write any syntax of prefix NAL Unit RBSP here
WelsUnloadNal (pCtx->pOut);
iPayloadSize = WelsEncodeNalExt (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&pNalLen[*pNalIdxInLayer]);
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->iFrameBsSize-pCtx->iPosBsBuffer,
pCtx->pFrameBs+pCtx->iPosBsBuffer,
&pNalLen[*pNalIdxInLayer]);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
iPayloadSize = pNalLen[*pNalIdxInLayer];
pCtx->iPosBsBuffer += iPayloadSize;
pLayerBsInfo->iNalLengthInByte[*pNalIdxInLayer] = iPayloadSize;
@ -2884,16 +2901,16 @@ static inline int32_t AddPrefixNal (sWelsEncCtx* pCtx,
(*pNalIdxInLayer) ++;
}
return iPayloadSize;
return ENC_RETURN_SUCCESS;
}
int32_t WritePadding (sWelsEncCtx* pCtx, int32_t iLen) {
int32_t WritePadding (sWelsEncCtx* pCtx, int32_t iLen, int32_t& iSize) {
int32_t i = 0;
int32_t iNal = 0;
SBitStringAux* pBs = NULL;
int32_t iNalLen;
int32_t iSize = 0;
iSize = 0;
iNal = pCtx->pOut->iNalIndex;
pBs = &pCtx->pOut->sBsWrite; // SBitStringAux instance for non VCL NALs decoding
@ -2903,7 +2920,7 @@ int32_t WritePadding (sWelsEncCtx* pCtx, int32_t iLen) {
"[RC] paddingcal pBuffer overflow, bufferlen=%lld, paddinglen=%d, iNalIdx= %d, iCountNals= %d\n",
static_cast<long long int> (pBs->pBufEnd - pBs->pBufPtr), iLen, iNal, pCtx->pOut->iCountNals);
#endif
return 0;
return ENC_RETURN_MEMOVERFLOWFOUND;
}
WelsLoadNal (pCtx->pOut, NAL_UNIT_FILLER_DATA, NRI_PRI_LOWEST);
@ -2917,12 +2934,16 @@ int32_t WritePadding (sWelsEncCtx* pCtx, int32_t iLen) {
BsFlush (pBs);
WelsUnloadNal (pCtx->pOut);
iNalLen = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer, &iNalLen);
int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
pCtx->iFrameBsSize-pCtx->iPosBsBuffer,
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&iNalLen);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
pCtx->iPosBsBuffer += iNalLen;
iSize += iNalLen;
return iSize;
return ENC_RETURN_SUCCESS;
}
/*
@ -3012,7 +3033,8 @@ int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) {
pLayerBsInfo->pBsBuf = pCtx->pFrameBs;
InitBits (&pCtx->pOut->sBsWrite, pCtx->pOut->pBsBuffer, pCtx->pOut->uiSize);
WelsWriteParameterSets (pCtx, &iNalLen[0], &iCountNal);
int32_t iReturn = WelsWriteParameterSets (pCtx, &iNalLen[0], &iCountNal);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
pLayerBsInfo->uiPriorityId = 0;
pLayerBsInfo->uiSpatialId = 0;
@ -3031,7 +3053,7 @@ int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) {
WelsEmms();
#endif //X86_ASM
return 0;
return ENC_RETURN_SUCCESS;
}
/*!
@ -3082,18 +3104,22 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
int32_t i = 0, j = 0, k = 0;
#endif//_DEBUG
pCtx->iEncoderError = ENC_RETURN_SUCCESS;
pFbi->iLayerNum = 0; // for initialization
// perform csc/denoise/downsample/padding, generate spatial layers
iSpatialNum = pCtx->pVpp->BuildSpatialPicList (pCtx, ppSrcList, iConfiguredLayerNum);
if (iSpatialNum < 1) { // skip due to temporal layer settings (different frame rate)
++ pCtx->iCodingIndex;
return WELS_FRAME_TYPE_SKIP;
pFbi->eOutputFrameType = WELS_FRAME_TYPE_SKIP;
return ENC_RETURN_SUCCESS;
}
eFrameType = DecideFrameType (pCtx, iSpatialNum);
if (eFrameType == WELS_FRAME_TYPE_SKIP)
return eFrameType;
if (eFrameType == WELS_FRAME_TYPE_SKIP) {
pFbi->eOutputFrameType = eFrameType;
return ENC_RETURN_SUCCESS;
}
InitFrameCoding (pCtx, eFrameType);
@ -3108,7 +3134,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
//if ( pSvcParam->bEnableSSEI )
// write parameter sets bitstream here
WelsWriteParameterSets (pCtx, &iNalLen[0], &iCountNal);
pCtx->iEncoderError = WelsWriteParameterSets (pCtx, &iNalLen[0], &iCountNal);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
pLayerBsInfo->uiPriorityId = 0;
pLayerBsInfo->uiSpatialId = 0;
@ -3177,7 +3204,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
if (iLayerNum >= MAX_LAYER_NUM_OF_FRAME) { // check available layer_bs_info writing as follows
WelsLog (pCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d)!", iLayerNum,
MAX_LAYER_NUM_OF_FRAME);
return -1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
iNalIdxInLayer = 0;
@ -3215,9 +3242,11 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
if (!WelsBuildRefList (pCtx, pCtx->iPOC)) {
// Force coding IDR as followed
ForceCodingIDR (pCtx);
WelsLog (pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsBuildRefList failed for P frames, pCtx->iNumRef0= %d.\n",
WelsLog (pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsBuildRefList failed for P frames, pCtx->iNumRef0= %d. ForceCodingIDR!\n",
pCtx->iNumRef0);
return -1;
pFbi->eOutputFrameType = WELS_FRAME_TYPE_IDR;
pCtx->iEncoderError = ENC_RETURN_CORRECTED;
return ENC_RETURN_CORRECTED;
}
#ifdef LONG_TERM_REF_DUMP
dump_ref (pCtx);
@ -3230,23 +3259,32 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
PreprocessSliceCoding (pCtx); // MUST be called after pfWelsRcPictureInit() and WelsInitCurrentLayer()
iLayerSize = 0;
if (SM_SINGLE_SLICE == param_d->sSliceCfg.uiSliceMode) { // only one slice within a sQualityStat layer
int32_t iSliceSize = 0;
int32_t iPayloadSize = 0;
if (pCtx->bNeedPrefixNalFlag) {
iLayerSize += AddPrefixNal (pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc);
pCtx->iEncoderError = AddPrefixNal (pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc, iPayloadSize);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
iLayerSize += iPayloadSize;
}
WelsLoadNal (pCtx->pOut, eNalType, eNalRefIdc);
WelsCodeOneSlice (pCtx, 0, eNalType);
pCtx->iEncoderError = WelsCodeOneSlice (pCtx, 0, eNalType);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
WelsUnloadNal (pCtx->pOut);
iSliceSize = WelsEncodeNalExt (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&iNalLen[iNalIdxInLayer]);
pCtx->iEncoderError = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->iFrameBsSize-pCtx->iPosBsBuffer,
pCtx->pFrameBs+pCtx->iPosBsBuffer,
&iNalLen[iNalIdxInLayer]);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
iSliceSize = iNalLen[iNalIdxInLayer];
iLayerSize += iSliceSize;
pCtx->iPosBsBuffer += iSliceSize;
pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
@ -3265,7 +3303,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
#endif//MT_ENABLED
{
const int32_t kiLastMbInFrame = pCtx->pCurDqLayer->pSliceEncCtx->iMbNumInFrame;
WelsCodeOnePicPartition (pCtx, pLayerBsInfo, &iNalIdxInLayer, &iLayerSize, 0, kiLastMbInFrame, 0);
pCtx->iEncoderError = WelsCodeOnePicPartition (pCtx, pLayerBsInfo, &iNalIdxInLayer, &iLayerSize, 0, kiLastMbInFrame, 0);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
} else {
//other multi-slice uiSliceMode
#if defined(MT_ENABLED)
@ -3283,13 +3322,13 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
WelsLog (pCtx, WELS_LOG_ERROR,
"WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d) at iDid= %d uiSliceMode= %d, iSliceCount= %d!",
iLayerNum, MAX_LAYER_NUM_OF_FRAME, iCurDid, param_d->sSliceCfg.uiSliceMode, iSliceCount);
return -1;
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (iSliceCount <= 1) {
WelsLog (pCtx, WELS_LOG_ERROR,
"WelsEncoderEncodeExt(), iSliceCount(%d) from GetCurrentSliceNum() is untrusted due stack/heap crupted!\n",
iSliceCount);
return -1;
return ENC_RETURN_UNEXPECTED;
}
if (pSvcParam->iCountThreadsNum >= iSliceCount) { //THREAD_FULLY_FIRE_MODE
@ -3313,13 +3352,15 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
WelsLog (pCtx, WELS_LOG_ERROR,
"[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n",
err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sSliceCfg.uiSliceMode, pSvcParam->iMultipleThreadIdc);
return -1;
return ENC_RETURN_UNEXPECTED;
}
WelsMultipleEventsWaitAllBlocking (iSliceCount, &pCtx->pSliceThreading->pSliceCodedEvent[0]);
// all slices are finished coding here
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
// append exclusive slice 0 bs to pFrameBs
#if defined(PACKING_ONE_SLICE_PER_LAYER)
iLayerSize = pCtx->iPosBsBuffer - iOrgSlicePos[0];
@ -3372,7 +3413,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
WelsLog (pCtx, WELS_LOG_ERROR,
"[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n",
err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sSliceCfg.uiSliceMode, pSvcParam->iMultipleThreadIdc);
return -1;
return ENC_RETURN_UNEXPECTED;
}
iIndexOfSliceToBeCoded = iNumThreadsRunning;
@ -3408,6 +3449,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
// TODO for pthread platforms
// alternate implementation using blocking due non-blocking with timeout mode not support at wels thread lib, tune back if available
WelsMultipleEventsWaitAllBlocking (iNumThreadsRunning, &pCtx->pSliceThreading->pSliceCodedEvent[0]);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
if (iIndexOfSliceToBeCoded < iSliceCount) {
int32_t iThreadIdx = 0;
// pick up succeeding slices for threading if left
@ -3464,10 +3506,11 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
WelsLog (pCtx, WELS_LOG_ERROR,
"[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n",
err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sSliceCfg.uiSliceMode, pSvcParam->iMultipleThreadIdc);
return -1;
return ENC_RETURN_UNEXPECTED;
}
WelsMultipleEventsWaitAllBlocking (kiPartitionCnt, &pCtx->pSliceThreading->pSliceCodedEvent[0]);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
#if defined(PACKING_ONE_SLICE_PER_LAYER)
iSliceCount = PostProcDynamicSlicingBsWriting (pCtx, pLayerBsInfo, &iLayerSize, kiPartitionCnt);
@ -3486,19 +3529,26 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
iSliceCount = GetCurrentSliceNum (pCtx->pCurDqLayer->pSliceEncCtx);
while (iSliceIdx < iSliceCount) {
int32_t iSliceSize = 0;
int32_t iPayloadSize = 0;
if (bNeedPrefix) {
iLayerSize += AddPrefixNal (pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc);
pCtx->iEncoderError = AddPrefixNal (pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc, iPayloadSize);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
iLayerSize += iPayloadSize;
}
WelsLoadNal (pCtx->pOut, eNalType, eNalRefIdc);
WelsCodeOneSlice (pCtx, iSliceIdx, eNalType);
pCtx->iEncoderError = WelsCodeOneSlice (pCtx, iSliceIdx, eNalType);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
WelsUnloadNal (pCtx->pOut);
iSliceSize = WelsEncodeNalExt (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&iNalLen[iNalIdxInLayer]);
pCtx->iEncoderError = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->iFrameBsSize-pCtx->iPosBsBuffer,
pCtx->pFrameBs+pCtx->iPosBsBuffer, &iNalLen[iNalIdxInLayer]);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
iSliceSize = iNalLen[iNalIdxInLayer];
pCtx->iPosBsBuffer += iSliceSize;
iLayerSize += iSliceSize;
pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize;
@ -3542,8 +3592,10 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
if (!WelsUpdateRefList (pCtx)) {
// Force coding IDR as followed
ForceCodingIDR (pCtx);
WelsLog (pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsUpdateRefList failed.\n");
return -1;
WelsLog (pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsUpdateRefList failed. ForceCodingIDR!\n");
//the above is to set the next frame to be IDR
pFbi->eOutputFrameType = eFrameType;
return ENC_RETURN_CORRECTED;
}
}
@ -3648,14 +3700,16 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
if (pSvcParam->iPaddingFlag && pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize > 0) {
const int32_t kiPaddingNalSize = WritePadding (pCtx, pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize);
int32_t iPaddingNalSize = 0;
pCtx->iEncoderError = WritePadding (pCtx, pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize, iPaddingNalSize);
WELS_VERIFY_RETURN_IFNEQ(pCtx->iEncoderError, ENC_RETURN_SUCCESS)
#if GOM_TRACE_FLAG
WelsLog (pCtx, WELS_LOG_INFO, "[RC] encoding_qp%d Padding: %d\n", pCtx->uiDependencyId,
pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize);
#endif
if (kiPaddingNalSize <= 0)
return -1;
if (iPaddingNalSize <= 0)
return ENC_RETURN_UNEXPECTED;
pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingBitrateStat += pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize;
@ -3667,7 +3721,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
pLayerBsInfo->uiQualityId = 0;
pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
pLayerBsInfo->iNalCount = 1;
pLayerBsInfo->iNalLengthInByte[0] = kiPaddingNalSize;
pLayerBsInfo->iNalLengthInByte[0] = iPaddingNalSize;
++ pLayerBsInfo;
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
++ iLayerNum;
@ -3697,7 +3751,10 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
if( pCtx->pVpp->UpdateSpatialPictures(pCtx, pSvcParam, iCurTid, d_idx) != 0 ){
ForceCodingIDR(pCtx);
return -1;
WelsLog (pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), Logic Error Found in temporal level. ForceCodingIDR!\n");
//the above is to set the next frame IDR
pFbi->eOutputFrameType = eFrameType;
return ENC_RETURN_CORRECTED;
}
if (pSvcParam->bEnableLongTermReference && ((pCtx->pLtr[pCtx->uiDependencyId].bLTRMarkingFlag
@ -3734,7 +3791,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
WelsEmms();
#endif //X86_ASM
return eFrameType;
pFbi->eOutputFrameType = eFrameType;
return ENC_RETURN_SUCCESS;
}
/*!
@ -3743,7 +3801,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, void* pDst, const SSourcePictur
*/
int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewParam) {
SWelsSvcCodingParam* pOldParam = NULL;
int32_t iReturn = 0;
int32_t iReturn = ENC_RETURN_SUCCESS;
int8_t iIndexD = 0;
bool bNeedReset = false;
@ -3751,7 +3809,7 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
/* Check validation in new parameters */
iReturn = ParamValidationExt (pNewParam);
if (iReturn != 0) return iReturn;
if (iReturn != ENC_RETURN_SUCCESS) return iReturn;
pOldParam = (*ppCtx)->pSvcParam;
@ -3942,6 +4000,7 @@ int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
const EWelsNalUnitType keNalType = pCtx->eNalType;
const EWelsNalRefIdc keNalRefIdc = pCtx->eNalPriority;
const bool kbNeedPrefix = pCtx->bNeedPrefixNalFlag;
int32_t iReturn = ENC_RETURN_SUCCESS;
//init
{
@ -3953,25 +4012,33 @@ int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
while (iAnyMbLeftInPartition > 0) {
int32_t iSliceSize = 0;
int32_t iPayloadSize = 0;
if (iSliceIdx >= pSliceCtx->iMaxSliceNumConstraint) { // insufficient memory in pSliceInLayer[]
// TODO: need exception handler for not large enough of MAX_SLICES_NUM related memory usage
// No idea about its solution due MAX_SLICES_NUM is fixed lenght in relevent pData structure
return 1;
return ENC_RETURN_MEMALLOCERR;
}
if (kbNeedPrefix) {
iPartitionBsSize += AddPrefixNal (pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, keNalType, keNalRefIdc);
iReturn = AddPrefixNal (pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, keNalType, keNalRefIdc, iPayloadSize);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
iPartitionBsSize += iPayloadSize;
}
WelsLoadNal (pCtx->pOut, keNalType, keNalRefIdc);
WelsCodeOneSlice (pCtx, iSliceIdx, keNalType);
iReturn=WelsCodeOneSlice (pCtx, iSliceIdx, keNalType);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
WelsUnloadNal (pCtx->pOut);
iSliceSize = WelsEncodeNalExt (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->pFrameBs + pCtx->iPosBsBuffer,
&iNalLen[iNalIdxInLayer]);
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
&pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
pCtx->iFrameBsSize-pCtx->iPosBsBuffer,
pCtx->pFrameBs+pCtx->iPosBsBuffer,
&iNalLen[iNalIdxInLayer]);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
iSliceSize = iNalLen[iNalIdxInLayer];
pCtx->iPosBsBuffer += iSliceSize;
iPartitionBsSize += iSliceSize;
pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize;
@ -4001,6 +4068,6 @@ int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
pLayerBsInfo->uiPriorityId = 0;
pLayerBsInfo->iNalCount = iNalIdxInLayer;
return 0;
return ENC_RETURN_SUCCESS;
}
} // namespace WelsSVCEnc

View File

@ -55,6 +55,7 @@ void WelsLoadNal (SWelsEncoderOutput* pEncoderOuput, const int32_t/*EWelsNalUnit
sNalHeader->uiForbiddenZeroBit = 0;
pRawNal->pRawData = &pWelsEncoderOuput->pBsBuffer[kiStartPos];
pRawNal->iStartPos = kiStartPos;
pRawNal->iPayloadSize = 0;
}
@ -68,7 +69,7 @@ void WelsUnloadNal (SWelsEncoderOutput* pEncoderOuput) {
const int32_t kiEndPos = (BsGetBitsPos (&pWelsEncoderOuput->sBsWrite) >> 3);
/* count payload size of pRawNal NAL */
pRawNal->iPayloadSize = &pWelsEncoderOuput->pBsBuffer[kiEndPos] - pRawNal->pRawData;
pRawNal->iPayloadSize = kiEndPos - pRawNal->iStartPos;
++ (*pIdx);
}
@ -89,6 +90,7 @@ void WelsLoadNalForSlice (SWelsSliceBs* pSliceBsIn, const int32_t/*EWelsNalUnitT
sNalHeader->uiForbiddenZeroBit = 0;
pRawNal->pRawData = &pSliceBs->pBsBuffer[kiStartPos];
pRawNal->iStartPos = kiStartPos;
pRawNal->iPayloadSize = 0;
}
@ -103,7 +105,7 @@ void WelsUnloadNalForSlice (SWelsSliceBs* pSliceBsIn) {
const int32_t kiEndPos = (BsGetBitsPos (pBitStringAux) >> 3);
/* count payload size of pRawNal NAL */
pRawNal->iPayloadSize = &pSliceBs->pBsBuffer[kiEndPos] - pRawNal->pRawData;
pRawNal->iPayloadSize = kiEndPos - pRawNal->iStartPos;
++ (*pIdx);
}
@ -114,25 +116,54 @@ void WelsUnloadNalForSlice (SWelsSliceBs* pSliceBsIn) {
* \param pDstLen length of pDst NAL output
* \param annexeb annexeb flag
* \param pRawNal pRawNal NAL pData
* \return length of pDst NAL
* \return ERRCODE
*/
int32_t WelsEncodeNal (SWelsNalRaw* pRawNal, void* pDst, int32_t* pDstLen) {
//TODO 1: refactor the calling of this func in multi-thread
//TODO 2: complete the realloc&copy
int32_t WelsEncodeNal (SWelsNalRaw* pRawNal, void* pNalHeaderExt, const int32_t kiDstBufferLen, void* pDst, int32_t* pDstLen) {
const bool kbNALExt = pRawNal->sNalExt.sNalHeader.eNalUnitType == NAL_UNIT_PREFIX
|| pRawNal->sNalExt.sNalHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_EXT;
int32_t iAssumedNeededLength = NAL_HEADER_SIZE+(kbNALExt?3:0)+pRawNal->iPayloadSize+1;
WELS_VERIFY_RETURN_IF(ENC_RETURN_UNEXPECTED, (iAssumedNeededLength<=0))
//since for each 0x000 need a 0x03, so the needed length will not exceed (iAssumeNeedLenth + iAssumeNeedLength/3), here adjust to >>1 to omit division
if (kiDstBufferLen < (iAssumedNeededLength + (iAssumedNeededLength>>1)) ) {
return ENC_RETURN_MEMALLOCERR;
//TODO: call the realloc&copy instead
}
uint8_t* pDstStart = (uint8_t*)pDst;
uint8_t* pDstPointer = pDstStart;
uint8_t* pSrcPointer = pRawNal->pRawData;
uint8_t* pSrcEnd = pRawNal->pRawData + pRawNal->iPayloadSize;
int32_t iZeroCount = 0;
int32_t iNalLength = 0;
*pDstLen = 0;
static const uint8_t kuiStartCodePrefix[4] = { 0, 0, 0, 1 };
static const uint8_t kuiStartCodePrefix[NAL_HEADER_SIZE] = { 0, 0, 0, 1 };
ST32 (pDstPointer, LD32 (&kuiStartCodePrefix[0]));
pDstPointer += 4;
/* NAL Unit Header */
*pDstPointer++ = (pRawNal->sNalExt.sNalHeader.uiNalRefIdc << 5) | (pRawNal->sNalExt.sNalHeader.eNalUnitType & 0x1f);
if (kbNALExt) {
SNalUnitHeaderExt* sNalExt = (SNalUnitHeaderExt*)pNalHeaderExt;
/* NAL UNIT Extension Header */
*pDstPointer++ = (0x80) |
(sNalExt->bIdrFlag << 6);
*pDstPointer++ = (0x80) |
(sNalExt->uiDependencyId << 4);
*pDstPointer++ = (sNalExt->uiTemporalId << 5) |
(sNalExt->bDiscardableFlag << 3) |
(0x07);
}
while (pSrcPointer < pSrcEnd) {
if (iZeroCount == 2 && *pSrcPointer <= 3) {
//add the code 03
*pDstPointer++ = 3;
iZeroCount = 0;
}
@ -149,73 +180,7 @@ int32_t WelsEncodeNal (SWelsNalRaw* pRawNal, void* pDst, int32_t* pDstLen) {
if (NULL != pDstLen)
*pDstLen = iNalLength;
return iNalLength;
}
/*!
* \brief encode a nal into a pBuffer for any type of NAL, involved WelsEncodeNal introduced in AVC
*
* \param pDst pDst NAL pData
* \param pDstLen length of pDst NAL output
* \param annexeb annexeb flag
* \param pRawNal pRawNal NAL pData
* \param pNalHeaderExt pointer of SNalUnitHeaderExt
*
* \return length of pDst NAL
*/
int32_t WelsEncodeNalExt (SWelsNalRaw* pRawNal, void* pNalHeaderExt, void* pDst, int32_t* pDstLen) {
SNalUnitHeaderExt* sNalExt = (SNalUnitHeaderExt*)pNalHeaderExt;
uint8_t* pDstStart = (uint8_t*)pDst;
uint8_t* pDstPointer = pDstStart;
uint8_t* pSrcPointer = pRawNal->pRawData;
uint8_t* pSrcEnd = pRawNal->pRawData + pRawNal->iPayloadSize;
int32_t iZeroCount = 0;
int32_t iNalLength = 0;
if (pRawNal->sNalExt.sNalHeader.eNalUnitType != NAL_UNIT_PREFIX
&& pRawNal->sNalExt.sNalHeader.eNalUnitType != NAL_UNIT_CODED_SLICE_EXT) {
return WelsEncodeNal (pRawNal, pDst, pDstLen);
}
/* FIXME this code doesn't check overflow */
static const uint8_t kuiStartCodePrefixExt[4] = { 0, 0, 0, 1 };
ST32 (pDstPointer, LD32 (&kuiStartCodePrefixExt[0]));
pDstPointer += 4;
/* NAL Unit Header */
*pDstPointer++ = (pRawNal->sNalExt.sNalHeader.uiNalRefIdc << 5) | (pRawNal->sNalExt.sNalHeader.eNalUnitType & 0x1f);
/* NAL UNIT Extension Header */
*pDstPointer++ = (0x80) |
(sNalExt->bIdrFlag << 6);
*pDstPointer++ = (0x80) |
(sNalExt->uiDependencyId << 4);
*pDstPointer++ = (sNalExt->uiTemporalId << 5) |
(sNalExt->bDiscardableFlag << 3) |
(0x07);
while (pSrcPointer < pSrcEnd) {
if (iZeroCount == 2 && *pSrcPointer <= 3) {
*pDstPointer++ = 3;
iZeroCount = 0;
}
if (*pSrcPointer == 0) {
++ iZeroCount;
} else {
iZeroCount = 0;
}
*pDstPointer++ = *pSrcPointer++;
}
/* count length of NAL Unit */
iNalLength = pDstPointer - pDstStart;
if (NULL != pDstLen)
*pDstLen = iNalLength;
return iNalLength;
return ENC_RETURN_SUCCESS;
}
/*!

View File

@ -347,6 +347,7 @@ int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPara
int32_t iIdx = 0;
int32_t iSliceBsBufferSize = 0;
int16_t iMaxSliceNum = 1;
int32_t iReturn = ENC_RETURN_SUCCESS;
if (NULL == ppCtx || NULL == pCodingParam || NULL == *ppCtx || iCountBsLen <= 0)
return 1;
@ -492,8 +493,6 @@ int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPara
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pCountBsSizeInPartition), FreeMemorySvc (ppCtx))
#endif//PACKING_ONE_SLICE_PER_LAYER
WelsMutexInit (&pSmt->mutexSliceNumUpdate);
(*ppCtx)->pSliceBs = (SWelsSliceBs*)pMa->WelsMalloc (sizeof (SWelsSliceBs) * iMaxSliceNum, "pSliceBs");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSliceBs), FreeMemorySvc (ppCtx))
@ -502,7 +501,7 @@ int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPara
iSliceBsBufferSize = iTargetSpatialBsSize;
iIdx = 0;
while (iIdx < iMaxSliceNum) {
pSliceB->pBsBuffer = (uint8_t*)pMa->WelsMalloc (iSliceBsBufferSize, "pSliceB->pBsBuffer");
pSliceB->pBsBuffer = (uint8_t*)pMa->WelsMalloc (iSliceBsBufferSize, "pSliceB->pBsBuffer");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSliceB->pBsBuffer), FreeMemorySvc (ppCtx))
pSliceB->uiSize = iSliceBsBufferSize;
@ -519,6 +518,12 @@ int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPara
++ iIdx;
}
iReturn = WelsMutexInit (&pSmt->mutexSliceNumUpdate);
WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx))
iReturn = WelsMutexInit (&(*ppCtx)->mutexEncoderError);
WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx))
#if defined(ENABLE_TRACE_MT)
WelsLog ((*ppCtx), WELS_LOG_INFO, "RequestMtResource(), iThreadNum=%d, iCountSliceNum= %d\n", pPara->iCountThreadsNum,
iMaxSliceNum);
@ -610,7 +615,9 @@ void ReleaseMtResource (sWelsEncCtx** ppCtx) {
pSmt->pCountBsSizeInPartition = NULL;
}
#endif//PACKING_ONE_SLICE_PER_LAYER
WelsMutexDestroy (&pSmt->mutexSliceNumUpdate);
WelsMutexDestroy (&((*ppCtx)->mutexEncoderError));
if (pSmt->pThreadPEncCtx != NULL) {
pMa->WelsFree (pSmt->pThreadPEncCtx, "pThreadPEncCtx");
@ -766,25 +773,32 @@ int32_t AppendSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, const int32
return iLayerSize;
}
int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer, const int32_t iSliceIdx) {
int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer, const int32_t iSliceIdx, int32_t& iSliceSize) {
SWelsSliceBs* pSliceBs = &pCtx->pSliceBs[iSliceIdx];
SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt;
uint8_t* pDst = pFrameBsBuffer;
int32_t pNalLen[2];
int32_t iSliceSize = 0;
const int32_t kiNalCnt = pSliceBs->iNalIndex;
int32_t iNalIdx = 0;
int32_t iNalSize = 0;
#if !defined(PACKING_ONE_SLICE_PER_LAYER)
const int32_t iFirstSlice = (iSliceIdx == 0);
int32_t iNalBase = iFirstSlice ? 0 : pLbi->iNalCount;
#else
int32_t iNalBase = 0;
#endif//!PACKING_ONE_SLICE_PER_LAYER
int32_t iReturn = ENC_RETURN_SUCCESS;
const int32_t kiWrittenLength = pCtx->iPosBsBuffer;
iSliceSize = 0;
while (iNalIdx < kiNalCnt) {
iSliceSize += WelsEncodeNalExt (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pDst, &pNalLen[iNalIdx]);
pDst += pNalLen[iNalIdx];
pLbi->iNalLengthInByte[iNalBase + iNalIdx] = pNalLen[iNalIdx];
iNalSize = 0;
iReturn = WelsEncodeNal (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pCtx->iFrameBsSize-kiWrittenLength-iSliceSize, pDst, &iNalSize);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
pNalLen[iNalIdx] = iNalSize;
iSliceSize += iNalSize;
pDst += iNalSize;
pLbi->iNalLengthInByte[iNalBase + iNalIdx] = iNalSize;
++ iNalIdx;
}
@ -811,31 +825,37 @@ int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFr
pLbi->iNalCount = kiNalCnt;
#endif//PACKING_ONE_SLICE_PER_LAYER
return iSliceSize;
return ENC_RETURN_SUCCESS;
}
int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pSliceBsBuf, const int32_t iSliceIdx) {
int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pSliceBsBuf, const int32_t iSliceIdx, int32_t& iSliceSize) {
SWelsSliceBs* pSliceBs = &pCtx->pSliceBs[iSliceIdx];
SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt;
uint8_t* pDst = pSliceBsBuf;
int32_t* pNalLen = &pSliceBs->iNalLen[0];
int32_t iSliceSize = 0;
const int32_t kiNalCnt = pSliceBs->iNalIndex;
int32_t iNalIdx = 0;
int32_t iNalSize = 0;
int32_t iReturn = ENC_RETURN_SUCCESS;
const int32_t kiWrittenLength = pSliceBs->sBsWrite.pBufPtr - pSliceBs->sBsWrite.pBuf;
iSliceSize = 0;
assert (kiNalCnt <= 2);
if (kiNalCnt > 2)
return 0;
while (iNalIdx < kiNalCnt) {
iSliceSize += WelsEncodeNalExt (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pDst, &pNalLen[iNalIdx]);
pDst += pNalLen[iNalIdx];
iNalSize = 0;
iReturn = WelsEncodeNal (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pSliceBs->uiSize-kiWrittenLength-iSliceSize, pDst, &iNalSize);
WELS_VERIFY_RETURN_IFNEQ(iReturn, ENC_RETURN_SUCCESS)
pNalLen[iNalIdx] = iNalSize;
iSliceSize += iNalSize;
pDst += iNalSize;
++ iNalIdx;
}
pSliceBs->uiBsPos = iSliceSize;
return iSliceSize;
return iReturn;
}
#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
@ -901,6 +921,7 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
bool bNeedPrefix = false;
EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0;
EWelsNalRefIdc eNalRefIdc = NRI_PRI_LOWEST;
int32_t iReturn = ENC_RETURN_SUCCESS;
if (NULL == pPrivateData)
WELS_THREAD_ROUTINE_RETURN (1);
@ -985,25 +1006,47 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
WelsLoadNalForSlice (pSliceBs, eNalType, eNalRefIdc);
WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
iReturn = WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
WelsUnloadNalForSlice (pSliceBs);
#if !defined(PACKING_ONE_SLICE_PER_LAYER)
if (0 == iSliceIdx) {
pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer;
iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx);
iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx, iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
pEncPEncCtx->iPosBsBuffer += iSliceSize;
} else
iSliceSize = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx);
{
iReturn = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx, iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
}
#else// PACKING_ONE_SLICE_PER_LAYER
if (0 == iSliceIdx) {
pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer;
iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx);
iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx, &iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
pEncPEncCtx->iPosBsBuffer += iSliceSize;
} else {
pLbi->pBsBuf = pSliceBs->bs + pSliceBs->uiBsPos;
iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx);
iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx, &iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
pSliceBs->uiBsPos += iSliceSize;
}
#endif//!PACKING_ONE_SLICE_PER_LAYER
@ -1101,7 +1144,11 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
WelsLoadNalForSlice (pSliceBs, eNalType, eNalRefIdc);
WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
iReturn = WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
WelsUnloadNalForSlice (pSliceBs);
@ -1109,20 +1156,38 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
if (0 == kiPartitionId) {
if (0 == iSliceIdx)
pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer;
iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer, iSliceIdx);
iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer, iSliceIdx, iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
pEncPEncCtx->iPosBsBuffer += iSliceSize;
} else
iSliceSize = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx);
{
iSliceSize = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx, iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
}
#else// PACKING_ONE_SLICE_PER_LAYER
pLbiPacking = pLbi + (iSliceIdx - kiPartitionId);
if (0 == kiPartitionId) {
pLbiPacking->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer;
iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx);
iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx, iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
pEncPEncCtx->iPosBsBuffer += iSliceSize;
} else {
pLbiPacking->pBsBuf = pSliceBs->bs + pSliceBs->uiBsPos;
iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx);
iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx, iSliceSize);
if (ENC_RETURN_SUCCESS!=iReturn) {
uiThrdRet = iReturn;
break;
}
pSliceBs->uiBsPos += iSliceSize;
}
pEncPEncCtx->pSliceThreading->pCountBsSizeInPartition[kiPartitionId] += iSliceSize;
@ -1197,6 +1262,11 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
WelsEventSignal (&pEncPEncCtx->pSliceThreading->pFinSliceCodingEvent[iEventIdx]); // notify to mother encoding threading
#endif//WIN32
//sync multi-threading error
WelsMutexLock (&pEncPEncCtx->mutexEncoderError);
if (uiThrdRet) pEncPEncCtx->iEncoderError |= uiThrdRet;
WelsMutexUnlock (&pEncPEncCtx->mutexEncoderError);
WELS_THREAD_ROUTINE_RETURN (uiThrdRet);
}
@ -1235,6 +1305,7 @@ int32_t CreateSliceThreads (sWelsEncCtx* pCtx) {
&pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0);
#endif//__GNUC__
#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
++ iIdx;
}
#if defined(ENABLE_TRACE_MT)

View File

@ -50,7 +50,7 @@
namespace WelsSVCEnc {
//#define ENC_TRACE
typedef void (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice);
typedef int32_t (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice);
typedef void (*PWelsSliceHeaderWriteFunc) (SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
int32_t* pPpsIdDelta);
@ -465,7 +465,7 @@ void OutputPMbWithoutConstructCsRsNoCopy (sWelsEncCtx* pCtx, SDqLayer* pDq, SSli
//encapsulate two kinds of reconstruction:
//first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)
//second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer)
void WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
SSliceCtx* pSliceCtx = pCurLayer->pSliceEncCtx;
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
@ -479,6 +479,7 @@ void WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
const int32_t kiSliceIdx = pSlice->uiSliceIdx;
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
SWelsMD sMd;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
for (; ;) {
iCurMbIdx = iNextMbIdx;
@ -494,7 +495,9 @@ void WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
WelsMdIntraMb (pEncCtx, &sMd, pCurMb, pMbCache);
UpdateNonZeroCountCache (pCurMb, pMbCache);
WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
pCurMb->uiSliceIdc = kiSliceIdx;
@ -511,10 +514,12 @@ void WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
break;
}
}
return ENC_RETURN_SUCCESS;
}
// Only for intra dynamic slicing
void WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
int32_t WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
SBitStringAux* pBs = pSlice->pSliceBsa;
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
SSliceCtx* pSliceCtx = pCurLayer->pSliceEncCtx;
@ -529,6 +534,7 @@ void WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + enc
const int32_t kiSliceIdx = pSlice->uiSliceIdx;
const int32_t kiPartitionId = (kiSliceIdx % pEncCtx->iActiveThreadsNum);
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
SWelsMD sMd;
SDynamicSlicingStack sDss;
@ -557,7 +563,9 @@ void WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + enc
sDss.uiBsStackCurBits = pBs->uiCurBits;
sDss.iBsStackLeftBits = pBs->iLeftBits;
WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
sDss.iCurrentPos = BsGetBitsPos (pBs);
@ -574,6 +582,7 @@ void WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + enc
break;
}
pCurMb->uiSliceIdc = kiSliceIdx;
#if defined(MB_TYPES_CHECK)
@ -593,12 +602,13 @@ void WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + enc
break;
}
}
return iEncReturn;
}
//encapsulate two kinds of reconstruction:
// first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)
// second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer)
void WelsPSliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag) { //pMd + encoding
int32_t WelsPSliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag) { //pMd + encoding
const SSliceHeaderExt* kpShExt = &pSlice->sSliceHeaderExt;
const SSliceHeader* kpSh = &kpShExt->sSliceHeader;
const int32_t kiSliceFirstMbXY = kpSh->iFirstMbInSlice;
@ -610,10 +620,10 @@ void WelsPSliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHigh
memset (&sMd.sMe, 0, sizeof (sMd.sMe));
//pMb loop
WelsMdInterMbLoop (pEncCtx, pSlice, &sMd, kiSliceFirstMbXY);
return WelsMdInterMbLoop (pEncCtx, pSlice, &sMd, kiSliceFirstMbXY);
}
void WelsPSliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag) {
int32_t WelsPSliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag) {
const SSliceHeaderExt* kpShExt = &pSlice->sSliceHeaderExt;
const SSliceHeader* kpSh = &kpShExt->sSliceHeader;
const int32_t kiSliceFirstMbXY = kpSh->iFirstMbInSlice;
@ -625,10 +635,10 @@ void WelsPSliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kb
memset (&sMd.sMe, 0, sizeof (sMd.sMe));
//mb loop
WelsMdInterMbLoopOverDynamicSlice (pEncCtx, pSlice, &sMd, kiSliceFirstMbXY);
return WelsMdInterMbLoopOverDynamicSlice (pEncCtx, pSlice, &sMd, kiSliceFirstMbXY);
}
void WelsCodePSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
int32_t WelsCodePSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
//pSlice-level init should be outside and before this function
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
@ -644,10 +654,10 @@ void WelsCodePSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
//initial pMd pointer
pEncCtx->pFuncList->pfInterMd = WelsMdInterMb;
}
WelsPSliceMdEnc (pEncCtx, pSlice, kbHighestSpatial);
return WelsPSliceMdEnc (pEncCtx, pSlice, kbHighestSpatial);
}
void WelsCodePOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
int32_t WelsCodePOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
//pSlice-level init should be outside and before this function
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
@ -663,22 +673,22 @@ void WelsCodePOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
//initial pMd pointer
pEncCtx->pFuncList->pfInterMd = WelsMdInterMb;
}
WelsPSliceMdEncDynamic (pEncCtx, pSlice, kbHighestSpatial);
return WelsPSliceMdEncDynamic (pEncCtx, pSlice, kbHighestSpatial);
}
// 1st index: 0: for P pSlice; 1: for I pSlice;
// 2nd index: 0: for non-dynamic pSlice; 1: for dynamic I pSlice;
const PWelsCodingSliceFunc g_pWelsSliceCoding[2][2] = {
PWelsCodingSliceFunc g_pWelsSliceCoding[2][2] = {
{ WelsCodePSlice, WelsCodePOverDynamicSlice }, // P SSlice
{ WelsISliceMdEnc, WelsISliceMdEncDynamic } // I SSlice
};
const PWelsSliceHeaderWriteFunc g_pWelsWriteSliceHeader[2] = { // 0: for base; 1: for ext;
PWelsSliceHeaderWriteFunc g_pWelsWriteSliceHeader[2] = { // 0: for base; 1: for ext;
WelsSliceHeaderWrite,
WelsSliceHeaderExtWrite
};
void WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const int32_t kiNalType) {
int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const int32_t kiNalType) {
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
SNalUnitHeaderExt* pNalHeadExt = &pCurLayer->sLayerInfo.sNalHeaderExt;
SSlice* pCurSlice = &pCurLayer->sLayerInfo.pSliceInLayer[kiSliceIdx];
@ -715,11 +725,15 @@ void WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const int
pCurSlice->uiLastMbQp = pCurLayer->sLayerInfo.pPpsP->iPicInitQp + pCurSlice->sSliceHeaderExt.sSliceHeader.iSliceQpDelta;
g_pWelsSliceCoding[pNalHeadExt->bIdrFlag][kiDynamicSliceFlag] (pEncCtx, pCurSlice);
int32_t iEncReturn = g_pWelsSliceCoding[pNalHeadExt->bIdrFlag][kiDynamicSliceFlag] (pEncCtx, pCurSlice);
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
BsRbspTrailingBits (pBs);
BsFlush (pBs);
return ENC_RETURN_SUCCESS;
}
//pFunc: UpdateMbNeighbourInfoForNextSlice()
@ -905,7 +919,7 @@ bool DynSlcJudgeSliceBoundaryStepBack (void* pCtx, void* pSlice, SSliceCtx* pSli
// pMb loop
///////////////
// for inter non-dynamic pSlice
void WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, const int32_t kiSliceFirstMbXY) {
int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, const int32_t kiSliceFirstMbXY) {
SWelsMD* pMd = (SWelsMD*)pWelsMd;
SBitStringAux* pBs = pSlice->pSliceBsa;
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
@ -923,6 +937,7 @@ void WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, con
uint16_t* pMvdCostTableInter = &pEncCtx->pMvdCostTableInter[kiMvdInterTableSize];
const int32_t kiSliceIdx = pSlice->uiSliceIdx;
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
for (;;) {
//point to current pMb
@ -958,7 +973,9 @@ void WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, con
} else {
BsWriteUE (pBs, iMbSkipRun);
iMbSkipRun = 0;
WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
}
//step (7): reconstruct current MB
@ -984,10 +1001,12 @@ void WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, con
if (iMbSkipRun) {
BsWriteUE (pBs, iMbSkipRun);
}
return iEncReturn;
}
// Only for inter dynamic slicing
void WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,
int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,
const int32_t kiSliceFirstMbXY) {
SWelsMD* pMd = (SWelsMD*)pWelsMd;
SBitStringAux* pBs = pSlice->pSliceBsa;
@ -1007,6 +1026,7 @@ void WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, vo
const int32_t kiSliceIdx = pSlice->uiSliceIdx;
const int32_t kiPartitionId = (kiSliceIdx % pEncCtx->iActiveThreadsNum);
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
int32_t iEncReturn = ENC_RETURN_SUCCESS;
SDynamicSlicingStack sDss;
sDss.iStartPos = BsGetBitsPos (pBs);
@ -1063,7 +1083,9 @@ void WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, vo
} else {
BsWriteUE (pBs, iMbSkipRun);
iMbSkipRun = 0;
WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
iEncReturn = WelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
if (ENC_RETURN_SUCCESS != iEncReturn)
return iEncReturn;
}
//DYNAMIC_SLICING_ONE_THREAD - MultiD
@ -1108,6 +1130,8 @@ void WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, vo
if (iMbSkipRun) {
BsWriteUE (pBs, iMbSkipRun);
}
return iEncReturn;
}
}//namespace WelsSVCEnc

View File

@ -208,8 +208,20 @@ void WelsSpatialWriteSubMbPred (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurM
}
}
int32_t CheckBitstreamBuffer(const uint8_t kuiSliceIdx, sWelsEncCtx* pEncCtx, SBitStringAux* pBs)
{
const int32_t iLeftLength = pBs->pBufEnd - pBs->pBufPtr - 1;
assert(iLeftLength > 0);
if (iLeftLength < MAX_MACROBLOCK_SIZE_IN_BYTE) {
return ENC_RETURN_MEMALLOCERR;
//TODO: call the realloc&copy instead
}
return ENC_RETURN_SUCCESS;
}
//============================Base Layer CAVLC Writing===============================
void WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {
int32_t WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {
SBitStringAux* pBs = pSlice->pSliceBsa;
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
@ -239,6 +251,9 @@ void WelsSpatialWriteMbSyn (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp +
pEncCtx->pCurDqLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset)];
}
/* Step 4: Check the left buffer */
return CheckBitstreamBuffer(pSlice->uiSliceIdx, pEncCtx, pBs);
}
void WelsWriteMbResidual (SMbCache* sMbCacheInfo, SMB* pCurMb, SBitStringAux* pBs) {

View File

@ -521,22 +521,32 @@ int CWelsH264SVCEncoder::EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSIn
int CWelsH264SVCEncoder::EncodeFrame2 (const SSourcePicture** pSrcPicList, int nSrcPicNum, SFrameBSInfo* pBsInfo) {
if (! (pSrcPicList && m_pEncContext && m_bInitialFlag)) {
if (!(pSrcPicList && m_pEncContext && m_bInitialFlag) || (nSrcPicNum<=0) ){
return videoFrameTypeInvalid;
}
int32_t iFrameTypeReturned = 0;
int32_t iFrameType = videoFrameTypeInvalid;
XMMREG_PROTECT_STORE(CWelsH264SVCEncoder);
const int32_t kiEncoderReturn = WelsEncoderEncodeExt (m_pEncContext, pBsInfo, pSrcPicList, nSrcPicNum);
XMMREG_PROTECT_LOAD(CWelsH264SVCEncoder);
if (nSrcPicNum > 0) {
XMMREG_PROTECT_STORE(CWelsH264SVCEncoder);
iFrameTypeReturned = WelsEncoderEncodeExt (m_pEncContext, pBsInfo, pSrcPicList, nSrcPicNum);
XMMREG_PROTECT_LOAD(CWelsH264SVCEncoder);
} else {
assert (0);
switch (kiEncoderReturn) {
case ENC_RETURN_MEMALLOCERR:
WelsUninitEncoderExt (&m_pEncContext);
return videoFrameTypeInvalid;
case ENC_RETURN_SUCCESS:
case ENC_RETURN_CORRECTED:
break;//continue processing
case ENC_RETURN_UNSUPPORTED_PARA:
case ENC_RETURN_UNEXPECTED:
return videoFrameTypeInvalid;
default:
WelsLog (m_pEncContext, WELS_LOG_ERROR, "unexpected return(%d) from WelsEncoderEncodeExt()!\n", kiEncoderReturn);
return videoFrameTypeInvalid;
}
iFrameTypeReturned = pBsInfo->eOutputFrameType;
switch (iFrameTypeReturned) {
case WELS_FRAME_TYPE_P:
iFrameType = videoFrameTypeP;
@ -832,7 +842,7 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
return cmInitParaError;
}
//adjust to valid range
m_pEncContext->pSvcParam->fMaxFrameRate = WELS_CLIP3 (iValue, MIN_FRAME_RATE, MAX_FRAME_RATE);
m_pEncContext->pSvcParam->fMaxFrameRate = WELS_CLIP3 (iValue, MIN_FRAME_RATE, MAX_FRAME_RATE);
WelsEncoderApplyFrameRate (m_pEncContext->pSvcParam);
}
break;