ref: c213c6ba30a6fcd292e2e50409e18049625c051f
parent: 8538b22f23b9c3e47548d841b8d6e94ccf7fb2cc
	author: dongzha <dongzha@DONGZHA-WS04.cisco.com>
	date: Tue Sep 16 05:58:58 EDT 2014
	
1. add Tid API UT 2. add Trace UT 3. Fix a crash issue when set NULL trace
--- a/codec/common/src/welsCodecTrace.cpp
+++ b/codec/common/src/welsCodecTrace.cpp
@@ -78,8 +78,9 @@
   char pBuf[MAX_LOG_SIZE] = {0};WelsVsnprintf (pBuf, MAX_LOG_SIZE, Str_Format, vl); // confirmed_safe_unsafe_usage
-
- m_fpTrace (m_pTraceCtx, iLevel, pBuf);
+  if (m_fpTrace) {+ m_fpTrace (m_pTraceCtx, iLevel, pBuf);
+ }
}
 void welsCodecTrace::SetTraceLevel (const int32_t iLevel) {--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -25,6 +25,19 @@
const char* pLossSequence;
};
+static void welsStderrTraceOrigin (void* ctx, int level, const char* string) {+ fprintf (stderr, "%s\n", string);
+}
+
+typedef struct STrace_Unit {+ 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 ::testing::TestWithParam<EncodeDecodeFileParamBase>,
   public BaseEncoderTest, public BaseDecoderTest {public:
@@ -31,6 +44,12 @@
   virtual void SetUp() {BaseEncoderTest::SetUp();
BaseDecoderTest::SetUp();
+ pFunc = welsStderrTraceOrigin;
+ 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);
}
   virtual void TearDown() {@@ -67,6 +86,9 @@
BufferedData buf_;
SBufferInfo dstBufInfo_;
std::vector<SLostSim> m_SLostSim;
+ WelsTraceCallback pFunc;
+ STraceUnit sTrace;
+ STraceUnit* pTraceInfo;
};
 class EncodeDecodeTestAPI : public EncodeDecodeTestBase {@@ -87,6 +109,7 @@
 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) {@@ -330,7 +353,53 @@
}
}
+bool ToRemainDidNal (const unsigned char* pSrc, EWelsNalUnitType eNalType, int iTarDid) {+ uint8_t uiCurByte = *pSrc;
+  if (IS_NEW_INTRODUCED_SVC_NAL (eNalType)) {+ int iDid = (uiCurByte & 0x70) >> 4;
+ return iDid == iTarDid;
+  } else if ((IS_VCL_NAL_AVC_BASE (eNalType)) && iTarDid != 0) {+ return false;
+  } else {+ return true;
+ }
+}
+void ExtractDidNal (SFrameBSInfo* pBsInfo, int& iSrcLen, std::vector<SLostSim>* p_SLostSim, int iTarDid) {+ unsigned char* pDst = new unsigned char[iSrcLen];
+ const unsigned char* pSrc = pBsInfo->sLayerInfo[0].pBsBuf;
+ int iDstLen = 0;
+ bool bLost;
+ SLostSim tmpSLostSim;
+ p_SLostSim->clear();
+ int iPrefix;
+ unsigned char* pSrcPtr = pBsInfo->sLayerInfo[0].pBsBuf;
+  for (int j = 0; j < pBsInfo->iLayerNum; j++) {+    for (int k = 0; k < pBsInfo->sLayerInfo[j].iNalCount; k++) {+      if (pSrcPtr[0] == 0 && pSrcPtr[1] == 0 && pSrcPtr[2] == 0 && pSrcPtr[3] == 1) {+ iPrefix = 4;
+      } else if (pSrcPtr[0] == 0 && pSrcPtr[1] == 0 && pSrcPtr[2] == 1) {+ iPrefix = 3;
+      } else {+ iPrefix = 0;
+ }
+ tmpSLostSim.eNalType = (EWelsNalUnitType) ((* (pSrcPtr + iPrefix)) & 0x1f); // eNalUnitType
+ bLost = (ToRemainDidNal ((pSrcPtr + iPrefix + 2), tmpSLostSim.eNalType, iTarDid)) ? false : true;
+ tmpSLostSim.isLost = bLost;
+ p_SLostSim->push_back (tmpSLostSim);
+      if (!bLost) {+ memcpy (pDst + iDstLen, pSrcPtr, pBsInfo->sLayerInfo[j].pNalLengthInByte[k]);
+ iDstLen += (pBsInfo->sLayerInfo[j].pNalLengthInByte[k]);
+ }
+ pSrcPtr += pBsInfo->sLayerInfo[j].pNalLengthInByte[k];
+ }
+ }
+ memset ((void*)pSrc, 0, iSrcLen);
+ memcpy ((void*)pSrc, pDst, iDstLen);
+ iSrcLen = iDstLen;
+ delete [] pDst;
+}
+
int SimulateNALLoss (const unsigned char* pSrc, int& iSrcLen, std::vector<SLostSim>* p_SLostSim,
                      const char* pLossChars, bool bLossPara, int& iLossIdx, bool& bVCLLoss) {unsigned char* pDst = new unsigned char[iSrcLen];
@@ -735,6 +804,406 @@
iIdx++;
}
(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();
+ prepareParam (p.width, p.height, p.frameRate);
+ param_.bPrefixNalAddingCtrl = false;
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ param_.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = p.slicenum;
+ 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;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+  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 == cmUnkonwReason);
+ //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);
+ 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 (int k = 0; k < m_SLostSim.size(); k++) {+      if (IS_VCL_NAL (iter->eNalType, 0) && iter->isLost == false) {+ bHasVCL = true;
+ break;
+ }
+ iter++;
+ }
+    if (iTid != -1) {+ ASSERT_EQ (iTid, 0);
+ }
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv);
+ 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();
+ prepareParam (p.width, p.height, p.frameRate);
+ param_.bPrefixNalAddingCtrl = true;
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 1;
+ param_.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ param_.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = p.slicenum;
+ 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 == cmUnkonwReason);
+ //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);
+ 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);
+ 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();
+ prepareParam (p.width / 2, p.height / 2, p.frameRate);
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 2;
+ param_.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ param_.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = p.slicenum;
+ param_.sSpatialLayers[1].iVideoWidth = p.width;
+ param_.sSpatialLayers[1].iVideoHeight = p.height;
+ param_.sSpatialLayers[1].fFrameRate = p.frameRate;
+ param_.sSpatialLayers[1].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ param_.sSpatialLayers[1].sSliceCfg.sSliceArgument.uiSliceNum = p.slicenum;
+
+ 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 == cmUnkonwReason);
+ //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);
+ 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);
+ 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();
+ prepareParam (p.width, p.height, p.frameRate);
+ param_.iSpatialLayerNum = 1;
+ param_.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ param_.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = p.slicenum;
+
+ 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;
+ pFunc = TestOutPutTrace;
+ pTraceInfo = &sTrace;
+ sTrace.iTarLevel = 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);
+ 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) {+ memset (buf_.data(), rand() % 256, frameSize);
+ iTraceLevel = rand() % 33;
+ sTrace.iTarLevel = iTraceLevel;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ rv = encoder_->EncodeFrame (&pic, &info);
+    if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
+ //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);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv);
+ 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();
+ prepareParam (p.width, p.height, p.frameRate);
+ param_.iSpatialLayerNum = 1;
+ param_.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ param_.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = p.slicenum;
+
+ 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;
+ 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) {+ memset (buf_.data(), rand() % 256, frameSize);
+ iTraceLevel = rand() % 33;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ rv = encoder_->EncodeFrame (&pic, &info);
+    if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
+ //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);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
}
INSTANTIATE_TEST_CASE_P (EncodeDecodeTestBase, EncodeDecodeTestAPI,
--
⑨