2772 lines · 123.2 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.
 *
 *      decoder_core.c: Wels decoder framework core implementation
 */

#include "decoder_core.h"
#include "error_code.h"
#include "memmgr_nal_unit.h"
#include "au_parser.h"
#include "decode_slice.h"
#include "manage_dec_ref.h"
#include "expand_pic.h"
#include "decoder.h"
#include "decode_mb_aux.h"
#include "memory_align.h"
#include "error_concealment.h"

namespace WelsDec {
static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) {
  PDqLayer pCurDq = pCtx->pCurDqLayer;
  PPicture pPic = pCtx->pDec;

  const int32_t kiWidth = pCurDq->iMbWidth << 4;
  const int32_t kiHeight = pCurDq->iMbHeight << 4;

  const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight;
  bool bFrameCompleteFlag = true;

  if (pPic->bNewSeqBegin) {
    memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop),
            sizeof (SPosOffset)); //confirmed_safe_unsafe_usage
#ifdef LONG_TERM_REF
    pCtx->bParamSetsLostFlag      = false;
#else
    pCtx->bReferenceLostAtT0Flag = false; // need initialize it due new seq, 6/4/2010
#endif //LONG_TERM_REF
    if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) {
      pCtx->bPrintFrameErrorTraceFlag = true;
      WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
               "DecodeFrameConstruction(): will output first frame of new sequence, %d x %d, crop_left:%d, crop_right:%d, crop_top:%d, crop_bottom:%d, ignored error packet:%d.",
               kiWidth, kiHeight, pCtx->sFrameCrop.iLeftOffset, pCtx->sFrameCrop.iRightOffset, pCtx->sFrameCrop.iTopOffset,
               pCtx->sFrameCrop.iBottomOffset, pCtx->iIgnoredErrorInfoPacketCount);
      pCtx->iIgnoredErrorInfoPacketCount = 0;
    }
  }

  const int32_t kiActualWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2;
  const int32_t kiActualHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2;


  if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
    if ((pCtx->sDecoderStatistics.uiWidth != (unsigned int) kiActualWidth)
        || (pCtx->sDecoderStatistics.uiHeight != (unsigned int) kiActualHeight)) {
      pCtx->sDecoderStatistics.uiResolutionChangeTimes++;
      pCtx->sDecoderStatistics.uiWidth = kiActualWidth;
      pCtx->sDecoderStatistics.uiHeight = kiActualHeight;
    }
    UpdateDecStatNoFreezingInfo (pCtx);
  }

  if (pCtx->pParam->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo
    PAccessUnit pCurAu = pCtx->pAccessUnitList;
    if (dsErrorFree == pCtx->iErrorCode) { //correct decoding, add to data buffer
      SParserBsInfo* pParser = pCtx->pParserBsInfo;
      SNalUnit* pCurNal = NULL;
      int32_t iTotalNalLen = 0;
      int32_t iNalLen = 0;
      int32_t iNum = 0;
      while (iNum < pParser->iNalNum) {
        iTotalNalLen += pParser->pNalLenInByte[iNum++];
      }
      uint8_t* pDstBuf = pParser->pDstBuff + iTotalNalLen;
      int32_t iIdx = pCurAu->uiStartPos;
      int32_t iEndIdx = pCurAu->uiEndPos;
      uint8_t* pNalBs = NULL;
      pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0;
      //pParser->iNalNum = 0;
      pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4) - ((pCtx->pSps->sFrameCrop.iLeftOffset +
                                  pCtx->pSps->sFrameCrop.iRightOffset) << 1);
      pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4) - ((pCtx->pSps->sFrameCrop.iTopOffset +
                                   pCtx->pSps->sFrameCrop.iBottomOffset) << 1);

      if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR
        if (pCtx->bFrameFinish) { //add required sps/pps
          if (pParser->iNalNum > pCtx->iMaxNalNum - 2) { //2 reserved for sps+pps
            WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
                     "DecodeFrameConstruction(): current NAL num (%d) plus sps & pps exceeds permitted num (%d). Will expand",
                     pParser->iNalNum, pCtx->iMaxNalNum);
            WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + 2))
          }
          bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType);
          SSpsBsInfo* pSpsBs = NULL;
          SPpsBsInfo* pPpsBs = NULL;
          int32_t iSpsId = pCtx->pSps->iSpsId;
          int32_t iPpsId = pCtx->pPps->iPpsId;
          pCtx->bParamSetsLostFlag = false;
          //find required sps, pps and write into dst buff
          pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId];
          pPpsBs = &pCtx->sPpsBsInfo [iPpsId];
          if (pDstBuf - pParser->pDstBuff + pSpsBs->uiSpsBsLen + pPpsBs->uiPpsBsLen >= MAX_ACCESS_UNIT_CAPACITY) {
            WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
                     "DecodeFrameConstruction(): sps pps size: (%d %d) too large. Failed to parse. \n", pSpsBs->uiSpsBsLen,
                     pPpsBs->uiPpsBsLen);
            pCtx->iErrorCode |= dsOutOfMemory;
            pCtx->pParserBsInfo->iNalNum = 0;
            return ERR_INFO_OUT_OF_MEMORY;
          }
          memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen);
          pParser->pNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen;
          pDstBuf += pSpsBs->uiSpsBsLen;
          memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen);
          pParser->pNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen;
          pDstBuf += pPpsBs->uiPpsBsLen;
          pCtx->bFrameFinish = false;
        }
      }
      //then VCL data re-write
      if (pParser->iNalNum + iEndIdx - iIdx + 1 > pCtx->iMaxNalNum) { //calculate total NAL num
        WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
                 "DecodeFrameConstruction(): current NAL num (%d) exceeds permitted num (%d). Will expand",
                 pParser->iNalNum + iEndIdx - iIdx + 1, pCtx->iMaxNalNum);
        WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, ExpandBsLenBuffer (pCtx, pParser->iNalNum + iEndIdx - iIdx + 1))
      }
      while (iIdx <= iEndIdx) {
        pCurNal = pCurAu->pNalUnitsList [iIdx ++];
        iNalLen = pCurNal->sNalData.sVclNal.iNalLength;
        pNalBs = pCurNal->sNalData.sVclNal.pNalPos;
        pParser->pNalLenInByte [pParser->iNalNum ++] = iNalLen;
        if (pDstBuf - pParser->pDstBuff + iNalLen >= MAX_ACCESS_UNIT_CAPACITY) {
          WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
                   "DecodeFrameConstruction(): composed output size (%ld) exceeds (%d). Failed to parse. current data pos %d out of %d:, previously accumulated num: %d, total num: %d, previously accumulated len: %d, current len: %d, current buf pos: %p, header buf pos: %p \n",
                   (long) (pDstBuf - pParser->pDstBuff + iNalLen), MAX_ACCESS_UNIT_CAPACITY, iIdx, iEndIdx, iNum, pParser->iNalNum,
                   iTotalNalLen, iNalLen, pDstBuf, pParser->pDstBuff);
          pCtx->iErrorCode |= dsOutOfMemory;
          pCtx->pParserBsInfo->iNalNum = 0;
          return ERR_INFO_OUT_OF_MEMORY;
        }

        memcpy (pDstBuf, pNalBs, iNalLen);
        pDstBuf += iNalLen;
      }
      if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { //frame complete
        pCtx->iTotalNumMbRec = 0;
        pCtx->bFramePending = false;
        pCtx->bFrameFinish = true; //finish current frame and mark it
      } else if (pCtx->iTotalNumMbRec != 0) { //frame incomplete
        pCtx->bFramePending = true;
        pCtx->pDec->bIsComplete = false;
        pCtx->bFrameFinish = false; //current frame not finished
        pCtx->iErrorCode |= dsFramePending;
        return ERR_INFO_PARSEONLY_PENDING;
        //pCtx->pParserBsInfo->iNalNum = 0;
      }
    } else { //error
      pCtx->pParserBsInfo->uiOutBsTimeStamp = 0;
      pCtx->pParserBsInfo->iNalNum = 0;
      pCtx->pParserBsInfo->iSpsWidthInPixel = 0;
      pCtx->pParserBsInfo->iSpsHeightInPixel = 0;
      return ERR_INFO_PARSEONLY_ERROR;
    }
    return ERR_NONE;
  }

  if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) {
    WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
             "DecodeFrameConstruction(): iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ",
             pCtx->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight);
    bFrameCompleteFlag = false; //return later after output buffer is done
    if (pCtx->bInstantDecFlag) //no-delay decoding, wait for new slice
      return ERR_INFO_MB_NUM_INADEQUATE;
  } else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag
             && (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done
    pCtx->pDec->bIsComplete = true;
    pCtx->bFreezeOutput = false;
  }

  pCtx->iTotalNumMbRec = 0;

  //////output:::normal path
  pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp;
  ppDst[0]      = pPic->pData[0];
  ppDst[1]      = pPic->pData[1];
  ppDst[2]      = pPic->pData[2];

  pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;

  pDstInfo->UsrData.sSystemBuffer.iWidth = kiActualWidth;
  pDstInfo->UsrData.sSystemBuffer.iHeight = kiActualHeight;
  pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
  pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
  ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2;
  ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset  * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
  ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset  * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
  pDstInfo->iBufferStatus = 1;

  bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth)
                       || (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight);
  pCtx->iLastImgWidthInPixel = pDstInfo->UsrData.sSystemBuffer.iWidth;
  pCtx->iLastImgHeightInPixel = pDstInfo->UsrData.sSystemBuffer.iHeight;
  if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete
    pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag
                                         && pPic->bIsComplete); // When EC disable, ECed picture not output
  else if ((pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE
            || pCtx->pParam->eEcActiveIdc == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
           && pCtx->iErrorCode && bOutResChange)
    pCtx->bFreezeOutput = true;

  if (pDstInfo->iBufferStatus == 0) {
    if (!bFrameCompleteFlag)
      pCtx->iErrorCode |= dsBitstreamError;
    return ERR_INFO_MB_NUM_INADEQUATE;
  }
  if (pCtx->bFreezeOutput) {
    pDstInfo->iBufferStatus = 0;
    if (pPic->bNewSeqBegin) {
      WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
               "DecodeFrameConstruction():New sequence detected, but freezed, correct MBs (%d) out of whole MBs (%d).",
               kiTotalNumMbInCurLayer - pCtx->iMbEcedNum, kiTotalNumMbInCurLayer);
    }
  }
  pCtx->iMbEcedNum = pPic->iMbEcedNum;
  pCtx->iMbNum = pPic->iMbNum;
  pCtx->iMbEcedPropNum = pPic->iMbEcedPropNum;
  if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
    if (pDstInfo->iBufferStatus && ((pCtx->sDecoderStatistics.uiWidth != (unsigned int) kiActualWidth)
                                    || (pCtx->sDecoderStatistics.uiHeight != (unsigned int) kiActualHeight))) {
      pCtx->sDecoderStatistics.uiResolutionChangeTimes++;
      pCtx->sDecoderStatistics.uiWidth = kiActualWidth;
      pCtx->sDecoderStatistics.uiHeight = kiActualHeight;
    }
    UpdateDecStat (pCtx, pDstInfo->iBufferStatus != 0);
  }
  return ERR_NONE;
}

