/******************************************************************************
*
* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/**
******************************************************************************
* @file ihevcd_cabac.h
*
* @brief
* This file contains decoder cabac engine related structures and
* interface prototypes
*
* @author
* Ittiam
******************************************************************************
*/
#ifndef _IHEVCD_CABAC_H_
#define _IHEVCD_CABAC_H_
#include "ihevc_typedefs.h"
/*****************************************************************************/
/* Constant Macros */
/*****************************************************************************/
/**
*******************************************************************************
@brief
*******************************************************************************
*/
#define CABAC_BITS 9
/**
* Following definitions control whether cabac functions are inlined as macros or
* are called as functions. Set these to 0 to debug cabac leaf level functions
* Note these macros assume FULLRANGE is 1.
*/
#define CABAC_DECODE_BIN 1
#define CABAC_DECODE_BYPASS_BIN 1
#define CABAC_DECODE_BYPASS_BINS 1
/*****************************************************************************/
/* Function Macros */
/*****************************************************************************/
#if CABAC_DECODE_BIN
#define IHEVCD_CABAC_DECODE_BIN(u4_bin, ps_cabac, ps_bitstrm, ctxt_index) \
{ \
UWORD32 u4_range = ps_cabac->u4_range; \
UWORD32 u4_ofst = ps_cabac->u4_ofst; \
UWORD32 u4_rlps; \
UWORD8 *pu1_ctxt_model = &ps_cabac->au1_ctxt_models[ctxt_index]; \
WORD32 state_mps = *pu1_ctxt_model; \
WORD32 clz; \
UWORD32 u4_qnt_range; \
\
/* Sanity checks */ \
ASSERT(FULLRANGE == 1); \
ASSERT(u4_range >= 256); \
ASSERT((ctxt_index >= 0) && (ctxt_index < IHEVC_CAB_CTXT_END)); \
ASSERT(state_mps < 128); \
clz = CLZ(u4_range); \
clz -= (32 - RANGE_NUMBITS); \
u4_qnt_range = u4_range << clz; \
u4_qnt_range = (u4_qnt_range >> (RANGE_SHIFT + 6)) & 0x3; \
/* Get the lps range from LUT based on quantized range and state */ \
u4_rlps = gau1_ihevc_cabac_rlps[state_mps >> 1][u4_qnt_range]; \
u4_rlps = u4_rlps << (RANGE_SHIFT - clz); \
u4_range -= u4_rlps; \
\
u4_bin = state_mps & 1; \
\
if(u4_ofst >= u4_range) \
{ \
u4_bin = 1 - u4_bin; \
u4_ofst -= u4_range; \
u4_range = u4_rlps; \
} \
\
*pu1_ctxt_model = gau1_ihevc_next_state[(state_mps << 1) | u4_bin]; \
\
/*****************************************************************/ \
/* Re-normalization; calculate bits generated based on range(R) */ \
/*****************************************************************/ \
if(u4_range < (1 << 8)) \
{ \
UWORD32 u4_bits; \
WORD32 numbits; \
numbits = CLZ(u4_range); \
numbits -= (32 - RANGE_NUMBITS); \
BITS_GET(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, \
ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, numbits); \
\
u4_ofst <<= numbits; \
u4_ofst |= u4_bits; \
u4_range <<= numbits; \
\
} \
/* Update the cabac context */ \
ps_cabac->u4_range = u4_range; \
ps_cabac->u4_ofst = u4_ofst; \
\
}
#else
#define IHEVCD_CABAC_DECODE_BIN(u4_bin, ps_cabac, ps_bitstrm, ctxt_index) \
u4_bin = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm, ctxt_index);
#endif
#if CABAC_DECODE_BYPASS_BIN
#define IHEVCD_CABAC_DECODE_BYPASS_BIN(u4_bin, ps_cabac, ps_bitstrm) \
{ \
\
UWORD32 u4_range = ps_cabac->u4_range; \
UWORD32 u4_ofst = ps_cabac->u4_ofst; \
UWORD32 u4_bits; \
\
/* Sanity checks */ \
ASSERT(FULLRANGE == 1); \
ASSERT(u4_range >= 256); \
\
BIT_GET(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, \
ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word); \
\
u4_ofst <<= 1; \
u4_ofst |= u4_bits; \
\
u4_bin = 0; \
if(u4_ofst >= u4_range) \
{ \
u4_bin = 1; \
u4_ofst -= u4_range; \
} \
\
/* Update the cabac context */ \
ps_cabac->u4_ofst = u4_ofst; \
}
#else
#define IHEVCD_CABAC_DECODE_BYPASS_BIN(u4_bin, ps_cabac, ps_bitstrm) \
u4_bin = ihevcd_cabac_decode_bypass_bin(ps_cabac, ps_bitstrm);
#endif
#if CABAC_DECODE_BYPASS_BINS
#define IHEVCD_CABAC_DECODE_BYPASS_BINS(u4_bins, ps_cabac, ps_bitstrm, numbins) \
{ \
UWORD32 u4_range = ps_cabac->u4_range; \
UWORD32 u4_ofst = ps_cabac->u4_ofst; \
UWORD32 u4_bits; \
ASSERT(FULLRANGE == 1); \
ASSERT(u4_range >= 256); \
ASSERT(numbins > 0); \
{ \
WORD32 numbins_tmp = numbins; \
/* Sanity checks */ \
ASSERT(numbins < 17); \
\
u4_bins = 0; \
\
BITS_GET(u4_bits, ps_bitstrm->pu4_buf, ps_bitstrm->u4_bit_ofst, \
ps_bitstrm->u4_cur_word, ps_bitstrm->u4_nxt_word, numbins); \
do \
{ \
UWORD32 u4_bit; \
numbins_tmp--; \
u4_bit = (u4_bits >> numbins_tmp) & 1; \
u4_ofst <<= 1; \
u4_ofst |= u4_bit; \
\
u4_bins <<= 1; \
if(u4_ofst >= u4_range) \
{ \
u4_bins += 1; \
u4_ofst -= u4_range; \
} \
}while(numbins_tmp); \
\
/* Update the cabac context */ \
ps_cabac->u4_ofst = u4_ofst; \
} \
}
#else
#define IHEVCD_CABAC_DECODE_BYPASS_BINS(u4_bins, ps_cabac, ps_bitstrm, numbins) \
u4_bins = ihevcd_cabac_decode_bypass_bins(ps_cabac, ps_bitstrm, numbins);
#endif
/*****************************************************************************/
/* Structures */
/*****************************************************************************/
/*****************************************************************************/
/* Extern Function Declarations */
/*****************************************************************************/
IHEVCD_ERROR_T ihevcd_cabac_init
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 slice_qp,
WORD32 cabac_init_idc,
const UWORD8 *pu1_init_ctxt
);
UWORD32 ihevcd_cabac_decode_bin
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 ctxt_index
);
UWORD32 ihevcd_cabac_decode_bypass_bin
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm
);
UWORD32 ihevcd_cabac_decode_terminate
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm
);
UWORD32 ihevcd_cabac_decode_bypass_bins
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 num_bins
);
UWORD32 ihevcd_cabac_decode_bins_tunary
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 c_max,
WORD32 ctxt_index,
WORD32 ctxt_shift,
WORD32 ctxt_inc_max
);
UWORD32 ihevcd_cabac_decode_bypass_bins_tunary
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 c_max
);
UWORD32 ihevcd_cabac_decode_bypass_bins_egk
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 k
);
UWORD32 ihevcd_cabac_decode_bypass_bins_trunc_rice
(
cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 c_rice_param,
WORD32 c_rice_max
);
IHEVCD_ERROR_T ihevcd_cabac_flush(cab_ctxt_t *ps_cabac);
IHEVCD_ERROR_T ihevcd_cabac_reset(cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm);
#endif /* _IHEVCD_CABAC_H_ */