Merge pull request #1480 from dongzha/cleanCabacDecoder

add decoder cabac support and add  UT
This commit is contained in:
sijchen 2014-11-03 15:38:24 +08:00
commit 938f441751
32 changed files with 2617 additions and 472 deletions

View File

@ -30,6 +30,8 @@
4CE4469F18BC5EAB0017DF25 /* welsDecoderExt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4468518BC5EAB0017DF25 /* welsDecoderExt.cpp */; };
4CE447AC18BC6BE90017DF25 /* block_add_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4CE447A718BC6BE90017DF25 /* block_add_neon.S */; };
4CE447AE18BC6BE90017DF25 /* intra_pred_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4CE447A918BC6BE90017DF25 /* intra_pred_neon.S */; };
6A3E814219D79AE900C19C1F /* cabac_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */; };
6A3E814419D7A40600C19C1F /* parse_mb_syn_cabac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */; };
6C749B6A197CC6E600A111F9 /* block_add_aarch64_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C749B69197CC6E600A111F9 /* block_add_aarch64_neon.S */; };
9ABF4382193EB60900A6BD61 /* expand_pic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9ABF4381193EB60900A6BD61 /* expand_pic.cpp */; };
9AED66561946A1DE009A3567 /* welsCodecTrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AED66551946A1DE009A3567 /* welsCodecTrace.cpp */; };
@ -109,6 +111,10 @@
4CE4468518BC5EAB0017DF25 /* welsDecoderExt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = welsDecoderExt.cpp; sourceTree = "<group>"; };
4CE447A718BC6BE90017DF25 /* block_add_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = block_add_neon.S; sourceTree = "<group>"; };
4CE447A918BC6BE90017DF25 /* intra_pred_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = intra_pred_neon.S; sourceTree = "<group>"; };
6A3E814019D79AD900C19C1F /* cabac_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cabac_decoder.h; sourceTree = "<group>"; };
6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cabac_decoder.cpp; sourceTree = "<group>"; };
6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_mb_syn_cabac.cpp; sourceTree = "<group>"; };
6A3E814519D7A40D00C19C1F /* parse_mb_syn_cabac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_mb_syn_cabac.h; sourceTree = "<group>"; };
6C749B69197CC6E600A111F9 /* block_add_aarch64_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = block_add_aarch64_neon.S; path = arm64/block_add_aarch64_neon.S; sourceTree = "<group>"; };
9ABF4380193EB5F700A6BD61 /* expand_pic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = expand_pic.h; path = ../../../common/inc/expand_pic.h; sourceTree = "<group>"; };
9ABF4381193EB60900A6BD61 /* expand_pic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = expand_pic.cpp; path = ../../../common/src/expand_pic.cpp; sourceTree = "<group>"; };
@ -191,6 +197,8 @@
4CE4464418BC5EAA0017DF25 /* inc */ = {
isa = PBXGroup;
children = (
6A3E814519D7A40D00C19C1F /* parse_mb_syn_cabac.h */,
6A3E814019D79AD900C19C1F /* cabac_decoder.h */,
9AED665A1946A21D009A3567 /* utils.h */,
9ABF4380193EB5F700A6BD61 /* expand_pic.h */,
F0B204FA18FD23CF005DA23F /* error_concealment.h */,
@ -232,6 +240,8 @@
4CE4466618BC5EAA0017DF25 /* src */ = {
isa = PBXGroup;
children = (
6A3E814319D7A40600C19C1F /* parse_mb_syn_cabac.cpp */,
6A3E814119D79AE900C19C1F /* cabac_decoder.cpp */,
9AED66581946A203009A3567 /* utils.cpp */,
9ABF4381193EB60900A6BD61 /* expand_pic.cpp */,
F0B204FB18FD23D8005DA23F /* error_concealment.cpp */,
@ -346,6 +356,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6A3E814419D7A40600C19C1F /* parse_mb_syn_cabac.cpp in Sources */,
4CE4469B18BC5EAB0017DF25 /* pic_queue.cpp in Sources */,
4CE4469F18BC5EAB0017DF25 /* welsDecoderExt.cpp in Sources */,
4CE4469318BC5EAB0017DF25 /* fmo.cpp in Sources */,
@ -355,6 +366,7 @@
4CE4469518BC5EAB0017DF25 /* manage_dec_ref.cpp in Sources */,
4CE4468A18BC5EAB0017DF25 /* au_parser.cpp in Sources */,
4CE4469918BC5EAB0017DF25 /* mv_pred.cpp in Sources */,
6A3E814219D79AE900C19C1F /* cabac_decoder.cpp in Sources */,
4CE447AC18BC6BE90017DF25 /* block_add_neon.S in Sources */,
6C749B6A197CC6E600A111F9 /* block_add_aarch64_neon.S in Sources */,
4CE4469418BC5EAB0017DF25 /* get_intra_predictor.cpp in Sources */,

View File

@ -655,6 +655,10 @@
RelativePath="..\..\..\decoder\core\inc\bit_stream.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\cabac_decoder.h"
>
</File>
<File
RelativePath="..\..\..\common\inc\copy_mb.h"
>
@ -775,6 +779,10 @@
RelativePath="..\..\..\decoder\core\inc\parameter_sets.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cabac.h"
>
</File>
<File
RelativePath="..\..\..\decoder\core\inc\parse_mb_syn_cavlc.h"
>
@ -832,6 +840,10 @@
RelativePath="..\..\..\decoder\core\src\bit_stream.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\cabac_decoder.cpp"
>
</File>
<File
RelativePath="..\..\..\common\src\common_tables.cpp"
>
@ -912,6 +924,10 @@
RelativePath="..\..\..\decoder\core\src\mv_pred.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\parse_mb_syn_cabac.cpp"
>
</File>
<File
RelativePath="..\..\..\decoder\core\src\parse_mb_syn_cavlc.cpp"
>

View File

@ -35,7 +35,6 @@
#define WELS_BIT_STREAM_H__
#include "typedefs.h"
namespace WelsDec {
/*
@ -64,7 +63,7 @@ typedef struct TagBitStringAux {
*/
int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t kiSize);
void InitReadBits (PBitStringAux pBitString);
int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset);

View File

@ -0,0 +1,111 @@
/*!
* \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 cabac_decoder.h
*
* \brief Interfaces introduced for cabac decoder
*
* \date 10/10/2014 Created
*
*************************************************************************************
*/
#ifndef WELS_CABAC_DECODER_H__
#define WELS_CABAC_DECODER_H__
#include "decoder_context.h"
#include "error_code.h"
#include "wels_common_defs.h"
namespace WelsDec {
static const uint8_t g_kRenormTable256[256] = {
6, 6, 6, 6, 6, 6, 6, 6,
5, 5, 5, 5, 5, 5, 5, 5,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1
};
//1. CABAC context initialization
void WelsCabacGlobalInit(PWelsDecoderContext pCabacCtx);
void WelsCabacContextInit (PWelsDecoderContext pCtx, uint8_t eSliceType, int32_t iCabacInitIdc, int32_t iQp);
//2. decoding Engine initialization
int32_t InitCabacDecEngineFromBS (PWelsCabacDecEngine pDecEngine, SBitStringAux* pBsAux);
void RestoreCabacDecEngineToBS (PWelsCabacDecEngine pDecEngine, SBitStringAux* pBsAux);
//3. actual decoding
int32_t Read32BitsCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiValue, int32_t& iNumBitsRead);
int32_t DecodeBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBit);
int32_t DecodeBypassCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal);
int32_t DecodeTerminateCabac (PWelsCabacDecEngine pDecEngine, uint32_t& uiBinVal);
//4. unary parsing
int32_t DecodeUnaryBinCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, int32_t iCtxOffset,
uint32_t& uiSymVal);
//5. EXGk parsing
int32_t DecodeExpBypassCabac (PWelsCabacDecEngine pDecEngine, int32_t iCount, uint32_t& uiSymVal);
uint32_t DecodeUEGLevelCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t& uiBinVal);
int32_t DecodeUEGMvCabac (PWelsCabacDecEngine pDecEngine, PWelsCabacCtx pBinCtx, uint32_t iMaxC, uint32_t& uiCode);
#define WELS_CABAC_HALF 0x01FE
#define WELS_CABAC_QUARTER 0x0100
#define WELS_CABAC_FALSE_RETURN(iErrorInfo) \
if(iErrorInfo) { \
return iErrorInfo; \
}
}
#endif

View File

@ -66,10 +66,12 @@ struct TagDqLayer {
int8_t* pMbType;
int32_t* pSliceIdc; // using int32_t for slice_idc
int16_t (*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
int16_t (*pMvd[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
int8_t (*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM];
int8_t* pLumaQp;
int8_t* pChromaQp;
int8_t* pCbp;
uint8_t *pCbfDc;
int8_t (*pNzc)[24];
int8_t (*pNzcRs)[24];
int8_t* pResidualPredFlag;

View File

@ -219,7 +219,7 @@ static inline int32_t BsGetTe0 (PBitStringAux pBs, int32_t iRange, uint32_t* pCo
static inline int32_t BsGetTrailingBits (uint8_t* pBuf) {
// TODO
uint32_t uiValue = *pBuf;
int32_t iRetNum = 1;
int32_t iRetNum = 0;
do {
if (uiValue & 1)

View File

@ -38,11 +38,16 @@
namespace WelsDec {
int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx);
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur);
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx);
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur);
typedef int32_t (*PWelsDecMbCavlcFunc) (PWelsDecoderContext pCtx, PNalUnit pNalCur);
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
typedef int32_t (*PWelsDecMbFunc) (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacISlice(PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacPSlice(PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacISliceBaseMode0(PWelsDecoderContext pCtx, uint32_t& uiEosFlag);
int32_t WelsDecodeMbCabacPSliceBaseMode0(PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiEosFlag);
int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx); //construction based on slice
@ -77,6 +82,8 @@ void SetNonZeroCount_AArch64_neon (int8_t* pNonZeroCount);
void SetNonZeroCount_c (int8_t* pNonZeroCount);
void WelsBlockFuncInit (SBlockFunc* pFunc, int32_t iCpu);
void WelsBlockZero16x16_c(int16_t * block, int32_t stride);
void WelsBlockZero8x8_c(int16_t * block, int32_t stride);
} // namespace WelsDec

View File

@ -43,6 +43,7 @@
#include "utils.h"
#include "wels_const.h"
#include "wels_common_basis.h"
#include "wels_common_defs.h"
#include "codec_app_def.h"
#include "parameter_sets.h"
#include "nalu.h"
@ -56,6 +57,42 @@
#include "expand_pic.h"
namespace WelsDec {
#define MAX_PRED_MODE_ID_I16x16 3
#define MAX_PRED_MODE_ID_CHROMA 3
#define MAX_PRED_MODE_ID_I4x4 8
#define WELS_QP_MAX 51
typedef struct SWels_Cabac_Element {
uint8_t uiState;
uint8_t uiMPS;
}SWelsCabacCtx, *PWelsCabacCtx;
typedef struct
{
uint64_t uiRange;
uint64_t uiOffset;
int32_t iBitsLeft;
uint8_t *pBuffStart;
uint8_t *pBuffCurr;
uint8_t *pBuffEnd;
} SWelsCabacDecEngine, *PWelsCabacDecEngine;
#define NEW_CTX_OFFSET_MB_TYPE_I 3
#define NEW_CTX_OFFSET_SKIP 11
#define NEW_CTX_OFFSET_SUBMB_TYPE 21
#define NEW_CTX_OFFSET_MVD 40
#define NEW_CTX_OFFSET_REF_NO 54
#define NEW_CTX_OFFSET_DELTA_QP 60
#define NEW_CTX_OFFSET_IPR 68
#define NEW_CTX_OFFSET_CIPR 64
#define NEW_CTX_OFFSET_CBP 73
#define NEW_CTX_OFFSET_CBF 85
#define NEW_CTX_OFFSET_MAP 105
#define NEW_CTX_OFFSET_LAST 166
#define NEW_CTX_OFFSET_ONE 227
#define NEW_CTX_OFFSET_ABS 232
#define CTX_NUM_MVD 7
#define CTX_NUM_CBP 4
typedef struct TagDataBuffer {
uint8_t* pHead;
@ -141,16 +178,20 @@ PChromaDeblockingEQ4Func pfChromaDeblockingEQ4Hor;
} SDeblockingFunc, *PDeblockingFunc;
typedef void (*PWelsNonZeroCountFunc) (int8_t* pNonZeroCount);
typedef void (*PWelsBlockZeroFunc) (int16_t* block,int32_t stride);
typedef struct TagBlockFunc {
PWelsNonZeroCountFunc pWelsSetNonZeroCountFunc;
PWelsBlockZeroFunc pWelsBlockZero16x16Func;
PWelsBlockZeroFunc pWelsBlockZero8x8Func;
} SBlockFunc;
typedef void (*PWelsFillNeighborMbInfoIntra4x4Func) (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
typedef void (*PWelsFillNeighborMbInfoIntra4x4Func) (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int8_t* pIntraPredMode, PDqLayer pCurLayer);
typedef int32_t (*PWelsParseIntra4x4ModeFunc) (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
typedef void (*PWelsMapNeighToSample) (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail);
typedef void (*PWelsMap16NeighToSample) (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail);
typedef int32_t (*PWelsParseIntra4x4ModeFunc) (PWelsNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer);
typedef int32_t (*PWelsParseIntra16x16ModeFunc) (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
typedef int32_t (*PWelsParseIntra16x16ModeFunc) (PWelsNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
enum {
OVERWRITE_NONE = 0,
@ -202,6 +243,8 @@ struct {
int8_t (*pRefIndex[LAYER_NUM_EXCHANGEABLE][LIST_A])[MB_BLOCK4x4_NUM];
int8_t* pLumaQp[LAYER_NUM_EXCHANGEABLE]; /*mb luma_qp*/
int8_t* pChromaQp[LAYER_NUM_EXCHANGEABLE]; /*mb chroma_qp*/
int16_t (*pMvd[LAYER_NUM_EXCHANGEABLE][LIST_A])[MB_BLOCK4x4_NUM][MV_A]; //[LAYER_NUM_EXCHANGEABLE MB_BLOCK4x4_NUM*]
uint8_t *pCbfDc[LAYER_NUM_EXCHANGEABLE];
int8_t (*pNzc[LAYER_NUM_EXCHANGEABLE])[24];
int8_t (*pNzcRs[LAYER_NUM_EXCHANGEABLE])[24];
int16_t (*pScaledTCoeff[LAYER_NUM_EXCHANGEABLE])[MB_COEFF_LIST_SIZE]; /*need be aligned*/
@ -308,8 +351,8 @@ int32_t iCurSeqIntervalMaxPicWidth;
int32_t iCurSeqIntervalMaxPicHeight;
PWelsFillNeighborMbInfoIntra4x4Func pFillInfoCacheIntra4x4Func;
PWelsParseIntra4x4ModeFunc pParseIntra4x4ModeFunc;
PWelsParseIntra16x16ModeFunc pParseIntra16x16ModeFunc;
PWelsMapNeighToSample pMap4x4NeighToSampleFunc;
PWelsMap16NeighToSample pMap16x16NeighToSampleFunc;
//feedback whether or not have VCL in current AU, and the temporal ID
int32_t iFeedbackVclNalInAu;
@ -325,7 +368,10 @@ void* pTraceHandle;
//Save the last nal header info
SNalUnitHeaderExt sLastNalHdrExt;
SSliceHeader sLastSliceHeader;
SWelsCabacCtx sWelsCabacContexts[4][WELS_QP_MAX + 1][WELS_CONTEXT_COUNT];
bool bCabacInited;
SWelsCabacCtx pCabacCtx[WELS_CONTEXT_COUNT];
PWelsCabacDecEngine pCabacDecEngine;
} SWelsDecoderContext, *PWelsDecoderContext;
static inline void ResetActiveSPSForEachLayer (PWelsDecoderContext pCtx) {
@ -337,6 +383,7 @@ for (int i = 0; i < MAX_LAYER_NUM; i++) {
//}
//#endif//__cplusplus
} // namespace WelsDec
#endif//WELS_DECODER_FRAMEWORK_H__

View File

@ -180,7 +180,9 @@ EER_INFO_INVALID_MMCO_LONG2UNUSED,
ERR_INFO_INVALID_MMCO_SHOART2LONG,
ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW,
ERR_INFO_INVALID_MMCO_REF_NUM_NOT_ENOUGH,
ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX
ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX,
//for CABAC
ERR_CABAC_NO_BS_TO_READ,
};
//-----------------------------------------------------------------------------------------------------------

View File

@ -69,7 +69,11 @@ int32_t iLeftType;
int32_t iTopType;
int32_t iLeftTopType;
int32_t iRightTopType;
} SNeighAvail, *PNeighAvail;
int8_t iTopCbp;
int8_t iLeftCbp;
int8_t iDummy[2]; //for align
} SWelsNeighAvail, *PWelsNeighAvail;
} // namespace WelsDec

View File

@ -0,0 +1,72 @@
/*!
* \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 parse_mb_syn_cabac.h
*
* \brief cabac parse for syntax elements
*
* \date 10/10/2014 Created
*
*************************************************************************************
*/
#ifndef WELS_PARSE_MB_SYN_CABAC_H__
#define WELS_PARSE_MB_SYN_CABAC_H__
#include "decoder_context.h"
#include "cabac_decoder.h"
namespace WelsDec {
int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal);
int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip);
int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType);
int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal);
int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal);
int32_t ParseInterMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]);
int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
int8_t ref_idx[LIST_A][30],
int32_t iListIdx, int32_t index, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal);
int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal);
int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal);
int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta);
int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t index, int32_t iResProperty,
PWelsDecoderContext pCtx, uint32_t& uiCbpBit);
int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
uint32_t& uiBinVal);
int32_t ParseSignificantCoeffCabac (int32_t* significant, int32_t iResProperty, PWelsDecoderContext pCtx);
int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
int32_t index, int32_t iMaxNumCoeff, const uint8_t* pScanTable, int32_t iResProperty, int16_t* sTCoeff, uint8_t uiQp,
PWelsDecoderContext pCtx);
int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx);
}
//#pragma pack()
#endif

