Merge pull request #1802 from sijchen/savc50

[Encoder] fix for in-middle changing simulcast avc setting
This commit is contained in:
ruil2 2015-02-06 14:21:47 +08:00
commit 296ab4d490
4 changed files with 100 additions and 70 deletions

View File

@ -243,6 +243,30 @@ typedef struct TagWelsEncCtx {
bool bDependencyRecFlag[MAX_DEPENDENCY_LAYER];
bool bRecFlag;
#endif
uint32_t GetNeededSpsNum() {
if (0 == sPSOVector.uiNeededSpsNum) {
sPSOVector.uiNeededSpsNum = ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) :
((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1)));
}
return sPSOVector.uiNeededSpsNum;
}
uint32_t GetNeededSubsetSpsNum() {
if (0 == sPSOVector.uiNeededSubsetSpsNum) {
sPSOVector.uiNeededSubsetSpsNum = ((pSvcParam->bSimulcastAVC) ? (0) :
((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (pSvcParam->iSpatialLayerNum - 1)));
}
return sPSOVector.uiNeededSubsetSpsNum;
}
uint32_t GetNeededPpsNum() {
if (0 == sPSOVector.uiNeededPpsNum) {
sPSOVector.uiNeededPpsNum = ((pSvcParam->eSpsPpsIdStrategy & SPS_PPS_LISTING) ? (MAX_PPS_COUNT) :
(1 + pSvcParam->iSpatialLayerNum));
}
return sPSOVector.uiNeededPpsNum;
}
} sWelsEncCtx/*, *PWelsEncCtx*/;
}
#endif//sWelsEncCtx_H__

View File

