hevcdec: add support for persistent rice adaptation flag
Some checks failed
CMake / build (cmake, aarch64-linux-gnu-gcc, -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/aarch64_toolchain.cmake, aarch64-linux-gnu-g++, ubuntu-latest-cross-aarch64-cmake, ubuntu-latest) (push) Has been cancelled
CMake / build (cmake, arm-linux-gnueabihf-gcc, -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/aarch32_toolchain.cmake, arm-linux-gnueabihf-g++, ubuntu-latest-cross-aarch32-cmake, ubuntu-latest) (push) Has been cancelled
CMake / build (cmake, clang, , clang++, macos-latest-clang-cmake, macos-latest) (push) Has been cancelled
CMake / build (cmake, clang, , clang++, ubuntu-24.04-arm-clang-cmake, ubuntu-24.04-arm) (push) Has been cancelled
CMake / build (cmake, clang, , clang++, ubuntu-latest-clang-cmake, ubuntu-latest) (push) Has been cancelled
CMake / build (cmake, clang, -DSANITIZE=fuzzer-no-link,address, clang++, ubuntu-latest-clang-cmake-asan-fuzzer, ubuntu-latest) (push) Has been cancelled
CMake / build (cmake, clang, -G Ninja, clang++, ubuntu-latest-clang-cmake-ninja, ubuntu-latest) (push) Has been cancelled
CMake / build (cmake, gcc, , g++, ubuntu-latest-gcc-cmake, ubuntu-latest) (push) Has been cancelled

Test: ./hevcdec
Change-Id: I835753e513b757330a4905ac29340422fc8d1590
This commit is contained in:
Ram Mohan M 2026-03-16 20:30:36 +05:30 committed by Harish Mahendrakar
parent b77a7babd3
commit a960c019e0
7 changed files with 124 additions and 21 deletions

View file

