
Avoid X86_ASM ifdef. Ideally, we may want to update all routines to average vertically first, which would make this unnecessary. In the interim, this enables the tests to run successfully on x86 without SSSE3 support again.
974 lines
36 KiB
C++
974 lines
36 KiB
C++
#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* const pHashStr[][2] = { //DO NOT CHANGE!
|
|
// Allow for different output depending on whether averaging is done
|
|
// vertically or horizontally first when downsampling.
|
|
{ "244eebcb51f4c2a56e83fc5da3373cad9ec0e1e5", "9c4e6146b29bac5d5d4be3c5bbab9c072dcb3f3f" },
|
|
{ "bbad99ef99e37b34bcb4f09a7ec4d144375f6be7", "f350001c333902029800bd291fbed915a4bdf19a" },
|
|
{ "809f97e836650624d92f0b8e200a6ab25f810d6f", "eb9d853b7daec03052c4850027ac94adc84c3a7e" }
|
|
};
|
|
|
|
class DecodeParseAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
|
|
public:
|
|
DecodeParseAPI() {
|
|
memset (&BsInfo_, 0, sizeof (SParserBsInfo));
|
|
fYuv_ = NULL;
|
|
iWidth_ = 0;
|
|
iHeight_ = 0;
|
|
memset (&ctx_, 0, sizeof (SHA1Context));
|
|
}
|
|
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();
|
|
if (fYuv_ != NULL) {
|
|
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()) {
|
|
CompareHashAnyOf (digest, pHashStr[uiTargetLayerId], sizeof *pHashStr / sizeof **pHashStr);
|
|
}
|
|
} //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
|
|
}
|
|
|
|
|
|
|