View File

@ -49,101 +49,19 @@
namespace WelsDec {
#define I16_LUMA_DC 1
#define I16_LUMA_AC 2
#define LUMA_DC_AC 3
#define CHROMA_DC 4
#define CHROMA_AC 5
typedef struct TagReadBitsCache {
uint32_t uiCache32Bit;
uint8_t uiRemainBits;
uint8_t* pBuf;
} SReadBitsCache;
#define SHIFT_BUFFER(pBitsCache) { pBitsCache->pBuf+=2; pBitsCache->uiRemainBits += 16; pBitsCache->uiCache32Bit |= (((pBitsCache->pBuf[2] << 8) | pBitsCache->pBuf[3]) << (32 - pBitsCache->uiRemainBits)); }
#define POP_BUFFER(pBitsCache, iCount) { pBitsCache->uiCache32Bit <<= iCount; pBitsCache->uiRemainBits -= iCount; }
static const uint8_t g_kuiZigzagScan[16] = { //4*4block residual zig-zag scan order
0, 1, 4, 8,
5, 2, 3, 6,
9, 12, 13, 10,
7, 11, 14, 15,
};
typedef struct TagI16PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
} SI16PredInfo;
static const SI16PredInfo g_ksI16PredInfo[4] = {
{I16_PRED_V, 0, 1, 0},
{I16_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I16_PRED_P, 1, 1, 1},
};
static const SI16PredInfo g_ksChromaPredInfo[4] = {
{ 0, 0, 0, 0},
{C_PRED_H, 1, 0, 0},
{C_PRED_V, 0, 1, 0},
{C_PRED_P, 1, 1, 1},
};
typedef struct TagI4PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
// int8_t right_top_avail; //when right_top unavailable but top avail, we can pad the right-top with the rightmost pixel of top
} SI4PredInfo;
static const SI4PredInfo g_ksI4PredInfo[9] = {
{ I4_PRED_V, 0, 1, 0},
{ I4_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I4_PRED_DDL, 0, 1, 0},
{I4_PRED_DDR, 1, 1, 1},
{ I4_PRED_VR, 1, 1, 1},
{ I4_PRED_HD, 1, 1, 1},
{ I4_PRED_VL, 0, 1, 0},
{ I4_PRED_HU, 1, 0, 0},
};
static const uint8_t g_kuiI16CbpTable[6] = {0, 16, 32, 15, 31, 47}; //reference to JM
typedef struct TagPartMbInfo {
MbType iType;
int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
int8_t iPartWidth; //based on 4*4 block
} SPartMbInfo;
static const SPartMbInfo g_ksInterMbTypeInfo[5] = {
{MB_TYPE_16x16, 1, 4},
{MB_TYPE_16x8, 2, 4},
{MB_TYPE_8x16, 2, 2},
{MB_TYPE_8x8, 4, 4},
{MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
};
static const SPartMbInfo g_ksInterSubMbTypeInfo[4] = {
{SUB_MB_TYPE_8x8, 1, 2},
{SUB_MB_TYPE_8x4, 2, 2},
{SUB_MB_TYPE_4x8, 2, 1},
{SUB_MB_TYPE_4x4, 4, 1},
};
void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer);
void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, PDqLayer pCurLayer);
void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void GetNeighborAvailMbType (PWelsNeighAvail pNeighAvail, PDqLayer pCurLayer);
void WelsFillCacheNonZeroCount (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, PDqLayer pCurLayer);
void WelsFillCacheConstrain0Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer);
void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void WelsFillCacheConstrain1Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer);
void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
void WelsFillCacheInterCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int16_t iMvdCache[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer);
void WelsFillCacheInter (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer);
/*!
* \brief check iPredMode for intra16x16 eligible or not
* \param input : current iPredMode
@ -190,19 +108,7 @@ int32_t WelsResidualBlockCavlc (SVlcTable* pVlcTable,
PWelsDecoderContext pCtx);
/*!
* \brief parsing intra mode
* \param input : current mb, bit-stream
* \param output: 0 indicating decoding correctly; -1 means error
*/
int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer);
int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer);
int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer);
/*!
* \brief parsing inter info (including ref_index and mvd)
* \brief parsing inter info (including ref_index and pMvd)
* \param input : decoding context, current mb, bit-stream
* \param output: 0 indicating decoding correctly; -1 means error
*/

View File

@ -197,6 +197,7 @@ bool bSliceHeaderExtFlag; // Indicate which slice header is used, avc or ext?
/*from lower layer: slice header*/
uint8_t eSliceType;
uint8_t uiPadding[2];
int32_t iLastDeltaQp;
} SSlice, *PSlice;
} // namespace WelsDec

View File

@ -47,6 +47,11 @@ namespace WelsDec {
extern const uint8_t g_kuiScan8[24];
extern const uint8_t g_kuiLumaDcZigzagScan[16];
extern const uint8_t g_kuiChromaDcScan[4];
extern const uint8_t g_kMbNonZeroCountIdx[24];
extern const uint8_t g_kCacheNzcScanIdx[4*4+4+4+3];
extern const uint8_t g_kCache26ScanIdx[16];
extern const uint8_t g_kCache30ScanIdx[16];
extern const uint8_t g_kNonZeroScanIdxC[4];
/* Profile IDC */
typedef uint8_t ProfileIdc;
enum {
@ -118,7 +123,94 @@ typedef int32_t SubMbType;
#define IS_I_BL(type) ( (type) == MB_TYPE_INTRA_BL )
#define IS_SUB8x8(type) (MB_TYPE_8x8 == (type) || MB_TYPE_8x8_REF0 == (type))
#define I16_LUMA_DC 1
#define I16_LUMA_AC 2
#define LUMA_DC_AC 3
#define CHROMA_DC 4
#define CHROMA_AC 5
#define CHROMA_DC_U 6
#define CHROMA_DC_V 7
#define CHROMA_AC_U 8
#define CHROMA_AC_V 9
typedef struct TagReadBitsCache {
uint32_t uiCache32Bit;
uint8_t uiRemainBits;
uint8_t* pBuf;
} SReadBitsCache;
#define SHIFT_BUFFER(pBitsCache) { pBitsCache->pBuf+=2; pBitsCache->uiRemainBits += 16; pBitsCache->uiCache32Bit |= (((pBitsCache->pBuf[2] << 8) | pBitsCache->pBuf[3]) << (32 - pBitsCache->uiRemainBits)); }
#define POP_BUFFER(pBitsCache, iCount) { pBitsCache->uiCache32Bit <<= iCount; pBitsCache->uiRemainBits -= iCount; }
static const uint8_t g_kuiZigzagScan[16] = { //4*4block residual zig-zag scan order
0, 1, 4, 8,
5, 2, 3, 6,
9, 12, 13, 10,
7, 11, 14, 15,
};
typedef struct TagI16PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
} SI16PredInfo;
static const SI16PredInfo g_ksI16PredInfo[4] = {
{I16_PRED_V, 0, 1, 0},
{I16_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I16_PRED_P, 1, 1, 1},
};
static const SI16PredInfo g_ksChromaPredInfo[4] = {
{ 0, 0, 0, 0},
{C_PRED_H, 1, 0, 0},
{C_PRED_V, 0, 1, 0},
{C_PRED_P, 1, 1, 1},
};
typedef struct TagI4PredInfo {
int8_t iPredMode;
int8_t iLeftAvail;
int8_t iTopAvail;
int8_t iLeftTopAvail;
// int8_t right_top_avail; //when right_top unavailable but top avail, we can pad the right-top with the rightmost pixel of top
} SI4PredInfo;
static const SI4PredInfo g_ksI4PredInfo[9] = {
{ I4_PRED_V, 0, 1, 0},
{ I4_PRED_H, 1, 0, 0},
{ 0, 0, 0, 0},
{I4_PRED_DDL, 0, 1, 0},
{I4_PRED_DDR, 1, 1, 1},
{ I4_PRED_VR, 1, 1, 1},
{ I4_PRED_HD, 1, 1, 1},
{ I4_PRED_VL, 0, 1, 0},
{ I4_PRED_HU, 1, 0, 0},
};
static const uint8_t g_kuiI16CbpTable[6] = {0, 16, 32, 15, 31, 47};
typedef struct TagPartMbInfo {
MbType iType;
int8_t iPartCount; //P_16*16, P_16*8, P_8*16, P_8*8 based on 8*8 block; P_8*4, P_4*8, P_4*4 based on 4*4 block
int8_t iPartWidth; //based on 4*4 block
} SPartMbInfo;
static const SPartMbInfo g_ksInterMbTypeInfo[5] = {
{MB_TYPE_16x16, 1, 4},
{MB_TYPE_16x8, 2, 4},
{MB_TYPE_8x16, 2, 2},
{MB_TYPE_8x8, 4, 4},
{MB_TYPE_8x8_REF0, 4, 4}, //ref0--ref_idx not present in bit-stream and default as 0
};
static const SPartMbInfo g_ksInterSubMbTypeInfo[4] = {
{SUB_MB_TYPE_8x8, 1, 2},
{SUB_MB_TYPE_8x4, 2, 2},
{SUB_MB_TYPE_4x8, 2, 1},
{SUB_MB_TYPE_4x4, 4, 1},
};
} // namespace WelsDec

View File

@ -96,4 +96,10 @@
#define MAX_ACCESS_UNIT_CAPACITY 7077888 //Maximum AU size in bytes for level 5.2 for single frame
#define MAX_MACROBLOCK_CAPACITY 5000 //Maximal legal MB capacity, 15000 bits is enough
enum {
BASE_MB = 0,
NON_AVC_REWRITE_ENHANCE_MB =1,
AVC_REWRITE_ENHANCE_MB = 2
};
#endif//WELS_CONSTANCE_H__

View File

@ -43,7 +43,6 @@
#include "error_code.h"
#include "memmgr_nal_unit.h"
#include "decoder_core.h"
#include "decoder_core.h"
namespace WelsDec {
/*!
@ -227,14 +226,18 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
pCurNal->sNalHeaderExt.sNalUnitHeader.uiForbiddenZeroBit = pNalUnitHeader->uiForbiddenZeroBit;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc = pNalUnitHeader->uiNalRefIdc;
pCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType = pNalUnitHeader->eNalUnitType;
if (pNalUnitHeader->uiNalRefIdc != 0) {
pBs = &pCtx->sBs;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
pBs = &pCtx->sBs;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
InitBits (pBs, pNal, iBitSize);
ParsePrefixNalUnit (pCtx, pBs);
iErr = InitBits (pBs, pNal, iBitSize);
if (iErr) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_PREFIX: InitBits() fail due invalid access.");
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
ParsePrefixNalUnit (pCtx, pBs);
}
pCurNal->sNalData.sPrefixNal.bPrefixNalCorrectFlag = true;
break;
@ -309,7 +312,12 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
pBs = &pCurAu->pNalUnitsList[uiAvailNalNum - 1]->sNalData.sVclNal.sSliceBitsRead;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit
InitBits (pBs, pNal, iBitSize);
iErr = InitBits (pBs, pNal, iBitSize);
if (iErr) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_CODED_SLICE: InitBits() fail due invalid access.");
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
iErr = ParseSliceHeaderSyntaxs (pCtx, pBs, bExtensionFlag);
if (iErr != ERR_NONE) {
if ((uiAvailNalNum == 1) && (pCurNal->sNalHeaderExt.bIdrFlag)) { //IDR parse error
@ -505,8 +513,16 @@ int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t
switch (eNalType) {
case NAL_UNIT_SPS:
case NAL_UNIT_SUBSET_SPS:
if (iBitSize > 0)
InitBits (pBs, pRbsp, iBitSize);
if (iBitSize > 0) {
iErr = InitBits (pBs, pRbsp, iBitSize);
if (ERR_NONE != iErr) {
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
return iErr;
}
}
iErr = ParseSps (pCtx, pBs, &iPicWidth, &iPicHeight);
if (ERR_NONE != iErr) { // modified for pSps/pSubsetSps invalid, 12/1/2009
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
@ -519,8 +535,16 @@ int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t
break;
case NAL_UNIT_PPS:
if (iBitSize > 0)
InitBits (pBs, pRbsp, iBitSize);
if (iBitSize > 0) {
iErr = InitBits (pBs, pRbsp, iBitSize);
if (ERR_NONE != iErr) {
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
return iErr;
}
}
iErr = ParsePps (pCtx, &pCtx->sPpsBuffer[0], pBs);
if (ERR_NONE != iErr) { // modified for pps invalid, 12/1/2009
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)

View File

@ -38,6 +38,7 @@
*************************************************************************************
*/
#include "bit_stream.h"
#include "error_code.h"
namespace WelsDec {
@ -47,10 +48,14 @@ inline uint32_t GetValue4Bytes (uint8_t* pDstNal) {
return uiValue;
}
void InitReadBits (PBitStringAux pBitString) {
int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset) {
if(pBitString->pCurBuf>=(pBitString->pEndBuf - iEndOffset)) {
return ERR_INFO_INVALID_ACCESS;
}
pBitString->uiCurBits = GetValue4Bytes (pBitString->pCurBuf);
pBitString->pCurBuf += 4;
pBitString->iLeftBits = -16;
return ERR_NONE;
}
/*!
@ -60,23 +65,24 @@ void InitReadBits (PBitStringAux pBitString) {
* \param kpBuf bit-stream buffer
* \param kiSize size in bits for decoder; size in bytes for encoder
*
* \return size of buffer data in byte; failed in -1 return
* \return 0: success, other: fail
*/
int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t kiSize) {
const int32_t kiSizeBuf = (kiSize + 7) >> 3;
uint8_t* pTmp = (uint8_t*)kpBuf;
if (NULL == pTmp)
return -1;
return ERR_INFO_INVALID_ACCESS;
pBitString->pStartBuf = pTmp; // buffer to start position
pBitString->pEndBuf = pTmp + kiSizeBuf; // buffer + length
pBitString->iBits = kiSize; // count bits of overall bitstreaming inputindex;
pBitString->pCurBuf = pBitString->pStartBuf;
InitReadBits (pBitString);
return kiSizeBuf;
int32_t iErr = InitReadBits (pBitString, 0);
if(iErr) {
return iErr;
}
return ERR_NONE;
}
} // namespace WelsDec

