ref: 46667588e3f90c212e06da087f4847fbeebea7cd
parent: f679da900f3a4fc7630a7b5c0335367ed7cabbdb
author: sijchen <sijchen@cisco.com>
date: Mon Nov 30 05:47:10 EST 2015
moving test cases to specific files to avoid the too long encode_decode_api_test.cpp
--- /dev/null
+++ b/test/api/decode_api_test.cpp
@@ -1,0 +1,962 @@
+#include <gtest/gtest.h>
+#include "codec_def.h"
+#include "utils/BufferedData.h"
+#include "utils/FileInputStream.h"
+#include "BaseDecoderTest.h"
+#include "BaseEncoderTest.h"
+#include "wels_common_defs.h"
+#include "utils/HashFunctions.h"
+#include <string>
+#include <vector>
+#include "encode_decode_api_test.h"
+using namespace WelsCommon;
+
+static void TestOutPutTrace (void* ctx, int level, const char* string) {
+ STraceUnit* pTraceUnit = (STraceUnit*) ctx;
+ EXPECT_LE (level, pTraceUnit->iTarLevel);
+}
+
+TEST_P (EncodeDecodeTestAPI, DecoderVclNal) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ InitialEncDec (p.width, p.height);
+
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+
+ EncodeOneFrame (0);
+
+ //decoding after each encoding frame
+ int vclNal, len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
+ EXPECT_EQ (vclNal, FEEDBACK_UNKNOWN_NAL); //no reconstruction, unknown return
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ ASSERT_TRUE (rv == cmResultSuccess);
+ rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
+ EXPECT_EQ (vclNal, FEEDBACK_VCL_NAL);
+ iIdx++;
+ } //while
+ //ignore last frame
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ InitialEncDec (p.width, p.height);
+
+ int32_t iEncFrameNum = -1;
+ int32_t iDecFrameNum;
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (0);
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
+ EXPECT_EQ (iDecFrameNum, -1);
+ iEncFrameNum++;
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
+ EXPECT_EQ (iEncFrameNum, iDecFrameNum);
+ iIdx++;
+ } //while
+ //ignore last frame
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionIDR) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ //init for encoder
+ // I420: 1(Y) + 1/4(U) + 1/4(V)
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ InitialEncDec (p.width, p.height);
+
+ int32_t iEncCurIdrPicId = 0;
+ int32_t iDecCurIdrPicId;
+ int32_t iIDRPeriod = 1;
+ int32_t iSpsPpsIdAddition = 0;
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ iSpsPpsIdAddition = rand() %
+ 2; //the current strategy supports more than 2 modes, but the switch between the modes>2 is not allowed
+ iIDRPeriod = (rand() % 150) + 1;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+
+ EncodeOneFrame (0);
+
+ if (info.eFrameType == videoFrameTypeIDR) {
+ iEncCurIdrPicId = iEncCurIdrPicId + 1;
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
+ EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
+ EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
+ iIdx++;
+ } //while
+ //ignore last frame
+}
+
+TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iSkipedBytes;
+ unsigned long long uiEncTimeStamp = 100;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ uint32_t uiEcIdc = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ if (dstBufInfo_.iBufferStatus == 1) {
+ EXPECT_EQ (uiEncTimeStamp, dstBufInfo_.uiOutYuvTimeStamp);
+ }
+ iIdx++;
+ uiEncTimeStamp++;
+ }
+ (void) iSkipedBytes;
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.bPrefixNalAddingCtrl = false;
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ if (iTid != -1) {
+ ASSERT_EQ (iTid, 0);
+ }
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ std::vector<SLostSim>::iterator iter = m_SLostSim.begin();
+ bool bHasVCL = false;
+ for (unsigned int k = 0; k < m_SLostSim.size(); k++) {
+ if (IS_VCL_NAL (iter->eNalType, 0) && iter->isLost == false) {
+ bHasVCL = true;
+ break;
+ }
+ iter++;
+ }
+ (void) bHasVCL;
+ if (iTid != -1) {
+ ASSERT_EQ (iTid, 0);
+ }
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_WITH_PREFIX_NOLOSS) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.bPrefixNalAddingCtrl = true;
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 0);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, -1);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionTid_SVC_L1_NOLOSS) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (2, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 2;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 1);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, -1);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+
+
+TEST_P (EncodeDecodeTestAPI, SetOption_Trace) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = 1;
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ pFunc = TestOutPutTrace;
+ pTraceInfo = &sTrace;
+ sTrace.iTarLevel = iTraceLevel;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+
+
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ iTraceLevel = rand() % 33;
+ sTrace.iTarLevel = iTraceLevel;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 0);
+ SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, SetOption_Trace_NULL) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = 1;
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ pFunc = NULL;
+ pTraceInfo = NULL;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ iTraceLevel = rand() % 33;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 0);
+ SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+
+
+
+class DecodeCrashTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
+ public:
+ uint8_t iRandValue;
+ public:
+ void SetUp() {
+ EncodeDecodeTestBase::SetUp();
+ ucBuf_ = NULL;
+ ucBuf_ = new unsigned char [1000000];
+ ASSERT_TRUE (ucBuf_ != NULL);
+ }
+
+ void TearDown() {
+ EncodeDecodeTestBase::TearDown();
+ if (NULL != ucBuf_) {
+ delete[] ucBuf_;
+ ucBuf_ = NULL;
+ }
+ ASSERT_TRUE (ucBuf_ == NULL);
+ }
+
+ void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
+ memset (pParam, 0, sizeof (SEncParamExt));
+ EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
+ }
+
+ void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam);
+ void EncodeOneFrame() {
+ int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
+ memset (buf_.data(), iRandValue, (frameSize >> 2));
+ memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
+ int rv = encoder_->EncodeFrame (&EncPic, &info);
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
+ }
+ protected:
+ unsigned char* ucBuf_;
+};
+
+void DecodeCrashTestAPI::prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam) {
+ // for encoder
+ // I420: 1(Y) + 1/4(U) + 1/4(V)
+ int frameSize = EncDecFileParam.width * EncDecFileParam.height * 3 / 2;
+
+ buf_.SetLength (frameSize);
+ ASSERT_TRUE (buf_.Length() == (size_t)frameSize);
+
+ memset (&EncPic, 0, sizeof (SSourcePicture));
+ EncPic.iPicWidth = EncDecFileParam.width;
+ EncPic.iPicHeight = EncDecFileParam.height;
+ EncPic.iColorFormat = videoFormatI420;
+ EncPic.iStride[0] = EncPic.iPicWidth;
+ EncPic.iStride[1] = EncPic.iStride[2] = EncPic.iPicWidth >> 1;
+ EncPic.pData[0] = buf_.data();
+ EncPic.pData[1] = EncPic.pData[0] + EncDecFileParam.width * EncDecFileParam.height;
+ EncPic.pData[2] = EncPic.pData[1] + (EncDecFileParam.width * EncDecFileParam.height >> 2);
+
+ //for decoder
+ memset (&info, 0, sizeof (SFrameBSInfo));
+
+ //set a fixed random value
+ iRandValue = rand() % 256;
+}
+
+struct EncodeDecodeParamBase {
+ int width;
+ int height;
+ float frameRate;
+ int iTarBitrate;
+};
+
+#define NUM_OF_POSSIBLE_RESOLUTION (9)
+static const EncodeDecodeParamBase kParamArray[] = {
+ {160, 90, 6.0f, 250000},
+ {90, 160, 6.0f, 250000},
+ {320, 180, 12.0f, 500000},
+ {180, 320, 12.0f, 500000},
+ {480, 270, 12.0f, 600000},
+ {270, 480, 12.0f, 600000},
+ {640, 360, 24.0f, 800000},
+ {360, 640, 24.0f, 800000},
+ {1280, 720, 24.0f, 1000000},
+};
+
+//#define DEBUG_FILE_SAVE_CRA
+TEST_F (DecodeCrashTestAPI, DecoderCrashTest) {
+ uint32_t uiGet;
+ encoder_->Uninitialize();
+
+ //do tests until crash
+ unsigned int uiLoopRound = 0;
+ unsigned char* pucBuf = ucBuf_;
+ int iDecAuSize;
+#ifdef DEBUG_FILE_SAVE_CRA
+ //open file to save tested BS
+ FILE* fDataFile = fopen ("test_crash.264", "wb");
+ FILE* fLenFile = fopen ("test_crash_len.log", "w");
+ int iFileSize = 0;
+#endif
+
+ //set eCurStrategy for one test
+ EParameterSetStrategy eCurStrategy = CONSTANT_ID;
+ switch (rand() % 7) {
+ case 1:
+ eCurStrategy = INCREASING_ID;
+ break;
+ case 2:
+ eCurStrategy = SPS_LISTING;
+ break;
+ case 3:
+ eCurStrategy = SPS_LISTING_AND_PPS_INCREASING;
+ break;
+ case 6:
+ eCurStrategy = SPS_PPS_LISTING;
+ break;
+ default:
+ //using the initial value
+ break;
+ }
+
+ do {
+ int iTotalFrameNum = (rand() % 100) + 1;
+ int iSeed = rand() % NUM_OF_POSSIBLE_RESOLUTION;
+ EncodeDecodeParamBase p = kParamArray[iSeed];
+#ifdef DEBUG_FILE_SAVE_CRA
+ printf ("using param set %d in loop %d\n", iSeed, uiLoopRound);
+#endif
+ //Initialize Encoder
+ prepareParam (1, 1, p.width, p.height, p.frameRate, ¶m_);
+ param_.iRCMode = RC_TIMESTAMP_MODE;
+ param_.iTargetBitrate = p.iTarBitrate;
+ param_.uiIntraPeriod = 0;
+ param_.eSpsPpsIdStrategy = eCurStrategy;
+ param_.bEnableBackgroundDetection = true;
+ param_.bEnableSceneChangeDetect = (rand() % 3) ? true : false;
+ param_.bPrefixNalAddingCtrl = (rand() % 2) ? true : false;
+ param_.iEntropyCodingModeFlag = 0;
+ param_.bEnableFrameSkip = true;
+ param_.iMultipleThreadIdc = 0;
+ param_.sSpatialLayers[0].iSpatialBitrate = p.iTarBitrate;
+ param_.sSpatialLayers[0].iMaxSpatialBitrate = p.iTarBitrate << 1;
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceMode = (rand() % 2) ? SM_SIZELIMITED_SLICE : SM_SINGLE_SLICE;
+ if (param_.sSpatialLayers[0].sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE) {
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 1400;
+ param_.uiMaxNalSize = 1400;
+ } else {
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 0;
+ param_.uiMaxNalSize = 0;
+ }
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ //Start for enc/dec
+ int iIdx = 0;
+ unsigned char* pData[3] = { NULL };
+
+ EncodeDecodeFileParamBase pInput; //to conform with old functions
+ pInput.width = p.width;
+ pInput.height = p.height;
+ pInput.frameRate = p.frameRate;
+ prepareEncDecParam (pInput);
+ while (iIdx++ < iTotalFrameNum) { // loop in frame
+ EncodeOneFrame();
+#ifdef DEBUG_FILE_SAVE_CRA
+ //reset file if file size large
+ if ((info.eFrameType == videoFrameTypeIDR) && (iFileSize >= (1 << 25))) {
+ fclose (fDataFile);
+ fDataFile = fopen ("test_crash.264", "wb");
+ iFileSize = 0;
+ decoder_->Uninitialize();
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+ rv = decoder_->Initialize (&decParam);
+ ASSERT_EQ (0, rv);
+ }
+#endif
+ if (info.eFrameType == videoFrameTypeSkip)
+ continue;
+ //deal with packets
+ unsigned char* pBsBuf;
+ iDecAuSize = 0;
+ pucBuf = ucBuf_; //init buf start pos for decoder usage
+ for (int iLayerNum = 0; iLayerNum < info.iLayerNum; iLayerNum++) {
+ SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayerNum];
+ pBsBuf = info.sLayerInfo[iLayerNum].pBsBuf;
+ int iTotalNalCnt = pLayerBsInfo->iNalCount;
+ for (int iNalCnt = 0; iNalCnt < iTotalNalCnt; iNalCnt++) { //loop in NAL
+ int iPacketSize = pLayerBsInfo->pNalLengthInByte[iNalCnt];
+ //packet loss
+ int iLossRateRange = (uiLoopRound % 100) + 1; //1-100
+ int iLossRate = (rand() % iLossRateRange);
+ bool bPacketLost = (rand() % 101) > (100 -
+ iLossRate); // [0, (100-iLossRate)] indicates NO LOSS, (100-iLossRate, 100] indicates LOSS
+ if (!bPacketLost) { //no loss
+ memcpy (pucBuf, pBsBuf, iPacketSize);
+ pucBuf += iPacketSize;
+ iDecAuSize += iPacketSize;
+ }
+#ifdef DEBUG_FILE_SAVE_CRA
+ else {
+ printf ("lost packet size=%d at frame-type=%d at loss rate %d (%d)\n", iPacketSize, info.eFrameType, iLossRate,
+ iLossRateRange);
+ }
+#endif
+ //update bs info
+ pBsBuf += iPacketSize;
+ } //nal
+ } //layer
+
+#ifdef DEBUG_FILE_SAVE_CRA
+ //save to file
+ fwrite (ucBuf_, 1, iDecAuSize, fDataFile);
+ fflush (fDataFile);
+ iFileSize += iDecAuSize;
+
+ //save to len file
+ unsigned long ulTmp[4];
+ ulTmp[0] = ulTmp[1] = ulTmp[2] = iIdx;
+ ulTmp[3] = iDecAuSize;
+ fwrite (ulTmp, sizeof (unsigned long), 4, fLenFile); // index, timeStamp, data size
+ fflush (fLenFile);
+#endif
+
+ //decode
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+
+ rv = decoder_->DecodeFrame2 (ucBuf_, iDecAuSize, pData, &dstBufInfo_);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ //guarantee decoder EC status
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
+ } //frame
+ uiLoopRound ++;
+ if (uiLoopRound >= (1 << 30))
+ uiLoopRound = 0;
+#ifdef DEBUG_FILE_SAVE_CRA
+ if (uiLoopRound % 100 == 0)
+ printf ("run %d times.\n", uiLoopRound);
+ } while (1); //while (iLoopRound<100);
+ fclose (fDataFile);
+ fclose (fLenFile);
+#else
+ }
+ while (uiLoopRound < 10);
+#endif
+
+}
+
+const uint32_t kiTotalLayer = 3; //DO NOT CHANGE!
+const uint32_t kiSliceNum = 2; //DO NOT CHANGE!
+const uint32_t kiWidth = 160; //DO NOT CHANGE!
+const uint32_t kiHeight = 96; //DO NOT CHANGE!
+const uint32_t kiFrameRate = 12; //DO NOT CHANGE!
+const uint32_t kiFrameNum = 100; //DO NOT CHANGE!
+const char* pHashStr[] = { //DO NOT CHANGE!
+ "585663f78cadb70d9c9f179b9b53b90ffddf3178",
+ "f350001c333902029800bd291fbed915a4bdf19a",
+ "eb9d853b7daec03052c4850027ac94adc84c3a7e"
+};
+
+class DecodeParseAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
+ public:
+ void SetUp() {
+ SHA1Reset (&ctx_);
+ EncodeDecodeTestBase::SetUp();
+
+ if (decoder_)
+ decoder_->Uninitialize();
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ decParam.bParseOnly = true;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+ int rv = decoder_->Initialize (&decParam);
+ ASSERT_EQ (0, rv);
+ memset (&BsInfo_, 0, sizeof (SParserBsInfo));
+ fYuv_ = fopen ("./res/CiscoVT2people_160x96_6fps.yuv", "rb");
+ ASSERT_TRUE (fYuv_ != NULL);
+ iWidth_ = kiWidth;
+ iHeight_ = kiHeight;
+ }
+ void TearDown() {
+ EncodeDecodeTestBase::TearDown();
+ fclose (fYuv_);
+ }
+
+ void prepareEncDecParam (const EncodeDecodeFileParamBase p) {
+ EncodeDecodeTestBase::prepareEncDecParam (p);
+ unsigned char* pTmpPtr = BsInfo_.pDstBuff; //store for restore
+ memset (&BsInfo_, 0, sizeof (SParserBsInfo));
+ BsInfo_.pDstBuff = pTmpPtr;
+ }
+
+ void EncodeOneFrame (int iIdx) {
+ int iFrameSize = iWidth_ * iHeight_ * 3 / 2;
+ int iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
+ if (feof (fYuv_) || iSize != iFrameSize) {
+ rewind (fYuv_);
+ iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
+ ASSERT_TRUE (iSize == iFrameSize);
+ }
+ int rv = encoder_->EncodeFrame (&EncPic, &info);
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
+ }
+
+ void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
+ memset (pParam, 0, sizeof (SEncParamExt));
+ EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
+ }
+
+ protected:
+ SParserBsInfo BsInfo_;
+ FILE* fYuv_;
+ int iWidth_;
+ int iHeight_;
+ SHA1Context ctx_;
+};
+
+//#define DEBUG_FILE_SAVE
+TEST_F (DecodeParseAPI, ParseOnly_General) {
+ EncodeDecodeFileParamBase p;
+ p.width = iWidth_;
+ p.height = iHeight_;
+ p.frameRate = kiFrameRate;
+ p.numframes = kiFrameNum;
+ prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = kiTotalLayer;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == 0);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ uint32_t uiTargetLayerId = rand() % kiTotalLayer; //run only once
+#ifdef DEBUG_FILE_SAVE
+ FILE* fDec = fopen ("output.264", "wb");
+ FILE* fEnc = fopen ("enc.264", "wb");
+ FILE* fExtract = fopen ("extract.264", "wb");
+#endif
+ if (uiTargetLayerId < kiTotalLayer) { //should always be true
+ //Start for enc
+ int iLen = 0;
+ prepareEncDecParam (p);
+ int iFrame = 0;
+
+ while (iFrame < p.numframes) {
+ //encode
+ EncodeOneFrame (iFrame);
+ //extract target layer data
+ encToDecData (info, iLen);
+#ifdef DEBUG_FILE_SAVE
+ fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fEnc);
+#endif
+ ExtractDidNal (&info, iLen, &m_SLostSim, uiTargetLayerId);
+#ifdef DEBUG_FILE_SAVE
+ fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fExtract);
+#endif
+ //parseonly
+ //BsInfo_.pDstBuff = new unsigned char [1000000];
+ rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum != 0);
+ //get final output bs
+ iLen = 0;
+ int i = 0;
+ while (i < BsInfo_.iNalNum) {
+ iLen += BsInfo_.iNalLenInByte[i];
+ i++;
+ }
+#ifdef DEBUG_FILE_SAVE
+ fwrite (BsInfo_.pDstBuff, iLen, 1, fDec);
+#endif
+ SHA1Input (&ctx_, BsInfo_.pDstBuff, iLen);
+ iFrame++;
+ }
+ //calculate final SHA1 value
+ unsigned char digest[SHA_DIGEST_LENGTH];
+ SHA1Result (&ctx_, digest);
+ if (!HasFatalFailure()) {
+ CompareHash (digest, pHashStr[uiTargetLayerId]);
+ }
+ } //while
+#ifdef DEBUG_FILE_SAVE
+ fclose (fEnc);
+ fclose (fExtract);
+ fclose (fDec);
+#endif
+}
+
+//This case is for one layer only, for incomplete frame input
+//First slice is loss for random one picture with 2 slices per pic
+TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) {
+ int32_t iLayerNum = 1;
+ int32_t iSliceNum = 2;
+ EncodeDecodeFileParamBase p;
+ p.width = iWidth_;
+ p.height = iHeight_;
+ p.frameRate = kiFrameRate;
+ p.numframes = 5;
+ prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = iLayerNum;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == 0);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ int32_t iMissedPicNum = rand() % (p.numframes - 1) + 1; //IDR no loss
+ //Start for enc
+ int iLen = 0;
+ uint32_t uiGet;
+ prepareEncDecParam (p);
+ int iFrame = 0;
+
+ while (iFrame < p.numframes) {
+ //encode
+ EncodeOneFrame (iFrame);
+ //parseonly
+ if (iFrame == iMissedPicNum) { //make current frame partly missing
+ //Frame: P, first slice loss
+ int32_t iTotalSliceSize = 0;
+ encToDecSliceData (0, 0, info, iTotalSliceSize); //slice 1 lost
+ encToDecSliceData (0, 1, info, iLen); //slice 2
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, iLen, &BsInfo_);
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
+ EXPECT_TRUE (rv != 0);
+ } else { //normal frame, complete
+ encToDecData (info, iLen);
+ rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
+ EXPECT_TRUE (rv == 0); //parse correct
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
+ if (iFrame < iMissedPicNum) { //correct frames, all OK with output
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum != 0);
+ } else { //(iFrame > iMissedPicNum), should output nothing as error
+ EXPECT_TRUE (rv != 0);
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ }
+ }
+ iFrame++;
+ } //while
+}
+
+
+
--- /dev/null
+++ b/test/api/decoder_ec_test.cpp
@@ -1,0 +1,809 @@
+#include <gtest/gtest.h>
+#include "codec_def.h"
+#include "utils/BufferedData.h"
+#include "utils/FileInputStream.h"
+#include "BaseDecoderTest.h"
+#include "BaseEncoderTest.h"
+#include "wels_common_defs.h"
+#include <string>
+#include <vector>
+#include "encode_decode_api_test.h"
+using namespace WelsCommon;
+
+TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_DISABLE) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.bEnableLongTermReference = true;
+ param_.iLTRRefNum = 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ if (decoder_ != NULL) {
+ decoder_->Uninitialize();
+ }
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_DISABLE;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+ rv = decoder_->Initialize (&decParam);
+ ASSERT_EQ (0, rv);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ int iSkipedBytes;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ iSkipedBytes = SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx,
+ bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ if (iSkipedBytes && bVCLLoss) {
+ ASSERT_TRUE (dstBufInfo_.iBufferStatus == 0);
+ }
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_SLICE_COPY) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ int iSkipedBytes;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ iSkipedBytes = SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx,
+ bVCLLoss);
+ uint32_t uiEcIdc = rand() % 2 == 1 ? ERROR_CON_DISABLE : ERROR_CON_SLICE_COPY;
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+ (void) iSkipedBytes;
+}
+
+static const EncodeDecodeFileParamBase kFileParamArray[] = {
+ {300, 160, 96, 6.0f, 2, 1, "000000000000001010101010101010101010101001101010100000010101000011"},
+ {300, 140, 96, 6.0f, 4, 1, "000000000000001010101010101010101010101001101010100000010101000011"},
+ {300, 140, 96, 6.0f, 4, 1, "000000000000001010111010101011101010101001101010100000010101110011010101"},
+};
+
+INSTANTIATE_TEST_CASE_P (EncodeDecodeTestAPIBase, EncodeDecodeTestAPI,
+ ::testing::ValuesIn (kFileParamArray));
+
+TEST_P (EncodeDecodeTestAPI, SetOptionECIDC_GeneralSliceChange) {
+ uint32_t uiEcIdc;
+ uint32_t uiGet;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
+
+ uiEcIdc = 0;
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+
+ //Start for enc/dec
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int iIdx = 0;
+ bool bVCLLoss = false;
+ int iPacketNum;
+ int len;
+ int iTotalSliceSize;
+
+ //enc/dec pictures
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ //decoding after each encoding frame
+ len = 0;
+ iPacketNum = 0;
+ iTotalSliceSize = 0;
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ while (iPacketNum < info.sLayerInfo[0].iNalCount) {
+ encToDecSliceData (0, iPacketNum, info, len);
+ uiEcIdc = (ERROR_CON_IDC) (rand() % 2);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+
+ bVCLLoss = rand() & 1; //loss or not
+ if (!bVCLLoss) { //not loss
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize,
+ info.sLayerInfo[0].pNalLengthInByte[iPacketNum], pData, &dstBufInfo_);
+ if (uiEcIdc == ERROR_CON_DISABLE)
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ }
+ //EC_IDC should not change till now
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Set again inside
+ uiEcIdc = (ERROR_CON_IDC) (rand() % 2);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ //EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ if (uiEcIdc == ERROR_CON_DISABLE && rv != 0)
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+
+ //deal with next slice
+ iTotalSliceSize += len;
+ iPacketNum++;
+ } //while slice
+ iIdx++;
+ } //while frame
+}
+
+//This case contain 1 slice per picture
+//coding order: 0 1 2 3 4 5 6 7
+//frame type: IDR P P P P P P P
+//EC_IDC: 0 0 0 2 0 0 1 1
+//loss: N Y N N N Y Y N
+
+TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificFrameChange) {
+ uint32_t uiEcIdc;
+ uint32_t uiGet;
+ EncodeDecodeFileParamBase p = kFileParamArray[0];
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+
+ param_.iSpatialLayerNum = 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (ERROR_CON_IDC) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ //set EC=DISABLE
+ uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+
+ //Start for enc/dec
+ int iIdx = 0;
+ int len = 0;
+ unsigned char* pData[3] = { NULL };
+ InitialEncDec (p.width, p.height);
+ //Frame 0: IDR, EC_IDC=DISABLE, loss = 0
+ EncodeOneFrame (1);
+ encToDecData (info, len);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (ERROR_CON_IDC) ERROR_CON_DISABLE);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_EQ (rv, 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
+ iIdx++;
+
+ //Frame 1: P, EC_IDC=DISABLE, loss = 1
+ EncodeOneFrame (1);
+ iIdx++;
+
+ //Frame 2: P, EC_IDC=DISABLE, loss = 0
+ EncodeOneFrame (1);
+ encToDecData (info, len);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_TRUE (rv != 0); //construction error due to data loss
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output due to EC DISABLE
+ iIdx++;
+
+ //set EC=SLICE_COPY
+ uiEcIdc = (uint32_t) (ERROR_CON_SLICE_COPY);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 3: P, EC_IDC=SLICE_COPY, loss = 0
+ EncodeOneFrame (1);
+ encToDecData (info, len);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_TRUE (rv != 0); //construction error due to data loss
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
+ iIdx++;
+
+ //set EC=DISABLE
+ uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 4: P, EC_IDC=DISABLE, loss = 0
+ EncodeOneFrame (1);
+ encToDecData (info, len);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ //Ref picture is ECed, so current status is ECed, when EC disable, NO output
+ EXPECT_TRUE (rv != 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ iIdx++;
+
+ //Frame 5: P, EC_IDC=DISABLE, loss = 1
+ EncodeOneFrame (1);
+ iIdx++;
+
+ //set EC=FRAME_COPY
+ uiEcIdc = (uint32_t) (ERROR_CON_FRAME_COPY);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 6: P, EC_IDC=FRAME_COPY, loss = 1
+ EncodeOneFrame (1);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ iIdx++;
+
+ //Frame 7: P, EC_IDC=FRAME_COPY, loss = 0
+ EncodeOneFrame (1);
+ encToDecData (info, len);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_FRAME_COPY);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_TRUE (rv == 0); // Now the parse process is Error_None, and the reconstruction will has error return
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_TRUE (rv != 0); //not sure if previous data drop would be detected in construction
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
+ iIdx++;
+}
+
+//This case contain 2 slices per picture for IDR loss
+//coding order: 0 1 2 3 4
+//frame type IDR P P P P
+//EC_IDC 2 2 0 1 0
+//loss (2 slice: 1,2): 2 0 0 1 0
+
+TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRLoss) {
+ uint32_t uiEcIdc = 2; //default set as SLICE_COPY
+ uint32_t uiGet;
+ EncodeDecodeFileParamBase p = kFileParamArray[0];
+ prepareParamDefault (1, 2, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ //Start for enc/dec
+ int iIdx = 0;
+ int len = 0;
+ unsigned char* pData[3] = { NULL };
+ int iTotalSliceSize = 0;
+
+ InitialEncDec (p.width, p.height);
+
+ //Frame 0: IDR, EC_IDC=2, loss = 2
+ EncodeOneFrame (1);
+ iTotalSliceSize = 0;
+ encToDecSliceData (0, 0, info, len); //SPS
+ iTotalSliceSize = len;
+ encToDecSliceData (0, 1, info, len); //PPS
+ iTotalSliceSize += len;
+ encToDecSliceData (1, 0, info, len); //first slice
+ iTotalSliceSize += len;
+ //second slice loss
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iTotalSliceSize, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_EQ (rv, 0); // Reconstruct first slice OK
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //slice incomplete, no output
+ iIdx++;
+
+ //Frame 1: P, EC_IDC=2, loss = 0
+ //will clean SPS/PPS status
+ EncodeOneFrame (1);
+ encToDecData (info, len); //all slice together
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_TRUE ((rv & 32) != 0); //parse correct, but reconstruct ECed
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //ECed output for frame 0
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //ECed status, reconstruction current frame 1
+ EXPECT_TRUE ((rv & 32) != 0); //decoder ECed status
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //ECed output for frame 1
+ iIdx++;
+
+ //set EC=DISABLE
+ uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 2: P, EC_IDC=0, loss = 0
+ /////will clean SPS/PPS status
+ EncodeOneFrame (1);
+ encToDecData (info, len); //all slice together
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ // Ref picture is ECed, so reconstructed picture is ECed
+ EXPECT_TRUE ((rv & 32) != 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ iIdx++;
+
+ //set EC=SLICE_COPY
+ uiEcIdc = (uint32_t) (ERROR_CON_FRAME_COPY);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 3: P, EC_IDC=2, loss = 1
+ EncodeOneFrame (1);
+ encToDecSliceData (0, 0, info, iTotalSliceSize); //slice 1 lost
+ encToDecSliceData (0, 1, info, len); //slice 2
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_FRAME_COPY);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_TRUE ((rv & 32) != 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //slice loss
+ iIdx++;
+
+ //set EC=DISABLE
+ uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 4: P, EC_IDC=0, loss = 0
+ EncodeOneFrame (1);
+ encToDecData (info, len); //all slice
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_TRUE (rv != 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); // EC_IDC=0, previous picture slice lost, no output
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_TRUE (rv != 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); // No ref picture, no output
+ iIdx++;
+
+}
+
+
+
+//This case contain 2 slices per picture for no IDR loss
+//coding order: 0 1 2 3 4 5
+//frame type IDR P P P P IDR
+//EC_IDC 0 2 0 2 0 ^2^
+//loss (2 slice: 1,2): 0 0 1 2 0 0
+
+TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRNoLoss) {
+ uint32_t uiEcIdc;
+ uint32_t uiGet;
+ EncodeDecodeFileParamBase p = kFileParamArray[0];
+ prepareParamDefault (1, 2, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ //Start for enc/dec
+ int iIdx = 0;
+ int len = 0;
+ unsigned char* pData[3] = { NULL };
+ int iTotalSliceSize = 0;
+
+ InitialEncDec (p.width, p.height);
+
+ //set EC=DISABLE
+ uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 0: IDR, EC_IDC=0, loss = 0
+ //Expected result: all OK, 2nd Output
+ EncodeOneFrame (1);
+ encToDecData (info, len); //all slice
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //output frame 0
+ iIdx++;
+
+ //Frame 1: P, EC_IDC=0, loss = 0
+ //Expected result: all OK, 2nd Output
+ EncodeOneFrame (1);
+ encToDecData (info, len); //all slice together
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //ECed output for frame 0
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction current frame 1
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //ECed output for frame 1
+ iIdx++;
+
+ //Frame 2: P, EC_IDC=0, loss = 1
+ //Expected result: all OK, no Output
+ EncodeOneFrame (1);
+ encToDecSliceData (0, 0, info, iTotalSliceSize); // slice 1 lost
+ encToDecSliceData (0, 1, info, len); // slice 2 only
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_EQ (rv, 0); //parse correct
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+ iIdx++;
+
+ //set EC=SLICE_COPY
+ uiEcIdc = (uint32_t) (ERROR_CON_SLICE_COPY);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 3: P, EC_IDC=2, loss = 2
+ //Expected result: neither OK, 1st Output
+ EncodeOneFrame (1);
+ encToDecSliceData (0, 0, info, len); //slice 1 only
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_TRUE ((rv & 32) != 0); //parse OK but frame 2 ECed
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //slice loss but ECed output Frame 2
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ EXPECT_TRUE ((rv & 32) != 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //slice loss
+ iIdx++;
+
+ //set EC=DISABLE
+ uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ //Frame 4: P, EC_IDC=0, loss = 0
+ //Expected result: depends on DecodeFrame2 result. If OK, output; else ,no output
+ EncodeOneFrame (1);
+ encToDecData (info, len); //all slice
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ EXPECT_TRUE (rv != 0); //previous slice not outputted, will return error due to incomplete frame
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
+ // previous frame NOT output, no ref
+ EXPECT_TRUE (rv != 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
+ iIdx++;
+
+ //Frame 5: IDR, EC_IDC=2->0, loss = 0
+ //Expected result: depends on DecodeFrame2 result. If OK, output; else ,no output
+ int32_t iIDRPeriod = 1;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ EncodeOneFrame (1);
+ EXPECT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ encToDecSliceData (0, 0, info, len); //SPS
+ iTotalSliceSize = len;
+ encToDecSliceData (0, 1, info, len); //PPS
+ iTotalSliceSize += len;
+ encToDecSliceData (1, 0, info, len); //slice 1
+ iTotalSliceSize += len;
+ //set EC=SLICE_COPY for slice 1
+ uiEcIdc = (uint32_t) (ERROR_CON_SLICE_COPY);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iTotalSliceSize, pData, &dstBufInfo_);
+ EXPECT_TRUE (rv == 0); // IDR status return error_free
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //frame incomplete
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
+ EXPECT_TRUE (rv == 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
+ //set EC=DISABLE for slice 2
+ encToDecSliceData (1, 1, info, len); //slice 1
+ uiEcIdc = (int) (ERROR_CON_DISABLE);
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, uiEcIdc);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, len, pData, &dstBufInfo_);
+ EXPECT_EQ (rv, 0); //Parse correct under no EC
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //frame incomplete
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
+ EXPECT_EQ (rv, 0);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //output previous pic
+ iIdx++;
+
+}
+
+static const EncodeDecodeFileParamBase kSVCSwitch[] = {
+ {300, 160, 96, 6.0f, 2, 1, "120012130101012311201221323"},
+};
+
+TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_I) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = kSVCSwitch[0];
+ p.width = p.width << 2;
+ p.height = p.height << 2;
+ prepareParamDefault (4, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 4;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = (int32_t) pow (2.0f, (param_.iTemporalLayerNum - 1)) * ((rand() % 5) + 1);
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iTarDid = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ if (info.eFrameType == videoFrameTypeIDR) {
+ iTarDid = rand() % 4;
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+
+ ExtractDidNal (&info, len, &m_SLostSim, iTarDid);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_EQ (rv, 0);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, -1);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ ASSERT_EQ (rv, 0);
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_P) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = kSVCSwitch[0];
+ int iTarDid = 0;
+ int iLastDid = 0;
+ p.width = p.width << 2;
+ p.height = p.height << 2;
+ prepareParamDefault (4, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 4;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ if (iIdx < (int) strlen (p.pLossSequence)) {
+ switch (p.pLossSequence[iIdx]) {
+ case '0':
+ iTarDid = 0;
+ break;
+ case '1':
+ iTarDid = 1;
+ break;
+ case '2':
+ iTarDid = 2;
+ break;
+ case '3':
+ iTarDid = 3;
+ break;
+ default :
+ iTarDid = rand() % 4;
+ break;
+ }
+ } else {
+ iTarDid = rand() % 4;
+ }
+
+ ExtractDidNal (&info, len, &m_SLostSim, iTarDid);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, -1);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, false);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ if (info.eFrameType == videoFrameTypeP && iIdx > 0 && iLastDid != iTarDid) {
+ ASSERT_NE (rv, 0);
+ } else if (info.eFrameType == videoFrameTypeIDR) {
+ ASSERT_EQ (rv, 0);
+ }
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, false);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ iLastDid = iTarDid;
+ }
+}
+
+
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -5,7 +5,6 @@
#include "BaseDecoderTest.h"
#include "BaseEncoderTest.h"
#include "wels_common_defs.h"
-#include "utils/HashFunctions.h"
#include <string>
#include <vector>
#include "encode_decode_api_test.h"
@@ -112,23 +111,21 @@
void EncodeDecodeTestAPIBase::TestOneSimulcastAVC (SEncParamExt* pParam, ISVCDecoder** decoder, unsigned char** pBsBuf, int iSpatialLayerNum,
int iEncFrameNum,
- int iCallTimes) {
-//#define DEBUG_FILE_SAVE4
+ int iSaveFileIdx) {
int aLen[MAX_SPATIAL_LAYER_NUM] = {0, 0, 0, 0};
-#ifdef DEBUG_FILE_SAVE4
+
FILE* fEnc[MAX_SPATIAL_LAYER_NUM];
- if (iCallTimes == 0) {
+ if (iSaveFileIdx == 1) {
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 {
+ } else if (iSaveFileIdx > 1) {
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;
@@ -164,9 +161,10 @@
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
+ if (iSaveFileIdx > 0) {
+ fwrite (pBsBuf[iIdx], aLen[iIdx], 1, fEnc[iIdx]);
+ }
+
iResult = decoder[iIdx]->DecodeFrame2 (pBsBuf[iIdx], aLen[iIdx], pData, &dstBufInfo_);
EXPECT_TRUE (iResult == cmResultSuccess) << "iResult=" << iResult << ", LayerIdx=" << iIdx;
@@ -176,426 +174,14 @@
}
}
-#ifdef DEBUG_FILE_SAVE4
+ if (iSaveFileIdx > 0) {
fclose (fEnc[0]);
fclose (fEnc[1]);
fclose (fEnc[2]);
fclose (fEnc[3]);
-#endif
-}
-
-void EncodeDecodeTestAPIBase::InitialEncDec (int iWidth, int iHeight) {
-
- // for encoder
- // I420: 1(Y) + 1/4(U) + 1/4(V)
- int frameSize = iWidth * iHeight * 3 / 2;
-
- buf_.SetLength (frameSize);
- ASSERT_TRUE (buf_.Length() == (size_t)frameSize);
-
- memset (&EncPic, 0, sizeof (SSourcePicture));
- EncPic.iPicWidth = iWidth;
- EncPic.iPicHeight = iHeight;
- EncPic.iColorFormat = videoFormatI420;
- EncPic.iStride[0] = EncPic.iPicWidth;
- EncPic.iStride[1] = EncPic.iStride[2] = EncPic.iPicWidth >> 1;
- EncPic.pData[0] = buf_.data();
- EncPic.pData[1] = EncPic.pData[0] + iWidth * iHeight;
- EncPic.pData[2] = EncPic.pData[1] + (iWidth * iHeight >> 2);
-
- //for decoder
- memset (&info, 0, sizeof (SFrameBSInfo));
-
- //set a fixed random value
- iRandValue = rand() % 256;
-}
-
-void EncodeDecodeTestAPIBase::RandomParamExtCombination() {
-
- param_.iPicWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 2, MAX_WIDTH);
- param_.iPicHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 2, MAX_HEIGHT);
-
- param_.fMaxFrameRate = rand() % FRAME_RATE_RANGE + 0.5f;
- param_.iUsageType = static_cast<EUsageType> (rand() % 2);
- param_.iTemporalLayerNum = rand() % TEMPORAL_LAYER_NUM_RANGE;
- param_.iSpatialLayerNum = rand() % SPATIAL_LAYER_NUM_RANGE;
-
- param_.uiIntraPeriod = rand() - 1;
- param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
- param_.iMultipleThreadIdc = rand();
-
- int iValue = rand() % 7;
- switch (iValue) {
- case 0:
- param_.eSpsPpsIdStrategy = CONSTANT_ID;
- break;
- case 0x01:
- param_.eSpsPpsIdStrategy = INCREASING_ID;
- break;
- case 0x02:
- param_.eSpsPpsIdStrategy = SPS_LISTING;
- break;
- case 0x03:
- param_.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
- break;
- case 0x06:
- param_.eSpsPpsIdStrategy = SPS_PPS_LISTING;
- break;
- default:
- param_.eSpsPpsIdStrategy = CONSTANT_ID;
- break;
}
- param_.bPrefixNalAddingCtrl = (rand() % 2 == 0) ? false : true;
- param_.bEnableSSEI = (rand() % 2 == 0) ? false : true;
- param_.iPaddingFlag = rand() % 2;
-
- //LTR
- param_.bEnableLongTermReference = (rand() % 2 == 0) ? false : true;
- param_.bIsLosslessLink = (rand() % 2 == 0) ? false : true;
- param_.iLTRRefNum = rand();
- param_.iLtrMarkPeriod = rand();
-
- //loop filter
- param_.iLoopFilterDisableIdc = rand() % 7;
- param_.iLoopFilterAlphaC0Offset = rand();
- param_.iLoopFilterBetaOffset = rand();
-
- param_.bEnableDenoise = (rand() % 2 == 0) ? false : true;
- param_.bEnableBackgroundDetection = (rand() % 2 == 0) ? false : true;
- param_.bEnableAdaptiveQuant = (rand() % 2 == 0) ? false : true;
- param_.bEnableFrameCroppingFlag = (rand() % 2 == 0) ? false : true;
- param_.bEnableSceneChangeDetect = (rand() % 2 == 0) ? false : true;
-
- //for rc
- param_.iRCMode = static_cast<RC_MODES> (rand() % RC_MODE_RANGE - 1);
- param_.iMaxBitrate = rand() % BIT_RATE_RANGE;
- param_.iTargetBitrate = rand() % BIT_RATE_RANGE;
- param_.iMaxQp = rand() % QP_RANGE;
- param_.iMinQp = rand() % QP_RANGE;
- param_.uiMaxNalSize = rand();
- param_.bEnableFrameSkip = (rand() % 2 == 0) ? false : true;
-
- for (int iSpatialIdx = 0; iSpatialIdx < param_.iSpatialLayerNum; iSpatialIdx++) {
- if (iSpatialIdx < MAX_SPATIAL_LAYER_NUM) {
- SSpatialLayerConfig* pSpatialLayer = ¶m_.sSpatialLayers[iSpatialIdx];
-
- //to do: profile and level id
- //pSpatialLayer->uiProfileIdc = 0;
- //pSpatialLayer->uiLevelIdc = 0;
- pSpatialLayer->iVideoWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 2, MAX_WIDTH);
- pSpatialLayer->iVideoHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 2, MAX_HEIGHT);
- pSpatialLayer->fFrameRate = rand() % FRAME_RATE_RANGE + 0.5f;
- pSpatialLayer->iMaxSpatialBitrate = rand() % BIT_RATE_RANGE;
- pSpatialLayer->iSpatialBitrate = rand() % BIT_RATE_RANGE;
-
-
- pSpatialLayer->sSliceArgument.uiSliceMode = static_cast<SliceModeEnum> (rand() % SLICE_MODE_NUM);
- if (pSpatialLayer->sSliceArgument.uiSliceMode != SM_SIZELIMITED_SLICE) {
- param_.uiMaxNalSize = 0;
- }
- pSpatialLayer->sSliceArgument.uiSliceNum = rand();
- pSpatialLayer->sSliceArgument.uiSliceSizeConstraint = rand();
- }
- }
}
-void EncodeDecodeTestAPIBase::ValidateParamExtCombination() {
-
- bool bDynSliceModeFlag = false;
- unsigned int uiGOPSize = 0;
- unsigned int uiSliceNum = 0;
- int iTotalBitRate = 0;
- int iMinQP = 0;
-
- param_.iPicWidth = WELS_CLIP3 (param_.iPicWidth, 2, MAX_WIDTH);
- param_.iPicHeight = WELS_CLIP3 (param_.iPicHeight, 2, MAX_HEIGHT);
- param_.fMaxFrameRate = WELS_CLIP3 (param_.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
- param_.iTemporalLayerNum = WELS_CLIP3 (param_.iTemporalLayerNum, 1, MAX_TEMPORAL_LAYER_NUM);
-
- if (CAMERA_VIDEO_REAL_TIME == param_.iUsageType)
- param_.iSpatialLayerNum = WELS_CLIP3 (param_.iSpatialLayerNum, 1, MAX_SPATIAL_LAYER_NUM);
- else
- param_.iSpatialLayerNum = 1;
-
- //IntraPeriod
- uiGOPSize = 1 << (param_.iTemporalLayerNum - 1);
- param_.uiIntraPeriod -= param_.uiIntraPeriod % uiGOPSize;
-
- //RefNum
- int32_t iRefUpperBound = (param_.iUsageType == CAMERA_VIDEO_REAL_TIME) ?
- MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA : MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN;
- param_.iNumRefFrame = WELS_CLIP3 (param_.iNumRefFrame, MIN_REF_PIC_COUNT, iRefUpperBound);
-
- //to do: will add more validate logic for thread number
- param_.iMultipleThreadIdc = 1;
-
- //LTR
- //iLTRRefNum: not supported to set it arbitrary yet
- if (true == param_.bEnableLongTermReference) {
- param_.iLTRRefNum = (SCREEN_CONTENT_REAL_TIME == param_.iUsageType) ? LONG_TERM_REF_NUM_SCREEN : LONG_TERM_REF_NUM;
- param_.iLtrMarkPeriod = (0 == param_.iLtrMarkPeriod) ? 1 : param_.iLtrMarkPeriod;
-
- } else {
- param_.iLTRRefNum = 0;
- }
-
- //loop filter
- param_.iLoopFilterDisableIdc = param_.iLoopFilterDisableIdc % LOOP_FILTER_IDC_NUM;
- param_.iLoopFilterAlphaC0Offset = param_.iLoopFilterAlphaC0Offset % (2 * LOOF_FILTER_OFFSET_RANGE + 1) -
- LOOF_FILTER_OFFSET_RANGE;
- param_.iLoopFilterBetaOffset = param_.iLoopFilterBetaOffset % (2 * LOOF_FILTER_OFFSET_RANGE + 1) -
- LOOF_FILTER_OFFSET_RANGE;
-
- for (int iSpatialIdx = 0; iSpatialIdx < param_.iSpatialLayerNum; iSpatialIdx++) {
- SSpatialLayerConfig* pSpatialLayer = ¶m_.sSpatialLayers[iSpatialIdx];
- pSpatialLayer->iVideoWidth = param_.iPicWidth >> (param_.iSpatialLayerNum - 1 - iSpatialIdx);
- pSpatialLayer->iVideoHeight = param_.iPicHeight >> (param_.iSpatialLayerNum - 1 - iSpatialIdx);
- pSpatialLayer->fFrameRate = param_.fMaxFrameRate;
-
- pSpatialLayer->iMaxSpatialBitrate = WELS_CLIP3 (pSpatialLayer->iMaxSpatialBitrate, 1, BIT_RATE_RANGE);
- pSpatialLayer->iSpatialBitrate = WELS_CLIP3 (pSpatialLayer->iSpatialBitrate, 1, pSpatialLayer->iMaxSpatialBitrate);
- iTotalBitRate += pSpatialLayer->iSpatialBitrate;
-
- uiSliceNum = pSpatialLayer->sSliceArgument.uiSliceNum;
- pSpatialLayer->sSliceArgument.uiSliceNum = WELS_CLIP3 (uiSliceNum, 1, MAX_SLICES_NUM);
- pSpatialLayer->sSliceArgument.uiSliceSizeConstraint = 0;
-
-
- //for SM_FIXEDSLCNUM_SLICE
- // to do will add this when GOM bug fixed
- if (SM_FIXEDSLCNUM_SLICE == pSpatialLayer->sSliceArgument.uiSliceMode) {
- pSpatialLayer->sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
- }
-
- //for slice mode = SM_SIZELIMITED_SLICE
- if (SM_SIZELIMITED_SLICE == pSpatialLayer->sSliceArgument.uiSliceMode) {
- bDynSliceModeFlag = true;
- }
-
- //for slice mode = SM_RASTER_SLICE
- if (SM_RASTER_SLICE == pSpatialLayer->sSliceArgument.uiSliceMode) {
- if (0 != pSpatialLayer->sSliceArgument.uiSliceMbNum[0]) {
- SliceParamValidationForMode2 (iSpatialIdx);
- } else {
- SliceParamValidationForMode3 (iSpatialIdx);
- }
- }
- }
-
- //for RC
- if ((RC_QUALITY_MODE == param_.iRCMode) || (RC_BITRATE_MODE == param_.iRCMode)) {
- param_.bEnableFrameSkip = true;
- }
- if (param_.iTargetBitrate < iTotalBitRate) {
- param_.iTargetBitrate = iTotalBitRate;
- }
- if (param_.iMaxBitrate < param_.iTargetBitrate) {
- param_.iMaxBitrate = param_.iTargetBitrate;
- }
- param_.iMaxQp = WELS_CLIP3 (param_.iMaxQp, MIN_QP, MAX_QP);
- param_.iMinQp = WELS_CLIP3 (param_.iMinQp, MIN_QP, MAX_QP);
- iMinQP = (param_.iMaxQp < param_.iMinQp) ? param_.iMaxQp : param_.iMinQp;
- param_.iMaxQp = (param_.iMaxQp > param_.iMinQp) ? param_.iMaxQp : param_.iMinQp;
- param_.iMinQp = iMinQP;
- param_.uiMaxNalSize = 0;
-
- //for slice mode = SM_SIZELIMITED_SLICE
- if (true == bDynSliceModeFlag) {
- SliceParamValidationForMode4();
- }
-
-}
-
-
-void EncodeDecodeTestAPIBase::SliceParamValidationForMode2 (int iSpatialIdx) {
-
- unsigned int uiMbWidth = 0;
- unsigned int uiMbHeight = 0;
- unsigned int uiMbNumInFrame = 0;
- unsigned int uiCountMb = 0;
- unsigned int uiSliceIdx = 0;
- unsigned int uiActualSliceCount = 0;
-
- uiMbWidth = (param_.iPicWidth + 15) >> 4;
- uiMbHeight = (param_.iPicHeight + 15) >> 4;
- uiMbNumInFrame = uiMbWidth * uiMbHeight;
-
- uiSliceIdx = 0;
- while (uiSliceIdx < MAX_SLICES_NUM) {
- param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiSliceIdx] = rand() % uiMbNumInFrame;
- uiCountMb += param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiSliceIdx];
- uiActualSliceCount = uiSliceIdx + 1;
-
- if (uiCountMb >= uiMbNumInFrame) {
- break;
- }
-
- ++ uiSliceIdx;
- }
-
- if (uiCountMb >= uiMbNumInFrame) {
- param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiActualSliceCount - 1] -=
- (uiCountMb - uiMbNumInFrame);
-
- } else {
- param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiActualSliceCount - 1 ] +=
- (uiMbNumInFrame - uiCountMb);
- }
- param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceNum = uiActualSliceCount;
-
-}
-void EncodeDecodeTestAPIBase::SliceParamValidationForMode3 (int iSpatialIdx) {
-
- unsigned int uiMbHeight = 0;
-
- uiMbHeight = (param_.iPicHeight + 15) >> 4;
-
- //change slice mode to SM_SINGLE_SLICE
- if (uiMbHeight > MAX_SLICES_NUM) {
- param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
- }
-
-}
-
-void EncodeDecodeTestAPIBase::SliceParamValidationForMode4() {
- //slice mode of all spatial layer should be set as SM_SIZELIMITED_SLICE
- for (int iSpatialIdx = 0; iSpatialIdx < param_.iSpatialLayerNum; iSpatialIdx++) {
- param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceSizeConstraint = 600;
- param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMode = SM_SIZELIMITED_SLICE;
- }
- param_.uiMaxNalSize = 1500;
-}
-
-static const EncodeDecodeFileParamBase kFileParamArray[] = {
- {300, 160, 96, 6.0f, 2, 1, "000000000000001010101010101010101010101001101010100000010101000011"},
- {300, 140, 96, 6.0f, 4, 1, "000000000000001010101010101010101010101001101010100000010101000011"},
- {300, 140, 96, 6.0f, 4, 1, "000000000000001010111010101011101010101001101010100000010101110011010101"},
-};
-
-TEST_P (EncodeDecodeTestAPI, DecoderVclNal) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- InitialEncDec (p.width, p.height);
-
- int iIdx = 0;
- while (iIdx <= p.numframes) {
-
- EncodeOneFrame (0);
-
- //decoding after each encoding frame
- int vclNal, len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_TRUE (rv == cmResultSuccess);
- rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
- EXPECT_EQ (vclNal, FEEDBACK_UNKNOWN_NAL); //no reconstruction, unknown return
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- ASSERT_TRUE (rv == cmResultSuccess);
- rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
- EXPECT_EQ (vclNal, FEEDBACK_VCL_NAL);
- iIdx++;
- } //while
- //ignore last frame
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- InitialEncDec (p.width, p.height);
-
- int32_t iEncFrameNum = -1;
- int32_t iDecFrameNum;
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (0);
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
- EXPECT_EQ (iDecFrameNum, -1);
- iEncFrameNum++;
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
- EXPECT_EQ (iEncFrameNum, iDecFrameNum);
- iIdx++;
- } //while
- //ignore last frame
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionIDR) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- //init for encoder
- // I420: 1(Y) + 1/4(U) + 1/4(V)
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- InitialEncDec (p.width, p.height);
-
- int32_t iEncCurIdrPicId = 0;
- int32_t iDecCurIdrPicId;
- int32_t iIDRPeriod = 1;
- int32_t iSpsPpsIdAddition = 0;
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- iSpsPpsIdAddition = rand() %
- 2; //the current strategy supports more than 2 modes, but the switch between the modes>2 is not allowed
- iIDRPeriod = (rand() % 150) + 1;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
-
- EncodeOneFrame (0);
-
- if (info.eFrameType == videoFrameTypeIDR) {
- iEncCurIdrPicId = iEncCurIdrPicId + 1;
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
- EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
- EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
- iIdx++;
- } //while
- //ignore last frame
-}
-
-
long IsKeyFrameLost (ISVCDecoder* pDecoder, SLTRRecoverRequest* p_LTR_Recover_Request, long hr) {
long bLost = NO_RECOVERY_REQUSET;
int tempInt = -1;
@@ -785,3130 +371,5 @@
iSrcLen = iDstLen;
delete [] pDst;
return iSkipedBytes;
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLIDR) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- InitialEncDec (p.width, p.height);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = (int32_t) pow (2.0f, (param_.iTemporalLayerNum - 1)) * ((rand() % 5) + 1);
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (0);
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- encoder_->ForceIntraFrame (true);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLLTR) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- int frameSize = p.width * p.height * 3 / 2;
- buf_.SetLength (frameSize);
- ASSERT_TRUE (buf_.Length() == (size_t)frameSize);
- SFrameBSInfo info;
- memset (&info, 0, sizeof (SFrameBSInfo));
-
- SSourcePicture pic;
- memset (&pic, 0, sizeof (SSourcePicture));
- pic.iPicWidth = p.width;
- pic.iPicHeight = p.height;
- pic.iColorFormat = videoFormatI420;
- pic.iStride[0] = pic.iPicWidth;
- pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
- pic.pData[0] = buf_.data();
- pic.pData[1] = pic.pData[0] + p.width * p.height;
- pic.pData[2] = pic.pData[1] + (p.width * p.height >> 2);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- memset (buf_.data(), rand() % 256, frameSize);
- rv = encoder_->EncodeFrame (&pic, &info);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
- m_LTR_Recover_Request.uiFeedbackType = LTR_RECOVERY_REQUEST;
- m_LTR_Recover_Request.iCurrentFrameNum = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
- m_LTR_Recover_Request.uiIDRPicId = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
- m_LTR_Recover_Request.iLastCorrectFrameNum = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
- encoder_->SetOption (ENCODER_LTR_RECOVERY_REQUEST, &m_LTR_Recover_Request);
- m_LTR_Marking_Feedback.uiFeedbackType = rand() % 2 == 1 ? LTR_MARKING_SUCCESS : LTR_MARKING_FAILED;
- m_LTR_Marking_Feedback.uiIDRPicId = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
- m_LTR_Marking_Feedback.iLTRFrameNum = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
- encoder_->SetOption (ENCODER_LTR_MARKING_FEEDBACK, &m_LTR_Marking_Feedback);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionLTR_Engine) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_DISABLE) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.bEnableLongTermReference = true;
- param_.iLTRRefNum = 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- if (decoder_ != NULL) {
- decoder_->Uninitialize();
- }
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- decParam.uiTargetDqLayer = UCHAR_MAX;
- decParam.eEcActiveIdc = ERROR_CON_DISABLE;
- decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
- rv = decoder_->Initialize (&decParam);
- ASSERT_EQ (0, rv);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- int iSkipedBytes;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- iSkipedBytes = SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx,
- bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- if (iSkipedBytes && bVCLLoss) {
- ASSERT_TRUE (dstBufInfo_.iBufferStatus == 0);
- }
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_SLICE_COPY) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- int iSkipedBytes;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- iSkipedBytes = SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx,
- bVCLLoss);
- uint32_t uiEcIdc = rand() % 2 == 1 ? ERROR_CON_DISABLE : ERROR_CON_SLICE_COPY;
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
- (void) iSkipedBytes;
-}
-
-TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iSkipedBytes;
- unsigned long long uiEncTimeStamp = 100;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- uint32_t uiEcIdc = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- if (dstBufInfo_.iBufferStatus == 1) {
- EXPECT_EQ (uiEncTimeStamp, dstBufInfo_.uiOutYuvTimeStamp);
- }
- iIdx++;
- uiEncTimeStamp++;
- }
- (void) iSkipedBytes;
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.bPrefixNalAddingCtrl = false;
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- if (iTid != -1) {
- ASSERT_EQ (iTid, 0);
- }
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- std::vector<SLostSim>::iterator iter = m_SLostSim.begin();
- bool bHasVCL = false;
- for (unsigned int k = 0; k < m_SLostSim.size(); k++) {
- if (IS_VCL_NAL (iter->eNalType, 0) && iter->isLost == false) {
- bHasVCL = true;
- break;
- }
- iter++;
- }
- (void) bHasVCL;
- if (iTid != -1) {
- ASSERT_EQ (iTid, 0);
- }
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_WITH_PREFIX_NOLOSS) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.bPrefixNalAddingCtrl = true;
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- param_.iSpatialLayerNum = 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 0);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, -1);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionTid_SVC_L1_NOLOSS) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (2, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- param_.iSpatialLayerNum = 2;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 1);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, -1);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-
-
-TEST_P (EncodeDecodeTestAPI, SetOption_Trace) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = 1;
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- pFunc = TestOutPutTrace;
- pTraceInfo = &sTrace;
- sTrace.iTarLevel = iTraceLevel;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
-
-
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- iTraceLevel = rand() % 33;
- sTrace.iTarLevel = iTraceLevel;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 0);
- SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, SetOption_Trace_NULL) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = 1;
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- pFunc = NULL;
- pTraceInfo = NULL;
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- iTraceLevel = rand() % 33;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 0);
- SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-INSTANTIATE_TEST_CASE_P (EncodeDecodeTestAPIBase, EncodeDecodeTestAPI,
- ::testing::ValuesIn (kFileParamArray));
-
-TEST_P (EncodeDecodeTestAPI, SetOptionECIDC_GeneralSliceChange) {
- uint32_t uiEcIdc;
- uint32_t uiGet;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
-
- uiEcIdc = 0;
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
-
- //Start for enc/dec
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int iIdx = 0;
- bool bVCLLoss = false;
- int iPacketNum;
- int len;
- int iTotalSliceSize;
-
- //enc/dec pictures
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- //decoding after each encoding frame
- len = 0;
- iPacketNum = 0;
- iTotalSliceSize = 0;
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- while (iPacketNum < info.sLayerInfo[0].iNalCount) {
- encToDecSliceData (0, iPacketNum, info, len);
- uiEcIdc = (ERROR_CON_IDC) (rand() % 2);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
-
- bVCLLoss = rand() & 1; //loss or not
- if (!bVCLLoss) { //not loss
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize,
- info.sLayerInfo[0].pNalLengthInByte[iPacketNum], pData, &dstBufInfo_);
- if (uiEcIdc == ERROR_CON_DISABLE)
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- }
- //EC_IDC should not change till now
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Set again inside
- uiEcIdc = (ERROR_CON_IDC) (rand() % 2);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
-
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- //EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- if (uiEcIdc == ERROR_CON_DISABLE && rv != 0)
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
-
- //deal with next slice
- iTotalSliceSize += len;
- iPacketNum++;
- } //while slice
- iIdx++;
- } //while frame
-}
-
-//This case contain 1 slice per picture
-//coding order: 0 1 2 3 4 5 6 7
-//frame type: IDR P P P P P P P
-//EC_IDC: 0 0 0 2 0 0 1 1
-//loss: N Y N N N Y Y N
-
-TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificFrameChange) {
- uint32_t uiEcIdc;
- uint32_t uiGet;
- EncodeDecodeFileParamBase p = kFileParamArray[0];
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
-
- param_.iSpatialLayerNum = 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (ERROR_CON_IDC) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- //set EC=DISABLE
- uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
-
- //Start for enc/dec
- int iIdx = 0;
- int len = 0;
- unsigned char* pData[3] = { NULL };
- InitialEncDec (p.width, p.height);
- //Frame 0: IDR, EC_IDC=DISABLE, loss = 0
- EncodeOneFrame (1);
- encToDecData (info, len);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (ERROR_CON_IDC) ERROR_CON_DISABLE);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_EQ (rv, 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
- iIdx++;
-
- //Frame 1: P, EC_IDC=DISABLE, loss = 1
- EncodeOneFrame (1);
- iIdx++;
-
- //Frame 2: P, EC_IDC=DISABLE, loss = 0
- EncodeOneFrame (1);
- encToDecData (info, len);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_TRUE (rv != 0); //construction error due to data loss
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output due to EC DISABLE
- iIdx++;
-
- //set EC=SLICE_COPY
- uiEcIdc = (uint32_t) (ERROR_CON_SLICE_COPY);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 3: P, EC_IDC=SLICE_COPY, loss = 0
- EncodeOneFrame (1);
- encToDecData (info, len);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_TRUE (rv != 0); //construction error due to data loss
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
- iIdx++;
-
- //set EC=DISABLE
- uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 4: P, EC_IDC=DISABLE, loss = 0
- EncodeOneFrame (1);
- encToDecData (info, len);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- //Ref picture is ECed, so current status is ECed, when EC disable, NO output
- EXPECT_TRUE (rv != 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- iIdx++;
-
- //Frame 5: P, EC_IDC=DISABLE, loss = 1
- EncodeOneFrame (1);
- iIdx++;
-
- //set EC=FRAME_COPY
- uiEcIdc = (uint32_t) (ERROR_CON_FRAME_COPY);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 6: P, EC_IDC=FRAME_COPY, loss = 1
- EncodeOneFrame (1);
- EXPECT_EQ (uiGet, uiEcIdc);
- iIdx++;
-
- //Frame 7: P, EC_IDC=FRAME_COPY, loss = 0
- EncodeOneFrame (1);
- encToDecData (info, len);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_FRAME_COPY);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_TRUE (rv == 0); // Now the parse process is Error_None, and the reconstruction will has error return
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_TRUE (rv != 0); //not sure if previous data drop would be detected in construction
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
- iIdx++;
-}
-
-//This case contain 2 slices per picture for IDR loss
-//coding order: 0 1 2 3 4
-//frame type IDR P P P P
-//EC_IDC 2 2 0 1 0
-//loss (2 slice: 1,2): 2 0 0 1 0
-
-TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRLoss) {
- uint32_t uiEcIdc = 2; //default set as SLICE_COPY
- uint32_t uiGet;
- EncodeDecodeFileParamBase p = kFileParamArray[0];
- prepareParamDefault (1, 2, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- //Start for enc/dec
- int iIdx = 0;
- int len = 0;
- unsigned char* pData[3] = { NULL };
- int iTotalSliceSize = 0;
-
- InitialEncDec (p.width, p.height);
-
- //Frame 0: IDR, EC_IDC=2, loss = 2
- EncodeOneFrame (1);
- iTotalSliceSize = 0;
- encToDecSliceData (0, 0, info, len); //SPS
- iTotalSliceSize = len;
- encToDecSliceData (0, 1, info, len); //PPS
- iTotalSliceSize += len;
- encToDecSliceData (1, 0, info, len); //first slice
- iTotalSliceSize += len;
- //second slice loss
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iTotalSliceSize, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_EQ (rv, 0); // Reconstruct first slice OK
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //slice incomplete, no output
- iIdx++;
-
- //Frame 1: P, EC_IDC=2, loss = 0
- //will clean SPS/PPS status
- EncodeOneFrame (1);
- encToDecData (info, len); //all slice together
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_TRUE ((rv & 32) != 0); //parse correct, but reconstruct ECed
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //ECed output for frame 0
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //ECed status, reconstruction current frame 1
- EXPECT_TRUE ((rv & 32) != 0); //decoder ECed status
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //ECed output for frame 1
- iIdx++;
-
- //set EC=DISABLE
- uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 2: P, EC_IDC=0, loss = 0
- /////will clean SPS/PPS status
- EncodeOneFrame (1);
- encToDecData (info, len); //all slice together
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- // Ref picture is ECed, so reconstructed picture is ECed
- EXPECT_TRUE ((rv & 32) != 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- iIdx++;
-
- //set EC=SLICE_COPY
- uiEcIdc = (uint32_t) (ERROR_CON_FRAME_COPY);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 3: P, EC_IDC=2, loss = 1
- EncodeOneFrame (1);
- encToDecSliceData (0, 0, info, iTotalSliceSize); //slice 1 lost
- encToDecSliceData (0, 1, info, len); //slice 2
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_FRAME_COPY);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_TRUE ((rv & 32) != 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //slice loss
- iIdx++;
-
- //set EC=DISABLE
- uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 4: P, EC_IDC=0, loss = 0
- EncodeOneFrame (1);
- encToDecData (info, len); //all slice
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_TRUE (rv != 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); // EC_IDC=0, previous picture slice lost, no output
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_TRUE (rv != 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); // No ref picture, no output
- iIdx++;
-
-}
-
-
-
-//This case contain 2 slices per picture for no IDR loss
-//coding order: 0 1 2 3 4 5
-//frame type IDR P P P P IDR
-//EC_IDC 0 2 0 2 0 ^2^
-//loss (2 slice: 1,2): 0 0 1 2 0 0
-
-TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRNoLoss) {
- uint32_t uiEcIdc;
- uint32_t uiGet;
- EncodeDecodeFileParamBase p = kFileParamArray[0];
- prepareParamDefault (1, 2, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- //Start for enc/dec
- int iIdx = 0;
- int len = 0;
- unsigned char* pData[3] = { NULL };
- int iTotalSliceSize = 0;
-
- InitialEncDec (p.width, p.height);
-
- //set EC=DISABLE
- uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 0: IDR, EC_IDC=0, loss = 0
- //Expected result: all OK, 2nd Output
- EncodeOneFrame (1);
- encToDecData (info, len); //all slice
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //output frame 0
- iIdx++;
-
- //Frame 1: P, EC_IDC=0, loss = 0
- //Expected result: all OK, 2nd Output
- EncodeOneFrame (1);
- encToDecData (info, len); //all slice together
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //ECed output for frame 0
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction current frame 1
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //ECed output for frame 1
- iIdx++;
-
- //Frame 2: P, EC_IDC=0, loss = 1
- //Expected result: all OK, no Output
- EncodeOneFrame (1);
- encToDecSliceData (0, 0, info, iTotalSliceSize); // slice 1 lost
- encToDecSliceData (0, 1, info, len); // slice 2 only
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_EQ (rv, 0); //parse correct
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
- iIdx++;
-
- //set EC=SLICE_COPY
- uiEcIdc = (uint32_t) (ERROR_CON_SLICE_COPY);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 3: P, EC_IDC=2, loss = 2
- //Expected result: neither OK, 1st Output
- EncodeOneFrame (1);
- encToDecSliceData (0, 0, info, len); //slice 1 only
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_TRUE ((rv & 32) != 0); //parse OK but frame 2 ECed
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //slice loss but ECed output Frame 2
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- EXPECT_TRUE ((rv & 32) != 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //slice loss
- iIdx++;
-
- //set EC=DISABLE
- uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- //Frame 4: P, EC_IDC=0, loss = 0
- //Expected result: depends on DecodeFrame2 result. If OK, output; else ,no output
- EncodeOneFrame (1);
- encToDecData (info, len); //all slice
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- EXPECT_TRUE (rv != 0); //previous slice not outputted, will return error due to incomplete frame
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
- // previous frame NOT output, no ref
- EXPECT_TRUE (rv != 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
- iIdx++;
-
- //Frame 5: IDR, EC_IDC=2->0, loss = 0
- //Expected result: depends on DecodeFrame2 result. If OK, output; else ,no output
- int32_t iIDRPeriod = 1;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- EncodeOneFrame (1);
- EXPECT_TRUE (info.eFrameType == videoFrameTypeIDR);
- encToDecSliceData (0, 0, info, len); //SPS
- iTotalSliceSize = len;
- encToDecSliceData (0, 1, info, len); //PPS
- iTotalSliceSize += len;
- encToDecSliceData (1, 0, info, len); //slice 1
- iTotalSliceSize += len;
- //set EC=SLICE_COPY for slice 1
- uiEcIdc = (uint32_t) (ERROR_CON_SLICE_COPY);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iTotalSliceSize, pData, &dstBufInfo_);
- EXPECT_TRUE (rv == 0); // IDR status return error_free
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //frame incomplete
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
- EXPECT_TRUE (rv == 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
- //set EC=DISABLE for slice 2
- encToDecSliceData (1, 1, info, len); //slice 1
- uiEcIdc = (int) (ERROR_CON_DISABLE);
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, uiEcIdc);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, len, pData, &dstBufInfo_);
- EXPECT_EQ (rv, 0); //Parse correct under no EC
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //frame incomplete
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
- EXPECT_EQ (rv, 0);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //output previous pic
- iIdx++;
-
-}
-
-static const EncodeDecodeFileParamBase kSVCSwitch[] = {
- {300, 160, 96, 6.0f, 2, 1, "120012130101012311201221323"},
-};
-
-TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_I) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = kSVCSwitch[0];
- p.width = p.width << 2;
- p.height = p.height << 2;
- prepareParamDefault (4, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- param_.iSpatialLayerNum = 4;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = (int32_t) pow (2.0f, (param_.iTemporalLayerNum - 1)) * ((rand() % 5) + 1);
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iTarDid = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- if (info.eFrameType == videoFrameTypeIDR) {
- iTarDid = rand() % 4;
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
-
- ExtractDidNal (&info, len, &m_SLostSim, iTarDid);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_EQ (rv, 0);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, -1);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- ASSERT_EQ (rv, 0);
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_P) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- EncodeDecodeFileParamBase p = kSVCSwitch[0];
- int iTarDid = 0;
- int iLastDid = 0;
- p.width = p.width << 2;
- p.height = p.height << 2;
- prepareParamDefault (4, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- param_.iSpatialLayerNum = 4;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- InitialEncDec (p.width, p.height);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
-
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- if (iIdx < (int) strlen (p.pLossSequence)) {
- switch (p.pLossSequence[iIdx]) {
- case '0':
- iTarDid = 0;
- break;
- case '1':
- iTarDid = 1;
- break;
- case '2':
- iTarDid = 2;
- break;
- case '3':
- iTarDid = 3;
- break;
- default :
- iTarDid = rand() % 4;
- break;
- }
- } else {
- iTarDid = rand() % 4;
- }
-
- ExtractDidNal (&info, len, &m_SLostSim, iTarDid);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, -1);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, false);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- if (info.eFrameType == videoFrameTypeP && iIdx > 0 && iLastDid != iTarDid) {
- ASSERT_NE (rv, 0);
- } else if (info.eFrameType == videoFrameTypeIDR) {
- ASSERT_EQ (rv, 0);
- }
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, false);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- iLastDid = iTarDid;
- }
-}
-
-TEST_F (EncodeDecodeTestAPI, SetOptionEncParamExt) {
- int iSpatialLayerNum = 4;
- 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;
- encoder_->GetDefaultParams (¶m_);
- prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- int iTraceLevel = WELS_LOG_QUIET;
- rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- for (int i = 0; i < iEncFrameNum; i++) {
- int iResult;
- int len = 0;
- unsigned char* pData[3] = { NULL };
-
- RandomParamExtCombination();
- iResult = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ¶m_);
- //ValidateParamExtCombination();
- //ASSERT_TRUE (iResult == cmResultSuccess);
- //to do
- // currently, there are still some error cases even though under condition cmResultSuccess == iResult
- // so need to enhance the validation check for any random value of each variable in ParamExt
-
- if (cmResultSuccess == iResult) {
- InitialEncDec (param_.iPicWidth, param_.iPicHeight);
- EncodeOneFrame (0);
- encToDecData (info, len);
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
-
- iResult = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_TRUE (iResult == cmResultSuccess);
- iResult = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_);
- ASSERT_TRUE (iResult == cmResultSuccess);
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
- }
- }
-
- iTraceLevel = WELS_LOG_ERROR;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-}
-
-class DecodeCrashTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
- public:
- uint8_t iRandValue;
- public:
- void SetUp() {
- EncodeDecodeTestBase::SetUp();
- ucBuf_ = NULL;
- ucBuf_ = new unsigned char [1000000];
- ASSERT_TRUE (ucBuf_ != NULL);
- }
-
- void TearDown() {
- EncodeDecodeTestBase::TearDown();
- if (NULL != ucBuf_) {
- delete[] ucBuf_;
- ucBuf_ = NULL;
- }
- ASSERT_TRUE (ucBuf_ == NULL);
- }
-
- void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
- memset (pParam, 0, sizeof (SEncParamExt));
- EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
- }
-
- void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam);
- void EncodeOneFrame() {
- int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
- memset (buf_.data(), iRandValue, (frameSize >> 2));
- memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
- int rv = encoder_->EncodeFrame (&EncPic, &info);
- ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
- }
- protected:
- unsigned char* ucBuf_;
-};
-
-void DecodeCrashTestAPI::prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam) {
- // for encoder
- // I420: 1(Y) + 1/4(U) + 1/4(V)
- int frameSize = EncDecFileParam.width * EncDecFileParam.height * 3 / 2;
-
- buf_.SetLength (frameSize);
- ASSERT_TRUE (buf_.Length() == (size_t)frameSize);
-
- memset (&EncPic, 0, sizeof (SSourcePicture));
- EncPic.iPicWidth = EncDecFileParam.width;
- EncPic.iPicHeight = EncDecFileParam.height;
- EncPic.iColorFormat = videoFormatI420;
- EncPic.iStride[0] = EncPic.iPicWidth;
- EncPic.iStride[1] = EncPic.iStride[2] = EncPic.iPicWidth >> 1;
- EncPic.pData[0] = buf_.data();
- EncPic.pData[1] = EncPic.pData[0] + EncDecFileParam.width * EncDecFileParam.height;
- EncPic.pData[2] = EncPic.pData[1] + (EncDecFileParam.width * EncDecFileParam.height >> 2);
-
- //for decoder
- memset (&info, 0, sizeof (SFrameBSInfo));
-
- //set a fixed random value
- iRandValue = rand() % 256;
-}
-
-struct EncodeDecodeParamBase {
- int width;
- int height;
- float frameRate;
- int iTarBitrate;
-};
-
-#define NUM_OF_POSSIBLE_RESOLUTION (9)
-static const EncodeDecodeParamBase kParamArray[] = {
- {160, 90, 6.0f, 250000},
- {90, 160, 6.0f, 250000},
- {320, 180, 12.0f, 500000},
- {180, 320, 12.0f, 500000},
- {480, 270, 12.0f, 600000},
- {270, 480, 12.0f, 600000},
- {640, 360, 24.0f, 800000},
- {360, 640, 24.0f, 800000},
- {1280, 720, 24.0f, 1000000},
-};
-
-//#define DEBUG_FILE_SAVE_CRA
-TEST_F (DecodeCrashTestAPI, DecoderCrashTest) {
- uint32_t uiGet;
- encoder_->Uninitialize();
-
- //do tests until crash
- unsigned int uiLoopRound = 0;
- unsigned char* pucBuf = ucBuf_;
- int iDecAuSize;
-#ifdef DEBUG_FILE_SAVE_CRA
- //open file to save tested BS
- FILE* fDataFile = fopen ("test_crash.264", "wb");
- FILE* fLenFile = fopen ("test_crash_len.log", "w");
- int iFileSize = 0;
-#endif
-
- //set eCurStrategy for one test
- EParameterSetStrategy eCurStrategy = CONSTANT_ID;
- switch (rand() % 7) {
- case 1:
- eCurStrategy = INCREASING_ID;
- break;
- case 2:
- eCurStrategy = SPS_LISTING;
- break;
- case 3:
- eCurStrategy = SPS_LISTING_AND_PPS_INCREASING;
- break;
- case 6:
- eCurStrategy = SPS_PPS_LISTING;
- break;
- default:
- //using the initial value
- break;
- }
-
- do {
- int iTotalFrameNum = (rand() % 100) + 1;
- int iSeed = rand() % NUM_OF_POSSIBLE_RESOLUTION;
- EncodeDecodeParamBase p = kParamArray[iSeed];
-#ifdef DEBUG_FILE_SAVE_CRA
- printf ("using param set %d in loop %d\n", iSeed, uiLoopRound);
-#endif
- //Initialize Encoder
- prepareParam (1, 1, p.width, p.height, p.frameRate, ¶m_);
- param_.iRCMode = RC_TIMESTAMP_MODE;
- param_.iTargetBitrate = p.iTarBitrate;
- param_.uiIntraPeriod = 0;
- param_.eSpsPpsIdStrategy = eCurStrategy;
- param_.bEnableBackgroundDetection = true;
- param_.bEnableSceneChangeDetect = (rand() % 3) ? true : false;
- param_.bPrefixNalAddingCtrl = (rand() % 2) ? true : false;
- param_.iEntropyCodingModeFlag = 0;
- param_.bEnableFrameSkip = true;
- param_.iMultipleThreadIdc = 0;
- param_.sSpatialLayers[0].iSpatialBitrate = p.iTarBitrate;
- param_.sSpatialLayers[0].iMaxSpatialBitrate = p.iTarBitrate << 1;
- param_.sSpatialLayers[0].sSliceArgument.uiSliceMode = (rand() % 2) ? SM_SIZELIMITED_SLICE : SM_SINGLE_SLICE;
- if (param_.sSpatialLayers[0].sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE) {
- param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 1400;
- param_.uiMaxNalSize = 1400;
- } else {
- param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 0;
- param_.uiMaxNalSize = 0;
- }
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- //Start for enc/dec
- int iIdx = 0;
- unsigned char* pData[3] = { NULL };
-
- EncodeDecodeFileParamBase pInput; //to conform with old functions
- pInput.width = p.width;
- pInput.height = p.height;
- pInput.frameRate = p.frameRate;
- prepareEncDecParam (pInput);
- while (iIdx++ < iTotalFrameNum) { // loop in frame
- EncodeOneFrame();
-#ifdef DEBUG_FILE_SAVE_CRA
- //reset file if file size large
- if ((info.eFrameType == videoFrameTypeIDR) && (iFileSize >= (1 << 25))) {
- fclose (fDataFile);
- fDataFile = fopen ("test_crash.264", "wb");
- iFileSize = 0;
- decoder_->Uninitialize();
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- decParam.uiTargetDqLayer = UCHAR_MAX;
- decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
- decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
-
- rv = decoder_->Initialize (&decParam);
- ASSERT_EQ (0, rv);
- }
-#endif
- if (info.eFrameType == videoFrameTypeSkip)
- continue;
- //deal with packets
- unsigned char* pBsBuf;
- iDecAuSize = 0;
- pucBuf = ucBuf_; //init buf start pos for decoder usage
- for (int iLayerNum = 0; iLayerNum < info.iLayerNum; iLayerNum++) {
- SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayerNum];
- pBsBuf = info.sLayerInfo[iLayerNum].pBsBuf;
- int iTotalNalCnt = pLayerBsInfo->iNalCount;
- for (int iNalCnt = 0; iNalCnt < iTotalNalCnt; iNalCnt++) { //loop in NAL
- int iPacketSize = pLayerBsInfo->pNalLengthInByte[iNalCnt];
- //packet loss
- int iLossRateRange = (uiLoopRound % 100) + 1; //1-100
- int iLossRate = (rand() % iLossRateRange);
- bool bPacketLost = (rand() % 101) > (100 -
- iLossRate); // [0, (100-iLossRate)] indicates NO LOSS, (100-iLossRate, 100] indicates LOSS
- if (!bPacketLost) { //no loss
- memcpy (pucBuf, pBsBuf, iPacketSize);
- pucBuf += iPacketSize;
- iDecAuSize += iPacketSize;
- }
-#ifdef DEBUG_FILE_SAVE_CRA
- else {
- printf ("lost packet size=%d at frame-type=%d at loss rate %d (%d)\n", iPacketSize, info.eFrameType, iLossRate,
- iLossRateRange);
- }
-#endif
- //update bs info
- pBsBuf += iPacketSize;
- } //nal
- } //layer
-
-#ifdef DEBUG_FILE_SAVE_CRA
- //save to file
- fwrite (ucBuf_, 1, iDecAuSize, fDataFile);
- fflush (fDataFile);
- iFileSize += iDecAuSize;
-
- //save to len file
- unsigned long ulTmp[4];
- ulTmp[0] = ulTmp[1] = ulTmp[2] = iIdx;
- ulTmp[3] = iDecAuSize;
- fwrite (ulTmp, sizeof (unsigned long), 4, fLenFile); // index, timeStamp, data size
- fflush (fLenFile);
-#endif
-
- //decode
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
-
- rv = decoder_->DecodeFrame2 (ucBuf_, iDecAuSize, pData, &dstBufInfo_);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- //guarantee decoder EC status
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
- } //frame
- uiLoopRound ++;
- if (uiLoopRound >= (1 << 30))
- uiLoopRound = 0;
-#ifdef DEBUG_FILE_SAVE_CRA
- if (uiLoopRound % 100 == 0)
- printf ("run %d times.\n", uiLoopRound);
- } while (1); //while (iLoopRound<100);
- fclose (fDataFile);
- fclose (fLenFile);
-#else
- }
- while (uiLoopRound < 10);
-#endif
-
-}
-
-const uint32_t kiTotalLayer = 3; //DO NOT CHANGE!
-const uint32_t kiSliceNum = 2; //DO NOT CHANGE!
-const uint32_t kiWidth = 160; //DO NOT CHANGE!
-const uint32_t kiHeight = 96; //DO NOT CHANGE!
-const uint32_t kiFrameRate = 12; //DO NOT CHANGE!
-const uint32_t kiFrameNum = 100; //DO NOT CHANGE!
-const char* pHashStr[] = { //DO NOT CHANGE!
- "585663f78cadb70d9c9f179b9b53b90ffddf3178",
- "f350001c333902029800bd291fbed915a4bdf19a",
- "eb9d853b7daec03052c4850027ac94adc84c3a7e"
-};
-
-class DecodeParseAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
- public:
- void SetUp() {
- SHA1Reset (&ctx_);
- EncodeDecodeTestBase::SetUp();
-
- if (decoder_)
- decoder_->Uninitialize();
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- decParam.uiTargetDqLayer = UCHAR_MAX;
- decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
- decParam.bParseOnly = true;
- decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
-
- int rv = decoder_->Initialize (&decParam);
- ASSERT_EQ (0, rv);
- memset (&BsInfo_, 0, sizeof (SParserBsInfo));
- fYuv_ = fopen ("./res/CiscoVT2people_160x96_6fps.yuv", "rb");
- ASSERT_TRUE (fYuv_ != NULL);
- iWidth_ = kiWidth;
- iHeight_ = kiHeight;
- }
- void TearDown() {
- EncodeDecodeTestBase::TearDown();
- fclose (fYuv_);
- }
-
- void prepareEncDecParam (const EncodeDecodeFileParamBase p) {
- EncodeDecodeTestBase::prepareEncDecParam (p);
- unsigned char* pTmpPtr = BsInfo_.pDstBuff; //store for restore
- memset (&BsInfo_, 0, sizeof (SParserBsInfo));
- BsInfo_.pDstBuff = pTmpPtr;
- }
-
- void EncodeOneFrame (int iIdx) {
- int iFrameSize = iWidth_ * iHeight_ * 3 / 2;
- int iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
- if (feof (fYuv_) || iSize != iFrameSize) {
- rewind (fYuv_);
- iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
- ASSERT_TRUE (iSize == iFrameSize);
- }
- int rv = encoder_->EncodeFrame (&EncPic, &info);
- ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
- }
-
- void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
- memset (pParam, 0, sizeof (SEncParamExt));
- EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
- }
-
- protected:
- SParserBsInfo BsInfo_;
- FILE* fYuv_;
- int iWidth_;
- int iHeight_;
- SHA1Context ctx_;
-};
-
-//#define DEBUG_FILE_SAVE
-TEST_F (DecodeParseAPI, ParseOnly_General) {
- EncodeDecodeFileParamBase p;
- p.width = iWidth_;
- p.height = iHeight_;
- p.frameRate = kiFrameRate;
- p.numframes = kiFrameNum;
- prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = kiTotalLayer;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == 0);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- uint32_t uiTargetLayerId = rand() % kiTotalLayer; //run only once
-#ifdef DEBUG_FILE_SAVE
- FILE* fDec = fopen ("output.264", "wb");
- FILE* fEnc = fopen ("enc.264", "wb");
- FILE* fExtract = fopen ("extract.264", "wb");
-#endif
- if (uiTargetLayerId < kiTotalLayer) { //should always be true
- //Start for enc
- int iLen = 0;
- prepareEncDecParam (p);
- int iFrame = 0;
-
- while (iFrame < p.numframes) {
- //encode
- EncodeOneFrame (iFrame);
- //extract target layer data
- encToDecData (info, iLen);
-#ifdef DEBUG_FILE_SAVE
- fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fEnc);
-#endif
- ExtractDidNal (&info, iLen, &m_SLostSim, uiTargetLayerId);
-#ifdef DEBUG_FILE_SAVE
- fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fExtract);
-#endif
- //parseonly
- //BsInfo_.pDstBuff = new unsigned char [1000000];
- rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum != 0);
- //get final output bs
- iLen = 0;
- int i = 0;
- while (i < BsInfo_.iNalNum) {
- iLen += BsInfo_.iNalLenInByte[i];
- i++;
- }
-#ifdef DEBUG_FILE_SAVE
- fwrite (BsInfo_.pDstBuff, iLen, 1, fDec);
-#endif
- SHA1Input (&ctx_, BsInfo_.pDstBuff, iLen);
- iFrame++;
- }
- //calculate final SHA1 value
- unsigned char digest[SHA_DIGEST_LENGTH];
- SHA1Result (&ctx_, digest);
- if (!HasFatalFailure()) {
- CompareHash (digest, pHashStr[uiTargetLayerId]);
- }
- } //while
-#ifdef DEBUG_FILE_SAVE
- fclose (fEnc);
- fclose (fExtract);
- fclose (fDec);
-#endif
-}
-
-//This case is for one layer only, for incomplete frame input
-//First slice is loss for random one picture with 2 slices per pic
-TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) {
- int32_t iLayerNum = 1;
- int32_t iSliceNum = 2;
- EncodeDecodeFileParamBase p;
- p.width = iWidth_;
- p.height = iHeight_;
- p.frameRate = kiFrameRate;
- p.numframes = 5;
- prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = iLayerNum;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == 0);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- int32_t iMissedPicNum = rand() % (p.numframes - 1) + 1; //IDR no loss
- //Start for enc
- int iLen = 0;
- uint32_t uiGet;
- prepareEncDecParam (p);
- int iFrame = 0;
-
- while (iFrame < p.numframes) {
- //encode
- EncodeOneFrame (iFrame);
- //parseonly
- if (iFrame == iMissedPicNum) { //make current frame partly missing
- //Frame: P, first slice loss
- int32_t iTotalSliceSize = 0;
- encToDecSliceData (0, 0, info, iTotalSliceSize); //slice 1 lost
- encToDecSliceData (0, 1, info, iLen); //slice 2
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, iLen, &BsInfo_);
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
- EXPECT_TRUE (rv != 0);
- } else { //normal frame, complete
- encToDecData (info, iLen);
- rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
- EXPECT_TRUE (rv == 0); //parse correct
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
- if (iFrame < iMissedPicNum) { //correct frames, all OK with output
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum != 0);
- } else { //(iFrame > iMissedPicNum), should output nothing as error
- EXPECT_TRUE (rv != 0);
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- }
- }
- iFrame++;
- } //while
-}
-
-//#define DEBUG_FILE_SAVE2
-TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING1) {
-
- int iWidth = GetRandWidth();
- int iHeight = GetRandHeight();
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = 0;
- int iSpatialLayerNum = 1;
- int iSliceNum = 1;
-
- // prepare params
- SEncParamExt sParam1;
- SEncParamExt sParam2;
- SEncParamExt sParam3;
- encoder_->GetDefaultParams (&sParam1);
- prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
- sParam1.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
- //prepare param2
- memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
- while (GET_MB_WIDTH (sParam2.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth)) {
- sParam2.iPicWidth = GetRandWidth();
- }
- prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
- sParam2.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
- //prepare param3
- memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
- while (GET_MB_WIDTH (sParam3.iPicHeight) == GET_MB_WIDTH (sParam1.iPicHeight)) {
- sParam3.iPicHeight = GetRandHeight();
- }
- prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
- sParam3.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
-
- //prepare output if needed
- FILE* fEnc = NULL;
-#ifdef DEBUG_FILE_SAVE2
- fEnc = fopen ("enc2.264", "wb");
-#endif
-
- // Test part#1
- // step#1: pParam1
- //int TraceLevel = WELS_LOG_INFO;
- //encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
- int rv = encoder_->InitializeExt (&sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
- sParam1.iPicHeight;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- // new IDR
- rv = encoder_->ForceIntraFrame (true);
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- // step#2: pParam2
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam2.iPicWidth << "x" <<
- sParam2.iPicHeight;
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
- // new IDR
- rv = encoder_->ForceIntraFrame (true);
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
- // step#3: back to pParam1
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
- sParam1.iPicHeight;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- // step#4: back to pParam2
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << sParam2.iPicWidth << sParam2.iPicHeight;
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
-#ifdef DEBUG_FILE_SAVE2
- fclose (fEnc);
-#endif
- rv = encoder_->Uninitialize();
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
-
- // Test part#2
- // step#1: pParam1
- rv = encoder_->InitializeExt (&sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
-
-#ifdef DEBUG_FILE_SAVE2
- fEnc = fopen ("enc3.264", "wb");
-#endif
- iEncFrameNum = 0;
- EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
-
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
-#ifdef DEBUG_FILE_SAVE2
- fclose (fEnc);
-#endif
- rv = encoder_->Uninitialize();
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
-}
-
-//#define DEBUG_FILE_SAVE5
-TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING2) {
- //usage 3: 2 Params with different num_ref, encode IDR0, P1, IDR2;
- //the bs will show two SPS and different PPS
-
- int iWidth = GetRandWidth();
- int iHeight = GetRandHeight();
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = 0;
- int iSpatialLayerNum = 1;
- int iSliceNum = 1;
-
- // prepare params
- SEncParamExt sParam1;
- SEncParamExt sParam2;
- encoder_->GetDefaultParams (&sParam1);
- prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
- sParam1.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
- sParam1.iTemporalLayerNum = 1;
- //prepare param2
- memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
- prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
- sParam2.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
- sParam2.iTemporalLayerNum = 3;
-
- //prepare output if needed
- FILE* fEnc = NULL;
-#ifdef DEBUG_FILE_SAVE5
- fEnc = fopen ("encID2.264", "wb");
-#endif
-
- // step#1: pParam1
- int rv = encoder_->InitializeExt (&sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
- sParam1.iPicHeight;
-
- // step#2: pParam2
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
-
- // step#3: set back to pParam1, with a smaller num_ref, it still uses the previous SPS
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam1: rv = " << rv;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- // new IDR, PPS increases
- rv = encoder_->ForceIntraFrame (true);
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- rv = encoder_->Uninitialize();
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
-
-#ifdef DEBUG_FILE_SAVE5
- fclose (fEnc);
-#endif
-}
-
-TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING3) {
-
- int iWidth = GetRandWidth();
- int iHeight = GetRandHeight();
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = 0;
- int iSpatialLayerNum = 1;
- int iSliceNum = 1;
-
- // prepare params
- SEncParamExt sParam1;
- SEncParamExt sParam2;
- encoder_->GetDefaultParams (&sParam1);
- prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
- sParam1.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
-
- //prepare output if needed
- FILE* fEnc = NULL;
-#ifdef DEBUG_FILE_SAVE2
- fEnc = fopen ("enc4.264", "wb");
-#endif
-
- // step#1: pParam1
- int rv = encoder_->InitializeExt (&sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
-
- int max_count = 65; // make it more then twice as MAX_SPS_COUNT
- std::vector<int> vWidthTable;
- vWidthTable.push_back (GET_MB_WIDTH (sParam1.iPicWidth));
-
- std::vector<int>::iterator vWidthTableIt;
- for (int times = 0; times < max_count; times++) {
- //prepare param2
- memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
- do {
- sParam2.iPicWidth = GetRandWidth();
- vWidthTableIt = std::find (vWidthTable.begin(), vWidthTable.end(), GET_MB_WIDTH (sParam2.iPicWidth));
- } while (vWidthTableIt != vWidthTable.end());
- vWidthTable.push_back (GET_MB_WIDTH (sParam2.iPicWidth));
- prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
- sParam2.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
-
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv << ", sParam2.iPicWidth=" <<
- sParam2.iPicWidth;
- } // end of setting loop
-
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
-#ifdef DEBUG_FILE_SAVE2
- fclose (fEnc);
-#endif
- rv = encoder_->Uninitialize();
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
-}
-
-//#define DEBUG_FILE_SAVE6
-TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING1) {
- //usage 1: 1 resolution Params, encode IDR0, P1, IDR2;
- //the bs will show same SPS and different PPS
- // PPS: pic_parameter_set_id 1 ( 0)
- // PPS: seq_parameter_set_id 1 ( 0)
- // PPS: pic_parameter_set_id 010 ( 1)
- // PPS: seq_parameter_set_id 1 ( 0)
- // SH: slice_type 011 ( 2)
- // SH: pic_parameter_set_id 1 ( 0)
- // SH: slice_type 1 ( 0)
- // SH: pic_parameter_set_id 1 ( 0)
- // SH: slice_type 011 ( 2)
- // SH: pic_parameter_set_id 010 ( 1)
- int iWidth = GetRandWidth();
- int iHeight = GetRandHeight();
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = 0;
- int iSpatialLayerNum = 1;
- int iSliceNum = 1;
-
- // prepare params
- SEncParamExt sParam1;
- encoder_->GetDefaultParams (&sParam1);
- prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
- sParam1.eSpsPpsIdStrategy = SPS_PPS_LISTING;
-
- //prepare output if needed
- FILE* fEnc = NULL;
-#ifdef DEBUG_FILE_SAVE6
- fEnc = fopen ("encLIST1.264", "wb");
-#endif
-
- // step#1: pParam1
- int rv = encoder_->InitializeExt (&sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
- sParam1.iPicHeight;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- // new IDR
- rv = encoder_->ForceIntraFrame (true);
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- rv = encoder_->Uninitialize();
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
-
-#ifdef DEBUG_FILE_SAVE6
- fclose (fEnc);
-#endif
-}
-
-TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING2) {
- //usage 2: 2 resolution Params, encode IDR0, IDR1, IDR2;
- //the bs will show two SPS and different PPS
- // === SPS LIST ===
- //SPS: seq_parameter_set_id 1 ( 0) -- PARAM1
- //SPS: seq_parameter_set_id 010 ( 1) -- PARAM2
- // === PPS LIST ===
- //PPS: pic_parameter_set_id 1 ( 0)
- //PPS: seq_parameter_set_id 1 ( 0)
- //PPS: pic_parameter_set_id 010 ( 1)
- //PPS: seq_parameter_set_id 010 ( 1)
- //PPS: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0
- //PPS: seq_parameter_set_id 1 ( 0)
- //PPS: pic_parameter_set_id 00100 ( 3) -- PPS3 - SPS1
- //PPS: seq_parameter_set_id 010 ( 1)
- //PPS: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0
- //PPS: seq_parameter_set_id 1 ( 0)
- // === VCL LAYER ===
- //SH: slice_type 011 ( 2) -- PARAM2
- //SH: pic_parameter_set_id 010 ( 1) -- PPS1 - SPS1 - PARAM2
- //SH: slice_type 011 ( 2) -- PARAM1
- //SH: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0 - PARAM1
- //SH: slice_type 011 ( 2) -- PARAM1
- //SH: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0 - PARAM1
-
- int iWidth = GetRandWidth();
- int iHeight = GetRandHeight();
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = 0;
- int iSpatialLayerNum = 1;
- int iSliceNum = 1;
-
- // prepare params
- SEncParamExt sParam1;
- SEncParamExt sParam2;
- encoder_->GetDefaultParams (&sParam1);
- prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
- sParam1.eSpsPpsIdStrategy = SPS_PPS_LISTING;
- //prepare param2
- memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
- while (GET_MB_WIDTH (sParam2.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth)) {
- sParam2.iPicWidth = GetRandWidth();
- }
- prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
- sParam2.eSpsPpsIdStrategy = SPS_PPS_LISTING;
-
- //prepare output if needed
- FILE* fEnc = NULL;
-#ifdef DEBUG_FILE_SAVE5
- fEnc = fopen ("encLIST2.264", "wb");
-#endif
-
- // step#1: pParam1
- int rv = encoder_->InitializeExt (&sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
- sParam1.iPicHeight;
-
- // step#2: pParam2
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
- // step#3: back to pParam1, SHOULD NOT encounter ERROR
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
- sParam1.iPicHeight;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- // new IDR
- rv = encoder_->ForceIntraFrame (true);
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
- EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
-
- rv = encoder_->Uninitialize();
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
-
-#ifdef DEBUG_FILE_SAVE5
- fclose (fEnc);
-#endif
-}
-
-TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) {
-
- int iWidth = GetRandWidth();
- int iHeight = GetRandHeight();
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = 0;
- int iSpatialLayerNum = 1;
- int iSliceNum = 1;
-
- // prepare params
- SEncParamExt sParam1;
- SEncParamExt sParam2;
- SEncParamExt sParam3;
- encoder_->GetDefaultParams (&sParam1);
- prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
- sParam1.eSpsPpsIdStrategy = SPS_PPS_LISTING;
- //prepare param2
- memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
- while (GET_MB_WIDTH (sParam2.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth)) {
- sParam2.iPicWidth = GetRandWidth();
- }
- prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
- sParam2.eSpsPpsIdStrategy = SPS_PPS_LISTING;
- //prepare param3
- memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
- while (GET_MB_WIDTH (sParam3.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth) ||
- GET_MB_WIDTH (sParam3.iPicWidth) == GET_MB_WIDTH (sParam2.iPicWidth)) {
- sParam3.iPicWidth = GetRandWidth();
- }
- prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
- sParam3.eSpsPpsIdStrategy = SPS_PPS_LISTING;
-
- //prepare output if needed
- FILE* fEnc = NULL;
-#ifdef DEBUG_FILE_SAVE5
- fEnc = fopen ("enc4.264", "wb");
-#endif
-
- // step#1: ordinary encoding
- int rv = encoder_->InitializeExt (&sParam1);
- ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
- sParam1.iPicHeight;
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
- // step#2: set strategy for success
- int32_t iNewStra = SPS_PPS_LISTING;
- rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << " iNewStra=" << iNewStra;
-
- // step#3: setting new strategy, SHOULD encounter ERROR
- unsigned int TraceLevel = WELS_LOG_QUIET;
- rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
- ASSERT_TRUE (rv == cmResultSuccess);
- iNewStra = CONSTANT_ID;
- rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
- ASSERT_TRUE (rv != cmResultSuccess);
-
- EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
-
- // step#4: pParam3, SHOULD encounter ERROR
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
- ASSERT_TRUE (rv != cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam3.iPicWidth << "x" <<
- sParam3.iPicHeight;
-
- rv = encoder_->Uninitialize();
- ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
-
-#ifdef DEBUG_FILE_SAVE5
- fclose (fEnc);
-#endif
-}
-
-
-TEST_F (EncodeDecodeTestAPI, SimulcastSVC) {
- int iSpatialLayerNum = WelsClip3 ((rand() % MAX_SPATIAL_LAYER_NUM), 2, MAX_SPATIAL_LAYER_NUM);
- int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 16, MAX_WIDTH);
- int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 16, MAX_HEIGHT);
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
- int iSliceNum = 1;
- encoder_->GetDefaultParams (¶m_);
- prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- 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[MAX_SPATIAL_LAYER_NUM] = { NULL };
- fEnc[0] = fopen ("enc0.264", "wb");
- fEnc[1] = fopen ("enc1.264", "wb");
- fEnc[2] = fopen ("enc2.264", "wb");
- fEnc[3] = fopen ("enc3.264", "wb");
-#endif
-
- // init decoders
- 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);
- EXPECT_TRUE (decoder[iIdx] != NULL);
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- 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);
- }
-
- for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
- int iResult;
- int iLayerLen = 0;
- unsigned char* pData[3] = { NULL };
-
- InitialEncDec (param_.iPicWidth, param_.iPicHeight);
- EncodeOneFrame (0);
-
- iLayerLen = 0;
- 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];
- }
-
- if (layerInfo.uiLayerType == NON_VIDEO_CODING_LAYER) {
- // under SimulcastSVC, need to copy non-VCL to all layers
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- memcpy ((pBsBuf[iIdx] + aLen[iIdx]), layerInfo.pBsBuf, iLayerLen * sizeof (unsigned char));
- aLen[iIdx] += iLayerLen;
- }
- } else {
- iIdx = layerInfo.uiSpatialId;
- EXPECT_TRUE (iIdx < 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_SAVE2
- 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;
- }
- }
-
- // free all
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- if (pBsBuf[iIdx]) {
- free (pBsBuf[iIdx]);
- }
-
- if (decoder[iIdx] != NULL) {
- decoder[iIdx]->Uninitialize();
- WelsDestroyDecoder (decoder[iIdx]);
- }
-
-#ifdef DEBUG_FILE_SAVE2
- fclose (fEnc[iIdx]);
-#endif
- }
-
-}
-
-TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
-//#define DEBUG_FILE_SAVE3
- int iSpatialLayerNum = WelsClip3 ((rand() % MAX_SPATIAL_LAYER_NUM), 2, MAX_SPATIAL_LAYER_NUM);
- int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 16, MAX_WIDTH);
- int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 16, MAX_HEIGHT);
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
- int iSliceNum = 1;
- encoder_->GetDefaultParams (¶m_);
- prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
-
- //set flag of bSimulcastAVC
- param_.bSimulcastAVC = true;
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- 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[MAX_SPATIAL_LAYER_NUM];
- fEnc[0] = fopen ("enc0.264", "wb");
- fEnc[1] = fopen ("enc1.264", "wb");
- fEnc[2] = fopen ("enc2.264", "wb");
- fEnc[3] = fopen ("enc3.264", "wb");
-#endif
-
- int iIdx = 0;
-
- //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);
- EXPECT_TRUE (decoder[iIdx] != NULL);
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- 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);
- }
-
- iEncFrameNum = 10;
- for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
- int iResult;
- int iLayerLen = 0;
- unsigned char* pData[3] = { NULL };
-
- InitialEncDec (param_.iPicWidth, param_.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];
- const int kiFirstNalType = ((* (layerInfo.pBsBuf + 4)) & 0x1f);
- ASSERT_TRUE ((kiFirstNalType == NAL_SPS) || (kiFirstNalType == NAL_PPS) || (kiFirstNalType == NAL_SLICE)
- || (kiFirstNalType == NAL_SLICE_IDR) || (kiFirstNalType == NAL_SEI));
- for (int iNal = 0; iNal < layerInfo.iNalCount; ++iNal) {
- iLayerLen += layerInfo.pNalLengthInByte[iNal];
- }
-
- iIdx = layerInfo.uiSpatialId;
- EXPECT_TRUE (iIdx < 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_SAVE3
- 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;
- }
- }
-
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- free (pBsBuf[iIdx]);
-
- if (decoder[iIdx] != NULL) {
- decoder[iIdx]->Uninitialize();
- WelsDestroyDecoder (decoder[iIdx]);
- }
- }
-#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
- for (int i = 0; i <)MAX_SPATIAL_LAYER_NUM;
- i++) {
- fclose (fEnc[i]);
- }
-#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;
- iWidth = VALID_SIZE (iWidth);
- iHeight = VALID_SIZE (iHeight);
- // 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 (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.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]);
- }
-
- }
-}
-
-struct EncodeOptionParam {
- bool bTestNalSize;
- bool bAllRandom;
- bool bTestDecoder;
- int iNumframes;
- int iWidth;
- int iHeight;
- int iQp;
- SliceModeEnum eSliceMode;
- int uiMaxNalLen;
- float fFramerate;
- int iThreads;
- const char* sFileSave;
-};
-
-static const EncodeOptionParam kOptionParamArray[] = {
- {true, true, false, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 1, ""},
- {true, true, false, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 1, ""},
- {true, true, false, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, true, false, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, true, false, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, true, false, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, false, true, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 1, ""},
- {true, false, true, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 1, ""},
- {true, false, true, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, false, true, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, false, true, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, false, true, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, true, true, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 1, ""},
- {true, true, true, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 1, ""},
- {true, true, true, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, true, true, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, true, true, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {true, true, true, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {false, false, true, 3, 4096, 2304, 2, SM_SINGLE_SLICE, 0, 7.5, 1, ""}, // large picture size
- {false, true, false, 30, 32, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
- {false, true, false, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 4, ""},
- {false, true, false, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 2, ""},
- {false, true, false, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 3, ""},
- {false, true, false, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 2, ""},
- {false, true, false, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 2, ""},
- {false, true, false, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 3, ""},
- {false, true, false, 30, 32, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 3, ""},
- {false, false, true, 30, 600, 460, 1, SM_FIXEDSLCNUM_SLICE, 0, 15.0, 4, ""},
- {false, false, true, 30, 600, 460, 1, SM_FIXEDSLCNUM_SLICE, 0, 15.0, 8, ""},
-};
-
-class EncodeTestAPI : public ::testing::TestWithParam<EncodeOptionParam>, public ::EncodeDecodeTestAPIBase {
- public:
- void SetUp() {
- EncodeDecodeTestAPIBase::SetUp();
- }
-
- void TearDown() {
- EncodeDecodeTestAPIBase::TearDown();
- }
- void EncodeOneFrameRandom (int iCheckTypeIndex, bool bAllRandom) {
- int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
- uint8_t* ptr = buf_.data();
- uint8_t uiVal = rand() % 256;
- for (int i = 0; i < frameSize; i++) {
- ptr[i] = bAllRandom ? (rand() % 256) : uiVal;
- }
- int rv = encoder_->EncodeFrame (&EncPic, &info);
- if (0 == iCheckTypeIndex)
- ASSERT_TRUE (rv == cmResultSuccess) << "rv=" << rv;
- else if (1 == iCheckTypeIndex)
- ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason) << "rv=" << rv;
- }
-};
-
-INSTANTIATE_TEST_CASE_P (EncodeDecodeTestAPIBase, EncodeTestAPI,
- ::testing::ValuesIn (kOptionParamArray));
-
-TEST_P (EncodeTestAPI, SetEncOptionSize) {
- EncodeOptionParam p = GetParam();
- FILE* pFile = NULL;
- if (p.sFileSave != NULL && strlen (p.sFileSave) > 0) {
- pFile = fopen (p.sFileSave, "wb");
- }
- memset (¶m_, 0, sizeof (SEncParamExt));
- encoder_->GetDefaultParams (¶m_);
- param_.uiMaxNalSize = p.uiMaxNalLen;
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- param_.iSpatialLayerNum = 1;
- param_.iUsageType = CAMERA_VIDEO_REAL_TIME;
- param_.iPicWidth = p.iWidth;
- param_.iPicHeight = p.iHeight;
- param_.fMaxFrameRate = p.fFramerate;
- param_.iRCMode = RC_OFF_MODE; //rc off
- param_.iMultipleThreadIdc = p.iThreads;
- param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
- param_.sSpatialLayers[0].iVideoWidth = p.iWidth ;
- param_.sSpatialLayers[0].iVideoHeight = p.iHeight;
- param_.sSpatialLayers[0].fFrameRate = p.fFramerate;
- param_.sSpatialLayers[0].sSliceArgument.uiSliceMode = p.eSliceMode;
- if (SM_FIXEDSLCNUM_SLICE == p.eSliceMode) {
- param_.sSpatialLayers[0].sSliceArgument.uiSliceNum = 8;
- }
-
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- InitialEncDec (p.iWidth, p.iHeight);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = (int32_t) pow (2.0f, (param_.iTemporalLayerNum - 1)) * ((rand() % 5) + 1);
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- int iIdx = 0;
- int iLen;
- unsigned char* pData[3] = { NULL };
-
- //FIXME: remove this after the multi-thread case is correctly handled in encoder
- if (p.iThreads > 1 && SM_SIZELIMITED_SLICE == p.eSliceMode) {
- p.bAllRandom = false;
- }
-
- while (iIdx <= p.iNumframes) {
- EncodeOneFrameRandom (0, p.bAllRandom);
- encToDecData (info, iLen);
- if (pFile) {
- fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, pFile);
- fflush (pFile);
- }
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- if (iLen && p.bTestDecoder) {
- rv = decoder_->DecodeFrameNoDelay (info.sLayerInfo[0].pBsBuf, iLen, pData, &dstBufInfo_);
- ASSERT_EQ (rv, 0);
- ASSERT_EQ (dstBufInfo_.iBufferStatus, 1);
- }
- int iLayer = 0;
- while (iLayer < info.iLayerNum) {
- SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayer];
- if (pLayerBsInfo != NULL) {
- int iNalIdx = WELS_MAX (pLayerBsInfo->iNalCount - 2, 0); // ignore last slice under single slice mode
- do {
- if (p.bTestNalSize) { // ignore the case that 2 MBs in one picture, and the multithreads case, enable them when code is ready
- ASSERT_GE (((int)param_.uiMaxNalSize), pLayerBsInfo->pNalLengthInByte[iNalIdx]);
- }
- -- iNalIdx;
- } while (iNalIdx >= 0);
- }
- ++ iLayer;
- }
- iIdx++;
- }
- if (pFile) {
- fclose (pFile);
- }
-}
-
-
-
-TEST_F (EncodeDecodeTestAPI, SimulcastAVCDiffFps) {
-//#define DEBUG_FILE_SAVE_SimulcastAVCDiffFps
- 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 = 30;
- int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
- int iSliceNum = 1;
- encoder_->GetDefaultParams (¶m_);
- prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
-
- //set flag of bSimulcastAVC
- param_.bSimulcastAVC = true;
- param_.iTemporalLayerNum = (rand() % 2) ? 3 : 4;
-
- unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
- int aLen[MAX_SPATIAL_LAYER_NUM] = {0};
- ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
-
-#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
- FILE* fEnc[MAX_SPATIAL_LAYER_NUM];
- fEnc[0] = fopen ("enc0.264", "wb");
- fEnc[1] = fopen ("enc1.264", "wb");
- fEnc[2] = fopen ("enc2.264", "wb");
- fEnc[3] = fopen ("enc3.264", "wb");
-#endif
-
- int iIdx = 0;
-
- //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);
- EXPECT_TRUE (decoder[iIdx] != NULL);
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- 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);
- }
-
-#define PATTERN_NUM (18)
- const int32_t iTemporalPattern[PATTERN_NUM][MAX_SPATIAL_LAYER_NUM] = { {2, 1, 1, 1}, {2, 2, 2, 1}, {4, 1, 1, 1}, {4, 2, 1, 1},
- {1, 2, 1, 1}, {1, 1, 2, 1}, {1, 4, 1, 1}, {2, 4, 2, 1}, {1, 4, 2, 1}, {1, 4, 4, 1},
- {1, 2, 2, 1}, {2, 1, 2, 1}, {1, 2, 4, 1},
- {1, 1, 1, 2}, {1, 2, 2, 2}, {1, 2, 2, 4}, {1, 2, 4, 2}, {1, 4, 4, 4},
- };
- for (int iPatternIdx = 0; iPatternIdx < PATTERN_NUM; iPatternIdx++) {
- for (int i = 0; i < iSpatialLayerNum; i++) {
- param_.sSpatialLayers[i].fFrameRate = (fFrameRate / iTemporalPattern[iPatternIdx][i]);
- }
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- iEncFrameNum = 10;
- int iInsertIdr = rand() % iEncFrameNum;
- for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
- int iResult;
- int iLayerLen = 0;
- unsigned char* pData[3] = { NULL };
-
- InitialEncDec (param_.iPicWidth, param_.iPicHeight);
- EncodeOneFrame (0);
-
- if (iInsertIdr == iFrame) {
- encoder_->ForceIntraFrame (true);
- }
-
- // init aLen for the current frame
- 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];
- const int kiFirstNalType = ((* (layerInfo.pBsBuf + 4)) & 0x1f);
- ASSERT_TRUE ((kiFirstNalType == NAL_SPS) || (kiFirstNalType == NAL_PPS) || (kiFirstNalType == NAL_SLICE)
- || (kiFirstNalType == NAL_SLICE_IDR) || (kiFirstNalType == NAL_SEI));
- for (int iNal = 0; iNal < layerInfo.iNalCount; ++iNal) {
- iLayerLen += layerInfo.pNalLengthInByte[iNal];
- }
-
- iIdx = layerInfo.uiSpatialId;
- EXPECT_TRUE (iIdx < 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));
-
- if (aLen[iIdx] > 0) {
-#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
- 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 << iPatternIdx;
- EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx;
- }
- }
- }
- }
-
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- free (pBsBuf[iIdx]);
-
- if (decoder[iIdx] != NULL) {
- decoder[iIdx]->Uninitialize();
- WelsDestroyDecoder (decoder[iIdx]);
- }
- }
-#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
- for (int i = 0; i < MAX_SPATIAL_LAYER_NUM; i++) {
- fclose (fEnc[i]);
- }
-#endif
-}
-
-TEST_F (EncodeDecodeTestAPI, DiffSlicingInDlayer) {
- int iSpatialLayerNum = 3;
- int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
- int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
- 2240);//TODO: use MAX_HEIGHT after the limit is removed
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
-
- // prepare params
- SEncParamExt sParam;
- encoder_->GetDefaultParams (&sParam);
- prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
- sParam.iMultipleThreadIdc = (rand() % 4) + 1;
- sParam.bSimulcastAVC = 1;
- sParam.sSpatialLayers[0].iVideoWidth = (iWidth >> 2);
- sParam.sSpatialLayers[0].iVideoHeight = (iHeight >> 2);
- sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_RASTER_SLICE;
- sParam.sSpatialLayers[1].sSliceArgument.uiSliceMbNum[0] = 0;
-
- sParam.sSpatialLayers[1].iVideoWidth = (iWidth >> 1);
- sParam.sSpatialLayers[1].iVideoHeight = (iHeight >> 1);
- sParam.sSpatialLayers[1].sSliceArgument.uiSliceMode = SM_RASTER_SLICE;
- sParam.sSpatialLayers[1].sSliceArgument.uiSliceMbNum[0] = 30;
- sParam.sSpatialLayers[1].sSliceArgument.uiSliceMbNum[1] = 32;
-
- sParam.sSpatialLayers[2].iVideoWidth = iWidth;
- sParam.sSpatialLayers[2].iVideoHeight = iHeight;
- sParam.sSpatialLayers[2].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
- sParam.sSpatialLayers[2].sSliceArgument.uiSliceNum = (rand() % 30) + 1;
-
- int rv = encoder_->InitializeExt (&sParam);
- ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
-
- unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
- ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
-
- int iIdx = 0;
-
- //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);
-
- long rv = WelsCreateDecoder (&decoder[iIdx]);
- ASSERT_EQ (0, rv);
- EXPECT_TRUE (decoder[iIdx] != NULL);
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- 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 (&sParam, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
-
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- free (pBsBuf[iIdx]);
-
- if (decoder[iIdx] != NULL) {
- decoder[iIdx]->Uninitialize();
- WelsDestroyDecoder (decoder[iIdx]);
- }
-
- }
-}
-
-TEST_F (EncodeDecodeTestAPI, DiffSlicingInDlayerMixed) {
- int iSpatialLayerNum = 2;
- int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
- int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
- 1120);//TODO: use MAX_HEIGHT after the limit is removed
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
-
- // prepare params
- SEncParamExt sParam;
- encoder_->GetDefaultParams (&sParam);
- prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
- sParam.iMultipleThreadIdc = (rand() % 4) + 1;
- sParam.bSimulcastAVC = 1;
- sParam.sSpatialLayers[0].iVideoWidth = (iWidth >> 2);
- sParam.sSpatialLayers[0].iVideoHeight = (iHeight >> 2);
- sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_RASTER_SLICE;
-
- sParam.sSpatialLayers[1].iVideoWidth = iWidth;
- sParam.sSpatialLayers[1].iVideoHeight = iHeight;
- sParam.sSpatialLayers[1].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
- sParam.sSpatialLayers[1].sSliceArgument.uiSliceNum = 1;
-
- int rv = encoder_->InitializeExt (&sParam);
- ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
-
- unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
- ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
-
- int iIdx = 0;
-
- //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);
-
- long rv = WelsCreateDecoder (&decoder[iIdx]);
- ASSERT_EQ (0, rv);
- EXPECT_TRUE (decoder[iIdx] != NULL);
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- 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 (&sParam, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
-
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- free (pBsBuf[iIdx]);
-
- if (decoder[iIdx] != NULL) {
- decoder[iIdx]->Uninitialize();
- WelsDestroyDecoder (decoder[iIdx]);
- }
-
- }
-}
-
-TEST_F (EncodeDecodeTestAPI, ThreadNumAndSliceNum) {
- int iSpatialLayerNum = 1;
- int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
- int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
- 2240);//TODO: use MAX_HEIGHT after the limit is removed
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
-
- // prepare params
- SEncParamExt sParam;
- encoder_->GetDefaultParams (&sParam);
- prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
- sParam.iMultipleThreadIdc = (rand() % 3) + 2;
- sParam.bSimulcastAVC = 1;
- sParam.sSpatialLayers[0].iVideoWidth = iWidth;
- sParam.sSpatialLayers[0].iVideoHeight = iHeight;
- sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
- sParam.sSpatialLayers[0].sSliceArgument.uiSliceNum = (rand() % 2) ? (sParam.iMultipleThreadIdc + 1) :
- (sParam.iMultipleThreadIdc - 1);
-
- int rv = encoder_->InitializeExt (&sParam);
- ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
-
- unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
- ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
-
- int iIdx = 0;
-
- //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);
-
- long rv = WelsCreateDecoder (&decoder[iIdx]);
- ASSERT_EQ (0, rv);
- EXPECT_TRUE (decoder[iIdx] != NULL);
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- 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 (&sParam, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
-
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- free (pBsBuf[iIdx]);
-
- if (decoder[iIdx] != NULL) {
- decoder[iIdx]->Uninitialize();
- WelsDestroyDecoder (decoder[iIdx]);
- }
-
- }
-}
-
-
-TEST_F (EncodeDecodeTestAPI, TriggerLoadBalancing) {
-//#define DEBUG_FILE_SAVE_TRIGGER
- int iSpatialLayerNum = 1;
- int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
- int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
- 2240);//TODO: use MAX_HEIGHT after the limit is removed
- float fFrameRate = rand() + 0.5f;
- int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
-
- // prepare params
- SEncParamExt sParam;
- encoder_->GetDefaultParams (&sParam);
- prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
- sParam.iMultipleThreadIdc = 4;
- sParam.bSimulcastAVC = 1;
- sParam.sSpatialLayers[0].iVideoWidth = iWidth;
- sParam.sSpatialLayers[0].iVideoHeight = iHeight;
- sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
- sParam.sSpatialLayers[0].sSliceArgument.uiSliceNum = sParam.iMultipleThreadIdc;
-
- int rv = encoder_->InitializeExt (&sParam);
- ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
-
- unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
- ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
-
- int iIdx = 0;
- int aLen[MAX_SPATIAL_LAYER_NUM] = {};
-
-#ifdef DEBUG_FILE_SAVE_TRIGGER
- FILE* fEnc = fopen ("trigger00.264", "wb");
- printf("Current Threads is %d\n", sParam.iMultipleThreadIdc);
-#endif
-
- //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);
-
- long rv = WelsCreateDecoder (&decoder[iIdx]);
- ASSERT_EQ (0, rv);
- EXPECT_TRUE (decoder[iIdx] != NULL);
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- 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);
- }
-
- rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam);
- ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed pParam: rv = " << rv;
-
- //begin testing
- for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
- int iResult;
- int iLayerLen = 0;
- unsigned char* pData[3] = { NULL };
-
- InitialEncDec (sParam.iPicWidth, sParam.iPicHeight);
- int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
- memset (buf_.data(), rand() % 256, (frameSize >> 2));
- memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
-
- int iStartStrip = 0;
- //during first half the complex strip is at top, then during the second half it is at bottom
- if (iFrame > iEncFrameNum / 2) {
- iStartStrip = EncPic.iPicHeight * EncPic.iPicWidth;
- }
- for (int k = 0; k < (EncPic.iPicHeight / 2); k++) {
- memset (buf_.data() + k * EncPic.iPicWidth + iStartStrip, rand() % 256, (EncPic.iPicWidth));
- }
-
- int rv = encoder_->EncodeFrame (&EncPic, &info);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- // 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_SAVE_TRIGGER
- fwrite (pBsBuf[iIdx], aLen[iIdx], 1, fEnc);
-#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;
- }
- }
-
- for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
- free (pBsBuf[iIdx]);
-
- if (decoder[iIdx] != NULL) {
- decoder[iIdx]->Uninitialize();
- WelsDestroyDecoder (decoder[iIdx]);
- }
- }
-#ifdef DEBUG_FILE_SAVE_TRIGGER
- fclose(fEnc);
-#endif
}
--- a/test/api/encode_decode_api_test.h
+++ b/test/api/encode_decode_api_test.h
@@ -5,7 +5,6 @@
#include "BaseDecoderTest.h"
#include "BaseEncoderTest.h"
#include "wels_common_defs.h"
-#include "utils/HashFunctions.h"
#include <string>
#include <vector>
using namespace WelsCommon;
@@ -66,11 +65,6 @@
int iTarLevel;
} STraceUnit;
-static void TestOutPutTrace (void* ctx, int level, const char* string) {
- STraceUnit* pTraceUnit = (STraceUnit*) ctx;
- EXPECT_LE (level, pTraceUnit->iTarLevel);
-}
-
class EncodeDecodeTestBase : public BaseEncoderTest, public BaseDecoderTest {
public:
uint8_t iRandValue;
@@ -160,4 +154,14 @@
};
+bool ToRemainDidNal (const unsigned char* pSrc, EWelsNalUnitType eNalType, int iTarDid);
+void ExtractDidNal (SFrameBSInfo* pBsInfo, int& iSrcLen, std::vector<SLostSim>* p_SLostSim, int iTarDid);
+int SimulateNALLoss (const unsigned char* pSrc, int& iSrcLen, std::vector<SLostSim>* p_SLostSim,
+ const char* pLossChars, bool bLossPara, int& iLossIdx, bool& bVCLLoss);
+long IsKeyFrameLost (ISVCDecoder* pDecoder, SLTRRecoverRequest* p_LTR_Recover_Request, long hr);
+bool IsLTRMarking (ISVCDecoder* pDecoder);
+void LTRRecoveryRequest (ISVCDecoder* pDecoder, ISVCEncoder* pEncoder, SLTRRecoverRequest* p_LTR_Recover_Request,
+ long hr, bool m_P2PmodeFlag);
+void LTRMarkFeedback (ISVCDecoder* pDecoder, ISVCEncoder* pEncoder, SLTRMarkingFeedback* p_LTR_Marking_Feedback,
+ long hr);
--- /dev/null
+++ b/test/api/encode_options_test.cpp
@@ -1,0 +1,1671 @@
+#include <gtest/gtest.h>
+#include "codec_def.h"
+#include "utils/BufferedData.h"
+#include "utils/FileInputStream.h"
+#include "BaseDecoderTest.h"
+#include "BaseEncoderTest.h"
+#include "wels_common_defs.h"
+#include <string>
+#include <vector>
+#include "encode_decode_api_test.h"
+using namespace WelsCommon;
+
+void EncodeDecodeTestAPIBase::InitialEncDec (int iWidth, int iHeight) {
+ // for encoder
+ // I420: 1(Y) + 1/4(U) + 1/4(V)
+ int frameSize = iWidth * iHeight * 3 / 2;
+
+ buf_.SetLength (frameSize);
+ ASSERT_TRUE (buf_.Length() == (size_t)frameSize);
+
+ memset (&EncPic, 0, sizeof (SSourcePicture));
+ EncPic.iPicWidth = iWidth;
+ EncPic.iPicHeight = iHeight;
+ EncPic.iColorFormat = videoFormatI420;
+ EncPic.iStride[0] = EncPic.iPicWidth;
+ EncPic.iStride[1] = EncPic.iStride[2] = EncPic.iPicWidth >> 1;
+ EncPic.pData[0] = buf_.data();
+ EncPic.pData[1] = EncPic.pData[0] + iWidth * iHeight;
+ EncPic.pData[2] = EncPic.pData[1] + (iWidth * iHeight >> 2);
+
+ //for decoder
+ memset (&info, 0, sizeof (SFrameBSInfo));
+
+ //set a fixed random value
+ iRandValue = rand() % 256;
+}
+
+void EncodeDecodeTestAPIBase::RandomParamExtCombination() {
+
+ param_.iPicWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 2, MAX_WIDTH);
+ param_.iPicHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 2, MAX_HEIGHT);
+
+ param_.fMaxFrameRate = rand() % FRAME_RATE_RANGE + 0.5f;
+ param_.iUsageType = static_cast<EUsageType> (rand() % 2);
+ param_.iTemporalLayerNum = rand() % TEMPORAL_LAYER_NUM_RANGE;
+ param_.iSpatialLayerNum = rand() % SPATIAL_LAYER_NUM_RANGE;
+
+ param_.uiIntraPeriod = rand() - 1;
+ param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
+ param_.iMultipleThreadIdc = rand();
+
+ int iValue = rand() % 7;
+ switch (iValue) {
+ case 0:
+ param_.eSpsPpsIdStrategy = CONSTANT_ID;
+ break;
+ case 0x01:
+ param_.eSpsPpsIdStrategy = INCREASING_ID;
+ break;
+ case 0x02:
+ param_.eSpsPpsIdStrategy = SPS_LISTING;
+ break;
+ case 0x03:
+ param_.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+ break;
+ case 0x06:
+ param_.eSpsPpsIdStrategy = SPS_PPS_LISTING;
+ break;
+ default:
+ param_.eSpsPpsIdStrategy = CONSTANT_ID;
+ break;
+ }
+ param_.bPrefixNalAddingCtrl = (rand() % 2 == 0) ? false : true;
+ param_.bEnableSSEI = (rand() % 2 == 0) ? false : true;
+ param_.iPaddingFlag = rand() % 2;
+
+ //LTR
+ param_.bEnableLongTermReference = (rand() % 2 == 0) ? false : true;
+ param_.bIsLosslessLink = (rand() % 2 == 0) ? false : true;
+ param_.iLTRRefNum = rand();
+ param_.iLtrMarkPeriod = rand();
+
+ //loop filter
+ param_.iLoopFilterDisableIdc = rand() % 7;
+ param_.iLoopFilterAlphaC0Offset = rand();
+ param_.iLoopFilterBetaOffset = rand();
+
+ param_.bEnableDenoise = (rand() % 2 == 0) ? false : true;
+ param_.bEnableBackgroundDetection = (rand() % 2 == 0) ? false : true;
+ param_.bEnableAdaptiveQuant = (rand() % 2 == 0) ? false : true;
+ param_.bEnableFrameCroppingFlag = (rand() % 2 == 0) ? false : true;
+ param_.bEnableSceneChangeDetect = (rand() % 2 == 0) ? false : true;
+
+ //for rc
+ param_.iRCMode = static_cast<RC_MODES> (rand() % RC_MODE_RANGE - 1);
+ param_.iMaxBitrate = rand() % BIT_RATE_RANGE;
+ param_.iTargetBitrate = rand() % BIT_RATE_RANGE;
+ param_.iMaxQp = rand() % QP_RANGE;
+ param_.iMinQp = rand() % QP_RANGE;
+ param_.uiMaxNalSize = rand();
+ param_.bEnableFrameSkip = (rand() % 2 == 0) ? false : true;
+
+ for (int iSpatialIdx = 0; iSpatialIdx < param_.iSpatialLayerNum; iSpatialIdx++) {
+ if (iSpatialIdx < MAX_SPATIAL_LAYER_NUM) {
+ SSpatialLayerConfig* pSpatialLayer = ¶m_.sSpatialLayers[iSpatialIdx];
+
+ //to do: profile and level id
+ //pSpatialLayer->uiProfileIdc = 0;
+ //pSpatialLayer->uiLevelIdc = 0;
+ pSpatialLayer->iVideoWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 2, MAX_WIDTH);
+ pSpatialLayer->iVideoHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 2, MAX_HEIGHT);
+ pSpatialLayer->fFrameRate = rand() % FRAME_RATE_RANGE + 0.5f;
+ pSpatialLayer->iMaxSpatialBitrate = rand() % BIT_RATE_RANGE;
+ pSpatialLayer->iSpatialBitrate = rand() % BIT_RATE_RANGE;
+
+
+ pSpatialLayer->sSliceArgument.uiSliceMode = static_cast<SliceModeEnum> (rand() % SLICE_MODE_NUM);
+ if (pSpatialLayer->sSliceArgument.uiSliceMode != SM_SIZELIMITED_SLICE) {
+ param_.uiMaxNalSize = 0;
+ }
+ pSpatialLayer->sSliceArgument.uiSliceNum = rand();
+ pSpatialLayer->sSliceArgument.uiSliceSizeConstraint = rand();
+ }
+ }
+}
+
+void EncodeDecodeTestAPIBase::ValidateParamExtCombination() {
+
+ bool bDynSliceModeFlag = false;
+ unsigned int uiGOPSize = 0;
+ unsigned int uiSliceNum = 0;
+ int iTotalBitRate = 0;
+ int iMinQP = 0;
+
+ param_.iPicWidth = WELS_CLIP3 (param_.iPicWidth, 2, MAX_WIDTH);
+ param_.iPicHeight = WELS_CLIP3 (param_.iPicHeight, 2, MAX_HEIGHT);
+ param_.fMaxFrameRate = WELS_CLIP3 (param_.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
+ param_.iTemporalLayerNum = WELS_CLIP3 (param_.iTemporalLayerNum, 1, MAX_TEMPORAL_LAYER_NUM);
+
+ if (CAMERA_VIDEO_REAL_TIME == param_.iUsageType)
+ param_.iSpatialLayerNum = WELS_CLIP3 (param_.iSpatialLayerNum, 1, MAX_SPATIAL_LAYER_NUM);
+ else
+ param_.iSpatialLayerNum = 1;
+
+ //IntraPeriod
+ uiGOPSize = 1 << (param_.iTemporalLayerNum - 1);
+ param_.uiIntraPeriod -= param_.uiIntraPeriod % uiGOPSize;
+
+ //RefNum
+ int32_t iRefUpperBound = (param_.iUsageType == CAMERA_VIDEO_REAL_TIME) ?
+ MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA : MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN;
+ param_.iNumRefFrame = WELS_CLIP3 (param_.iNumRefFrame, MIN_REF_PIC_COUNT, iRefUpperBound);
+
+ //to do: will add more validate logic for thread number
+ param_.iMultipleThreadIdc = 1;
+
+ //LTR
+ //iLTRRefNum: not supported to set it arbitrary yet
+ if (true == param_.bEnableLongTermReference) {
+ param_.iLTRRefNum = (SCREEN_CONTENT_REAL_TIME == param_.iUsageType) ? LONG_TERM_REF_NUM_SCREEN : LONG_TERM_REF_NUM;
+ param_.iLtrMarkPeriod = (0 == param_.iLtrMarkPeriod) ? 1 : param_.iLtrMarkPeriod;
+
+ } else {
+ param_.iLTRRefNum = 0;
+ }
+
+ //loop filter
+ param_.iLoopFilterDisableIdc = param_.iLoopFilterDisableIdc % LOOP_FILTER_IDC_NUM;
+ param_.iLoopFilterAlphaC0Offset = param_.iLoopFilterAlphaC0Offset % (2 * LOOF_FILTER_OFFSET_RANGE + 1) -
+ LOOF_FILTER_OFFSET_RANGE;
+ param_.iLoopFilterBetaOffset = param_.iLoopFilterBetaOffset % (2 * LOOF_FILTER_OFFSET_RANGE + 1) -
+ LOOF_FILTER_OFFSET_RANGE;
+
+ for (int iSpatialIdx = 0; iSpatialIdx < param_.iSpatialLayerNum; iSpatialIdx++) {
+ SSpatialLayerConfig* pSpatialLayer = ¶m_.sSpatialLayers[iSpatialIdx];
+ pSpatialLayer->iVideoWidth = param_.iPicWidth >> (param_.iSpatialLayerNum - 1 - iSpatialIdx);
+ pSpatialLayer->iVideoHeight = param_.iPicHeight >> (param_.iSpatialLayerNum - 1 - iSpatialIdx);
+ pSpatialLayer->fFrameRate = param_.fMaxFrameRate;
+
+ pSpatialLayer->iMaxSpatialBitrate = WELS_CLIP3 (pSpatialLayer->iMaxSpatialBitrate, 1, BIT_RATE_RANGE);
+ pSpatialLayer->iSpatialBitrate = WELS_CLIP3 (pSpatialLayer->iSpatialBitrate, 1, pSpatialLayer->iMaxSpatialBitrate);
+ iTotalBitRate += pSpatialLayer->iSpatialBitrate;
+
+ uiSliceNum = pSpatialLayer->sSliceArgument.uiSliceNum;
+ pSpatialLayer->sSliceArgument.uiSliceNum = WELS_CLIP3 (uiSliceNum, 1, MAX_SLICES_NUM);
+ pSpatialLayer->sSliceArgument.uiSliceSizeConstraint = 0;
+
+
+ //for SM_FIXEDSLCNUM_SLICE
+ // to do will add this when GOM bug fixed
+ if (SM_FIXEDSLCNUM_SLICE == pSpatialLayer->sSliceArgument.uiSliceMode) {
+ pSpatialLayer->sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
+ }
+
+ //for slice mode = SM_SIZELIMITED_SLICE
+ if (SM_SIZELIMITED_SLICE == pSpatialLayer->sSliceArgument.uiSliceMode) {
+ bDynSliceModeFlag = true;
+ }
+
+ //for slice mode = SM_RASTER_SLICE
+ if (SM_RASTER_SLICE == pSpatialLayer->sSliceArgument.uiSliceMode) {
+ if (0 != pSpatialLayer->sSliceArgument.uiSliceMbNum[0]) {
+ SliceParamValidationForMode2 (iSpatialIdx);
+ } else {
+ SliceParamValidationForMode3 (iSpatialIdx);
+ }
+ }
+ }
+
+ //for RC
+ if ((RC_QUALITY_MODE == param_.iRCMode) || (RC_BITRATE_MODE == param_.iRCMode)) {
+ param_.bEnableFrameSkip = true;
+ }
+ if (param_.iTargetBitrate < iTotalBitRate) {
+ param_.iTargetBitrate = iTotalBitRate;
+ }
+ if (param_.iMaxBitrate < param_.iTargetBitrate) {
+ param_.iMaxBitrate = param_.iTargetBitrate;
+ }
+ param_.iMaxQp = WELS_CLIP3 (param_.iMaxQp, MIN_QP, MAX_QP);
+ param_.iMinQp = WELS_CLIP3 (param_.iMinQp, MIN_QP, MAX_QP);
+ iMinQP = (param_.iMaxQp < param_.iMinQp) ? param_.iMaxQp : param_.iMinQp;
+ param_.iMaxQp = (param_.iMaxQp > param_.iMinQp) ? param_.iMaxQp : param_.iMinQp;
+ param_.iMinQp = iMinQP;
+ param_.uiMaxNalSize = 0;
+
+ //for slice mode = SM_SIZELIMITED_SLICE
+ if (true == bDynSliceModeFlag) {
+ SliceParamValidationForMode4();
+ }
+
+}
+
+
+void EncodeDecodeTestAPIBase::SliceParamValidationForMode2 (int iSpatialIdx) {
+
+ unsigned int uiMbWidth = 0;
+ unsigned int uiMbHeight = 0;
+ unsigned int uiMbNumInFrame = 0;
+ unsigned int uiCountMb = 0;
+ unsigned int uiSliceIdx = 0;
+ unsigned int uiActualSliceCount = 0;
+
+ uiMbWidth = (param_.iPicWidth + 15) >> 4;
+ uiMbHeight = (param_.iPicHeight + 15) >> 4;
+ uiMbNumInFrame = uiMbWidth * uiMbHeight;
+
+ uiSliceIdx = 0;
+ while (uiSliceIdx < MAX_SLICES_NUM) {
+ param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiSliceIdx] = rand() % uiMbNumInFrame;
+ uiCountMb += param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiSliceIdx];
+ uiActualSliceCount = uiSliceIdx + 1;
+
+ if (uiCountMb >= uiMbNumInFrame) {
+ break;
+ }
+
+ ++ uiSliceIdx;
+ }
+
+ if (uiCountMb >= uiMbNumInFrame) {
+ param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiActualSliceCount - 1] -=
+ (uiCountMb - uiMbNumInFrame);
+
+ } else {
+ param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMbNum[uiActualSliceCount - 1 ] +=
+ (uiMbNumInFrame - uiCountMb);
+ }
+ param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceNum = uiActualSliceCount;
+
+}
+void EncodeDecodeTestAPIBase::SliceParamValidationForMode3 (int iSpatialIdx) {
+
+ unsigned int uiMbHeight = 0;
+
+ uiMbHeight = (param_.iPicHeight + 15) >> 4;
+
+ //change slice mode to SM_SINGLE_SLICE
+ if (uiMbHeight > MAX_SLICES_NUM) {
+ param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
+ }
+
+}
+
+void EncodeDecodeTestAPIBase::SliceParamValidationForMode4() {
+ //slice mode of all spatial layer should be set as SM_SIZELIMITED_SLICE
+ for (int iSpatialIdx = 0; iSpatialIdx < param_.iSpatialLayerNum; iSpatialIdx++) {
+ param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceSizeConstraint = 600;
+ param_.sSpatialLayers[iSpatialIdx].sSliceArgument.uiSliceMode = SM_SIZELIMITED_SLICE;
+ }
+ param_.uiMaxNalSize = 1500;
+}
+
+TEST_F (EncodeDecodeTestAPI, SetOptionEncParamExt) {
+ int iSpatialLayerNum = 4;
+ 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;
+ encoder_->GetDefaultParams (¶m_);
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ int iTraceLevel = WELS_LOG_QUIET;
+ rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ for (int i = 0; i < iEncFrameNum; i++) {
+ int iResult;
+ int len = 0;
+ unsigned char* pData[3] = { NULL };
+
+ RandomParamExtCombination();
+ iResult = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ¶m_);
+ //ValidateParamExtCombination();
+ //ASSERT_TRUE (iResult == cmResultSuccess);
+ //to do
+ // currently, there are still some error cases even though under condition cmResultSuccess == iResult
+ // so need to enhance the validation check for any random value of each variable in ParamExt
+
+ if (cmResultSuccess == iResult) {
+ InitialEncDec (param_.iPicWidth, param_.iPicHeight);
+ EncodeOneFrame (0);
+ encToDecData (info, len);
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+
+ iResult = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_TRUE (iResult == cmResultSuccess);
+ iResult = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_);
+ ASSERT_TRUE (iResult == cmResultSuccess);
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
+ }
+ }
+
+ iTraceLevel = WELS_LOG_ERROR;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+}
+
+struct EncodeDecodeParamBase {
+ int width;
+ int height;
+ float frameRate;
+ int iTarBitrate;
+};
+
+//#define DEBUG_FILE_SAVE2
+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING1) {
+
+ int iWidth = GetRandWidth();
+ int iHeight = GetRandHeight();
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = 0;
+ int iSpatialLayerNum = 1;
+ int iSliceNum = 1;
+
+ // prepare params
+ SEncParamExt sParam1;
+ SEncParamExt sParam2;
+ SEncParamExt sParam3;
+ encoder_->GetDefaultParams (&sParam1);
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
+ sParam1.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+ //prepare param2
+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
+ while (GET_MB_WIDTH (sParam2.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth)) {
+ sParam2.iPicWidth = GetRandWidth();
+ }
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
+ sParam2.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+ //prepare param3
+ memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
+ while (GET_MB_WIDTH (sParam3.iPicHeight) == GET_MB_WIDTH (sParam1.iPicHeight)) {
+ sParam3.iPicHeight = GetRandHeight();
+ }
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
+ sParam3.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+
+ //prepare output if needed
+ FILE* fEnc = NULL;
+#ifdef DEBUG_FILE_SAVE2
+ fEnc = fopen ("enc2.264", "wb");
+#endif
+
+ // Test part#1
+ // step#1: pParam1
+ //int TraceLevel = WELS_LOG_INFO;
+ //encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
+ int rv = encoder_->InitializeExt (&sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
+ sParam1.iPicHeight;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ // new IDR
+ rv = encoder_->ForceIntraFrame (true);
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ // step#2: pParam2
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam2.iPicWidth << "x" <<
+ sParam2.iPicHeight;
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+ // new IDR
+ rv = encoder_->ForceIntraFrame (true);
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+ // step#3: back to pParam1
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
+ sParam1.iPicHeight;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ // step#4: back to pParam2
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << sParam2.iPicWidth << sParam2.iPicHeight;
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+#ifdef DEBUG_FILE_SAVE2
+ fclose (fEnc);
+#endif
+ rv = encoder_->Uninitialize();
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+
+ // Test part#2
+ // step#1: pParam1
+ rv = encoder_->InitializeExt (&sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
+
+#ifdef DEBUG_FILE_SAVE2
+ fEnc = fopen ("enc3.264", "wb");
+#endif
+ iEncFrameNum = 0;
+ EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
+
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+#ifdef DEBUG_FILE_SAVE2
+ fclose (fEnc);
+#endif
+ rv = encoder_->Uninitialize();
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+}
+
+//#define DEBUG_FILE_SAVE5
+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING2) {
+ //usage 3: 2 Params with different num_ref, encode IDR0, P1, IDR2;
+ //the bs will show two SPS and different PPS
+
+ int iWidth = GetRandWidth();
+ int iHeight = GetRandHeight();
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = 0;
+ int iSpatialLayerNum = 1;
+ int iSliceNum = 1;
+
+ // prepare params
+ SEncParamExt sParam1;
+ SEncParamExt sParam2;
+ encoder_->GetDefaultParams (&sParam1);
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
+ sParam1.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+ sParam1.iTemporalLayerNum = 1;
+ //prepare param2
+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
+ sParam2.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+ sParam2.iTemporalLayerNum = 3;
+
+ //prepare output if needed
+ FILE* fEnc = NULL;
+#ifdef DEBUG_FILE_SAVE5
+ fEnc = fopen ("encID2.264", "wb");
+#endif
+
+ // step#1: pParam1
+ int rv = encoder_->InitializeExt (&sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
+ sParam1.iPicHeight;
+
+ // step#2: pParam2
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
+
+ // step#3: set back to pParam1, with a smaller num_ref, it still uses the previous SPS
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam1: rv = " << rv;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ // new IDR, PPS increases
+ rv = encoder_->ForceIntraFrame (true);
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ rv = encoder_->Uninitialize();
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+
+#ifdef DEBUG_FILE_SAVE5
+ fclose (fEnc);
+#endif
+}
+
+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING3) {
+
+ int iWidth = GetRandWidth();
+ int iHeight = GetRandHeight();
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = 0;
+ int iSpatialLayerNum = 1;
+ int iSliceNum = 1;
+
+ // prepare params
+ SEncParamExt sParam1;
+ SEncParamExt sParam2;
+ encoder_->GetDefaultParams (&sParam1);
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
+ sParam1.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+
+ //prepare output if needed
+ FILE* fEnc = NULL;
+#ifdef DEBUG_FILE_SAVE2
+ fEnc = fopen ("enc4.264", "wb");
+#endif
+
+ // step#1: pParam1
+ int rv = encoder_->InitializeExt (&sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
+
+ int max_count = 65; // make it more then twice as MAX_SPS_COUNT
+ std::vector<int> vWidthTable;
+ vWidthTable.push_back (GET_MB_WIDTH (sParam1.iPicWidth));
+
+ std::vector<int>::iterator vWidthTableIt;
+ for (int times = 0; times < max_count; times++) {
+ //prepare param2
+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
+ do {
+ sParam2.iPicWidth = GetRandWidth();
+ vWidthTableIt = std::find (vWidthTable.begin(), vWidthTable.end(), GET_MB_WIDTH (sParam2.iPicWidth));
+ } while (vWidthTableIt != vWidthTable.end());
+ vWidthTable.push_back (GET_MB_WIDTH (sParam2.iPicWidth));
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
+ sParam2.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
+
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv << ", sParam2.iPicWidth=" <<
+ sParam2.iPicWidth;
+ } // end of setting loop
+
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+#ifdef DEBUG_FILE_SAVE2
+ fclose (fEnc);
+#endif
+ rv = encoder_->Uninitialize();
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+}
+
+//#define DEBUG_FILE_SAVE6
+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING1) {
+ //usage 1: 1 resolution Params, encode IDR0, P1, IDR2;
+ //the bs will show same SPS and different PPS
+ // PPS: pic_parameter_set_id 1 ( 0)
+ // PPS: seq_parameter_set_id 1 ( 0)
+ // PPS: pic_parameter_set_id 010 ( 1)
+ // PPS: seq_parameter_set_id 1 ( 0)
+ // SH: slice_type 011 ( 2)
+ // SH: pic_parameter_set_id 1 ( 0)
+ // SH: slice_type 1 ( 0)
+ // SH: pic_parameter_set_id 1 ( 0)
+ // SH: slice_type 011 ( 2)
+ // SH: pic_parameter_set_id 010 ( 1)
+ int iWidth = GetRandWidth();
+ int iHeight = GetRandHeight();
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = 0;
+ int iSpatialLayerNum = 1;
+ int iSliceNum = 1;
+
+ // prepare params
+ SEncParamExt sParam1;
+ encoder_->GetDefaultParams (&sParam1);
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
+ sParam1.eSpsPpsIdStrategy = SPS_PPS_LISTING;
+
+ //prepare output if needed
+ FILE* fEnc = NULL;
+#ifdef DEBUG_FILE_SAVE6
+ fEnc = fopen ("encLIST1.264", "wb");
+#endif
+
+ // step#1: pParam1
+ int rv = encoder_->InitializeExt (&sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
+ sParam1.iPicHeight;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ // new IDR
+ rv = encoder_->ForceIntraFrame (true);
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ rv = encoder_->Uninitialize();
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+
+#ifdef DEBUG_FILE_SAVE6
+ fclose (fEnc);
+#endif
+}
+
+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING2) {
+ //usage 2: 2 resolution Params, encode IDR0, IDR1, IDR2;
+ //the bs will show two SPS and different PPS
+ // === SPS LIST ===
+ //SPS: seq_parameter_set_id 1 ( 0) -- PARAM1
+ //SPS: seq_parameter_set_id 010 ( 1) -- PARAM2
+ // === PPS LIST ===
+ //PPS: pic_parameter_set_id 1 ( 0)
+ //PPS: seq_parameter_set_id 1 ( 0)
+ //PPS: pic_parameter_set_id 010 ( 1)
+ //PPS: seq_parameter_set_id 010 ( 1)
+ //PPS: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0
+ //PPS: seq_parameter_set_id 1 ( 0)
+ //PPS: pic_parameter_set_id 00100 ( 3) -- PPS3 - SPS1
+ //PPS: seq_parameter_set_id 010 ( 1)
+ //PPS: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0
+ //PPS: seq_parameter_set_id 1 ( 0)
+ // === VCL LAYER ===
+ //SH: slice_type 011 ( 2) -- PARAM2
+ //SH: pic_parameter_set_id 010 ( 1) -- PPS1 - SPS1 - PARAM2
+ //SH: slice_type 011 ( 2) -- PARAM1
+ //SH: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0 - PARAM1
+ //SH: slice_type 011 ( 2) -- PARAM1
+ //SH: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0 - PARAM1
+
+ int iWidth = GetRandWidth();
+ int iHeight = GetRandHeight();
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = 0;
+ int iSpatialLayerNum = 1;
+ int iSliceNum = 1;
+
+ // prepare params
+ SEncParamExt sParam1;
+ SEncParamExt sParam2;
+ encoder_->GetDefaultParams (&sParam1);
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
+ sParam1.eSpsPpsIdStrategy = SPS_PPS_LISTING;
+ //prepare param2
+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
+ while (GET_MB_WIDTH (sParam2.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth)) {
+ sParam2.iPicWidth = GetRandWidth();
+ }
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
+ sParam2.eSpsPpsIdStrategy = SPS_PPS_LISTING;
+
+ //prepare output if needed
+ FILE* fEnc = NULL;
+#ifdef DEBUG_FILE_SAVE5
+ fEnc = fopen ("encLIST2.264", "wb");
+#endif
+
+ // step#1: pParam1
+ int rv = encoder_->InitializeExt (&sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
+ sParam1.iPicHeight;
+
+ // step#2: pParam2
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+ // step#3: back to pParam1, SHOULD NOT encounter ERROR
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
+ sParam1.iPicHeight;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ // new IDR
+ rv = encoder_->ForceIntraFrame (true);
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
+
+ rv = encoder_->Uninitialize();
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+
+#ifdef DEBUG_FILE_SAVE5
+ fclose (fEnc);
+#endif
+}
+
+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) {
+
+ int iWidth = GetRandWidth();
+ int iHeight = GetRandHeight();
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = 0;
+ int iSpatialLayerNum = 1;
+ int iSliceNum = 1;
+
+ // prepare params
+ SEncParamExt sParam1;
+ SEncParamExt sParam2;
+ SEncParamExt sParam3;
+ encoder_->GetDefaultParams (&sParam1);
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
+ sParam1.eSpsPpsIdStrategy = SPS_PPS_LISTING;
+ //prepare param2
+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
+ while (GET_MB_WIDTH (sParam2.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth)) {
+ sParam2.iPicWidth = GetRandWidth();
+ }
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
+ sParam2.eSpsPpsIdStrategy = SPS_PPS_LISTING;
+ //prepare param3
+ memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
+ while (GET_MB_WIDTH (sParam3.iPicWidth) == GET_MB_WIDTH (sParam1.iPicWidth) ||
+ GET_MB_WIDTH (sParam3.iPicWidth) == GET_MB_WIDTH (sParam2.iPicWidth)) {
+ sParam3.iPicWidth = GetRandWidth();
+ }
+ prepareParamDefault (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
+ sParam3.eSpsPpsIdStrategy = SPS_PPS_LISTING;
+
+ //prepare output if needed
+ FILE* fEnc = NULL;
+#ifdef DEBUG_FILE_SAVE5
+ fEnc = fopen ("enc4.264", "wb");
+#endif
+
+ // step#1: ordinary encoding
+ int rv = encoder_->InitializeExt (&sParam1);
+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
+ sParam1.iPicHeight;
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+ // step#2: set strategy for success
+ int32_t iNewStra = SPS_PPS_LISTING;
+ rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << " iNewStra=" << iNewStra;
+
+ // step#3: setting new strategy, SHOULD encounter ERROR
+ unsigned int TraceLevel = WELS_LOG_QUIET;
+ rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ iNewStra = CONSTANT_ID;
+ rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
+ ASSERT_TRUE (rv != cmResultSuccess);
+
+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
+
+ // step#4: pParam3, SHOULD encounter ERROR
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
+ ASSERT_TRUE (rv != cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam3.iPicWidth << "x" <<
+ sParam3.iPicHeight;
+
+ rv = encoder_->Uninitialize();
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
+
+#ifdef DEBUG_FILE_SAVE5
+ fclose (fEnc);
+#endif
+}
+
+
+TEST_F (EncodeDecodeTestAPI, SimulcastSVC) {
+ int iSpatialLayerNum = WelsClip3 ((rand() % MAX_SPATIAL_LAYER_NUM), 2, MAX_SPATIAL_LAYER_NUM);
+ int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 16, MAX_WIDTH);
+ int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 16, MAX_HEIGHT);
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+ int iSliceNum = 1;
+ encoder_->GetDefaultParams (¶m_);
+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ 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[MAX_SPATIAL_LAYER_NUM] = { NULL };
+ fEnc[0] = fopen ("enc0.264", "wb");
+ fEnc[1] = fopen ("enc1.264", "wb");
+ fEnc[2] = fopen ("enc2.264", "wb");
+ fEnc[3] = fopen ("enc3.264", "wb");
+#endif
+
+ // init decoders
+ 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);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ 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);
+ }
+
+ for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
+ int iResult;
+ int iLayerLen = 0;
+ unsigned char* pData[3] = { NULL };
+
+ InitialEncDec (param_.iPicWidth, param_.iPicHeight);
+ EncodeOneFrame (0);
+
+ iLayerLen = 0;
+ 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];
+ }
+
+ if (layerInfo.uiLayerType == NON_VIDEO_CODING_LAYER) {
+ // under SimulcastSVC, need to copy non-VCL to all layers
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ memcpy ((pBsBuf[iIdx] + aLen[iIdx]), layerInfo.pBsBuf, iLayerLen * sizeof (unsigned char));
+ aLen[iIdx] += iLayerLen;
+ }
+ } else {
+ iIdx = layerInfo.uiSpatialId;
+ EXPECT_TRUE (iIdx < 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_SAVE2
+ 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;
+ }
+ }
+
+ // free all
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ if (pBsBuf[iIdx]) {
+ free (pBsBuf[iIdx]);
+ }
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+
+#ifdef DEBUG_FILE_SAVE2
+ fclose (fEnc[iIdx]);
+#endif
+ }
+
+}
+
+TEST_F (EncodeDecodeTestAPI, SimulcastAVC) {
+//#define DEBUG_FILE_SAVE3
+ int iSpatialLayerNum = WelsClip3 ((rand() % MAX_SPATIAL_LAYER_NUM), 2, MAX_SPATIAL_LAYER_NUM);
+ int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 16, MAX_WIDTH);
+ int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 16, MAX_HEIGHT);
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+ int iSliceNum = 1;
+ encoder_->GetDefaultParams (¶m_);
+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
+
+ //set flag of bSimulcastAVC
+ param_.bSimulcastAVC = true;
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ 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[MAX_SPATIAL_LAYER_NUM];
+ fEnc[0] = fopen ("enc0.264", "wb");
+ fEnc[1] = fopen ("enc1.264", "wb");
+ fEnc[2] = fopen ("enc2.264", "wb");
+ fEnc[3] = fopen ("enc3.264", "wb");
+#endif
+
+ int iIdx = 0;
+
+ //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);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ 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);
+ }
+
+ iEncFrameNum = 10;
+ for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
+ int iResult;
+ int iLayerLen = 0;
+ unsigned char* pData[3] = { NULL };
+
+ InitialEncDec (param_.iPicWidth, param_.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];
+ const int kiFirstNalType = ((* (layerInfo.pBsBuf + 4)) & 0x1f);
+ ASSERT_TRUE ((kiFirstNalType == NAL_SPS) || (kiFirstNalType == NAL_PPS) || (kiFirstNalType == NAL_SLICE)
+ || (kiFirstNalType == NAL_SLICE_IDR) || (kiFirstNalType == NAL_SEI));
+ for (int iNal = 0; iNal < layerInfo.iNalCount; ++iNal) {
+ iLayerLen += layerInfo.pNalLengthInByte[iNal];
+ }
+
+ iIdx = layerInfo.uiSpatialId;
+ EXPECT_TRUE (iIdx < 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_SAVE3
+ 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;
+ }
+ }
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+ }
+#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
+ for (int i = 0; i <)MAX_SPATIAL_LAYER_NUM;
+ i++) {
+ fclose (fEnc[i]);
+ }
+#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;
+ iWidth = VALID_SIZE (iWidth);
+ iHeight = VALID_SIZE (iHeight);
+ // 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 (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.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, 0);
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+
+ }
+}
+
+struct EncodeOptionParam {
+ bool bTestNalSize;
+ bool bAllRandom;
+ bool bTestDecoder;
+ int iNumframes;
+ int iWidth;
+ int iHeight;
+ int iQp;
+ SliceModeEnum eSliceMode;
+ int uiMaxNalLen;
+ float fFramerate;
+ int iThreads;
+ const char* sFileSave;
+};
+
+static const EncodeOptionParam kOptionParamArray[] = {
+ {true, true, false, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 1, ""},
+ {true, true, false, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 1, ""},
+ {true, true, false, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, true, false, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, true, false, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, true, false, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, false, true, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 1, ""},
+ {true, false, true, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 1, ""},
+ {true, false, true, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, false, true, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, false, true, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, false, true, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, true, true, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 1, ""},
+ {true, true, true, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 1, ""},
+ {true, true, true, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, true, true, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, true, true, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {true, true, true, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {false, false, true, 3, 4096, 2304, 2, SM_SINGLE_SLICE, 0, 7.5, 1, ""}, // large picture size
+ {false, true, false, 30, 32, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 1, ""},
+ {false, true, false, 30, 600, 460, 1, SM_SIZELIMITED_SLICE, 450, 15.0, 4, ""},
+ {false, true, false, 30, 340, 96, 24, SM_SIZELIMITED_SLICE, 1000, 30.0, 2, ""},
+ {false, true, false, 30, 140, 196, 51, SM_SIZELIMITED_SLICE, 500, 7.5, 3, ""},
+ {false, true, false, 30, 110, 296, 50, SM_SIZELIMITED_SLICE, 500, 7.5, 2, ""},
+ {false, true, false, 30, 104, 416, 44, SM_SIZELIMITED_SLICE, 500, 7.5, 2, ""},
+ {false, true, false, 30, 16, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 3, ""},
+ {false, true, false, 30, 32, 16, 2, SM_SIZELIMITED_SLICE, 500, 7.5, 3, ""},
+ {false, false, true, 30, 600, 460, 1, SM_FIXEDSLCNUM_SLICE, 0, 15.0, 4, ""},
+ {false, false, true, 30, 600, 460, 1, SM_FIXEDSLCNUM_SLICE, 0, 15.0, 8, ""},
+};
+
+class EncodeTestAPI : public ::testing::TestWithParam<EncodeOptionParam>, public ::EncodeDecodeTestAPIBase {
+ public:
+ void SetUp() {
+ EncodeDecodeTestAPIBase::SetUp();
+ }
+
+ void TearDown() {
+ EncodeDecodeTestAPIBase::TearDown();
+ }
+ void EncodeOneFrameRandom (int iCheckTypeIndex, bool bAllRandom) {
+ int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
+ uint8_t* ptr = buf_.data();
+ uint8_t uiVal = rand() % 256;
+ for (int i = 0; i < frameSize; i++) {
+ ptr[i] = bAllRandom ? (rand() % 256) : uiVal;
+ }
+ int rv = encoder_->EncodeFrame (&EncPic, &info);
+ if (0 == iCheckTypeIndex)
+ ASSERT_TRUE (rv == cmResultSuccess) << "rv=" << rv;
+ else if (1 == iCheckTypeIndex)
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason) << "rv=" << rv;
+ }
+};
+
+INSTANTIATE_TEST_CASE_P (EncodeDecodeTestAPIBase, EncodeTestAPI,
+ ::testing::ValuesIn (kOptionParamArray));
+
+TEST_P (EncodeTestAPI, SetEncOptionSize) {
+ EncodeOptionParam p = GetParam();
+ FILE* pFile = NULL;
+ if (p.sFileSave != NULL && strlen (p.sFileSave) > 0) {
+ pFile = fopen (p.sFileSave, "wb");
+ }
+ memset (¶m_, 0, sizeof (SEncParamExt));
+ encoder_->GetDefaultParams (¶m_);
+ param_.uiMaxNalSize = p.uiMaxNalLen;
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 1;
+ param_.iUsageType = CAMERA_VIDEO_REAL_TIME;
+ param_.iPicWidth = p.iWidth;
+ param_.iPicHeight = p.iHeight;
+ param_.fMaxFrameRate = p.fFramerate;
+ param_.iRCMode = RC_OFF_MODE; //rc off
+ param_.iMultipleThreadIdc = p.iThreads;
+ param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
+ param_.sSpatialLayers[0].iVideoWidth = p.iWidth ;
+ param_.sSpatialLayers[0].iVideoHeight = p.iHeight;
+ param_.sSpatialLayers[0].fFrameRate = p.fFramerate;
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceMode = p.eSliceMode;
+ if (SM_FIXEDSLCNUM_SLICE == p.eSliceMode) {
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceNum = 8;
+ }
+
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ InitialEncDec (p.iWidth, p.iHeight);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = (int32_t) pow (2.0f, (param_.iTemporalLayerNum - 1)) * ((rand() % 5) + 1);
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ int iIdx = 0;
+ int iLen;
+ unsigned char* pData[3] = { NULL };
+
+ //FIXME: remove this after the multi-thread case is correctly handled in encoder
+ if (p.iThreads > 1 && SM_SIZELIMITED_SLICE == p.eSliceMode) {
+ p.bAllRandom = false;
+ }
+
+ while (iIdx <= p.iNumframes) {
+ EncodeOneFrameRandom (0, p.bAllRandom);
+ encToDecData (info, iLen);
+ if (pFile) {
+ fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, pFile);
+ fflush (pFile);
+ }
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ if (iLen && p.bTestDecoder) {
+ rv = decoder_->DecodeFrameNoDelay (info.sLayerInfo[0].pBsBuf, iLen, pData, &dstBufInfo_);
+ ASSERT_EQ (rv, 0);
+ ASSERT_EQ (dstBufInfo_.iBufferStatus, 1);
+ }
+ int iLayer = 0;
+ while (iLayer < info.iLayerNum) {
+ SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayer];
+ if (pLayerBsInfo != NULL) {
+ int iNalIdx = WELS_MAX (pLayerBsInfo->iNalCount - 2, 0); // ignore last slice under single slice mode
+ do {
+ if (p.bTestNalSize) { // ignore the case that 2 MBs in one picture, and the multithreads case, enable them when code is ready
+ ASSERT_GE (((int)param_.uiMaxNalSize), pLayerBsInfo->pNalLengthInByte[iNalIdx]);
+ }
+ -- iNalIdx;
+ } while (iNalIdx >= 0);
+ }
+ ++ iLayer;
+ }
+ iIdx++;
+ }
+ if (pFile) {
+ fclose (pFile);
+ }
+}
+
+
+
+TEST_F (EncodeDecodeTestAPI, SimulcastAVCDiffFps) {
+//#define DEBUG_FILE_SAVE_SimulcastAVCDiffFps
+ 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 = 30;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+ int iSliceNum = 1;
+ encoder_->GetDefaultParams (¶m_);
+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
+
+ //set flag of bSimulcastAVC
+ param_.bSimulcastAVC = true;
+ param_.iTemporalLayerNum = (rand() % 2) ? 3 : 4;
+
+ unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
+ int aLen[MAX_SPATIAL_LAYER_NUM] = {0};
+ ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
+
+#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
+ FILE* fEnc[MAX_SPATIAL_LAYER_NUM];
+ fEnc[0] = fopen ("enc0.264", "wb");
+ fEnc[1] = fopen ("enc1.264", "wb");
+ fEnc[2] = fopen ("enc2.264", "wb");
+ fEnc[3] = fopen ("enc3.264", "wb");
+#endif
+
+ int iIdx = 0;
+
+ //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);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ 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);
+ }
+
+#define PATTERN_NUM (18)
+ const int32_t iTemporalPattern[PATTERN_NUM][MAX_SPATIAL_LAYER_NUM] = { {2, 1, 1, 1}, {2, 2, 2, 1}, {4, 1, 1, 1}, {4, 2, 1, 1},
+ {1, 2, 1, 1}, {1, 1, 2, 1}, {1, 4, 1, 1}, {2, 4, 2, 1}, {1, 4, 2, 1}, {1, 4, 4, 1},
+ {1, 2, 2, 1}, {2, 1, 2, 1}, {1, 2, 4, 1},
+ {1, 1, 1, 2}, {1, 2, 2, 2}, {1, 2, 2, 4}, {1, 2, 4, 2}, {1, 4, 4, 4},
+ };
+ for (int iPatternIdx = 0; iPatternIdx < PATTERN_NUM; iPatternIdx++) {
+ for (int i = 0; i < iSpatialLayerNum; i++) {
+ param_.sSpatialLayers[i].fFrameRate = (fFrameRate / iTemporalPattern[iPatternIdx][i]);
+ }
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ iEncFrameNum = 10;
+ int iInsertIdr = rand() % iEncFrameNum;
+ for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
+ int iResult;
+ int iLayerLen = 0;
+ unsigned char* pData[3] = { NULL };
+
+ InitialEncDec (param_.iPicWidth, param_.iPicHeight);
+ EncodeOneFrame (0);
+
+ if (iInsertIdr == iFrame) {
+ encoder_->ForceIntraFrame (true);
+ }
+
+ // init aLen for the current frame
+ 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];
+ const int kiFirstNalType = ((* (layerInfo.pBsBuf + 4)) & 0x1f);
+ ASSERT_TRUE ((kiFirstNalType == NAL_SPS) || (kiFirstNalType == NAL_PPS) || (kiFirstNalType == NAL_SLICE)
+ || (kiFirstNalType == NAL_SLICE_IDR) || (kiFirstNalType == NAL_SEI));
+ for (int iNal = 0; iNal < layerInfo.iNalCount; ++iNal) {
+ iLayerLen += layerInfo.pNalLengthInByte[iNal];
+ }
+
+ iIdx = layerInfo.uiSpatialId;
+ EXPECT_TRUE (iIdx < 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));
+
+ if (aLen[iIdx] > 0) {
+#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
+ 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 << iPatternIdx;
+ EXPECT_EQ (dstBufInfo_.iBufferStatus, 1) << "LayerIdx=" << iIdx;
+ }
+ }
+ }
+ }
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+ }
+#ifdef DEBUG_FILE_SAVE_SimulcastAVCDiffFps
+ for (int i = 0; i < MAX_SPATIAL_LAYER_NUM; i++) {
+ fclose (fEnc[i]);
+ }
+#endif
+}
+
+TEST_F (EncodeDecodeTestAPI, DiffSlicingInDlayer) {
+ int iSpatialLayerNum = 3;
+ int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
+ int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
+ 2240);//TODO: use MAX_HEIGHT after the limit is removed
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+
+ // prepare params
+ SEncParamExt sParam;
+ encoder_->GetDefaultParams (&sParam);
+ prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
+ sParam.iMultipleThreadIdc = (rand() % 4) + 1;
+ sParam.bSimulcastAVC = 1;
+ sParam.sSpatialLayers[0].iVideoWidth = (iWidth >> 2);
+ sParam.sSpatialLayers[0].iVideoHeight = (iHeight >> 2);
+ sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_RASTER_SLICE;
+ sParam.sSpatialLayers[1].sSliceArgument.uiSliceMbNum[0] = 0;
+
+ sParam.sSpatialLayers[1].iVideoWidth = (iWidth >> 1);
+ sParam.sSpatialLayers[1].iVideoHeight = (iHeight >> 1);
+ sParam.sSpatialLayers[1].sSliceArgument.uiSliceMode = SM_RASTER_SLICE;
+ sParam.sSpatialLayers[1].sSliceArgument.uiSliceMbNum[0] = 30;
+ sParam.sSpatialLayers[1].sSliceArgument.uiSliceMbNum[1] = 32;
+
+ sParam.sSpatialLayers[2].iVideoWidth = iWidth;
+ sParam.sSpatialLayers[2].iVideoHeight = iHeight;
+ sParam.sSpatialLayers[2].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ sParam.sSpatialLayers[2].sSliceArgument.uiSliceNum = (rand() % 30) + 1;
+
+ int rv = encoder_->InitializeExt (&sParam);
+ ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
+
+ unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
+ ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
+
+ int iIdx = 0;
+
+ //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);
+
+ long rv = WelsCreateDecoder (&decoder[iIdx]);
+ ASSERT_EQ (0, rv);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ 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 (&sParam, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+
+ }
+}
+
+TEST_F (EncodeDecodeTestAPI, DiffSlicingInDlayerMixed) {
+ int iSpatialLayerNum = 2;
+ int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
+ int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
+ 1120);//TODO: use MAX_HEIGHT after the limit is removed
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+
+ // prepare params
+ SEncParamExt sParam;
+ encoder_->GetDefaultParams (&sParam);
+ prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
+ sParam.iMultipleThreadIdc = (rand() % 4) + 1;
+ sParam.bSimulcastAVC = 1;
+ sParam.sSpatialLayers[0].iVideoWidth = (iWidth >> 2);
+ sParam.sSpatialLayers[0].iVideoHeight = (iHeight >> 2);
+ sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_RASTER_SLICE;
+
+ sParam.sSpatialLayers[1].iVideoWidth = iWidth;
+ sParam.sSpatialLayers[1].iVideoHeight = iHeight;
+ sParam.sSpatialLayers[1].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ sParam.sSpatialLayers[1].sSliceArgument.uiSliceNum = 1;
+
+ int rv = encoder_->InitializeExt (&sParam);
+ ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
+
+ unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
+ ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
+
+ int iIdx = 0;
+
+ //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);
+
+ long rv = WelsCreateDecoder (&decoder[iIdx]);
+ ASSERT_EQ (0, rv);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ 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 (&sParam, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+
+ }
+}
+
+TEST_F (EncodeDecodeTestAPI, ThreadNumAndSliceNum) {
+ int iSpatialLayerNum = 1;
+ int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
+ int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
+ 2240);//TODO: use MAX_HEIGHT after the limit is removed
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+
+ // prepare params
+ SEncParamExt sParam;
+ encoder_->GetDefaultParams (&sParam);
+ prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
+ sParam.iMultipleThreadIdc = (rand() % 3) + 2;
+ sParam.bSimulcastAVC = 1;
+ sParam.sSpatialLayers[0].iVideoWidth = iWidth;
+ sParam.sSpatialLayers[0].iVideoHeight = iHeight;
+ sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ sParam.sSpatialLayers[0].sSliceArgument.uiSliceNum = (rand() % 2) ? (sParam.iMultipleThreadIdc + 1) :
+ (sParam.iMultipleThreadIdc - 1);
+
+ int rv = encoder_->InitializeExt (&sParam);
+ ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
+
+ unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
+ ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
+
+ int iIdx = 0;
+
+ //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);
+
+ long rv = WelsCreateDecoder (&decoder[iIdx]);
+ ASSERT_EQ (0, rv);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ 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 (&sParam, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+
+ }
+}
+
+
+TEST_F (EncodeDecodeTestAPI, TriggerLoadBalancing) {
+ int iSpatialLayerNum = 1;
+ int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
+ int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2),
+ 2240);//TODO: use MAX_HEIGHT after the limit is removed
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+
+ // prepare params
+ SEncParamExt sParam;
+ encoder_->GetDefaultParams (&sParam);
+ prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
+ sParam.iMultipleThreadIdc = (rand() % 8) + 1;
+ sParam.bSimulcastAVC = 1;
+ sParam.sSpatialLayers[0].iVideoWidth = iWidth;
+ sParam.sSpatialLayers[0].iVideoHeight = iHeight;
+ sParam.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ sParam.sSpatialLayers[0].sSliceArgument.uiSliceNum = sParam.iMultipleThreadIdc;
+
+ int rv = encoder_->InitializeExt (&sParam);
+ ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
+
+ unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
+ ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
+
+ int iIdx = 0;
+ int aLen[MAX_SPATIAL_LAYER_NUM] = {};
+
+ //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);
+
+ long rv = WelsCreateDecoder (&decoder[iIdx]);
+ ASSERT_EQ (0, rv);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ 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);
+ }
+
+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam);
+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed pParam: rv = " << rv;
+
+ //begin testing
+ for (int iFrame = 0; iFrame < iEncFrameNum; iFrame++) {
+ int iResult;
+ int iLayerLen = 0;
+ unsigned char* pData[3] = { NULL };
+
+ InitialEncDec (sParam.iPicWidth, sParam.iPicHeight);
+ int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
+ memset (buf_.data(), rand() % 256, (frameSize >> 2));
+ memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
+
+ int iStartStrip = 0;
+ //during first half the complex strip is at top, then during the second half it is at bottom
+ if (iFrame > iEncFrameNum / 2) {
+ iStartStrip = EncPic.iPicHeight * EncPic.iPicWidth;
+ }
+ for (int k = 0; k < (EncPic.iPicHeight / 2); k++) {
+ memset (buf_.data() + k * EncPic.iPicWidth + iStartStrip, rand() % 256, (EncPic.iPicWidth));
+ }
+
+ int rv = encoder_->EncodeFrame (&EncPic, &info);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ // 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;
+ }
+ }
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+
+ }
+}
+
--- /dev/null
+++ b/test/api/ltr_test.cpp
@@ -1,0 +1,153 @@
+#include <gtest/gtest.h>
+#include "codec_def.h"
+#include "utils/BufferedData.h"
+#include "utils/FileInputStream.h"
+#include "BaseDecoderTest.h"
+#include "BaseEncoderTest.h"
+#include "wels_common_defs.h"
+#include <string>
+#include <vector>
+#include "encode_decode_api_test.h"
+using namespace WelsCommon;
+
+
+TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLIDR) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ InitialEncDec (p.width, p.height);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = (int32_t) pow (2.0f, (param_.iTemporalLayerNum - 1)) * ((rand() % 5) + 1);
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (0);
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ encoder_->ForceIntraFrame (true);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLLTR) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ int frameSize = p.width * p.height * 3 / 2;
+ buf_.SetLength (frameSize);
+ ASSERT_TRUE (buf_.Length() == (size_t)frameSize);
+ SFrameBSInfo info;
+ memset (&info, 0, sizeof (SFrameBSInfo));
+
+ SSourcePicture pic;
+ memset (&pic, 0, sizeof (SSourcePicture));
+ pic.iPicWidth = p.width;
+ pic.iPicHeight = p.height;
+ pic.iColorFormat = videoFormatI420;
+ pic.iStride[0] = pic.iPicWidth;
+ pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
+ pic.pData[0] = buf_.data();
+ pic.pData[1] = pic.pData[0] + p.width * p.height;
+ pic.pData[2] = pic.pData[1] + (p.width * p.height >> 2);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ memset (buf_.data(), rand() % 256, frameSize);
+ rv = encoder_->EncodeFrame (&pic, &info);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
+ m_LTR_Recover_Request.uiFeedbackType = LTR_RECOVERY_REQUEST;
+ m_LTR_Recover_Request.iCurrentFrameNum = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
+ m_LTR_Recover_Request.uiIDRPicId = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
+ m_LTR_Recover_Request.iLastCorrectFrameNum = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
+ encoder_->SetOption (ENCODER_LTR_RECOVERY_REQUEST, &m_LTR_Recover_Request);
+ m_LTR_Marking_Feedback.uiFeedbackType = rand() % 2 == 1 ? LTR_MARKING_SUCCESS : LTR_MARKING_FAILED;
+ m_LTR_Marking_Feedback.uiIDRPicId = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
+ m_LTR_Marking_Feedback.iLTRFrameNum = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
+ encoder_->SetOption (ENCODER_LTR_MARKING_FEEDBACK, &m_LTR_Marking_Feedback);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionLTR_Engine) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ InitialEncDec (p.width, p.height);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
--- a/test/api/targets.mk
+++ b/test/api/targets.mk
@@ -4,11 +4,16 @@
$(API_TEST_SRCDIR)/BaseEncoderTest.cpp\
$(API_TEST_SRCDIR)/cpp_interface_test.cpp\
$(API_TEST_SRCDIR)/DataGenerator.cpp\
+ $(API_TEST_SRCDIR)/decode_api_test.cpp\
$(API_TEST_SRCDIR)/decode_encode_test.cpp\
+ $(API_TEST_SRCDIR)/decoder_ec_test.cpp\
$(API_TEST_SRCDIR)/decoder_test.cpp\
$(API_TEST_SRCDIR)/encode_decode_api_test.cpp\
+ $(API_TEST_SRCDIR)/encode_options_test.cpp\
$(API_TEST_SRCDIR)/encoder_test.cpp\
+ $(API_TEST_SRCDIR)/ltr_test.cpp\
$(API_TEST_SRCDIR)/simple_test.cpp\
+
API_TEST_OBJS += $(API_TEST_CPP_SRCS:.cpp=.$(OBJ))