1083 lines · 37.8 KB · C++
RawDownload
/*! * \copy *     Copyright (c)  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. * */ #include <assert.h>#include "welsEncoderExt.h"#include "welsCodecTrace.h"#include "typedefs.h"#include "wels_const.h"#include "utils.h"#include "macros.h" #include "crt_util_safe_x.h"	// Safe CRT routines like util for cross platforms#include "ref_list_mgr_svc.h" #include <time.h>#if defined(_WIN32) /*&& defined(_DEBUG)*/ #include <windows.h>#include <stdio.h>#include <stdarg.h>#include <sys/types.h>#include <sys/timeb.h>#else#include <sys/time.h>#endif namespace WelsSVCEnc { /* *	CWelsH264SVCEncoder class implementation */CWelsH264SVCEncoder::CWelsH264SVCEncoder()  :	m_pEncContext (NULL),    m_pWelsTrace (NULL),    m_pSrcPicList (NULL),    m_iSrcListSize (0),    m_iMaxPicWidth (0),    m_iMaxPicHeight (0),    m_iCspInternal (0),    m_bInitialFlag (false) {#ifdef REC_FRAME_COUNT  int32_t m_uiCountFrameNum = 0;#endif//REC_FRAME_COUNT #ifdef OUTPUT_BIT_STREAM  char strStreamFileName[1024] = { 0 };  //for .264  int32_t iBufferUsed = 0;  int32_t iBufferLeft = 1023;  int32_t iCurUsed;   char strLenFileName[1024] = { 0 }; //for .len  int32_t iBufferUsedSize = 0;  int32_t iBufferLeftSize = 1023;  int32_t iCurUsedSize;#endif//OUTPUT_BIT_STREAM #ifdef OUTPUT_BIT_STREAM  SWelsTime tTime;   WelsGetTimeOfDay(&tTime);   iCurUsed      = WelsSnprintf (strStreamFileName, iBufferLeft, "enc_bs_0x%p_", (void*)this);  iCurUsedSize  = WelsSnprintf (strLenFileName, iBufferLeftSize, "enc_size_0x%p_", (void*)this);    if (iCurUsed > 0) {    iBufferUsed += iCurUsed;    iBufferLeft -= iCurUsed;  }  if (iBufferLeft > 0) {    iCurUsed = WelsStrftime (&strStreamFileName[iBufferUsed], iBufferLeft, "%y%m%d%H%M%S", &tTime);    iBufferUsed += iCurUsed;    iBufferLeft -= iCurUsed;  }   if (iCurUsedSize > 0) {    iBufferUsedSize += iCurUsedSize;    iBufferLeftSize -= iCurUsedSize;  }  if (iBufferLeftSize > 0) {    iCurUsedSize = WelsStrftime (&strLenFileName[iBufferUsedSize], iBufferLeftSize, "%y%m%d%H%M%S", &tTime);    iBufferUsedSize += iCurUsedSize;    iBufferLeftSize -= iCurUsedSize;  }   if (iBufferLeft > 0) {    iCurUsed = WelsSnprintf (&strStreamFileName[iBufferUsed], iBufferLeft, ".%03.3u.264",                             WelsGetMillisecond(&tTime));    if (iCurUsed > 0) {      iBufferUsed += iCurUsed;      iBufferLeft -= iCurUsed;    }  }   if (iBufferLeftSize > 0) {    iCurUsedSize = WelsSnprintf (&strLenFileName[iBufferUsedSize], iBufferLeftSize, ".%03.3u.len",                                 WelsGetMillisecond(&tTime));    if (iCurUsedSize > 0) {      iBufferUsedSize += iCurUsedSize;      iBufferLeftSize -= iCurUsedSize;    }  }   m_pFileBs     = WelsFopen (strStreamFileName, "wb");  m_pFileBsSize = WelsFopen (strLenFileName, "wb");   m_bSwitch	= false;  m_iSwitchTimes	= 0;#endif//OUTPUT_BIT_STREAM   InitEncoder();  XMMREG_PROTECT_INIT(CWelsH264SVCEncoder);} CWelsH264SVCEncoder::~CWelsH264SVCEncoder() {  WelsLog (NULL, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder()\n");   if (m_pWelsTrace != NULL) {    delete m_pWelsTrace;    m_pWelsTrace = NULL;  }#ifdef REC_FRAME_COUNT  WelsLog (m_pEncContext, WELS_LOG_INFO,           "CWelsH264SVCEncoder::~CWelsH264SVCEncoder(), m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum,           m_iCspInternal);#endif #ifdef REC_FRAME_COUNT  m_uiCountFrameNum = 0;#endif//REC_FRAME_COUNT #ifdef OUTPUT_BIT_STREAM  if (m_pFileBs) {    WelsFclose (m_pFileBs);    m_pFileBs = NULL;  }  if (m_pFileBsSize) {    WelsFclose (m_pFileBsSize);    m_pFileBsSize = NULL;  }  m_bSwitch	= false;  m_iSwitchTimes	= 0;#endif//OUTPUT_BIT_STREAM   Uninitialize();  XMMREG_PROTECT_UNINIT(CWelsH264SVCEncoder);} void CWelsH264SVCEncoder::InitEncoder (void) { #ifdef REC_FRAME_COUNT  WelsLog (m_pEncContext, WELS_LOG_INFO,           "CWelsH264SVCEncoder::InitEncoder, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal);#endif   m_pWelsTrace	= new welsCodecTrace();  if (m_pWelsTrace != NULL) {    const int32_t iWelsTraceExistingFlag = m_pWelsTrace->WelsTraceModuleIsExist();    if (iWelsTraceExistingFlag) {      m_pWelsTrace->SetTraceLevel (WELS_LOG_DEFAULT);      WelsSetLogCallback (welsCodecTrace::CODEC_TRACE);    }  }   // initialization  WelsSetLogLevel (WELS_LOG_DEFAULT);	// no output, WELS_LOG_QUIET} /* Interfaces override from ISVCEncoder */ /* *	SVC Encoder Initialization */int CWelsH264SVCEncoder::Initialize (const SEncParamBase* argv) {   if (NULL == argv) {    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p\n",             argv);    return cmInitParaError;  }   SWelsSvcCodingParam	sConfig (true);  // Convert SEncParamBase into WelsSVCParamConfig here..  if (sConfig.ParamBaseTranscode (*argv, true)) {    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n");    Uninitialize();    return cmInitParaError;  }   return Initialize2 (&sConfig);} int CWelsH264SVCEncoder::InitializeExt (const SEncParamExt* argv) {   if (NULL == argv) {    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p\n",             argv);    return cmInitParaError;  }   SWelsSvcCodingParam	sConfig (true);  // Convert SEncParamExt into WelsSVCParamConfig here..  if (sConfig.ParamTranscode (*argv)) {    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n");    Uninitialize();    return cmInitParaError;  }   return Initialize2 (&sConfig);} int CWelsH264SVCEncoder::Initialize2 (SWelsSvcCodingParam* pCfg) {  if (NULL == pCfg) {    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p.\n",             pCfg);    return cmInitParaError;  }   if (m_bInitialFlag) {    WelsLog (m_pEncContext, WELS_LOG_WARNING, "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.\n",             m_bInitialFlag);    Uninitialize();  } #ifdef REC_FRAME_COUNT  SWelsSvcCodingParam &sEncodingParam = *pCfg;  WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Initialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n",           m_uiCountFrameNum, m_iCspInternal);  WelsLog (m_pEncContext, WELS_LOG_INFO,           "coding_param->iPicWidth= %d;coding_param->iPicHeight= %d;coding_param->iTargetBitrate= %d;coding_param->iRCMode= %d;coding_param->iTemporalLayerNum= %d;coding_param->iSpatialLayerNum= %d;coding_param->fFrameRate= %.6ff;coding_param->iInputCsp= %d;coding_param->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableFrameSkip= %d;coding_param->bEnableCropPic= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d;\n",           sEncodingParam.iPicWidth,           sEncodingParam.iPicHeight,           sEncodingParam.iTargetBitrate,           sEncodingParam.iRCMode,           sEncodingParam.iTemporalLayerNum,           sEncodingParam.iSpatialLayerNum,           sEncodingParam.fMaxFrameRate,           sEncodingParam.iInputCsp,           sEncodingParam.uiIntraPeriod,           sEncodingParam.bEnableSpsPpsIdAddition,           sEncodingParam.bPrefixNalAddingCtrl,           sEncodingParam.bEnableDenoise,           sEncodingParam.bEnableBackgroundDetection,           sEncodingParam.bEnableAdaptiveQuant,           sEncodingParam.bEnableFrameSkip,           sEncodingParam.bEnableCropPic,           sEncodingParam.bEnableLongTermReference,           sEncodingParam.iLtrMarkPeriod);  int32_t i = 0;  while (i < sEncodingParam.iSpatialLayerNum) {    SSpatialLayerConfig* spatial_cfg = &sEncodingParam.sSpatialLayers[i];    WelsLog (m_pEncContext, WELS_LOG_INFO,             "coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.uiSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d;\n",             i, spatial_cfg->iVideoWidth,             spatial_cfg->iVideoHeight,             spatial_cfg->fFrameRate,             spatial_cfg->iSpatialBitrate,             spatial_cfg->sSliceCfg.uiSliceMode,             spatial_cfg->sSliceCfg.sSliceArgument.uiSliceNum,             spatial_cfg->sSliceCfg.sSliceArgument.uiSliceSizeConstraint            );    ++ i;  }#endif//REC_FRAME_COUNT   const int32_t iColorspace = pCfg->iInputCsp;  if (0 == iColorspace) {    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInputCsp= %d.\n", iColorspace);    Uninitialize();    return cmInitParaError;  }   // Check valid parameters  const int32_t iNumOfLayers = pCfg->iSpatialLayerNum;  if (iNumOfLayers < 1 || iNumOfLayers > MAX_DEPENDENCY_LAYER) {    WelsLog (m_pEncContext, WELS_LOG_ERROR,             "CWelsH264SVCEncoder::Initialize(), invalid iSpatialLayerNum= %d, valid at range of [1, %d].\n", iNumOfLayers,             MAX_DEPENDENCY_LAYER);    Uninitialize();    return cmInitParaError;  }  if (pCfg->iTemporalLayerNum < 1)    pCfg->iTemporalLayerNum	= 1;  if (pCfg->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) {    WelsLog (m_pEncContext, WELS_LOG_ERROR,             "CWelsH264SVCEncoder::Initialize(), invalid iTemporalLayerNum= %d, valid at range of [1, %d].\n",             pCfg->iTemporalLayerNum, MAX_TEMPORAL_LEVEL);    Uninitialize();    return cmInitParaError;  }   //	assert( cfg.uiGopSize >= 1 && ( cfg.uiIntraPeriod && (cfg.uiIntraPeriod % cfg.uiGopSize) == 0) );   if (pCfg->uiGopSize < 1 || pCfg->uiGopSize > MAX_GOP_SIZE) {    WelsLog (m_pEncContext, WELS_LOG_ERROR,             "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d].\n", pCfg->uiGopSize,             MAX_GOP_SIZE);    Uninitialize();    return cmInitParaError;  }   if (!WELS_POWER2_IF (pCfg->uiGopSize)) {    WelsLog (m_pEncContext, WELS_LOG_ERROR,             "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d] and yield to power of 2.\n",             pCfg->uiGopSize, MAX_GOP_SIZE);    Uninitialize();    return cmInitParaError;  }   if (pCfg->uiIntraPeriod && pCfg->uiIntraPeriod < pCfg->uiGopSize) {    WelsLog (m_pEncContext, WELS_LOG_ERROR,             "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d.\n",             pCfg->uiIntraPeriod, pCfg->uiGopSize);    Uninitialize();    return cmInitParaError;  }   if ((pCfg->uiIntraPeriod && (pCfg->uiIntraPeriod & (pCfg->uiGopSize - 1)) != 0)) {    WelsLog (m_pEncContext, WELS_LOG_ERROR,             "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d also multiple of it.\n",             pCfg->uiIntraPeriod, pCfg->uiGopSize);    Uninitialize();    return cmInitParaError;  }   // Fine tune num_ref_num  if (pCfg->bEnableLongTermReference) {    pCfg->iLTRRefNum = LONG_TERM_REF_NUM;  } else {    pCfg->iLTRRefNum = 0;  }  pCfg->iNumRefFrame = ((pCfg->uiGopSize >> 1) > 1) ? ((pCfg->uiGopSize >> 1) + pCfg->iLTRRefNum) :                       (MIN_REF_PIC_COUNT + pCfg->iLTRRefNum);   pCfg->iNumRefFrame = WELS_CLIP3 (pCfg->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);   if (pCfg->iLtrMarkPeriod == 0) {    pCfg->iLtrMarkPeriod = 30;  }   const int32_t kiDecStages = WELS_LOG2 (pCfg->uiGopSize);  pCfg->iInputCsp			= iColorspace;  pCfg->iTemporalLayerNum	= (int8_t) (1 + kiDecStages);  pCfg->iLoopFilterAlphaC0Offset	= WELS_CLIP3 (pCfg->iLoopFilterAlphaC0Offset, -6, 6);  pCfg->iLoopFilterBetaOffset		= WELS_CLIP3 (pCfg->iLoopFilterBetaOffset, -6, 6); //	m_pSrcPicList	= (SSourcePicture **)WelsMalloc( pCfg->iSpatialLayerNum * sizeof(SSourcePicture *), "m_pSrcPicList" );  // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched)  m_pSrcPicList	= new SSourcePicture* [iNumOfLayers];   if (NULL == m_pSrcPicList) {    WelsLog (m_pEncContext, WELS_LOG_ERROR,             "CWelsH264SVCEncoder::Initialize(), pOut of memory due m_pSrcPicList memory request.\n");    Uninitialize();    return cmMallocMemeError;  }   // decide property list size between INIT_TYPE_PARAMETER_BASED/INIT_TYPE_CONFIG_BASED  m_iMaxPicWidth	= pCfg->iPicWidth;  m_iMaxPicHeight	= pCfg->iPicHeight;  m_iSrcListSize  = iNumOfLayers;   for (int32_t i = 0; i < m_iSrcListSize; ++ i) {//		m_pSrcPicList[i]	= (SSourcePicture *)WelsMalloc( sizeof(SSourcePicture), "m_pSrcPicList[]" );    // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched)    m_pSrcPicList[i]	= new SSourcePicture;     if (NULL == m_pSrcPicList[i]) {      WelsLog (m_pEncContext, WELS_LOG_ERROR,               "CWelsH264SVCEncoder::Initialize(), pOut of memory due m_pSrcPicList[%d] memory request.\n", i);      Uninitialize();      m_iSrcListSize = 0;      return cmMallocMemeError;    }    InitPic (m_pSrcPicList[i], iColorspace, m_iMaxPicWidth, m_iMaxPicHeight);  }   if (WelsInitEncoderExt (&m_pEncContext, pCfg)) {    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.\n");    Uninitialize();    return cmInitParaError;  }   m_iCspInternal	= iColorspace;  m_bInitialFlag  = true;   return cmResultSuccess;} /* *	SVC Encoder Uninitialization */int32_t CWelsH264SVCEncoder::Uninitialize() {  if (!m_bInitialFlag) {    return 0;  }   WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize()..\n"); #ifdef REC_FRAME_COUNT  WelsLog (m_pEncContext, WELS_LOG_INFO,           "CWelsH264SVCEncoder::Uninitialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal);#endif//REC_FRAME_COUNT   if (NULL != m_pEncContext) {    if (NULL != m_pSrcPicList) {      for (int32_t i = 0; i < m_iSrcListSize; i++) {        SSourcePicture* pic = m_pSrcPicList[i];        if (NULL != pic) {//					WelsFree( pic, "m_pSrcPicList[]" );          // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched)          delete pic;           pic = NULL;        }      }//			WelsFree( m_pSrcPicList, "m_pSrcPicList" );      // prefer use new/delete pair due encoder intialization stage not start yet for CacheLineSize not detection here (16 or 64 not matched)      delete [] m_pSrcPicList;       m_pSrcPicList = NULL;      m_iSrcListSize = 0;    }     WelsUninitEncoderExt (&m_pEncContext);    m_pEncContext	= NULL;  }   m_bInitialFlag = false;   return 0;}  int32_t CWelsH264SVCEncoder::RawData2SrcPic (const uint8_t* pSrc) {  assert (m_iSrcListSize > 0);   int32_t y_length = m_iMaxPicWidth * m_iMaxPicHeight;  m_pSrcPicList[0]->pData[0] = const_cast<uint8_t*> (pSrc);   switch (m_iCspInternal & (~videoFormatVFlip)) {  case videoFormatYVYU:  case videoFormatUYVY:  case videoFormatYUY2:  case videoFormatRGB:  case videoFormatBGR:  case videoFormatBGRA:  case videoFormatRGBA:  case videoFormatARGB:  case videoFormatABGR:    m_pSrcPicList[0]->pData[1] = m_pSrcPicList[0]->pData[2] = NULL;    break;  case videoFormatI420:  case videoFormatYV12:    m_pSrcPicList[0]->pData[1] = m_pSrcPicList[0]->pData[0] + y_length;    m_pSrcPicList[0]->pData[2] = m_pSrcPicList[0]->pData[1] + (y_length >> 2);    break;  default:    return 1;  }   return 0;}  /* *	SVC core encoding */int CWelsH264SVCEncoder::EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo) {  if (! (kpSrcPic && m_pEncContext && m_bInitialFlag)) {    return videoFrameTypeInvalid;

Lines 1–500 of 1083.

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