Squashed merge from writenal_refactor2
This commit is contained in:
parent
a921bc6589
commit
e45e859473
@ -292,6 +292,7 @@ typedef struct {
|
||||
int iLayerNum;
|
||||
SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME];
|
||||
|
||||
int eOutputFrameType;
|
||||
} SFrameBSInfo, *PFrameBSInfo;
|
||||
|
||||
typedef struct Source_Picture_s {
|
||||
|
@ -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
|
||||
|
@ -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*
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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__)
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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©
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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© 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) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user