1 #include <gtest/gtest.h>
2 #include "codec_app_def.h"
3 #include "codec_api.h"
4 #include "decoder_context.h"
5 #include "decoder.h"
6 #include "decoder_core.h"
7 #include "welsCodecTrace.h"
8 #include "../../common/src/welsCodecTrace.cpp"
9
10 using namespace WelsDec;
11
12 #define BUF_SIZE 100
13 typedef enum DecCase {
14 CorrectDec = 0,
15 ErrorDec = 1,
16 CorrectParseOnly = 2,
17 ErrorParseOnly = 3,
18 RESERVED,
19 } EDecCase;
20
DecodeFrame(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo,PWelsDecoderContext pCtx)21 DECODING_STATE DecodeFrame (const unsigned char* kpSrc,
22 const int kiSrcLen,
23 unsigned char** ppDst,
24 SBufferInfo* pDstInfo,
25 PWelsDecoderContext pCtx) {
26 PWelsDecoderContext m_pDecContext = pCtx;
27 if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
28 return dsOutOfMemory;
29 }
30 if (kiSrcLen > 0 && kpSrc != NULL) {
31 m_pDecContext->bEndOfStreamFlag = false;
32 } else {
33 //For application MODE, the error detection should be added for safe.
34 //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
35 m_pDecContext->bEndOfStreamFlag = true;
36 m_pDecContext->bInstantDecFlag = true;
37 }
38
39
40 ppDst[0] = ppDst[1] = ppDst[2] = NULL;
41 m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
42 m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
43 unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
44 memset (pDstInfo, 0, sizeof (SBufferInfo));
45 pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
46
47 m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
48 m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
49 m_pDecContext->iFrameNumOfAuMarkedLtr = 0;
50 m_pDecContext->iFrameNum = -1; //initialize
51
52
53 m_pDecContext->iFeedbackTidInAu = -1; //initialize
54 if (pDstInfo) {
55 pDstInfo->uiOutYuvTimeStamp = 0;
56 m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
57 } else {
58 m_pDecContext->uiTimeStamp = 0;
59 }
60 WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
61 pDstInfo, NULL); //iErrorCode has been modified in this function
62 m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
63
64 return (DECODING_STATE) m_pDecContext->iErrorCode;
65 }
66
UninitDecoder(PWelsDecoderContext & pCtx)67 void UninitDecoder (PWelsDecoderContext& pCtx) {
68 if (NULL == pCtx)
69 return;
70
71 WelsEndDecoder (pCtx);
72 if (NULL != pCtx->pMemAlign) {
73 delete pCtx->pMemAlign;
74 pCtx->pMemAlign = NULL;
75 }
76 if (NULL != pCtx) {
77 free (pCtx);
78 pCtx = NULL;
79 }
80
81 }
82
InitDecoder(const SDecodingParam * pParam,PWelsDecoderContext pCtx,SLogContext * pLogCtx)83 int32_t InitDecoder (const SDecodingParam* pParam, PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
84
85
86 if (NULL == pCtx)
87 return cmMallocMemeError;
88
89 if (NULL == pCtx->pMemAlign) {
90 pCtx->pMemAlign = new CMemoryAlign (16);
91 if (NULL == pCtx->pMemAlign)
92 return cmMallocMemeError;
93 }
94
95 pCtx->sLogCtx = *pLogCtx;
96
97 //check param and update decoder context
98 pCtx->pParam = (SDecodingParam*) pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam), "SDecodingParam");
99 WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoder (pCtx));
100 int32_t iRet = DecoderConfigParam (pCtx, pParam);
101 WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
102
103 WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, WelsInitDecoder (pCtx, pLogCtx), UninitDecoder (pCtx));
104
105 return cmResultSuccess;
106 }
107
Initialize(const SDecodingParam * pParam,PWelsDecoderContext pCtx,SLogContext * pLogCtx)108 long Initialize (const SDecodingParam* pParam, PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
109 int iRet = ERR_NONE;
110 if (pParam == NULL) {
111 return cmInitParaError;
112 }
113
114 // H.264 decoder initialization,including memory allocation,then open it ready to decode
115 iRet = InitDecoder (pParam, pCtx, pLogCtx);
116 if (iRet)
117 return iRet;
118
119 return cmResultSuccess;
120 }
121
122 class DecoderParseSyntaxTest : public ::testing::Test {
123 public:
SetUp()124 virtual void SetUp() {
125
126 int rv = WelsCreateDecoder (&m_pDec);
127 ASSERT_EQ (0, rv);
128 ASSERT_TRUE (m_pDec != NULL);
129 }
130
TearDown()131 virtual void TearDown() {
132 if (m_pDec) {
133 WelsDestroyDecoder (m_pDec);
134 }
135 }
136 //Init members
137 int32_t Init();
138 //Uninit members
139 void Uninit();
140 //Decoder real bitstream
141 bool DecodeBs (const char* sFileName, EDecCase eDecCase);
142 //Parse real bitstream
143 bool ParseBs (const char* sFileName, EDecCase eDecCase);
144 //Scalinglist
145 void TestScalingList();
146 //specific bitstream test
147 void TestSpecificBs();
148 void TestSpecificBsError();
149 //Do whole tests here
150 void DecoderParseSyntaxTestAll();
151
152
153 public:
154 ISVCDecoder* m_pDec;
155 SDecodingParam m_sDecParam;
156 SBufferInfo m_sBufferInfo;
157 SParserBsInfo m_sParserBsInfo;
158 SWelsDecoderSpsPpsCTX m_sDecoderSpsPpsCTX;
159 SWelsLastDecPicInfo m_sLastDecPicInfo;
160 SDecoderStatistics m_sDecoderStatistics;
161 SVlcTable m_sVlcTable;
162
163 uint8_t* m_pData[3];
164 unsigned char m_szBuffer[BUF_SIZE]; //for mocking packet
165 int m_iBufLength; //record the valid data in m_szBuffer
166 PWelsDecoderContext m_pCtx;
167 welsCodecTrace* m_pWelsTrace;
168
169 };
170
171 //Init members
Init()172 int32_t DecoderParseSyntaxTest::Init() {
173 memset (&m_sBufferInfo, 0, sizeof (SBufferInfo));
174 memset (&m_sDecParam, 0, sizeof (SDecodingParam));
175 memset (&m_sParserBsInfo, 0, sizeof (SParserBsInfo));
176 memset (&m_sDecoderSpsPpsCTX, 0, sizeof (SWelsDecoderSpsPpsCTX));
177 memset (&m_sLastDecPicInfo, 0, sizeof (SWelsLastDecPicInfo));
178 memset (&m_sDecoderStatistics, 0, sizeof (SDecoderStatistics));
179 memset (&m_sVlcTable, 0, sizeof (SVlcTable));
180
181 m_sDecParam.pFileNameRestructed = NULL;
182 m_sDecParam.uiCpuLoad = rand() % 100;
183 m_sDecParam.uiTargetDqLayer = rand() % 100;
184 m_sDecParam.eEcActiveIdc = (ERROR_CON_IDC)7;
185 m_sDecParam.sVideoProperty.size = sizeof (SVideoProperty);
186 m_sDecParam.sVideoProperty.eVideoBsType = (VIDEO_BITSTREAM_TYPE) (rand() % 2);
187 m_sDecParam.bParseOnly = false;
188
189 m_pData[0] = m_pData[1] = m_pData[2] = NULL;
190 m_szBuffer[0] = m_szBuffer[1] = m_szBuffer[2] = 0;
191 m_szBuffer[3] = 1;
192 m_iBufLength = 4;
193 //
194 m_pCtx = (PWelsDecoderContext)malloc (sizeof (SWelsDecoderContext));
195 if (m_pCtx == NULL)
196 return ERR_MALLOC_FAILED;
197 memset (m_pCtx, 0, sizeof (SWelsDecoderContext));
198 m_pWelsTrace = new welsCodecTrace();
199 if (m_pWelsTrace != NULL) {
200 m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
201 } else {
202 free (m_pCtx);
203 m_pCtx = NULL;
204 return ERR_MALLOC_FAILED;
205 }
206 m_pCtx->pLastDecPicInfo = &m_sLastDecPicInfo;
207 m_pCtx->pDecoderStatistics = &m_sDecoderStatistics;
208 m_pCtx->pVlcTable = &m_sVlcTable;
209 WelsDecoderSpsPpsDefaults (m_pCtx->sSpsPpsCtx);
210 CM_RETURN eRet = (CM_RETURN)Initialize (&m_sDecParam, m_pCtx, &m_pWelsTrace->m_sLogCtx);
211 return (int32_t)eRet;
212 }
213
Uninit()214 void DecoderParseSyntaxTest::Uninit() {
215 if (m_pCtx) {
216 UninitDecoder (m_pCtx);
217 }
218 if (m_pWelsTrace) {
219 delete m_pWelsTrace;
220 m_pWelsTrace = NULL;
221 }
222 memset (&m_sDecParam, 0, sizeof (SDecodingParam));
223 memset (&m_sBufferInfo, 0, sizeof (SBufferInfo));
224 m_pData[0] = m_pData[1] = m_pData[2] = NULL;
225 m_iBufLength = 0;
226 }
227
DecodeBs(const char * sFileName,EDecCase eDecCase)228 bool DecoderParseSyntaxTest::DecodeBs (const char* sFileName, EDecCase eDecCase) {
229
230 uint8_t* pBuf = NULL;
231 int32_t iBufPos = 0;
232 int32_t iFileSize;
233 int32_t i = 0;
234 int32_t iSliceSize;
235 int32_t iEndOfStreamFlag = 0;
236 FILE* pH264File;
237 uint8_t uiStartCode[4] = {0, 0, 0, 1};
238 int iRet = 0;
239
240 #if defined(ANDROID_NDK)
241 std::string filename = std::string ("/sdcard/") + sFileName;
242 if ((pH264File = fopen (filename.c_str(), "rb")) == NULL)
243 return false;
244 #else
245 if ((pH264File = fopen (sFileName, "rb")) == NULL)
246 return false;
247 #endif
248 fseek (pH264File, 0L, SEEK_END);
249 iFileSize = (int32_t) ftell (pH264File);
250 fseek (pH264File, 0L, SEEK_SET);
251 pBuf = new uint8_t[iFileSize + 4];
252 if (pBuf == NULL) {
253 fclose (pH264File);
254 return false;
255 }
256 if ((fread (pBuf, 1, iFileSize, pH264File) != (unsigned int) iFileSize)) {
257 fclose (pH264File);
258 if (pBuf) {
259 delete[] pBuf;
260 pBuf = NULL;
261 }
262 return false;
263 }
264 memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage
265 while (true) {
266 if (iBufPos >= iFileSize) {
267 iEndOfStreamFlag = true;
268 if (iEndOfStreamFlag)
269 m_pDec->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
270 break;
271 }
272 for (i = 0; i < iFileSize; i++) {
273 if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
274 && i > 0)) {
275 break;
276 }
277 }
278 iSliceSize = i;
279 iRet |= DecodeFrame (pBuf + iBufPos, iSliceSize, m_pData, &m_sBufferInfo, m_pCtx);
280 iBufPos += iSliceSize;
281 }
282 if (eDecCase == CorrectDec) {
283 EXPECT_TRUE (iRet == dsErrorFree);
284 } else if (eDecCase == ErrorDec) {
285 EXPECT_TRUE ((iRet & (dsBitstreamError | dsRefLost | dsDataErrorConcealed)) != 0) << "iRet = " << iRet;
286 }
287
288 fclose (pH264File);
289 if (pBuf) {
290 delete[] pBuf;
291 pBuf = NULL;
292 }
293
294 return true;
295 }
ParseBs(const char * sFileName,EDecCase eDecCase)296 bool DecoderParseSyntaxTest::ParseBs (const char* sFileName, EDecCase eDecCase) {
297
298 uint8_t* pBuf = NULL;
299 int32_t iBufPos = 0;
300 int32_t iFileSize;
301 int32_t i = 0;
302 int32_t iSliceSize;
303 int32_t iSliceIndex = 0;
304 int32_t iEndOfStreamFlag = 0;
305 FILE* pH264File;
306 uint8_t uiStartCode[4] = { 0, 0, 0, 1 };
307 int iRet = 0;
308
309 #if defined(ANDROID_NDK)
310 std::string filename = std::string ("/sdcard/") + sFileName;
311 if ((pH264File = fopen (filename.c_str(), "rb")) == NULL)
312 return false;
313 #else
314 if ((pH264File = fopen (sFileName, "rb")) == NULL)
315 return false;
316 #endif
317 fseek (pH264File, 0L, SEEK_END);
318 iFileSize = (int32_t)ftell (pH264File);
319 fseek (pH264File, 0L, SEEK_SET);
320 pBuf = new uint8_t[iFileSize + 4];
321 if (pBuf == NULL) {
322 fclose (pH264File);
323 return false;
324 }
325 if (fread (pBuf, 1, iFileSize, pH264File) != (unsigned int)iFileSize) {
326 fclose (pH264File);
327 if (pBuf) {
328 delete[] pBuf;
329 pBuf = NULL;
330 }
331 return false;
332 }
333 memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage
334 while (true) {
335 if (iBufPos >= iFileSize) {
336 iEndOfStreamFlag = true;
337 if (iEndOfStreamFlag)
338 m_pDec->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
339 break;
340 }
341 for (i = 0; i < iFileSize; i++) {
342 if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
343 && i > 0)) {
344 break;
345 }
346 }
347 iSliceSize = i;
348 memset (&m_sParserBsInfo, 0, sizeof (SParserBsInfo));
349 iRet |= m_pDec->DecodeParser (pBuf + iBufPos, iSliceSize, &m_sParserBsInfo);
350 iRet |= m_pDec->DecodeParser (NULL, 0, &m_sParserBsInfo);
351 if (eDecCase == CorrectParseOnly) {
352 EXPECT_TRUE (iRet == dsErrorFree || iRet == dsFramePending);
353 }
354
355 iBufPos += iSliceSize;
356 ++iSliceIndex;
357 if (iSliceIndex == 4)
358 break;
359 }
360 if (eDecCase == ErrorDec) {
361 EXPECT_TRUE ((iRet & (dsBitstreamError | dsRefLost | dsDataErrorConcealed)) != 0) << iRet;
362 }
363
364 fclose (pH264File);
365 if (pBuf) {
366 delete[] pBuf;
367 pBuf = NULL;
368 }
369
370 return true;
371 }
372
373
TestScalingList()374 void DecoderParseSyntaxTest::TestScalingList() {
375 uint8_t iScalingList[6][16] = {
376 {17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 15 },
377 { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 39 },
378 { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 40 },
379 {17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 14 },
380 {10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34 },
381 { 9, 13, 18, 21, 13, 18, 21, 24, 18, 21, 24, 27, 21, 24, 27, 27 }
382 };
383 uint8_t iScalingListPPS[6][16] = {
384 { 17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 15 },
385 { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 39 },
386 { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 40 },
387 { 17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 14 },
388 { 10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34 },
389 { 9, 13, 18, 21, 13, 18, 21, 24, 18, 21, 24, 27, 21, 24, 27, 27 }
390 };
391 uint8_t iScalingListZero[6][16];
392 memset (iScalingListZero, 0, 6 * 16 * sizeof (uint8_t));
393 //Scalinglist matrix not written into sps or pps
394 int32_t iRet = ERR_NONE;
395 iRet = Init();
396 ASSERT_EQ (iRet, ERR_NONE);
397 ASSERT_TRUE (DecodeBs ("res/BA_MW_D.264", CorrectDec));
398 ASSERT_TRUE (m_pCtx->sSpsPpsCtx.sSpsBuffer[0].bSeqScalingMatrixPresentFlag == false);
399 EXPECT_EQ (0, memcmp (iScalingListZero, m_pCtx->sSpsPpsCtx.sSpsBuffer[0].iScalingList4x4, 6 * 16 * sizeof (uint8_t)));
400 ASSERT_TRUE (m_pCtx->sSpsPpsCtx.sPpsBuffer[0].bPicScalingMatrixPresentFlag == false);
401 EXPECT_EQ (0, memcmp (iScalingListZero, m_pCtx->sSpsPpsCtx.sPpsBuffer[0].iScalingList4x4, 6 * 16 * sizeof (uint8_t)));
402 Uninit();
403 //Scalinglist value just written into sps and pps
404 iRet = Init();
405 ASSERT_EQ (iRet, ERR_NONE);
406 ASSERT_TRUE (DecodeBs ("res/test_scalinglist_jm.264", CorrectDec));
407 ASSERT_TRUE (m_pCtx->sSpsPpsCtx.sSpsBuffer[0].bSeqScalingMatrixPresentFlag);
408 for (int i = 0; i < 6; i++) {
409 EXPECT_EQ (0, memcmp (iScalingList[i], m_pCtx->sSpsPpsCtx.sSpsBuffer[0].iScalingList4x4[i], 16 * sizeof (uint8_t)));
410 }
411
412 ASSERT_TRUE (m_pCtx->sSpsPpsCtx.sPpsBuffer[0].bPicScalingMatrixPresentFlag == true);
413 for (int i = 0; i < 6; i++) {
414 EXPECT_EQ (0, memcmp (iScalingListPPS[i], m_pCtx->sSpsPpsCtx.sPpsBuffer[0].iScalingList4x4[i], 16 * sizeof (uint8_t)));
415 }
416 Uninit();
417 }
418
TestSpecificBs()419 void DecoderParseSyntaxTest::TestSpecificBs() {
420 int32_t iRet = ERR_NONE;
421 m_sDecParam.bParseOnly = true;
422 m_sDecParam.eEcActiveIdc = ERROR_CON_DISABLE;
423 iRet = m_pDec->Initialize (&m_sDecParam);
424 ASSERT_EQ (iRet, ERR_NONE);
425 ASSERT_TRUE (ParseBs ("res/jm_1080p_allslice.264", CorrectParseOnly));
426 m_pDec->Uninitialize();
427 }
428
TestSpecificBsError()429 void DecoderParseSyntaxTest::TestSpecificBsError() {
430 int32_t iRet = ERR_NONE;
431 Init();
432 ASSERT_EQ (iRet, ERR_NONE);
433 ASSERT_TRUE (DecodeBs ("res/Cisco_Men_whisper_640x320_CAVLC_Bframe_9.264", CorrectDec));
434 Uninit();
435 }
436
437 //TEST here for whole tests
TEST_F(DecoderParseSyntaxTest,DecoderParseSyntaxTestAll)438 TEST_F (DecoderParseSyntaxTest, DecoderParseSyntaxTestAll) {
439
440 TestScalingList();
441 TestSpecificBs();
442 TestSpecificBsError();
443 }
444
445
446