1498 lines · 56.9 KB · C++
RawDownload
/*! * \copy *     Copyright (c)  2009-2013, Cisco Systems *     All rights reserved. * *     Redistribution and use in source and binary forms, with or without *     modification, are permitted provided that the following conditions *     are met: * *        * Redistributions of source code must retain the above copyright *          notice, this list of conditions and the following disclaimer. * *        * Redistributions in binary form must reproduce the above copyright *          notice, this list of conditions and the following disclaimer in *          the documentation and/or other materials provided with the *          distribution. * *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *     POSSIBILITY OF SUCH DAMAGE. * * *  welsDecoderExt.cpp * *  Abstract *      Cisco OpenH264 decoder extension utilization * *  History *      3/12/2009 Created * * ************************************************************************///#include <assert.h>#include "welsDecoderExt.h"#include "welsCodecTrace.h"#include "codec_def.h"#include "typedefs.h"#include "memory_align.h"#include "utils.h"#include "version.h" //#include "macros.h"#include "decoder.h"#include "decoder_core.h"#include "manage_dec_ref.h"#include "error_concealment.h" #include "measure_time.h"extern "C" {#include "decoder_core.h"#include "manage_dec_ref.h"}#include "error_code.h"#include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms#include <time.h>#if defined(_WIN32) /*&& defined(_DEBUG)*/ #include <windows.h>#include <stdio.h>#include <stdarg.h>#include <sys/types.h>#include <malloc.h>#else#include <sys/time.h>#endif namespace WelsDec { //////////////////////////////////////////////////////////////////////// Construction/Destruction////////////////////////////////////////////////////////////////////// /****************************************************************************   Description:*       class CWelsDecoder constructor function, do initialization  and*       alloc memory required**   Input parameters: none**   return: none***************************************************************************/DECLARE_PROCTHREAD (pThrProcInit, p) {  SWelsDecThreadInfo* sThreadInfo = (SWelsDecThreadInfo*)p;#if defined(WIN32)  _alloca (WELS_DEC_MAX_THREAD_STACK_SIZE * (sThreadInfo->uiThrNum + 1));#endif  return sThreadInfo->pThrProcMain (p);} static DECODING_STATE  ConstructAccessUnit (CWelsDecoder* pWelsDecoder, PWelsDecoderThreadCTX pThrCtx) {  int iRet = dsErrorFree;  //WelsMutexLock (&pWelsDecoder->m_csDecoder);  if (pThrCtx->pCtx->pLastThreadCtx != NULL) {    PWelsDecoderThreadCTX pLastThreadCtx = (PWelsDecoderThreadCTX) (pThrCtx->pCtx->pLastThreadCtx);    WAIT_EVENT (&pLastThreadCtx->sSliceDecodeStart, WELS_DEC_THREAD_WAIT_INFINITE);    RESET_EVENT (&pLastThreadCtx->sSliceDecodeStart);  }  pThrCtx->pDec = NULL;  if (GetThreadCount (pThrCtx->pCtx) > 1) {    RESET_EVENT (&pThrCtx->sSliceDecodeFinish);  }  iRet |= pWelsDecoder->DecodeFrame2WithCtx (pThrCtx->pCtx, NULL, 0, pThrCtx->ppDst, &pThrCtx->sDstInfo);   //WelsMutexUnlock (&pWelsDecoder->m_csDecoder);  return (DECODING_STATE)iRet;} DECLARE_PROCTHREAD (pThrProcFrame, p) {  SWelsDecoderThreadCTX* pThrCtx = (SWelsDecoderThreadCTX*)p;  while (1) {    RELEASE_SEMAPHORE (pThrCtx->sThreadInfo.sIsBusy);    RELEASE_SEMAPHORE (&pThrCtx->sThreadInfo.sIsIdle);    WAIT_SEMAPHORE (&pThrCtx->sThreadInfo.sIsActivated, WELS_DEC_THREAD_WAIT_INFINITE);    if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_RUN) {      CWelsDecoder* pWelsDecoder = (CWelsDecoder*)pThrCtx->threadCtxOwner;      ConstructAccessUnit (pWelsDecoder, pThrCtx);    } else if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_ABORT) {      break;    }  }  return 0;} CWelsDecoder::CWelsDecoder (void)  : m_pWelsTrace (NULL),    m_uiDecodeTimeStamp (0),    m_bIsBaseline (false),    m_iCpuCount (1),    m_iThreadCount (0),    m_iCtxCount (1),    m_pPicBuff (NULL),    m_bParamSetsLostFlag (false),    m_bFreezeOutput (false),    m_DecCtxActiveCount (0),    m_pDecThrCtx (NULL),    m_pLastDecThrCtx (NULL),    m_iLastBufferedIdx (0) {#ifdef OUTPUT_BIT_STREAM  char chFileName[1024] = { 0 };  //for .264  int iBufUsed = 0;  int iBufLeft = 1023;  int iCurUsed;   char chFileNameSize[1024] = { 0 }; //for .len  int iBufUsedSize = 0;  int iBufLeftSize = 1023;  int iCurUsedSize;#endif//OUTPUT_BIT_STREAM    m_pWelsTrace = new welsCodecTrace();  if (m_pWelsTrace != NULL) {    m_pWelsTrace->SetCodecInstance (this);    m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");  }   ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);   m_iCpuCount = GetCPUCount();  if (m_iCpuCount > WELS_DEC_MAX_NUM_CPU) {    m_iCpuCount = WELS_DEC_MAX_NUM_CPU;  }   m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iCtxCount];  memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iCtxCount);  for (int32_t i = 0; i < WELS_DEC_MAX_NUM_CPU; ++i) {    m_pDecThrCtxActive[i] = NULL;  }#ifdef OUTPUT_BIT_STREAM  SWelsTime sCurTime;   WelsGetTimeOfDay (&sCurTime);   iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void*)this);  iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void*)this);   iBufUsed += iCurUsed;  iBufLeft -= iCurUsed;  if (iBufLeft > 0) {    iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);    iBufUsed += iCurUsed;    iBufLeft -= iCurUsed;  }   iBufUsedSize += iCurUsedSize;  iBufLeftSize -= iCurUsedSize;  if (iBufLeftSize > 0) {    iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);    iBufUsedSize += iCurUsedSize;    iBufLeftSize -= iCurUsedSize;  }   if (iBufLeft > 0) {    iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));    iBufUsed += iCurUsed;    iBufLeft -= iCurUsed;  }   if (iBufLeftSize > 0) {    iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",                                 WelsGetMillisecond (&sCurTime));    iBufUsedSize += iCurUsedSize;    iBufLeftSize -= iCurUsedSize;  }    m_pFBS = WelsFopen (chFileName, "wb");  m_pFBSSize = WelsFopen (chFileNameSize, "wb");#endif//OUTPUT_BIT_STREAM} /****************************************************************************   Description:*       class CWelsDecoder destructor function, destroy allocced memory**   Input parameters: none**   return: none***************************************************************************/CWelsDecoder::~CWelsDecoder() {  if (m_pWelsTrace != NULL) {    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");  }  CloseDecoderThreads();  UninitDecoder(); #ifdef OUTPUT_BIT_STREAM  if (m_pFBS) {    WelsFclose (m_pFBS);    m_pFBS = NULL;  }  if (m_pFBSSize) {    WelsFclose (m_pFBSSize);    m_pFBSSize = NULL;  }#endif//OUTPUT_BIT_STREAM   if (m_pWelsTrace != NULL) {    delete m_pWelsTrace;    m_pWelsTrace = NULL;  }  if (m_pDecThrCtx != NULL) {    delete[] m_pDecThrCtx;    m_pDecThrCtx = NULL;  }} long CWelsDecoder::Initialize (const SDecodingParam* pParam) {  int iRet = ERR_NONE;  if (m_pWelsTrace == NULL) {    return cmMallocMemeError;  }   if (pParam == NULL) {    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsDecoder::Initialize(), invalid input argument.");    return cmInitParaError;  }   // H.264 decoder initialization,including memory allocation,then open it ready to decode  iRet = InitDecoder (pParam);  if (iRet)    return iRet;   return cmResultSuccess;} long CWelsDecoder::Uninitialize() {  UninitDecoder();   return ERR_NONE;} void CWelsDecoder::UninitDecoder (void) {  for (int32_t i = 0; i < m_iCtxCount; ++i) {    if (m_pDecThrCtx[i].pCtx != NULL) {      if (i > 0) {        WelsResetRefPicWithoutUnRef (m_pDecThrCtx[i].pCtx);      }      UninitDecoderCtx (m_pDecThrCtx[i].pCtx);    }  }} void CWelsDecoder::OpenDecoderThreads() {  if (m_iThreadCount >= 1) {    m_uiDecodeTimeStamp = 0;    CREATE_SEMAPHORE (&m_sIsBusy, m_iThreadCount, m_iThreadCount, NULL);    WelsMutexInit (&m_csDecoder);    CREATE_EVENT (&m_sBufferingEvent, 1, 0, NULL);    SET_EVENT (&m_sBufferingEvent);    CREATE_EVENT (&m_sReleaseBufferEvent, 1, 0, NULL);    SET_EVENT (&m_sReleaseBufferEvent);    for (int32_t i = 0; i < m_iThreadCount; ++i) {      m_pDecThrCtx[i].sThreadInfo.uiThrMaxNum = m_iThreadCount;      m_pDecThrCtx[i].sThreadInfo.uiThrNum = i;      m_pDecThrCtx[i].sThreadInfo.uiThrStackSize = WELS_DEC_MAX_THREAD_STACK_SIZE;      m_pDecThrCtx[i].sThreadInfo.pThrProcMain = pThrProcFrame;      m_pDecThrCtx[i].sThreadInfo.sIsBusy = &m_sIsBusy;      m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;      m_pDecThrCtx[i].threadCtxOwner = this;      m_pDecThrCtx[i].kpSrc = NULL;      m_pDecThrCtx[i].kiSrcLen = 0;      m_pDecThrCtx[i].ppDst = NULL;      m_pDecThrCtx[i].pDec = NULL;      CREATE_EVENT (&m_pDecThrCtx[i].sImageReady, 1, 0, NULL);      CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart, 1, 0, NULL);      CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinish, 1, 0, NULL);      CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, 0, 1, NULL);      CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated, 0, 1, NULL);      CREATE_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle, pThrProcInit, (void*) (& (m_pDecThrCtx[i])));    }  }}void CWelsDecoder::CloseDecoderThreads() {  if (m_iThreadCount >= 1) {    for (int32_t i = 0; i < m_iThreadCount; i++) { //waiting the completion begun slices      WAIT_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);      m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_ABORT;      RELEASE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated);      WAIT_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle);      CLOSE_EVENT (&m_pDecThrCtx[i].sImageReady);      CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart);      CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinish);      CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle);      CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated);    }    WelsMutexDestroy (&m_csDecoder);    CLOSE_EVENT (&m_sBufferingEvent);    CLOSE_EVENT (&m_sReleaseBufferEvent);    CLOSE_SEMAPHORE (&m_sIsBusy);  }} void CWelsDecoder::UninitDecoderCtx (PWelsDecoderContext& pCtx) {  if (pCtx != NULL) {     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoderCtx(), openh264 codec version = %s.",             VERSION_NUMBER);     WelsEndDecoder (pCtx);     if (pCtx->pMemAlign != NULL) {      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,               "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",               pCtx->pMemAlign->WelsGetMemoryUsage());      delete pCtx->pMemAlign;      pCtx->pMemAlign = NULL;    }     if (NULL != pCtx) {      WelsFree (pCtx, "m_pDecContext");       pCtx = NULL;    }    if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = NULL;  }} // the return value of this function is not suitable, it need report failure info to upper layer.int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {   WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,           "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",           VERSION_NUMBER, (int32_t)pParam->bParseOnly);  if (m_iThreadCount >= 1 && pParam->bParseOnly) {    m_iThreadCount = 0;  }  OpenDecoderThreads();  //reset decoder context  memset (&m_sDecoderStatistics, 0, sizeof (SDecoderStatistics));  memset (&m_sLastDecPicInfo, 0, sizeof (SWelsLastDecPicInfo));  memset (&m_sVlcTable, 0, sizeof (SVlcTable));  UninitDecoder();  WelsDecoderLastDecPicInfoDefaults (m_sLastDecPicInfo);  for (int32_t i = 0; i < m_iCtxCount; ++i) {    InitDecoderCtx (m_pDecThrCtx[i].pCtx, pParam);    if (m_iThreadCount >= 1) {      m_pDecThrCtx[i].pCtx->pThreadCtx = &m_pDecThrCtx[i];    }  }  m_bParamSetsLostFlag = false;  m_bFreezeOutput = false;  return cmResultSuccess;} // the return value of this function is not suitable, it need report failure info to upper layer.int32_t CWelsDecoder::InitDecoderCtx (PWelsDecoderContext& pCtx, const SDecodingParam* pParam) {   WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,           "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",           VERSION_NUMBER, (int32_t)pParam->bParseOnly);   //reset decoder context  UninitDecoderCtx (pCtx);  pCtx = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");  if (NULL == pCtx)    return cmMallocMemeError;  int32_t iCacheLineSize = 16;   // on chip cache line size in byte  pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize);  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pMemAlign), UninitDecoderCtx (pCtx))  if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = pCtx;  //fill in default value into context  pCtx->pLastDecPicInfo = &m_sLastDecPicInfo;  pCtx->pDecoderStatistics = &m_sDecoderStatistics;  pCtx->pVlcTable = &m_sVlcTable;  pCtx->pPictInfoList = m_sPictInfoList;  pCtx->pPictReoderingStatus = &m_sReoderingStatus;  pCtx->pCsDecoder = &m_csDecoder;  WelsDecoderDefaults (pCtx, &m_pWelsTrace->m_sLogCtx);  WelsDecoderSpsPpsDefaults (pCtx->sSpsPpsCtx);  //check param and update decoder context  pCtx->pParam = (SDecodingParam*)pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam),                 "SDecodingParam");  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoderCtx (pCtx));  int32_t iRet = DecoderConfigParam (pCtx, pParam);  WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);   //init decoder  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (pCtx, &m_pWelsTrace->m_sLogCtx),                              UninitDecoderCtx (pCtx))  pCtx->pPicBuff = NULL;  return cmResultSuccess;} int32_t CWelsDecoder::ResetDecoder (PWelsDecoderContext& pCtx) {  // TBC: need to be modified when context and trace point are null  if (m_iThreadCount >= 1) {    ThreadResetDecoder (pCtx);  } else {    if (pCtx != NULL && m_pWelsTrace != NULL) {      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d",               pCtx->iErrorCode);      SDecodingParam sPrevParam;      memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam));       WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoderCtx (pCtx, &sPrevParam),                                  UninitDecoderCtx (pCtx));    } else if (m_pWelsTrace != NULL) {      WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");    }    ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, false);  }  return ERR_INFO_UNINIT;} int32_t CWelsDecoder::ThreadResetDecoder (PWelsDecoderContext& pCtx) {  // TBC: need to be modified when context and trace point are null  SDecodingParam sPrevParam;  if (pCtx != NULL && m_pWelsTrace != NULL) {    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d", pCtx->iErrorCode);    memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam));    ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);    CloseDecoderThreads();    UninitDecoder();    InitDecoder (&sPrevParam);  } else if (m_pWelsTrace != NULL) {    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");  }  return ERR_INFO_UNINIT;} /* * Set Option */long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {  int iVal = 0;  if (eOptID == DECODER_OPTION_NUM_OF_THREADS) {    if (pOption != NULL) {      int32_t threadCount = * ((int32_t*)pOption);      if (threadCount < 0) threadCount = 0;      if (threadCount > m_iCpuCount) {        threadCount = m_iCpuCount;      }      if (threadCount > 3) {        threadCount = 3;      }      if (threadCount != m_iThreadCount) {        m_iThreadCount = threadCount;        if (m_pDecThrCtx != NULL) {          delete [] m_pDecThrCtx;          m_iCtxCount = m_iThreadCount == 0 ? 1 : m_iThreadCount;          m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iCtxCount];          memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iCtxCount);        }      }    }    return cmResultSuccess;  }  for (int32_t i = 0; i < m_iCtxCount; ++i) {

Lines 1–500 of 1498.

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