1019 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. * */ #ifndef NO_DYNAMIC_VP#if defined(_WIN32)#include <windows.h>#elif defined(MACOS)#include "bundleloader.h"#elif defined(__GNUC__)#include <dlfcn.h>#endif#endif #include "wels_preprocess.h"#include "picture_handle.h"#include "encoder_context.h"#include "utils.h" #ifdef NO_DYNAMIC_VPEResult WELSAPI CreateVpInterface (void** ppCtx, int iVersion);EResult WELSAPI DestroyVpInterface (void** ppCtx, int iVersion);#endif namespace WelsSVCEnc { #define WelsSafeDelete(p) if(p){ delete (p); (p) = NULL; }  //***** entry API declaration ************************************************************************//typedef EResult (WELSAPI* pfnCreateVpInterface) (void**, int);typedef EResult (WELSAPI* pfnDestroyVpInterface) (void*, int); int32_t WelsInitScaledPic (SWelsSvcCodingParam* pParam,  Scaled_Picture*  pScaledPic, CMemoryAlign* pMemoryAlign);bool  JudgeNeedOfScaling (SWelsSvcCodingParam* pParam, Scaled_Picture* pScaledPic);void    FreeScaledPic (Scaled_Picture*  pScaledPic, CMemoryAlign* pMemoryAlign); //******* table definition ***********************************************************************//const uint8_t g_kuiRefTemporalIdx[MAX_TEMPORAL_LEVEL][MAX_GOP_SIZE] = {  {  0, }, // 0  {  0,  0, }, // 1  {  0,  0,  0,  1, }, // 2  {  0,  0,  0,  2,  0,  1,  1,  2, }, // 3}; const int32_t g_kiPixMapSizeInBits = sizeof (uint8_t) * 8;  inline  void   WelsUpdateSpatialIdxMap (sWelsEncCtx* pEncCtx, int32_t iPos, SPicture* pPic, int32_t iDidx) {  pEncCtx->sSpatialIndexMap[iPos].pSrc = pPic;  pEncCtx->sSpatialIndexMap[iPos].iDid = iDidx;}  //***************************************************************************************************//CWelsLib::CWelsLib (sWelsEncCtx* pEncCtx) {  m_pInterface[0] = m_pInterface[1] = NULL; #ifndef NO_DYNAMIC_VP#if defined(_WIN32)  const char WelsVPLib[] = "welsvp.dll";  HMODULE shModule = LoadLibrary (WelsVPLib);  if (!shModule)    WelsLog (pEncCtx, WELS_LOG_ERROR, "welsvp load lib dynamic failed module=%x\n", shModule); #elif defined(MACOS)  const char WelsVPLib[] = "welsvp.bundle";  char pCurPath[256];  GetCurrentModulePath (pCurPath, 256);  strlcat (pCurPath, WelsVPLib, 256);  CFBundleRef shModule = LoadBundle (pCurPath);  if (!shModule)    WelsLog (pEncCtx, WELS_LOG_ERROR, "welsvp load lib dynamic failed module=%x\n", shModule); #elif defined(__GNUC__)  const char WelsVPLib[] = "./libwelsvp.so";  void* shModule = NULL;  shModule = dlopen (WelsVPLib, RTLD_LAZY);  if (shModule == NULL)    printf ("dlopen %s iRet=%p, err=%s\n", WelsVPLib, shModule, dlerror());#endif   m_pVpLib = (void*)shModule;#endif} CWelsLib::~CWelsLib() {#ifndef NO_DYNAMIC_VP  if (m_pVpLib) {#if defined(_WIN32)    HMODULE shModule = (HMODULE)m_pVpLib;    FreeLibrary (shModule); #elif defined(MACOS)    CFBundleRef shModule = (CFBundleRef)m_pVpLib;    FreeBundle (shModule); #elif defined(__GNUC__)    void* shModule = m_pVpLib;    dlclose (shModule);#endif    m_pVpLib = NULL;  }#endif} void* CWelsLib::QueryFunction (const char* pName) {  void* pFunc = NULL; #ifndef NO_DYNAMIC_VP  if (m_pVpLib) {#if defined(_WIN32)    HMODULE shModule = (HMODULE)m_pVpLib;    pFunc = (void*)GetProcAddress (shModule, pName); #elif defined(MACOS)    CFBundleRef shModule = (CFBundleRef)m_pVpLib;    pFunc = (void*)GetProcessAddress (shModule, pName); #elif defined(__GNUC__)    void* shModule = m_pVpLib;    pFunc = (void*)dlsym (shModule, pName);    if (pFunc == NULL)      printf ("dlsym %p iRet=%p, err=%s\n", shModule, pFunc, dlerror());#endif  }#endif  return pFunc;} int32_t CWelsLib::CreateIface (IWelsVP** ppInterfaceVp) {  *ppInterfaceVp = NULL;#ifndef NO_DYNAMIC_VP  if (m_pVpLib) { #endif    pfnCreateVpInterface  pCreateVpInterface  = NULL;    pfnDestroyVpInterface pDestroyVpInterface = NULL; #ifndef NO_DYNAMIC_VP    pCreateVpInterface  = (pfnCreateVpInterface)  QueryFunction ("CreateVpInterface");    pDestroyVpInterface = (pfnDestroyVpInterface) QueryFunction ("DestroyVpInterface");#else    pCreateVpInterface  = CreateVpInterface;    // TODO(ekr@rtfm.com): This cast corrects a signature difference... This is a potential real problem    pDestroyVpInterface = (pfnDestroyVpInterface)DestroyVpInterface;#endif     m_pInterface[0] = (void*)pCreateVpInterface;    m_pInterface[1] = (void*)pDestroyVpInterface;     if (m_pInterface[0] && m_pInterface[1])      pCreateVpInterface ((void**)ppInterfaceVp, WELSVP_INTERFACE_VERION);#ifndef NO_DYNAMIC_VP  } else {  }#endif   return (*ppInterfaceVp) ? 0 : 1;} int32_t CWelsLib::DestroyIface (IWelsVP* pInterfaceVp) {  if (pInterfaceVp) {    pfnDestroyVpInterface pDestroyVpInterface = (pfnDestroyVpInterface) m_pInterface[1];    if (pDestroyVpInterface) {      pDestroyVpInterface (pInterfaceVp, WELSVP_INTERFACE_VERION);    } else {    }  }   return 0;} /*****************************************************************************	implement of the interface****************************************************************************/ CWelsPreProcess::CWelsPreProcess (sWelsEncCtx* pEncCtx) {  m_pInterfaceVp = NULL;  m_pEncLib = NULL;  m_bInitDone = false;  m_bOfficialBranch  = false;  m_pEncCtx = pEncCtx;  memset (&m_sScaledPicture, 0, sizeof (m_sScaledPicture));} CWelsPreProcess::~CWelsPreProcess() {  FreeScaledPic (&m_sScaledPicture,  m_pEncCtx->pMemAlign);  WelsPreprocessDestroy();} int32_t CWelsPreProcess::WelsPreprocessCreate() {  if (m_pEncLib == NULL && m_pInterfaceVp == NULL) {    m_pEncLib  = new CWelsLib (m_pEncCtx);    if (!m_pEncLib)      goto exit;     m_pEncLib->CreateIface (&m_pInterfaceVp);    if (!m_pInterfaceVp)      goto exit;  } else    goto exit;   return 0; exit:  WelsPreprocessDestroy();  return 1;} int32_t CWelsPreProcess::WelsPreprocessDestroy() {  if (m_pEncLib) {    m_pEncLib->DestroyIface (m_pInterfaceVp);    m_pInterfaceVp = NULL;    WelsSafeDelete (m_pEncLib);  }   return 0;} int32_t CWelsPreProcess::WelsPreprocessReset (sWelsEncCtx* pCtx) {  int32_t iRet = -1;   if (pCtx) {    FreeScaledPic (&m_sScaledPicture, pCtx->pMemAlign);    iRet = InitLastSpatialPictures (pCtx);    iRet = WelsInitScaledPic (pCtx->pSvcParam, &m_sScaledPicture, pCtx->pMemAlign);  }   return iRet;} int32_t CWelsPreProcess::BuildSpatialPicList (sWelsEncCtx* pCtx, const SSourcePicture** kppSrcPicList,    const int32_t kiConfiguredLayerNum) {  SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;  int32_t	iNumDependencyLayer = (int32_t)pSvcParam->iSpatialLayerNum;  int32_t iSpatialNum = 0;   if (!m_bInitDone) {    if (WelsPreprocessCreate() != 0)      return -1;    if (WelsPreprocessReset (pCtx) != 0)      return -1;     m_bOfficialBranch  = (iNumDependencyLayer != kiConfiguredLayerNum);    if (!m_bOfficialBranch && (iNumDependencyLayer == 1)) {      // check the input source uiSize to decide if need switch to official branch      // NOTICE: the layernum=1 case is confused in official/non-official cases!      SSourcePicture** pic_queue = (SSourcePicture**)kppSrcPicList;      for (int32_t i = 0; i < iNumDependencyLayer; i++) {        if (pSvcParam->sDependencyLayers[i].iFrameWidth != pic_queue[i]->iPicWidth ||            pSvcParam->sDependencyLayers[i].iFrameHeight != pic_queue[i]->iPicHeight) {          m_bOfficialBranch = true;          break;        }      }    }    m_bInitDone = true;  }   if (m_pInterfaceVp == NULL)    return -1;   if (kiConfiguredLayerNum <= 0)    return -1;   pCtx->pVaa->bSceneChangeFlag = pCtx->pVaa->bIdrPeriodFlag = false;  if (pSvcParam->uiIntraPeriod)    pCtx->pVaa->bIdrPeriodFlag = (1 + pCtx->iFrameIndex >= (int32_t)pSvcParam->uiIntraPeriod) ? true : false;   if (m_bOfficialBranch) {	// Perform Down Sampling potentially due to application    assert (kiConfiguredLayerNum == 1);    iSpatialNum	= SingleLayerPreprocess (pCtx, kppSrcPicList[0], &m_sScaledPicture);  } else { // for console each spatial pictures are available there    iSpatialNum	= kiConfiguredLayerNum;    MultiLayerPreprocess (pCtx, kppSrcPicList, iSpatialNum);  }   return iSpatialNum;} int32_t CWelsPreProcess::AnalyzeSpatialPic (sWelsEncCtx* pCtx, const int32_t kiDidx) {  SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;  bool bNeededMbAq = (pSvcParam->bEnableAdaptiveQuant && (pCtx->eSliceType == P_SLICE));  bool bCalculateBGD = (pCtx->eSliceType == P_SLICE && pSvcParam->bEnableBackgroundDetection);   int32_t iCurTemporalIdx  = pCtx->uiSpatialLayersInTemporal[kiDidx] - 1;   int32_t iRefTemporalIdx = (int32_t)g_kuiRefTemporalIdx[pSvcParam->iDecompStages][pCtx->iCodingIndex &                            (pSvcParam->uiGopSize - 1)];  if (pCtx->uiTemporalId == 0 && pCtx->pLtr[pCtx->uiDependencyId].bReceivedT0LostFlag)    iRefTemporalIdx = pCtx->uiSpatialLayersInTemporal[kiDidx] + pCtx->pVaa->uiValidLongTermPicIdx;   SPicture* pCurPic = pCtx->pSpatialPic[kiDidx][iCurTemporalIdx];  SPicture* pRefPic = pCtx->pSpatialPic[kiDidx][iRefTemporalIdx];  {    SPicture* pLastPic = m_pLastSpatialPicture[kiDidx][0];    bool bCalculateSQDiff = ((pLastPic->pData[0] == pRefPic->pData[0]) && bNeededMbAq);    bool bCalculateVar = (pSvcParam->iRCMode == RC_MODE1 && pCtx->eSliceType == I_SLICE);     VaaCalculation (pCtx->pVaa, pCurPic, pRefPic, bCalculateSQDiff, bCalculateVar, bCalculateBGD);  }   if (pSvcParam->bEnableBackgroundDetection) {    BackgroundDetection (pCtx->pVaa, pCurPic, pRefPic, bCalculateBGD && pRefPic->iPictureType != I_SLICE);  }   if (bNeededMbAq) {    SPicture* pCurPic = m_pLastSpatialPicture[kiDidx][1];    SPicture* pRefPic = m_pLastSpatialPicture[kiDidx][0];     AdaptiveQuantCalculation (pCtx->pVaa, pCurPic, pRefPic);  }   if (pSvcParam->bEnableRc) {    AnalyzePictureComplexity (pCtx, pCurPic, pRefPic, kiDidx, bCalculateBGD);  }   WelsExchangeSpatialPictures (&m_pLastSpatialPicture[kiDidx][1], &m_pLastSpatialPicture[kiDidx][0]);   return 0;}  /**	SingleLayerPreprocess: down sampling if applicable*  @return:	exact number of spatial layers need to encoder indeed*/int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSourcePicture* kpSrc,    Scaled_Picture* pScaledPicture) {  SWelsSvcCodingParam* pSvcParam    = pCtx->pSvcParam;  int8_t	iDependencyId			= pSvcParam->iSpatialLayerNum - 1;  int32_t iPicturePos	                    = pCtx->uiSpatialLayersInTemporal[iDependencyId] - 1;   SPicture* pSrcPic					= NULL;	// large  SPicture* pDstPic					= NULL;	// small  SDLayerParam* pDlayerParam					= NULL;  int32_t iSpatialNum					= 0;  int32_t iSrcWidth					= 0;  int32_t iSrcHeight					= 0;  int32_t iTargetWidth					= 0;  int32_t iTargetHeight					= 0;  int32_t iTemporalId = 0;  int32_t iActualSpatialLayerNum      = 0;   pDlayerParam = &pSvcParam->sDependencyLayers[iDependencyId];  iTargetWidth	  = pDlayerParam->iFrameWidth;  iTargetHeight  = pDlayerParam->iFrameHeight;  iTemporalId    = pDlayerParam->uiCodingIdx2TemporalId[pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1)];  iSrcWidth   = pSvcParam->SUsedPicRect.iWidth;  iSrcHeight  = pSvcParam->SUsedPicRect.iHeight;   pSrcPic = pScaledPicture->pScaledInputPicture ? pScaledPicture->pScaledInputPicture :            pCtx->pSpatialPic[iDependencyId][iPicturePos];   WelsMoveMemoryWrapper (pSvcParam, pSrcPic, kpSrc, iSrcWidth, iSrcHeight);   if (pSvcParam->bEnableDenoise)    BilateralDenoising (pSrcPic, iSrcWidth, iSrcHeight);   // different scaling in between input picture and dst highest spatial picture.  int32_t iShrinkWidth  = iSrcWidth;  int32_t iShrinkHeight = iSrcHeight;  pDstPic = pSrcPic;  if (pScaledPicture->pScaledInputPicture) {    // for highest downsampling    pDstPic		= pCtx->pSpatialPic[iDependencyId][iPicturePos];    iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId];    iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId];  }  DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight);   if (pSvcParam->bEnableSceneChangeDetect && !pCtx->pVaa->bIdrPeriodFlag      && !pCtx->bEncCurFrmAsIdrFlag      && ! (pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1))) {    SPicture* pRefPic = pCtx->pLtr[iDependencyId].bReceivedT0LostFlag ?                        pCtx->pSpatialPic[iDependencyId][pCtx->uiSpatialLayersInTemporal[iDependencyId] +                            pCtx->pVaa->uiValidLongTermPicIdx] : m_pLastSpatialPicture[iDependencyId][0];     pCtx->pVaa->bSceneChangeFlag = DetectSceneChange (pDstPic, pRefPic);  }   for (int32_t i = 0; i < pSvcParam->iSpatialLayerNum; i++) {    if (pSvcParam->sDependencyLayers[i].uiCodingIdx2TemporalId[pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1)]        != INVALID_TEMPORAL_ID) {      ++ iActualSpatialLayerNum;    }  }   if (iTemporalId != INVALID_TEMPORAL_ID) {    WelsUpdateSpatialIdxMap (pCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId);    ++ iSpatialNum;    -- iActualSpatialLayerNum;  }   m_pLastSpatialPicture[iDependencyId][1]	= pCtx->pSpatialPic[iDependencyId][iPicturePos];  -- iDependencyId;   // generate other spacial layer  // pSrc is  //	-- padded input pic, if downsample should be applied to generate highest layer, [if] block above  //	-- highest layer, if no downsampling, [else] block above  if (pSvcParam->iSpatialLayerNum > 1) {    while (iDependencyId >= 0) {      pDlayerParam			= &pSvcParam->sDependencyLayers[iDependencyId];      iTargetWidth	= pDlayerParam->iFrameWidth;      iTargetHeight	= pDlayerParam->iFrameHeight;      iTemporalId = pDlayerParam->uiCodingIdx2TemporalId[pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1)];      iPicturePos		= pCtx->uiSpatialLayersInTemporal[iDependencyId] - 1;       // NOT work for CGS, FIXME      // spatial layer is able to encode indeed      if ((iTemporalId != INVALID_TEMPORAL_ID)) {        // down sampling performed         pDstPic	= pCtx->pSpatialPic[iDependencyId][iPicturePos];	// small        iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId];        iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId];        DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight);         WelsUpdateSpatialIdxMap (pCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId);         -- iActualSpatialLayerNum;        ++ iSpatialNum;         m_pLastSpatialPicture[iDependencyId][1]	= pCtx->pSpatialPic[iDependencyId][iPicturePos];      }      -- iDependencyId;    }  }   return iSpatialNum;} int32_t CWelsPreProcess::MultiLayerPreprocess (sWelsEncCtx* pCtx, const SSourcePicture** kppSrcPicList,    const int32_t kiSpatialNum) {  SWelsSvcCodingParam* pSvcParam	= pCtx->pSvcParam;  const SSourcePicture* pSrc			= NULL;  SPicture* pDstPic						= NULL;  const int32_t iSpatialLayersCfgCount =    pSvcParam->iSpatialLayerNum;	// count number of spatial layers to be encoded in cfg  int32_t i							= 0;  int32_t j							= -1;   do {    pSrc	= kppSrcPicList[i];     // do not clear j, just let it continue to save complexity    do {      ++ j;      if (pSvcParam->sDependencyLayers[j].iFrameWidth == pSrc->iPicWidth &&          pSvcParam->sDependencyLayers[j].iFrameHeight == pSrc->iPicHeight) {        break;      }    } while (j < iSpatialLayersCfgCount);     assert (j < iSpatialLayersCfgCount);    pDstPic = pCtx->pSpatialPic[j][pCtx->uiSpatialLayersInTemporal[j] - 1];     WelsUpdateSpatialIdxMap (pCtx, i, pDstPic, j);     WelsMoveMemoryWrapper (pSvcParam, pDstPic, pSrc, pSrc->iPicWidth, pSrc->iPicHeight);     if (pSvcParam->bEnableDenoise)      BilateralDenoising (pDstPic, pSrc->iPicWidth, pSrc->iPicHeight);     m_pLastSpatialPicture[j][1]	= pDstPic;    ++ i;  } while (i < kiSpatialNum); 

Lines 1–500 of 1019.

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