inline bool    CheckSliceNeedReconstruct (uint8_t uiLayerDqId, uint8_t uiTargetDqId) {
  return (uiLayerDqId == uiTargetDqId); // target layer
}

inline uint8_t GetTargetDqId (uint8_t uiTargetDqId,  SDecodingParam* psParam) {
  uint8_t  uiRequiredDqId = psParam ? psParam->uiTargetDqLayer : (uint8_t)255;

  return WELS_MIN (uiTargetDqId, uiRequiredDqId);
}


inline void    HandleReferenceLostL0 (PWelsDecoderContext pCtx, PNalUnit pCurNal) {
  if (0 == pCurNal->sNalHeaderExt.uiTemporalId) {
    pCtx->bReferenceLostAtT0Flag = true;
  }
  pCtx->iErrorCode |= dsBitstreamError;
}

inline void    HandleReferenceLost (PWelsDecoderContext pCtx, PNalUnit pCurNal) {
  if ((0 == pCurNal->sNalHeaderExt.uiTemporalId) || (1 == pCurNal->sNalHeaderExt.uiTemporalId)) {
    pCtx->bReferenceLostAtT0Flag = true;
  }
  pCtx->iErrorCode |= dsRefLost;
}

inline int32_t  WelsDecodeConstructSlice (PWelsDecoderContext pCtx, PNalUnit pCurNal) {
  int32_t  iRet = WelsTargetSliceConstruction (pCtx);

  if (iRet) {
    HandleReferenceLostL0 (pCtx, pCurNal);
  }

  return iRet;
}