@ -89,6 +89,10 @@ typedef struct TagParaSetOffset {
int32_t eSpsPpsIdStrategy;
#endif
uint32_t uiNeededSpsNum;
uint32_t uiNeededSubsetSpsNum;
uint32_t uiNeededPpsNum;
uint32_t uiInUseSpsNum;
uint32_t uiInUseSubsetSpsNum;
uint32_t uiInUsePpsNum;

View File

@ -141,7 +141,7 @@ void CheckLevelSetting (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32
SSpatialLayerConfig* pLayerInfo = &pParam->sSpatialLayers[iLayer];
pLayerInfo->uiLevelIdc = uiLevelIdc;
if (uiLevelIdc > LEVEL_5_2) {
WelsLog (pLogCtx, WELS_LOG_INFO, "change unexpected levelidc(%d) setting to LEVEL_UNKNOWN", pLayerInfo->uiLevelIdc );
WelsLog (pLogCtx, WELS_LOG_INFO, "change unexpected levelidc(%d) setting to LEVEL_UNKNOWN", pLayerInfo->uiLevelIdc);
pLayerInfo->uiLevelIdc = LEVEL_UNKNOWN;
}
}
@ -337,12 +337,14 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
// eSpsPpsIdStrategy checkings
if (pCodingParam->iSpatialLayerNum > 1 && (SPS_LISTING & pCodingParam->eSpsPpsIdStrategy)) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with multiple SpatialLayers (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID", pCodingParam->eSpsPpsIdStrategy, pCodingParam->iSpatialLayerNum);
"ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with multiple SpatialLayers (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
pCodingParam->eSpsPpsIdStrategy, pCodingParam->iSpatialLayerNum);
pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
}
if (pCodingParam->iUsageType == SCREEN_CONTENT_REAL_TIME && (SPS_LISTING & pCodingParam->eSpsPpsIdStrategy)) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with iUsageType (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID", pCodingParam->eSpsPpsIdStrategy, pCodingParam->iUsageType);
"ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with iUsageType (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
pCodingParam->eSpsPpsIdStrategy, pCodingParam->iUsageType);
pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
}
@ -502,7 +504,8 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
iMbHeight = (kiPicHeight + 15) >> 4;
iMaxSliceNum = MAX_SLICES_NUM;
if (iMbHeight > iMaxSliceNum) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX(%d)!", iMbHeight, MAX_SLICES_NUM);
WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX(%d)!",
iMbHeight, MAX_SLICES_NUM);
return ENC_RETURN_UNSUPPORTED_PARA;
}
pSpatialLayer->sSliceCfg.sSliceArgument.uiSliceNum = iMbHeight;
@ -698,9 +701,9 @@ static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingPara
// count parasets
iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) +
iCountNumLayers // plus iCountNumLayers for reserved application
+ ((SPS_LISTING & pParam->eSpsPpsIdStrategy) ? MAX_SPS_COUNT : 0) //for Sps
+ (((SPS_LISTING & pParam->eSpsPpsIdStrategy) && (iNumDependencyLayers > 1)) ? MAX_SPS_COUNT : 0) //for SubsetSps
+ ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) ? MAX_PPS_COUNT : 0);
+ (*ppCtx)->GetNeededSpsNum()
+ (*ppCtx)->GetNeededSubsetSpsNum()
+ (*ppCtx)->GetNeededPpsNum();
// to check number of layers / nals / slices dependencies, 12/8/2010
if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
@ -1026,7 +1029,6 @@ int32_t FindExistingPps (SWelsSPS* pSps, SSubsetSps* pSubsetSps, const bool kbUs
return INVALID_ID;
}
/*!
* \brief initialize ppDqLayerList and slicepEncCtx_list due to count number of layers available
* \pParam pCtx sWelsEncCtx*
@ -1195,54 +1197,41 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
}
// for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010
// SPS
if (!pParam->bSimulcastAVC) {
if (! (SPS_LISTING & pParam->eSpsPpsIdStrategy)) {
(*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (sizeof (SWelsSPS), "pSpsArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
if (iDlayerCount > 1) {
(*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc ((iDlayerCount - 1) * sizeof (SSubsetSps), "pSubsetArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc (ppCtx))
}
} else {
// pParam->eSpsPpsIdStrategy == SPS_LISTING_AND_PPS_INCREASING
// new memory
(*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SWelsSPS), "pSpsArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
(*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SSubsetSps), "pSubsetArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc (ppCtx))
// copy from existing if the pointer exists
if (NULL != pExistingParasetList) {
(*ppCtx)->sPSOVector.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
(*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
memcpy ((*ppCtx)->pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
memcpy ((*ppCtx)->pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
}
}
const int32_t kiNeededSpsNum = (*ppCtx)->GetNeededSpsNum();
const int32_t kiNeededSubsetSpsNum = (*ppCtx)->GetNeededSubsetSpsNum();
(*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (kiNeededSpsNum * sizeof (SWelsSPS), "pSpsArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
if (kiNeededSubsetSpsNum > 0) {
(*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc (kiNeededSubsetSpsNum * sizeof (SSubsetSps), "pSubsetArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc (ppCtx))
} else {
//bSimulcastAVC
(*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (iDlayerCount * sizeof (SWelsSPS), "pSpsArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
(*ppCtx)->pSubsetArray = NULL;
}
// PPS
if (! (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy)) {
(*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (iDlayerCount * sizeof (SWelsPPS), "pPPSArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
} else {
(*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (MAX_PPS_COUNT * sizeof (SWelsPPS), "pPPSArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
if ((SPS_LISTING & pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
(*ppCtx)->sPSOVector.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
memcpy ((*ppCtx)->pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
// copy from existing if the pointer exists
if (NULL != pExistingParasetList) {
(*ppCtx)->sPSOVector.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
memcpy ((*ppCtx)->pPPSArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
if (kiNeededSubsetSpsNum > 0) {
(*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
memcpy ((*ppCtx)->pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
} else {
(*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = 0;
}
}
// PPS
const int32_t kiNeededPpsNum = (*ppCtx)->GetNeededPpsNum();
(*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (kiNeededPpsNum * sizeof (SWelsPPS), "pPPSArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
// copy from existing if the pointer exists
if ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
(*ppCtx)->sPSOVector.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
memcpy ((*ppCtx)->pPPSArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
}
if (INCREASING_ID & pParam->eSpsPpsIdStrategy) {
(*ppCtx)->pPSOVector = & ((*ppCtx)->sPSOVector);
} else {
@ -1728,8 +1717,8 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingPa
return 1;
}
const int32_t kiSpsSize = (pParam->eSpsPpsIdStrategy & SPS_LISTING) ? (MAX_SPS_COUNT * SPS_BUFFER_SIZE): (pParam->iSpatialLayerNum * SPS_BUFFER_SIZE);
const int32_t kiPpsSize = (pParam->eSpsPpsIdStrategy & SPS_PPS_LISTING) ? (MAX_PPS_COUNT * SPS_BUFFER_SIZE) : ((1 + pParam->iSpatialLayerNum) * PPS_BUFFER_SIZE);
const int32_t kiSpsSize = (*ppCtx)->GetNeededSpsNum() * SPS_BUFFER_SIZE;
const int32_t kiPpsSize = (*ppCtx)->GetNeededPpsNum() * PPS_BUFFER_SIZE;
iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + kiSpsSize + kiPpsSize;
int32_t iLayerBsSize = 0;
@ -3469,7 +3458,8 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
// write SPS
iNonVclSize = 0;
assert (kiSpatialNum == pCtx->iSpsNum);
assert ((kiSpatialNum == pCtx->iSpsNum) || (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy));
for (int32_t iIdx = 0; iIdx < pCtx->iSpsNum; iIdx++) {
//writing one NAL
@ -4252,13 +4242,16 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
pOldParam = (*ppCtx)->pSvcParam;
if (pOldParam->iUsageType != pNewParam->iUsageType) {
WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR, "WelsEncoderParamAdjust(), does not expect in-middle change of iUsgaeType from %d to %d", pOldParam->iUsageType, pNewParam->iUsageType);
WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
"WelsEncoderParamAdjust(), does not expect in-middle change of iUsgaeType from %d to %d", pOldParam->iUsageType,
pNewParam->iUsageType);
return ENC_RETURN_UNSUPPORTED_PARA;
}
/* Decide whether need reset for IDR frame based on adjusting prarameters changed */
/* Temporal levels, spatial settings and/ or quality settings changed need update parameter sets related. */
bNeedReset = (pOldParam == NULL) ||
(pOldParam->bSimulcastAVC != pNewParam->bSimulcastAVC) ||
(pOldParam->iSpatialLayerNum != pNewParam->iSpatialLayerNum) ||
(pOldParam->iPicWidth != pNewParam->iPicWidth
|| pOldParam->iPicHeight != pNewParam->iPicHeight) ||
@ -4339,21 +4332,30 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
&& (SPS_LISTING & pNewParam->eSpsPpsIdStrategy)) {
pExistingParasetList = &sExistingParasetList;
sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
if (NULL != (*ppCtx)->pSubsetArray) {
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
} else {
sExistingParasetList.uiInUseSubsetSpsNum = 0;
}
}
if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
&& (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy)) {
pExistingParasetList = &sExistingParasetList;
sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
sExistingParasetList.uiInUsePpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
memcpy (sExistingParasetList.sPps, (*ppCtx)->pPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
if (NULL != (*ppCtx)->pSubsetArray) {
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
} else {
sExistingParasetList.uiInUseSubsetSpsNum = 0;
}
memcpy (iTmpPpsIdList, ((*ppCtx)->sPSOVector.iPpsIdList), MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
}
}

View File

@ -3030,8 +3030,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) {
TEST_F (EncodeDecodeTestAPI, SimulcastSVC) {
#define LAYER_NUM (4)
int iSpatialLayerNum = WelsClip3 ((rand() % LAYER_NUM), 2, LAYER_NUM);
int iSpatialLayerNum = WelsClip3 ((rand() % MAX_SPATIAL_LAYER_NUM), 2, MAX_SPATIAL_LAYER_NUM);
int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_WIDTH);
int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_HEIGHT);
float fFrameRate = rand() + 0.5f;
@ -3043,12 +3042,12 @@ TEST_F (EncodeDecodeTestAPI, SimulcastSVC) {
int rv = encoder_->InitializeExt (&param_);
ASSERT_TRUE (rv == cmResultSuccess);
unsigned char* pBsBuf[LAYER_NUM];
int aLen[LAYER_NUM] = {0};
ISVCDecoder* decoder[LAYER_NUM];
unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
int aLen[MAX_SPATIAL_LAYER_NUM] = {0};
ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
#ifdef DEBUG_FILE_SAVE2
FILE* fEnc[LAYER_NUM] = { NULL };
FILE* fEnc[MAX_SPATIAL_LAYER_NUM] = { NULL };
fEnc[0] = fopen ("enc0.264", "wb");
fEnc[1] = fopen ("enc1.264", "wb");
fEnc[2] = fopen ("enc2.264", "wb");
@ -3059,11 +3058,12 @@ TEST_F (EncodeDecodeTestAPI, SimulcastSVC) {
int iIdx = 0;
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
pBsBuf[iIdx] = static_cast<unsigned char*> (malloc (iWidth * iHeight * 3 * sizeof (unsigned char) / 2));
EXPECT_TRUE (pBsBuf[iIdx] != NULL);
aLen[iIdx] = 0;
long rv = WelsCreateDecoder (&decoder[iIdx]);
ASSERT_EQ (0, rv);
ASSERT_TRUE (decoder[iIdx] != NULL);
EXPECT_TRUE (decoder[iIdx] != NULL);
SDecodingParam decParam;
memset (&decParam, 0, sizeof (SDecodingParam));
@ -3144,8 +3144,7 @@ TEST_F (EncodeDecodeTestAPI, SimulcastSVC) {
TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
//#define DEBUG_FILE_SAVE3
#define LAYER_NUM (4)
int iSpatialLayerNum = WelsClip3 ((rand() % LAYER_NUM), 2, LAYER_NUM);
int iSpatialLayerNum = WelsClip3 ((rand() % MAX_SPATIAL_LAYER_NUM), 2, MAX_SPATIAL_LAYER_NUM);
int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_WIDTH);
int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 1 << iSpatialLayerNum, MAX_HEIGHT);
float fFrameRate = rand() + 0.5f;
@ -3160,12 +3159,12 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
int rv = encoder_->InitializeExt (&param_);
ASSERT_TRUE (rv == cmResultSuccess);
unsigned char* pBsBuf[LAYER_NUM];
int aLen[LAYER_NUM] = {0};
ISVCDecoder* decoder[LAYER_NUM];
unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
int aLen[MAX_SPATIAL_LAYER_NUM] = {0};
ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
#ifdef DEBUG_FILE_SAVE3
FILE* fEnc[LAYER_NUM];
FILE* fEnc[MAX_SPATIAL_LAYER_NUM];
fEnc[0] = fopen ("enc0.264", "wb");
fEnc[1] = fopen ("enc1.264", "wb");
fEnc[2] = fopen ("enc2.264", "wb");
@ -3177,11 +3176,12 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
//create decoder
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
pBsBuf[iIdx] = static_cast<unsigned char*> (malloc (iWidth * iHeight * 3 * sizeof (unsigned char) / 2));
EXPECT_TRUE (pBsBuf[iIdx] != NULL);
aLen[iIdx] = 0;
long rv = WelsCreateDecoder (&decoder[iIdx]);
ASSERT_EQ (0, rv);
ASSERT_TRUE (decoder[iIdx] != NULL);
EXPECT_TRUE (decoder[iIdx] != NULL);
SDecodingParam decParam;
memset (&decParam, 0, sizeof (SDecodingParam));