• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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