complete logic of simulcastavc with sps_pps_listing

This commit is contained in:
Sijia Chen
2015-02-11 17:31:17 +08:00
parent a73c1e6814
commit f9080ac090
3 changed files with 290 additions and 37 deletions

View File

@@ -246,8 +246,8 @@ typedef struct TagWelsEncCtx {
uint32_t GetNeededSpsNum() {
if (0 == sPSOVector.uiNeededSpsNum) {
sPSOVector.uiNeededSpsNum = ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) :
((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1)));
sPSOVector.uiNeededSpsNum = ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (1));
sPSOVector.uiNeededSpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
}
return sPSOVector.uiNeededSpsNum;
}
@@ -264,6 +264,7 @@ typedef struct TagWelsEncCtx {
if (0 == sPSOVector.uiNeededPpsNum) {
sPSOVector.uiNeededPpsNum = ((pSvcParam->eSpsPpsIdStrategy & SPS_PPS_LISTING) ? (MAX_PPS_COUNT) :
(1 + pSvcParam->iSpatialLayerNum));
sPSOVector.uiNeededPpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
}
return sPSOVector.uiNeededPpsNum;
}

View File

@@ -321,7 +321,6 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
return ENC_RETURN_UNSUPPORTED_PARA;
}
//about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode
// (1) Single Thread
// if (THREAD==1)//single thread
@@ -335,9 +334,10 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
}
// eSpsPpsIdStrategy checkings
if (pCodingParam->iSpatialLayerNum > 1 && (SPS_LISTING & pCodingParam->eSpsPpsIdStrategy)) {
if (pCodingParam->iSpatialLayerNum > 1 && (!pCodingParam->bSimulcastAVC)
&& (SPS_LISTING & pCodingParam->eSpsPpsIdStrategy)) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with multiple SpatialLayers (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
"ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with multiple svc SpatialLayers (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
pCodingParam->eSpsPpsIdStrategy, pCodingParam->iSpatialLayerNum);
pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
}
@@ -540,7 +540,8 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
}
if (pCodingParam->uiMaxNalSize < (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE)) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiMaxNalSize (%d) settings! should be larger than (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE)(%d)",
WelsLog (pLogCtx, WELS_LOG_ERROR,
"ParamValidationExt(), invalid uiMaxNalSize (%d) settings! should be larger than (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE)(%d)",
pCodingParam->uiMaxNalSize, (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE));
return ENC_RETURN_UNSUPPORTED_PARA;
}
@@ -3140,6 +3141,7 @@ int32_t WelsWriteOneSPS (sWelsEncCtx* pCtx, const int32_t kiSpsIdx, int32_t& iNa
pCtx->iPosBsBuffer += iNalSize;
return ENC_RETURN_SUCCESS;
}
int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNalSize) {
//TODO
int32_t iNal = pCtx->pOut->iNalIndex;
@@ -3159,6 +3161,29 @@ int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNa
return ENC_RETURN_SUCCESS;
}
void UpdatePpsList (sWelsEncCtx* pCtx) {
assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
//Generate PPS LIST
int32_t iPpsId = 0, iUsePpsNum = pCtx->iPpsNum;
for (int32_t iIdrRound = 0; iIdrRound < MAX_PPS_COUNT; iIdrRound++) {
for (iPpsId = 0; iPpsId < pCtx->iPpsNum; iPpsId++) {
pCtx->sPSOVector.iPpsIdList[iPpsId][iIdrRound] = ((iIdrRound * iUsePpsNum + iPpsId) % MAX_PPS_COUNT);
}
}
for (iPpsId = iUsePpsNum; iPpsId < MAX_PPS_COUNT; iPpsId++) {
memcpy (& (pCtx->pPPSArray[iPpsId]), & (pCtx->pPPSArray[iPpsId % iUsePpsNum]), sizeof (SWelsPPS));
pCtx->pPPSArray[iPpsId].iPpsId = iPpsId;
pCtx->iPpsNum++;
}
assert (pCtx->iPpsNum == MAX_PPS_COUNT);
pCtx->sPSOVector.uiInUsePpsNum = pCtx->iPpsNum;
}
/*!
* \brief write all parameter sets introduced in SVC extension
* \return writing results, success or error
@@ -3245,29 +3270,11 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
}
/* write all PPS */
iIdx = 0;
if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
//Generate PPS LIST
int32_t iPpsId = 0, iUsePpsNum = pCtx->iPpsNum;
for (int32_t iIdrRound = 0; iIdrRound < MAX_PPS_COUNT; iIdrRound++) {
for (iPpsId = 0; iPpsId < pCtx->iPpsNum; iPpsId++) {
pCtx->sPSOVector.iPpsIdList[iPpsId][iIdrRound] = ((iIdrRound * iUsePpsNum + iPpsId) % MAX_PPS_COUNT);
}
}
for (iPpsId = iUsePpsNum; iPpsId < MAX_PPS_COUNT; iPpsId++) {
memcpy (& (pCtx->pPPSArray[iPpsId]), & (pCtx->pPPSArray[iPpsId % iUsePpsNum]), sizeof (SWelsPPS));
pCtx->pPPSArray[iPpsId].iPpsId = iPpsId;
pCtx->iPpsNum++;
}
assert (pCtx->iPpsNum == MAX_PPS_COUNT);
pCtx->sPSOVector.uiInUsePpsNum = pCtx->iPpsNum;
UpdatePpsList (pCtx);
}
iIdx = 0;
while (iIdx < pCtx->iPpsNum) {
if ((INCREASING_ID & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
//para_set_type = 2: PPS, use MAX_PPS_COUNT
@@ -3479,7 +3486,6 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
iCountNal = 1;
//finish writing one NAL
pLayerBsInfo->uiSpatialId = iIdx;
pLayerBsInfo->uiTemporalId = 0;
pLayerBsInfo->uiQualityId = 0;
@@ -3511,7 +3517,6 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
iCountNal = 1;
//finish writing one NAL
pLayerBsInfo->uiSpatialId = iIdx;
pLayerBsInfo->uiTemporalId = 0;
pLayerBsInfo->uiQualityId = 0;
@@ -3538,6 +3543,87 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
return iReturn;
}
int32_t WriteSavcParaset_Listing (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
SLayerBSInfo*& pLayerBsInfo, int32_t& iLayerNum, int32_t& iFrameSize) {
int32_t iNonVclSize = 0, iCountNal = 0, iReturn;
// write SPS
iNonVclSize = 0;
for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
iCountNal = 0;
for (int32_t iIdx = 0; iIdx < pCtx->iSpsNum; iIdx++) {
//writing one NAL
int32_t iNalSize = 0;
iReturn = WelsWriteOneSPS (pCtx, iIdx, iNalSize);
WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
iNonVclSize += iNalSize;
iCountNal ++;
//finish writing one NAL
}
pLayerBsInfo->uiSpatialId = iSpatialId;
pLayerBsInfo->uiTemporalId = 0;
pLayerBsInfo->uiQualityId = 0;
pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
pLayerBsInfo->iNalCount = iCountNal;
//point to next pLayerBsInfo
++ pLayerBsInfo;
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
//update for external countings
iCountNal = 0;
++ iLayerNum;
}
// write PPS
if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
UpdatePpsList (pCtx);
}
//TODO: under new strategy, will PPS be correctly updated?
for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
iCountNal = 0;
for (int32_t iIdx = 0; iIdx < pCtx->iPpsNum; iIdx++) {
//writing one NAL
int32_t iNalSize = 0;
iReturn = WelsWriteOnePPS (pCtx, iIdx, iNalSize);
WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
iNonVclSize += iNalSize;
iCountNal ++;
//finish writing one NAL
}
pLayerBsInfo->uiSpatialId = iSpatialId;
pLayerBsInfo->uiTemporalId = 0;
pLayerBsInfo->uiQualityId = 0;
pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
pLayerBsInfo->iNalCount = iCountNal;
//point to next pLayerBsInfo
++ pLayerBsInfo;
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
//update for external countings
iCountNal = 0;
++ iLayerNum;
}
// to check number of layers / nals / slices dependencies
if (iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WriteSavcParaset(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
iLayerNum, MAX_LAYER_NUM_OF_FRAME);
return ENC_RETURN_UNEXPECTED;
}
iFrameSize += iNonVclSize;
return iReturn;
}
/*!
* \brief core svc encoding process
@@ -3637,9 +3723,13 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
++ pCtx->uiIdrPicId;
// write parameter sets bitstream or SEI/SSEI (if any) here
// TODO: use function pointer instead
pCtx->iEncoderError = ((!pSvcParam->bSimulcastAVC)
? (WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize))
: (WriteSavcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize)));
if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
pCtx->iEncoderError = ((!pSvcParam->bSimulcastAVC)
? (WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize))
: (WriteSavcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize)));
} else {
pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
}
WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
}
@@ -4217,6 +4307,33 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pFbi->eFrameType = eFrameType;
pFbi->iFrameSizeInBytes = iFrameSize;
#ifdef _DEBUG
if (pFbi->iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
pFbi->iLayerNum, MAX_LAYER_NUM_OF_FRAME);
return ENC_RETURN_UNEXPECTED;
}
int32_t iTotalNal = 0;
for (int32_t k = 0; k < pFbi->iLayerNum; k++) {
iTotalNal += pFbi->sLayerInfo[k].iNalCount;
if ((pCtx->iActiveThreadsNum > 1) && (MAX_NAL_UNITS_IN_LAYER < pFbi->sLayerInfo[k].iNalCount)) {
WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR,
"WelsEncoderEncodeExt(), iCountNumNals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) under multi-thread(%d) NOT supported!",
pFbi->sLayerInfo[k].iNalCount, MAX_NAL_UNITS_IN_LAYER), pCtx->iActiveThreadsNum;
return ENC_RETURN_UNEXPECTED;
}
}
if (iTotalNal > pCtx->pOut->iCountNals) {
WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iTotalNal(%d) > iCountNals(%d)!",
iTotalNal, pCtx->pOut->iCountNals);
return ENC_RETURN_UNEXPECTED;
}
#endif
return ENC_RETURN_SUCCESS;
}

View File

@@ -224,6 +224,80 @@ class EncodeDecodeTestAPIBase : public EncodeDecodeTestBase {
fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, pfEnc);
}
}
void TestOneSimulcastAVC (SEncParamExt* pParam, ISVCDecoder** decoder, unsigned char** pBsBuf, int iSpatialLayerNum,
int iEncFrameNum,
int iCallTimes) {
//#define DEBUG_FILE_SAVE4
int aLen[MAX_SPATIAL_LAYER_NUM] = {0, 0, 0, 0};
#ifdef DEBUG_FILE_SAVE4
FILE* fEnc[MAX_SPATIAL_LAYER_NUM];
if (iCallTimes == 0) {
fEnc[0] = fopen ("enc00.264", "wb");
fEnc[1] = fopen ("enc01.264", "wb");
fEnc[2] = fopen ("enc02.264", "wb");
fEnc[3] = fopen ("enc03.264", "wb");
} else {
fEnc[0] = fopen ("enc10.264", "wb");
fEnc[1] = fopen ("enc11.264", "wb");
fEnc[2] = fopen ("enc12.264", "wb");
fEnc[3] = fopen ("enc13.264", "wb");
}
#endif
int rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, pParam);
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed pParam: rv = " << rv;
int iIdx;
//begin testing
for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
int iResult;
int iLayerLen = 0;
unsigned char* pData[3] = { NULL };
InitialEncDec (pParam->iPicWidth, pParam->iPicHeight);
EncodeOneFrame (0);
// init
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
aLen[iIdx] = 0;
}
for (int iLayer = 0; iLayer < info.iLayerNum; ++iLayer) {
iLayerLen = 0;
const SLayerBSInfo& layerInfo = info.sLayerInfo[iLayer];
for (int iNal = 0; iNal < layerInfo.iNalCount; ++iNal) {
iLayerLen += layerInfo.pNalLengthInByte[iNal];
}
iIdx = layerInfo.uiSpatialId;
EXPECT_TRUE (iIdx < iSpatialLayerNum) << "iIdx = " << iIdx << ", iSpatialLayerNum = " << iSpatialLayerNum;
memcpy ((pBsBuf[iIdx] + aLen[iIdx]), layerInfo.pBsBuf, iLayerLen * sizeof (unsigned char));
aLen[iIdx] += iLayerLen;
}
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
pData[0] = pData[1] = pData[2] = 0;
memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
#ifdef DEBUG_FILE_SAVE4
fwrite (pBsBuf[iIdx], aLen[iIdx], 1, fEnc[iIdx]);
#endif
iResult = decoder[iIdx]->DecodeFrame2 (pBsBuf[iIdx], aLen[iIdx], pData, &dstBufInfo_);
EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << ", LayerIdx=" << iIdx;
iResult = decoder[iIdx]->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_);
EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << ", LayerIdx=" << iIdx;
EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx;
}
}
#ifdef DEBUG_FILE_SAVE4
fclose (fEnc[0]);
fclose (fEnc[1]);
fclose (fEnc[2]);
fclose (fEnc[3]);
#endif
}
};
class EncodeDecodeTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestAPIBase {
@@ -3194,7 +3268,7 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
ASSERT_EQ (0, rv);
}
iEncFrameNum = 1;
iEncFrameNum = 10;
for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
int iResult;
int iLayerLen = 0;
@@ -3237,7 +3311,6 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx;
EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx;
}
}
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
@@ -3247,9 +3320,72 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
decoder[iIdx]->Uninitialize();
WelsDestroyDecoder (decoder[iIdx]);
}
#ifdef DEBUG_FILE_SAVE3
fclose (fEnc[iIdx]);
#endif
}
}
TEST_F (EncodeDecodeTestAPI, SimulcastAVC_SPS_PPS_LISTING) {
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;
int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
int iSliceNum = 1;
// prepare params
SEncParamExt sParam1;
SEncParamExt sParam2;
encoder_->GetDefaultParams (&sParam1);
prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
//set flag of SPS_PPS_LISTING
sParam1.eSpsPpsIdStrategy = SPS_PPS_LISTING;//SPS_LISTING;//
//set flag of bSimulcastAVC
sParam1.bSimulcastAVC = true;
//prepare param2
memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
sParam2.sSpatialLayers[0].iVideoWidth = (sParam1.sSpatialLayers[0].iVideoWidth / 2);
sParam2.sSpatialLayers[0].iVideoHeight = (sParam1.sSpatialLayers[0].iVideoHeight / 2);
int rv = encoder_->InitializeExt (&sParam1);
ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam1: rv = " << rv;;
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
int iIdx = 0;
//create decoder
for (int iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
pBsBuf[iIdx] = static_cast<unsigned char*> (malloc (iWidth * iHeight * 3 * sizeof (unsigned char) / 2));
EXPECT_TRUE (pBsBuf[iIdx] != NULL);
long rv = WelsCreateDecoder (&decoder[iIdx]);
ASSERT_EQ (0, rv);
EXPECT_TRUE (decoder[iIdx] != NULL);
SDecodingParam decParam;
memset (&decParam, 0, sizeof (SDecodingParam));
decParam.eOutputColorFormat = videoFormatI420;
decParam.uiTargetDqLayer = UCHAR_MAX;
decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
rv = decoder[iIdx]->Initialize (&decParam);
ASSERT_EQ (0, rv);
}
TestOneSimulcastAVC (&sParam1, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
TestOneSimulcastAVC (&sParam2, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 1);
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
free (pBsBuf[iIdx]);
if (decoder[iIdx] != NULL) {
decoder[iIdx]->Uninitialize();
WelsDestroyDecoder (decoder[iIdx]);
}
}
}
@@ -3399,4 +3535,3 @@ TEST_P (EncodeTestAPI, SetEncOptionSize) {
}
}