#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 100
typedef 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;
  SWelsDecoderSpsPpsCTX   m_sDecoderSpsPpsCTX;
  SWelsLastDecPicInfo     m_sLastDecPicInfo;
  SDecoderStatistics      m_sDecoderStatistics;
  SVlcTable               m_sVlcTable;

  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 members
int32_t DecoderParseSyntaxTest::Init() {
  memset (&m_sBufferInfo, 0, sizeof (SBufferInfo));
  memset (&m_sDecParam, 0, sizeof (SDecodingParam));
  memset (&m_sParserBsInfo, 0, sizeof (SParserBsInfo));
  memset (&m_sDecoderSpsPpsCTX, 0, sizeof (SWelsDecoderSpsPpsCTX));
  memset (&m_sLastDecPicInfo, 0, sizeof (SWelsLastDecPicInfo));
  memset (&m_sDecoderStatistics, 0, sizeof (SDecoderStatistics));
  memset (&m_sVlcTable, 0, sizeof (SVlcTable));

  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;
  }
  m_pCtx->pLastDecPicInfo = &m_sLastDecPicInfo;
  m_pCtx->pDecoderStatistics = &m_sDecoderStatistics;
  m_pCtx->pVlcTable = &m_sVlcTable;
  WelsDecoderSpsPpsDefaults (m_pCtx->sSpsPpsCtx);
  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->sSpsPpsCtx.sSpsBuffer[0].bSeqScalingMatrixPresentFlag == false);
  EXPECT_EQ (0, memcmp (iScalingListZero, m_pCtx->sSpsPpsCtx.sSpsBuffer[0].iScalingList4x4, 6 * 16 * sizeof (uint8_t)));
  ASSERT_TRUE (m_pCtx->sSpsPpsCtx.sPpsBuffer[0].bPicScalingMatrixPresentFlag == false);
  EXPECT_EQ (0, memcmp (iScalingListZero, m_pCtx->sSpsPpsCtx.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->sSpsPpsCtx.sSpsBuffer[0].bSeqScalingMatrixPresentFlag);
  for (int i = 0; i < 6; i++) {
    EXPECT_EQ (0, memcmp (iScalingList[i], m_pCtx->sSpsPpsCtx.sSpsBuffer[0].iScalingList4x4[i], 16 * sizeof (uint8_t)));
  }

  ASSERT_TRUE (m_pCtx->sSpsPpsCtx.sPpsBuffer[0].bPicScalingMatrixPresentFlag == true);
  for (int i = 0; i < 6; i++) {
    EXPECT_EQ (0, memcmp (iScalingListPPS[i], m_pCtx->sSpsPpsCtx.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", CorrectDec));
  Uninit();
}

//TEST here for whole tests
TEST_F (DecoderParseSyntaxTest, DecoderParseSyntaxTestAll) {

  TestScalingList();
  TestSpecificBs();
  TestSpecificBsError();
}