int32_t ParsePredWeightedTable (PBitStringAux pBs, PSliceHeader pSh) {
  uint32_t uiCode;
  int32_t iList = 0;
  int32_t iCode;

  WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
  WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "luma_log2_weight_denom",
                                  GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_LOG2_WEIGHT_DENOM));
  pSh->sPredWeightTable.uiLumaLog2WeightDenom = uiCode;
  if (pSh->pSps->uiChromaArrayType != 0) {
    WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
    WELS_CHECK_SE_BOTH_ERROR_NOLOG (uiCode, 0, 7, "chroma_log2_weight_denom",
                                    GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_LOG2_WEIGHT_DENOM));
    pSh->sPredWeightTable.uiChromaLog2WeightDenom = uiCode;
  }

  if ((pSh->sPredWeightTable.uiLumaLog2WeightDenom | pSh->sPredWeightTable.uiChromaLog2WeightDenom) > 7)
    return ERR_NONE;

  do {

    for (int i = 0; i < pSh->uiRefCount[iList]; i++) {
      //luma
      WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
      if (!!uiCode) {

        WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
        WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_weight",
                                        GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_WEIGHT));
        pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = iCode;

        WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
        WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "luma_offset",
                                        GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_LUMA_OFFSET));
        pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = iCode;
      } else {
        pSh->sPredWeightTable.sPredList[iList].iLumaWeight[i] = 1 << (pSh->sPredWeightTable.uiLumaLog2WeightDenom);
        pSh->sPredWeightTable.sPredList[iList].iLumaOffset[i] = 0;

      }
      //chroma
      if (pSh->pSps->uiChromaArrayType == 0)
        continue;

      WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
      if (!!uiCode) {
        for (int j = 0; j < 2; j++) {


          WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
          WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_weight",
                                          GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_WEIGHT));
          pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = iCode;

          WELS_READ_VERIFY (BsGetSe (pBs, &iCode));
          WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, -128, 127, "chroma_offset",
                                          GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_CHROMA_OFFSET));
          pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = iCode;
        }
      } else {
        for (int j = 0; j < 2; j++) {


          pSh->sPredWeightTable.sPredList[iList].iChromaWeight[i][j] = 1 << (pSh->sPredWeightTable.uiChromaLog2WeightDenom);
          pSh->sPredWeightTable.sPredList[iList].iChromaOffset[i][j] = 0;
        }
      }

    }
    ++iList;
    if (pSh->eSliceType != B_SLICE) {
      break;
    }
  } while (iList < LIST_A);//TODO: SUPPORT LIST_A
  return ERR_NONE;
}

