427 lines · 13.0 KB · C++
RawDownload
#include <gtest/gtest.h>#include "codec_app_def.h"#include "codec_api.h"#include "decoder_context.h"#include "decoder.h"#include "decoder_core.h"#include "welsCodecTrace.h"#include "../../common/src/welsCodecTrace.cpp" using namespace WelsDec; #define BUF_SIZE 100typedef enum DecCase {  CorrectDec = 0,  ErrorDec = 1,  CorrectParseOnly = 2,  ErrorParseOnly = 3,  RESERVED,} EDecCase; DECODING_STATE DecodeFrame (const unsigned char* kpSrc,                            const int kiSrcLen,                            unsigned char** ppDst,                            SBufferInfo* pDstInfo,                            PWelsDecoderContext pCtx) {  PWelsDecoderContext m_pDecContext = pCtx;  if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {    return dsOutOfMemory;  }  if (kiSrcLen > 0 && kpSrc != NULL) {    m_pDecContext->bEndOfStreamFlag = false;  } else {    //For application MODE, the error detection should be added for safe.    //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.    m_pDecContext->bEndOfStreamFlag = true;    m_pDecContext->bInstantDecFlag = true;  }    ppDst[0] = ppDst[1] = ppDst[2] = NULL;  m_pDecContext->iErrorCode             = dsErrorFree; //initialize at the starting of AU decoding.  m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize  unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;  memset (pDstInfo, 0, sizeof (SBufferInfo));  pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;   m_pDecContext->bReferenceLostAtT0Flag       = false; //initialize for LTR  m_pDecContext->bCurAuContainLtrMarkSeFlag = false;  m_pDecContext->iFrameNumOfAuMarkedLtr      = 0;  m_pDecContext->iFrameNum                       = -1; //initialize    m_pDecContext->iFeedbackTidInAu             = -1; //initialize  if (pDstInfo) {    pDstInfo->uiOutYuvTimeStamp = 0;    m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;  } else {    m_pDecContext->uiTimeStamp = 0;  }  WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,                pDstInfo, NULL); //iErrorCode has been modified in this function  m_pDecContext->bInstantDecFlag = false; //reset no-delay flag   return (DECODING_STATE) m_pDecContext->iErrorCode;} void UninitDecoder (PWelsDecoderContext& pCtx) {  if (NULL == pCtx)    return;   WelsEndDecoder (pCtx);  if (NULL != pCtx->pMemAlign) {    delete pCtx->pMemAlign;    pCtx->pMemAlign = NULL;  }  if (NULL != pCtx) {    free (pCtx);    pCtx = NULL;  } } int32_t InitDecoder (const SDecodingParam* pParam, PWelsDecoderContext pCtx, SLogContext* pLogCtx) {    if (NULL == pCtx)    return cmMallocMemeError;   if (NULL == pCtx->pMemAlign) {    pCtx->pMemAlign = new CMemoryAlign (16);    if (NULL == pCtx->pMemAlign)      return cmMallocMemeError;  }   pCtx->sLogCtx = *pLogCtx;   //check param and update decoder context  pCtx->pParam = (SDecodingParam*) pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam), "SDecodingParam");  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoder (pCtx));  int32_t iRet = DecoderConfigParam (pCtx, pParam);  WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);   WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, WelsInitDecoder (pCtx, pLogCtx), UninitDecoder (pCtx));   return cmResultSuccess;} long Initialize (const SDecodingParam* pParam, PWelsDecoderContext pCtx, SLogContext* pLogCtx) {  int iRet = ERR_NONE;  if (pParam == NULL) {    return cmInitParaError;  }   // H.264 decoder initialization,including memory allocation,then open it ready to decode  iRet = InitDecoder (pParam, pCtx, pLogCtx);  if (iRet)    return iRet;   return cmResultSuccess;} class DecoderParseSyntaxTest : public ::testing::Test { public:  virtual void SetUp() {     int rv = WelsCreateDecoder (&m_pDec);    ASSERT_EQ (0, rv);    ASSERT_TRUE (m_pDec != NULL);  }   virtual void TearDown() {    if (m_pDec) {      WelsDestroyDecoder (m_pDec);    }  }  //Init members  int32_t Init();  //Uninit members  void Uninit();  //Decoder real bitstream  bool DecodeBs (const char* sFileName, EDecCase eDecCase);  //Parse real bitstream  bool ParseBs (const char* sFileName, EDecCase eDecCase);  //Scalinglist  void TestScalingList();  //specific bitstream test  void TestSpecificBs();  void TestSpecificBsError();  //Do whole tests here  void DecoderParseSyntaxTestAll();   public:  ISVCDecoder* m_pDec;  SDecodingParam m_sDecParam;  SBufferInfo m_sBufferInfo;  SParserBsInfo m_sParserBsInfo;  uint8_t* m_pData[3];  unsigned char m_szBuffer[BUF_SIZE]; //for mocking packet  int m_iBufLength; //record the valid data in m_szBuffer  PWelsDecoderContext m_pCtx;  welsCodecTrace* m_pWelsTrace; }; //Init membersint32_t DecoderParseSyntaxTest::Init() {  memset (&m_sBufferInfo, 0, sizeof (SBufferInfo));  memset (&m_sDecParam, 0, sizeof (SDecodingParam));  memset (&m_sParserBsInfo, 0, sizeof (SParserBsInfo));  m_sDecParam.pFileNameRestructed = NULL;  m_sDecParam.uiCpuLoad = rand() % 100;  m_sDecParam.uiTargetDqLayer = rand() % 100;  m_sDecParam.eEcActiveIdc = (ERROR_CON_IDC)7;  m_sDecParam.sVideoProperty.size = sizeof (SVideoProperty);  m_sDecParam.sVideoProperty.eVideoBsType = (VIDEO_BITSTREAM_TYPE) (rand() % 2);  m_sDecParam.bParseOnly = false;   m_pData[0] = m_pData[1] = m_pData[2] = NULL;  m_szBuffer[0] = m_szBuffer[1] = m_szBuffer[2] = 0;  m_szBuffer[3] = 1;  m_iBufLength = 4;  //  m_pCtx = (PWelsDecoderContext)malloc (sizeof (SWelsDecoderContext));  if (m_pCtx == NULL)    return ERR_MALLOC_FAILED;  memset (m_pCtx, 0, sizeof (SWelsDecoderContext));  m_pWelsTrace = new welsCodecTrace();  if (m_pWelsTrace != NULL) {    m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);  } else {    free (m_pCtx);    m_pCtx = NULL;    return ERR_MALLOC_FAILED;  }  CM_RETURN eRet = (CM_RETURN)Initialize (&m_sDecParam, m_pCtx, &m_pWelsTrace->m_sLogCtx);  return (int32_t)eRet;} void DecoderParseSyntaxTest::Uninit() {  if (m_pCtx) {    UninitDecoder (m_pCtx);  }  if (m_pWelsTrace) {    delete m_pWelsTrace;    m_pWelsTrace = NULL;  }  memset (&m_sDecParam, 0, sizeof (SDecodingParam));  memset (&m_sBufferInfo, 0, sizeof (SBufferInfo));  m_pData[0] = m_pData[1] = m_pData[2] = NULL;  m_iBufLength = 0;} bool DecoderParseSyntaxTest::DecodeBs (const char* sFileName, EDecCase eDecCase) {   uint8_t* pBuf = NULL;  int32_t iBufPos = 0;  int32_t iFileSize;  int32_t i = 0;  int32_t iSliceSize;  int32_t iEndOfStreamFlag = 0;  FILE* pH264File;  uint8_t uiStartCode[4] = {0, 0, 0, 1};  int iRet = 0; #if defined(ANDROID_NDK)  std::string filename = std::string ("/sdcard/") + sFileName;  if ((pH264File = fopen (filename.c_str(), "rb")) == NULL)    return false;#else  if ((pH264File = fopen (sFileName, "rb")) == NULL)    return false;#endif  fseek (pH264File, 0L, SEEK_END);  iFileSize = (int32_t) ftell (pH264File);  fseek (pH264File, 0L, SEEK_SET);  pBuf = new uint8_t[iFileSize + 4];  if (pBuf == NULL) {    fclose (pH264File);    return false;  }  if ((fread (pBuf, 1, iFileSize, pH264File) != (unsigned int) iFileSize)) {    fclose (pH264File);    if (pBuf) {      delete[] pBuf;      pBuf = NULL;    }    return false;  }  memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage  while (true) {    if (iBufPos >= iFileSize) {      iEndOfStreamFlag = true;      if (iEndOfStreamFlag)        m_pDec->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);      break;    }    for (i = 0; i < iFileSize; i++) {      if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1           && i > 0)) {        break;      }    }    iSliceSize = i;    iRet |= DecodeFrame (pBuf + iBufPos, iSliceSize, m_pData, &m_sBufferInfo, m_pCtx);    iBufPos += iSliceSize;  }  if (eDecCase == CorrectDec)    EXPECT_TRUE (iRet == dsErrorFree);  else if (eDecCase == ErrorDec)    EXPECT_TRUE ((iRet & (dsBitstreamError | dsRefLost | dsDataErrorConcealed)) != 0) << "iRet = " << iRet;   fclose (pH264File);  if (pBuf) {    delete[] pBuf;    pBuf = NULL;  }   return true;}bool DecoderParseSyntaxTest::ParseBs (const char* sFileName, EDecCase eDecCase) {   uint8_t* pBuf = NULL;  int32_t iBufPos = 0;  int32_t iFileSize;  int32_t i = 0;  int32_t iSliceSize;  int32_t iSliceIndex = 0;  int32_t iEndOfStreamFlag = 0;  FILE* pH264File;  uint8_t uiStartCode[4] = { 0, 0, 0, 1 };  int iRet = 0; #if defined(ANDROID_NDK)  std::string filename = std::string ("/sdcard/") + sFileName;  if ((pH264File = fopen (filename.c_str(), "rb")) == NULL)    return false;#else  if ((pH264File = fopen (sFileName, "rb")) == NULL)    return false;#endif  fseek (pH264File, 0L, SEEK_END);  iFileSize = (int32_t)ftell (pH264File);  fseek (pH264File, 0L, SEEK_SET);  pBuf = new uint8_t[iFileSize + 4];  if (pBuf == NULL) {    fclose (pH264File);    return false;  }  if (fread (pBuf, 1, iFileSize, pH264File) != (unsigned int)iFileSize) {    fclose (pH264File);    if (pBuf) {      delete[] pBuf;      pBuf = NULL;    }    return false;  }  memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage  while (true) {    if (iBufPos >= iFileSize) {      iEndOfStreamFlag = true;      if (iEndOfStreamFlag)        m_pDec->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);      break;    }    for (i = 0; i < iFileSize; i++) {      if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1           && i > 0)) {        break;      }    }    iSliceSize = i;    memset (&m_sParserBsInfo, 0, sizeof (SParserBsInfo));    iRet |= m_pDec->DecodeParser (pBuf + iBufPos, iSliceSize, &m_sParserBsInfo);    iRet |= m_pDec->DecodeParser (NULL, 0, &m_sParserBsInfo);    if (eDecCase == CorrectParseOnly)      EXPECT_TRUE (iRet == dsErrorFree || iRet == dsFramePending);    iBufPos += iSliceSize;    ++iSliceIndex;    if (iSliceIndex == 4)      break;  }  if (eDecCase == ErrorDec)    EXPECT_TRUE ((iRet & (dsBitstreamError | dsRefLost | dsDataErrorConcealed)) != 0) << iRet;   fclose (pH264File);  if (pBuf) {    delete[] pBuf;    pBuf = NULL;  }   return true;}  void DecoderParseSyntaxTest::TestScalingList() {  uint8_t iScalingList[6][16] = {    {17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 15 },    { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 39 },    { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 40 },    {17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 14 },    {10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34 },    { 9, 13, 18, 21, 13, 18, 21, 24, 18, 21, 24, 27, 21, 24, 27, 27 }  };  uint8_t iScalingListPPS[6][16] = {    { 17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 15 },    { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 39 },    { 6, 12, 19, 26, 12, 19, 26, 31, 19, 26, 31, 35, 26, 31, 35, 40 },    { 17, 17, 16, 16, 17, 16, 15, 15, 16, 15, 15, 15, 16, 15, 15, 14 },    { 10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34 },    { 9, 13, 18, 21, 13, 18, 21, 24, 18, 21, 24, 27, 21, 24, 27, 27 }  };  uint8_t iScalingListZero[6][16];  memset (iScalingListZero, 0, 6 * 16 * sizeof (uint8_t));  //Scalinglist matrix not written into sps or pps  int32_t iRet = ERR_NONE;  iRet = Init();  ASSERT_EQ (iRet, ERR_NONE);  ASSERT_TRUE (DecodeBs ("res/BA_MW_D.264", CorrectDec));  ASSERT_TRUE (m_pCtx->sSpsBuffer[0].bSeqScalingMatrixPresentFlag == false);  EXPECT_EQ (0, memcmp (iScalingListZero, m_pCtx->sSpsBuffer[0].iScalingList4x4, 6 * 16 * sizeof (uint8_t)));  ASSERT_TRUE (m_pCtx->sPpsBuffer[0].bPicScalingMatrixPresentFlag == false);  EXPECT_EQ (0, memcmp (iScalingListZero, m_pCtx->sPpsBuffer[0].iScalingList4x4, 6 * 16 * sizeof (uint8_t)));  Uninit();  //Scalinglist value just written into sps and pps  iRet = Init();  ASSERT_EQ (iRet, ERR_NONE);  ASSERT_TRUE (DecodeBs ("res/test_scalinglist_jm.264", CorrectDec));  ASSERT_TRUE (m_pCtx->sSpsBuffer[0].bSeqScalingMatrixPresentFlag);  for (int i = 0; i < 6; i++) {    EXPECT_EQ (0, memcmp (iScalingList[i], m_pCtx->sSpsBuffer[0].iScalingList4x4[i], 16 * sizeof (uint8_t)));  }   ASSERT_TRUE (m_pCtx->sPpsBuffer[0].bPicScalingMatrixPresentFlag == true);  for (int i = 0; i < 6; i++) {    EXPECT_EQ (0, memcmp (iScalingListPPS[i], m_pCtx->sPpsBuffer[0].iScalingList4x4[i], 16 * sizeof (uint8_t)));  }  Uninit();} void DecoderParseSyntaxTest::TestSpecificBs() {  int32_t iRet = ERR_NONE;  m_sDecParam.bParseOnly = true;  m_sDecParam.eEcActiveIdc = ERROR_CON_DISABLE;  iRet = m_pDec->Initialize (&m_sDecParam);  ASSERT_EQ (iRet, ERR_NONE);  ASSERT_TRUE (ParseBs ("res/jm_1080p_allslice.264", CorrectParseOnly));  m_pDec->Uninitialize();} void DecoderParseSyntaxTest::TestSpecificBsError() {  int32_t iRet = ERR_NONE;  Init();  ASSERT_EQ (iRet, ERR_NONE);  ASSERT_TRUE (DecodeBs ("res/Cisco_Men_whisper_640x320_CAVLC_Bframe_9.264", ErrorDec));  Uninit();} //TEST here for whole testsTEST_F (DecoderParseSyntaxTest, DecoderParseSyntaxTestAll) {   TestScalingList();  TestSpecificBs();  TestSpecificBsError();}  

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t