View File

@ -0,0 +1,330 @@
/*!
* \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 initialization
void 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 initialization
int32_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 decoding
int32_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;
int64_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;
}
}
}

View File

@ -44,6 +44,7 @@
#include "decode_slice.h"
#include "parse_mb_syn_cavlc.h"
#include "parse_mb_syn_cabac.h"
#include "rec_mb.h"
#include "mv_pred.h"
@ -318,6 +319,576 @@ void WelsChromaDcIdct (int16_t* pBlock) {
pBlk[iStride1] = (iE - iB) >> 1;
}
void WelsMap4x4NeighToSampleNormal (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail) { //left
pSampleAvail[ 6] =
pSampleAvail[12] =
pSampleAvail[18] =
pSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail) { //top_left
pSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail) { //top
pSampleAvail[1] =
pSampleAvail[2] =
pSampleAvail[3] =
pSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail) { //top_right
pSampleAvail[5] = 1;
}
}
void WelsMap4x4NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) { //left
pSampleAvail[ 6] =
pSampleAvail[12] =
pSampleAvail[18] =
pSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) { //top_left
pSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) { //top
pSampleAvail[1] =
pSampleAvail[2] =
pSampleAvail[3] =
pSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail && IS_INTRA (pNeighAvail->iRightTopType)) { //top_right
pSampleAvail[5] = 1;
}
}
void WelsMap16x16NeighToSampleNormal (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail) {
*pSampleAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail) {
*pSampleAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail) {
*pSampleAvail |= 1;
}
}
void WelsMap16x16NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {
*pSampleAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {
*pSampleAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {
*pSampleAvail |= 1;
}
}
int32_t ParseIntra4x4Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t* pIntraPredMode,
PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiCode;
int32_t iCode;
pCtx->pMap4x4NeighToSampleFunc (pNeighAvail, iSampleAvail);
uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
for (i = 0; i < 16; i++) {
int32_t iPrevIntra4x4PredMode = 0;
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
WELS_READ_VERIFY (ParseIntraPredModeLumaCabac (pCtx, iCode));
iPrevIntra4x4PredMode = iCode;
} else {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
iPrevIntra4x4PredMode = uiCode;
}
const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
int8_t iBestMode;
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
if (iPrevIntra4x4PredMode == -1)
iBestMode = kiPredMode;
else
iBestMode = iPrevIntra4x4PredMode + (iPrevIntra4x4PredMode >= kiPredMode);
} else {
if (iPrevIntra4x4PredMode) {
iBestMode = kiPredMode;
} else {
WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode));
iBestMode = uiCode + (uiCode >= kiPredMode);
}
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
pIntraPredMode[g_kuiScan8[i]] = iBestMode;
iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
}
ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));
if (iCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = iCode;
} else {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
}
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return ERR_NONE;
}
int32_t ParseIntra16x16Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiCode;
int32_t iCode;
pCtx->pMap16x16NeighToSampleFunc (pNeighAvail, &uiNeighAvail);
if (CheckIntra16x16PredMode (uiNeighAvail,
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {
WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));
if (iCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = iCode;
} else {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
}
if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]
|| CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return ERR_NONE;
}
int32_t WelsDecodeMbCabacISliceBaseMode0 (PWelsDecoderContext pCtx, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBsAux = pCurLayer->pBitStringAux;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
SWelsNeighAvail sNeighAvail;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t iMbMode, i;
uint32_t uiMbType = 0, uiCbp = 0, uiCbpLuma = 0, uiCbpChroma = 0;
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag;
GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
WELS_READ_VERIFY (ParseMBTypeISliceCabac (pCtx, &sNeighAvail, uiMbType));
if (uiMbType > 25) {
return ERR_INFO_INVALID_MB_TYPE;
} else if (25 == uiMbType) { //I_PCM
WELS_READ_VERIFY (ParseIPCMInfoCabac (pCtx));
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
} else if (0 == uiMbType) { //I4x4
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBsAux, pCurLayer));
//get uiCbp for I4x4
WELS_READ_VERIFY (ParseCbpInfoCabac (pCtx, &sNeighAvail, uiCbp));
pCurLayer->pCbp[iMbXy] = uiCbp;
uiCbpChroma = uiCbp >> 4;
uiCbpLuma = uiCbp & 15;
} else { //I16x16;
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA16x16;
pCurLayer->pIntraPredMode[iMbXy][7] = (uiMbType - 1) & 3;
pCurLayer->pCbp[iMbXy] = g_kuiI16CbpTable[ (uiMbType - 1) >> 2];
uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBsAux, pCurLayer));
}
iMbMode = BASE_MB;
memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (pCurLayer->pScaledTCoeff[iMbXy][0]));
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
pCurLayer->pCbfDc[iMbXy] = 0;
if (pCurLayer->pCbp[iMbXy] == 0 && IS_INTRA4x4 (pCurLayer->pMbType[iMbXy])) {
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 ((pCurLayer->pLumaQp[iMbXy] +
pSliceHeader->pPps->iChromaQpIndexOffset), 0, 51)];
}
if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
int32_t iQpDelta, iId8x8, iId4x4;
WELS_READ_VERIFY (ParseDeltaQpCabac (pCtx, iQpDelta));
if (iQpDelta > 25 || iQpDelta < -26) {//out of iQpDelta range
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 ((pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset), 0, 51)];
if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
//step1: Luma DC
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 0, 16, g_kuiLumaDcZigzagScan,
I16_LUMA_DC, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy], pCtx));
//step2: Luma AC
if (uiCbpLuma) {
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, i,
iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), I16_LUMA_AC,
pCurLayer->pScaledTCoeff[iMbXy] + (i << 4), pCurLayer->pLumaQp[iMbXy], pCtx));
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
} else { //pNonZeroCount = 0
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
}
} else { //non-MB_TYPE_INTRA16x16
for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
if (uiCbpLuma & (1 << iId8x8)) {
int32_t iIdx = (iId8x8 << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
//Luma (DC and AC decoding together)
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, iIdx, iScanIdxEnd - iScanIdxStart + 1,
g_kuiZigzagScan + iScanIdxStart, LUMA_DC_AC, pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pLumaQp[iMbXy],
pCtx));
iIdx++;
}
} else {
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2)]], 0);
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2) + 2]], 0);
}
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
}
//chroma
//step1: DC
if (1 == uiCbpChroma || 2 == uiCbpChroma) {
//Cb Cr
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 16 + (0 << 2), 4, g_kuiChromaDcScan,
CHROMA_DC_V, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (0 << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, 16 + (1 << 2), 4, g_kuiChromaDcScan,
CHROMA_DC_U, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (1 << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
}
//step2: AC
if (2 == uiCbpChroma) {
for (i = 0; i < 2; i++) { //Cb Cr
int32_t iResProperty = i ? CHROMA_AC_V : CHROMA_AC_U;
int32_t iIdx = 16 + (i << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (&sNeighAvail, pNonZeroCount, pBsAux, iIdx,
iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), iResProperty,
pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
iIdx++;
}
}
ST16 (&pCurLayer->pNzc[iMbXy][16], LD16 (&pNonZeroCount[6 + 8 * 1]));
ST16 (&pCurLayer->pNzc[iMbXy][20], LD16 (&pNonZeroCount[6 + 8 * 2]));
ST16 (&pCurLayer->pNzc[iMbXy][18], LD16 (&pNonZeroCount[6 + 8 * 4]));
ST16 (&pCurLayer->pNzc[iMbXy][22], LD16 (&pNonZeroCount[6 + 8 * 5]));
} else {
ST16 (&pCurLayer->pNzc[iMbXy][16], 0);
ST16 (&pCurLayer->pNzc[iMbXy][20], 0);
ST16 (&pCurLayer->pNzc[iMbXy][18], 0);
ST16 (&pCurLayer->pNzc[iMbXy][22], 0);
}
} else {
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
}
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
}
int32_t WelsDecodeMbCabacISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
WELS_READ_VERIFY (WelsDecodeMbCabacISliceBaseMode0 (pCtx, uiEosFlag));
return ERR_NONE;
}
int32_t WelsDecodeMbCabacPSliceBaseMode0 (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBsAux = pCurLayer->pBitStringAux;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t iMbMode, i;
uint32_t uiMbType = 0, uiCbp = 0, uiCbpLuma = 0, uiCbpChroma = 0;
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
WELS_READ_VERIFY (ParseMBTypePSliceCabac (pCtx, pNeighAvail, uiMbType));
// uiMbType = 4 is not allowded.
if (uiMbType < 4) { //Inter mode
int16_t pMotionVector[LIST_A][30][MV_A];
int16_t pMvdCache[LIST_A][30][MV_A];
int8_t pRefIndex[LIST_A][30];
pCurLayer->pMbType[iMbXy] = g_ksInterMbTypeInfo[uiMbType].iType;
WelsFillCacheInterCabac (pNeighAvail, pNonZeroCount, pMotionVector, pMvdCache, pRefIndex, pCurLayer);
WELS_READ_VERIFY (ParseInterMotionInfoCabac (pCtx, pNeighAvail, pNonZeroCount, pMotionVector, pMvdCache, pRefIndex));
iMbMode = BASE_MB;
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
} else { //Intra mode
uiMbType -= 5;
if (uiMbType > 25) {
return ERR_INFO_INVALID_MB_TYPE;
}
if (25 == uiMbType) { //I_PCM
WELS_READ_VERIFY (ParseIPCMInfoCabac (pCtx));
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
} else { //normal Intra mode
if (0 == uiMbType) { //Intra4x4
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (pNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, pNeighAvail, pIntraPredMode, pBsAux, pCurLayer));
} else { //Intra16x16
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA16x16;
pCurLayer->pIntraPredMode[iMbXy][7] = (uiMbType - 1) & 3;
pCurLayer->pCbp[iMbXy] = g_kuiI16CbpTable[ (uiMbType - 1) >> 2];
uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (pNeighAvail, pNonZeroCount, pCurLayer);
WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, pNeighAvail, pBsAux, pCurLayer));
}
iMbMode = BASE_MB;
}
}
if (MB_TYPE_INTRA16x16 != pCurLayer->pMbType[iMbXy]) {
WELS_READ_VERIFY (ParseCbpInfoCabac (pCtx, pNeighAvail, uiCbp));
pCurLayer->pCbp[iMbXy] = uiCbp;
uiCbpChroma = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpLuma = pCurLayer->pCbp[iMbXy] & 15;
}
pCtx->sBlockFunc.pWelsBlockZero16x16Func (pCurLayer->pScaledTCoeff[iMbXy], 16);
pCtx->sBlockFunc.pWelsBlockZero8x8Func (pCurLayer->pScaledTCoeff[iMbXy] + 256, 8);
pCtx->sBlockFunc.pWelsBlockZero8x8Func (pCurLayer->pScaledTCoeff[iMbXy] + 256 + 64, 8);
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
if (pCurLayer->pCbp[iMbXy] || MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
int32_t iQpDelta, iId8x8, iId4x4;
WELS_READ_VERIFY (ParseDeltaQpCabac (pCtx, iQpDelta));
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
if (MB_TYPE_INTRA16x16 == pCurLayer->pMbType[iMbXy]) {
//step1: Luma DC
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, 0, 16, g_kuiLumaDcZigzagScan,
I16_LUMA_DC, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy], pCtx));
//step2: Luma AC
if (uiCbpLuma) {
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, i, iScanIdxEnd - WELS_MAX (iScanIdxStart,
1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1), I16_LUMA_AC, pCurLayer->pScaledTCoeff[iMbXy] + (i << 4),
pCurLayer->pLumaQp[iMbXy], pCtx));
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
} else {
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
}
} else { //non-MB_TYPE_INTRA16x16
for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
if (uiCbpLuma & (1 << iId8x8)) {
int32_t iIdx = (iId8x8 << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
//Luma (DC and AC decoding together)
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, iIdx, iScanIdxEnd - iScanIdxStart + 1,
g_kuiZigzagScan + iScanIdxStart, LUMA_DC_AC, pCurLayer->pScaledTCoeff[iMbXy] + (iIdx << 4), pCurLayer->pLumaQp[iMbXy],
pCtx));
iIdx++;
}
} else {
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[iId8x8 << 2]], 0);
ST16 (&pNonZeroCount[g_kCacheNzcScanIdx[ (iId8x8 << 2) + 2]], 0);
}
}
ST32 (&pCurLayer->pNzc[iMbXy][0], LD32 (&pNonZeroCount[1 + 8 * 1]));
ST32 (&pCurLayer->pNzc[iMbXy][4], LD32 (&pNonZeroCount[1 + 8 * 2]));
ST32 (&pCurLayer->pNzc[iMbXy][8], LD32 (&pNonZeroCount[1 + 8 * 3]));
ST32 (&pCurLayer->pNzc[iMbXy][12], LD32 (&pNonZeroCount[1 + 8 * 4]));
}
//chroma
//step1: DC
if (1 == uiCbpChroma || 2 == uiCbpChroma) {
for (i = 0; i < 2; i++) {
int32_t iResProperty = i ? CHROMA_DC_V : CHROMA_DC_U;
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, 16 + (i << 2), 4, g_kuiChromaDcScan,
iResProperty, pCurLayer->pScaledTCoeff[iMbXy] + 256 + (i << 6), pCurLayer->pChromaQp[iMbXy], pCtx));
}
}
//step2: AC
if (2 == uiCbpChroma) {
for (i = 0; i < 2; i++) {
int32_t iResProperty = i ? CHROMA_AC_V : CHROMA_AC_U;
int32_t index = 16 + (i << 2);
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
WELS_READ_VERIFY (ParseResidualBlockCabac (pNeighAvail, pNonZeroCount, pBsAux, index,
iScanIdxEnd - WELS_MAX (iScanIdxStart, 1) + 1, g_kuiZigzagScan + WELS_MAX (iScanIdxStart, 1),
iResProperty, pCurLayer->pScaledTCoeff[iMbXy] + (index << 4), pCurLayer->pChromaQp[iMbXy], pCtx));
index++;
}
}
ST16 (&pCurLayer->pNzc[iMbXy][16], LD16 (&pNonZeroCount[6 + 8 * 1]));
ST16 (&pCurLayer->pNzc[iMbXy][20], LD16 (&pNonZeroCount[6 + 8 * 2]));
ST16 (&pCurLayer->pNzc[iMbXy][18], LD16 (&pNonZeroCount[6 + 8 * 4]));
ST16 (&pCurLayer->pNzc[iMbXy][22], LD16 (&pNonZeroCount[6 + 8 * 5]));
} else {
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
}
} else {
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp;
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
}
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
if (uiEosFlag) {
RestoreCabacDecEngineToBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux);
}
return ERR_NONE;
}
int32_t WelsDecodeMbCabacPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
uint32_t uiCode;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t i;
SWelsNeighAvail uiNeighAvail;
pCurLayer->pCbp[iMbXy] = 0;
pCurLayer->pCbfDc[iMbXy] = 0;
pCurLayer->pChromaPredMode[iMbXy] = C_PRED_DC;
GetNeighborAvailMbType (&uiNeighAvail, pCurLayer);
WELS_READ_VERIFY (ParseSkipFlagCabac (pCtx, &uiNeighAvail, uiCode));
if (uiCode) {
int16_t pMv[2] = {0};
pCurLayer->pMbType[iMbXy] = MB_TYPE_SKIP;
ST32 (&pCurLayer->pNzc[iMbXy][0], 0);
ST32 (&pCurLayer->pNzc[iMbXy][4], 0);
ST32 (&pCurLayer->pNzc[iMbXy][8], 0);
ST32 (&pCurLayer->pNzc[iMbXy][12], 0);
ST32 (&pCurLayer->pNzc[iMbXy][16], 0);
ST32 (&pCurLayer->pNzc[iMbXy][20], 0);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
memset (pCurLayer->pRefIndex[0][iMbXy], 0, sizeof (int8_t) * 16);
//predict mv
PredPSkipMvFromNeighbor (pCurLayer, pMv);
for (i = 0; i < 16; i++) {
ST32 (pCurLayer->pMv[0][iMbXy][i], * (uint32_t*)pMv);
ST32 (pCurLayer->pMvd[0][iMbXy][i], 0);
}
if (!pSlice->sSliceHeaderExt.bDefaultResidualPredFlag) {
memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (int16_t));
}
//reset rS
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp; //??????????????? dqaunt of previous mb
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pCurLayer->pLumaQp[iMbXy] +
pSliceHeader->pPps->iChromaQpIndexOffset, 0, 51)];
//for neighboring CABAC usage
pSlice->iLastDeltaQp = 0;
WELS_READ_VERIFY (ParseEndOfSliceCabac (pCtx, uiEosFlag));
return ERR_NONE;
}
WELS_READ_VERIFY (WelsDecodeMbCabacPSliceBaseMode0 (pCtx, &uiNeighAvail, uiEosFlag));
return ERR_NONE;
}
int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PFmo pFmo = pCtx->pFmo;
@ -329,34 +900,50 @@ int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNal
PSliceHeader pSliceHeader = &pSliceHeaderExt->sSliceHeader;
int32_t iMbX, iMbY;
const int32_t kiCountNumMb = pSliceHeader->pSps->uiTotalMbCount; //need to be correct when fmo or multi slice
PBitStringAux pBs = pCurLayer->pBitStringAux;
intX_t iUsedBits = 0;
PWelsDecMbCavlcFunc pDecMbCavlcFunc;
uint32_t uiEosFlag = 0;
PWelsDecMbFunc pDecMbFunc;
pSlice->iTotalMbInCurSlice = 0; //initialize at the starting of slice decoding.
if (P_SLICE == pSliceHeader->eSliceType) {
pDecMbCavlcFunc = WelsDecodeMbCavlcPSlice;
} else { //I_SLICE
pDecMbCavlcFunc = WelsDecodeMbCavlcISlice;
if (pCtx->pPps->bEntropyCodingModeFlag) {
if (pSlice->sSliceHeaderExt.bAdaptiveMotionPredFlag ||
pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag ||
pSlice->sSliceHeaderExt.bAdaptiveResidualPredFlag) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
"WelsDecodeSlice()::::ILP flag exist, not supported with CABAC enabled!");
pCtx->iErrorCode |= dsBitstreamError;
return dsBitstreamError;
}
if (P_SLICE == pSliceHeader->eSliceType)
pDecMbFunc = WelsDecodeMbCabacPSlice;
else //I_SLICE. B_SLICE not supported now
pDecMbFunc = WelsDecodeMbCabacISlice;
} else {
if (P_SLICE == pSliceHeader->eSliceType) {
pDecMbFunc = WelsDecodeMbCavlcPSlice;
} else { //I_SLICE
pDecMbFunc = WelsDecodeMbCavlcISlice;
}
}
if (pSliceHeader->pPps->bConstainedIntraPredFlag) {
pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain1Intra4x4;
pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain1;
pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain1;
pCtx->pMap4x4NeighToSampleFunc = WelsMap4x4NeighToSampleConstrain1;
pCtx->pMap16x16NeighToSampleFunc = WelsMap16x16NeighToSampleConstrain1;
} else {
pCtx->pFillInfoCacheIntra4x4Func = WelsFillCacheConstrain0Intra4x4;
pCtx->pParseIntra4x4ModeFunc = ParseIntra4x4ModeConstrain0;
pCtx->pParseIntra16x16ModeFunc = ParseIntra16x16ModeConstrain0;
pCtx->pMap4x4NeighToSampleFunc = WelsMap4x4NeighToSampleNormal;
pCtx->pMap16x16NeighToSampleFunc = WelsMap16x16NeighToSampleNormal;
}
pCtx->eSliceType = pSliceHeader->eSliceType;
if (pCurLayer->sLayerInfo.pPps->bEntropyCodingModeFlag == 1) {
//CABAC encoding is unsupported yet!
return -1;
int32_t iQp = pSlice->sSliceHeaderExt.sSliceHeader.iSliceQp;
int32_t iCabacInitIdc = pSlice->sSliceHeaderExt.sSliceHeader.iCabacInitIdc;
WelsCabacContextInit (pCtx, pSlice->eSliceType, iCabacInitIdc, iQp);
//InitCabacCtx (pCtx->pCabacCtx, pSlice->eSliceType, iCabacInitIdc, iQp);
pSlice->iLastDeltaQp = 0;
WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCtx->pCabacDecEngine, pCtx->pCurDqLayer->pBitStringAux));
}
iNextMbXyIndex = pSliceHeader->iFirstMbInSlice;
@ -398,31 +985,21 @@ int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNal
}
pCurLayer->pSliceIdc[iNextMbXyIndex] = iSliceIdc;
iRet = pDecMbCavlcFunc (pCtx, pNalCur);
iRet = pDecMbFunc (pCtx, pNalCur, uiEosFlag);
if (iRet != ERR_NONE) {
return iRet;
}
++pSlice->iTotalMbInCurSlice;
if (uiEosFlag) { //end of slice
break;
}
if (pSliceHeader->pPps->uiNumSliceGroups > 1) {
iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex);
} else {
++iNextMbXyIndex;
}
// check whether there is left bits to read next time in case multiple slices
iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
if (iUsedBits == pBs->iBits && 0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun) { // slice boundary
break;
}
if (iUsedBits > pBs->iBits) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"WelsDecodeSlice()::::pBs incomplete, iUsedBits:%" PRId64" > pBs->iBits:%d, MUST stop decoding.",
(int64_t) iUsedBits, pBs->iBits);
return -1;
}
iMbX = iNextMbXyIndex % pCurLayer->iMbWidth;
iMbY = iNextMbXyIndex / pCurLayer->iMbWidth;
pCurLayer->iMbX = iMbX;
@ -440,7 +1017,7 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
SNeighAvail sNeighAvail;
SWelsNeighAvail sNeighAvail;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
@ -455,11 +1032,11 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
int32_t iCode;
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;
pCurLayer->pResidualPredFlag[iMbXy] = pSlice->sSliceHeaderExt.bDefaultResidualPredFlag;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //mb_type
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //uiMbType
uiMbType = uiCode;
if (uiMbType > 25) {
return ERR_INFO_INVALID_MB_TYPE;
@ -508,20 +1085,18 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
}
pBs->pCurBuf += 384;
InitReadBits (pBs);
//step 3: update QP and pNonZeroCount
pCurLayer->pLumaQp[iMbXy] = 0;
pCurLayer->pChromaQp[iMbXy] = 0;
memset (pNzc, 16, sizeof (pCurLayer->pNzc[iMbXy])); //Rec. 9.2.1 for PCM, nzc=16
WELS_READ_VERIFY(InitReadBits (pBs, 0));
return 0;
} else if (0 == uiMbType) { //reference to JM
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
if (pCtx->pParseIntra4x4ModeFunc (&sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
return -1;
}
WELS_READ_VERIFY (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBs, pCurLayer));
//uiCbp
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //coded_block_pattern
@ -542,9 +1117,7 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
uiCbpC = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpL = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
if (pCtx->pParseIntra16x16ModeFunc (&sNeighAvail, pBs, pCurLayer)) {
return -1;
}
WELS_READ_VERIFY (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBs, pCurLayer));
}
memset (pCurLayer->pScaledTCoeff[iMbXy], 0, 384 * sizeof (pCurLayer->pScaledTCoeff[iMbXy][0]));
@ -572,19 +1145,7 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp + iQpDelta; //update iLastMbQp
//refer to JVT-X201wcm1.doc equation(7-35)
if ((unsigned) (pCurLayer->pLumaQp[iMbXy]) > 51) {
if (pCurLayer->pLumaQp[iMbXy] < 0) {
pCurLayer->pLumaQp[iMbXy] += 52;
} else {
pCurLayer->pLumaQp[iMbXy] -= 52;
}
}
//QP should be in the range of [0, 51]
if (pCurLayer->pLumaQp[iMbXy] < 0 || pCurLayer->pLumaQp[iMbXy] > 51) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset, 0,
@ -673,14 +1234,14 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
return 0;
}
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBs = pCurLayer->pBitStringAux;
PSliceHeaderExt pSliceHeaderExt = &pCurLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt;
int32_t iBaseModeFlag;
int32_t iRet = 0; //should have the return value to indicate decoding error or not, It's NECESSARY--2010.4.15
uint32_t uiCode;
intX_t iUsedBits;
if (pSliceHeaderExt->bAdaptiveBaseModeFlag == 1) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
iBaseModeFlag = uiCode;
@ -698,6 +1259,19 @@ int32_t WelsDecodeMbCavlcISlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
return iRet;
}
// check whether there is left bits to read next time in case multiple slices
iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
// sub 1, for stop bit
if ((iUsedBits == (pBs->iBits - 1)) && (0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun)) { // slice boundary
uiEosFlag = 1;
}
if (iUsedBits > (pBs->iBits -
1)) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"WelsDecodeMbCavlcISlice()::::pBs incomplete, iUsedBits:%"PRId64" > pBs->iBits:%d, MUST stop decoding.",
(int64_t) iUsedBits, pBs->iBits);
return -1;
}
return 0;
}
@ -708,11 +1282,10 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
SNeighAvail sNeighAvail;
int32_t iScanIdxStart = pSlice->sSliceHeaderExt.uiScanIdxStart;
int32_t iScanIdxEnd = pSlice->sSliceHeaderExt.uiScanIdxEnd;
SWelsNeighAvail sNeighAvail;
int32_t iMbX = pCurLayer->iMbX;
int32_t iMbY = pCurLayer->iMbY;
const int32_t iMbXy = pCurLayer->iMbXyIndex;
@ -721,15 +1294,13 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
uint32_t uiMbType = 0, uiCbp = 0, uiCbpL = 0, uiCbpC = 0;
uint32_t uiCode;
int32_t iCode;
GetNeighborAvailMbType (&sNeighAvail, pCurLayer);
ENFORCE_STACK_ALIGN_1D (uint8_t, pNonZeroCount, 48, 16);
pCurLayer->pInterPredictionDoneFlag[iMbXy] = 0;//2009.10.23
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //mb_type
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //uiMbType
uiMbType = uiCode;
if (uiMbType < 5) { //inter MB type
int16_t iMotionVector[LIST_A][30][MV_A];
int8_t iRefIndex[LIST_A][30];
pCurLayer->pMbType[iMbXy] = g_ksInterMbTypeInfo[uiMbType].iType;
WelsFillCacheInter (&sNeighAvail, pNonZeroCount, iMotionVector, iRefIndex, pCurLayer);
@ -800,7 +1371,6 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
}
pBs->pCurBuf += 384;
InitReadBits (pBs);
//step 3: update QP and pNonZeroCount
pCurLayer->pLumaQp[iMbXy] = 0;
@ -812,13 +1382,14 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
ST32A4 (&pNzc[12], 0x10101010);
ST32A4 (&pNzc[16], 0x10101010);
ST32A4 (&pNzc[20], 0x10101010);
WELS_READ_VERIFY (InitReadBits (pBs, 0));
return 0;
} else {
if (0 == uiMbType) {
ENFORCE_STACK_ALIGN_1D (int8_t, pIntraPredMode, 48, 16);
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA4x4;
pCtx->pFillInfoCacheIntra4x4Func (&sNeighAvail, pNonZeroCount, pIntraPredMode, pCurLayer);
if (pCtx->pParseIntra4x4ModeFunc (&sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
if (ParseIntra4x4Mode (pCtx, &sNeighAvail, pIntraPredMode, pBs, pCurLayer)) {
return -1;
}
} else { //I_PCM exclude, we can ignore it
@ -828,7 +1399,7 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
uiCbpC = pCurLayer->pCbp[iMbXy] >> 4;
uiCbpL = pCurLayer->pCbp[iMbXy] & 15;
WelsFillCacheNonZeroCount (&sNeighAvail, pNonZeroCount, pCurLayer);
if (pCtx->pParseIntra16x16ModeFunc (&sNeighAvail, pBs, pCurLayer)) {
if (ParseIntra16x16Mode (pCtx, &sNeighAvail, pBs, pCurLayer)) {
return -1;
}
}
@ -877,19 +1448,7 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = pSlice->iLastMbQp + iQpDelta; //update iLastMbQp
//refer to JVT-X201wcm1.doc equation(7-35)
if ((unsigned) (pCurLayer->pLumaQp[iMbXy]) > 51) {
if (pCurLayer->pLumaQp[iMbXy] < 0) {
pCurLayer->pLumaQp[iMbXy] += 52;
} else {
pCurLayer->pLumaQp[iMbXy] -= 52;
}
}
//QP should be in the range of [0, 51]
if (pCurLayer->pLumaQp[iMbXy] < 0 || pCurLayer->pLumaQp[iMbXy] > 51) {
return ERR_INFO_INVALID_QP;
}
pCurLayer->pLumaQp[iMbXy] = (pSlice->iLastMbQp + iQpDelta + 52) % 52; //update last_mb_qp
pSlice->iLastMbQp = pCurLayer->pLumaQp[iMbXy];
pCurLayer->pChromaQp[iMbXy] = g_kuiChromaQpTable[WELS_CLIP3 (pSlice->iLastMbQp +
pSliceHeader->pPps->iChromaQpIndexOffset, 0,
@ -978,12 +1537,12 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
return 0;
}
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur, uint32_t& uiEosFlag) {
PDqLayer pCurLayer = pCtx->pCurDqLayer;
PBitStringAux pBs = pCurLayer->pBitStringAux;
PSlice pSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
intX_t iUsedBits;
const int32_t iMbXy = pCurLayer->iMbXyIndex;
int8_t* pNzc = pCurLayer->pNzc[iMbXy];
int32_t iBaseModeFlag, i;
@ -996,7 +1555,6 @@ int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
if (-1 == pSlice->iMbSkipRun) {
return -1;
}
}
if (pSlice->iMbSkipRun--) {
int16_t iMv[2];
@ -1031,27 +1589,37 @@ int32_t WelsDecodeMbCavlcPSlice (PWelsDecoderContext pCtx, PNalUnit pNalCur) {
}
pCurLayer->pCbp[iMbXy] = 0;
return 0;
}
if (pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag == 1) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
iBaseModeFlag = uiCode;
} else {
iBaseModeFlag = pSlice->sSliceHeaderExt.bDefaultBaseModeFlag;
if (pSlice->sSliceHeaderExt.bAdaptiveBaseModeFlag == 1) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //base_mode_flag
iBaseModeFlag = uiCode;
} else {
iBaseModeFlag = pSlice->sSliceHeaderExt.bDefaultBaseModeFlag;
}
if (!iBaseModeFlag) {
iRet = WelsActualDecodeMbCavlcPSlice (pCtx);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "iBaseModeFlag (%d) != 0, inter-layer prediction not supported.",
iBaseModeFlag);
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP);
}
if (iRet) { //occur error when parsing, MUST STOP decoding
return iRet;
}
}
if (!iBaseModeFlag) {
iRet = WelsActualDecodeMbCavlcPSlice (pCtx);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "iBaseModeFlag (%d) != 0, inter-layer prediction not supported.",
iBaseModeFlag);
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_ILP);
// check whether there is left bits to read next time in case multiple slices
iUsedBits = ((pBs->pCurBuf - pBs->pStartBuf) << 3) - (16 - pBs->iLeftBits);
// sub 1, for stop bit
if ((iUsedBits == (pBs->iBits - 1)) && (0 >= pCurLayer->sLayerInfo.sSliceInLayer.iMbSkipRun)) { // slice boundary
uiEosFlag = 1;
}
if (iRet) { //occur error when parsing, MUST STOP decoding
return iRet;
if (iUsedBits > (pBs->iBits -
1)) { //When BS incomplete, as long as find it, SHOULD stop decoding to avoid mosaic or crash.
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"WelsDecodeMbCavlcISlice()::::pBs incomplete, iUsedBits:%"PRId64" > pBs->iBits:%d, MUST stop decoding.",
(int64_t) iUsedBits, pBs->iBits);
return -1;
}
return 0;
}
@ -1069,6 +1637,21 @@ void WelsBlockFuncInit (SBlockFunc* pFunc, int32_t iCpu) {
pFunc->pWelsSetNonZeroCountFunc = SetNonZeroCount_AArch64_neon;
}
#endif
pFunc->pWelsBlockZero16x16Func = WelsBlockZero16x16_c;
pFunc->pWelsBlockZero8x8Func = WelsBlockZero8x8_c;
//TO DO add neon and X86
#ifdef HAVE_NEON
if (iCpu & WELS_CPU_NEON) {
}
#endif
#ifdef HAVE_NEON_AARCH64
if (iCpu & WELS_CPU_NEON) {
}
#endif
}
void SetNonZeroCount_c (int8_t* pNonZeroCount) {
@ -1079,4 +1662,21 @@ void SetNonZeroCount_c (int8_t* pNonZeroCount) {
}
}
void WelsBlockInit (int16_t* pBlock, int iW, int iH, int iStride, uint8_t uiVal) {
int32_t i;
int16_t* pDst = pBlock;
for (i = 0; i < iH; i++) {
memset (pDst, uiVal, iW * sizeof (int16_t));
pDst += iStride;
}
}
void WelsBlockZero16x16_c (int16_t* pBlock, int32_t iStride) {
WelsBlockInit (pBlock, 16, 16, iStride, 0);
}
void WelsBlockZero8x8_c (int16_t* pBlock, int32_t iStride) {
WelsBlockInit (pBlock, 8, 8, iStride, 0);
}
} // namespace WelsDec

View File

@ -139,7 +139,7 @@ void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
pCtx->uiCpuFlag = 0;
pCtx->bAuReadyFlag = 0; // au data is not ready
pCtx->bCabacInited = false;
pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);
@ -241,6 +241,10 @@ int32_t WelsRequestMem (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const
pCtx->bHaveGotMemory = true; // global memory for decoder context related is requested
pCtx->pDec = NULL; // need prefetch a new pic due to spatial size changed
if (pCtx->pCabacDecEngine == NULL)
pCtx->pCabacDecEngine = (SWelsCabacDecEngine*) WelsMalloc (sizeof (SWelsCabacDecEngine), "pCtx->pCabacDecEngine");
return ERR_NONE;
}
@ -267,7 +271,7 @@ void WelsFreeMem (PWelsDecoderContext pCtx) {
pCtx->iImgWidthInPixel = 0;
pCtx->iImgHeightInPixel = 0;
pCtx->bHaveGotMemory = false;
WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
}
/*!
@ -464,6 +468,7 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
} else {
iConsumedBytes = 0;
pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero
pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
@ -502,13 +507,12 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
return pCtx->iErrorCode;
}
pDstNal += iDstIdx; //update current position
pDstNal += (iDstIdx + 4); //init, increase 4 reserved zero bytes, used to store the next NAL
if ((iSrcLength - iSrcConsumed + 4) > (pRawData->pEnd - pDstNal)) {
pRawData->pCurPos = pRawData->pHead;
pDstNal = pRawData->pCurPos = pRawData->pHead;
} else {
pRawData->pCurPos = pDstNal;
}
pDstNal = pRawData->pCurPos + 4; //init, 4 bytes used to store the next NAL
pSrcNal += iSrcIdx + 3;
iSrcConsumed += 3;
@ -524,6 +528,7 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
//last NAL decoding
iConsumedBytes = 0;
pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero
pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
@ -557,8 +562,7 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
}
return pCtx->iErrorCode;
}
pDstNal += iDstIdx;
pRawData->pCurPos = pDstNal; //init the pCurPos for next NAL(s) storage
pRawData->pCurPos = pDstNal + iDstIdx + 4; //init, increase 4 reserved zero bytes, used to store the next NAL
} else { /* no supplementary picture payload input, but stored a picture */
PAccessUnit pCurAu =
pCtx->pAccessUnitList; // current access unit, it will never point to NULL after decode's successful initialization

