/****************************************************************************** * * Copyright (C) 2022 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 * isvce_cavlc.c * * @brief * Contains all the routines to code syntax elements and residuals when entropy * coding chosen is CAVLC * * @author * ittiam * * @par List of Functions: * - isvce_compute_zeroruns_and_trailingones() * - isvce_write_coeff4x4_cavlc() * - isvce_write_coeff8x8_cavlc() * - isvce_encode_residue() * - isvce_write_islice_mb_cavlc() * - isvce_write_pslice_mb_cavlc() * * @remarks * None * ******************************************************************************* */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #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 "isvc_macros.h" #include "isvc_defs.h" #include "isvce_defs.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 "isvc_structs.h" #include "isvc_trans_quant_itrans_iquant.h" #include "isvc_inter_pred_filters.h" #include "isvc_mem_fns.h" #include "ih264_padding.h" #include "ih264_intra_pred_filters.h" #include "ih264_deblk_edge_filters.h" #include "isvc_cabac_tables.h" #include "irc_cntrl_param.h" #include "irc_frame_info_collector.h" #include "isvce_rate_control.h" #include "isvce_cabac_structs.h" #include "isvce_structs.h" #include "isvce_encode_header.h" #include "ih264_cavlc_tables.h" #include "isvce_cavlc.h" #include "ih264e_statistics.h" #include "ih264e_trace.h" #include "isvce_encode_header.h" #include "isvce_utils.h" /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /** ******************************************************************************* * * @brief * This function computes run of zero, number of trailing ones and sign of * trailing ones basing on the significant coeff map, residual block and * total nnz. * * @param[in] pi2_res_block * Pointer to residual block containing levels in scan order * * @param[in] u4_total_coeff * Total non-zero coefficients in that sub block * * @param[in] pu1_zero_run * Pointer to array to store run of zeros * * @param[in] u4_sig_coeff_map * significant coefficient map * * @returns u4_totzero_sign_trailone * Bits 0-8 contains number of trailing ones. * Bits 8-16 contains bitwise sign information of trailing one * Bits 16-24 contains total number of zeros. * * @remarks * None * ******************************************************************************* */ static UWORD32 isvce_compute_zeroruns_and_trailingones(WORD16 *pi2_res_block, UWORD32 u4_total_coeff, UWORD8 *pu1_zero_run, UWORD32 u4_sig_coeff_map) { UWORD32 i = 0; UWORD32 u4_nnz_coeff = 0; WORD32 i4_run = -1; UWORD32 u4_sign = 0; UWORD32 u4_tot_zero = 0; UWORD32 u4_trailing1 = 0; WORD32 i4_val; UWORD32 u4_totzero_sign_trailone; UWORD32 *pu4_zero_run; pu4_zero_run = (void *) pu1_zero_run; pu4_zero_run[0] = 0; pu4_zero_run[1] = 0; pu4_zero_run[2] = 0; pu4_zero_run[3] = 0; /* Compute Runs of zeros for all nnz coefficients except the last 3 */ if(u4_total_coeff > 3) { for(i = 0; u4_nnz_coeff < (u4_total_coeff - 3); i++) { i4_run++; i4_val = (u4_sig_coeff_map & 0x1); u4_sig_coeff_map >>= 1; if(i4_val != 0) { pu1_zero_run[u4_nnz_coeff++] = i4_run; i4_run = -1; } } } /* Compute T1's, Signof(T1's) and Runs of zeros for the last 3 */ while(u4_nnz_coeff != u4_total_coeff) { i4_run++; i4_val = (u4_sig_coeff_map & 0x1); u4_sig_coeff_map >>= 1; if(i4_val != 0) { if(pi2_res_block[u4_nnz_coeff] == 1) { pu1_zero_run[u4_nnz_coeff] = i4_run; u4_trailing1++; } else { if(pi2_res_block[u4_nnz_coeff] == -1) { pu1_zero_run[u4_nnz_coeff] = i4_run; u4_sign |= 1 << u4_trailing1; u4_trailing1++; } else { pu1_zero_run[u4_nnz_coeff] = i4_run; u4_trailing1 = 0; u4_sign = 0; } } i4_run = -1; u4_nnz_coeff++; } i++; } u4_tot_zero = i - u4_total_coeff; u4_totzero_sign_trailone = (u4_tot_zero << 16) | (u4_sign << 8) | u4_trailing1; return (u4_totzero_sign_trailone); } /** ******************************************************************************* * * @brief * This function generates CAVLC coded bit stream for the given residual block * * @param[in] pi2_res_block * Pointer to residual block containing levels in scan order * * @param[in] u4_total_coeff * Total non-zero coefficients in the sub block * * @param[in] u4_block_type * block type * * @param[in] pu1_zero_run * Pointer to array to store run of zeros * * @param[in] u4_nc * average of non zero coeff from top and left blocks (when available) * * @param[in, out] ps_bit_stream * structure pointing to a buffer holding output bit stream * * @param[in] u4_sig_coeff_map * significant coefficient map of the residual block * * @returns * error code * * @remarks * If the block type is CAVLC_CHROMA_4x4_DC, then u4_nc is non-significant * ******************************************************************************* */ static IH264E_ERROR_T isvce_write_coeff4x4_cavlc(WORD16 *pi2_res_block, UWORD32 u4_total_coeff, ENTROPY_BLK_TYPE u4_block_type, UWORD8 *pu1_zero_run, UWORD32 u4_nc, bitstrm_t *ps_bit_stream, UWORD32 u4_sig_coeff_map) { IH264E_ERROR_T error_status = IH264E_SUCCESS; UWORD32 u4_totzero_sign_trailone = 0; UWORD32 u4_trailing_ones = 0; UWORD32 u4_tot_zeros = 0; UWORD32 u4_remaining_coeff = 0; UWORD32 u4_sign1 = 0; UWORD32 u4_max_num_coeff = 0; const UWORD32 au4_max_num_nnz_coeff[] = {16, 15, 16, 4, 15}; /* validate inputs */ ASSERT(u4_block_type <= CAVLC_CHROMA_4x4_AC); u4_max_num_coeff = au4_max_num_nnz_coeff[u4_block_type]; ASSERT(u4_total_coeff <= u4_max_num_coeff); if(!u4_total_coeff) { UWORD32 u4_codeword = 15; UWORD32 u4_codesize = 1; if(u4_block_type == CAVLC_CHROMA_4x4_DC) { u4_codeword = 1; u4_codesize = 2; DEBUG("\n[%d numcoeff, %d numtrailing ones]", u4_total_coeff, 0); ENTROPY_TRACE("\tnumber of non zero coeffs ", u4_total_coeff); ENTROPY_TRACE("\tnumber of trailing ones ", 0); } else { UWORD32 u4_vlcnum = u4_nc >> 1; /* write coeff_token */ if(u4_vlcnum > 3) { /* Num-FLC */ u4_codeword = 3; u4_codesize = 6; } else { /* Num-VLC 0, 1, 2 */ if(u4_vlcnum > 1) { u4_vlcnum = 2; } u4_codesize <<= u4_vlcnum; u4_codeword >>= (4 - u4_codesize); } DEBUG("\n[%d numcoeff, %d numtrailing ones, %d nnz]", u4_total_coeff, 0, u4_nc); ENTROPY_TRACE("\tnumber of non zero coeffs ", u4_total_coeff); ENTROPY_TRACE("\tnC ", u4_nc); } DEBUG("\nCOEFF TOKEN 0: %d u4_codeword, %d u4_codesize", u4_codeword, u4_codesize); ENTROPY_TRACE("\tcodeword ", u4_codeword); ENTROPY_TRACE("\tcodesize ", u4_codesize); error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize); return error_status; } else { /* Compute zero run, number of trailing ones and their sign. */ u4_totzero_sign_trailone = isvce_compute_zeroruns_and_trailingones( pi2_res_block, u4_total_coeff, pu1_zero_run, u4_sig_coeff_map); u4_trailing_ones = u4_totzero_sign_trailone & 0xFF; u4_sign1 = (u4_totzero_sign_trailone >> 8) & 0xFF; u4_tot_zeros = (u4_totzero_sign_trailone >> 16) & 0xFF; u4_remaining_coeff = u4_total_coeff - u4_trailing_ones; /* write coeff_token */ { UWORD32 u4_codeword; UWORD32 u4_codesize; if(u4_block_type == CAVLC_CHROMA_4x4_DC) { u4_codeword = gu1_code_coeff_token_table_chroma[u4_trailing_ones][u4_total_coeff - 1]; u4_codesize = gu1_size_coeff_token_table_chroma[u4_trailing_ones][u4_total_coeff - 1]; DEBUG("\n[%d numcoeff, %d numtrailing ones]", u4_total_coeff, u4_trailing_ones); ENTROPY_TRACE("\tnumber of non zero coeffs ", u4_total_coeff); ENTROPY_TRACE("\tnumber of trailing ones ", u4_trailing_ones); } else { UWORD32 u4_vlcnum = u4_nc >> 1; if(u4_vlcnum > 3) { /* Num-FLC */ u4_codeword = ((u4_total_coeff - 1) << 2) + u4_trailing_ones; u4_codesize = 6; } else { /* Num-VLC 0, 1, 2 */ if(u4_vlcnum > 1) { u4_vlcnum = 2; } u4_codeword = gu1_code_coeff_token_table[u4_vlcnum][u4_trailing_ones][u4_total_coeff - 1]; u4_codesize = gu1_size_coeff_token_table[u4_vlcnum][u4_trailing_ones][u4_total_coeff - 1]; } DEBUG("\n[%d numcoeff, %d numtrailing ones, %d nnz]", u4_total_coeff, u4_trailing_ones, u4_nc); ENTROPY_TRACE("\tnumber of non zero coeffs ", u4_total_coeff); ENTROPY_TRACE("\tnumber of trailing ones ", u4_trailing_ones); ENTROPY_TRACE("\tnC ", u4_nc); } DEBUG("\nCOEFF TOKEN 0: %d u4_codeword, %d u4_codesize", u4_codeword, u4_codesize); ENTROPY_TRACE("\tcodeword ", u4_codeword); ENTROPY_TRACE("\tcodesize ", u4_codesize); error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize); } /* write sign of trailing ones */ if(u4_trailing_ones) { DEBUG("\nT1's: %d u4_codeword, %d u4_codesize", u4_sign1, u4_trailing_ones); error_status = ih264e_put_bits(ps_bit_stream, u4_sign1, u4_trailing_ones); ENTROPY_TRACE("\tnumber of trailing ones ", u4_trailing_ones); ENTROPY_TRACE("\tsign of trailing ones ", u4_sign1); } /* write level codes */ if(u4_remaining_coeff) { WORD32 i4_level = pi2_res_block[u4_remaining_coeff - 1]; UWORD32 u4_escape; UWORD32 u4_suffix_length = 0; // Level-VLC[N] UWORD32 u4_abs_level, u4_abs_level_actual = 0; WORD32 i4_sign; const UWORD32 u4_rndfactor[] = {0, 0, 1, 3, 7, 15, 31}; DEBUG("\n \t%d coeff,", i4_level); ENTROPY_TRACE("\tcoeff ", i4_level); if(u4_trailing_ones < 3) { /* If there are less than 3 T1s, then the first non-T1 level is * incremented if negative (decremented if positive)*/ if(i4_level < 0) { i4_level += 1; } else { i4_level -= 1; } u4_abs_level_actual = 1; /* Initialize VLC table (Suffix Length) to encode the level */ if(u4_total_coeff > 10) { u4_suffix_length = 1; } } i4_sign = (i4_level >> (sizeof(WORD32) * CHAR_BIT - 1)); u4_abs_level = ((i4_level + i4_sign) ^ i4_sign); u4_abs_level_actual += u4_abs_level; u4_escape = (u4_abs_level + u4_rndfactor[u4_suffix_length]) >> u4_suffix_length; while(1) { UWORD32 u4_codesize; UWORD32 u4_codeword; UWORD32 u4_codeval; u4_remaining_coeff--; GATHER_CAVLC_STATS1(); { u4_codeval = u4_abs_level << 1; u4_codeval = u4_codeval - 2 - i4_sign; if((!u4_suffix_length) && (u4_escape > 7) && (u4_abs_level < 16)) { u4_codeword = (1 << 4) + (u4_codeval - 14); u4_codesize = 19; } else if(u4_escape > 7) { u4_codeword = (1 << 12) + (u4_codeval - (15 << u4_suffix_length)); u4_codesize = 28; if(!u4_suffix_length) { u4_codeword -= 15; } } else { u4_codeword = (1 << u4_suffix_length) + (u4_codeval & ((1 << u4_suffix_length) - 1)); u4_codesize = (u4_codeval >> u4_suffix_length) + 1 + u4_suffix_length; } } /*put the level code in bitstream*/ DEBUG("\nLEVEL: %d u4_codeword, %d u4_codesize", u4_codeword, u4_codesize); ENTROPY_TRACE("\tcodeword ", u4_codeword); ENTROPY_TRACE("\tcodesize ", u4_codesize); error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize); if(u4_remaining_coeff == 0) break; /*update suffix length for next level*/ if(u4_suffix_length == 0) { u4_suffix_length++; } if(u4_suffix_length < 6) { if(u4_abs_level_actual > gu1_threshold_vlc_level[u4_suffix_length]) { u4_suffix_length++; } } /* next level */ i4_level = pi2_res_block[u4_remaining_coeff - 1]; DEBUG("\n \t%d coeff,", i4_level); ENTROPY_TRACE("\tcoeff ", i4_level); i4_sign = (i4_level >> (sizeof(WORD32) * CHAR_BIT - 1)); u4_abs_level = ((i4_level + i4_sign) ^ i4_sign); u4_abs_level_actual = u4_abs_level; u4_escape = (u4_abs_level + u4_rndfactor[u4_suffix_length]) >> u4_suffix_length; } } DEBUG("\n \t %d totalzeros", u4_tot_zeros); ENTROPY_TRACE("\ttotal zeros ", u4_tot_zeros); /* Write Total Zeros */ if(u4_total_coeff < u4_max_num_coeff) { WORD32 index; UWORD32 u4_codeword; UWORD32 u4_codesize; if(u4_block_type == CAVLC_CHROMA_4x4_DC) { UWORD8 gu1_index_zero_table_chroma[] = {0, 4, 7}; index = gu1_index_zero_table_chroma[u4_total_coeff - 1] + u4_tot_zeros; u4_codesize = gu1_size_zero_table_chroma[index]; u4_codeword = gu1_code_zero_table_chroma[index]; } else { index = gu1_index_zero_table[u4_total_coeff - 1] + u4_tot_zeros; u4_codesize = gu1_size_zero_table[index]; u4_codeword = gu1_code_zero_table[index]; } DEBUG("\nTOTAL ZEROS: %d u4_codeword, %d u4_codesize", u4_codeword, u4_codesize); ENTROPY_TRACE("\tcodeword ", u4_codeword); ENTROPY_TRACE("\tcodesize ", u4_codesize); error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize); } /* Write Run Before */ if(u4_tot_zeros) { UWORD32 u4_max_num_coef = u4_total_coeff - 1; UWORD32 u4_codeword; UWORD32 u4_codesize; UWORD32 u4_zeros_left = u4_tot_zeros; while(u4_max_num_coef) { UWORD32 u4_run_before = pu1_zero_run[u4_max_num_coef]; UWORD32 u4_index; if(u4_zeros_left > MAX_ZERO_LEFT) { u4_index = gu1_index_run_table[MAX_ZERO_LEFT]; } else { u4_index = gu1_index_run_table[u4_zeros_left - 1]; } u4_codesize = gu1_size_run_table[u4_index + u4_run_before]; u4_codeword = gu1_code_run_table[u4_index + u4_run_before]; DEBUG("\nRUN BEFORE ZEROS: %d u4_codeword, %d u4_codesize", u4_codeword, u4_codesize); ENTROPY_TRACE("\tcodeword ", u4_codeword); ENTROPY_TRACE("\tcodesize ", u4_codesize); error_status = ih264e_put_bits(ps_bit_stream, u4_codeword, u4_codesize); u4_zeros_left -= u4_run_before; if(!u4_zeros_left) { break; } u4_max_num_coef--; } } } return error_status; } /** ******************************************************************************* * * @brief * This function generates CAVLC coded bit stream for the given subblock * * @param[in] ps_ent_ctxt * Pointer to entropy context * * @param[in] pi2_res_block * Pointers to residual blocks of all the partitions for the current subblk * (containing levels in scan order) * * @param[in] pu1_nnz * Total non-zero coefficients of all the partitions for the current subblk * * @param[in] pu2_sig_coeff_map * Significant coefficient map of all the partitions for the current subblk * * @param[in] u4_block_type * entropy coding block type * * @param[in] u4_ngbr_avbl * top and left availability of all the partitions for the current subblk * (packed) * * @param[in] pu1_top_nnz * pointer to the buffer containing nnz of all the subblks to the top * * @param[in] pu1_left_nnz * pointer to the buffer containing nnz of all the subblks to the left * * @returns error status * * @remarks none * ******************************************************************************* */ static IH264E_ERROR_T isvce_write_coeff8x8_cavlc(isvce_entropy_ctxt_t *ps_ent_ctxt, WORD16 **pi2_res_block, UWORD8 *pu1_nnz, UWORD16 *pu2_sig_coeff_map, ENTROPY_BLK_TYPE u4_block_type, UWORD32 u4_ngbr_avlb, UWORD8 *pu1_top_nnz, UWORD8 *pu1_left_nnz) { IH264E_ERROR_T error_status = IH264E_SUCCESS; bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; UWORD8 *pu1_zero_run = ps_ent_ctxt->au1_zero_run, *pu1_ngbr_avbl; UWORD32 u4_nC; UWORD8 u1_mb_a, u1_mb_b; pu1_ngbr_avbl = (void *) (&u4_ngbr_avlb); /* encode ac block index 4x4 = 0*/ u1_mb_a = pu1_ngbr_avbl[0] & 0x0F; u1_mb_b = pu1_ngbr_avbl[0] & 0xF0; u4_nC = 0; if(u1_mb_a) u4_nC += pu1_left_nnz[0]; if(u1_mb_b) u4_nC += pu1_top_nnz[0]; if(u1_mb_a && u1_mb_b) u4_nC = (u4_nC + 1) >> 1; pu1_left_nnz[0] = pu1_top_nnz[0] = pu1_nnz[0]; error_status = isvce_write_coeff4x4_cavlc(pi2_res_block[0], pu1_nnz[0], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[0]); /* encode ac block index 4x4 = 1*/ u1_mb_a = pu1_ngbr_avbl[1] & 0x0F; u1_mb_b = pu1_ngbr_avbl[1] & 0xF0; u4_nC = 0; if(u1_mb_a) u4_nC += pu1_left_nnz[0]; if(u1_mb_b) u4_nC += pu1_top_nnz[1]; if(u1_mb_a && u1_mb_b) u4_nC = (u4_nC + 1) >> 1; pu1_left_nnz[0] = pu1_top_nnz[1] = pu1_nnz[1]; error_status = isvce_write_coeff4x4_cavlc(pi2_res_block[1], pu1_nnz[1], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[1]); /* encode ac block index 4x4 = 2*/ u1_mb_a = pu1_ngbr_avbl[2] & 0x0F; u1_mb_b = pu1_ngbr_avbl[2] & 0xF0; u4_nC = 0; if(u1_mb_a) u4_nC += pu1_left_nnz[1]; if(u1_mb_b) u4_nC += pu1_top_nnz[0]; if(u1_mb_a && u1_mb_b) u4_nC = (u4_nC + 1) >> 1; pu1_left_nnz[1] = pu1_top_nnz[0] = pu1_nnz[2]; error_status = isvce_write_coeff4x4_cavlc(pi2_res_block[2], pu1_nnz[2], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[2]); /* encode ac block index 4x4 = 0*/ u1_mb_a = pu1_ngbr_avbl[3] & 0x0F; u1_mb_b = pu1_ngbr_avbl[3] & 0xF0; u4_nC = 0; if(u1_mb_a) u4_nC += pu1_left_nnz[1]; if(u1_mb_b) u4_nC += pu1_top_nnz[1]; if(u1_mb_a && u1_mb_b) u4_nC = (u4_nC + 1) >> 1; pu1_left_nnz[1] = pu1_top_nnz[1] = pu1_nnz[3]; error_status = isvce_write_coeff4x4_cavlc(pi2_res_block[3], pu1_nnz[3], u4_block_type, pu1_zero_run, u4_nC, ps_bitstream, pu2_sig_coeff_map[3]); return error_status; } /** ******************************************************************************* * * @brief * This function encodes luma and chroma residues of a macro block when * the entropy coding mode chosen is cavlc. * * @param[in] ps_ent_ctxt * Pointer to entropy context * * @param[in] u4_mb_type * current mb type * * @param[in] u4_cbp * coded block pattern for the current mb * * @returns error code * * @remarks none * ******************************************************************************* */ static IH264E_ERROR_T isvce_encode_residue(isvce_entropy_ctxt_t *ps_ent_ctxt, UWORD32 u4_mb_type, UWORD32 u4_cbp) { /* error status */ IH264E_ERROR_T error_status = IH264E_SUCCESS; /* packed residue */ void *pv_mb_coeff_data = ps_ent_ctxt->pv_mb_coeff_data; /* bit stream buffer */ bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; /* zero run */ UWORD8 *pu1_zero_run = ps_ent_ctxt->au1_zero_run; /* temp var */ UWORD32 u4_nC, u4_ngbr_avlb; UWORD8 au1_nnz[4], *pu1_ngbr_avlb, *pu1_top_nnz, *pu1_left_nnz; UWORD16 au2_sig_coeff_map[4] = {0}; WORD16 *pi2_res_block[4] = {NULL}; UWORD8 *pu1_slice_idx = ps_ent_ctxt->pu1_slice_idx; tu_sblk_coeff_data_t *ps_mb_coeff_data; ENTROPY_BLK_TYPE e_entropy_blk_type = CAVLC_LUMA_4x4; /* ngbr availability */ UWORD8 u1_mb_a, u1_mb_b; /* cbp */ UWORD32 u4_cbp_luma = u4_cbp & 0xF, u4_cbp_chroma = u4_cbp >> 4; /* mb indices */ WORD32 i4_mb_x, i4_mb_y; /* derive neighbor availability */ i4_mb_x = ps_ent_ctxt->i4_mb_x; i4_mb_y = ps_ent_ctxt->i4_mb_y; pu1_slice_idx += (i4_mb_y * ps_ent_ctxt->i4_wd_mbs); /* left macroblock availability */ u1_mb_a = (i4_mb_x == 0 || (pu1_slice_idx[i4_mb_x - 1] != pu1_slice_idx[i4_mb_x])) ? 0 : 1; /* top macroblock availability */ u1_mb_b = (i4_mb_y == 0 || (pu1_slice_idx[i4_mb_x - ps_ent_ctxt->i4_wd_mbs] != pu1_slice_idx[i4_mb_x])) ? 0 : 1; pu1_ngbr_avlb = (void *) (&u4_ngbr_avlb); pu1_top_nnz = ps_ent_ctxt->pu1_top_nnz_luma[ps_ent_ctxt->i4_mb_x]; pu1_left_nnz = (UWORD8 *) &ps_ent_ctxt->u4_left_nnz_luma; /* encode luma residue */ /* mb type intra 16x16 */ if(u4_mb_type == I16x16) { /* parse packed coeff data structure for residual data */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); /* estimate nnz for the current mb */ u4_nC = 0; if(u1_mb_a) u4_nC += pu1_left_nnz[0]; if(u1_mb_b) u4_nC += pu1_top_nnz[0]; if(u1_mb_a && u1_mb_b) u4_nC = (u4_nC + 1) >> 1; /* encode dc block */ ENTROPY_TRACE("Luma DC blk idx %d", 0); error_status = isvce_write_coeff4x4_cavlc(pi2_res_block[0], au1_nnz[0], CAVLC_LUMA_4x4_DC, pu1_zero_run, u4_nC, ps_bitstream, au2_sig_coeff_map[0]); e_entropy_blk_type = CAVLC_LUMA_4x4_AC; } if(u4_cbp_luma & 1) { /* encode ac block index 8x8 = 0*/ /* parse packed coeff data structure for residual data */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]); /* derive sub block neighbor availability */ pu1_ngbr_avlb[0] = (u1_mb_b << 4) | (u1_mb_a); pu1_ngbr_avlb[1] = (u1_mb_b << 4) | 1; pu1_ngbr_avlb[2] = (1 << 4) | (u1_mb_a); pu1_ngbr_avlb[3] = 0x11; /* encode sub blk */ ENTROPY_TRACE("Luma blk idx %d", 0); error_status = isvce_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz, pu1_left_nnz); } else { pu1_top_nnz[0] = pu1_top_nnz[1] = 0; pu1_left_nnz[0] = pu1_left_nnz[1] = 0; } if(u4_cbp_luma & 2) { /* encode ac block index 8x8 = 1*/ /* parse packed coeff data structure for residual data */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]); /* derive sub block neighbor availability */ pu1_ngbr_avlb[1] = pu1_ngbr_avlb[0] = (u1_mb_b << 4) | 1; pu1_ngbr_avlb[3] = pu1_ngbr_avlb[2] = 0x11; /* encode sub blk */ ENTROPY_TRACE("Luma blk idx %d", 1); error_status = isvce_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz + 2, pu1_left_nnz); } else { (pu1_top_nnz + 2)[0] = (pu1_top_nnz + 2)[1] = 0; pu1_left_nnz[0] = pu1_left_nnz[1] = 0; } if(u4_cbp_luma & 0x4) { /* encode ac block index 8x8 = 2*/ /* parse packed coeff data structure for residual data */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]); /* derive sub block neighbor availability */ pu1_ngbr_avlb[2] = pu1_ngbr_avlb[0] = (1 << 4) | u1_mb_a; pu1_ngbr_avlb[1] = pu1_ngbr_avlb[3] = 0x11; /* encode sub blk */ ENTROPY_TRACE("Luma blk idx %d", 2); error_status = isvce_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz, (pu1_left_nnz + 2)); } else { pu1_top_nnz[0] = pu1_top_nnz[1] = 0; (pu1_left_nnz + 2)[0] = (pu1_left_nnz + 2)[1] = 0; } if(u4_cbp_luma & 0x8) { /* encode ac block index 8x8 = 3*/ /* parse packed coeff data structure for residual data */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]); /* derive sub block neighbor availability */ u4_ngbr_avlb = 0x11111111; /* encode sub blk */ ENTROPY_TRACE("Luma blk idx %d", 3); error_status = isvce_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, e_entropy_blk_type, u4_ngbr_avlb, pu1_top_nnz + 2, pu1_left_nnz + 2); } else { (pu1_top_nnz + 2)[0] = (pu1_top_nnz + 2)[1] = 0; (pu1_left_nnz + 2)[0] = (pu1_left_nnz + 2)[1] = 0; } /* encode chroma residue */ if(u4_cbp_chroma & 3) { /* parse packed coeff data structure for residual data */ /* cb, cr */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]); /* encode dc block */ /* cb, cr */ ENTROPY_TRACE("Chroma DC blk idx %d", 0); error_status = isvce_write_coeff4x4_cavlc(pi2_res_block[0], au1_nnz[0], CAVLC_CHROMA_4x4_DC, pu1_zero_run, 0, ps_bitstream, au2_sig_coeff_map[0]); ENTROPY_TRACE("Chroma DC blk idx %d", 1); error_status = isvce_write_coeff4x4_cavlc(pi2_res_block[1], au1_nnz[1], CAVLC_CHROMA_4x4_DC, pu1_zero_run, 0, ps_bitstream, au2_sig_coeff_map[1]); } pu1_top_nnz = ps_ent_ctxt->pu1_top_nnz_cbcr[ps_ent_ctxt->i4_mb_x]; pu1_left_nnz = (UWORD8 *) &ps_ent_ctxt->u4_left_nnz_cbcr; /* encode sub blk */ if(u4_cbp_chroma & 0x2) { /* encode ac block index 8x8 = 0*/ /* derive sub block neighbor availability */ pu1_ngbr_avlb[0] = (u1_mb_b << 4) | (u1_mb_a); pu1_ngbr_avlb[1] = (u1_mb_b << 4) | 1; pu1_ngbr_avlb[2] = (1 << 4) | (u1_mb_a); pu1_ngbr_avlb[3] = 0x11; /* parse packed coeff data structure for residual data */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]); ENTROPY_TRACE("Chroma AC blk idx %d", 0); error_status = isvce_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, CAVLC_CHROMA_4x4_AC, u4_ngbr_avlb, pu1_top_nnz, pu1_left_nnz); } else { pu1_top_nnz[0] = pu1_top_nnz[1] = 0; pu1_left_nnz[0] = pu1_left_nnz[1] = 0; } pu1_top_nnz += 2; pu1_left_nnz += 2; /* encode sub blk */ if(u4_cbp_chroma & 0x2) { /* parse packed coeff data structure for residual data */ PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[0], au2_sig_coeff_map[0], pi2_res_block[0]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[1], au2_sig_coeff_map[1], pi2_res_block[1]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[2], au2_sig_coeff_map[2], pi2_res_block[2]); PARSE_COEFF_DATA_BLOCK_4x4(pv_mb_coeff_data, ps_mb_coeff_data, au1_nnz[3], au2_sig_coeff_map[3], pi2_res_block[3]); ENTROPY_TRACE("Chroma AC blk idx %d", 1); error_status = isvce_write_coeff8x8_cavlc(ps_ent_ctxt, pi2_res_block, au1_nnz, au2_sig_coeff_map, CAVLC_CHROMA_4x4_AC, u4_ngbr_avlb, pu1_top_nnz, pu1_left_nnz); } else { pu1_top_nnz[0] = pu1_top_nnz[1] = 0; pu1_left_nnz[0] = pu1_left_nnz[1] = 0; } /* store the index of the next mb coeff data */ ps_ent_ctxt->pv_mb_coeff_data = pv_mb_coeff_data; return error_status; } /** ******************************************************************************* * * @brief * This function generates CAVLC coded bit stream for an Intra Slice. * * @description * The mb syntax layer for intra slices constitutes luma mb mode, luma sub modes * (if present), 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 isvce_write_islice_mb_cavlc(isvce_entropy_ctxt_t *ps_ent_ctxt) { /* error status */ IH264E_ERROR_T error_status = IH264E_SUCCESS; /* bit stream ptr */ bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; /* packed header data */ UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data; isvce_mb_hdr_common_t *ps_mb_hdr = (isvce_mb_hdr_common_t *) ps_ent_ctxt->pv_mb_header_data; /* mb header info */ /* * mb_tpm : mb type plus mode * mb_type : luma mb type and chroma mb type are packed * cbp : coded block pattern * mb_qp_delta : mb qp delta * chroma_intra_mode : chroma intra mode * luma_intra_mode : luma intra mode */ WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode; WORD8 mb_qp_delta; /* temp var */ WORD32 i, mb_type_stream; WORD32 bitstream_start_offset, bitstream_end_offset; svc_slice_header_t *ps_svc_slice_header = ps_ent_ctxt->ps_svc_slice_hdr_base + (ps_ent_ctxt->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT); /* Starting bitstream offset for header in bits */ bitstream_start_offset = isvce_get_num_bits(ps_bitstream); /********************************************************************/ /* BEGIN HEADER GENERATION */ /********************************************************************/ if(ps_ent_ctxt->u1_spatial_layer_id && ps_svc_slice_header->i1_adaptive_base_mode_flag) { /* write base_mode_flag */ PUT_BITS(ps_bitstream, ps_mb_hdr->u1_base_mode_flag, 1, error_status, "base_mode_flag"); } else { ps_mb_hdr->u1_base_mode_flag = 0; } /* mb header info */ mb_tpm = ps_mb_hdr->u1_mb_type_mode; cbp = ps_mb_hdr->u1_cbp; mb_qp_delta = ((WORD16) ps_mb_hdr->u1_mb_qp) - ((WORD16) ps_ent_ctxt->ps_mb_qp_ctxt->u1_cur_mb_qp); /* mb type */ mb_type = mb_tpm & 0xF; /* is intra ? */ if(!ps_mb_hdr->u1_base_mode_flag) { if(mb_type == I16x16) { UWORD32 u4_cbp_l, u4_cbp_c; u4_cbp_c = (cbp >> 4); u4_cbp_l = (cbp & 0xF); luma_intra_mode = (mb_tpm >> 4) & 3; chroma_intra_mode = (mb_tpm >> 6); mb_type_stream = luma_intra_mode + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12; /* write mb type */ PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type"); /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i16x16_t); } else if(mb_type == I4x4) { isvce_mb_hdr_i4x4_t *ps_mb_hdr_i4x4 = (isvce_mb_hdr_i4x4_t *) ps_ent_ctxt->pv_mb_header_data; /* mb sub blk modes */ WORD32 intra_pred_mode_flag, rem_intra_mode; WORD32 byte; chroma_intra_mode = (mb_tpm >> 6); /* write mb type */ PUT_BITS_UEV(ps_bitstream, 0, error_status, "mb type"); for(i = 0; i < 16; i += 2) { /* sub blk idx 1 */ byte = ps_mb_hdr_i4x4->au1_sub_blk_modes[i >> 1]; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } /* sub blk idx 2 */ byte >>= 4; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } } /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i4x4_t); } else if(mb_type == I8x8) { /* transform 8x8 flag */ UWORD32 u4_transform_size_8x8_flag = ps_ent_ctxt->i1_transform_8x8_mode_flag; isvce_mb_hdr_i8x8_t *ps_mb_hdr_i8x8 = (isvce_mb_hdr_i8x8_t *) ps_ent_ctxt->pv_mb_header_data; /* mb sub blk modes */ WORD32 intra_pred_mode_flag, rem_intra_mode; WORD32 byte; chroma_intra_mode = (mb_tpm >> 6); ASSERT(0); /* write mb type */ PUT_BITS_UEV(ps_bitstream, 0, error_status, "mb type"); /* u4_transform_size_8x8_flag */ PUT_BITS(ps_bitstream, u4_transform_size_8x8_flag, 1, error_status, "u4_transform_size_8x8_flag"); /* write sub block modes */ for(i = 0; i < 4; i++) { /* sub blk idx 1 */ byte = ps_mb_hdr_i8x8->au1_sub_blk_modes[i >> 1]; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } /* sub blk idx 2 */ byte >>= 4; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } } /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i8x8_t); } } else { pu1_byte += sizeof(isvce_mb_hdr_base_mode_t); } /* coded_block_pattern */ if(ps_mb_hdr->u1_base_mode_flag || mb_type != I16x16) { PUT_BITS_UEV(ps_bitstream, gu1_cbp_map_tables[cbp][ps_mb_hdr->u1_base_mode_flag], error_status, "coded_block_pattern"); if(cbp % 16 > 0 && ps_ent_ctxt->i1_transform_8x8_mode_flag && (ps_mb_hdr->u1_base_mode_flag || (mb_type == I8x8 || mb_type == I4x4))) { PUT_BITS(ps_bitstream, ps_ent_ctxt->i1_transform_8x8_mode_flag, 1, error_status, "u4_transform_size_8x8_flag"); } } if((cbp > 0) || (mb_type == I16x16)) { /* mb_qp_delta */ PUT_BITS_SEV(ps_bitstream, mb_qp_delta, error_status, "mb_qp_delta"); ps_ent_ctxt->ps_mb_qp_ctxt->u1_cur_mb_qp = ps_mb_hdr->u1_mb_qp; } /* Ending bitstream offset for header in bits */ bitstream_end_offset = isvce_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; /* residual */ error_status = isvce_encode_residue(ps_ent_ctxt, mb_type, cbp); /* Ending bitstream offset for reside in bits */ bitstream_end_offset = isvce_get_num_bits(ps_bitstream); ps_ent_ctxt->u4_residue_bits[0] += bitstream_end_offset - bitstream_start_offset; /* store the index of the next mb syntax layer */ ps_ent_ctxt->pv_mb_header_data = pu1_byte; return error_status; } /** ******************************************************************************* * * @brief * This function generates CAVLC coded bit stream for Inter slices * * @description * The mb syntax layer for inter slices constitutes luma mb mode, luma sub modes * (if present), 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 isvce_write_pslice_mb_cavlc(isvce_entropy_ctxt_t *ps_ent_ctxt) { /* mb header info */ /* * mb_tpm : mb type plus mode * mb_type : luma mb type and chroma mb type are packed * cbp : coded block pattern * mb_qp_delta : mb qp delta * chroma_intra_mode : chroma intra mode * luma_intra_mode : luma intra mode * ps_pu : Pointer to the array of structures having motion vectors, size * and position of sub partitions */ WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode; WORD8 mb_qp_delta; WORD32 i, mb_type_stream; WORD32 bitstream_start_offset, bitstream_end_offset; UWORD8 u1_is_intra_mb; bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; isvce_mb_hdr_common_t *ps_mb_hdr = (isvce_mb_hdr_common_t *) ps_ent_ctxt->pv_mb_header_data; svc_slice_header_t *ps_svc_slice_header = ps_ent_ctxt->ps_svc_slice_hdr_base + (ps_ent_ctxt->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT); IH264E_ERROR_T error_status = IH264E_SUCCESS; UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data; WORD32 cbptable = 1; WORD32 is_inter = 0; /* Starting bitstream offset for header in bits */ bitstream_start_offset = isvce_get_num_bits(ps_bitstream); /********************************************************************/ /* BEGIN HEADER GENERATION */ /********************************************************************/ /* mb header info */ mb_tpm = ps_mb_hdr->u1_mb_type_mode; /* mb type */ mb_type = mb_tpm & 0xF; u1_is_intra_mb = (mb_type == I16x16) || (mb_type == I8x8) || (mb_type == I4x4); /* check for skip */ if(mb_type == PSKIP) { UWORD32 *nnz; is_inter = 1; /* increment skip counter */ (*ps_ent_ctxt->pi4_mb_skip_run)++; /* store the index of the next mb syntax layer */ pu1_byte += sizeof(isvce_mb_hdr_pskip_t); ps_ent_ctxt->pv_mb_header_data = pu1_byte; /* set nnz to zero */ ps_ent_ctxt->u4_left_nnz_luma = 0; nnz = (UWORD32 *) ps_ent_ctxt->pu1_top_nnz_luma[ps_ent_ctxt->i4_mb_x]; *nnz = 0; ps_ent_ctxt->u4_left_nnz_cbcr = 0; nnz = (UWORD32 *) ps_ent_ctxt->pu1_top_nnz_cbcr[ps_ent_ctxt->i4_mb_x]; *nnz = 0; /* residual */ error_status = isvce_encode_residue(ps_ent_ctxt, P16x16, 0); bitstream_end_offset = isvce_get_num_bits(ps_bitstream); ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset - bitstream_start_offset; return error_status; } /* remaining mb header info */ cbp = ps_mb_hdr->u1_cbp; mb_qp_delta = ((WORD16) ps_mb_hdr->u1_mb_qp) - ((WORD16) ps_ent_ctxt->ps_mb_qp_ctxt->u1_cur_mb_qp); /* mb skip run */ PUT_BITS_UEV(ps_bitstream, *ps_ent_ctxt->pi4_mb_skip_run, error_status, "mb skip run"); /* reset skip counter */ *ps_ent_ctxt->pi4_mb_skip_run = 0; if(ps_ent_ctxt->u1_spatial_layer_id && ps_svc_slice_header->i1_adaptive_base_mode_flag) { /* write base_mode_flag */ PUT_BITS(ps_bitstream, ps_mb_hdr->u1_base_mode_flag, 1, error_status, "base_mode_flag"); } else { ps_mb_hdr->u1_base_mode_flag = 0; } if(!ps_mb_hdr->u1_base_mode_flag) { /* is intra ? */ if(mb_type == I16x16) { UWORD32 u4_cbp_l, u4_cbp_c; is_inter = 0; u4_cbp_c = (cbp >> 4); u4_cbp_l = (cbp & 0xF); luma_intra_mode = (mb_tpm >> 4) & 3; chroma_intra_mode = (mb_tpm >> 6); mb_type_stream = luma_intra_mode + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12; mb_type_stream += 5; /* write mb type */ PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type"); /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i16x16_t); } else if(mb_type == I4x4) { isvce_mb_hdr_i4x4_t *ps_mb_hdr_i4x4 = (isvce_mb_hdr_i4x4_t *) ps_ent_ctxt->pv_mb_header_data; /* mb sub blk modes */ WORD32 intra_pred_mode_flag, rem_intra_mode; WORD32 byte; is_inter = 0; chroma_intra_mode = (mb_tpm >> 6); cbptable = 0; /* write mb type */ PUT_BITS_UEV(ps_bitstream, 5, error_status, "mb type"); for(i = 0; i < 16; i += 2) { /* sub blk idx 1 */ byte = ps_mb_hdr_i4x4->au1_sub_blk_modes[i >> 1]; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } /* sub blk idx 2 */ byte >>= 4; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } } /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i4x4_t); } else if(mb_type == I8x8) { isvce_mb_hdr_i8x8_t *ps_mb_hdr_i8x8 = (isvce_mb_hdr_i8x8_t *) ps_ent_ctxt->pv_mb_header_data; /* transform 8x8 flag */ UWORD32 u4_transform_size_8x8_flag = ps_ent_ctxt->i1_transform_8x8_mode_flag; /* mb sub blk modes */ WORD32 intra_pred_mode_flag, rem_intra_mode; WORD32 byte; is_inter = 0; chroma_intra_mode = (mb_tpm >> 6); cbptable = 0; ASSERT(0); /* write mb type */ PUT_BITS_UEV(ps_bitstream, 5, error_status, "mb type"); /* u4_transform_size_8x8_flag */ PUT_BITS(ps_bitstream, u4_transform_size_8x8_flag, 1, error_status, "u4_transform_size_8x8_flag"); /* write sub block modes */ for(i = 0; i < 4; i++) { /* sub blk idx 1 */ byte = ps_mb_hdr_i8x8->au1_sub_blk_modes[i >> 1]; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } /* sub blk idx 2 */ byte >>= 4; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } } /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i8x8_t); } else { isvce_mb_hdr_p16x16_t *ps_mb_hdr_p16x16 = (isvce_mb_hdr_p16x16_t *) ps_ent_ctxt->pv_mb_header_data; /* inter macro block partition cnt */ const UWORD8 au1_part_cnt[] = {1, 2, 2, 4}; /* mv ptr */ WORD16 *pi2_mv_ptr = (WORD16 *) ps_mb_hdr_p16x16->ai2_mvd; /* number of partitions for the current mb */ UWORD32 u4_part_cnt = au1_part_cnt[mb_type - 3]; is_inter = 1; /* write mb type */ PUT_BITS_UEV(ps_bitstream, mb_type - 3, error_status, "mb type"); for(i = 0; i < (WORD32) u4_part_cnt; i++) { if(ps_ent_ctxt->u1_spatial_layer_id && ps_svc_slice_header->i1_adaptive_motion_prediction_flag) { PUT_BITS(ps_bitstream, ps_mb_hdr_p16x16->u1_mvp_idx, 1, error_status, "motion_prediction_flag_l0"); } } for(i = 0; i < (WORD32) u4_part_cnt; i++) { PUT_BITS_SEV(ps_bitstream, pi2_mv_ptr[i], error_status, "mv x"); PUT_BITS_SEV(ps_bitstream, pi2_mv_ptr[i + 1], error_status, "mv y"); } pu1_byte += sizeof(isvce_mb_hdr_p16x16_t); } } else { pu1_byte += sizeof(isvce_mb_hdr_base_mode_t); } if(ps_ent_ctxt->u1_spatial_layer_id && ps_svc_slice_header->i1_adaptive_residual_prediction_flag && !ps_ent_ctxt ->ps_svc_nalu_ext_base[1 + (ps_ent_ctxt->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT)] .u1_idr_flag && (ps_mb_hdr->u1_base_mode_flag || !u1_is_intra_mb)) { PUT_BITS(ps_bitstream, ps_mb_hdr->u1_residual_prediction_flag, 1, error_status, "residual_prediction_flag"); } /* coded_block_pattern */ if(ps_mb_hdr->u1_base_mode_flag || (mb_type != I16x16)) { PUT_BITS_UEV(ps_bitstream, gu1_cbp_map_tables[cbp][cbptable], error_status, "coded_block_pattern"); } if((cbp > 0) || (mb_type == I16x16)) { /* mb_qp_delta */ PUT_BITS_SEV(ps_bitstream, mb_qp_delta, error_status, "mb_qp_delta"); ps_ent_ctxt->ps_mb_qp_ctxt->u1_cur_mb_qp = ps_mb_hdr->u1_mb_qp; } /* Ending bitstream offset for header in bits */ bitstream_end_offset = isvce_get_num_bits(ps_bitstream); ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset - bitstream_start_offset; /* start bitstream offset for residue in bits */ bitstream_start_offset = bitstream_end_offset; /* residual */ error_status = isvce_encode_residue(ps_ent_ctxt, mb_type, cbp); /* Ending bitstream offset for residue in bits */ bitstream_end_offset = isvce_get_num_bits(ps_bitstream); ps_ent_ctxt->u4_residue_bits[is_inter] += bitstream_end_offset - bitstream_start_offset; /* store the index of the next mb syntax layer */ ps_ent_ctxt->pv_mb_header_data = pu1_byte; return error_status; } /** ******************************************************************************* * * @brief * This function generates CAVLC coded bit stream for B slices * * @description * The mb syntax layer for inter slices constitutes luma mb mode, luma sub modes * (if present), 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 isvce_write_bslice_mb_cavlc(isvce_entropy_ctxt_t *ps_ent_ctxt) { /* mb header info */ /* * mb_tpm : mb type plus mode * mb_type : luma mb type and chroma mb type are packed * cbp : coded block pattern * mb_qp_delta : mb qp delta * chroma_intra_mode : chroma intra mode * luma_intra_mode : luma intra mode * ps_pu : Pointer to the array of structures having motion vectors, size * and position of sub partitions */ WORD32 mb_tpm, mb_type, cbp, chroma_intra_mode, luma_intra_mode; WORD8 mb_qp_delta; WORD32 i, j; WORD32 mb_type_stream; WORD32 bitstream_start_offset, bitstream_end_offset; UWORD8 u1_is_intra_mb; bitstrm_t *ps_bitstream = ps_ent_ctxt->ps_bitstrm; isvce_mb_hdr_common_t *ps_mb_hdr = (isvce_mb_hdr_common_t *) ps_ent_ctxt->pv_mb_header_data; svc_slice_header_t *ps_svc_slice_header = ps_ent_ctxt->ps_svc_slice_hdr_base + (ps_ent_ctxt->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT); IH264E_ERROR_T error_status = IH264E_SUCCESS; UWORD8 *pu1_byte = ps_ent_ctxt->pv_mb_header_data; WORD32 cbptable = 1; WORD32 is_inter = 0; /* Starting bitstream offset for header in bits */ bitstream_start_offset = isvce_get_num_bits(ps_bitstream); /********************************************************************/ /* BEGIN HEADER GENERATION */ /********************************************************************/ mb_tpm = ps_mb_hdr->u1_mb_type_mode; /* mb type */ mb_type = mb_tpm & 0xF; u1_is_intra_mb = (mb_type == I16x16) || (mb_type == I8x8) || (mb_type == I4x4); /* check for skip */ if(mb_type == BSKIP) { UWORD32 *nnz; is_inter = 1; /* increment skip counter */ (*ps_ent_ctxt->pi4_mb_skip_run)++; /* store the index of the next mb syntax layer */ pu1_byte += sizeof(isvce_mb_hdr_bskip_t); ps_ent_ctxt->pv_mb_header_data = pu1_byte; /* set nnz to zero */ ps_ent_ctxt->u4_left_nnz_luma = 0; nnz = (UWORD32 *) ps_ent_ctxt->pu1_top_nnz_luma[ps_ent_ctxt->i4_mb_x]; *nnz = 0; ps_ent_ctxt->u4_left_nnz_cbcr = 0; nnz = (UWORD32 *) ps_ent_ctxt->pu1_top_nnz_cbcr[ps_ent_ctxt->i4_mb_x]; *nnz = 0; /* residual */ error_status = isvce_encode_residue(ps_ent_ctxt, B16x16, 0); bitstream_end_offset = isvce_get_num_bits(ps_bitstream); ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset - bitstream_start_offset; return error_status; } /* remaining mb header info */ cbp = ps_mb_hdr->u1_cbp; mb_qp_delta = ((WORD16) ps_mb_hdr->u1_mb_qp) - ((WORD16) ps_ent_ctxt->ps_mb_qp_ctxt->u1_cur_mb_qp); /* mb skip run */ PUT_BITS_UEV(ps_bitstream, *ps_ent_ctxt->pi4_mb_skip_run, error_status, "mb skip run"); /* reset skip counter */ *ps_ent_ctxt->pi4_mb_skip_run = 0; if(ps_ent_ctxt->u1_spatial_layer_id && ps_svc_slice_header->i1_adaptive_base_mode_flag) { /* write base_mode_flag */ PUT_BITS(ps_bitstream, ps_mb_hdr->u1_base_mode_flag, 1, error_status, "base_mode_flag"); } else { ps_mb_hdr->u1_base_mode_flag = 0; } if(!ps_mb_hdr->u1_base_mode_flag) { /* is intra ? */ if(mb_type == I16x16) { UWORD32 u4_cbp_l, u4_cbp_c; is_inter = 0; u4_cbp_c = (cbp >> 4); u4_cbp_l = (cbp & 0xF); luma_intra_mode = (mb_tpm >> 4) & 3; chroma_intra_mode = (mb_tpm >> 6); mb_type_stream = luma_intra_mode + 1 + (u4_cbp_c << 2) + (u4_cbp_l == 15) * 12; mb_type_stream += 23; /* write mb type */ PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type"); /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i16x16_t); } else if(mb_type == I4x4) { isvce_mb_hdr_i4x4_t *ps_mb_hdr_i4x4 = (isvce_mb_hdr_i4x4_t *) ps_ent_ctxt->pv_mb_header_data; /* mb sub blk modes */ WORD32 intra_pred_mode_flag, rem_intra_mode; WORD32 byte; is_inter = 0; chroma_intra_mode = (mb_tpm >> 6); cbptable = 0; /* write mb type */ PUT_BITS_UEV(ps_bitstream, 23, error_status, "mb type"); for(i = 0; i < 16; i += 2) { /* sub blk idx 1 */ byte = ps_mb_hdr_i4x4->au1_sub_blk_modes[i >> 1]; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } /* sub blk idx 2 */ byte >>= 4; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } } /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i4x4_t); } else if(mb_type == I8x8) { isvce_mb_hdr_i8x8_t *ps_mb_hdr_i8x8 = (isvce_mb_hdr_i8x8_t *) ps_ent_ctxt->pv_mb_header_data; /* transform 8x8 flag */ UWORD32 u4_transform_size_8x8_flag = ps_ent_ctxt->i1_transform_8x8_mode_flag; /* mb sub blk modes */ WORD32 intra_pred_mode_flag, rem_intra_mode; WORD32 byte; is_inter = 0; chroma_intra_mode = (mb_tpm >> 6); cbptable = 0; ASSERT(0); /* write mb type */ PUT_BITS_UEV(ps_bitstream, 23, error_status, "mb type"); /* u4_transform_size_8x8_flag */ PUT_BITS(ps_bitstream, u4_transform_size_8x8_flag, 1, error_status, "u4_transform_size_8x8_flag"); /* write sub block modes */ for(i = 0; i < 4; i++) { /* sub blk idx 1 */ byte = ps_mb_hdr_i8x8->au1_sub_blk_modes[i >> 1]; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } /* sub blk idx 2 */ byte >>= 4; intra_pred_mode_flag = byte & 0x1; /* prev_intra4x4_pred_mode_flag */ PUT_BITS(ps_bitstream, intra_pred_mode_flag, 1, error_status, "prev_intra4x4_pred_mode_flag"); /* rem_intra4x4_pred_mode */ if(!intra_pred_mode_flag) { rem_intra_mode = (byte & 0xF) >> 1; PUT_BITS(ps_bitstream, rem_intra_mode, 3, error_status, "rem_intra4x4_pred_mode"); } } /* intra_chroma_pred_mode */ PUT_BITS_UEV(ps_bitstream, chroma_intra_mode, error_status, "intra_chroma_pred_mode"); pu1_byte += sizeof(isvce_mb_hdr_i8x8_t); } else if(mb_type == BDIRECT) { is_inter = 1; /* write mb type */ PUT_BITS_UEV(ps_bitstream, B_DIRECT_16x16, error_status, "mb type"); pu1_byte += sizeof(isvce_mb_hdr_bdirect_t); } else { isvce_mb_hdr_b16x16_t *ps_mb_hdr_b16x16 = (isvce_mb_hdr_b16x16_t *) ps_ent_ctxt->pv_mb_header_data; /* inter macro block partition cnt for 16x16 16x8 8x16 8x8 */ const UWORD8 au1_part_cnt[] = {1, 2, 2, 4}; /* number of partitions for the current mb */ UWORD32 u4_part_cnt = au1_part_cnt[mb_type - B16x16]; /* Get the pred modes */ WORD32 i4_mb_part_pred_mode = (mb_tpm >> 4); ASSERT(mb_type == B16x16); is_inter = 1; mb_type_stream = mb_type - B16x16 + B_L0_16x16 + i4_mb_part_pred_mode; /* write mb type */ PUT_BITS_UEV(ps_bitstream, mb_type_stream, error_status, "mb type"); for(i = 0; i < (WORD32) u4_part_cnt; i++) { for(j = 0; j < NUM_PRED_DIRS; j++) { PRED_MODE_T e_pred_mode = (PRED_MODE_T) j; PRED_MODE_T e_cmpl_pred_mode = (e_pred_mode == L0) ? L1 : L0; if(((PRED_MODE_T) i4_mb_part_pred_mode) != e_pred_mode) { if(ps_svc_slice_header->i1_adaptive_motion_prediction_flag && ps_ent_ctxt->u1_spatial_layer_id) { PUT_BITS(ps_bitstream, ps_mb_hdr_b16x16->au1_mvp_idx[e_cmpl_pred_mode], 1, error_status, "motion_prediction_flag_l0"); } } } } for(i = 0; i < (WORD32) u4_part_cnt; i++) { if(i4_mb_part_pred_mode != L1) { PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mvd[0][0], error_status, "mv l0 x"); PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mvd[0][1], error_status, "mv l0 y"); } if(i4_mb_part_pred_mode != L0) { PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mvd[1][0], error_status, "mv l1 x"); PUT_BITS_SEV(ps_bitstream, ps_mb_hdr_b16x16->ai2_mvd[1][1], error_status, "mv l1 y"); } } pu1_byte += sizeof(isvce_mb_hdr_b16x16_t); } } if(ps_svc_slice_header->i1_adaptive_residual_prediction_flag && ps_ent_ctxt->u1_spatial_layer_id && (ps_mb_hdr->u1_base_mode_flag || !u1_is_intra_mb)) { PUT_BITS(ps_bitstream, ps_mb_hdr->u1_residual_prediction_flag, 1, error_status, "residual_prediction_flag"); } /* coded_block_pattern */ if(ps_mb_hdr->u1_base_mode_flag || mb_type != I16x16) { PUT_BITS_UEV(ps_bitstream, gu1_cbp_map_tables[cbp][cbptable], error_status, "coded_block_pattern"); } if((cbp > 0) || (mb_type == I16x16)) { /* mb_qp_delta */ PUT_BITS_SEV(ps_bitstream, mb_qp_delta, error_status, "mb_qp_delta"); ps_ent_ctxt->ps_mb_qp_ctxt->u1_cur_mb_qp = ps_mb_hdr->u1_mb_qp; } /* Ending bitstream offset for header in bits */ bitstream_end_offset = isvce_get_num_bits(ps_bitstream); ps_ent_ctxt->u4_header_bits[is_inter] += bitstream_end_offset - bitstream_start_offset; /* start bitstream offset for residue in bits */ bitstream_start_offset = bitstream_end_offset; /* residual */ error_status = isvce_encode_residue(ps_ent_ctxt, mb_type, cbp); /* Ending bitstream offset for residue in bits */ bitstream_end_offset = isvce_get_num_bits(ps_bitstream); ps_ent_ctxt->u4_residue_bits[is_inter] += bitstream_end_offset - bitstream_start_offset; /* store the index of the next mb syntax layer */ ps_ent_ctxt->pv_mb_header_data = pu1_byte; return error_status; } #if ENABLE_RE_ENC_AS_SKIP /** ****************************************************************************** * * @brief re-encode frame as all skip MBs * * @par Description * The frame is encoded as all skip MBs to comply with VBV restrictions * * @param[in] ps_entropy * pointer to entropy context (handle) * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T isvce_reencode_as_skip_frame_cavlc(isvce_entropy_ctxt_t *ps_entropy) { WORD32 i4_mb_skip_run; bitstrm_t *ps_bitstrm = ps_entropy->ps_bitstrm; bitstrm_t *ps_bitstrm_after_slice_hdr = ps_entropy->ps_bitstrm_after_slice_hdr; ps_bitstrm->i4_bits_left_in_cw = ps_bitstrm_after_slice_hdr->i4_bits_left_in_cw; ps_bitstrm->u4_cur_word = ps_bitstrm_after_slice_hdr->u4_cur_word; ps_bitstrm->u4_strm_buf_offset = ps_bitstrm_after_slice_hdr->u4_strm_buf_offset; ps_bitstrm->i4_zero_bytes_run = ps_bitstrm_after_slice_hdr->i4_zero_bytes_run; /* mb skip run */ i4_mb_skip_run = ps_entropy->i4_wd_mbs * ps_entropy->i4_ht_mbs; PUT_BITS_UEV(ps_bitstrm, i4_mb_skip_run, ps_entropy->i4_error_code, "mb skip run"); /* put rbsp trailing bits */ ps_entropy->i4_error_code = ih264e_put_rbsp_trailing_bits(ps_bitstrm); return ps_entropy->i4_error_code; } #endif