330 lines · 10.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. * *	cabac_decoder.cpp:	deals with cabac state transition and related functions */#include "cabac_decoder.h"namespace WelsDec {static const int16_t g_kMvdBinPos2Ctx [8] = {0, 1, 2, 3, 3, 3, 3, 3}; void WelsCabacGlobalInit (PWelsDecoderContext pCtx) {  for (int32_t iModel = 0; iModel < 4; iModel++) {    for (int32_t iQp = 0; iQp <= WELS_QP_MAX; iQp++)      for (int32_t iIdx = 0; iIdx < WELS_CONTEXT_COUNT; iIdx++) {        int32_t m               = g_kiCabacGlobalContextIdx[iIdx][iModel][0];        int32_t n               = g_kiCabacGlobalContextIdx[iIdx][iModel][1];        int32_t iPreCtxState    = WELS_CLIP3 ((((m * iQp) >> 4) + n), 1, 126);        uint8_t uiValMps         = 0;        uint8_t uiStateIdx       = 0;        if (iPreCtxState <= 63) {          uiStateIdx = 63 - iPreCtxState;          uiValMps = 0;        } else {          uiStateIdx = iPreCtxState - 64;          uiValMps = 1;        }        pCtx->sWelsCabacContexts[iModel][iQp][iIdx].uiState = uiStateIdx;        pCtx->sWelsCabacContexts[iModel][iQp][iIdx].uiMPS = uiValMps;      }  }  pCtx->bCabacInited = true;} // ------------------- 1. context initializationvoid WelsCabacContextInit (PWelsDecoderContext  pCtx, uint8_t eSliceType, int32_t iCabacInitIdc, int32_t iQp) {  int32_t iIdx =  pCtx->eSliceType == WelsCommon::I_SLICE ? 0 : iCabacInitIdc + 1;  if (!pCtx->bCabacInited) {    WelsCabacGlobalInit (pCtx);  }  memcpy (pCtx->pCabacCtx, pCtx->sWelsCabacContexts[iIdx][iQp],          WELS_CONTEXT_COUNT * sizeof (SWelsCabacCtx));} // ------------------- 2. decoding Engine initializationint32_t InitCabacDecEngineFromBS (PWelsCabacDecEngine pDecEngine, PBitStringAux pBsAux) {  int32_t iRemainingBits = - pBsAux->iLeftBits; //pBsAux->iLeftBits < 0  int32_t iRemainingBytes = (iRemainingBits >> 3) + 2; //+2: indicating the pre-read 2 bytes  uint8_t* pCurr;   pCurr = pBsAux->pCurBuf - iRemainingBytes;  if (pCurr >= (pBsAux->pEndBuf - 1)) {    return ERR_INFO_INVALID_ACCESS;  }  pDecEngine->uiOffset = ((pCurr[0] << 16) | (pCurr[1] << 8) | pCurr[2]);  pDecEngine->uiOffset <<= 16;  pDecEngine->uiOffset |= (pCurr[3] << 8) | pCurr[4];  pDecEngine->iBitsLeft = 31;  pDecEngine->pBuffCurr = pCurr + 5;   pDecEngine->uiRange = WELS_CABAC_HALF;  pDecEngine->pBuffStart = pBsAux->pStartBuf;  pDecEngine->pBuffEnd = pBsAux->pEndBuf;  pBsAux->iLeftBits = 0;  return ERR_NONE;} void RestoreCabacDecEngineToBS (PWelsCabacDecEngine pDecEngine, PBitStringAux pBsAux) {  //CABAC decoding finished, changing to SBitStringAux  pDecEngine->pBuffCurr -= (pDecEngine->iBitsLeft >> 3);  pDecEngine->iBitsLeft = 0;     //pcm_alignment_zero_bit in CABAC  pBsAux->iLeftBits = 0;  pBsAux->pStartBuf = pDecEngine->pBuffStart;  pBsAux->pCurBuf = pDecEngine->pBuffCurr;  pBsAux->uiCurBits = 0;  pBsAux->iIndex = 0;} // ------------------- 3. actual decodingint32_t Read32BitsCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiValue, int32_t& iNumBitsRead) {  intX_t iLeftBytes = pDecEngine->pBuffEnd - pDecEngine->pBuffCurr;  iNumBitsRead = 0;  uiValue = 0;  if (iLeftBytes <= 0) {    return ERR_CABAC_NO_BS_TO_READ;  }  switch (iLeftBytes) {  case 3:    uiValue = ((pDecEngine->pBuffCurr[0]) << 16 | (pDecEngine->pBuffCurr[1]) << 8 | (pDecEngine->pBuffCurr[2]));    pDecEngine->pBuffCurr += 3;    iNumBitsRead = 24;    break;  case 2:    uiValue = ((pDecEngine->pBuffCurr[0]) << 8 | (pDecEngine->pBuffCurr[1]));    pDecEngine->pBuffCurr += 2;    iNumBitsRead = 16;    break;  case 1:    uiValue = pDecEngine->pBuffCurr[0];    pDecEngine->pBuffCurr += 1;    iNumBitsRead = 8;    break;  default:    uiValue = ((pDecEngine->pBuffCurr[0] << 24) | (pDecEngine->pBuffCurr[1]) << 16 | (pDecEngine->pBuffCurr[2]) << 8 |               (pDecEngine->pBuffCurr[3]));    pDecEngine->pBuffCurr += 4;    iNumBitsRead = 32;    break;  }  return ERR_NONE;} int32_t DecodeBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBinVal) {  int32_t iErrorInfo = ERR_NONE;  uint32_t uiState = pBinCtx->uiState;  uiBinVal = pBinCtx->uiMPS;  uint64_t uiOffset = pDecEngine->uiOffset;  uint64_t uiRange = pDecEngine->uiRange;   int32_t iRenorm = 1;  uint32_t uiRangeLPS = g_kuiCabacRangeLps[uiState][ (uiRange >> 6) & 0x03];  uiRange -= uiRangeLPS;  if (uiOffset >= (uiRange << pDecEngine->iBitsLeft)) { //LPS    uiOffset -= (uiRange << pDecEngine->iBitsLeft);    uiBinVal ^= 0x0001;    if (!uiState)      pBinCtx->uiMPS ^= 0x01;    pBinCtx->uiState = g_kuiStateTransTable[uiState][0];    iRenorm = g_kRenormTable256[uiRangeLPS];    uiRange = (uiRangeLPS << iRenorm);  } else {  //MPS    pBinCtx->uiState = g_kuiStateTransTable[uiState][1];    if (uiRange >= WELS_CABAC_QUARTER) {      pDecEngine->uiRange = uiRange;      return ERR_NONE;    } else {      uiRange <<= 1;    }  }  //Renorm  pDecEngine->uiRange = uiRange;  pDecEngine->iBitsLeft -= iRenorm;  if (pDecEngine->iBitsLeft > 0) {    pDecEngine->uiOffset = uiOffset;    return ERR_NONE;  }  uint32_t uiVal = 0;  int32_t iNumBitsRead = 0;  iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);  pDecEngine->uiOffset = (uiOffset << iNumBitsRead) | uiVal;  pDecEngine->iBitsLeft += iNumBitsRead;  if (iErrorInfo && pDecEngine->iBitsLeft < 0) {    return iErrorInfo;  }  return ERR_NONE;} int32_t DecodeBypassCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal) {  int32_t iErrorInfo = ERR_NONE;  int32_t iBitsLeft = pDecEngine->iBitsLeft;  uint64_t uiOffset = pDecEngine->uiOffset;  uint64_t uiRangeValue;    if (iBitsLeft <= 0) {    uint32_t uiVal = 0;    int32_t iNumBitsRead = 0;    iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);    uiOffset = (uiOffset << iNumBitsRead) | uiVal;    iBitsLeft = iNumBitsRead;    if (iErrorInfo && iBitsLeft == 0) {      return iErrorInfo;    }  }  iBitsLeft--;  uiRangeValue = (pDecEngine->uiRange << iBitsLeft);  if (uiOffset >= uiRangeValue) {    pDecEngine->iBitsLeft = iBitsLeft;    pDecEngine->uiOffset = uiOffset - uiRangeValue;    uiBinVal = 1;    return ERR_NONE;  }  pDecEngine->iBitsLeft = iBitsLeft;  pDecEngine->uiOffset = uiOffset;  uiBinVal = 0;  return ERR_NONE;} int32_t DecodeTerminateCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal) {  int32_t iErrorInfo = ERR_NONE;  uint64_t uiRange = pDecEngine->uiRange - 2;  uint64_t uiOffset = pDecEngine->uiOffset;   if (uiOffset >= (uiRange << pDecEngine->iBitsLeft)) {    uiBinVal = 1;  } else {    uiBinVal = 0;    // Renorm    if (uiRange < WELS_CABAC_QUARTER) {      int32_t iRenorm = g_kRenormTable256[uiRange];      pDecEngine->uiRange = (uiRange << iRenorm);      pDecEngine->iBitsLeft -= iRenorm;      if (pDecEngine->iBitsLeft < 0) {        uint32_t uiVal = 0;        int32_t iNumBitsRead = 0;        iErrorInfo = Read32BitsCabac (pDecEngine, uiVal, iNumBitsRead);        pDecEngine->uiOffset = (pDecEngine->uiOffset << iNumBitsRead) | uiVal;        pDecEngine->iBitsLeft += iNumBitsRead;      }      if (iErrorInfo && pDecEngine->iBitsLeft < 0) {        return iErrorInfo;      }      return ERR_NONE;    } else {      pDecEngine->uiRange = uiRange;      return ERR_NONE;    }  }  return ERR_NONE;} int32_t DecodeUnaryBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, int32_t iCtxOffset,                             uint32_t& uiSymVal) {  uiSymVal = 0;  WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiSymVal));  if (uiSymVal == 0) {    return ERR_NONE;  } else {    uint32_t uiCode;    pBinCtx += iCtxOffset;    uiSymVal = 0;    do {      WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiCode));      ++uiSymVal;    } while (uiCode != 0);    return ERR_NONE;  }} int32_t DecodeExpBypassCabac (PWelsCabacDecEngine pDecEngine, int32_t iCount, uint32_t& uiSymVal) {  uint32_t uiCode;  int32_t iSymTmp = 0;  int32_t iSymTmp2 = 0;  uiSymVal = 0;  do {    WELS_READ_VERIFY (DecodeBypassCabac (pDecEngine, uiCode));    if (uiCode == 1) {      iSymTmp += (1 << iCount);      ++iCount;    }  } while (uiCode != 0);   while (iCount--) {    WELS_READ_VERIFY (DecodeBypassCabac (pDecEngine, uiCode));    if (uiCode == 1) {      iSymTmp2 |= (1 << iCount);    }  }  uiSymVal = (uint32_t) (iSymTmp + iSymTmp2);  return ERR_NONE;} uint32_t DecodeUEGLevelCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiCode) {  uiCode = 0;  WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiCode));  if (uiCode == 0)    return ERR_NONE;  else {    uint32_t uiTmp, uiCount = 1;    uiCode = 0;    do {      WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx, uiTmp));      ++uiCode;      ++uiCount;    } while (uiTmp != 0 && uiCount != 13);     if (uiTmp != 0) {      WELS_READ_VERIFY (DecodeExpBypassCabac (pDecEngine, 0, uiTmp));      uiCode += uiTmp + 1;    }    return ERR_NONE;  }  return ERR_NONE;} int32_t DecodeUEGMvCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t iMaxBin,  uint32_t& uiCode) {  WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx + g_kMvdBinPos2Ctx[0], uiCode));  if (uiCode == 0)    return ERR_NONE;  else {    uint32_t uiTmp, uiCount = 1;    uiCode = 0;    do {      WELS_READ_VERIFY (DecodeBinCabac (pDecEngine, pBinCtx + g_kMvdBinPos2Ctx[uiCount++], uiTmp));      uiCode++;    } while (uiTmp != 0 && uiCount != 8);     if (uiTmp != 0) {      WELS_READ_VERIFY (DecodeExpBypassCabac (pDecEngine, 3, uiTmp));      uiCode += (uiTmp + 1);    }    return ERR_NONE;  }}}

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