View File

@ -707,8 +707,11 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
}
if (pPps->bEntropyCodingModeFlag) {
WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseSliceHeaderSyntaxs(): CABAC in Enhancement layer not supported.");
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_UNSUPPORTED_CABAC_EL);
if (pSliceHead->eSliceType != I_SLICE && pSliceHead->eSliceType != SI_SLICE) {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
pSliceHead->iCabacInitIdc = uiCode;
} else
pSliceHead->iCabacInitIdc = 0;
}
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); //slice_qp_delta
@ -1021,6 +1024,10 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
"pCtx->sMb.pLumaQp[]");
pCtx->sMb.pChromaQp[i] = (int8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t),
"pCtx->sMb.pChromaQp[]");
pCtx->sMb.pMvd[i][0] = (int16_t (*)[16][2])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (
int16_t) * MV_A * MB_BLOCK4x4_NUM, "pCtx->sMb.pMvd[][]");
pCtx->sMb.pCbfDc[i] = (uint8_t*)WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (uint8_t),
"pCtx->sMb.pCbfDc[]");
pCtx->sMb.pNzc[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24,
"pCtx->sMb.pNzc[]");
pCtx->sMb.pNzcRs[i] = (int8_t (*)[24])WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int8_t) * 24,
@ -1057,6 +1064,8 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
(NULL == pCtx->sMb.pRefIndex[i][0]) ||
(NULL == pCtx->sMb.pLumaQp[i]) ||
(NULL == pCtx->sMb.pChromaQp[i]) ||
(NULL == pCtx->sMb.pMvd[i][0]) ||
(NULL == pCtx->sMb.pCbfDc[i]) ||
(NULL == pCtx->sMb.pNzc[i]) ||
(NULL == pCtx->sMb.pNzcRs[i]) ||
(NULL == pCtx->sMb.pScaledTCoeff[i]) ||
@ -1076,7 +1085,6 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
++ i;
} while (i < LAYER_NUM_EXCHANGEABLE);
pCtx->bInitialDqLayersMem = true;
pCtx->iPicWidthReq = kiMaxWidth;
pCtx->iPicHeightReq = kiMaxHeight;
@ -1124,6 +1132,16 @@ void UninitialDqLayersContext (PWelsDecoderContext pCtx) {
pCtx->sMb.pChromaQp[i] = NULL;
}
if (pCtx->sMb.pMvd[i][0]) {
WelsFree (pCtx->sMb.pMvd[i][0], "pCtx->sMb.pMvd[][]");
pCtx->sMb.pMvd[i][0] = NULL;
}
if (pCtx->sMb.pCbfDc[i]) {
WelsFree (pCtx->sMb.pCbfDc[i], "pCtx->sMb.pCbfDc[]");
pCtx->sMb.pCbfDc[i] = NULL;
}
if (pCtx->sMb.pNzc[i]) {
WelsFree (pCtx->sMb.pNzc[i], "pCtx->sMb.pNzc[]");
@ -1754,6 +1772,8 @@ void InitCurDqLayerData (PWelsDecoderContext pCtx, PDqLayer pCurDq) {
pCurDq->pRefIndex[0] = pCtx->sMb.pRefIndex[0][0];
pCurDq->pLumaQp = pCtx->sMb.pLumaQp[0];
pCurDq->pChromaQp = pCtx->sMb.pChromaQp[0];
pCurDq->pMvd[0] = pCtx->sMb.pMvd[0][0];
pCurDq->pCbfDc = pCtx->sMb.pCbfDc[0];
pCurDq->pNzc = pCtx->sMb.pNzc[0];
pCurDq->pNzcRs = pCtx->sMb.pNzcRs[0];
pCurDq->pScaledTCoeff = pCtx->sMb.pScaledTCoeff[0];

View File

@ -54,6 +54,56 @@ const uint8_t g_kuiScan4[16] = { //for mb cache in sMb (only current element, wi
// extern at wels_common_basis.h
/*common use table*/
const uint8_t g_kMbNonZeroCountIdx[24] = {
// 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
0, 1, 4, 5, // 2 3 | 6 7 0 | 1 0 1 2 3
2, 3, 6, 7, //--------------- --------- 4 5 6 7
8, 9, 12, 13, // 8 9 | 12 13 2 | 3 8 9 10 11
10, 11, 14, 15, // 10 11 | 14 15-----------------------------> 12 13 14 15
16, 17, 20, 21, //---------------- chroma 8*8 block 16 17 18 19
18, 19, 22, 23 // 16 17 | 20 21 0 1 20 21 22 23
};
//cache element equal to 26
const uint8_t g_kCacheNzcScanIdx[4 * 4 + 4 + 4 + 3] = {
/* Luma */
9, 10, 17, 18, // 1+1*8, 2+1*8, 1+2*8, 2+2*8,
11, 12, 19, 20, // 3+1*8, 4+1*8, 3+2*8, 4+2*8,
25, 26, 33, 34, // 1+3*8, 2+3*8, 1+4*8, 2+4*8,
27, 28, 35, 36, // 3+3*8, 4+3*8, 3+4*8, 4+4*8,
/* Cb */
14, 15, // 6+1*8, 7+1*8,
22, 23, // 6+2*8, 7+2*8,
/* Cr */
38, 39, // 6+4*8, 7+4*8,
46, 47, // 6+5*8, 7+5*8,
/* Luma DC */
41, // 1+5*8
/* Chroma DC */
42, 43 // 2+5*8, 3+5*8,
};
const uint8_t g_kCache26ScanIdx[16] = { //intra4*4_pred_mode and pNonZeroCount cache scan index, 4*4 block as basic unit
6, 7, 11, 12,
8, 9, 13, 14,
16, 17, 21, 22,
18, 19, 23, 24
};
//cache element equal to 30
const uint8_t g_kCache30ScanIdx[16] = { //mv or pRefIndex cache scan index, 4*4 block as basic unit
7, 8, 13, 14,
9, 10, 15, 16,
19, 20, 25, 26,
21, 22, 27, 28
};
const uint8_t g_kNonZeroScanIdxC[4] = { //pNonZeroCount cache for chroma, 4*4 block as basic unit
4, 5,
7, 8
};
const uint8_t g_kuiScan8[24] = { // [16 + 2*4]
9, 10, 17, 18, // 1+1*8, 2+1*8, 1+2*8, 2+2*8,
11, 12, 19, 20, // 3+1*8, 4+1*8, 3+2*8, 4+2*8,

View File

@ -0,0 +1,909 @@
/*!
* \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: cabac parse for syntax elements
*/
#include "parse_mb_syn_cabac.h"
#include "mv_pred.h"
#include "error_code.h"
namespace WelsDec {
#define IDX_UNUSED -1
static const int16_t g_kMaxPos [] = {IDX_UNUSED, 15, 14, 15, 3, 14, 3, 3, 14, 14};
static const int16_t g_kMaxC2 [] = {IDX_UNUSED, 4, 4, 4, 3, 4, 3, 3, 4, 4};
static const int16_t g_kBlockCat2CtxOffsetCBF[] = {IDX_UNUSED, 0, 4, 8, 12, 16, 12, 12, 16, 16};
static const int16_t g_kBlockCat2CtxOffsetMap [] = {IDX_UNUSED, 0, 15, 29, 44, 47, 44, 44, 47, 47};
static const int16_t g_kBlockCat2CtxOffsetLast[] = {IDX_UNUSED, 0, 15, 29, 44, 47, 44, 44, 47, 47};
static const int16_t g_kBlockCat2CtxOffsetOne [] = {IDX_UNUSED, 0 , 10, 20, 30, 39, 30, 30, 39, 39};
static const int16_t g_kBlockCat2CtxOffsetAbs [] = {IDX_UNUSED, 0 , 10, 20, 30, 39, 30, 30, 39, 39};
const uint8_t g_kTopBlkInsideMb[24] = { //for index with z-order 0~23
// 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
0, 0, 1, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
0, 0, 1, 1, //--------------- --------- 4 5 6 7
1, 1, 1, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
0, 0, 1, 1, //---------------- chroma 8*8 block 16 17 18 19
0, 0, 1, 1 // 16 17 | 20 21 0 1 20 21 22 23
// 18 19 | 22 23
};
const uint8_t g_kLeftBlkInsideMb[24] = { //for index with z-order 0~23
// 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
0, 1, 0, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
1, 1, 1, 1, //--------------- --------- 4 5 6 7
0, 1, 0, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
0, 1, 0, 1, //---------------- chroma 8*8 block 16 17 18 19
0, 1, 0, 1 // 16 17 | 20 21 0 1 20 21 22 23
// 18 19 | 22 23
};
void UpdateP16x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
const int8_t iListIdx) {
int32_t iRef32Bit = (int32_t) iRef;
const int32_t iRef4Bytes = (iRef32Bit << 24) | (iRef32Bit << 16) | (iRef32Bit << 8) | iRef32Bit;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef4Bytes);
ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef4Bytes);
//cache
ST32 (&pRefIndex[iListIdx][iCacheIdx ], iRef4Bytes);
ST32 (&pRefIndex[iListIdx][iCacheIdx6], iRef4Bytes);
}
void UpdateP8x16RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
const int8_t iListIdx) {
int16_t iRef16Bit = (int16_t) iRef;
const int16_t iRef2Bytes = (iRef16Bit << 8) | iRef16Bit;
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 2; i++, iPartIdx += 8) {
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef2Bytes);
ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef2Bytes);
//cache
ST16 (&pRefIndex[iListIdx][iCacheIdx ], iRef2Bytes);
ST16 (&pRefIndex[iListIdx][iCacheIdx6], iRef2Bytes);
}
}
void UpdateP8x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
const int8_t iListIdx) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 1] =
pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 4] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 5] = iRef;
}
void UpdateP16x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvd[2], const int8_t iListIdx) {
int32_t pMvd32[2];
ST32 (&pMvd32[0], LD32 (pMvd));
ST32 (&pMvd32[1], LD32 (pMvd));
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 16; i += 2) {
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][i], LD64 (pMvd32));
}
}
void UpdateP16x8MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
const int8_t iListIdx) {
int32_t pMvd32[2];
ST32 (&pMvd32[0], LD32 (pMvd));
ST32 (&pMvd32[1], LD32 (pMvd));
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 2; i++, iPartIdx += 4) {
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
//cache
ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
}
}
void UpdateP8x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
const int8_t iListIdx) {
int32_t pMvd32[2];
ST32 (&pMvd32[0], LD32 (pMvd));
ST32 (&pMvd32[1], LD32 (pMvd));
int32_t i;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
for (i = 0; i < 2; i++, iPartIdx += 8) {
const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
const uint8_t iScan4Idx4 = 4 + iScan4Idx;
const uint8_t iCacheIdx6 = 6 + iCacheIdx;
//mb
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
//cache
ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
}
}
int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal) {
uiBinVal = 0;
WELS_READ_VERIFY (DecodeTerminateCabac (pCtx->pCabacDecEngine, uiBinVal));
return ERR_NONE;
}
int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip) {
uiSkip = 0;
int32_t iCtxInc = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_SKIP) + (pNeighAvail->iTopAvail
&& pNeighAvail->iTopType != MB_TYPE_SKIP);
PWelsCabacCtx pBinCtx = (pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP + iCtxInc);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx, uiSkip));
return ERR_NONE;
}
int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal) {
uint32_t uiCode;
int32_t iIdxA = 0, iIdxB = 0;
int32_t iCtxInc;
uiBinVal = 0;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MB_TYPE_I; //I mode in I slice
iIdxA = (pNeighAvail->iLeftAvail) && (pNeighAvail->iLeftType != MB_TYPE_INTRA4x4
&& pNeighAvail->iLeftType != MB_TYPE_INTRA8x8);
iIdxB = (pNeighAvail->iTopAvail) && (pNeighAvail->iTopType != MB_TYPE_INTRA4x4
&& pNeighAvail->iTopType != MB_TYPE_INTRA8x8);
iCtxInc = iIdxA + iIdxB;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
uiBinVal = uiCode;
if (uiBinVal != 0) { //I16x16
WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
if (uiCode == 1)
uiBinVal = 25; //I_PCM
else {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
uiBinVal = 1 + uiCode * 12;
//decoding of uiCbp:0,1,2
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
if (uiCode != 0) {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
uiBinVal += 4;
if (uiCode != 0)
uiBinVal += 4;
}
//decoding of I pred-mode: 0,1,2,3
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
uiBinVal += (uiCode << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
uiBinVal += uiCode;
}
}
//I4x4
return ERR_NONE;
}
int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiMbType) {
uint32_t uiCode;
uiMbType = 0;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
if (uiCode) {
// Intra MB
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
if (uiCode) { // Intra 16x16
WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
if (uiCode) {
uiMbType = 30;
return ERR_NONE;//MB_TYPE_INTRA_PCM;
}
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
uiMbType = 6 + uiCode * 12;
//uiCbp: 0,1,2
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
if (uiCode) {
uiMbType += 4;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
if (uiCode)
uiMbType += 4;
}
//IPredMode: 0,1,2,3
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
uiMbType += (uiCode << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
uiMbType += uiCode;
} else
// Intra 4x4
uiMbType = 5;
} else { // P MB
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
if (uiCode) { //second bit
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
if (uiCode)
uiMbType = 1;
else
uiMbType = 2;
} else {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
if (uiCode)
uiMbType = 3;
else
uiMbType = 0;
}
}
return ERR_NONE;
}
int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType) {
uint32_t uiCode;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SUBMB_TYPE;
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
if (uiCode)
uiSubMbType = 0;
else {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode));
if (uiCode) {
WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
uiSubMbType = 3 - uiCode;
} else {
uiSubMbType = 1;
}
}
return ERR_NONE;
}
int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal) {
uint32_t uiCode;
iBinVal = 0;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR, uiCode));
if (uiCode == 1)
iBinVal = -1;
else {
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
iBinVal |= uiCode;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
iBinVal |= (uiCode << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
iBinVal |= (uiCode << 2);
}
return ERR_NONE;
}
int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal) {
uint32_t uiCode;
int32_t iIdxA, iIdxB, iCtxInc;
int8_t* pChromaPredMode = pCtx->pCurDqLayer->pChromaPredMode;
int8_t* pMbType = pCtx->pCurDqLayer->pMbType;
int32_t iLeftAvail = uiNeighAvail & 0x04;
int32_t iTopAvail = uiNeighAvail & 0x01;
int32_t iMbXy = pCtx->pCurDqLayer->iMbXyIndex;
int32_t iMbXyTop = iMbXy - pCtx->pCurDqLayer->iMbWidth;
int32_t iMbXyLeft = iMbXy - 1;
iBinVal = 0;
iIdxB = iTopAvail && (pChromaPredMode[iMbXyTop] > 0 && pChromaPredMode[iMbXyTop] <= 3)
&& pMbType[iMbXyTop] != MB_TYPE_INTRA_PCM;
iIdxA = iLeftAvail && (pChromaPredMode[iMbXyLeft] > 0 && pChromaPredMode[iMbXyLeft] <= 3)
&& pMbType[iMbXyLeft] != MB_TYPE_INTRA_PCM;
iCtxInc = iIdxA + iIdxB;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + iCtxInc, uiCode));
iBinVal = uiCode;
if (iBinVal != 0) {
uint32_t iSym;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, iSym));
if (iSym == 0) {
iBinVal = (iSym + 1);
return ERR_NONE;
}
iSym = 0;
do {
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, uiCode));
++iSym;
} while ((uiCode != 0) && (iSym < 1));
if ((uiCode != 0) && (iSym == 1))
++ iSym;
iBinVal = (iSym + 1);
return ERR_NONE;
}
return ERR_NONE;
}
int32_t ParseInterMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]) {
PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
PPicture* ppRefPic = pCtx->sRefPic.pRefList[LIST_0];
int32_t pRefCount[2];
int32_t i, j;
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int16_t pMv[4] = {0};
int16_t pMvd[4] = {0};
int8_t iRef[2] = {0};
int32_t iPartIdx;
int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
pRefCount[0] = pSliceHeader->uiRefCount[0];
pRefCount[1] = pSliceHeader->uiRefCount[1];
switch (pCurDqLayer->pMbType[iMbXy]) {
case MB_TYPE_16x16: {
iPartIdx = 0;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
iRef[0]));
if ((iRef[0] < 0) || (iRef[0] >= pRefCount[0]) || (ppRefPic[iRef[0]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
iRef[0] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
PredMv (pMotionVector, pRefIndex, 0, 4, iRef[0], pMv);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
UpdateP16x16MotionInfo (pCurDqLayer, iRef[0], pMv);
UpdateP16x16MvdCabac (pCurDqLayer, pMvd, LIST_0);
}
break;
case MB_TYPE_16x8:
for (i = 0; i < 2; i++) {
iPartIdx = i << 3;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
iRef[i]));
if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
iRef[i] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
}
for (i = 0; i < 2; i++) {
iPartIdx = i << 3;
PredInter16x8Mv (pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
UpdateP16x8MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
UpdateP16x8MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
}
break;
case MB_TYPE_8x16:
for (i = 0; i < 2; i++) {
iPartIdx = i << 2;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iPartIdx, pRefCount[0], 0,
iRef[i]));
if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
iRef[i] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
}
for (i = 0; i < 2; i++) {
iPartIdx = i << 2;
PredInter8x16Mv (pMotionVector, pRefIndex, i << 2, iRef[i], pMv/*&mv[0], &mv[1]*/);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
UpdateP8x16MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, iPartIdx, iRef[i], pMv);
UpdateP8x16MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
}
break;
case MB_TYPE_8x8:
case MB_TYPE_8x8_REF0: {
int8_t pRefIdx[4] = {0}, pSubPartCount[4], pPartW[4];
uint32_t uiSubMbType;
//sub_mb_type, partition
for (i = 0; i < 4; i++) {
WELS_READ_VERIFY (ParseSubMBTypeCabac (pCtx, pNeighAvail, uiSubMbType));
if (uiSubMbType >= 4) { //invalid sub_mb_type
return ERR_INFO_INVALID_SUB_MB_TYPE;
}
pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterSubMbTypeInfo[uiSubMbType].iType;
pSubPartCount[i] = g_ksInterSubMbTypeInfo[uiSubMbType].iPartCount;
pPartW[i] = g_ksInterSubMbTypeInfo[uiSubMbType].iPartWidth;
}
for (i = 0; i < 4; i++) {
int16_t iIdx8 = i << 2;
WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, LIST_0, iIdx8, pRefCount[0], 1,
pRefIdx[i]));
if ((pRefIdx[i] < 0) || (pRefIdx[i] >= pRefCount[0]) || (ppRefPic[pRefIdx[i]] == NULL)) { //error ref_idx
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
pRefIdx[i] = 0;
pCtx->iErrorCode |= dsBitstreamError;
} else {
return ERR_INFO_INVALID_REF_INDEX;
}
}
UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, pRefIdx[i], LIST_0);
}
//mv
for (i = 0; i < 4; i++) {
int8_t iPartCount = pSubPartCount[i];
uiSubMbType = pCurDqLayer->pSubMbType[iMbXy][i];
int16_t iPartIdx, iBlockW = pPartW[i];
uint8_t iScan4Idx, iCacheIdx;
iCacheIdx = g_kuiCache30ScanIdx[i << 2];
pRefIndex[0][iCacheIdx ] = pRefIndex[0][iCacheIdx + 1]
= pRefIndex[0][iCacheIdx + 6] = pRefIndex[0][iCacheIdx + 7] = pRefIdx[i];
for (j = 0; j < iPartCount; j++) {
iPartIdx = (i << 2) + j * iBlockW;
iScan4Idx = g_kuiScan4[iPartIdx];
iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
PredMv (pMotionVector, pRefIndex, iPartIdx, iBlockW, pRefIdx[i], pMv);
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
pMv[0] += pMvd[0];
pMv[1] += pMvd[1];
WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
if (SUB_MB_TYPE_8x8 == uiSubMbType) {
ST32 ((pMv + 2), LD32 (pMv));
ST32 ((pMvd + 2), LD32 (pMvd));
ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx], LD64 (pMv));
ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD64 (pMv));
ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx], LD64 (pMvd));
ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD64 (pMvd));
ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
ST64 (pMotionVector[0][iCacheIdx + 6], LD64 (pMv));
ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
ST64 (pMvdCache[0][iCacheIdx + 6], LD64 (pMvd));
} else if (SUB_MB_TYPE_8x4 == uiSubMbType) {
ST32 ((pMv + 2), LD32 (pMv));
ST32 ((pMvd + 2), LD32 (pMvd));
ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD64 (pMv));
ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD64 (pMvd));
ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
} else if (SUB_MB_TYPE_4x8 == uiSubMbType) {
ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD32 (pMv));
ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD32 (pMvd));
ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
ST32 (pMotionVector[0][iCacheIdx + 6], LD32 (pMv));
ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
ST32 (pMvdCache[0][iCacheIdx + 6], LD32 (pMvd));
} else { //SUB_MB_TYPE_4x4
ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
}
}
}
}
break;
default:
break;
}
return ERR_NONE;
}
int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
int8_t ref_idx[LIST_A][30],
int32_t iListIdx, int32_t iZOrderIdx, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal) {
if (iActiveRefNum == 1) {
iRefIdxVal = 0;
return ERR_NONE;
}
uint32_t uiCode;
int32_t iIdxA = 0, iIdxB = 0;
int32_t iCtxInc;
int8_t* pRefIdxInMB = pCtx->pCurDqLayer->pRefIndex[LIST_0][pCtx->pCurDqLayer->iMbXyIndex];
if (iZOrderIdx == 0) {
iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
} else if (iZOrderIdx == 4) {
iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
} else if (iZOrderIdx == 8) {
iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
} else {
iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
}
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + iCtxInc, uiCode));
if (uiCode) {
WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + 4, 1, uiCode));
++uiCode;
}
iRefIdxVal = (int8_t) uiCode;
return ERR_NONE;
}
int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal) {
uint32_t uiCode;
int32_t iIdxA = 0;
//int32_t sym;
int32_t iCtxInc;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MVD + iMvComp * CTX_NUM_MVD;
iMvdVal = 0;
if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 6] >= 0)
iIdxA = WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 6][iMvComp]);
if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 1] >= 0)
iIdxA += WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 1][iMvComp]);
if (iIdxA < 3)
iCtxInc = 0;
else if (iIdxA > 32)
iCtxInc = 2;
else
iCtxInc = 1;
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
if (uiCode) {
WELS_READ_VERIFY (DecodeUEGMvCabac (pCtx->pCabacDecEngine, pBinCtx + 3, 3, uiCode));
iMvdVal = (int16_t) (uiCode + 1);
WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
if (uiCode) {
iMvdVal = -iMvdVal;
}
} else {
iMvdVal = 0;
}
return ERR_NONE;
}
int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiCbp) {
int32_t iIdxA = 0, iIdxB = 0, pALeftMb[2], pBTopMb[2];
uiCbp = 0;
uint32_t pCbpBit[6];
int32_t iCtxInc;
//Luma: bit by bit for 4 8x8 blocks in z-order
pBTopMb[0] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iTopCbp & (1 << 2)) == 0);
pBTopMb[1] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iTopCbp & (1 << 3)) == 0);
pALeftMb[0] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iLeftCbp & (1 << 1)) == 0);
pALeftMb[1] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
&& ((pNeighAvail->iLeftCbp & (1 << 3)) == 0);
//left_top 8x8 block
iCtxInc = pALeftMb[0] + (pBTopMb[0] << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[0]));
if (pCbpBit[0])
uiCbp += 0x01;
//right_top 8x8 block
iIdxA = !pCbpBit[0];
iCtxInc = iIdxA + (pBTopMb[1] << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[1]));
if (pCbpBit[1])
uiCbp += 0x02;
//left_bottom 8x8 block
iIdxB = !pCbpBit[0];
iCtxInc = pALeftMb[1] + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[2]));
if (pCbpBit[2])
uiCbp += 0x04;
//right_bottom 8x8 block
iIdxB = !pCbpBit[1];
iIdxA = !pCbpBit[2];
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[3]));
if (pCbpBit[3])
uiCbp += 0x08;
//Chroma: bit by bit
iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4));
iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4));
//BitIdx = 0
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + CTX_NUM_CBP + iCtxInc,
pCbpBit[4]));
//BitIdx = 1
if (pCbpBit[4]) {
iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4) == 2);
iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4) == 2);
iCtxInc = iIdxA + (iIdxB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + 2 * CTX_NUM_CBP + iCtxInc,
pCbpBit[5]));
uiCbp += 1 << (4 + pCbpBit[5]);
}
return ERR_NONE;
}
int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta) {
uint32_t uiCode;
PSlice pCurrSlice = & (pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer);
iQpDelta = 0;
PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_DELTA_QP;
int32_t iCtxInc = (pCurrSlice->iLastDeltaQp != 0);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
if (uiCode != 0) {
WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pBinCtx + 2, 1, uiCode));
uiCode++;
iQpDelta = (uiCode + 1) >> 1;
if ((uiCode & 1) == 0)
iQpDelta = - iQpDelta;
}
pCurrSlice->iLastDeltaQp = iQpDelta;
return ERR_NONE;
}
int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t iZIndex, int32_t iResProperty,
PWelsDecoderContext pCtx, uint32_t& uiCbfBit) {
int8_t nA, nB/*, zigzag_idx = 0*/;
int32_t iCurrBlkXy = pCtx->pCurDqLayer->iMbXyIndex;
int32_t iTopBlkXy = iCurrBlkXy - pCtx->pCurDqLayer->iMbWidth; //default value: MB neighboring
int32_t iLeftBlkXy = iCurrBlkXy - 1; //default value: MB neighboring
uint8_t* pCbfDc = pCtx->pCurDqLayer->pCbfDc;
int8_t* pMbType = pCtx->pCurDqLayer->pMbType;
int32_t iCtxInc;
uiCbfBit = 0;
nA = nB = IS_INTRA (pMbType[iCurrBlkXy]);
if (iResProperty == I16_LUMA_DC || iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) { //DC
if (pNeighAvail->iTopAvail)
nB = (pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iTopBlkXy] >> iResProperty) & 1);
if (pNeighAvail->iLeftAvail)
nA = (pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iLeftBlkXy] >> iResProperty) & 1);
iCtxInc = nA + (nB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
if (uiCbfBit)
pCbfDc[iCurrBlkXy] |= (1 << iResProperty);
} else { //AC
//for 4x4 blk, make sure blk-idx is correct
if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] != 0xff) { //top blk available
if (g_kTopBlkInsideMb[iZIndex])
iTopBlkXy = iCurrBlkXy;
nB = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] || pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM;
}
if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] != 0xff) { //left blk available
if (g_kLeftBlkInsideMb[iZIndex])
iLeftBlkXy = iCurrBlkXy;
nA = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] || pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM;
}
iCtxInc = nA + (nB << 1);
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
}
return ERR_NONE;
}
int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
uint32_t& uiCoeffNum) {
uint32_t uiCode;
PWelsCabacCtx pMapCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MAP + g_kBlockCat2CtxOffsetMap [iResProperty];
PWelsCabacCtx pLastCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_LAST + g_kBlockCat2CtxOffsetLast[iResProperty];
int32_t i;
uiCoeffNum = 0;
int32_t i0 = 0;
int32_t i1 = g_kMaxPos[iResProperty];
for (i = i0; i < i1; ++i) {
//read significant
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pMapCtx + i, uiCode));
if (uiCode) {
* (pSignificantMap++) = 1;
++ uiCoeffNum;
//read last significant
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pLastCtx + i, uiCode));
if (uiCode) {
memset (pSignificantMap, 0, (i1 - i) * sizeof (int32_t));
return ERR_NONE;
}
} else
* (pSignificantMap++) = 0;
}
//deal with last pSignificantMap if no data
//if(i < i1+1)
{
*pSignificantMap = 1;
++uiCoeffNum;
}
return ERR_NONE;
}
int32_t ParseSignificantCoeffCabac (int32_t* pSignificant, int32_t iResProperty, PWelsDecoderContext pCtx) {
uint32_t uiCode;
PWelsCabacCtx pOneCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_ONE + g_kBlockCat2CtxOffsetOne[iResProperty];
PWelsCabacCtx pAbsCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_ABS + g_kBlockCat2CtxOffsetAbs[iResProperty];
const int16_t iMaxType = g_kMaxC2[iResProperty];
int32_t i = g_kMaxPos[iResProperty];
int32_t* pCoff = pSignificant + i;
int32_t c1 = 1;
int32_t c2 = 0;
for (; i >= 0; --i) {
if (*pCoff != 0) {
WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pOneCtx + c1, uiCode));
*pCoff += uiCode;
if (*pCoff == 2) {
WELS_READ_VERIFY (DecodeUEGLevelCabac (pCtx->pCabacDecEngine, pAbsCtx + c2, uiCode));
*pCoff += uiCode;
++c2;
c2 = WELS_MIN (c2, iMaxType);
c1 = 0;
} else if (c1) {
++c1;
c1 = WELS_MIN (c1, 4);
}
WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
if (uiCode)
*pCoff = - *pCoff;
}
pCoff--;
}
return ERR_NONE;
}
int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
int32_t iIndex, int32_t iMaxNumCoeff,
const uint8_t* pScanTable, int32_t iResProperty, short* sTCoeff, /*int mb_mode*/ uint8_t uiQp,
PWelsDecoderContext pCtx) {
int32_t iCurNzCacheIdx;
const uint16_t* pDeQuantMul = g_kuiDequantCoeff[uiQp];
uint32_t uiTotalCoeffNum = 0;
uint32_t uiCbpBit;
int32_t pSignificantMap[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
WELS_READ_VERIFY (ParseCbfInfoCabac (pNeighAvail, pNonZeroCountCache, iIndex, iResProperty, pCtx, uiCbpBit));
if (uiCbpBit) { //has coeff
WELS_READ_VERIFY (ParseSignificantMapCabac (pSignificantMap, iResProperty, pCtx, uiTotalCoeffNum));
WELS_READ_VERIFY (ParseSignificantCoeffCabac (pSignificantMap, iResProperty, pCtx));
}
iCurNzCacheIdx = g_kCacheNzcScanIdx[iIndex];
pNonZeroCountCache[iCurNzCacheIdx] = (uint8_t)uiTotalCoeffNum;
if (uiTotalCoeffNum == 0) {
return ERR_NONE;
}
int32_t j = 0;
if (iResProperty == I16_LUMA_DC) {
do {
if (pSignificantMap[j] != 0)
sTCoeff[pScanTable[j]] = pSignificantMap[j];
++j;
} while (j < 16);
} else if (iResProperty == CHROMA_DC_U) {
do {
if (pSignificantMap[j] != 0)
sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[0];
++j;
} while (j < 16);
} else { //luma ac, chroma ac
do {
if (pSignificantMap[j] != 0)
sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[pScanTable[j] & 0x07];
++j;
} while (j < 16);
}
return ERR_NONE;
}
int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx) {
int32_t i;
PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
SBitStringAux* pBsAux = pCtx->pCurDqLayer->pBitStringAux;
SDqLayer* pCurLayer = pCtx->pCurDqLayer;
int32_t iDstStrideLuma = pCurLayer->pDec->iLinesize[0];
int32_t iDstStrideChroma = pCurLayer->pDec->iLinesize[1];
int32_t iMbX = pCurLayer->iMbX;
int32_t iMbY = pCurLayer->iMbY;
int32_t iMbXy = pCurLayer->iMbXyIndex;
int32_t iMbOffsetLuma = (iMbX + iMbY * iDstStrideLuma) << 4;
int32_t iMbOffsetChroma = (iMbX + iMbY * iDstStrideChroma) << 3;
uint8_t* pMbDstY = pCtx->pDec->pData[0] + iMbOffsetLuma;
uint8_t* pMbDstU = pCtx->pDec->pData[1] + iMbOffsetChroma;
uint8_t* pMbDstV = pCtx->pDec->pData[2] + iMbOffsetChroma;
uint8_t* pPtrSrc;
pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA_PCM;
RestoreCabacDecEngineToBS (pCabacDecEngine, pBsAux);
intX_t iBytesLeft = pBsAux->pEndBuf - pBsAux->pCurBuf;
if (iBytesLeft < 384) {
return ERR_CABAC_NO_BS_TO_READ;
}
pPtrSrc = pBsAux->pCurBuf;
for (i = 0; i < 16; i++) { //luma
memcpy (pMbDstY , pPtrSrc, 16);
pMbDstY += iDstStrideLuma;
pPtrSrc += 16;
}
for (i = 0; i < 8; i++) { //cb
memcpy (pMbDstU, pPtrSrc, 8);
pMbDstU += iDstStrideChroma;
pPtrSrc += 8;
}
for (i = 0; i < 8; i++) { //cr
memcpy (pMbDstV, pPtrSrc, 8);
pMbDstV += iDstStrideChroma;
pPtrSrc += 8;
}
pBsAux->pCurBuf += 384;
pCurLayer->pLumaQp[iMbXy] = 0;
pCurLayer->pChromaQp[iMbXy] = 0;
memset (pCurLayer->pNzc[iMbXy], 16, sizeof (pCurLayer->pNzc[iMbXy]));
//step 4: cabac engine init
WELS_READ_VERIFY (InitReadBits (pBsAux, 1));
WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCabacDecEngine, pBsAux));
return ERR_NONE;
}
}

