Showing the changes to test/api/decode_api_test.cpp (1 of 7 files). Show all
Unified · Split
| @@ -0,0 +1,962 @@ | |||
| 1 | #include <gtest/gtest.h> | ||
| 2 | #include "codec_def.h" | ||
| 3 | #include "utils/BufferedData.h" | ||
| 4 | #include "utils/FileInputStream.h" | ||
| 5 | #include "BaseDecoderTest.h" | ||
| 6 | #include "BaseEncoderTest.h" | ||
| 7 | #include "wels_common_defs.h" | ||
| 8 | #include "utils/HashFunctions.h" | ||
| 9 | #include <string> | ||
| 10 | #include <vector> | ||
| 11 | #include "encode_decode_api_test.h" | ||
| 12 | using namespace WelsCommon; | ||
| 13 | |||
| 14 | static void TestOutPutTrace (void* ctx, int level, const char* string) { | ||
| 15 | STraceUnit* pTraceUnit = (STraceUnit*) ctx; | ||
| 16 | EXPECT_LE (level, pTraceUnit->iTarLevel); | ||
| 17 | } | ||
| 18 | |||
| 19 | TEST_P (EncodeDecodeTestAPI, DecoderVclNal) { | ||
| 20 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 21 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 22 | encoder_->Uninitialize(); | ||
| 23 | int rv = encoder_->InitializeExt (¶m_); | ||
| 24 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 25 | |||
| 26 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 27 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 28 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 29 | |||
| 30 | InitialEncDec (p.width, p.height); | ||
| 31 | |||
| 32 | int iIdx = 0; | ||
| 33 | while (iIdx <= p.numframes) { | ||
| 34 | |||
| 35 | EncodeOneFrame (0); | ||
| 36 | |||
| 37 | //decoding after each encoding frame | ||
| 38 | int vclNal, len = 0; | ||
| 39 | encToDecData (info, len); | ||
| 40 | unsigned char* pData[3] = { NULL }; | ||
| 41 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 42 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 43 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 44 | rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal); | ||
| 45 | EXPECT_EQ (vclNal, FEEDBACK_UNKNOWN_NAL); //no reconstruction, unknown return | ||
| 46 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 47 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 48 | rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal); | ||
| 49 | EXPECT_EQ (vclNal, FEEDBACK_VCL_NAL); | ||
| 50 | iIdx++; | ||
| 51 | } //while | ||
| 52 | //ignore last frame | ||
| 53 | } | ||
| 54 | |||
| 55 | TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) { | ||
| 56 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 57 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 58 | encoder_->Uninitialize(); | ||
| 59 | int rv = encoder_->InitializeExt (¶m_); | ||
| 60 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 61 | |||
| 62 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 63 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 64 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 65 | |||
| 66 | InitialEncDec (p.width, p.height); | ||
| 67 | |||
| 68 | int32_t iEncFrameNum = -1; | ||
| 69 | int32_t iDecFrameNum; | ||
| 70 | int iIdx = 0; | ||
| 71 | while (iIdx <= p.numframes) { | ||
| 72 | EncodeOneFrame (0); | ||
| 73 | //decoding after each encoding frame | ||
| 74 | int len = 0; | ||
| 75 | encToDecData (info, len); | ||
| 76 | unsigned char* pData[3] = { NULL }; | ||
| 77 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 78 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 79 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 80 | decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum); | ||
| 81 | EXPECT_EQ (iDecFrameNum, -1); | ||
| 82 | iEncFrameNum++; | ||
| 83 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 84 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 85 | decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum); | ||
| 86 | EXPECT_EQ (iEncFrameNum, iDecFrameNum); | ||
| 87 | iIdx++; | ||
| 88 | } //while | ||
| 89 | //ignore last frame | ||
| 90 | } | ||
| 91 | |||
| 92 | TEST_P (EncodeDecodeTestAPI, GetOptionIDR) { | ||
| 93 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 94 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 95 | encoder_->Uninitialize(); | ||
| 96 | int rv = encoder_->InitializeExt (¶m_); | ||
| 97 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 98 | |||
| 99 | //init for encoder | ||
| 100 | // I420: 1(Y) + 1/4(U) + 1/4(V) | ||
| 101 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 102 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 103 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 104 | |||
| 105 | InitialEncDec (p.width, p.height); | ||
| 106 | |||
| 107 | int32_t iEncCurIdrPicId = 0; | ||
| 108 | int32_t iDecCurIdrPicId; | ||
| 109 | int32_t iIDRPeriod = 1; | ||
| 110 | int32_t iSpsPpsIdAddition = 0; | ||
| 111 | int iIdx = 0; | ||
| 112 | while (iIdx <= p.numframes) { | ||
| 113 | iSpsPpsIdAddition = rand() % | ||
| 114 | 2; //the current strategy supports more than 2 modes, but the switch between the modes>2 is not allowed | ||
| 115 | iIDRPeriod = (rand() % 150) + 1; | ||
| 116 | encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod); | ||
| 117 | encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition); | ||
| 118 | |||
| 119 | EncodeOneFrame (0); | ||
| 120 | |||
| 121 | if (info.eFrameType == videoFrameTypeIDR) { | ||
| 122 | iEncCurIdrPicId = iEncCurIdrPicId + 1; | ||
| 123 | } | ||
| 124 | //decoding after each encoding frame | ||
| 125 | int len = 0; | ||
| 126 | encToDecData (info, len); | ||
| 127 | unsigned char* pData[3] = { NULL }; | ||
| 128 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 129 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 130 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 131 | decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId); | ||
| 132 | EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId); | ||
| 133 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 134 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 135 | decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId); | ||
| 136 | EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId); | ||
| 137 | iIdx++; | ||
| 138 | } //while | ||
| 139 | //ignore last frame | ||
| 140 | } | ||
| 141 | |||
| 142 | TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) { | ||
| 143 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 144 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 145 | encoder_->Uninitialize(); | ||
| 146 | int rv = encoder_->InitializeExt (¶m_); | ||
| 147 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 148 | |||
| 149 | InitialEncDec (p.width, p.height); | ||
| 150 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 151 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 152 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 153 | int32_t iSpsPpsIdAddition = 1; | ||
| 154 | encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition); | ||
| 155 | int32_t iIDRPeriod = 60; | ||
| 156 | encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod); | ||
| 157 | SLTRConfig sLtrConfigVal; | ||
| 158 | sLtrConfigVal.bEnableLongTermReference = 1; | ||
| 159 | sLtrConfigVal.iLTRRefNum = 1; | ||
| 160 | encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal); | ||
| 161 | int32_t iLtrPeriod = 2; | ||
| 162 | encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod); | ||
| 163 | int iIdx = 0; | ||
| 164 | int iSkipedBytes; | ||
| 165 | unsigned long long uiEncTimeStamp = 100; | ||
| 166 | while (iIdx <= p.numframes) { | ||
| 167 | EncodeOneFrame (1); | ||
| 168 | //decoding after each encoding frame | ||
| 169 | int len = 0; | ||
| 170 | encToDecData (info, len); | ||
| 171 | unsigned char* pData[3] = { NULL }; | ||
| 172 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 173 | uint32_t uiEcIdc = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE; | ||
| 174 | decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc); | ||
| 175 | dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp; | ||
| 176 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 177 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 178 | dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp; | ||
| 179 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 180 | if (dstBufInfo_.iBufferStatus == 1) { | ||
| 181 | EXPECT_EQ (uiEncTimeStamp, dstBufInfo_.uiOutYuvTimeStamp); | ||
| 182 | } | ||
| 183 | iIdx++; | ||
| 184 | uiEncTimeStamp++; | ||
| 185 | } | ||
| 186 | (void) iSkipedBytes; | ||
| 187 | } | ||
| 188 | |||
| 189 | TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) { | ||
| 190 | SLTRMarkingFeedback m_LTR_Marking_Feedback; | ||
| 191 | SLTRRecoverRequest m_LTR_Recover_Request; | ||
| 192 | m_LTR_Recover_Request.uiIDRPicId = 0; | ||
| 193 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 194 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 195 | param_.bPrefixNalAddingCtrl = false; | ||
| 196 | param_.iTemporalLayerNum = (rand() % 4) + 1; | ||
| 197 | encoder_->Uninitialize(); | ||
| 198 | int rv = encoder_->InitializeExt (¶m_); | ||
| 199 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 200 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 201 | InitialEncDec (p.width, p.height); | ||
| 202 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 203 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 204 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 205 | int32_t iSpsPpsIdAddition = 1; | ||
| 206 | encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition); | ||
| 207 | int32_t iIDRPeriod = 60; | ||
| 208 | encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod); | ||
| 209 | SLTRConfig sLtrConfigVal; | ||
| 210 | sLtrConfigVal.bEnableLongTermReference = 1; | ||
| 211 | sLtrConfigVal.iLTRRefNum = 1; | ||
| 212 | encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal); | ||
| 213 | int32_t iLtrPeriod = 2; | ||
| 214 | encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod); | ||
| 215 | int iIdx = 0; | ||
| 216 | int iLossIdx = 0; | ||
| 217 | bool bVCLLoss = false; | ||
| 218 | while (iIdx <= p.numframes) { | ||
| 219 | EncodeOneFrame (1); | ||
| 220 | if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) { | ||
| 221 | ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR); | ||
| 222 | } | ||
| 223 | //decoding after each encoding frame | ||
| 224 | int len = 0; | ||
| 225 | encToDecData (info, len); | ||
| 226 | unsigned char* pData[3] = { NULL }; | ||
| 227 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 228 | SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss); | ||
| 229 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 230 | int iTid = -1; | ||
| 231 | decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid); | ||
| 232 | if (iTid != -1) { | ||
| 233 | ASSERT_EQ (iTid, 0); | ||
| 234 | } | ||
| 235 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 236 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 237 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 238 | decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid); | ||
| 239 | std::vector<SLostSim>::iterator iter = m_SLostSim.begin(); | ||
| 240 | bool bHasVCL = false; | ||
| 241 | for (unsigned int k = 0; k < m_SLostSim.size(); k++) { | ||
| 242 | if (IS_VCL_NAL (iter->eNalType, 0) && iter->isLost == false) { | ||
| 243 | bHasVCL = true; | ||
| 244 | break; | ||
| 245 | } | ||
| 246 | iter++; | ||
| 247 | } | ||
| 248 | (void) bHasVCL; | ||
| 249 | if (iTid != -1) { | ||
| 250 | ASSERT_EQ (iTid, 0); | ||
| 251 | } | ||
| 252 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 253 | LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv); | ||
| 254 | iIdx++; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_WITH_PREFIX_NOLOSS) { | ||
| 259 | SLTRMarkingFeedback m_LTR_Marking_Feedback; | ||
| 260 | SLTRRecoverRequest m_LTR_Recover_Request; | ||
| 261 | m_LTR_Recover_Request.uiIDRPicId = 0; | ||
| 262 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 263 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 264 | param_.bPrefixNalAddingCtrl = true; | ||
| 265 | param_.iTemporalLayerNum = (rand() % 4) + 1; | ||
| 266 | param_.iSpatialLayerNum = 1; | ||
| 267 | encoder_->Uninitialize(); | ||
| 268 | int rv = encoder_->InitializeExt (¶m_); | ||
| 269 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 270 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 271 | |||
| 272 | InitialEncDec (p.width, p.height); | ||
| 273 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 274 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 275 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 276 | int32_t iSpsPpsIdAddition = 1; | ||
| 277 | encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition); | ||
| 278 | int32_t iIDRPeriod = 60; | ||
| 279 | encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod); | ||
| 280 | SLTRConfig sLtrConfigVal; | ||
| 281 | sLtrConfigVal.bEnableLongTermReference = 1; | ||
| 282 | sLtrConfigVal.iLTRRefNum = 1; | ||
| 283 | encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal); | ||
| 284 | int32_t iLtrPeriod = 2; | ||
| 285 | encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod); | ||
| 286 | int iIdx = 0; | ||
| 287 | while (iIdx <= p.numframes) { | ||
| 288 | EncodeOneFrame (1); | ||
| 289 | if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) { | ||
| 290 | ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR); | ||
| 291 | } | ||
| 292 | //decoding after each encoding frame | ||
| 293 | int len = 0; | ||
| 294 | encToDecData (info, len); | ||
| 295 | unsigned char* pData[3] = { NULL }; | ||
| 296 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 297 | ExtractDidNal (&info, len, &m_SLostSim, 0); | ||
| 298 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 299 | int iTid = -1; | ||
| 300 | decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid); | ||
| 301 | ASSERT_EQ (iTid, -1); | ||
| 302 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 303 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 304 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 305 | decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid); | ||
| 306 | ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId); | ||
| 307 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 308 | LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv); | ||
| 309 | iIdx++; | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | TEST_P (EncodeDecodeTestAPI, GetOptionTid_SVC_L1_NOLOSS) { | ||
| 314 | SLTRMarkingFeedback m_LTR_Marking_Feedback; | ||
| 315 | SLTRRecoverRequest m_LTR_Recover_Request; | ||
| 316 | m_LTR_Recover_Request.uiIDRPicId = 0; | ||
| 317 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 318 | prepareParamDefault (2, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 319 | param_.iTemporalLayerNum = (rand() % 4) + 1; | ||
| 320 | param_.iSpatialLayerNum = 2; | ||
| 321 | encoder_->Uninitialize(); | ||
| 322 | int rv = encoder_->InitializeExt (¶m_); | ||
| 323 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 324 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 325 | |||
| 326 | InitialEncDec (p.width, p.height); | ||
| 327 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 328 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 329 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 330 | int32_t iSpsPpsIdAddition = 1; | ||
| 331 | encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition); | ||
| 332 | int32_t iIDRPeriod = 60; | ||
| 333 | encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod); | ||
| 334 | SLTRConfig sLtrConfigVal; | ||
| 335 | sLtrConfigVal.bEnableLongTermReference = 1; | ||
| 336 | sLtrConfigVal.iLTRRefNum = 1; | ||
| 337 | encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal); | ||
| 338 | int32_t iLtrPeriod = 2; | ||
| 339 | encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod); | ||
| 340 | int iIdx = 0; | ||
| 341 | while (iIdx <= p.numframes) { | ||
| 342 | EncodeOneFrame (1); | ||
| 343 | if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) { | ||
| 344 | ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR); | ||
| 345 | } | ||
| 346 | //decoding after each encoding frame | ||
| 347 | int len = 0; | ||
| 348 | encToDecData (info, len); | ||
| 349 | unsigned char* pData[3] = { NULL }; | ||
| 350 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 351 | ExtractDidNal (&info, len, &m_SLostSim, 1); | ||
| 352 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 353 | int iTid = -1; | ||
| 354 | decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid); | ||
| 355 | ASSERT_EQ (iTid, -1); | ||
| 356 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 357 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 358 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 359 | decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid); | ||
| 360 | ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId); | ||
| 361 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 362 | LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv); | ||
| 363 | iIdx++; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | |||
| 368 | |||
| 369 | TEST_P (EncodeDecodeTestAPI, SetOption_Trace) { | ||
| 370 | SLTRMarkingFeedback m_LTR_Marking_Feedback; | ||
| 371 | SLTRRecoverRequest m_LTR_Recover_Request; | ||
| 372 | m_LTR_Recover_Request.uiIDRPicId = 0; | ||
| 373 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 374 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 375 | param_.iSpatialLayerNum = 1; | ||
| 376 | |||
| 377 | int rv = encoder_->InitializeExt (¶m_); | ||
| 378 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 379 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 380 | |||
| 381 | InitialEncDec (p.width, p.height); | ||
| 382 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 383 | pFunc = TestOutPutTrace; | ||
| 384 | pTraceInfo = &sTrace; | ||
| 385 | sTrace.iTarLevel = iTraceLevel; | ||
| 386 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 387 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 388 | encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc); | ||
| 389 | encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo); | ||
| 390 | decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc); | ||
| 391 | decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo); | ||
| 392 | |||
| 393 | |||
| 394 | int32_t iSpsPpsIdAddition = 1; | ||
| 395 | encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition); | ||
| 396 | int32_t iIDRPeriod = 60; | ||
| 397 | encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod); | ||
| 398 | SLTRConfig sLtrConfigVal; | ||
| 399 | sLtrConfigVal.bEnableLongTermReference = 1; | ||
| 400 | sLtrConfigVal.iLTRRefNum = 1; | ||
| 401 | encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal); | ||
| 402 | int32_t iLtrPeriod = 2; | ||
| 403 | encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod); | ||
| 404 | int iIdx = 0; | ||
| 405 | int iLossIdx = 0; | ||
| 406 | bool bVCLLoss = false; | ||
| 407 | while (iIdx <= p.numframes) { | ||
| 408 | iTraceLevel = rand() % 33; | ||
| 409 | sTrace.iTarLevel = iTraceLevel; | ||
| 410 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 411 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 412 | EncodeOneFrame (1); | ||
| 413 | if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) { | ||
| 414 | ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR); | ||
| 415 | } | ||
| 416 | //decoding after each encoding frame | ||
| 417 | int len = 0; | ||
| 418 | encToDecData (info, len); | ||
| 419 | unsigned char* pData[3] = { NULL }; | ||
| 420 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 421 | ExtractDidNal (&info, len, &m_SLostSim, 0); | ||
| 422 | SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss); | ||
| 423 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 424 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 425 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 426 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 427 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 428 | LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv); | ||
| 429 | iIdx++; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | TEST_P (EncodeDecodeTestAPI, SetOption_Trace_NULL) { | ||
| 434 | SLTRMarkingFeedback m_LTR_Marking_Feedback; | ||
| 435 | SLTRRecoverRequest m_LTR_Recover_Request; | ||
| 436 | m_LTR_Recover_Request.uiIDRPicId = 0; | ||
| 437 | EncodeDecodeFileParamBase p = GetParam(); | ||
| 438 | prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_); | ||
| 439 | param_.iSpatialLayerNum = 1; | ||
| 440 | int rv = encoder_->InitializeExt (¶m_); | ||
| 441 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 442 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 443 | |||
| 444 | InitialEncDec (p.width, p.height); | ||
| 445 | |||
| 446 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 447 | pFunc = NULL; | ||
| 448 | pTraceInfo = NULL; | ||
| 449 | encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc); | ||
| 450 | encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo); | ||
| 451 | decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc); | ||
| 452 | decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo); | ||
| 453 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 454 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 455 | |||
| 456 | int32_t iSpsPpsIdAddition = 1; | ||
| 457 | encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition); | ||
| 458 | int32_t iIDRPeriod = 60; | ||
| 459 | encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod); | ||
| 460 | SLTRConfig sLtrConfigVal; | ||
| 461 | sLtrConfigVal.bEnableLongTermReference = 1; | ||
| 462 | sLtrConfigVal.iLTRRefNum = 1; | ||
| 463 | encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal); | ||
| 464 | int32_t iLtrPeriod = 2; | ||
| 465 | encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod); | ||
| 466 | int iIdx = 0; | ||
| 467 | int iLossIdx = 0; | ||
| 468 | bool bVCLLoss = false; | ||
| 469 | while (iIdx <= p.numframes) { | ||
| 470 | iTraceLevel = rand() % 33; | ||
| 471 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 472 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 473 | EncodeOneFrame (1); | ||
| 474 | if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) { | ||
| 475 | ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR); | ||
| 476 | } | ||
| 477 | //decoding after each encoding frame | ||
| 478 | int len = 0; | ||
| 479 | encToDecData (info, len); | ||
| 480 | unsigned char* pData[3] = { NULL }; | ||
| 481 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 482 | ExtractDidNal (&info, len, &m_SLostSim, 0); | ||
| 483 | SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss); | ||
| 484 | rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_); | ||
| 485 | m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET; | ||
| 486 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 487 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 488 | LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true); | ||
| 489 | LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv); | ||
| 490 | iIdx++; | ||
| 491 | } | ||
| 492 | } | ||
| 493 | |||
| 494 | |||
| 495 | |||
| 496 | |||
| 497 | class DecodeCrashTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase { | ||
| 498 | public: | ||
| 499 | uint8_t iRandValue; | ||
| 500 | public: | ||
| 501 | void SetUp() { | ||
| 502 | EncodeDecodeTestBase::SetUp(); | ||
| 503 | ucBuf_ = NULL; | ||
| 504 | ucBuf_ = new unsigned char [1000000]; | ||
| 505 | ASSERT_TRUE (ucBuf_ != NULL); | ||
| 506 | } | ||
| 507 | |||
| 508 | void TearDown() { | ||
| 509 | EncodeDecodeTestBase::TearDown(); | ||
| 510 | if (NULL != ucBuf_) { | ||
| 511 | delete[] ucBuf_; | ||
| 512 | ucBuf_ = NULL; | ||
| 513 | } | ||
| 514 | ASSERT_TRUE (ucBuf_ == NULL); | ||
| 515 | } | ||
| 516 | |||
| 517 | void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) { | ||
| 518 | memset (pParam, 0, sizeof (SEncParamExt)); | ||
| 519 | EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam); | ||
| 520 | } | ||
| 521 | |||
| 522 | void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam); | ||
| 523 | void EncodeOneFrame() { | ||
| 524 | int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2; | ||
| 525 | memset (buf_.data(), iRandValue, (frameSize >> 2)); | ||
| 526 | memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2))); | ||
| 527 | int rv = encoder_->EncodeFrame (&EncPic, &info); | ||
| 528 | ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason); | ||
| 529 | } | ||
| 530 | protected: | ||
| 531 | unsigned char* ucBuf_; | ||
| 532 | }; | ||
| 533 | |||
| 534 | void DecodeCrashTestAPI::prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam) { | ||
| 535 | // for encoder | ||
| 536 | // I420: 1(Y) + 1/4(U) + 1/4(V) | ||
| 537 | int frameSize = EncDecFileParam.width * EncDecFileParam.height * 3 / 2; | ||
| 538 | |||
| 539 | buf_.SetLength (frameSize); | ||
| 540 | ASSERT_TRUE (buf_.Length() == (size_t)frameSize); | ||
| 541 | |||
| 542 | memset (&EncPic, 0, sizeof (SSourcePicture)); | ||
| 543 | EncPic.iPicWidth = EncDecFileParam.width; | ||
| 544 | EncPic.iPicHeight = EncDecFileParam.height; | ||
| 545 | EncPic.iColorFormat = videoFormatI420; | ||
| 546 | EncPic.iStride[0] = EncPic.iPicWidth; | ||
| 547 | EncPic.iStride[1] = EncPic.iStride[2] = EncPic.iPicWidth >> 1; | ||
| 548 | EncPic.pData[0] = buf_.data(); | ||
| 549 | EncPic.pData[1] = EncPic.pData[0] + EncDecFileParam.width * EncDecFileParam.height; | ||
| 550 | EncPic.pData[2] = EncPic.pData[1] + (EncDecFileParam.width * EncDecFileParam.height >> 2); | ||
| 551 | |||
| 552 | //for decoder | ||
| 553 | memset (&info, 0, sizeof (SFrameBSInfo)); | ||
| 554 | |||
| 555 | //set a fixed random value | ||
| 556 | iRandValue = rand() % 256; | ||
| 557 | } | ||
| 558 | |||
| 559 | struct EncodeDecodeParamBase { | ||
| 560 | int width; | ||
| 561 | int height; | ||
| 562 | float frameRate; | ||
| 563 | int iTarBitrate; | ||
| 564 | }; | ||
| 565 | |||
| 566 | #define NUM_OF_POSSIBLE_RESOLUTION (9) | ||
| 567 | static const EncodeDecodeParamBase kParamArray[] = { | ||
| 568 | {160, 90, 6.0f, 250000}, | ||
| 569 | {90, 160, 6.0f, 250000}, | ||
| 570 | {320, 180, 12.0f, 500000}, | ||
| 571 | {180, 320, 12.0f, 500000}, | ||
| 572 | {480, 270, 12.0f, 600000}, | ||
| 573 | {270, 480, 12.0f, 600000}, | ||
| 574 | {640, 360, 24.0f, 800000}, | ||
| 575 | {360, 640, 24.0f, 800000}, | ||
| 576 | {1280, 720, 24.0f, 1000000}, | ||
| 577 | }; | ||
| 578 | |||
| 579 | //#define DEBUG_FILE_SAVE_CRA | ||
| 580 | TEST_F (DecodeCrashTestAPI, DecoderCrashTest) { | ||
| 581 | uint32_t uiGet; | ||
| 582 | encoder_->Uninitialize(); | ||
| 583 | |||
| 584 | //do tests until crash | ||
| 585 | unsigned int uiLoopRound = 0; | ||
| 586 | unsigned char* pucBuf = ucBuf_; | ||
| 587 | int iDecAuSize; | ||
| 588 | #ifdef DEBUG_FILE_SAVE_CRA | ||
| 589 | //open file to save tested BS | ||
| 590 | FILE* fDataFile = fopen ("test_crash.264", "wb"); | ||
| 591 | FILE* fLenFile = fopen ("test_crash_len.log", "w"); | ||
| 592 | int iFileSize = 0; | ||
| 593 | #endif | ||
| 594 | |||
| 595 | //set eCurStrategy for one test | ||
| 596 | EParameterSetStrategy eCurStrategy = CONSTANT_ID; | ||
| 597 | switch (rand() % 7) { | ||
| 598 | case 1: | ||
| 599 | eCurStrategy = INCREASING_ID; | ||
| 600 | break; | ||
| 601 | case 2: | ||
| 602 | eCurStrategy = SPS_LISTING; | ||
| 603 | break; | ||
| 604 | case 3: | ||
| 605 | eCurStrategy = SPS_LISTING_AND_PPS_INCREASING; | ||
| 606 | break; | ||
| 607 | case 6: | ||
| 608 | eCurStrategy = SPS_PPS_LISTING; | ||
| 609 | break; | ||
| 610 | default: | ||
| 611 | //using the initial value | ||
| 612 | break; | ||
| 613 | } | ||
| 614 | |||
| 615 | do { | ||
| 616 | int iTotalFrameNum = (rand() % 100) + 1; | ||
| 617 | int iSeed = rand() % NUM_OF_POSSIBLE_RESOLUTION; | ||
| 618 | EncodeDecodeParamBase p = kParamArray[iSeed]; | ||
| 619 | #ifdef DEBUG_FILE_SAVE_CRA | ||
| 620 | printf ("using param set %d in loop %d\n", iSeed, uiLoopRound); | ||
| 621 | #endif | ||
| 622 | //Initialize Encoder | ||
| 623 | prepareParam (1, 1, p.width, p.height, p.frameRate, ¶m_); | ||
| 624 | param_.iRCMode = RC_TIMESTAMP_MODE; | ||
| 625 | param_.iTargetBitrate = p.iTarBitrate; | ||
| 626 | param_.uiIntraPeriod = 0; | ||
| 627 | param_.eSpsPpsIdStrategy = eCurStrategy; | ||
| 628 | param_.bEnableBackgroundDetection = true; | ||
| 629 | param_.bEnableSceneChangeDetect = (rand() % 3) ? true : false; | ||
| 630 | param_.bPrefixNalAddingCtrl = (rand() % 2) ? true : false; | ||
| 631 | param_.iEntropyCodingModeFlag = 0; | ||
| 632 | param_.bEnableFrameSkip = true; | ||
| 633 | param_.iMultipleThreadIdc = 0; | ||
| 634 | param_.sSpatialLayers[0].iSpatialBitrate = p.iTarBitrate; | ||
| 635 | param_.sSpatialLayers[0].iMaxSpatialBitrate = p.iTarBitrate << 1; | ||
| 636 | param_.sSpatialLayers[0].sSliceArgument.uiSliceMode = (rand() % 2) ? SM_SIZELIMITED_SLICE : SM_SINGLE_SLICE; | ||
| 637 | if (param_.sSpatialLayers[0].sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE) { | ||
| 638 | param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 1400; | ||
| 639 | param_.uiMaxNalSize = 1400; | ||
| 640 | } else { | ||
| 641 | param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 0; | ||
| 642 | param_.uiMaxNalSize = 0; | ||
| 643 | } | ||
| 644 | |||
| 645 | int rv = encoder_->InitializeExt (¶m_); | ||
| 646 | ASSERT_TRUE (rv == cmResultSuccess); | ||
| 647 | decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet); | ||
| 648 | EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY | ||
| 649 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 650 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 651 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 652 | |||
| 653 | //Start for enc/dec | ||
| 654 | int iIdx = 0; | ||
| 655 | unsigned char* pData[3] = { NULL }; | ||
| 656 | |||
| 657 | EncodeDecodeFileParamBase pInput; //to conform with old functions | ||
| 658 | pInput.width = p.width; | ||
| 659 | pInput.height = p.height; | ||
| 660 | pInput.frameRate = p.frameRate; | ||
| 661 | prepareEncDecParam (pInput); | ||
| 662 | while (iIdx++ < iTotalFrameNum) { // loop in frame | ||
| 663 | EncodeOneFrame(); | ||
| 664 | #ifdef DEBUG_FILE_SAVE_CRA | ||
| 665 | //reset file if file size large | ||
| 666 | if ((info.eFrameType == videoFrameTypeIDR) && (iFileSize >= (1 << 25))) { | ||
| 667 | fclose (fDataFile); | ||
| 668 | fDataFile = fopen ("test_crash.264", "wb"); | ||
| 669 | iFileSize = 0; | ||
| 670 | decoder_->Uninitialize(); | ||
| 671 | |||
| 672 | SDecodingParam decParam; | ||
| 673 | memset (&decParam, 0, sizeof (SDecodingParam)); | ||
| 674 | decParam.uiTargetDqLayer = UCHAR_MAX; | ||
| 675 | decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY; | ||
| 676 | decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; | ||
| 677 | |||
| 678 | rv = decoder_->Initialize (&decParam); | ||
| 679 | ASSERT_EQ (0, rv); | ||
| 680 | } | ||
| 681 | #endif | ||
| 682 | if (info.eFrameType == videoFrameTypeSkip) | ||
| 683 | continue; | ||
| 684 | //deal with packets | ||
| 685 | unsigned char* pBsBuf; | ||
| 686 | iDecAuSize = 0; | ||
| 687 | pucBuf = ucBuf_; //init buf start pos for decoder usage | ||
| 688 | for (int iLayerNum = 0; iLayerNum < info.iLayerNum; iLayerNum++) { | ||
| 689 | SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayerNum]; | ||
| 690 | pBsBuf = info.sLayerInfo[iLayerNum].pBsBuf; | ||
| 691 | int iTotalNalCnt = pLayerBsInfo->iNalCount; | ||
| 692 | for (int iNalCnt = 0; iNalCnt < iTotalNalCnt; iNalCnt++) { //loop in NAL | ||
| 693 | int iPacketSize = pLayerBsInfo->pNalLengthInByte[iNalCnt]; | ||
| 694 | //packet loss | ||
| 695 | int iLossRateRange = (uiLoopRound % 100) + 1; //1-100 | ||
| 696 | int iLossRate = (rand() % iLossRateRange); | ||
| 697 | bool bPacketLost = (rand() % 101) > (100 - | ||
| 698 | iLossRate); // [0, (100-iLossRate)] indicates NO LOSS, (100-iLossRate, 100] indicates LOSS | ||
| 699 | if (!bPacketLost) { //no loss | ||
| 700 | memcpy (pucBuf, pBsBuf, iPacketSize); | ||
| 701 | pucBuf += iPacketSize; | ||
| 702 | iDecAuSize += iPacketSize; | ||
| 703 | } | ||
| 704 | #ifdef DEBUG_FILE_SAVE_CRA | ||
| 705 | else { | ||
| 706 | printf ("lost packet size=%d at frame-type=%d at loss rate %d (%d)\n", iPacketSize, info.eFrameType, iLossRate, | ||
| 707 | iLossRateRange); | ||
| 708 | } | ||
| 709 | #endif | ||
| 710 | //update bs info | ||
| 711 | pBsBuf += iPacketSize; | ||
| 712 | } //nal | ||
| 713 | } //layer | ||
| 714 | |||
| 715 | #ifdef DEBUG_FILE_SAVE_CRA | ||
| 716 | //save to file | ||
| 717 | fwrite (ucBuf_, 1, iDecAuSize, fDataFile); | ||
| 718 | fflush (fDataFile); | ||
| 719 | iFileSize += iDecAuSize; | ||
| 720 | |||
| 721 | //save to len file | ||
| 722 | unsigned long ulTmp[4]; | ||
| 723 | ulTmp[0] = ulTmp[1] = ulTmp[2] = iIdx; | ||
| 724 | ulTmp[3] = iDecAuSize; | ||
| 725 | fwrite (ulTmp, sizeof (unsigned long), 4, fLenFile); // index, timeStamp, data size | ||
| 726 | fflush (fLenFile); | ||
| 727 | #endif | ||
| 728 | |||
| 729 | //decode | ||
| 730 | pData[0] = pData[1] = pData[2] = 0; | ||
| 731 | memset (&dstBufInfo_, 0, sizeof (SBufferInfo)); | ||
| 732 | |||
| 733 | rv = decoder_->DecodeFrame2 (ucBuf_, iDecAuSize, pData, &dstBufInfo_); | ||
| 734 | rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction | ||
| 735 | //guarantee decoder EC status | ||
| 736 | decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet); | ||
| 737 | EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); | ||
| 738 | } //frame | ||
| 739 | uiLoopRound ++; | ||
| 740 | if (uiLoopRound >= (1 << 30)) | ||
| 741 | uiLoopRound = 0; | ||
| 742 | #ifdef DEBUG_FILE_SAVE_CRA | ||
| 743 | if (uiLoopRound % 100 == 0) | ||
| 744 | printf ("run %d times.\n", uiLoopRound); | ||
| 745 | } while (1); //while (iLoopRound<100); | ||
| 746 | fclose (fDataFile); | ||
| 747 | fclose (fLenFile); | ||
| 748 | #else | ||
| 749 | } | ||
| 750 | while (uiLoopRound < 10); | ||
| 751 | #endif | ||
| 752 | |||
| 753 | } | ||
| 754 | |||
| 755 | const uint32_t kiTotalLayer = 3; //DO NOT CHANGE! | ||
| 756 | const uint32_t kiSliceNum = 2; //DO NOT CHANGE! | ||
| 757 | const uint32_t kiWidth = 160; //DO NOT CHANGE! | ||
| 758 | const uint32_t kiHeight = 96; //DO NOT CHANGE! | ||
| 759 | const uint32_t kiFrameRate = 12; //DO NOT CHANGE! | ||
| 760 | const uint32_t kiFrameNum = 100; //DO NOT CHANGE! | ||
| 761 | const char* pHashStr[] = { //DO NOT CHANGE! | ||
| 762 | "585663f78cadb70d9c9f179b9b53b90ffddf3178", | ||
| 763 | "f350001c333902029800bd291fbed915a4bdf19a", | ||
| 764 | "eb9d853b7daec03052c4850027ac94adc84c3a7e" | ||
| 765 | }; | ||
| 766 | |||
| 767 | class DecodeParseAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase { | ||
| 768 | public: | ||
| 769 | void SetUp() { | ||
| 770 | SHA1Reset (&ctx_); | ||
| 771 | EncodeDecodeTestBase::SetUp(); | ||
| 772 | |||
| 773 | if (decoder_) | ||
| 774 | decoder_->Uninitialize(); | ||
| 775 | SDecodingParam decParam; | ||
| 776 | memset (&decParam, 0, sizeof (SDecodingParam)); | ||
| 777 | decParam.uiTargetDqLayer = UCHAR_MAX; | ||
| 778 | decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY; | ||
| 779 | decParam.bParseOnly = true; | ||
| 780 | decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; | ||
| 781 | |||
| 782 | int rv = decoder_->Initialize (&decParam); | ||
| 783 | ASSERT_EQ (0, rv); | ||
| 784 | memset (&BsInfo_, 0, sizeof (SParserBsInfo)); | ||
| 785 | fYuv_ = fopen ("./res/CiscoVT2people_160x96_6fps.yuv", "rb"); | ||
| 786 | ASSERT_TRUE (fYuv_ != NULL); | ||
| 787 | iWidth_ = kiWidth; | ||
| 788 | iHeight_ = kiHeight; | ||
| 789 | } | ||
| 790 | void TearDown() { | ||
| 791 | EncodeDecodeTestBase::TearDown(); | ||
| 792 | fclose (fYuv_); | ||
| 793 | } | ||
| 794 | |||
| 795 | void prepareEncDecParam (const EncodeDecodeFileParamBase p) { | ||
| 796 | EncodeDecodeTestBase::prepareEncDecParam (p); | ||
| 797 | unsigned char* pTmpPtr = BsInfo_.pDstBuff; //store for restore | ||
| 798 | memset (&BsInfo_, 0, sizeof (SParserBsInfo)); | ||
| 799 | BsInfo_.pDstBuff = pTmpPtr; | ||
| 800 | } | ||
| 801 | |||
| 802 | void EncodeOneFrame (int iIdx) { | ||
| 803 | int iFrameSize = iWidth_ * iHeight_ * 3 / 2; | ||
| 804 | int iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_); | ||
| 805 | if (feof (fYuv_) || iSize != iFrameSize) { | ||
| 806 | rewind (fYuv_); | ||
| 807 | iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_); | ||
| 808 | ASSERT_TRUE (iSize == iFrameSize); | ||
| 809 | } | ||
| 810 | int rv = encoder_->EncodeFrame (&EncPic, &info); | ||
| 811 | ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason); | ||
| 812 | } | ||
| 813 | |||
| 814 | void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) { | ||
| 815 | memset (pParam, 0, sizeof (SEncParamExt)); | ||
| 816 | EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam); | ||
| 817 | } | ||
| 818 | |||
| 819 | protected: | ||
| 820 | SParserBsInfo BsInfo_; | ||
| 821 | FILE* fYuv_; | ||
| 822 | int iWidth_; | ||
| 823 | int iHeight_; | ||
| 824 | SHA1Context ctx_; | ||
| 825 | }; | ||
| 826 | |||
| 827 | //#define DEBUG_FILE_SAVE | ||
| 828 | TEST_F (DecodeParseAPI, ParseOnly_General) { | ||
| 829 | EncodeDecodeFileParamBase p; | ||
| 830 | p.width = iWidth_; | ||
| 831 | p.height = iHeight_; | ||
| 832 | p.frameRate = kiFrameRate; | ||
| 833 | p.numframes = kiFrameNum; | ||
| 834 | prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate, ¶m_); | ||
| 835 | param_.iSpatialLayerNum = kiTotalLayer; | ||
| 836 | encoder_->Uninitialize(); | ||
| 837 | int rv = encoder_->InitializeExt (¶m_); | ||
| 838 | ASSERT_TRUE (rv == 0); | ||
| 839 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 840 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 841 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 842 | uint32_t uiTargetLayerId = rand() % kiTotalLayer; //run only once | ||
| 843 | #ifdef DEBUG_FILE_SAVE | ||
| 844 | FILE* fDec = fopen ("output.264", "wb"); | ||
| 845 | FILE* fEnc = fopen ("enc.264", "wb"); | ||
| 846 | FILE* fExtract = fopen ("extract.264", "wb"); | ||
| 847 | #endif | ||
| 848 | if (uiTargetLayerId < kiTotalLayer) { //should always be true | ||
| 849 | //Start for enc | ||
| 850 | int iLen = 0; | ||
| 851 | prepareEncDecParam (p); | ||
| 852 | int iFrame = 0; | ||
| 853 | |||
| 854 | while (iFrame < p.numframes) { | ||
| 855 | //encode | ||
| 856 | EncodeOneFrame (iFrame); | ||
| 857 | //extract target layer data | ||
| 858 | encToDecData (info, iLen); | ||
| 859 | #ifdef DEBUG_FILE_SAVE | ||
| 860 | fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fEnc); | ||
| 861 | #endif | ||
| 862 | ExtractDidNal (&info, iLen, &m_SLostSim, uiTargetLayerId); | ||
| 863 | #ifdef DEBUG_FILE_SAVE | ||
| 864 | fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fExtract); | ||
| 865 | #endif | ||
| 866 | //parseonly | ||
| 867 | //BsInfo_.pDstBuff = new unsigned char [1000000]; | ||
| 868 | rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_); | ||
| 869 | EXPECT_TRUE (rv == 0); | ||
| 870 | EXPECT_TRUE (BsInfo_.iNalNum == 0); | ||
| 871 | rv = decoder_->DecodeParser (NULL, 0, &BsInfo_); | ||
| 872 | EXPECT_TRUE (rv == 0); | ||
| 873 | EXPECT_TRUE (BsInfo_.iNalNum != 0); | ||
| 874 | //get final output bs | ||
| 875 | iLen = 0; | ||
| 876 | int i = 0; | ||
| 877 | while (i < BsInfo_.iNalNum) { | ||
| 878 | iLen += BsInfo_.iNalLenInByte[i]; | ||
| 879 | i++; | ||
| 880 | } | ||
| 881 | #ifdef DEBUG_FILE_SAVE | ||
| 882 | fwrite (BsInfo_.pDstBuff, iLen, 1, fDec); | ||
| 883 | #endif | ||
| 884 | SHA1Input (&ctx_, BsInfo_.pDstBuff, iLen); | ||
| 885 | iFrame++; | ||
| 886 | } | ||
| 887 | //calculate final SHA1 value | ||
| 888 | unsigned char digest[SHA_DIGEST_LENGTH]; | ||
| 889 | SHA1Result (&ctx_, digest); | ||
| 890 | if (!HasFatalFailure()) { | ||
| 891 | CompareHash (digest, pHashStr[uiTargetLayerId]); | ||
| 892 | } | ||
| 893 | } //while | ||
| 894 | #ifdef DEBUG_FILE_SAVE | ||
| 895 | fclose (fEnc); | ||
| 896 | fclose (fExtract); | ||
| 897 | fclose (fDec); | ||
| 898 | #endif | ||
| 899 | } | ||
| 900 | |||
| 901 | //This case is for one layer only, for incomplete frame input | ||
| 902 | //First slice is loss for random one picture with 2 slices per pic | ||
| 903 | TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) { | ||
| 904 | int32_t iLayerNum = 1; | ||
| 905 | int32_t iSliceNum = 2; | ||
| 906 | EncodeDecodeFileParamBase p; | ||
| 907 | p.width = iWidth_; | ||
| 908 | p.height = iHeight_; | ||
| 909 | p.frameRate = kiFrameRate; | ||
| 910 | p.numframes = 5; | ||
| 911 | prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_); | ||
| 912 | param_.iSpatialLayerNum = iLayerNum; | ||
| 913 | encoder_->Uninitialize(); | ||
| 914 | int rv = encoder_->InitializeExt (¶m_); | ||
| 915 | ASSERT_TRUE (rv == 0); | ||
| 916 | int32_t iTraceLevel = WELS_LOG_QUIET; | ||
| 917 | encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 918 | decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel); | ||
| 919 | |||
| 920 | int32_t iMissedPicNum = rand() % (p.numframes - 1) + 1; //IDR no loss | ||
| 921 | //Start for enc | ||
| 922 | int iLen = 0; | ||
| 923 | uint32_t uiGet; | ||
| 924 | prepareEncDecParam (p); | ||
| 925 | int iFrame = 0; | ||
| 926 | |||
| 927 | while (iFrame < p.numframes) { | ||
| 928 | //encode | ||
| 929 | EncodeOneFrame (iFrame); | ||
| 930 | //parseonly | ||
| 931 | if (iFrame == iMissedPicNum) { //make current frame partly missing | ||
| 932 | //Frame: P, first slice loss | ||
| 933 | int32_t iTotalSliceSize = 0; | ||
| 934 | encToDecSliceData (0, 0, info, iTotalSliceSize); //slice 1 lost | ||
| 935 | encToDecSliceData (0, 1, info, iLen); //slice 2 | ||
| 936 | decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet); | ||
| 937 | EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE); | ||
| 938 | rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, iLen, &BsInfo_); | ||
| 939 | EXPECT_TRUE (rv == 0); | ||
| 940 | EXPECT_TRUE (BsInfo_.iNalNum == 0); | ||
| 941 | rv = decoder_->DecodeParser (NULL, 0, &BsInfo_); | ||
| 942 | EXPECT_TRUE (rv != 0); | ||
| 943 | } else { //normal frame, complete | ||
| 944 | encToDecData (info, iLen); | ||
| 945 | rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_); | ||
| 946 | EXPECT_TRUE (rv == 0); //parse correct | ||
| 947 | EXPECT_TRUE (BsInfo_.iNalNum == 0); | ||
| 948 | rv = decoder_->DecodeParser (NULL, 0, &BsInfo_); | ||
| 949 | if (iFrame < iMissedPicNum) { //correct frames, all OK with output | ||
| 950 | EXPECT_TRUE (rv == 0); | ||
| 951 | EXPECT_TRUE (BsInfo_.iNalNum != 0); | ||
| 952 | } else { //(iFrame > iMissedPicNum), should output nothing as error | ||
| 953 | EXPECT_TRUE (rv != 0); | ||
| 954 | EXPECT_TRUE (BsInfo_.iNalNum == 0); | ||
| 955 | } | ||
| 956 | } | ||
| 957 | iFrame++; | ||
| 958 | } //while | ||
| 959 | } | ||
| 960 | |||
| 961 | |||
| 962 | |||