void CreateImplicitWeightTable (PWelsDecoderContext pCtx) {

  PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
  PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
  PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
  if (pCurDqLayer->bUseWeightedBiPredIdc && pSliceHeader->pPps->uiWeightedBipredIdc == 2) {
    int32_t iPoc = pSliceHeader->iPicOrderCntLsb;

    if (pSliceHeader->uiRefCount[0] == 1 && pSliceHeader->uiRefCount[1] == 1
        && pCtx->sRefPic.pRefList[LIST_0][0]->iFramePoc + pCtx->sRefPic.pRefList[LIST_1][0]->iFramePoc == 2 * iPoc) {
      pCurDqLayer->bUseWeightedBiPredIdc = false;
      return;
    }

    pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom = 5;
    pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom = 5;
    for (int32_t iRef0 = 0; iRef0 < pSliceHeader->uiRefCount[0]; iRef0++) {
      if (pCtx->sRefPic.pRefList[LIST_0][iRef0]) {
        const int32_t iPoc0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->iFramePoc;
        bool bIsLongRef0 = pCtx->sRefPic.pRefList[LIST_0][iRef0]->bIsLongRef;
        for (int32_t iRef1 = 0; iRef1 < pSliceHeader->uiRefCount[1]; iRef1++) {
          if (pCtx->sRefPic.pRefList[LIST_1][iRef1]) {
            const int32_t iPoc1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->iFramePoc;
            bool bIsLongRef1 = pCtx->sRefPic.pRefList[LIST_1][iRef1]->bIsLongRef;
            pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 32;
            if (!bIsLongRef0 && !bIsLongRef1) {
              const int32_t iTd = WELS_CLIP3 (iPoc1 - iPoc0, -128, 127);
              if (iTd) {
                int32_t iTb = WELS_CLIP3 (iPoc - iPoc0, -128, 127);
                int32_t iTx = (16384 + (WELS_ABS (iTd) >> 1)) / iTd;
                int32_t iDistScaleFactor = (iTb * iTx + 32) >> 8;
                if (iDistScaleFactor >= -64 && iDistScaleFactor <= 128) {
                  pCurDqLayer->pPredWeightTable->iImplicitWeight[iRef0][iRef1] = 64 - iDistScaleFactor;
                }
              }
            }
          }
        }
      }
    }
  }
  return;
}