View File

@ -45,7 +45,7 @@
namespace WelsDec {
#define MAX_LEVEL_PREFIX 15
void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
void GetNeighborAvailMbType (PWelsNeighAvail pNeighAvail, PDqLayer pCurLayer) {
int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc;
int32_t iCurXy, iTopXy = 0, iLeftXy = 0, iLeftTopXy = 0, iRightTopXy = 0;
int32_t iCurX, iCurY;
@ -58,15 +58,18 @@ void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
iLeftXy = iCurXy - 1;
iLeftSliceIdc = pCurLayer->pSliceIdc[iLeftXy];
pNeighAvail->iLeftAvail = (iLeftSliceIdc == iCurSliceIdc);
pNeighAvail->iLeftCbp = pNeighAvail->iLeftAvail ? pCurLayer->pCbp[iLeftXy] : 0;
} else {
pNeighAvail->iLeftAvail = 0;
pNeighAvail->iLeftTopAvail = 0;
pNeighAvail->iLeftCbp = 0;
}
if (iCurY != 0) {
iTopXy = iCurXy - pCurLayer->iMbWidth;
iTopSliceIdc = pCurLayer->pSliceIdc[iTopXy];
pNeighAvail->iTopAvail = (iTopSliceIdc == iCurSliceIdc);
pNeighAvail->iTopCbp = pNeighAvail->iTopAvail ? pCurLayer->pCbp[iTopXy] : 0;
if (iCurX != 0) {
iLeftTopXy = iTopXy - 1;
iLeftTopSliceIdc = pCurLayer->pSliceIdc[iLeftTopXy];
@ -85,6 +88,7 @@ void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
pNeighAvail->iTopAvail = 0;
pNeighAvail->iLeftTopAvail = 0;
pNeighAvail->iRightTopAvail = 0;
pNeighAvail->iTopCbp = 0;
}
pNeighAvail->iLeftType = (pNeighAvail->iLeftAvail ? pCurLayer->pMbType[iLeftXy] : 0);
@ -92,14 +96,11 @@ void GetNeighborAvailMbType (PNeighAvail pNeighAvail, PDqLayer pCurLayer) {
pNeighAvail->iLeftTopType = (pNeighAvail->iLeftTopAvail ? pCurLayer->pMbType[iLeftTopXy] : 0);
pNeighAvail->iRightTopType = (pNeighAvail->iRightTopAvail ? pCurLayer->pMbType[iRightTopXy] : 0);
}
void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
void WelsFillCacheNonZeroCount (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
PDqLayer pCurLayer) { //no matter slice type, intra_pred_constrained_flag
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
int32_t iLeftXy = 0;
GetNeighborAvailMbType (pNeighAvail, pCurLayer);
if (pNeighAvail->iTopAvail) {
iTopXy = iCurXy - pCurLayer->iMbWidth;
}
@ -143,7 +144,7 @@ void WelsFillCacheNonZeroCount (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
pNonZeroCount[5 + 8 * 5] = -1;//unavailable
}
}
void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void WelsFillCacheConstrain1Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer) { //no matter slice type
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
@ -189,7 +190,7 @@ void WelsFillCacheConstrain1Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZero
}
}
void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
void WelsFillCacheConstrain0Intra4x4 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int8_t* pIntraPredMode,
PDqLayer pCurLayer) { //no matter slice type
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
@ -235,8 +236,142 @@ void WelsFillCacheConstrain0Intra4x4 (PNeighAvail pNeighAvail, uint8_t* pNonZero
}
}
void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer) {
void WelsFillCacheInterCabac(PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount, int16_t iMvArray[LIST_A][30][MV_A], int16_t iMvdCache[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer)
{
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
int32_t iLeftXy = 0;
int32_t iLeftTopXy = 0;
int32_t iRightTopXy = 0;
//stuff non_zero_coeff_count from pNeighAvail(left and top)
WelsFillCacheNonZeroCount (pNeighAvail, pNonZeroCount, pCurLayer);
if (pNeighAvail->iTopAvail) {
iTopXy = iCurXy - pCurLayer->iMbWidth;
}
if (pNeighAvail->iLeftAvail) {
iLeftXy = iCurXy - 1;
}
if (pNeighAvail->iLeftTopAvail) {
iLeftTopXy = iCurXy - 1 - pCurLayer->iMbWidth;
}
if (pNeighAvail->iRightTopAvail) {
iRightTopXy = iCurXy + 1 - pCurLayer->iMbWidth;
}
//stuff mv_cache and iRefIdxArray from left and top (inter)
if (pNeighAvail->iLeftAvail && IS_INTER (pNeighAvail->iLeftType)) {
ST32 (iMvArray[0][ 6], LD32 (pCurLayer->pMv[0][iLeftXy][ 3]));
ST32 (iMvArray[0][12], LD32 (pCurLayer->pMv[0][iLeftXy][ 7]));
ST32 (iMvArray[0][18], LD32 (pCurLayer->pMv[0][iLeftXy][11]));
ST32 (iMvArray[0][24], LD32 (pCurLayer->pMv[0][iLeftXy][15]));
ST32(iMvdCache[0][ 6], LD32(pCurLayer->pMvd[0][iLeftXy][ 3]));
ST32(iMvdCache[0][12], LD32(pCurLayer->pMvd[0][iLeftXy][ 7]));
ST32(iMvdCache[0][18], LD32(pCurLayer->pMvd[0][iLeftXy][11]));
ST32(iMvdCache[0][24], LD32(pCurLayer->pMvd[0][iLeftXy][15]));
iRefIdxArray[0][ 6] = pCurLayer->pRefIndex[0][iLeftXy][ 3];
iRefIdxArray[0][12] = pCurLayer->pRefIndex[0][iLeftXy][ 7];
iRefIdxArray[0][18] = pCurLayer->pRefIndex[0][iLeftXy][11];
iRefIdxArray[0][24] = pCurLayer->pRefIndex[0][iLeftXy][15];
} else {
ST32 (iMvArray[0][ 6], 0);
ST32 (iMvArray[0][12], 0);
ST32 (iMvArray[0][18], 0);
ST32 (iMvArray[0][24], 0);
ST32(iMvdCache[0][ 6], 0);
ST32(iMvdCache[0][12], 0);
ST32(iMvdCache[0][18], 0);
ST32(iMvdCache[0][24], 0);
if (0 == pNeighAvail->iLeftAvail) { //not available
iRefIdxArray[0][ 6] =
iRefIdxArray[0][12] =
iRefIdxArray[0][18] =
iRefIdxArray[0][24] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][ 6] =
iRefIdxArray[0][12] =
iRefIdxArray[0][18] =
iRefIdxArray[0][24] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iLeftTopAvail && IS_INTER (pNeighAvail->iLeftTopType)) {
ST32 (iMvArray[0][0], LD32 (pCurLayer->pMv[0][iLeftTopXy][15]));
ST32(iMvdCache[0][0], LD32(pCurLayer->pMvd[0][iLeftTopXy][15]));
iRefIdxArray[0][0] = pCurLayer->pRefIndex[0][iLeftTopXy][15];
} else {
ST32 (iMvArray[0][0], 0);
ST32(iMvdCache[0][0], 0);
if (0 == pNeighAvail->iLeftTopAvail) { //not available
iRefIdxArray[0][0] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][0] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iTopAvail && IS_INTER (pNeighAvail->iTopType)) {
ST64 (iMvArray[0][1], LD64 (pCurLayer->pMv[0][iTopXy][12]));
ST64 (iMvArray[0][3], LD64 (pCurLayer->pMv[0][iTopXy][14]));
ST64(iMvdCache[0][1], LD64(pCurLayer->pMvd[0][iTopXy][12]));
ST64(iMvdCache[0][3], LD64(pCurLayer->pMvd[0][iTopXy][14]));
ST32 (&iRefIdxArray[0][1], LD32 (&pCurLayer->pRefIndex[0][iTopXy][12]));
} else {
ST64 (iMvArray[0][1], 0);
ST64 (iMvArray[0][3], 0);
ST64(iMvdCache[0][1], 0);
ST64(iMvdCache[0][3], 0);
if (0 == pNeighAvail->iTopAvail) { //not available
iRefIdxArray[0][1] =
iRefIdxArray[0][2] =
iRefIdxArray[0][3] =
iRefIdxArray[0][4] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][1] =
iRefIdxArray[0][2] =
iRefIdxArray[0][3] =
iRefIdxArray[0][4] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iRightTopAvail && IS_INTER (pNeighAvail->iRightTopType)) {
ST32 (iMvArray[0][5], LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
ST32(iMvdCache[0][5], LD32(pCurLayer->pMvd[0][iRightTopXy][12]));
iRefIdxArray[0][5] = pCurLayer->pRefIndex[0][iRightTopXy][12];
} else {
ST32 (iMvArray[0][5], 0);
if (0 == pNeighAvail->iRightTopAvail) { //not available
iRefIdxArray[0][5] = REF_NOT_AVAIL;
} else { //available but is intra mb type
iRefIdxArray[0][5] = REF_NOT_IN_LIST;
}
}
//right-top 4*4 block unavailable
ST32 (iMvArray[0][ 9], 0);
ST32 (iMvArray[0][21], 0);
ST32 (iMvArray[0][11], 0);
ST32 (iMvArray[0][17], 0);
ST32 (iMvArray[0][23], 0);
ST32(iMvdCache[0][ 9], 0);
ST32(iMvdCache[0][21], 0);
ST32(iMvdCache[0][11], 0);
ST32(iMvdCache[0][17], 0);
ST32(iMvdCache[0][23], 0);
iRefIdxArray[0][ 9] =
iRefIdxArray[0][21] =
iRefIdxArray[0][11] =
iRefIdxArray[0][17] =
iRefIdxArray[0][23] = REF_NOT_AVAIL;
}
void WelsFillCacheInter (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30], PDqLayer pCurLayer)
{
int32_t iCurXy = pCurLayer->iMbXyIndex;
int32_t iTopXy = 0;
int32_t iLeftXy = 0;
@ -298,7 +433,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
iRefIdxArray[0][0] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iTopAvail && IS_INTER (pNeighAvail->iTopType)) {
ST64 (iMvArray[0][1], LD64 (pCurLayer->pMv[0][iTopXy][12]));
ST64 (iMvArray[0][3], LD64 (pCurLayer->pMv[0][iTopXy][14]));
@ -306,7 +440,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
} else {
ST64 (iMvArray[0][1], 0);
ST64 (iMvArray[0][3], 0);
if (0 == pNeighAvail->iTopAvail) { //not available
iRefIdxArray[0][1] =
iRefIdxArray[0][2] =
@ -319,7 +452,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
iRefIdxArray[0][4] = REF_NOT_IN_LIST;
}
}
if (pNeighAvail->iRightTopAvail && IS_INTER (pNeighAvail->iRightTopType)) {
ST32 (iMvArray[0][5], LD32 (pCurLayer->pMv[0][iRightTopXy][12]));
iRefIdxArray[0][5] = pCurLayer->pRefIndex[0][iRightTopXy][12];
@ -331,7 +463,6 @@ void WelsFillCacheInter (PNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
iRefIdxArray[0][5] = REF_NOT_IN_LIST;
}
}
//right-top 4*4 block unavailable
ST32 (iMvArray[0][ 9], 0);
ST32 (iMvArray[0][21], 0);
@ -358,9 +489,6 @@ int32_t PredIntra4x4Mode (int8_t* pIntraPredMode, int32_t iIdx4) {
return iBestMode;
}
#define MAX_PRED_MODE_ID_I16x16 3
#define MAX_PRED_MODE_ID_CHROMA 3
#define MAX_PRED_MODE_ID_I4x4 8
#define CHECK_I16_MODE(a, b, c, d) \
((a == g_ksI16PredInfo[a].iPredMode) && \
(b >= g_ksI16PredInfo[a].iLeftAvail) && \
@ -760,216 +888,6 @@ int32_t WelsResidualBlockCavlc (SVlcTable* pVlcTable, uint8_t* pNonZeroCountCach
return 0;
}
int32_t ParseIntra4x4ModeConstrain0 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiCode;
if (pNeighAvail->iLeftAvail) { //left
iSampleAvail[ 6] =
iSampleAvail[12] =
iSampleAvail[18] =
iSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail) { //top_left
iSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail) { //top
iSampleAvail[1] =
iSampleAvail[2] =
iSampleAvail[3] =
iSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail) { //top_right
iSampleAvail[5] = 1;
}
uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ]
const int32_t kiPrevIntra4x4PredMode = uiCode;
const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
int8_t iBestMode;
if (kiPrevIntra4x4PredMode) {
iBestMode = kiPredMode;
} else { //kPrevIntra4x4PredMode == 0
WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode)); //rem_intra4x4_pred_mode[ luma4x4BlkIdx ]
const int32_t kiRemIntra4x4PredMode = uiCode;
if (kiRemIntra4x4PredMode < kiPredMode) {
iBestMode = kiRemIntra4x4PredMode;
} else {
iBestMode = kiRemIntra4x4PredMode + 1;
}
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
pIntraPredMode[g_kuiScan8[i]] = iBestMode;
iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
}
ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseIntra4x4ModeConstrain1 (PNeighAvail pNeighAvail, int8_t* pIntraPredMode, PBitStringAux pBs,
PDqLayer pCurDqLayer) {
int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
int32_t iFinalMode, i;
uint8_t uiNeighAvail = 0;
uint32_t uiCode;
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) { //left
iSampleAvail[ 6] =
iSampleAvail[12] =
iSampleAvail[18] =
iSampleAvail[24] = 1;
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) { //top_left
iSampleAvail[0] = 1;
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) { //top
iSampleAvail[1] =
iSampleAvail[2] =
iSampleAvail[3] =
iSampleAvail[4] = 1;
}
if (pNeighAvail->iRightTopAvail && IS_INTRA (pNeighAvail->iRightTopType)) { //top_right
iSampleAvail[5] = 1;
}
uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);
for (i = 0; i < 16; i++) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ]
const int32_t kiPrevIntra4x4PredMode = uiCode; //1bit
const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);
int8_t iBestMode;
if (kiPrevIntra4x4PredMode) {
iBestMode = kiPredMode;
} else { //kPrevIntra4x4PredMode == 0
WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode)); //rem_intra4x4_pred_mode[ luma4x4BlkIdx ]
const int32_t kiRemIntra4x4PredMode = uiCode;
if (kiRemIntra4x4PredMode < kiPredMode) {
iBestMode = kiRemIntra4x4PredMode;
} else {
iBestMode = kiRemIntra4x4PredMode + 1;
}
}
iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);
if (iFinalMode == ERR_INVALID_INTRA4X4_MODE) {
return ERR_INFO_INVALID_I4x4_PRED_MODE;
}
pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;
pIntraPredMode[g_kuiScan8[i]] = iBestMode;
iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;
}
ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));
pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];
pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];
pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseIntra16x16ModeConstrain0 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiCode;
if (pNeighAvail->iLeftAvail) {
uiNeighAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail) {
uiNeighAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail) {
uiNeighAvail |= 1;
}
if (CheckIntra16x16PredMode (uiNeighAvail,
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseIntra16x16ModeConstrain1 (PNeighAvail pNeighAvail, PBitStringAux pBs, PDqLayer pCurDqLayer) {
int32_t iMbXy = pCurDqLayer->iMbXyIndex;
uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)
uint32_t uiCode;
if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {
uiNeighAvail = (1 << 2);
}
if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {
uiNeighAvail |= (1 << 1);
}
if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {
uiNeighAvail |= 1;
}
if (CheckIntra16x16PredMode (uiNeighAvail,
&pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding
return ERR_INFO_INVALID_I16x16_PRED_MODE;
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode
if (uiCode > MAX_PRED_MODE_ID_CHROMA) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;
if (CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {
return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;
}
return 0;
}
int32_t ParseInterInfo (PWelsDecoderContext pCtx, int16_t iMvArray[LIST_A][30][MV_A], int8_t iRefIdxArray[LIST_A][30],
PBitStringAux pBs) {
PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;

View File

@ -2,6 +2,7 @@ DECODER_SRCDIR=codec/decoder
DECODER_CPP_SRCS=\
$(DECODER_SRCDIR)/core/src/au_parser.cpp\
$(DECODER_SRCDIR)/core/src/bit_stream.cpp\
$(DECODER_SRCDIR)/core/src/cabac_decoder.cpp\
$(DECODER_SRCDIR)/core/src/deblocking.cpp\
$(DECODER_SRCDIR)/core/src/decode_mb_aux.cpp\
$(DECODER_SRCDIR)/core/src/decode_slice.cpp\
@ -16,6 +17,7 @@ DECODER_CPP_SRCS=\
$(DECODER_SRCDIR)/core/src/mem_align.cpp\
$(DECODER_SRCDIR)/core/src/memmgr_nal_unit.cpp\
$(DECODER_SRCDIR)/core/src/mv_pred.cpp\
$(DECODER_SRCDIR)/core/src/parse_mb_syn_cabac.cpp\
$(DECODER_SRCDIR)/core/src/parse_mb_syn_cavlc.cpp\
$(DECODER_SRCDIR)/core/src/pic_queue.cpp\
$(DECODER_SRCDIR)/core/src/rec_mb.cpp\

BIN
res/QCIF_2P_I_allIPCM.264 Executable file

Binary file not shown.

BIN
res/test_cif_I_CABAC_PCM.264 Executable file

Binary file not shown.

BIN
res/test_cif_I_CABAC_slice.264 Executable file

Binary file not shown.

BIN
res/test_cif_P_CABAC_slice.264 Executable file

Binary file not shown.

BIN
res/test_qcif_cabac.264 Executable file

Binary file not shown.

View File

@ -119,7 +119,12 @@ static const FileParam kFileParamArray[] = {
{"res/SVA_CL1_E.264", "4fe09ab6cdc965ea10a20f1d6dd38aca954412bb"},
{"res/SVA_FM1_E.264", "fad08c4ff7cf2307b6579853d0f4652fc26645d3"},
{"res/SVA_NL1_B.264", "6d63f72a0c0d833b1db0ba438afff3b4180fb3e6"},
{"res/SVA_NL2_E.264", "70453ef8097c94dd190d6d2d1d5cb83c67e66238"}
{"res/SVA_NL2_E.264", "70453ef8097c94dd190d6d2d1d5cb83c67e66238"},
{"res/test_cif_I_CABAC_PCM.264", "95fdf21470d3bbcf95505abb2164042063a79d98"},
{"res/test_cif_I_CABAC_slice.264", "19121bc67f2b13fb8f030504fc0827e1ac6d0fdb"},
{"res/test_cif_P_CABAC_slice.264", "521bbd0ba2422369b724c7054545cf107a56f959"},
{"res/test_qcif_cabac.264", "587d1d05943f3cd416bf69469975fdee05361e69"},
{"res/QCIF_2P_I_allIPCM.264", "8724c0866ebdba7ebb7209a0c0c3ae3ae38a0240"}
};
INSTANTIATE_TEST_CASE_P (DecodeFile, DecoderOutputTest,

View File

@ -763,7 +763,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLIDR) {
decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
int32_t iSpsPpsIdAddition = 1;
encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
int32_t iIDRPeriod = 60;
int32_t iIDRPeriod = pow(2,(param_.iTemporalLayerNum-1)) * ((rand() % 5) + 1);
encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
SLTRConfig sLtrConfigVal;
sLtrConfigVal.bEnableLongTermReference = 1;
@ -1854,7 +1854,7 @@ TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_I) {
decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
int32_t iSpsPpsIdAddition = 1;
encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
int32_t iIDRPeriod = 15;
int32_t iIDRPeriod = pow(2,(param_.iTemporalLayerNum-1)) * ((rand() % 5) + 1);
encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
SLTRConfig sLtrConfigVal;
sLtrConfigVal.bEnableLongTermReference = 1;