ref: e45e85947327631ad48137546a2b9549fb87f99b
parent: a921bc6589620e0e1dbd6d7d3e6eb09f505595db
author: sijchen <sijchen@cisco.com>
date: Thu Feb 20 09:50:04 EST 2014
Squashed merge from writenal_refactor2
--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -292,6 +292,7 @@
int iLayerNum;
SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME];
+ int eOutputFrameType;
} SFrameBSInfo, *PFrameBSInfo;
typedef struct Source_Picture_s {
--- a/codec/common/macros.h
+++ b/codec/common/macros.h
@@ -196,6 +196,18 @@
/*
* 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
* bCaseIf: negative condition to be verified
*/
--- a/codec/encoder/core/inc/encoder.h
+++ b/codec/encoder/core/inc/encoder.h
@@ -58,6 +58,13 @@
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*
* \return successful - 0; otherwise none 0 for failed
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -220,6 +220,11 @@
SStatSliceInfo sPerInfo;
#endif//STAT_OUTPUT
+ int32_t iEncoderError;
+#ifdef MT_ENABLED
+ WELS_MUTEX mutexEncoderError;
+#endif
+
} sWelsEncCtx/*, *PWelsEncCtx*/;
}
#endif//sWelsEncCtx_H__
--- a/codec/encoder/core/inc/nal_encap.h
+++ b/codec/encoder/core/inc/nal_encap.h
@@ -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 @@
SNalUnitHeaderExt sNalExt; // NAL header information
+int32_t iStartPos; //NAL start position in buffer
} SWelsNalRaw;
/*
@@ -125,22 +127,9 @@
* \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
--- a/codec/encoder/core/inc/slice_multi_threading.h
+++ b/codec/encoder/core/inc/slice_multi_threading.h
@@ -80,7 +80,7 @@
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__)
--- a/codec/encoder/core/inc/svc_encode_slice.h
+++ b/codec/encoder/core/inc/svc_encode_slice.h
@@ -72,18 +72,18 @@
//===================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 @@
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
--- a/codec/encoder/core/inc/svc_set_mb_syn_cavlc.h
+++ b/codec/encoder/core/inc/svc_set_mb_syn_cavlc.h
@@ -52,13 +52,12 @@
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
--- a/codec/encoder/core/inc/wels_const.h
+++ b/codec/encoder/core/inc/wels_const.h
@@ -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
@@ -188,5 +180,16 @@
AVC_REWRITE_ENHANCE_MB = 1,
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__
--- a/codec/encoder/core/src/encoder.cpp
+++ b/codec/encoder/core/src/encoder.cpp
@@ -151,7 +151,7 @@
* \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
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -140,7 +140,7 @@
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 @@
pCodingParam->iSpatialLayerNum);
#endif//#if _DEBUG
- return 1;
+ return ENC_RETURN_UNSUPPORTED_PARA;
}
if (pCodingParam->iTemporalLayerNum < 1 || pCodingParam->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) {
@@ -156,7 +156,7 @@
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) {
@@ -163,7 +163,7 @@
#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 @@
"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 @@
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 @@
#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,7 +221,7 @@
"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) {
@@ -228,7 +228,7 @@
#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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
#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,7 +361,7 @@
#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)
@@ -368,7 +368,7 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
#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 @@
#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 @@
/*!
* \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 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 @@
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,12 +2835,15 @@
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]);
+ 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;
- pCtx->iPosBsBuffer += pNalLen[iCountNal];
- iSize += pNalLen[iCountNal];
-
++ iIdx;
++ iCountNal;
}
@@ -2841,7 +2850,7 @@
*pNumNal = iCountNal;
- return iSize;
+ return ENC_RETURN_SUCCESS;
}
static inline int32_t AddPrefixNal (sWelsEncCtx* pCtx,
@@ -2849,8 +2858,10 @@
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 @@
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 @@
// 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 @@
(*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 @@
"[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 @@
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 @@
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 @@
WelsEmms();
#endif //X86_ASM
- return 0;
+ return ENC_RETURN_SUCCESS;
}
/*!
@@ -3082,6 +3104,7 @@
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
@@ -3088,12 +3111,15 @@
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 @@
//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 @@
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 @@
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 @@
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 @@
#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 @@
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,7 +3352,7 @@
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]);
@@ -3320,6 +3359,8 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
WelsEmms();
#endif //X86_ASM
- return eFrameType;
+ pFbi->eOutputFrameType = eFrameType;
+ return ENC_RETURN_SUCCESS;
}
/*!
@@ -3743,7 +3801,7 @@
*/
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 @@
/* 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 @@
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 @@
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 @@
pLayerBsInfo->uiPriorityId = 0;
pLayerBsInfo->iNalCount = iNalIdxInLayer;
- return 0;
+ return ENC_RETURN_SUCCESS;
}
} // namespace WelsSVCEnc
--- a/codec/encoder/core/src/nal_encap.cpp
+++ b/codec/encoder/core/src/nal_encap.cpp
@@ -55,6 +55,7 @@
sNalHeader->uiForbiddenZeroBit = 0;
pRawNal->pRawData = &pWelsEncoderOuput->pBsBuffer[kiStartPos];
+ pRawNal->iStartPos = kiStartPos;
pRawNal->iPayloadSize = 0;
}
@@ -68,7 +69,7 @@
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 @@
sNalHeader->uiForbiddenZeroBit = 0;
pRawNal->pRawData = &pSliceBs->pBsBuffer[kiStartPos];
+ pRawNal->iStartPos = kiStartPos;
pRawNal->iPayloadSize = 0;
}
@@ -103,7 +105,7 @@
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,9 +116,21 @@
* \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©
+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© instead
+ }
uint8_t* pDstStart = (uint8_t*)pDst;
uint8_t* pDstPointer = pDstStart;
uint8_t* pSrcPointer = pRawNal->pRawData;
@@ -123,8 +137,9 @@
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;
@@ -131,74 +146,24 @@
/* NAL Unit Header */
*pDstPointer++ = (pRawNal->sNalExt.sNalHeader.uiNalRefIdc << 5) | (pRawNal->sNalExt.sNalHeader.eNalUnitType & 0x1f);
- while (pSrcPointer < pSrcEnd) {
- if (iZeroCount == 2 && *pSrcPointer <= 3) {
- *pDstPointer++ = 3;
- iZeroCount = 0;
- }
- if (*pSrcPointer == 0) {
- ++ iZeroCount;
- } else {
- iZeroCount = 0;
- }
- *pDstPointer++ = *pSrcPointer++;
- }
+ if (kbNALExt) {
+ SNalUnitHeaderExt* sNalExt = (SNalUnitHeaderExt*)pNalHeaderExt;
- /* count length of NAL Unit */
- iNalLength = pDstPointer - pDstStart;
- if (NULL != pDstLen)
- *pDstLen = iNalLength;
+ /* NAL UNIT Extension Header */
+ *pDstPointer++ = (0x80) |
+ (sNalExt->bIdrFlag << 6);
- return iNalLength;
-}
+ *pDstPointer++ = (0x80) |
+ (sNalExt->uiDependencyId << 4);
-/*!
- * \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);
+ *pDstPointer++ = (sNalExt->uiTemporalId << 5) |
+ (sNalExt->bDiscardableFlag << 3) |
+ (0x07);
}
- /* 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) {
+ //add the code 03
*pDstPointer++ = 3;
iZeroCount = 0;
}
@@ -215,7 +180,7 @@
if (NULL != pDstLen)
*pDstLen = iNalLength;
- return iNalLength;
+ return ENC_RETURN_SUCCESS;
}
/*!
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -347,6 +347,7 @@
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 @@
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 @@
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 @@
++ 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 @@
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,14 +773,14 @@
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;
@@ -780,11 +787,18 @@
#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 @@
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 @@
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,7 +1006,11 @@
WelsLoadNalForSlice (pSliceBs, eNalType, eNalRefIdc);
- WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
+ iReturn = WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
+ if (ENC_RETURN_SUCCESS!=iReturn) {
+ uiThrdRet = iReturn;
+ break;
+ }
WelsUnloadNalForSlice (pSliceBs);
@@ -992,18 +1017,36 @@
#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 @@
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 @@
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 @@
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 @@
&pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0);
#endif//__GNUC__
#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
+
++ iIdx;
}
#if defined(ENABLE_TRACE_MT)
--- a/codec/encoder/core/src/svc_encode_slice.cpp
+++ b/codec/encoder/core/src/svc_encode_slice.cpp
@@ -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 @@
//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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
+
pCurMb->uiSliceIdc = kiSliceIdx;
#if defined(MB_TYPES_CHECK)
@@ -593,12 +602,13 @@
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 @@
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 @@
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 @@
//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 @@
//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 @@
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 @@
// 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 @@
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 @@
} 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 @@
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 @@
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 @@
} 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 @@
if (iMbSkipRun) {
BsWriteUE (pBs, iMbSkipRun);
}
+
+ return iEncReturn;
}
}//namespace WelsSVCEnc
--- a/codec/encoder/core/src/svc_set_mb_syn_cavlc.cpp
+++ b/codec/encoder/core/src/svc_set_mb_syn_cavlc.cpp
@@ -208,8 +208,20 @@
}
}
+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© 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 @@
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) {
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -521,22 +521,32 @@
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 @@
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;