1248 lines · 47.3 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. * * * \file    decoder.c * * \brief   Interfaces implementation introduced in decoder system architecture * * \date    03/10/2009 Created * ************************************************************************************* */#include "codec_def.h"#include "decoder.h"#include "cpu.h"#include "au_parser.h"#include "get_intra_predictor.h"#include "rec_mb.h"#include "mc.h"#include "decode_mb_aux.h"#include "manage_dec_ref.h"#include "decoder_core.h"#include "deblocking.h"#include "expand_pic.h"#include "decode_slice.h"#include "error_concealment.h"#include "memory_align.h"#include "wels_decoder_thread.h" namespace WelsDec { extern PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const int32_t kiPicHeight); extern void FreePicture (PPicture pPic, CMemoryAlign* pMa); static int32_t CreatePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiSize,                              const int32_t kiPicWidth, const int32_t kiPicHeight) {   PPicBuff pPicBuf = NULL;  int32_t iPicIdx = 0;  if (kiSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {    return ERR_INFO_INVALID_PARAM;  }   CMemoryAlign* pMa = pCtx->pMemAlign;   pPicBuf = (PPicBuff)pMa->WelsMallocz (sizeof (SPicBuff), "PPicBuff");   if (NULL == pPicBuf) {    return ERR_INFO_OUT_OF_MEMORY;  }   pPicBuf->ppPic = (PPicture*)pMa->WelsMallocz (kiSize * sizeof (PPicture), "PPicture*");   if (NULL == pPicBuf->ppPic) {    pPicBuf->iCapacity = 0;    DestroyPicBuff (pCtx, &pPicBuf, pMa);    return ERR_INFO_OUT_OF_MEMORY;  }   for (iPicIdx = 0; iPicIdx < kiSize; ++ iPicIdx) {    PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);    if (NULL == pPic) {      // init capacity first for free memory      pPicBuf->iCapacity = iPicIdx;      DestroyPicBuff (pCtx, &pPicBuf, pMa);      return ERR_INFO_OUT_OF_MEMORY;    }    pPicBuf->ppPic[iPicIdx] = pPic;  } // initialize context in queue  pPicBuf->iCapacity   = kiSize;  pPicBuf->iCurrentIdx = 0;  * ppPicBuf           = pPicBuf;   return ERR_NONE;} static int32_t IncreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,                                const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {  PPicBuff pPicOldBuf = *ppPicBuf;  PPicBuff pPicNewBuf = NULL;  int32_t iPicIdx = 0;  if (kiOldSize <= 0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {    return ERR_INFO_INVALID_PARAM;  }   CMemoryAlign* pMa = pCtx->pMemAlign;  pPicNewBuf = (PPicBuff)pMa->WelsMallocz (sizeof (SPicBuff), "PPicBuff");   if (NULL == pPicNewBuf) {    return ERR_INFO_OUT_OF_MEMORY;  }   pPicNewBuf->ppPic = (PPicture*)pMa->WelsMallocz (kiNewSize * sizeof (PPicture), "PPicture*");   if (NULL == pPicNewBuf->ppPic) {    pPicNewBuf->iCapacity = 0;    DestroyPicBuff (pCtx, &pPicNewBuf, pMa);    return ERR_INFO_OUT_OF_MEMORY;  }   // increase new PicBuf  for (iPicIdx = kiOldSize; iPicIdx < kiNewSize; ++ iPicIdx) {    PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);    if (NULL == pPic) {      // Set maximum capacity as the new malloc memory at the tail      pPicNewBuf->iCapacity = iPicIdx;      DestroyPicBuff (pCtx, &pPicNewBuf, pMa);      return ERR_INFO_OUT_OF_MEMORY;    }    pPicNewBuf->ppPic[iPicIdx] = pPic;  }   // copy old PicBuf to new PicBuf  memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiOldSize * sizeof (PPicture)); // initialize context in queue  pPicNewBuf->iCapacity   = kiNewSize;  pPicNewBuf->iCurrentIdx = pPicOldBuf->iCurrentIdx;  * ppPicBuf              = pPicNewBuf;   for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {    pPicNewBuf->ppPic[i]->bUsedAsRef = false;    pPicNewBuf->ppPic[i]->bIsLongRef = false;    pPicNewBuf->ppPic[i]->iRefCount = 0;    pPicNewBuf->ppPic[i]->bIsComplete = false;  }// remove old PicBuf  if (pPicOldBuf->ppPic != NULL) {    pMa->WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");    pPicOldBuf->ppPic = NULL;  }  pPicOldBuf->iCapacity = 0;  pPicOldBuf->iCurrentIdx = 0;  pMa->WelsFree (pPicOldBuf, "pPicOldBuf");  pPicOldBuf = NULL;  return ERR_NONE;} static int32_t DecreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,                                const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {  PPicBuff pPicOldBuf = *ppPicBuf;  PPicBuff pPicNewBuf = NULL;  int32_t iPicIdx = 0;  if (kiOldSize <= 0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {    return ERR_INFO_INVALID_PARAM;  }   CMemoryAlign* pMa = pCtx->pMemAlign;   pPicNewBuf = (PPicBuff)pMa->WelsMallocz (sizeof (SPicBuff), "PPicBuff");   if (NULL == pPicNewBuf) {    return ERR_INFO_OUT_OF_MEMORY;  }   pPicNewBuf->ppPic = (PPicture*)pMa->WelsMallocz (kiNewSize * sizeof (PPicture), "PPicture*");   if (NULL == pPicNewBuf->ppPic) {    pPicNewBuf->iCapacity = 0;    DestroyPicBuff (pCtx, &pPicNewBuf, pMa);    return ERR_INFO_OUT_OF_MEMORY;  }   ResetReorderingPictureBuffers (pCtx->pPictReoderingStatus, pCtx->pPictInfoList, false);   int32_t iPrevPicIdx = -1;  for (iPrevPicIdx = 0; iPrevPicIdx < kiOldSize; ++iPrevPicIdx) {    if (pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb == pPicOldBuf->ppPic[iPrevPicIdx]) {      break;    }  }  int32_t iDelIdx;  if (iPrevPicIdx < kiOldSize && iPrevPicIdx >= kiNewSize) {    // found pPreviousDecodedPictureInDpb,    pPicNewBuf->ppPic[0] = pPicOldBuf->ppPic[iPrevPicIdx];    pPicNewBuf->iCurrentIdx = 0;    memcpy (pPicNewBuf->ppPic + 1, pPicOldBuf->ppPic, (kiNewSize - 1) * sizeof (PPicture));    iDelIdx = kiNewSize - 1;  } else {    memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiNewSize * sizeof (PPicture));    pPicNewBuf->iCurrentIdx = iPrevPicIdx < kiNewSize ? iPrevPicIdx : 0;    iDelIdx = kiNewSize;  }   //update references due to allocation changes  //all references' references have to be reset oss-buzz 14423  for (int32_t i = 0; i < kiNewSize; i++) {    for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {      int32_t j = -1;      while (++j < MAX_DPB_COUNT && pPicNewBuf->ppPic[i]->pRefPic[listIdx][j] != NULL) {        pPicNewBuf->ppPic[i]->pRefPic[listIdx][j] = NULL;      }    }  }   for (iPicIdx = iDelIdx; iPicIdx < kiOldSize; iPicIdx++) {    if (iPrevPicIdx != iPicIdx) {      if (pPicOldBuf->ppPic[iPicIdx] != NULL) {        FreePicture (pPicOldBuf->ppPic[iPicIdx], pMa);        pPicOldBuf->ppPic[iPicIdx] = NULL;      }    }  }   // initialize context in queue  pPicNewBuf->iCapacity = kiNewSize;  * ppPicBuf             = pPicNewBuf;   for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {    pPicNewBuf->ppPic[i]->bUsedAsRef = false;    pPicNewBuf->ppPic[i]->bIsLongRef = false;    pPicNewBuf->ppPic[i]->iRefCount = 0;    pPicNewBuf->ppPic[i]->bIsComplete = false;  }  // remove old PicBuf  if (pPicOldBuf->ppPic != NULL) {    pMa->WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");    pPicOldBuf->ppPic = NULL;  }  pPicOldBuf->iCapacity = 0;  pPicOldBuf->iCurrentIdx = 0;  pMa->WelsFree (pPicOldBuf, "pPicOldBuf");  pPicOldBuf = NULL;   return ERR_NONE;} void DestroyPicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, CMemoryAlign* pMa) {  PPicBuff pPicBuf = NULL;   ResetReorderingPictureBuffers (pCtx->pPictReoderingStatus, pCtx->pPictInfoList, false);   if (NULL == ppPicBuf || NULL == *ppPicBuf)    return;   pPicBuf = *ppPicBuf;  while (pPicBuf->ppPic != NULL) {    int32_t iPicIdx = 0;    while (iPicIdx < pPicBuf->iCapacity) {      PPicture pPic = pPicBuf->ppPic[iPicIdx];      if (pPic != NULL) {        FreePicture (pPic, pMa);      }      pPic = NULL;      ++ iPicIdx;    }     pMa->WelsFree (pPicBuf->ppPic, "pPicBuf->queue");     pPicBuf->ppPic = NULL;  }  pPicBuf->iCapacity = 0;  pPicBuf->iCurrentIdx = 0;   pMa->WelsFree (pPicBuf, "pPicBuf");   pPicBuf = NULL;  *ppPicBuf = NULL;} //reset picture reodering buffer listvoid ResetReorderingPictureBuffers (PPictReoderingStatus pPictReoderingStatus, PPictInfo pPictInfo,                                    const bool& fullReset) {  if (pPictReoderingStatus != NULL && pPictInfo != NULL) {    int32_t pictInfoListCount = fullReset ? 16 : (pPictReoderingStatus->iLargestBufferedPicIndex + 1);    pPictReoderingStatus->iPictInfoIndex = 0;    pPictReoderingStatus->iMinPOC = IMinInt32;    pPictReoderingStatus->iNumOfPicts = 0;    pPictReoderingStatus->iLastGOPRemainPicts = 0;    pPictReoderingStatus->iLastWrittenPOC = IMinInt32;    pPictReoderingStatus->iLargestBufferedPicIndex = 0;    for (int32_t i = 0; i < pictInfoListCount; ++i) {      pPictInfo[i].bLastGOP = false;      pPictInfo[i].iPOC = IMinInt32;    }  }} /* * fill data fields in default for decoder context */void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {  int32_t iCpuCores               = 1;  pCtx->sLogCtx = *pLogCtx;   pCtx->pArgDec                   = NULL;   pCtx->bHaveGotMemory            = false;              // not ever request memory blocks for decoder context related  pCtx->uiCpuFlag                 = 0;   pCtx->bAuReadyFlag              = 0;                  // au data is not ready  pCtx->bCabacInited = false;   pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);   pCtx->iImgWidthInPixel          = 0;  pCtx->iImgHeightInPixel         = 0;                  // alloc picture data when picture size is available  pCtx->iLastImgWidthInPixel      = 0;  pCtx->iLastImgHeightInPixel     = 0;  pCtx->bFreezeOutput = true;   pCtx->iFrameNum                 = -1;  pCtx->pLastDecPicInfo->iPrevFrameNum             = -1;  pCtx->iErrorCode                = ERR_NONE;   pCtx->pDec                      = NULL;   pCtx->pTempDec                  = NULL;   WelsResetRefPic (pCtx);   pCtx->iActiveFmoNum             = 0;   pCtx->pPicBuff          = NULL;   //pCtx->sSpsPpsCtx.bAvcBasedFlag             = true;  pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb = NULL;  pCtx->pDecoderStatistics->iAvgLumaQp = -1;  pCtx->pDecoderStatistics->iStatisticsLogInterval = 1000;  pCtx->bUseScalingList = false;  /*pCtx->sSpsPpsCtx.iSpsErrorIgnored = 0;  pCtx->sSpsPpsCtx.iSubSpsErrorIgnored = 0;  pCtx->sSpsPpsCtx.iPpsErrorIgnored = 0;  pCtx->sSpsPpsCtx.iPPSInvalidNum = 0;  pCtx->sSpsPpsCtx.iPPSLastInvalidId = -1;  pCtx->sSpsPpsCtx.iSPSInvalidNum = 0;  pCtx->sSpsPpsCtx.iSPSLastInvalidId = -1;  pCtx->sSpsPpsCtx.iSubSPSInvalidNum = 0;  pCtx->sSpsPpsCtx.iSubSPSLastInvalidId = -1;  */  pCtx->iFeedbackNalRefIdc = -1; //initialize  pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb = 0;  pCtx->pLastDecPicInfo->iPrevPicOrderCntLsb = 0; } /** fill data fields in SPS and PPS default for decoder context*/void WelsDecoderSpsPpsDefaults (SWelsDecoderSpsPpsCTX& sSpsPpsCtx) {  sSpsPpsCtx.bSpsExistAheadFlag = false;  sSpsPpsCtx.bSubspsExistAheadFlag = false;  sSpsPpsCtx.bPpsExistAheadFlag = false;  sSpsPpsCtx.bAvcBasedFlag = true;  sSpsPpsCtx.iSpsErrorIgnored = 0;  sSpsPpsCtx.iSubSpsErrorIgnored = 0;  sSpsPpsCtx.iPpsErrorIgnored = 0;  sSpsPpsCtx.iPPSInvalidNum = 0;  sSpsPpsCtx.iPPSLastInvalidId = -1;  sSpsPpsCtx.iSPSInvalidNum = 0;  sSpsPpsCtx.iSPSLastInvalidId = -1;  sSpsPpsCtx.iSubSPSInvalidNum = 0;  sSpsPpsCtx.iSubSPSLastInvalidId = -1;  sSpsPpsCtx.iSeqId = -1;} /** fill last decoded picture info*/void WelsDecoderLastDecPicInfoDefaults (SWelsLastDecPicInfo& sLastDecPicInfo) {  sLastDecPicInfo.iPrevPicOrderCntMsb = 0;  sLastDecPicInfo.iPrevPicOrderCntLsb = 0;  sLastDecPicInfo.pPreviousDecodedPictureInDpb = NULL;  sLastDecPicInfo.iPrevFrameNum = -1;  sLastDecPicInfo.bLastHasMmco5 = false;  sLastDecPicInfo.uiDecodingTimeStamp = 0;} /*!* \brief   copy SpsPps from one Ctx to another ctx for threaded code*/void CopySpsPps (PWelsDecoderContext pFromCtx, PWelsDecoderContext pToCtx) {  pToCtx->sSpsPpsCtx = pFromCtx->sSpsPpsCtx;  PAccessUnit pFromCurAu = pFromCtx->pAccessUnitList;  PSps pTmpLayerSps[MAX_LAYER_NUM];  for (int i = 0; i < MAX_LAYER_NUM; i++) {    pTmpLayerSps[i] = NULL;  }  // track the layer sps for the current au  for (unsigned int i = pFromCurAu->uiStartPos; i <= pFromCurAu->uiEndPos; i++) {    uint32_t uiDid = pFromCurAu->pNalUnitsList[i]->sNalHeaderExt.uiDependencyId;    pTmpLayerSps[uiDid] = pFromCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;    for (unsigned int j = 0; j < MAX_SPS_COUNT + 1; ++j) {      if (&pFromCtx->sSpsPpsCtx.sSpsBuffer[j] == pTmpLayerSps[uiDid]) {        pTmpLayerSps[uiDid] = &pToCtx->sSpsPpsCtx.sSpsBuffer[j];        break;      }    }  }  for (int i = 0; i < MAX_LAYER_NUM; i++) {    if (pTmpLayerSps[i] != NULL) {      pToCtx->sSpsPpsCtx.pActiveLayerSps[i] = pTmpLayerSps[i];    }  }} /* *  destory_mb_blocks */ /* *  get size of reference picture list in target layer incoming, = (iNumRefFrames */static inline int32_t GetTargetRefListSize (PWelsDecoderContext pCtx) {  int32_t iNumRefFrames = 0;  // +2 for EC MV Copy buffer exchange  if ((pCtx == NULL) || (pCtx->pSps == NULL)) {    iNumRefFrames = MAX_REF_PIC_COUNT + 2;  } else {    iNumRefFrames = pCtx->pSps->iNumRefFrames + 2;    int32_t  iThreadCount = GetThreadCount (pCtx);    if (iThreadCount > 1) {      iNumRefFrames = MAX_REF_PIC_COUNT;    }  } #ifdef LONG_TERM_REF  //pic_queue size minimum set 2  if (iNumRefFrames < 2) {    iNumRefFrames = 2;  }#endif   return iNumRefFrames;} /* *  request memory blocks for decoder avc part */int32_t WelsRequestMem (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight,                        bool& bReallocFlag) {  const int32_t kiPicWidth      = kiMbWidth << 4;  const int32_t kiPicHeight     = kiMbHeight << 4;  int32_t iErr = ERR_NONE;   int32_t iPicQueueSize         = 0;    // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)  bReallocFlag                  = false;  bool  bNeedChangePicQueue     = true;  CMemoryAlign* pMa = pCtx->pMemAlign;   WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiPicWidth <= 0 || kiPicHeight <= 0))   // Fixed the issue about different gop size over last, 5/17/2010  // get picture queue size currently  iPicQueueSize = GetTargetRefListSize (pCtx);  // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)  pCtx->iPicQueueNumber = iPicQueueSize;  if (pCtx->pPicBuff != NULL      && pCtx->pPicBuff->iCapacity ==      iPicQueueSize) // comparing current picture queue size requested and previous allocation picture queue    bNeedChangePicQueue = false;  // HD based pic buffer need consider memory size consumed when switch from 720p to other lower size  WELS_VERIFY_RETURN_IF (ERR_NONE, pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel                         && kiPicHeight == pCtx->iImgHeightInPixel) && (!bNeedChangePicQueue)) // have same scaled buffer   // sync update pRefList  if (GetThreadCount (pCtx) <= 1) {    WelsResetRefPic (pCtx); // added to sync update ref list due to pictures are free  }   if (pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel && kiPicHeight == pCtx->iImgHeightInPixel)      && pCtx->pPicBuff != NULL && pCtx->pPicBuff->iCapacity != iPicQueueSize) {    // currently only active for LIST_0 due to have no B frames    // Actually just need one memory allocation for the PicBuff. While it needs two pointer list (LIST_0 and LIST_1).    WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,             "WelsRequestMem(): memory re-alloc for no resolution change (size = %d * %d), ref list size change from %d to %d",             kiPicWidth, kiPicHeight, pCtx->pPicBuff->iCapacity, iPicQueueSize);    if (pCtx->pPicBuff->iCapacity < iPicQueueSize) {      iErr = IncreasePicBuff (pCtx, &pCtx->pPicBuff, pCtx->pPicBuff->iCapacity, kiPicWidth, kiPicHeight,                              iPicQueueSize);    } else {

Lines 1–500 of 1248.

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