/****************************************************************************** * * Copyright (C) 2015 The Android Open Source Project * * 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. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ /** ******************************************************************************* * @file * ih264e_cabac.c * * @brief * Contains all functions to encode in CABAC entropy mode * * * @author * Doney Alex * * @par List of Functions: * * * @remarks * None * ******************************************************************************* */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #include #include #include #include /* User include files */ #include "ih264e_config.h" #include "ih264_typedefs.h" #include "iv2.h" #include "ive2.h" #include "ih264_debug.h" #include "ih264_defs.h" #include "ih264e_defs.h" #include "ih264_macros.h" #include "ih264e_error.h" #include "ih264e_bitstream.h" #include "ime_distortion_metrics.h" #include "ime_defs.h" #include "ime_structs.h" #include "ih264_error.h" #include "ih264_structs.h" #include "ih264_trans_quant_itrans_iquant.h" #include "ih264_inter_pred_filters.h" #include "ih264_mem_fns.h" #include "ih264_padding.h" #include "ih264_platform_macros.h" #include "ih264_intra_pred_filters.h" #include "ih264_deblk_edge_filters.h" #include "ih264_cabac_tables.h" #include "irc_cntrl_param.h" #include "irc_frame_info_collector.h" #include "ih264e_rate_control.h" #include "ih264e_cabac_structs.h" #include "ih264e_structs.h" #include "ih264e_cabac.h" #include "ih264e_encode_header.h" #include "ih264_cavlc_tables.h" #include "ih264e_cavlc.h" #include "ih264e_statistics.h" #include "ih264e_trace.h" /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /** ******************************************************************************* * * @brief * Encodes mb_skip_flag using CABAC entropy coding mode. * * @param[in] u1_mb_skip_flag * mb_skip_flag * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @param[in] u4_ctxidx_offset * ctxIdxOffset for mb_skip_flag context * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_mb_skip(UWORD8 u1_mb_skip_flag, cabac_ctxt_t *ps_cabac_ctxt, UWORD32 u4_ctxidx_offset) { UWORD8 u4_ctx_inc; WORD8 a, b; a = ((ps_cabac_ctxt->ps_left_ctxt_mb_info->u1_mb_type & CAB_SKIP_MASK) ? 0 : 1); b = ((ps_cabac_ctxt->ps_top_ctxt_mb_info->u1_mb_type & CAB_SKIP_MASK) ? 0 : 1); u4_ctx_inc = a + b; /* Encode the bin */ ih264e_cabac_encode_bin(ps_cabac_ctxt, (UWORD32) u1_mb_skip_flag, ps_cabac_ctxt->au1_cabac_ctxt_table + u4_ctxidx_offset + u4_ctx_inc); } /* ! < Table 9-36 – Binarization for macroblock types in I slices in ITU_T_H264-201402 * Bits 0-7 : binarised value * Bits 8-15: length of binary sequence */ static const UWORD32 u4_mb_type_intra[26] = { 0x0100, 0x0620, 0x0621, 0x0622, 0x0623, 0x0748, 0x0749, 0x074a, 0x074b, 0x074c, 0x074d, 0x074e, 0x074f, 0x0628, 0x0629, 0x062a, 0x062b, 0x0758, 0x0759, 0x075a, 0x075b, 0x075c, 0x075d, 0x075e, 0x075f, 0x0203 }; /* CtxInc for mb types */ static const UWORD32 u4_mb_ctxinc[2][26] = { /* Intra CtxInc's */ { 0x00, 0x03467, 0x03467, 0x03467, 0x03467, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x03467, 0x03467, 0x03467, 0x03467, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x034567, 0x00}, /* Inter CtxInc's */ { 0x00, 0x001233, 0x001233, 0x001233, 0x001233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x001233, 0x001233, 0x001233, 0x001233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x0012233, 0x00} }; /** ******************************************************************************* * * @brief * Encodes mb_type for an intra MB. * * @param[in] u4_slice_type * slice type * * @param[in] u4_intra_mb_type * MB type (Table 7-11) * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * ** @param[in] u4_ctxidx_offset * ctxIdxOffset for mb_type context * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_intra_mb_type(UWORD32 u4_slice_type, UWORD32 u4_intra_mb_type, cabac_ctxt_t *ps_cabac_ctxt, UWORD32 u4_ctx_idx_offset) { encoding_envirnoment_t *ps_cab_enc_env = &(ps_cabac_ctxt->s_cab_enc_env); bin_ctxt_model *pu1_mb_bin_ctxt, *pu1_bin_ctxt; UWORD8 u1_bin; mb_info_ctxt_t *ps_left_ctxt = ps_cabac_ctxt->ps_left_ctxt_mb_info; mb_info_ctxt_t *ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; UWORD32 u4_bins; UWORD32 u4_ctx_inc; WORD8 i1_bins_len; UWORD32 u4_code_int_range; UWORD32 u4_code_int_low; UWORD16 u2_quant_code_int_range; UWORD16 u4_code_int_range_lps; WORD8 i; UWORD8 u1_ctx_inc; UWORD32 u4_table_val; pu1_mb_bin_ctxt = ps_cabac_ctxt->au1_cabac_ctxt_table + u4_ctx_idx_offset; u4_bins = u4_mb_type_intra[u4_intra_mb_type]; i1_bins_len = (WORD8) ((u4_bins >> 8) & 0x0f); u4_ctx_inc = u4_mb_ctxinc[(u4_slice_type != ISLICE)][u4_intra_mb_type]; u1_ctx_inc = 0; if (u4_slice_type == ISLICE) { if (ps_left_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u1_ctx_inc += ((ps_left_ctxt->u1_mb_type != CAB_I4x4) ? 1 : 0); if (ps_top_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u1_ctx_inc += ((ps_top_ctxt->u1_mb_type != CAB_I4x4) ? 1 : 0); u4_ctx_inc = (u4_ctx_inc | (u1_ctx_inc << ((i1_bins_len - 1) << 2))); } else { pu1_mb_bin_ctxt += 3; if (u4_slice_type == BSLICE) pu1_mb_bin_ctxt += 2; } u4_code_int_range = ps_cab_enc_env->u4_code_int_range; u4_code_int_low = ps_cab_enc_env->u4_code_int_low; for (i = (i1_bins_len - 1); i >= 0; i--) { WORD32 shift; u1_ctx_inc = ((u4_ctx_inc >> (i << 2)) & 0x0f); u1_bin = ((u4_bins >> i) & 0x01); /* Encode the bin */ pu1_bin_ctxt = pu1_mb_bin_ctxt + u1_ctx_inc; if (i != (i1_bins_len - 2)) { WORD8 i1_mps = !!((*pu1_bin_ctxt) & (0x40)); WORD8 i1_state = (*pu1_bin_ctxt) & 0x3F; u2_quant_code_int_range = ((u4_code_int_range >> 6) & 0x03); u4_table_val = gau4_ih264_cabac_table[i1_state][u2_quant_code_int_range]; u4_code_int_range_lps = u4_table_val & 0xFF; u4_code_int_range -= u4_code_int_range_lps; if (u1_bin != i1_mps) { u4_code_int_low += u4_code_int_range; u4_code_int_range = u4_code_int_range_lps; if (i1_state == 0) { /* MPS(CtxIdx) = 1 - MPS(CtxIdx) */ i1_mps = 1 - i1_mps; } i1_state = (u4_table_val >> 15) & 0x3F; } else { i1_state = (u4_table_val >> 8) & 0x3F; } (*pu1_bin_ctxt) = (i1_mps << 6) | i1_state; } else { u4_code_int_range -= 2; } /* Renormalize */ /*****************************************************************/ /* Renormalization; calculate bits generated based on range(R) */ /* Note : 6 <= R < 512; R is 2 only for terminating encode */ /*****************************************************************/ GETRANGE(shift, u4_code_int_range); shift = 9 - shift; u4_code_int_low <<= shift; u4_code_int_range <<= shift; /* bits to be inserted in the bitstream */ ps_cab_enc_env->u4_bits_gen += shift; ps_cab_enc_env->u4_code_int_range = u4_code_int_range; ps_cab_enc_env->u4_code_int_low = u4_code_int_low; /* generate stream when a byte is ready */ if (ps_cab_enc_env->u4_bits_gen > CABAC_BITS) { ih264e_cabac_put_byte(ps_cabac_ctxt); u4_code_int_range = ps_cab_enc_env->u4_code_int_range; u4_code_int_low = ps_cab_enc_env->u4_code_int_low; } } } /** ******************************************************************************* * * @brief * Encodes prev_intra4x4_pred_mode_flag and * rem_intra4x4_pred_mode using CABAC entropy coding mode * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @param[in] pu1_intra_4x4_modes * Pointer to array containing prev_intra4x4_pred_mode_flag and * rem_intra4x4_pred_mode * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_4x4mb_modes(cabac_ctxt_t *ps_cabac_ctxt, UWORD8 *pu1_intra_4x4_modes) { WORD32 i; WORD8 byte; for (i = 0; i < 16; i += 2) { /* sub blk idx 1 */ byte = *pu1_intra_4x4_modes++; if (byte & 0x1) { ih264e_cabac_encode_bin(ps_cabac_ctxt, 1, ps_cabac_ctxt->au1_cabac_ctxt_table + PREV_INTRA4X4_PRED_MODE_FLAG); } else { /* Binarization is FL and Cmax=7 */ ih264e_encode_decision_bins(byte & 0xF, 4, 0x05554, 4, ps_cabac_ctxt->au1_cabac_ctxt_table + REM_INTRA4X4_PRED_MODE - 5, ps_cabac_ctxt); } /* sub blk idx 2 */ byte >>= 4; if (byte & 0x1) { ih264e_cabac_encode_bin(ps_cabac_ctxt, 1, ps_cabac_ctxt->au1_cabac_ctxt_table + PREV_INTRA4X4_PRED_MODE_FLAG); } else { ih264e_encode_decision_bins(byte & 0xF, 4, 0x05554, 4, ps_cabac_ctxt->au1_cabac_ctxt_table + REM_INTRA4X4_PRED_MODE - 5, ps_cabac_ctxt); } } } /** ******************************************************************************* * * @brief * Encodes chroma intrapred mode for the MB. * * @param[in] u1_chroma_pred_mode * Chroma intr prediction mode * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_chroma_predmode(UWORD8 u1_chroma_pred_mode, cabac_ctxt_t *ps_cabac_ctxt) { WORD8 i1_temp; mb_info_ctxt_t *ps_curr_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info; mb_info_ctxt_t *ps_left_ctxt = ps_cabac_ctxt->ps_left_ctxt_mb_info; mb_info_ctxt_t *ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; UWORD32 u4_bins = 0; WORD8 i1_bins_len = 1; UWORD32 u4_ctx_inc = 0; UWORD8 a, b; a = ((ps_left_ctxt->u1_intrapred_chroma_mode != 0) ? 1 : 0); b = ((ps_top_ctxt->u1_intrapred_chroma_mode != 0) ? 1 : 0); /* Binarization is TU and Cmax=3 */ ps_curr_ctxt->u1_intrapred_chroma_mode = u1_chroma_pred_mode; u4_ctx_inc = a + b; u4_ctx_inc = (u4_ctx_inc | 0x330); if (u1_chroma_pred_mode) { u4_bins = 1; i1_temp = u1_chroma_pred_mode; i1_temp--; /* Put a stream of 1's of length Chromaps_pred_mode_ctxt value */ while (i1_temp) { u4_bins = (u4_bins | (1 << i1_bins_len)); i1_bins_len++; i1_temp--; } /* If Chromaps_pred_mode_ctxt < Cmax i.e 3. Terminate put a zero */ if (u1_chroma_pred_mode < 3) { i1_bins_len++; } } ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 3, ps_cabac_ctxt->au1_cabac_ctxt_table + INTRA_CHROMA_PRED_MODE, ps_cabac_ctxt); } /** ******************************************************************************* * * @brief * Encodes CBP for the MB. * * @param[in] u1_cbp * CBP for the MB * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_cbp(UWORD32 u4_cbp, cabac_ctxt_t *ps_cabac_ctxt) { mb_info_ctxt_t *ps_left_ctxt = ps_cabac_ctxt->ps_left_ctxt_mb_info; mb_info_ctxt_t *ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; WORD8 i2_cbp_chroma, i, j; UWORD8 u1_ctxt_inc, u1_bin; UWORD8 a, b; UWORD32 u4_ctx_inc; UWORD32 u4_bins; WORD8 i1_bins_len; /* CBP Luma, FL, Cmax = 15, L = 4 */ u4_ctx_inc = 0; u4_bins = 0; i1_bins_len = 5; for (i = 0; i < 4; i++) { /* calulate ctxtInc, depending on neighbour availability */ /* u1_ctxt_inc = CondTerm(A) + 2 * CondTerm(B); A: Left block and B: Top block */ /* Check for Top availability */ if (i >> 1) { j = i - 2; /* Top is available always and it's current MB */ b = (((u4_cbp >> j) & 0x01) != 0 ? 0 : 1); } else { /* for blocks whose top reference is in another MB */ { j = i + 2; b = ((ps_top_ctxt->u1_cbp >> j) & 0x01) ? 0 : 1; } } /* Check for Left availability */ if (i & 0x01) { /* Left is available always and it's current MB */ j = i - 1; a = (((u4_cbp >> j) & 0x01) != 0 ? 0 : 1); } else { { j = i + 1; a = ((ps_left_ctxt->u1_cbp >> j) & 0x01) ? 0 : 1; } } u1_ctxt_inc = a + 2 * b; u1_bin = ((u4_cbp >> i) & 0x01); u4_ctx_inc = (u4_ctx_inc | (u1_ctxt_inc << (i << 2))); u4_bins = (u4_bins | (u1_bin << i)); } /* CBP Chroma, TU, Cmax = 2 */ i2_cbp_chroma = u4_cbp >> 4; /* calulate ctxtInc, depending on neighbour availability */ a = (ps_left_ctxt->u1_cbp > 15) ? 1 : 0; b = (ps_top_ctxt->u1_cbp > 15) ? 1 : 0; u1_ctxt_inc = a + 2 * b; if (i2_cbp_chroma) { u4_ctx_inc = u4_ctx_inc | ((4 + u1_ctxt_inc) << 16); u4_bins = (u4_bins | 0x10); /* calulate ctxtInc, depending on neighbour availability */ a = (ps_left_ctxt->u1_cbp > 31) ? 1 : 0; b = (ps_top_ctxt->u1_cbp > 31) ? 1 : 0; u1_ctxt_inc = a + 2 * b; u4_ctx_inc = u4_ctx_inc | ((8 + u1_ctxt_inc) << 20); u4_bins = (u4_bins | (((i2_cbp_chroma >> 1) & 0x01) << i1_bins_len)); i1_bins_len++; } else { u4_ctx_inc = (u4_ctx_inc | ((4 + u1_ctxt_inc) << 16)); } ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 8, ps_cabac_ctxt->au1_cabac_ctxt_table + CBP_LUMA, ps_cabac_ctxt); } /** ******************************************************************************* * * @brief * Encodes mb_qp_delta for the MB. * * @param[in] i1_mb_qp_delta * mb_qp_delta * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_mb_qp_delta(WORD8 i1_mb_qp_delta, cabac_ctxt_t *ps_cabac_ctxt) { UWORD8 u1_code_num; UWORD8 u1_ctxt_inc; UWORD32 u4_ctx_inc; UWORD32 u4_bins; WORD8 i1_bins_len; UWORD8 u1_ctx_inc, u1_bin; /* Range of ps_mb_qp_delta_ctxt= -26 to +25 inclusive */ ASSERT((i1_mb_qp_delta < 26) && (i1_mb_qp_delta > -27)); /* if ps_mb_qp_delta_ctxt=0, then codeNum=0 */ u1_code_num = 0; if (i1_mb_qp_delta > 0) u1_code_num = (i1_mb_qp_delta << 1) - 1; else if (i1_mb_qp_delta < 0) u1_code_num = (ABS(i1_mb_qp_delta)) << 1; u4_ctx_inc = 0; u4_bins = 0; i1_bins_len = 1; /* calculate ctxtInc, depending on neighbour availability */ u1_ctxt_inc = (!(!(ps_cabac_ctxt->i1_prevps_mb_qp_delta_ctxt))); ps_cabac_ctxt->i1_prevps_mb_qp_delta_ctxt = i1_mb_qp_delta; if (u1_code_num == 0) { /* b0 */ u1_bin = (UWORD8) (u4_bins); u1_ctx_inc = u1_ctxt_inc & 0x0f; /* Encode the bin */ ih264e_cabac_encode_bin(ps_cabac_ctxt, u1_bin, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_QP_DELTA + u1_ctx_inc); } else { /* b0 */ u4_ctx_inc = u1_ctxt_inc; u4_bins = 1; u1_code_num--; if (u1_code_num == 0) { /* b1 */ u4_ctx_inc = (u4_ctx_inc | 0x20); i1_bins_len++; ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 3, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_QP_DELTA, ps_cabac_ctxt); } else { /* b1 */ u4_ctx_inc = (u4_ctx_inc | 0x20); u4_bins = (u4_bins | (1 << i1_bins_len)); i1_bins_len++; u1_code_num--; /* BinIdx from b2 onwards */ if (u1_code_num < 30) { /* maximum i1_bins_len = 31 */ while (u1_code_num) { u4_bins = (u4_bins | (1 << i1_bins_len)); i1_bins_len++; u1_code_num--; }; u4_ctx_inc = (u4_ctx_inc | 0x300); i1_bins_len++; ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 2, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_QP_DELTA, ps_cabac_ctxt); } else { /* maximum i1_bins_len = 53 */ u4_bins = 0xffffffff; i1_bins_len = 32; u4_ctx_inc = (u4_ctx_inc | 0x300); u1_code_num -= 30; ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 2, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_QP_DELTA, ps_cabac_ctxt); u4_bins = 0; i1_bins_len = 0; u4_ctx_inc = 0x033; while (u1_code_num) { u4_bins = (u4_bins | (1 << i1_bins_len)); i1_bins_len++; u1_code_num--; }; u4_ctx_inc = (u4_ctx_inc | 0x300); i1_bins_len++; ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 1, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_QP_DELTA, ps_cabac_ctxt); } } } } /** ******************************************************************************* * @brief * Encodes 4residual_block_cabac as defined in 7.3.5.3.3. * * @param[in] pi2_res_block * pointer to the array of residues * * @param[in] u1_nnz * Number of non zero coeffs in the block * * @param[in] u1_max_num_coeffs * Max number of coeffs that can be there in the block * * @param[in] u2_sig_coeff_map * Significant coeff map * * @param[in] u4_ctx_cat_offset * ctxIdxOffset for absolute value contexts * * @param[in] pu1_ctxt_sig_coeff * Pointer to residual state variables * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_write_coeff4x4(WORD16 *pi2_res_block, UWORD8 u1_nnz, UWORD8 u1_max_num_coeffs, UWORD16 u2_sig_coeff_map, UWORD32 u4_ctx_cat_offset, bin_ctxt_model *pu1_ctxt_sig_coeff, cabac_ctxt_t *ps_cabac_ctxt) { WORD8 i; WORD16 *pi16_coeffs; UWORD32 u4_sig_coeff, u4_bins; UWORD32 u4_ctx_inc; UWORD8 u1_last_sig_coef_index = (31 - CLZ(u2_sig_coeff_map)); /* Always put Coded Block Flag as 1 */ pi16_coeffs = pi2_res_block; { bin_ctxt_model *pu1_bin_ctxt; UWORD8 u1_bin, uc_last; i = 0; pu1_bin_ctxt = pu1_ctxt_sig_coeff; u4_sig_coeff = 0; u1_bin = 1; if ((u1_last_sig_coef_index)) { u1_bin = !!(u2_sig_coeff_map & 01); } uc_last = 1; do { /* Encode Decision */ ih264e_cabac_encode_bin(ps_cabac_ctxt, u1_bin, pu1_bin_ctxt); if (u1_bin & uc_last) { u4_sig_coeff = (u4_sig_coeff | (1 << i)); pu1_bin_ctxt = pu1_ctxt_sig_coeff + i + LAST_SIGNIFICANT_COEFF_FLAG_FRAME - SIGNIFICANT_COEFF_FLAG_FRAME; u1_bin = (i == u1_last_sig_coef_index); uc_last = 0; } else { i = i + 1; pu1_bin_ctxt = pu1_ctxt_sig_coeff + i; u1_bin = (i == u1_last_sig_coef_index); uc_last = 1; if ((i != u1_last_sig_coef_index)) { u1_bin = !!((u2_sig_coeff_map >> i) & 01); } } }while (!((i > u1_last_sig_coef_index) || (i > (u1_max_num_coeffs - 1)))); } /* Encode coeff_abs_level_minus1 and coeff_sign_flag */ { UWORD8 u1_sign; UWORD16 u2_abs_level; UWORD8 u1_abs_level_equal1 = 1, u1_abs_level_gt1 = 0; UWORD8 u1_ctx_inc; UWORD8 u1_coff; WORD16 i2_sufs; WORD8 i1_bins_len; i = u1_last_sig_coef_index; pi16_coeffs = pi2_res_block + u1_nnz - 1; do { { u4_sig_coeff = u4_sig_coeff & ((1 << i) - 1); u4_bins = 0; u4_ctx_inc = 0; i1_bins_len = 1; /* Encode the AbsLevelMinus1 */ u2_abs_level = ABS(*(pi16_coeffs)) - 1; /* CtxInc for bin0 */ u4_ctx_inc = MIN(u1_abs_level_equal1, 4); /* CtxInc for remaining */ u1_ctx_inc = 5 + MIN(u1_abs_level_gt1, 4); u4_ctx_inc = u4_ctx_inc + (u1_ctx_inc << 4); if (u2_abs_level) { u1_abs_level_gt1++; u1_abs_level_equal1 = 0; } if (!u1_abs_level_gt1) u1_abs_level_equal1++; u1_coff = 14; if (u2_abs_level >= u1_coff) { /* Prefix TU i.e string of 14 1's */ u4_bins = 0x3fff; i1_bins_len = 14; ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 1, ps_cabac_ctxt->au1_cabac_ctxt_table + u4_ctx_cat_offset, ps_cabac_ctxt); /* Suffix, uses EncodeBypass */ i2_sufs = u2_abs_level - u1_coff; u4_bins = ih264e_cabac_UEGk0_binarization(i2_sufs, &i1_bins_len); ih264e_cabac_encode_bypass_bins(ps_cabac_ctxt, u4_bins, i1_bins_len); } else { /* Prefix only */ u4_bins = (1 << u2_abs_level) - 1; i1_bins_len = u2_abs_level + 1; /* Encode Terminating bit */ ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 1, ps_cabac_ctxt->au1_cabac_ctxt_table + u4_ctx_cat_offset, ps_cabac_ctxt); } } /* encode coeff_sign_flag[i] */ u1_sign = ((*pi16_coeffs) < 0) ? 1 : 0; ih264e_cabac_encode_bypass_bin(ps_cabac_ctxt, u1_sign); i = CLZ(u4_sig_coeff); i = 31 - i; pi16_coeffs--; }while (u4_sig_coeff); } } /** ******************************************************************************* * @brief * Write DC coeffs for intra predicted luma block * * @param[in] ps_ent_ctxt * Pointer to entropy context structure * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_encode_residue_luma_dc(entropy_ctxt_t *ps_ent_ctxt) { /* CABAC context */ cabac_ctxt_t *ps_cabac_ctxt = ps_ent_ctxt->ps_cabac; tu_sblk_coeff_data_t *ps_mb_coeff_data; /* packed residue */ void *pv_mb_coeff_data = ps_ent_ctxt->pv_mb_coeff_data; UWORD16 u2_sig_coeff_map; WORD16 *pi2_res_block; UWORD8 u1_nnz; UWORD8 u1_cbf; mb_info_ctxt_t *ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; mb_info_ctxt_t *p_CurCtxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info; PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, u1_nnz, u2_sig_coeff_map, pi2_res_block); u1_cbf = !!(u1_nnz); { UWORD32 u4_ctx_inc; UWORD8 u1_a, u1_b; u1_a = ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] & 0x1; u1_b = ps_top_ctxt->u1_yuv_dc_csbp & 0x1; u4_ctx_inc = u1_a + (u1_b << 1); ih264e_cabac_encode_bin(ps_cabac_ctxt, u1_cbf, ps_cabac_ctxt->au1_cabac_ctxt_table + CBF + (LUMA_DC_CTXCAT << 2) + u4_ctx_inc); } /* Write coded_block_flag */ if (u1_cbf) { ih264e_cabac_write_coeff4x4(pi2_res_block, u1_nnz, 15, u2_sig_coeff_map, COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_0_OFFSET, ps_cabac_ctxt->au1_cabac_ctxt_table + SIGNIFICANT_COEFF_FLAG_FRAME + SIG_COEFF_CTXT_CAT_0_OFFSET, ps_cabac_ctxt); ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] |= 0x1; p_CurCtxt->u1_yuv_dc_csbp |= 0x1; } else { ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x6; p_CurCtxt->u1_yuv_dc_csbp &= 0x6; } ps_ent_ctxt->pv_mb_coeff_data = pv_mb_coeff_data; } /** ******************************************************************************* * @brief * Write chroma residues to the bitstream * * @param[in] ps_ent_ctxt * Pointer to entropy context structure * * @param[in] u1_chroma_cbp * coded block pattern, chroma * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_write_chroma_residue(entropy_ctxt_t *ps_ent_ctxt, UWORD8 u1_chroma_cbp) { /* CABAC context */ cabac_ctxt_t *ps_cabac_ctxt = ps_ent_ctxt->ps_cabac; tu_sblk_coeff_data_t *ps_mb_coeff_data; /* packed residue */ void *pv_mb_coeff_data = ps_ent_ctxt->pv_mb_coeff_data; UWORD16 u2_sig_coeff_map; UWORD8 u1_nnz; mb_info_ctxt_t *ps_top_ctxt_mb_info, *ps_curr_ctxt; ps_top_ctxt_mb_info = ps_cabac_ctxt->ps_top_ctxt_mb_info; ps_curr_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info; /********************/ /* Write Chroma DC */ /********************/ { WORD16 *pi2_res_block; UWORD8 u1_left_dc_csbp, u1_top_dc_csbp, u1_uv, u1_cbf; u1_left_dc_csbp = (ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0]) >> 1; u1_top_dc_csbp = (ps_top_ctxt_mb_info->u1_yuv_dc_csbp) >> 1; for (u1_uv = 0; u1_uv < 2; u1_uv++) { PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, u1_nnz, u2_sig_coeff_map, pi2_res_block); u1_cbf = !!(u1_nnz); { UWORD8 u1_a, u1_b; UWORD32 u4_ctx_inc; u1_a = (u1_left_dc_csbp >> u1_uv) & 0x01; u1_b = (u1_top_dc_csbp >> u1_uv) & 0x01; u4_ctx_inc = (u1_a + (u1_b << 1)); ih264e_cabac_encode_bin(ps_cabac_ctxt, u1_cbf, ps_cabac_ctxt->au1_cabac_ctxt_table + CBF + (CHROMA_DC_CTXCAT << 2) + u4_ctx_inc); } if (u1_cbf) { ih264e_cabac_write_coeff4x4(pi2_res_block, u1_nnz, 3, u2_sig_coeff_map, COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_3_OFFSET, ps_cabac_ctxt->au1_cabac_ctxt_table + SIGNIFICANT_COEFF_FLAG_FRAME + SIG_COEFF_CTXT_CAT_3_OFFSET, ps_cabac_ctxt); SETBIT(u1_top_dc_csbp, u1_uv); SETBIT(u1_left_dc_csbp, u1_uv); } else { CLEARBIT(u1_top_dc_csbp, u1_uv); CLEARBIT(u1_left_dc_csbp, u1_uv); } } /*************************************************************/ /* Update the DC csbp */ /*************************************************************/ ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x1; ps_curr_ctxt->u1_yuv_dc_csbp &= 0x1; ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] |= (u1_left_dc_csbp << 1); ps_curr_ctxt->u1_yuv_dc_csbp |= (u1_top_dc_csbp << 1); } /*******************/ /* Write Chroma AC */ /*******************/ { if (u1_chroma_cbp == 2) { UWORD8 u1_uv_blkno, u1_left_ac_csbp, u1_top_ac_csbp; WORD16 *pi2_res_block; u1_left_ac_csbp = ps_cabac_ctxt->pu1_left_uv_ac_csbp[0]; u1_top_ac_csbp = ps_top_ctxt_mb_info->u1_yuv_ac_csbp >> 4; for (u1_uv_blkno = 0; u1_uv_blkno < 8; u1_uv_blkno++) { UWORD8 u1_cbf; UWORD8 u1_b2b0, u1_b2b1; PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, u1_nnz, u2_sig_coeff_map, pi2_res_block); u1_cbf = !!(u1_nnz); u1_b2b0 = ((u1_uv_blkno & 0x4) >> 1) | (u1_uv_blkno & 0x1); u1_b2b1 = ((u1_uv_blkno & 0x4) >> 1) | ((u1_uv_blkno & 0x2) >> 1); { UWORD8 u1_a, u1_b; UWORD32 u4_ctx_inc; /* write coded_block_flag */ u1_a = (u1_left_ac_csbp >> u1_b2b1) & 0x1; u1_b = (u1_top_ac_csbp >> u1_b2b0) & 0x1; u4_ctx_inc = u1_a + (u1_b << 1); ih264e_cabac_encode_bin(ps_cabac_ctxt, u1_cbf, ps_cabac_ctxt->au1_cabac_ctxt_table + CBF + (CHROMA_AC_CTXCAT << 2) + u4_ctx_inc); } if (u1_cbf) { ih264e_cabac_write_coeff4x4(pi2_res_block, u1_nnz, 14, u2_sig_coeff_map, COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_4_OFFSET, ps_cabac_ctxt->au1_cabac_ctxt_table + +SIGNIFICANT_COEFF_FLAG_FRAME + SIG_COEFF_CTXT_CAT_4_OFFSET, ps_cabac_ctxt); SETBIT(u1_left_ac_csbp, u1_b2b1); SETBIT(u1_top_ac_csbp, u1_b2b0); } else { CLEARBIT(u1_left_ac_csbp, u1_b2b1); CLEARBIT(u1_top_ac_csbp, u1_b2b0); } } /*************************************************************/ /* Update the AC csbp */ /*************************************************************/ ps_cabac_ctxt->pu1_left_uv_ac_csbp[0] = u1_left_ac_csbp; ps_curr_ctxt->u1_yuv_ac_csbp &= 0x0f; ps_curr_ctxt->u1_yuv_ac_csbp |= (u1_top_ac_csbp << 4); } else { ps_cabac_ctxt->pu1_left_uv_ac_csbp[0] = 0; ps_curr_ctxt->u1_yuv_ac_csbp &= 0xf; } } ps_ent_ctxt->pv_mb_coeff_data = pv_mb_coeff_data; } /** ******************************************************************************* * @brief * Encodes Residues for the MB as defined in 7.3.5.3 * * @param[in] ps_ent_ctxt * Pointer to entropy context structure * * @param[in] u1_cbp * coded block pattern * * @param[in] u1_ctx_cat * Context category, LUMA_AC_CTXCAT or LUMA_4x4_CTXCAT * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_encode_residue(entropy_ctxt_t *ps_ent_ctxt, UWORD32 u4_cbp, UWORD8 u1_ctx_cat) { /* CABAC context */ cabac_ctxt_t *ps_cabac_ctxt = ps_ent_ctxt->ps_cabac; tu_sblk_coeff_data_t *ps_mb_coeff_data; /* packed residue */ void *pv_mb_coeff_data = ps_ent_ctxt->pv_mb_coeff_data; UWORD16 u2_sig_coeff_map; UWORD8 u1_nnz; mb_info_ctxt_t *ps_curr_ctxt; mb_info_ctxt_t *ps_top_ctxt; UWORD8 u1_left_ac_csbp; UWORD8 u1_top_ac_csbp; UWORD32 u4_ctx_idx_offset_sig_coef, u4_ctx_idx_offset_abs_lvl; ps_curr_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info; ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; u1_left_ac_csbp = ps_cabac_ctxt->pu1_left_y_ac_csbp[0]; u1_top_ac_csbp = ps_top_ctxt->u1_yuv_ac_csbp; if (u4_cbp & 0xf) { /* Write luma residue */ UWORD8 u1_offset; WORD16 *pi2_res_block; UWORD8 u1_subblk_num; if (u1_ctx_cat == LUMA_AC_CTXCAT) { u1_offset = 1; u4_ctx_idx_offset_sig_coef = SIG_COEFF_CTXT_CAT_1_OFFSET; u4_ctx_idx_offset_abs_lvl = COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_1_OFFSET; } else { u1_offset = 0; u4_ctx_idx_offset_sig_coef = SIG_COEFF_CTXT_CAT_2_OFFSET; u4_ctx_idx_offset_abs_lvl = COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_2_OFFSET; } for (u1_subblk_num = 0; u1_subblk_num < 16; u1_subblk_num++) { UWORD8 u1_b0, u1_b1, u1_b2, u1_b3, u1_b2b0, u1_b3b1, u1_b3b2; u1_b0 = (u1_subblk_num & 0x1); u1_b1 = (u1_subblk_num & 0x2) >> 1; u1_b2 = (u1_subblk_num & 0x4) >> 2; u1_b3 = (u1_subblk_num & 0x8) >> 3; u1_b2b0 = (u1_b2 << 1) | (u1_b0); u1_b3b1 = (u1_b3 << 1) | (u1_b1); u1_b3b2 = (u1_b3 << 1) | (u1_b2); if (!((u4_cbp >> u1_b3b2) & 0x1)) { /* ---------------------------------------------------------- */ /* The current block is not coded so skip all the sub block */ /* and set the pointer of scan level, csbp accrodingly */ /* ---------------------------------------------------------- */ CLEARBIT(u1_top_ac_csbp, u1_b2b0); CLEARBIT(u1_top_ac_csbp, (u1_b2b0 + 1)); CLEARBIT(u1_left_ac_csbp, u1_b3b1); CLEARBIT(u1_left_ac_csbp, (u1_b3b1 + 1)); u1_subblk_num += 3; } else { UWORD8 u1_csbf; PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, u1_nnz, u2_sig_coeff_map, pi2_res_block); u1_csbf = !!(u1_nnz); { UWORD8 u1_a, u1_b; UWORD32 u4_ctx_inc; u1_b = (u1_top_ac_csbp >> u1_b2b0) & 0x01; u1_a = (u1_left_ac_csbp >> u1_b3b1) & 0x01; u4_ctx_inc = u1_a + (u1_b << 1); /* Encode the bin */ ih264e_cabac_encode_bin(ps_cabac_ctxt, u1_csbf, ps_cabac_ctxt->au1_cabac_ctxt_table + CBF + (u1_ctx_cat << 2) + u4_ctx_inc); } /**************************/ /* Write coded_block_flag */ /**************************/ if (u1_csbf) { ih264e_cabac_write_coeff4x4(pi2_res_block, u1_nnz, (UWORD8) (15 - u1_offset), u2_sig_coeff_map, u4_ctx_idx_offset_abs_lvl, ps_cabac_ctxt->au1_cabac_ctxt_table + SIGNIFICANT_COEFF_FLAG_FRAME + u4_ctx_idx_offset_sig_coef, ps_cabac_ctxt); SETBIT(u1_top_ac_csbp, u1_b2b0); SETBIT(u1_left_ac_csbp, u1_b3b1); } else { CLEARBIT(u1_top_ac_csbp, u1_b2b0); CLEARBIT(u1_left_ac_csbp, u1_b3b1); } } } /**************************************************************************/ /* Update the AC csbp */ /**************************************************************************/ ps_cabac_ctxt->pu1_left_y_ac_csbp[0] = u1_left_ac_csbp & 0xf; u1_top_ac_csbp &= 0x0f; ps_curr_ctxt->u1_yuv_ac_csbp &= 0xf0; ps_curr_ctxt->u1_yuv_ac_csbp |= u1_top_ac_csbp; } else { ps_cabac_ctxt->pu1_left_y_ac_csbp[0] = 0; ps_curr_ctxt->u1_yuv_ac_csbp &= 0xf0; } /* Write chroma residue */ ps_ent_ctxt->pv_mb_coeff_data = pv_mb_coeff_data; { UWORD8 u1_cbp_chroma; u1_cbp_chroma = u4_cbp >> 4; if (u1_cbp_chroma) { ih264e_cabac_write_chroma_residue(ps_ent_ctxt, u1_cbp_chroma); } else { ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x1; ps_curr_ctxt->u1_yuv_dc_csbp &= 0x1; ps_cabac_ctxt->pu1_left_uv_ac_csbp[0] = 0; ps_curr_ctxt->u1_yuv_ac_csbp &= 0xf; } } } /** ******************************************************************************* * @brief * Encodes a Motion vector (9.3.3.1.1.7 ) * * @param[in] u1_mvd * Motion vector to be encoded * * @param[in] u4_ctx_idx_offset * * ctxIdxOffset for MV_X or MV_Ycontext * * @param[in] ui2_abs_mvd * sum of absolute value of corresponding neighboring motion vectors * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_ctx_mvd(WORD16 u1_mvd, UWORD32 u4_ctx_idx_offset, UWORD16 ui2_abs_mvd, cabac_ctxt_t *ps_cabac_ctxt) { UWORD8 u1_bin, u1_ctxt_inc; WORD8 k = 3, u1_coff = 9; WORD16 i2_abs_mvd, i2_sufs; UWORD32 u4_ctx_inc; UWORD32 u4_bins; WORD8 i1_bins_len; /* if mvd < u1_coff only Prefix else Prefix + Suffix encode sign bit Prefix TU encoding Cmax =u1_coff and Suffix 3rd order Exp-Golomb */ if (ui2_abs_mvd < 3) u4_ctx_inc = 0; else if (ui2_abs_mvd > 32) u4_ctx_inc = 2; else u4_ctx_inc = 1; u4_bins = 0; i1_bins_len = 1; if (u1_mvd == 0) { ih264e_cabac_encode_bin(ps_cabac_ctxt, 0, ps_cabac_ctxt->au1_cabac_ctxt_table + u4_ctx_idx_offset + u4_ctx_inc); } else { i2_abs_mvd = ABS(u1_mvd); if (i2_abs_mvd >= u1_coff) { /* Prefix TU i.e string of 9 1's */ u4_bins = 0x1ff; i1_bins_len = 9; u4_ctx_inc = (u4_ctx_inc | 0x065430); ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 4, ps_cabac_ctxt->au1_cabac_ctxt_table + u4_ctx_idx_offset, ps_cabac_ctxt); /* Suffix, uses EncodeBypass */ u4_bins = 0; i1_bins_len = 0; i2_sufs = i2_abs_mvd - u1_coff; while (1) { if (i2_sufs >= (1 << k)) { u4_bins = (u4_bins | (1 << (31 - i1_bins_len))); i1_bins_len++; i2_sufs = i2_sufs - (1 << k); k++; } else { i1_bins_len++; while (k--) { u1_bin = ((i2_sufs >> k) & 0x01); u4_bins = (u4_bins | (u1_bin << (31 - i1_bins_len))); i1_bins_len++; } break; } } u4_bins >>= (32 - i1_bins_len); ih264e_cabac_encode_bypass_bins(ps_cabac_ctxt, u4_bins, i1_bins_len); } else { /* Prefix only */ /* b0 */ u4_bins = 1; i2_abs_mvd--; u1_ctxt_inc = 3; while (i2_abs_mvd) { i2_abs_mvd--; u4_bins = (u4_bins | (1 << i1_bins_len)); if (u1_ctxt_inc <= 6) { u4_ctx_inc = (u4_ctx_inc | (u1_ctxt_inc << (i1_bins_len << 2))); u1_ctxt_inc++; } i1_bins_len++; } /* Encode Terminating bit */ if (i1_bins_len <= 4) u4_ctx_inc = (u4_ctx_inc | (u1_ctxt_inc << (i1_bins_len << 2))); i1_bins_len++; ih264e_encode_decision_bins(u4_bins, i1_bins_len, u4_ctx_inc, 4, ps_cabac_ctxt->au1_cabac_ctxt_table + u4_ctx_idx_offset, ps_cabac_ctxt); } /* sign bit, uses EncodeBypass */ if (u1_mvd > 0) ih264e_cabac_encode_bypass_bin(ps_cabac_ctxt, 0); else ih264e_cabac_encode_bypass_bin(ps_cabac_ctxt, 1); } } /** ******************************************************************************* * @brief * Encodes all motion vectors for a P16x16 MB * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @param[in] pi2_mv_ptr * Pointer to array of motion vectors * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_mvds_p16x16(cabac_ctxt_t *ps_cabac_ctxt, WORD16 *pi2_mv_ptr) { /* Encode the differential component of the motion vectors */ { UWORD8 u1_abs_mvd_x, u1_abs_mvd_y; UWORD8 *pu1_top_mv_ctxt, *pu1_lft_mv_ctxt; WORD16 u2_mv; u1_abs_mvd_x = 0; u1_abs_mvd_y = 0; pu1_top_mv_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_mv[0]; pu1_lft_mv_ctxt = ps_cabac_ctxt->pu1_left_mv_ctxt_inc[0]; { UWORD16 u2_abs_mvd_x_a, u2_abs_mvd_x_b, u2_abs_mvd_y_a, u2_abs_mvd_y_b; u2_abs_mvd_x_b = (UWORD16) pu1_top_mv_ctxt[0]; u2_abs_mvd_y_b = (UWORD16) pu1_top_mv_ctxt[1]; u2_abs_mvd_x_a = (UWORD16) pu1_lft_mv_ctxt[0]; u2_abs_mvd_y_a = (UWORD16) pu1_lft_mv_ctxt[1]; u2_mv = *(pi2_mv_ptr++); ih264e_cabac_enc_ctx_mvd(u2_mv, MVD_X, (UWORD16) (u2_abs_mvd_x_a + u2_abs_mvd_x_b), ps_cabac_ctxt); u1_abs_mvd_x = CLIP3(0, 127, ABS(u2_mv)); u2_mv = *(pi2_mv_ptr++); ih264e_cabac_enc_ctx_mvd(u2_mv, MVD_Y, (UWORD16) (u2_abs_mvd_y_a + u2_abs_mvd_y_b), ps_cabac_ctxt); u1_abs_mvd_y = CLIP3(0, 127, ABS(u2_mv)); } /***************************************************************/ /* Store abs_mvd_values cabac contexts */ /***************************************************************/ pu1_top_mv_ctxt[0] = pu1_lft_mv_ctxt[0] = u1_abs_mvd_x; pu1_top_mv_ctxt[1] = pu1_lft_mv_ctxt[1] = u1_abs_mvd_y; } } /** ******************************************************************************* * @brief * Encodes all motion vectors for a B MB (Assues that mbype is B_L0_16x16, B_L1_16x16 or B_Bi_16x16 * * @param[in] ps_cabac_ctxt * Pointer to cabac context structure * * @param[in] pi2_mv_ptr * Pointer to array of motion vectors * * @returns * * @remarks * None * ******************************************************************************* */ static void ih264e_cabac_enc_mvds_b16x16(cabac_ctxt_t *ps_cabac_ctxt, WORD16 *pi2_mv_ptr, WORD32 i4_mb_part_pred_mode ) { /* Encode the differential component of the motion vectors */ { UWORD8 u1_abs_mvd_x, u1_abs_mvd_y; UWORD8 *pu1_top_mv_ctxt, *pu1_lft_mv_ctxt; WORD16 u2_mv; u1_abs_mvd_x = 0; u1_abs_mvd_y = 0; pu1_top_mv_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_mv[0]; pu1_lft_mv_ctxt = ps_cabac_ctxt->pu1_left_mv_ctxt_inc[0]; if (i4_mb_part_pred_mode != PRED_L1)/* || PRED_BI */ { UWORD16 u2_abs_mvd_x_a, u2_abs_mvd_x_b, u2_abs_mvd_y_a, u2_abs_mvd_y_b; u2_abs_mvd_x_b = (UWORD16) pu1_top_mv_ctxt[0]; u2_abs_mvd_y_b = (UWORD16) pu1_top_mv_ctxt[1]; u2_abs_mvd_x_a = (UWORD16) pu1_lft_mv_ctxt[0]; u2_abs_mvd_y_a = (UWORD16) pu1_lft_mv_ctxt[1]; u2_mv = *(pi2_mv_ptr++); ih264e_cabac_enc_ctx_mvd(u2_mv, MVD_X, (UWORD16) (u2_abs_mvd_x_a + u2_abs_mvd_x_b), ps_cabac_ctxt); u1_abs_mvd_x = CLIP3(0, 127, ABS(u2_mv)); u2_mv = *(pi2_mv_ptr++); ih264e_cabac_enc_ctx_mvd(u2_mv, MVD_Y, (UWORD16) (u2_abs_mvd_y_a + u2_abs_mvd_y_b), ps_cabac_ctxt); u1_abs_mvd_y = CLIP3(0, 127, ABS(u2_mv)); } /***************************************************************/ /* Store abs_mvd_values cabac contexts */ /***************************************************************/ pu1_top_mv_ctxt[0] = pu1_lft_mv_ctxt[0] = u1_abs_mvd_x; pu1_top_mv_ctxt[1] = pu1_lft_mv_ctxt[1] = u1_abs_mvd_y; u1_abs_mvd_x = 0; u1_abs_mvd_y = 0; if (i4_mb_part_pred_mode != PRED_L0)/* || PRED_BI */ { UWORD16 u2_abs_mvd_x_a, u2_abs_mvd_x_b, u2_abs_mvd_y_a, u2_abs_mvd_y_b; u2_abs_mvd_x_b = (UWORD16) pu1_top_mv_ctxt[2]; u2_abs_mvd_y_b = (UWORD16) pu1_top_mv_ctxt[3]; u2_abs_mvd_x_a = (UWORD16) pu1_lft_mv_ctxt[2]; u2_abs_mvd_y_a = (UWORD16) pu1_lft_mv_ctxt[3]; u2_mv = *(pi2_mv_ptr++); ih264e_cabac_enc_ctx_mvd(u2_mv, MVD_X, (UWORD16) (u2_abs_mvd_x_a + u2_abs_mvd_x_b), ps_cabac_ctxt); u1_abs_mvd_x = CLIP3(0, 127, ABS(u2_mv)); u2_mv = *(pi2_mv_ptr++); ih264e_cabac_enc_ctx_mvd(u2_mv, MVD_Y, (UWORD16) (u2_abs_mvd_y_a + u2_abs_mvd_y_b), ps_cabac_ctxt); u1_abs_mvd_y = CLIP3(0, 127, ABS(u2_mv)); } /***************************************************************/ /* Store abs_mvd_values cabac contexts */ /***************************************************************/ pu1_top_mv_ctxt[2] = pu1_lft_mv_ctxt[2] = u1_abs_mvd_x; pu1_top_mv_ctxt[3] = pu1_lft_mv_ctxt[3] = u1_abs_mvd_y; } } /** ******************************************************************************* * * @brief * This function generates CABAC coded bit stream for an Intra Slice. * * @description * The mb syntax layer for intra slices constitutes luma mb mode, mb qp delta, coded block pattern, chroma mb mode and * luma/chroma residue. These syntax elements are written as directed by table * 7.3.5 of h264 specification. * * @param[in] ps_ent_ctxt * pointer to entropy context * * @returns error code * * @remarks none * ******************************************************************************* */ IH264E_ERROR_T ih264e_write_islice_mb_cabac(entropy_ctxt_t *ps_ent_ctxt) { /* bit stream ptr */ bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; /* CABAC context */ cabac_ctxt_t *ps_cabac_ctxt = ps_ent_ctxt->ps_cabac; /* packed header data */ UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data; mb_info_ctxt_t *ps_curr_ctxt; WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode; WORD8 mb_qp_delta; UWORD32 u4_cbp_l, u4_cbp_c; WORD32 byte_count = 0; WORD32 bitstream_start_offset, bitstream_end_offset; if ((ps_bitstream->u4_strm_buf_offset + MIN_STREAM_SIZE_MB) >= ps_bitstream->u4_max_strm_size) { /* return without corrupting the buffer beyond its size */ return (IH264E_BITSTREAM_BUFFER_OVERFLOW); } /* mb header info */ mb_tpm = *pu1_byte++; byte_count++; cbp = *pu1_byte++; byte_count++; mb_qp_delta = *pu1_byte++; byte_count++; /* mb type */ mb_type = mb_tpm & 0xF; ih264e_get_cabac_context(ps_ent_ctxt, mb_type); ps_curr_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info; /* Starting bitstream offset for header in bits */ bitstream_start_offset = GET_NUM_BITS(ps_bitstream); u4_cbp_c = (cbp >> 4); u4_cbp_l = (cbp & 0xF); if (mb_type == I16x16) { luma_intra_mode = ((mb_tpm >> 4) & 3) + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12; } else { luma_intra_mode = 0; } chroma_intra_mode = (mb_tpm >> 6); /* Encode Intra pred mode, Luma */ ih264e_cabac_enc_intra_mb_type(ISLICE, luma_intra_mode, ps_cabac_ctxt, MB_TYPE_I_SLICE); if (mb_type == I4x4) { /* Encode 4x4 MB modes */ ih264e_cabac_enc_4x4mb_modes(ps_cabac_ctxt, pu1_byte); byte_count += 8; } /* Encode chroma mode */ ih264e_cabac_enc_chroma_predmode(chroma_intra_mode, ps_cabac_ctxt); if (mb_type != I16x16) { /* Encode MB cbp */ ih264e_cabac_enc_cbp(cbp, ps_cabac_ctxt); } if ((cbp > 0) || (mb_type == I16x16)) { /* Encode mb_qp_delta */ ih264e_cabac_enc_mb_qp_delta(mb_qp_delta, ps_cabac_ctxt); /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[0] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ bitstream_start_offset = bitstream_end_offset; if (mb_type == I16x16) { ps_curr_ctxt->u1_mb_type = CAB_I16x16; ps_curr_ctxt->u1_cbp = cbp; ih264e_cabac_encode_residue_luma_dc(ps_ent_ctxt); ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_AC_CTXCAT); } else { ps_curr_ctxt->u1_cbp = cbp; ps_curr_ctxt->u1_mb_type = I4x4; ps_curr_ctxt->u1_mb_type = CAB_I4x4; ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_4X4_CTXCAT); ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x6; ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_yuv_dc_csbp &= 0x6; } /* Ending bitstream offset for reside in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_residue_bits[0] += bitstream_end_offset - bitstream_start_offset; } else { ps_curr_ctxt->u1_yuv_ac_csbp = 0; ps_curr_ctxt->u1_yuv_dc_csbp = 0; *(ps_cabac_ctxt->pu1_left_uv_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_y_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_yuv_dc_csbp) = 0; /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[0] += bitstream_end_offset - bitstream_start_offset; /* Computing the number of used used for encoding the MB syntax */ } memset(ps_curr_ctxt->u1_mv, 0, 16); memset(ps_cabac_ctxt->pu1_left_mv_ctxt_inc, 0, 16); ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_cbp = cbp; ps_ent_ctxt->pv_mb_header_data = ((WORD8 *)ps_ent_ctxt->pv_mb_header_data) + byte_count; if (mb_type == I16x16) { ps_curr_ctxt->u1_mb_type = CAB_I16x16; } else { ps_curr_ctxt->u1_mb_type = CAB_I4x4; } return IH264E_SUCCESS; } /** ******************************************************************************* * * @brief * This function generates CABAC coded bit stream for Inter slices * * @description * The mb syntax layer for inter slices constitutes luma mb mode, mb qp delta, coded block pattern, chroma mb mode and * luma/chroma residue. These syntax elements are written as directed by table * 7.3.5 of h264 specification * * @param[in] ps_ent_ctxt * pointer to entropy context * * @returns error code * * @remarks none * ******************************************************************************* */ IH264E_ERROR_T ih264e_write_pslice_mb_cabac(entropy_ctxt_t *ps_ent_ctxt) { /* bit stream ptr */ bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; /* CABAC context */ cabac_ctxt_t *ps_cabac_ctxt = ps_ent_ctxt->ps_cabac; mb_info_ctxt_t *ps_curr_ctxt; WORD32 bitstream_start_offset, bitstream_end_offset; WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode; WORD8 mb_qp_delta; UWORD32 u4_cbp_l, u4_cbp_c; WORD32 byte_count = 0; UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data; if ((ps_bitstream->u4_strm_buf_offset + MIN_STREAM_SIZE_MB) >= ps_bitstream->u4_max_strm_size) { /* return without corrupting the buffer beyond its size */ return (IH264E_BITSTREAM_BUFFER_OVERFLOW); } /* mb header info */ mb_tpm = *pu1_byte++; byte_count++; /* mb type */ mb_type = mb_tpm & 0xF; /* CABAC contexts for the MB */ ih264e_get_cabac_context(ps_ent_ctxt, mb_type); ps_curr_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info; /* if Intra MB */ if (mb_type == I16x16 || mb_type == I4x4) { cbp = *pu1_byte++; byte_count++; mb_qp_delta = *pu1_byte++; byte_count++; /* Starting bitstream offset for header in bits */ bitstream_start_offset = GET_NUM_BITS(ps_bitstream); /* Encode mb_skip_flag */ ih264e_cabac_enc_mb_skip(0, ps_cabac_ctxt, MB_SKIP_FLAG_P_SLICE); u4_cbp_c = (cbp >> 4); u4_cbp_l = (cbp & 0xF); if (mb_type == I16x16) { luma_intra_mode = ((mb_tpm >> 4) & 3) + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12; } else { luma_intra_mode = 0; } /* Encode intra mb type */ { ih264e_cabac_encode_bin(ps_cabac_ctxt, 1, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_TYPE_P_SLICE); ih264e_cabac_enc_intra_mb_type(PSLICE, (UWORD8) luma_intra_mode, ps_cabac_ctxt, MB_TYPE_P_SLICE); } if (mb_type == I4x4) { /* Intra 4x4 modes */ ih264e_cabac_enc_4x4mb_modes(ps_cabac_ctxt, pu1_byte); byte_count += 8; } chroma_intra_mode = (mb_tpm >> 6); ih264e_cabac_enc_chroma_predmode(chroma_intra_mode, ps_cabac_ctxt); if (mb_type != I16x16) { /* encode CBP */ ih264e_cabac_enc_cbp(cbp, ps_cabac_ctxt); } if ((cbp > 0) || (mb_type == I16x16)) { ih264e_cabac_enc_mb_qp_delta(mb_qp_delta, ps_cabac_ctxt); /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[0] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ bitstream_start_offset = bitstream_end_offset; /* Encoding Residue */ if (mb_type == I16x16) { ps_curr_ctxt->u1_mb_type = CAB_I16x16; ps_curr_ctxt->u1_cbp = (UWORD8) cbp; ih264e_cabac_encode_residue_luma_dc(ps_ent_ctxt); ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_AC_CTXCAT); } else { ps_curr_ctxt->u1_cbp = (UWORD8) cbp; ps_curr_ctxt->u1_mb_type = I4x4; ps_curr_ctxt->u1_mb_type = CAB_I4x4; ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_4X4_CTXCAT); ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x6; ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_yuv_dc_csbp &= 0x6; } /* Ending bitstream offset for reside in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_residue_bits[0] += bitstream_end_offset - bitstream_start_offset; } else { ps_curr_ctxt->u1_yuv_ac_csbp = 0; ps_curr_ctxt->u1_yuv_dc_csbp = 0; *(ps_cabac_ctxt->pu1_left_uv_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_y_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_yuv_dc_csbp) = 0; /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[0] += bitstream_end_offset - bitstream_start_offset; } memset(ps_curr_ctxt->u1_mv, 0, 16); memset(ps_cabac_ctxt->pu1_left_mv_ctxt_inc, 0, 16); ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_cbp = (UWORD8) cbp; if (mb_type == I16x16) { ps_curr_ctxt->u1_mb_type = CAB_I16x16; } else { ps_curr_ctxt->u1_mb_type = CAB_I4x4; } ps_ent_ctxt->pv_mb_header_data = ((WORD8 *)ps_ent_ctxt->pv_mb_header_data) + byte_count; return IH264E_SUCCESS; } else /* Inter MB */ { /* Starting bitstream offset for header in bits */ bitstream_start_offset = GET_NUM_BITS(ps_bitstream); /* Encoding P16x16 */ if (mb_type != PSKIP) { cbp = *pu1_byte++; byte_count++; mb_qp_delta = *pu1_byte++; byte_count++; /* Encoding mb_skip */ ih264e_cabac_enc_mb_skip(0, ps_cabac_ctxt, MB_SKIP_FLAG_P_SLICE); /* Encoding mb_type as P16x16 */ { UWORD32 u4_ctx_inc_p; u4_ctx_inc_p = (0x010 + ((2) << 8)); ih264e_encode_decision_bins(0, 3, u4_ctx_inc_p, 3, &(ps_cabac_ctxt->au1_cabac_ctxt_table[MB_TYPE_P_SLICE]), ps_cabac_ctxt); } ps_curr_ctxt->u1_mb_type = CAB_P; { WORD16 *pi2_mv_ptr = (WORD16 *) pu1_byte; byte_count += 4; ps_curr_ctxt->u1_mb_type = (ps_curr_ctxt->u1_mb_type | CAB_NON_BD16x16); /* Encoding motion vector for P16x16 */ ih264e_cabac_enc_mvds_p16x16(ps_cabac_ctxt, pi2_mv_ptr); } /* Encode CBP */ ih264e_cabac_enc_cbp(cbp, ps_cabac_ctxt); if (cbp) { /* encode mb_qp_delta */ ih264e_cabac_enc_mb_qp_delta(mb_qp_delta, ps_cabac_ctxt); } /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[1] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ bitstream_start_offset = bitstream_end_offset; } else/* MB = PSKIP */ { ih264e_cabac_enc_mb_skip(1, ps_cabac_ctxt, MB_SKIP_FLAG_P_SLICE); ps_curr_ctxt->u1_mb_type = CAB_P_SKIP; (*ps_ent_ctxt->pi4_mb_skip_run)++; memset(ps_curr_ctxt->u1_mv, 0, 16); memset(ps_cabac_ctxt->pu1_left_mv_ctxt_inc, 0, 16); cbp = 0; /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[1] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ } if (cbp > 0) { /* Encode residue */ ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_4X4_CTXCAT); /* Ending bitstream offset for reside in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_residue_bits[1] += bitstream_end_offset - bitstream_start_offset; ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x6; ps_curr_ctxt->u1_yuv_dc_csbp &= 0x6; } else { ps_curr_ctxt->u1_yuv_ac_csbp = 0; ps_curr_ctxt->u1_yuv_dc_csbp = 0; *(ps_cabac_ctxt->pu1_left_uv_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_y_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_yuv_dc_csbp) = 0; } ps_curr_ctxt->u1_intrapred_chroma_mode = 0; ps_curr_ctxt->u1_cbp = cbp; ps_ent_ctxt->pv_mb_header_data = ((WORD8 *)ps_ent_ctxt->pv_mb_header_data) + byte_count; return IH264E_SUCCESS; } } /* ! < Table 9-37 – Binarization for macroblock types in B slices in ITU_T_H264-201402 * Bits 0-7 : binarised value * Bits 8-15: length of binary sequence */ static const UWORD32 u4_b_mb_type[27] = { 0x0100, 0x0301, 0x0305, 0x0603, 0x0623, 0x0613, 0x0633, 0x060b, 0x062b, 0x061b, 0x063b, 0x061f, 0x0707, 0x0747, 0x0727, 0x0767, 0x0717, 0x0757, 0x0737, 0x0777, 0x070f, 0x074f, 0x063f }; /* CtxInc for mb types in B slices */ static const UWORD32 ui_b_mb_type_ctx_inc[27] = { 0x00, 0x0530, 0x0530, 0x0555430, 0x0555430, 0x0555430, 0x0555430, 0x0555430, 0x0555430, 0x0555430, 0x0555430, 0x0555430, 0x05555430, 0x05555430, 0x05555430, 0x05555430, 0x05555430, 0x05555430, 0x05555430, 0x05555430, 0x05555430, 0x05555430, 0x0555430 }; /** ******************************************************************************* * * @brief * This function generates CABAC coded bit stream for B slices * * @description * The mb syntax layer for inter slices constitutes luma mb mode, * mb qp delta, coded block pattern, chroma mb mode and * luma/chroma residue. These syntax elements are written as directed by table * 7.3.5 of h264 specification * * @param[in] ps_ent_ctxt * pointer to entropy context * * @returns error code * * @remarks none * ******************************************************************************* */ IH264E_ERROR_T ih264e_write_bslice_mb_cabac(entropy_ctxt_t *ps_ent_ctxt) { /* bit stream ptr */ bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; /* CABAC context */ cabac_ctxt_t *ps_cabac_ctxt = ps_ent_ctxt->ps_cabac; mb_info_ctxt_t *ps_curr_ctxt; WORD32 bitstream_start_offset, bitstream_end_offset; WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode; WORD8 mb_qp_delta; UWORD32 u4_cbp_l, u4_cbp_c; WORD32 byte_count = 0; UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data; if ((ps_bitstream->u4_strm_buf_offset + MIN_STREAM_SIZE_MB) >= ps_bitstream->u4_max_strm_size) { /* return without corrupting the buffer beyond its size */ return (IH264E_BITSTREAM_BUFFER_OVERFLOW); } /* mb header info */ mb_tpm = *pu1_byte++; byte_count++; /* mb type */ mb_type = mb_tpm & 0xF; /* CABAC contexts for the MB */ ih264e_get_cabac_context(ps_ent_ctxt, mb_type); ps_curr_ctxt = ps_cabac_ctxt->ps_curr_ctxt_mb_info; /* if Intra MB */ if (mb_type == I16x16 || mb_type == I4x4) { cbp = *pu1_byte++; byte_count++; mb_qp_delta = *pu1_byte++; byte_count++; /* Starting bitstream offset for header in bits */ bitstream_start_offset = GET_NUM_BITS(ps_bitstream); /* Encode mb_skip_flag */ ih264e_cabac_enc_mb_skip(0, ps_cabac_ctxt, MB_SKIP_FLAG_B_SLICE); u4_cbp_c = (cbp >> 4); u4_cbp_l = (cbp & 0xF); if (mb_type == I16x16) { luma_intra_mode = ((mb_tpm >> 4) & 3) + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12; } else { luma_intra_mode = 0; } /* Encode intra mb type */ { mb_info_ctxt_t *ps_left_ctxt = ps_cabac_ctxt->ps_left_ctxt_mb_info; mb_info_ctxt_t *ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; UWORD32 u4_ctx_inc = 0; if (ps_left_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u4_ctx_inc += ((ps_left_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16) ? 1 : 0; if (ps_top_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u4_ctx_inc += ((ps_top_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16) ? 1 : 0; /* Intra Prefix Only "111101" */ u4_ctx_inc = (u4_ctx_inc | 0x05555430); ih264e_encode_decision_bins(0x2f, 6, u4_ctx_inc, 3, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_TYPE_B_SLICE, ps_cabac_ctxt); ih264e_cabac_enc_intra_mb_type(BSLICE, (UWORD8) luma_intra_mode, ps_cabac_ctxt, MB_TYPE_B_SLICE); } if (mb_type == I4x4) { /* Intra 4x4 modes */ ih264e_cabac_enc_4x4mb_modes(ps_cabac_ctxt, pu1_byte); byte_count += 8; } chroma_intra_mode = (mb_tpm >> 6); ih264e_cabac_enc_chroma_predmode(chroma_intra_mode, ps_cabac_ctxt); if (mb_type != I16x16) { /* encode CBP */ ih264e_cabac_enc_cbp(cbp, ps_cabac_ctxt); } if ((cbp > 0) || (mb_type == I16x16)) { ih264e_cabac_enc_mb_qp_delta(mb_qp_delta, ps_cabac_ctxt); /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[0] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ bitstream_start_offset = bitstream_end_offset; /* Encoding Residue */ if (mb_type == I16x16) { ps_curr_ctxt->u1_mb_type = CAB_I16x16; ps_curr_ctxt->u1_cbp = (UWORD8) cbp; ih264e_cabac_encode_residue_luma_dc(ps_ent_ctxt); ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_AC_CTXCAT); } else { ps_curr_ctxt->u1_cbp = (UWORD8) cbp; ps_curr_ctxt->u1_mb_type = I4x4; ps_curr_ctxt->u1_mb_type = CAB_I4x4; ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_4X4_CTXCAT); ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x6; ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_yuv_dc_csbp &= 0x6; } /* Ending bitstream offset for reside in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_residue_bits[0] += bitstream_end_offset - bitstream_start_offset; } else { ps_curr_ctxt->u1_yuv_ac_csbp = 0; ps_curr_ctxt->u1_yuv_dc_csbp = 0; *(ps_cabac_ctxt->pu1_left_uv_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_y_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_yuv_dc_csbp) = 0; /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[0] += bitstream_end_offset - bitstream_start_offset; } memset(ps_curr_ctxt->u1_mv, 0, 16); memset(ps_cabac_ctxt->pu1_left_mv_ctxt_inc, 0, 16); ps_cabac_ctxt->ps_curr_ctxt_mb_info->u1_cbp = (UWORD8) cbp; if (mb_type == I16x16) { ps_curr_ctxt->u1_mb_type = CAB_I16x16; } else { ps_curr_ctxt->u1_mb_type = CAB_I4x4; } ps_ent_ctxt->pv_mb_header_data = ((WORD8 *)ps_ent_ctxt->pv_mb_header_data) + byte_count; return IH264E_SUCCESS; } else /* Inter MB */ { /* Starting bitstream offset for header in bits */ bitstream_start_offset = GET_NUM_BITS(ps_bitstream); /* Encoding B_Direct_16x16 */ if (mb_type == BDIRECT) { cbp = *pu1_byte++; byte_count++; mb_qp_delta = *pu1_byte++; byte_count++; /* Encoding mb_skip */ ih264e_cabac_enc_mb_skip(0, ps_cabac_ctxt, MB_SKIP_FLAG_B_SLICE); /* Encoding mb_type as B_Direct_16x16 */ { mb_info_ctxt_t *ps_left_ctxt = ps_cabac_ctxt->ps_left_ctxt_mb_info; mb_info_ctxt_t *ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; UWORD32 u4_ctx_inc = 0; if (ps_left_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u4_ctx_inc += ((ps_left_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16) ? 1 : 0; if (ps_top_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u4_ctx_inc += ((ps_top_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16) ? 1 : 0; /* Encode the bin */ ih264e_cabac_encode_bin( ps_cabac_ctxt, 0, ps_cabac_ctxt->au1_cabac_ctxt_table + MB_TYPE_B_SLICE + u4_ctx_inc); } ps_curr_ctxt->u1_mb_type = CAB_BD16x16; memset(ps_curr_ctxt->u1_mv, 0, 16); memset(ps_cabac_ctxt->pu1_left_mv_ctxt_inc, 0, 16); /* Encode CBP */ ih264e_cabac_enc_cbp(cbp, ps_cabac_ctxt); if (cbp) { /* encode mb_qp_delta */ ih264e_cabac_enc_mb_qp_delta(mb_qp_delta, ps_cabac_ctxt); } /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[1] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ bitstream_start_offset = bitstream_end_offset; /* Starting bitstream offset for residue */ } else if (mb_type == BSKIP)/* MB = BSKIP */ { ih264e_cabac_enc_mb_skip(1, ps_cabac_ctxt, MB_SKIP_FLAG_B_SLICE); ps_curr_ctxt->u1_mb_type = CAB_B_SKIP; memset(ps_curr_ctxt->u1_mv, 0, 16); memset(ps_cabac_ctxt->pu1_left_mv_ctxt_inc, 0, 16); cbp = 0; /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[1] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ } else /* mbype is B_L0_16x16, B_L1_16x16 or B_Bi_16x16 */ { WORD32 i4_mb_part_pred_mode = (mb_tpm >> 4); UWORD32 u4_mb_type = mb_type - B16x16 + B_L0_16x16 + i4_mb_part_pred_mode; cbp = *pu1_byte++; byte_count++; mb_qp_delta = *pu1_byte++; byte_count++; /* Encoding mb_skip */ ih264e_cabac_enc_mb_skip(0, ps_cabac_ctxt, MB_SKIP_FLAG_B_SLICE); /* Encoding mb_type as B16x16 */ { mb_info_ctxt_t *ps_left_ctxt = ps_cabac_ctxt->ps_left_ctxt_mb_info; mb_info_ctxt_t *ps_top_ctxt = ps_cabac_ctxt->ps_top_ctxt_mb_info; UWORD32 u4_ctx_inc = 0; UWORD32 u4_mb_type_bins = u4_b_mb_type[u4_mb_type]; UWORD32 u4_bin_len = (u4_mb_type_bins >> 8) & 0x0F; u4_mb_type_bins = u4_mb_type_bins & 0xFF; if (ps_left_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u4_ctx_inc += ((ps_left_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16) ? 1 : 0; if (ps_top_ctxt != ps_cabac_ctxt->ps_def_ctxt_mb_info) u4_ctx_inc += ((ps_top_ctxt->u1_mb_type & CAB_BD16x16_MASK) != CAB_BD16x16) ? 1 : 0; u4_ctx_inc = u4_ctx_inc | ui_b_mb_type_ctx_inc[u4_mb_type]; ih264e_encode_decision_bins(u4_mb_type_bins, u4_bin_len, u4_ctx_inc, u4_bin_len, &(ps_cabac_ctxt->au1_cabac_ctxt_table[MB_TYPE_B_SLICE]), ps_cabac_ctxt); } ps_curr_ctxt->u1_mb_type = CAB_NON_BD16x16; { WORD16 *pi2_mv_ptr = (WORD16 *) pu1_byte; /* Get the pred modes */ byte_count += 4 * (1 + (i4_mb_part_pred_mode == PRED_BI)); ps_curr_ctxt->u1_mb_type = (ps_curr_ctxt->u1_mb_type | CAB_NON_BD16x16); /* Encoding motion vector for B16x16 */ ih264e_cabac_enc_mvds_b16x16(ps_cabac_ctxt, pi2_mv_ptr, i4_mb_part_pred_mode); } /* Encode CBP */ ih264e_cabac_enc_cbp(cbp, ps_cabac_ctxt); if (cbp) { /* encode mb_qp_delta */ ih264e_cabac_enc_mb_qp_delta(mb_qp_delta, ps_cabac_ctxt); } /* Ending bitstream offset for header in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_header_bits[1] += bitstream_end_offset - bitstream_start_offset; /* Starting bitstream offset for residue */ bitstream_start_offset = bitstream_end_offset; } if (cbp > 0) { /* Encode residue */ ih264e_cabac_encode_residue(ps_ent_ctxt, cbp, LUMA_4X4_CTXCAT); /* Ending bitstream offset for reside in bits */ bitstream_end_offset = GET_NUM_BITS(ps_bitstream); ps_ent_ctxt->u4_residue_bits[1] += bitstream_end_offset - bitstream_start_offset; ps_cabac_ctxt->pu1_left_yuv_dc_csbp[0] &= 0x6; ps_curr_ctxt->u1_yuv_dc_csbp &= 0x6; } else { ps_curr_ctxt->u1_yuv_ac_csbp = 0; ps_curr_ctxt->u1_yuv_dc_csbp = 0; *(ps_cabac_ctxt->pu1_left_uv_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_y_ac_csbp) = 0; *(ps_cabac_ctxt->pu1_left_yuv_dc_csbp) = 0; } ps_curr_ctxt->u1_intrapred_chroma_mode = 0; ps_curr_ctxt->u1_cbp = cbp; ps_ent_ctxt->pv_mb_header_data = ((WORD8 *)ps_ent_ctxt->pv_mb_header_data) + byte_count; return IH264E_SUCCESS; } }