/*
 *  Predeclared function routines ..
 */
int32_t ParseRefPicListReordering (PBitStringAux pBs, PSliceHeader pSh) {
  int32_t iList = 0;
  const EWelsSliceType keSt = pSh->eSliceType;
  PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering;
  PSps pSps = pSh->pSps;
  uint32_t uiCode;
  if (keSt == I_SLICE || keSt == SI_SLICE)
    return ERR_NONE;

  // Common syntaxs for P or B slices: list0, list1 followed if B slices used.
  do {
    WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //ref_pic_list_modification_flag_l0
    pRefPicListReordering->bRefPicListReorderingFlag[iList] = !!uiCode;

    if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) {
      int32_t iIdx = 0;
      do {
        WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //modification_of_pic_nums_idc
        const uint32_t kuiIdc = uiCode;

        //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)---
        if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) {
          return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING);
        }
        pRefPicListReordering->sReorderingSyn[iList][iIdx].uiReorderingOfPicNumsIdc = kuiIdc;
        if (kuiIdc == 3)
          break;

        if (iIdx >= pSh->uiRefCount[iList] || iIdx >= MAX_REF_PIC_COUNT)
          return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING);

        if (kuiIdc == 0 || kuiIdc == 1) {
          // abs_diff_pic_num_minus1 should be in range 0 to MaxPicNum-1, MaxPicNum is derived as
          // 2^(4+log2_max_frame_num_minus4)
          WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //abs_diff_pic_num_minus1
          WELS_CHECK_SE_UPPER_ERROR_NOLOG (uiCode, (uint32_t) (1 << pSps->uiLog2MaxFrameNum), "abs_diff_pic_num_minus1",
                                           GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING));
          pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = uiCode; // uiAbsDiffPicNumMinus1
        } else if (kuiIdc == 2) {
          WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num
          pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = uiCode;
        }

        ++ iIdx;
      } while (true);
    }
    if (keSt != B_SLICE)
      break;
    ++ iList;
  } while (iList < LIST_A);

  return ERR_NONE;
}

int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps,
                               const bool kbIdrFlag) {
  PRefPicMarking const kpRefMarking = &pSh->sRefMarking;
  uint32_t uiCode;
  if (kbIdrFlag) {
    WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //no_output_of_prior_pics_flag
    kpRefMarking->bNoOutputOfPriorPicsFlag = !!uiCode;
    WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //long_term_reference_flag
    kpRefMarking->bLongTermRefFlag = !!uiCode;
  } else {
    WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //adaptive_ref_pic_marking_mode_flag
    kpRefMarking->bAdaptiveRefPicMarkingModeFlag = !!uiCode;
    if (kpRefMarking->bAdaptiveRefPicMarkingModeFlag) {
      int32_t iIdx = 0;
      bool bAllowMmco5 = true, bMmco4Exist = false, bMmco5Exist = false, bMmco6Exist = false;
      do {
        WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //memory_management_control_operation
        const uint32_t kuiMmco = uiCode;

        kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kuiMmco;
        if (kuiMmco == MMCO_END)
          break;

        if (kuiMmco == MMCO_SHORT2UNUSED || kuiMmco == MMCO_SHORT2LONG) {

Lines 1–500 of 2772.

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