@ -2638,9 +2638,9 @@ typedef struct
WORD8 i1_use_high_precision_pred_wt;
/**
* fast_rice_adaptation_enabled_flag
* persistent_rice_adaptation_enabled_flag
*/
WORD8 i1_fast_rice_adaptation_enabled_flag;
WORD8 i1_persistent_rice_adaptation_enabled_flag;
/**
* cabac_bypass_alignment_enabled_flag

View file

@ -133,7 +133,12 @@ IHEVCD_ERROR_T ihevcd_cabac_init(cab_ctxt_t *ps_cabac,
bitstrm_t *ps_bitstrm,
WORD32 qp,
WORD32 cabac_init_idc,
const UWORD8 *pu1_init_ctxt)
const UWORD8 *pu1_init_ctxt
#ifdef ENABLE_MAIN_REXT_PROFILE
,
const WORD32 *pi4_rice_stat_coeff
#endif
)
{
/* Sanity checks */
ASSERT(ps_cabac != NULL);
@ -162,6 +167,16 @@ IHEVCD_ERROR_T ihevcd_cabac_init(cab_ctxt_t *ps_cabac,
memcpy(ps_cabac->au1_ctxt_models,
pu1_init_ctxt,
IHEVC_CAB_CTXT_END);
#ifdef ENABLE_MAIN_REXT_PROFILE
/* golomb rice statistics */
if(pi4_rice_stat_coeff)
{
memcpy(ps_cabac->ai4_rice_stat_coeff, pi4_rice_stat_coeff,
sizeof(ps_cabac->ai4_rice_stat_coeff));
}
#endif
DEBUG_RANGE_OFST("init", ps_cabac->u4_range, ps_cabac->u4_ofst);
/*

View file

@ -214,6 +214,10 @@ IHEVCD_ERROR_T ihevcd_cabac_init
WORD32 slice_qp,
WORD32 cabac_init_idc,
const UWORD8 *pu1_init_ctxt
#ifdef ENABLE_MAIN_REXT_PROFILE
,
const WORD32 *pi4_rice_stat_coeff
#endif
);

View file

@ -1996,7 +1996,7 @@ IHEVCD_ERROR_T ihevcd_parse_sps(codec_t *ps_codec)
ps_sps->i1_use_high_precision_pred_wt = value;
BITS_PARSE("persistent_rice_adaptation_enabled_flag", value, ps_bitstrm, 1);
ps_sps->i1_fast_rice_adaptation_enabled_flag = value;
ps_sps->i1_persistent_rice_adaptation_enabled_flag = value;
BITS_PARSE("cabac_bypass_alignment_enabled_flag", value, ps_bitstrm, 1);
ps_sps->i1_align_cabac_before_bypass = value;
@ -2009,7 +2009,7 @@ IHEVCD_ERROR_T ihevcd_parse_sps(codec_t *ps_codec)
|| ps_sps->i1_explicit_rdpcm_enabled_flag
|| ps_sps->i1_extended_precision_processing_flag
|| ps_sps->i1_intra_smoothing_disabled_flag
|| ps_sps->i1_fast_rice_adaptation_enabled_flag
|| ps_sps->i1_persistent_rice_adaptation_enabled_flag
|| ps_sps->i1_align_cabac_before_bypass)
{
return IHEVCD_INVALID_PARAMETER;
@ -2020,11 +2020,6 @@ IHEVCD_ERROR_T ihevcd_parse_sps(codec_t *ps_codec)
// main-rext 8-bit profiles require these fields to be off
return IHEVCD_INVALID_PARAMETER;
}
if(ps_sps->i1_fast_rice_adaptation_enabled_flag)
{
// TODO: decoder does not yet supports these tool-sets
return IHEVCD_UNSUPPORTED_TOOL_SET;
}
if(ps_sps->i1_sps_multilayer_extension_flag || ps_sps->i1_sps_3d_extension_flag
|| ps_sps->i1_sps_scc_extension_flag)
{

View file

@ -189,6 +189,7 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
WORD32 explicit_rdpcm_flag, explicit_rdpcm_dir;
#endif
WORD32 value;
sps_t *ps_sps;
pps_t *ps_pps;
WORD32 last_scan_pos, last_sub_blk;
bitstrm_t *ps_bitstrm = &ps_codec->s_parse.s_bitstrm;
@ -208,6 +209,7 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
WORD32 sig_coeff_base_ctxt, abs_gt1_base_ctxt;
UNUSED(x0);
UNUSED(y0);
ps_sps = ps_codec->s_parse.ps_sps;
ps_pps = ps_codec->s_parse.ps_pps;
sign_data_hiding_flag = ps_pps->i1_sign_data_hiding_flag;
@ -245,7 +247,7 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
#ifdef ENABLE_MAIN_REXT_PROFILE
if(PRED_MODE_INTER == ps_codec->s_parse.s_cu.i4_pred_mode
&& ps_codec->s_parse.ps_sps->i1_explicit_rdpcm_enabled_flag
&& ps_sps->i1_explicit_rdpcm_enabled_flag
&& (transform_skip_flag || ps_codec->s_parse.s_cu.i4_cu_transquant_bypass))
{
@ -346,7 +348,7 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
scan_idx = SCAN_DIAG_UPRIGHT;
if(PRED_MODE_INTRA == ps_codec->s_parse.s_cu.i4_pred_mode)
{
int is_YUV444 = ps_codec->s_parse.ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV444;
int is_YUV444 = ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV444;
if((2 == log2_trafo_size) || ((3 == log2_trafo_size) && (0 == c_idx || is_YUV444)))
{
if((6 <= intra_pred_mode) &&
@ -515,6 +517,9 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
WORD32 rice_param;
WORD32 xs, ys;
#ifdef ENABLE_MAIN_REXT_PROFILE
WORD8 i1_update_stats = ps_sps->i1_persistent_rice_adaptation_enabled_flag;
#endif
sub_blk_pos = 0;
if(i && (log2_trafo_size > 2))
@ -615,7 +620,7 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
/* derive the context inc as per section 9.3.3.1.4 */
sig_ctxinc = 0;
#ifdef ENABLE_MAIN_REXT_PROFILE
if(ps_codec->s_parse.ps_sps->i1_transform_skip_context_enabled_flag
if(ps_sps->i1_transform_skip_context_enabled_flag
&& (ps_codec->s_parse.s_cu.i4_cu_transquant_bypass
|| transform_skip_flag))
{
@ -787,7 +792,7 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
#endif
|| (PRED_MODE_INTRA == ps_codec->s_parse.s_cu.i4_pred_mode
#ifdef ENABLE_MAIN_REXT_PROFILE
&& ps_codec->s_parse.ps_sps->i1_implicit_rdpcm_enabled_flag
&& ps_sps->i1_implicit_rdpcm_enabled_flag
#else
&& 0
#endif
@ -838,7 +843,22 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
num_sig_coeff = 0;
sum_abs_level = 0;
rice_param = 0;
#ifdef ENABLE_MAIN_REXT_PROFILE
WORD32 sb_type = 2 * (c_idx == 0 ? 1 : 0);
if(ps_sps->i1_persistent_rice_adaptation_enabled_flag)
{
if(!(transform_skip_flag == 0 && ps_codec->s_parse.s_cu.i4_cu_transquant_bypass == 0))
{
sb_type += 1;
}
rice_param = ps_cabac->ai4_rice_stat_coeff[sb_type] / 4;
}
else
#endif
{
rice_param = 0;
}
{
UWORD32 clz;
UWORD32 u4_sig_coeff_map_shift;
@ -924,10 +944,36 @@ WORD32 ihevcd_parse_residual_coding(codec_t *ps_codec,
}
/* update the rice param based on coeff level */
if((base_lvl > (3 << rice_param)) && (rice_param < 4))
if(base_lvl > (3 << rice_param))
{
rice_param++;
#ifdef ENABLE_MAIN_REXT_PROFILE
if(ps_sps->i1_persistent_rice_adaptation_enabled_flag)
{
rice_param += 1;
}
else
#endif
{
rice_param = MIN((rice_param + 1), 4);
}
}
#ifdef ENABLE_MAIN_REXT_PROFILE
if(i1_update_stats)
{
if(coeff_abs_level_remaining
>= (3 << (ps_cabac->ai4_rice_stat_coeff[sb_type] / 4)))
{
ps_cabac->ai4_rice_stat_coeff[sb_type]++;
}
else if((2 * coeff_abs_level_remaining
< (1 << (ps_cabac->ai4_rice_stat_coeff[sb_type] / 4)))
&& ps_cabac->ai4_rice_stat_coeff[sb_type] > 0)
{
ps_cabac->ai4_rice_stat_coeff[sb_type]--;
}
i1_update_stats = 0;
}
#endif
/* Compute absolute level */
level = base_lvl;

View file

@ -2741,11 +2741,19 @@ IHEVCD_ERROR_T ihevcd_parse_slice_data(codec_t *ps_codec)
}
else if((0 == ps_pps->i1_entropy_coding_sync_enabled_flag) || (ps_pps->i1_entropy_coding_sync_enabled_flag && (0 != ps_codec->s_parse.i4_ctb_x)))
{
#ifdef ENABLE_MAIN_REXT_PROFILE
WORD32 ai4_stats[4] = {0};
#endif
ret = ihevcd_cabac_init(&ps_codec->s_parse.s_cabac,
&ps_codec->s_parse.s_bitstrm,
slice_qp,
cabac_init_idc,
&gau1_ihevc_cab_ctxts[cabac_init_idc][slice_qp][0]);
&gau1_ihevc_cab_ctxts[cabac_init_idc][slice_qp][0]
#ifdef ENABLE_MAIN_REXT_PROFILE
,
ps_sps->i1_persistent_rice_adaptation_enabled_flag ? ai4_stats : NULL
#endif
);
if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
{
ps_codec->i4_slice_error = 1;
@ -2837,11 +2845,19 @@ IHEVCD_ERROR_T ihevcd_parse_slice_data(codec_t *ps_codec)
* of whether it is a dependent or an independent slice */
if(0 == ps_codec->i4_slice_error)
{
#ifdef ENABLE_MAIN_REXT_PROFILE
WORD32 ai4_stats[4] = {0};
#endif
ret = ihevcd_cabac_init(&ps_codec->s_parse.s_cabac,
&ps_codec->s_parse.s_bitstrm,
slice_qp,
cabac_init_idc,
&gau1_ihevc_cab_ctxts[cabac_init_idc][slice_qp][0]);
&gau1_ihevc_cab_ctxts[cabac_init_idc][slice_qp][0]
#ifdef ENABLE_MAIN_REXT_PROFILE
,
ps_sps->i1_persistent_rice_adaptation_enabled_flag ? ai4_stats : NULL
#endif
);
if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
{
ps_codec->i4_slice_error = 1;
@ -2912,12 +2928,20 @@ IHEVCD_ERROR_T ihevcd_parse_slice_data(codec_t *ps_codec)
ps_codec->s_parse.u4_qp = slice_qp;
if(default_ctxt)
{
#ifdef ENABLE_MAIN_REXT_PROFILE
WORD32 ai4_stats[4] = {0};
#endif
//memcpy(&ps_codec->s_parse.s_cabac.au1_ctxt_models, &gau1_ihevc_cab_ctxts[cabac_init_idc][slice_qp][0], size);
ret = ihevcd_cabac_init(&ps_codec->s_parse.s_cabac,
&ps_codec->s_parse.s_bitstrm,
slice_qp,
cabac_init_idc,
&gau1_ihevc_cab_ctxts[cabac_init_idc][slice_qp][0]);
&gau1_ihevc_cab_ctxts[cabac_init_idc][slice_qp][0]
#ifdef ENABLE_MAIN_REXT_PROFILE
,
ps_sps->i1_persistent_rice_adaptation_enabled_flag ? ai4_stats : NULL
#endif
);
if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
{
@ -2933,7 +2957,14 @@ IHEVCD_ERROR_T ihevcd_parse_slice_data(codec_t *ps_codec)
&ps_codec->s_parse.s_bitstrm,
slice_qp,
cabac_init_idc,
(const UWORD8 *)&ps_codec->s_parse.s_cabac.au1_ctxt_models_sync);
(const UWORD8 *)&ps_codec->s_parse.s_cabac.au1_ctxt_models_sync
#ifdef ENABLE_MAIN_REXT_PROFILE
,
ps_sps->i1_persistent_rice_adaptation_enabled_flag ?
ps_codec->s_parse.s_cabac.ai4_rice_stat_coeff_sync :
NULL
#endif
);
if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
{
@ -3044,6 +3075,11 @@ IHEVCD_ERROR_T ihevcd_parse_slice_data(codec_t *ps_codec)
{
WORD32 size = sizeof(ps_codec->s_parse.s_cabac.au1_ctxt_models);
memcpy(&ps_codec->s_parse.s_cabac.au1_ctxt_models_sync, &ps_codec->s_parse.s_cabac.au1_ctxt_models, size);
#ifdef ENABLE_MAIN_REXT_PROFILE
size = sizeof(ps_codec->s_parse.s_cabac.ai4_rice_stat_coeff_sync);
memcpy(&ps_codec->s_parse.s_cabac.ai4_rice_stat_coeff_sync, &ps_codec->s_parse.s_cabac.ai4_rice_stat_coeff, size);
#endif
}
}

View file

@ -119,6 +119,13 @@ typedef struct cab_ctxt
*/
UWORD8 au1_ctxt_models_sync[IHEVC_CAB_CTXT_END];
#ifdef ENABLE_MAIN_REXT_PROFILE
/** golomb rice adaptation statistics */
WORD32 ai4_rice_stat_coeff[4];
WORD32 ai4_rice_stat_coeff_sync[4];
#endif
}cab_ctxt_t;
typedef enum