complete logic of simulcastavc with sps_pps_listing
This commit is contained in:
@@ -246,8 +246,8 @@ typedef struct TagWelsEncCtx {
|
|||||||
|
|
||||||
uint32_t GetNeededSpsNum() {
|
uint32_t GetNeededSpsNum() {
|
||||||
if (0 == sPSOVector.uiNeededSpsNum) {
|
if (0 == sPSOVector.uiNeededSpsNum) {
|
||||||
sPSOVector.uiNeededSpsNum = ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) :
|
sPSOVector.uiNeededSpsNum = ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (1));
|
||||||
((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1)));
|
sPSOVector.uiNeededSpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
|
||||||
}
|
}
|
||||||
return sPSOVector.uiNeededSpsNum;
|
return sPSOVector.uiNeededSpsNum;
|
||||||
}
|
}
|
||||||
@@ -264,6 +264,7 @@ typedef struct TagWelsEncCtx {
|
|||||||
if (0 == sPSOVector.uiNeededPpsNum) {
|
if (0 == sPSOVector.uiNeededPpsNum) {
|
||||||
sPSOVector.uiNeededPpsNum = ((pSvcParam->eSpsPpsIdStrategy & SPS_PPS_LISTING) ? (MAX_PPS_COUNT) :
|
sPSOVector.uiNeededPpsNum = ((pSvcParam->eSpsPpsIdStrategy & SPS_PPS_LISTING) ? (MAX_PPS_COUNT) :
|
||||||
(1 + pSvcParam->iSpatialLayerNum));
|
(1 + pSvcParam->iSpatialLayerNum));
|
||||||
|
sPSOVector.uiNeededPpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
|
||||||
}
|
}
|
||||||
return sPSOVector.uiNeededPpsNum;
|
return sPSOVector.uiNeededPpsNum;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,7 +321,6 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
|
|||||||
return ENC_RETURN_UNSUPPORTED_PARA;
|
return ENC_RETURN_UNSUPPORTED_PARA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode
|
//about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode
|
||||||
// (1) Single Thread
|
// (1) Single Thread
|
||||||
// if (THREAD==1)//single thread
|
// if (THREAD==1)//single thread
|
||||||
@@ -335,9 +334,10 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eSpsPpsIdStrategy checkings
|
// 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,
|
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, pCodingParam->iSpatialLayerNum);
|
||||||
pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
|
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)) {
|
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));
|
pCodingParam->uiMaxNalSize, (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE));
|
||||||
return ENC_RETURN_UNSUPPORTED_PARA;
|
return ENC_RETURN_UNSUPPORTED_PARA;
|
||||||
}
|
}
|
||||||
@@ -3140,6 +3141,7 @@ int32_t WelsWriteOneSPS (sWelsEncCtx* pCtx, const int32_t kiSpsIdx, int32_t& iNa
|
|||||||
pCtx->iPosBsBuffer += iNalSize;
|
pCtx->iPosBsBuffer += iNalSize;
|
||||||
return ENC_RETURN_SUCCESS;
|
return ENC_RETURN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNalSize) {
|
int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNalSize) {
|
||||||
//TODO
|
//TODO
|
||||||
int32_t iNal = pCtx->pOut->iNalIndex;
|
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;
|
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
|
* \brief write all parameter sets introduced in SVC extension
|
||||||
* \return writing results, success or error
|
* \return writing results, success or error
|
||||||
@@ -3245,29 +3270,11 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write all PPS */
|
/* write all PPS */
|
||||||
iIdx = 0;
|
|
||||||
if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
|
if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
|
||||||
assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
|
UpdatePpsList (pCtx);
|
||||||
|
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iIdx = 0;
|
||||||
while (iIdx < pCtx->iPpsNum) {
|
while (iIdx < pCtx->iPpsNum) {
|
||||||
if ((INCREASING_ID & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
|
if ((INCREASING_ID & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
|
||||||
//para_set_type = 2: PPS, use MAX_PPS_COUNT
|
//para_set_type = 2: PPS, use MAX_PPS_COUNT
|
||||||
@@ -3479,7 +3486,6 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
|
|||||||
iCountNal = 1;
|
iCountNal = 1;
|
||||||
//finish writing one NAL
|
//finish writing one NAL
|
||||||
|
|
||||||
|
|
||||||
pLayerBsInfo->uiSpatialId = iIdx;
|
pLayerBsInfo->uiSpatialId = iIdx;
|
||||||
pLayerBsInfo->uiTemporalId = 0;
|
pLayerBsInfo->uiTemporalId = 0;
|
||||||
pLayerBsInfo->uiQualityId = 0;
|
pLayerBsInfo->uiQualityId = 0;
|
||||||
@@ -3511,7 +3517,6 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
|
|||||||
iCountNal = 1;
|
iCountNal = 1;
|
||||||
//finish writing one NAL
|
//finish writing one NAL
|
||||||
|
|
||||||
|
|
||||||
pLayerBsInfo->uiSpatialId = iIdx;
|
pLayerBsInfo->uiSpatialId = iIdx;
|
||||||
pLayerBsInfo->uiTemporalId = 0;
|
pLayerBsInfo->uiTemporalId = 0;
|
||||||
pLayerBsInfo->uiQualityId = 0;
|
pLayerBsInfo->uiQualityId = 0;
|
||||||
@@ -3538,6 +3543,87 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
|
|||||||
return iReturn;
|
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
|
* \brief core svc encoding process
|
||||||
@@ -3637,9 +3723,13 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
|
|||||||
++ pCtx->uiIdrPicId;
|
++ pCtx->uiIdrPicId;
|
||||||
// write parameter sets bitstream or SEI/SSEI (if any) here
|
// write parameter sets bitstream or SEI/SSEI (if any) here
|
||||||
// TODO: use function pointer instead
|
// TODO: use function pointer instead
|
||||||
|
if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
|
||||||
pCtx->iEncoderError = ((!pSvcParam->bSimulcastAVC)
|
pCtx->iEncoderError = ((!pSvcParam->bSimulcastAVC)
|
||||||
? (WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize))
|
? (WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize))
|
||||||
: (WriteSavcParaset (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)
|
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->eFrameType = eFrameType;
|
||||||
pFbi->iFrameSizeInBytes = iFrameSize;
|
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;
|
return ENC_RETURN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,80 @@ class EncodeDecodeTestAPIBase : public EncodeDecodeTestBase {
|
|||||||
fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, pfEnc);
|
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 {
|
class EncodeDecodeTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestAPIBase {
|
||||||
@@ -3194,7 +3268,7 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
|
|||||||
ASSERT_EQ (0, rv);
|
ASSERT_EQ (0, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
iEncFrameNum = 1;
|
iEncFrameNum = 10;
|
||||||
for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
|
for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
|
||||||
int iResult;
|
int iResult;
|
||||||
int iLayerLen = 0;
|
int iLayerLen = 0;
|
||||||
@@ -3237,7 +3311,6 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
|
|||||||
EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx;
|
EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << "LayerIdx=" << iIdx;
|
||||||
EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx;
|
EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
|
for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
|
||||||
@@ -3247,9 +3320,72 @@ TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
|
|||||||
decoder[iIdx]->Uninitialize();
|
decoder[iIdx]->Uninitialize();
|
||||||
WelsDestroyDecoder (decoder[iIdx]);
|
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user