/****************************************************************************** * * Copyright (C) 2018 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 ihevce_encode_header.c * * @brief * This file contains function definitions related to header encoding * * @author * Ittiam * * List of Functions * ihevce_generate_nal_unit_header * ihevce_generate_when_profile_present * ihevce_generate_profile_tier_level * ihevce_short_term_ref_pic_set * ihevce_generate_bit_rate_pic_rate_info * ihevce_generate_aud * ihevce_generate_eos * ihevce_generate_vps * ihevce_generate_sps * ihevce_generate_pps * ihevce_generate_slice_header * ihevce_populate_vps * ihevce_populate_sps * ihevce_populate_pps * ihevce_populate_slice_header * ihevce_insert_entry_offset_slice_header * ****************************************************************************** */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <stdarg.h> #include <math.h> /* User include files */ #include "ihevc_typedefs.h" #include "itt_video_api.h" #include "ihevce_api.h" #include "rc_cntrl_param.h" #include "rc_frame_info_collector.h" #include "rc_look_ahead_params.h" #include "ihevc_defs.h" #include "ihevc_macros.h" #include "ihevc_debug.h" #include "ihevc_structs.h" #include "ihevc_platform_macros.h" #include "ihevc_deblk.h" #include "ihevc_itrans_recon.h" #include "ihevc_chroma_itrans_recon.h" #include "ihevc_chroma_intra_pred.h" #include "ihevc_intra_pred.h" #include "ihevc_inter_pred.h" #include "ihevc_mem_fns.h" #include "ihevc_padding.h" #include "ihevc_weighted_pred.h" #include "ihevc_sao.h" #include "ihevc_resi_trans.h" #include "ihevc_quant_iquant_ssd.h" #include "ihevc_cabac_tables.h" #include "ihevc_trans_tables.h" #include "ihevc_trans_macros.h" #include "ihevce_defs.h" #include "ihevce_lap_enc_structs.h" #include "ihevce_multi_thrd_structs.h" #include "ihevce_multi_thrd_funcs.h" #include "ihevce_me_common_defs.h" #include "ihevce_had_satd.h" #include "ihevce_error_codes.h" #include "ihevce_error_checks.h" #include "ihevce_bitstream.h" #include "ihevce_cabac.h" #include "ihevce_rdoq_macros.h" #include "ihevce_function_selector.h" #include "ihevce_enc_structs.h" #include "ihevce_global_tables.h" #include "ihevce_encode_header.h" #include "ihevce_encode_header_sei_vui.h" #include "ihevce_trace.h" /*****************************************************************************/ /* Constant Macros */ /*****************************************************************************/ #define CU_LEVEL_QP_LIMIT_8x8 3 #define CU_LEVEL_QP_LIMIT_16x16 2 #define CU_LEVEL_QP_LIMIT_32x32 1 /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /** ****************************************************************************** * * @brief Generate nal unit header in the stream as per section 7.3.1.2 * * @par Description * Inserts the nal type and temporal id plus 1 as per section 7.3.1.2 Nal unit * header syntax * * @param[inout] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] nal_unit_type * nal type to be inserted * * @param[in] temporal id * temporal id to be inserted * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_generate_nal_unit_header( bitstrm_t *ps_bitstrm, WORD32 nal_unit_type, WORD32 nuh_temporal_id) { WORD32 return_status = IHEVCE_SUCCESS; /* sanity checks */ ASSERT((nal_unit_type >= 0) && (nal_unit_type < 64)); ASSERT((nuh_temporal_id >= 0) && (nuh_temporal_id < 7)); /* forbidden_zero_bit + nal_unit_type */ PUT_BITS( ps_bitstrm, nal_unit_type, (1 + 6), /*extra 1 is for forbidden zero bit */ return_status); /* nuh_reserved_zero_6bits */ PUT_BITS(ps_bitstrm, 0, 6, return_status); /* nuh_temporal_id_plus1 */ PUT_BITS(ps_bitstrm, (nuh_temporal_id + 1), 3, return_status); return (return_status); } /** ****************************************************************************** * * @brief Generates fields related to Profile, Tier and Level data. * * @par Description * Generates fields related to Profile, Tier and Level data. * Called when profile_present flag is 1 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_ptl * pointer to structure containing Profile, Tier and Level data data * * @return success or failure error code * ****************************************************************************** */ static WORD32 ihevce_generate_when_profile_present(bitstrm_t *ps_bitstrm, profile_tier_lvl_t *ps_ptl) { WORD32 return_status = IHEVCE_SUCCESS; WORD32 i; /* XXX_profile_space[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_profile_space, 2, return_status); ENTROPY_TRACE("XXX_profile_space[]", ps_ptl->i1_profile_space); /* XXX_tier_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_tier_flag, 1, return_status); ENTROPY_TRACE("XXX_tier_flag[]", ps_ptl->i1_tier_flag); /* XXX_profile_idc[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_profile_idc, 5, return_status); ENTROPY_TRACE("XXX_profile_idc[]", ps_ptl->i1_profile_idc); for(i = 0; i < MAX_PROFILE_COMPATBLTY; i++) { /* XXX_profile_compatibility_flag[][j] */ PUT_BITS(ps_bitstrm, ps_ptl->ai1_profile_compatibility_flag[i], 1, return_status); ENTROPY_TRACE( "XXX_profile_compatibility_flag[][j]", ps_ptl->ai1_profile_compatibility_flag[i]); } /* XXX_progressive_source_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_progressive_source_flag, 1, return_status); ENTROPY_TRACE("XXX_progressive_source_flag[]", ps_ptl->i1_general_progressive_source_flag); /* XXX_interlaced_source_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_interlaced_source_flag, 1, return_status); ENTROPY_TRACE("XXX_interlaced_source_flag[]", ps_ptl->i1_general_interlaced_source_flag); /* XXX_non_packed_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_non_packed_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_non_packed_constraint_flag[]", ps_ptl->i1_general_non_packed_constraint_flag); /* XXX_frame_only_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_frame_only_constraint_flag, 1, return_status); ENTROPY_TRACE("XXX_frame_only_constraint_flag[]", ps_ptl->i1_frame_only_constraint_flag); /* XXX_general_max_12bit_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_max_12bit_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_max_12bit_constraint_flag[]", ps_ptl->i1_general_max_12bit_constraint_flag); /* XXX_general_max_10bit_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_max_10bit_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_max_10bit_constraint_flag[]", ps_ptl->i1_general_max_10bit_constraint_flag); /* XXX_general_max_8bit_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_max_8bit_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_max_8bit_constraint_flag[]", ps_ptl->i1_general_max_8bit_constraint_flag); /* XXX_general_max_422chroma_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_max_422chroma_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_max_422chroma_constraint_flag[]", ps_ptl->i1_general_max_422chroma_constraint_flag); /* XXX_general_max_420chroma_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_max_420chroma_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_max_420chroma_constraint_flag[]", ps_ptl->i1_general_max_420chroma_constraint_flag); /* XXX_general_max_monochrome_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_max_monochrome_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_max_monochrome_constraint_flag[]", ps_ptl->i1_general_max_monochrome_constraint_flag); /* XXX_general_intra_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_intra_constraint_flag, 1, return_status); ENTROPY_TRACE("XXX_general_intra_constraint_flag[]", ps_ptl->i1_general_intra_constraint_flag); /* XXX_general_one_picture_only_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_one_picture_only_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_one_picture_only_constraint_flag[]", ps_ptl->i1_general_one_picture_only_constraint_flag); /* XXX_general_lower_bit_rate_constraint_flag[] */ PUT_BITS(ps_bitstrm, ps_ptl->i1_general_lower_bit_rate_constraint_flag, 1, return_status); ENTROPY_TRACE( "XXX_general_lower_bit_rate_constraint_flag[]", ps_ptl->i1_general_lower_bit_rate_constraint_flag); /* XXX_reserved_zero_35bits[] */ PUT_BITS(ps_bitstrm, 0, 16, return_status); PUT_BITS(ps_bitstrm, 0, 16, return_status); PUT_BITS(ps_bitstrm, 0, 3, return_status); ENTROPY_TRACE("XXX_reserved_zero_35bits[]", 0); return return_status; } /** ****************************************************************************** * * @brief Generates Profile, Tier and Level data * * @par Description * Generates Profile, Tier and Level data as per Section 7.3.3 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_ptl * pointer to structure containing Profile, Tier and Level data data * * @param[in] i1_profile_present_flag * flag that indicates whether profile-related data is present * * @param[in] i1_vps_max_sub_layers_minus1 * (Maximum number of sub_layers present) minus 1 * * @return success or failure error code * ****************************************************************************** */ static WORD32 ihevce_generate_profile_tier_level( bitstrm_t *ps_bitstrm, profile_tier_lvl_info_t *ps_ptl, WORD8 i1_profile_present_flag, WORD8 i1_max_sub_layers_minus1) { WORD32 i; WORD32 return_status = IHEVCE_SUCCESS; if(i1_profile_present_flag) { ihevce_generate_when_profile_present(ps_bitstrm, &ps_ptl->s_ptl_gen); } /* general_level_idc */ PUT_BITS(ps_bitstrm, ps_ptl->s_ptl_gen.u1_level_idc, 8, return_status); ENTROPY_TRACE("general_level_idc", ps_ptl->s_ptl_gen.u1_level_idc); for(i = 0; i < i1_max_sub_layers_minus1; i++) { /* sub_layer_profile_present_flag[i] */ PUT_BITS(ps_bitstrm, ps_ptl->ai1_sub_layer_profile_present_flag[i], 1, return_status); ENTROPY_TRACE( "sub_layer_profile_present_flag[i]", ps_ptl->ai1_sub_layer_profile_present_flag[i]); /* sub_layer_level_present_flag[i] */ PUT_BITS(ps_bitstrm, ps_ptl->ai1_sub_layer_level_present_flag[i], 1, return_status); ENTROPY_TRACE( "sub_layer_level_present_flag[i]", ps_ptl->ai1_sub_layer_level_present_flag[i]); } if(i1_max_sub_layers_minus1 > 0) { for(i = i1_max_sub_layers_minus1; i < 8; i++) { /* reserved_zero_2bits[i] */ PUT_BITS(ps_bitstrm, 0, 2, return_status); ENTROPY_TRACE("reserved_zero_2bits[i]", 0); } } for(i = 0; i < i1_max_sub_layers_minus1; i++) { if(ps_ptl->ai1_sub_layer_profile_present_flag[i]) { ihevce_generate_when_profile_present(ps_bitstrm, &ps_ptl->as_ptl_sub[i]); } if(ps_ptl->ai1_sub_layer_level_present_flag[i]) //TEMPORALA_SCALABILITY CHANGES BUG_FIX { /* sub_layer_level_idc[i] */ PUT_BITS(ps_bitstrm, ps_ptl->as_ptl_sub[i].u1_level_idc, 8, return_status); ENTROPY_TRACE("sub_layer_level_idc[i]", ps_ptl->as_ptl_sub[i].u1_level_idc); } } return return_status; } /** ******************************************************************************* * * @brief * Generates short term reference picture set * * @par Description * Generates short term reference picture set as per section 7.3.5.2. * Can be called by either SPS or Slice header parsing modules. * * @param[in] ps_bitstrm * Pointer to bitstream structure * * @param[out] ps_stref_picset_base * Pointer to first short term ref pic set structure * * @param[in] num_short_term_ref_pic_sets * Number of short term reference pic sets * * @param[in] idx * Current short term ref pic set id * * @returns Error code from WORD32 * * ******************************************************************************* */ static WORD32 ihevce_short_term_ref_pic_set( bitstrm_t *ps_bitstrm, stref_picset_t *ps_stref_picset_base, WORD32 num_short_term_ref_pic_sets, WORD32 idx, WORD32 *pi4_NumPocTotalCurr) { WORD32 i; WORD32 return_status = IHEVCE_SUCCESS; stref_picset_t *ps_stref_picset = ps_stref_picset_base + idx; (void)num_short_term_ref_pic_sets; if(idx > 0) { /* inter_ref_pic_set_prediction_flag */ PUT_BITS( ps_bitstrm, ps_stref_picset->i1_inter_ref_pic_set_prediction_flag, 1, return_status); ENTROPY_TRACE( "inter_ref_pic_set_prediction_flag", ps_stref_picset->i1_inter_ref_pic_set_prediction_flag); } /* This flag is assumed to be 0 for now */ ASSERT(0 == ps_stref_picset->i1_inter_ref_pic_set_prediction_flag); /* num_negative_pics */ PUT_BITS_UEV(ps_bitstrm, ps_stref_picset->i1_num_neg_pics, return_status); ENTROPY_TRACE("num_negative_pics", ps_stref_picset->i1_num_neg_pics); /* num_positive_pics */ PUT_BITS_UEV(ps_bitstrm, ps_stref_picset->i1_num_pos_pics, return_status); ENTROPY_TRACE("num_positive_pics", ps_stref_picset->i1_num_pos_pics); for(i = 0; i < ps_stref_picset->i1_num_neg_pics; i++) { /* delta_poc_s0_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_stref_picset->ai2_delta_poc[i] - 1, return_status); ENTROPY_TRACE("delta_poc_s0_minus1", ps_stref_picset->ai2_delta_poc[i] - 1); /* used_by_curr_pic_s0_flag */ PUT_BITS(ps_bitstrm, ps_stref_picset->ai1_used[i], 1, return_status); ENTROPY_TRACE("used_by_curr_pic_s0_flag", ps_stref_picset->ai1_used[i]); /*get the num pocs used for cur pic*/ if(ps_stref_picset->ai1_used[i]) { *pi4_NumPocTotalCurr += 1; } } for(; i < (ps_stref_picset->i1_num_pos_pics + ps_stref_picset->i1_num_neg_pics); i++) { /* delta_poc_s1_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_stref_picset->ai2_delta_poc[i] - 1, return_status); ENTROPY_TRACE("delta_poc_s1_minus1", ps_stref_picset->ai2_delta_poc[i] - 1); /* used_by_curr_pic_s1_flag */ PUT_BITS(ps_bitstrm, ps_stref_picset->ai1_used[i], 1, return_status); ENTROPY_TRACE("used_by_curr_pic_s1_flag", ps_stref_picset->ai1_used[i]); /*get the num pocs used for cur pic*/ if(ps_stref_picset->ai1_used[i]) { *pi4_NumPocTotalCurr += 1; } } return return_status; } /** ****************************************************************************** * * @brief Generates ref pic list modification * * @par Description * Generate ref pic list modification syntax as per Section 7.3.6.2 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_slice_hdr * pointer to structure containing slice header * * @return success or failure error code * ****************************************************************************** */ static WORD32 ref_pic_list_modification( bitstrm_t *ps_bitstrm, slice_header_t *ps_slice_hdr, WORD32 i4_NumPocTotalCurr) { WORD32 return_status = IHEVCE_SUCCESS; WORD32 i; /* ref_pic_list_modification_flag_l0 */ PUT_BITS( ps_bitstrm, ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0, 1, return_status); ENTROPY_TRACE( "ref_pic_list_modification_flag_l0", ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0); if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0) { for(i = 0; i <= (ps_slice_hdr->i1_num_ref_idx_l0_active - 1); i++) { WORD32 num_bits = 32 - CLZ(i4_NumPocTotalCurr - 1); /* list_entry_l0[ i ] */ PUT_BITS(ps_bitstrm, ps_slice_hdr->s_rplm.i1_list_entry_l0[i], num_bits, return_status); ENTROPY_TRACE("list_entry_l0", ps_slice_hdr->s_rplm.i1_list_entry_l0[i]); } } if((BSLICE == ps_slice_hdr->i1_slice_type)) { /* ref_pic_list_modification_flag_l1 */ PUT_BITS( ps_bitstrm, ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1, 1, return_status); ENTROPY_TRACE( "ref_pic_list_modification_flag_l1", ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1); if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1) { for(i = 0; i <= (ps_slice_hdr->i1_num_ref_idx_l1_active - 1); i++) { WORD32 num_bits = 32 - CLZ(i4_NumPocTotalCurr - 1); /* list_entry_l1[ i ] */ PUT_BITS( ps_bitstrm, ps_slice_hdr->s_rplm.i1_list_entry_l1[i], num_bits, return_status); ENTROPY_TRACE("list_entry_l1", ps_slice_hdr->s_rplm.i1_list_entry_l1[i]); } } } /*end of B slice check*/ return return_status; } /** ****************************************************************************** * * @brief Generates Pred Weight Table * * @par Description * Generate Pred Weight Table as per Section 7.3.5.4 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_sps * pointer to structure containing SPS data * * @param[in] ps_pps * pointer to structure containing PPS data * * @param[in] ps_slice_hdr * pointer to structure containing slice header * * @return success or failure error code * ****************************************************************************** */ static WORD32 ihevce_generate_pred_weight_table( bitstrm_t *ps_bitstrm, sps_t *ps_sps, pps_t *ps_pps, slice_header_t *ps_slice_hdr) { WORD32 i; WORD32 delta_luma_weight; WORD32 delta_chroma_weight; WORD32 return_status = IHEVCE_SUCCESS; pred_wt_ofst_t *ps_wt_ofst = &ps_slice_hdr->s_wt_ofst; UWORD32 u4_luma_log2_weight_denom = ps_wt_ofst->i1_luma_log2_weight_denom; WORD32 chroma_log2_weight_denom = (ps_wt_ofst->i1_chroma_log2_weight_denom); WORD32 i4_wght_count = 0; (void)ps_pps; /* luma_log2_weight_denom */ PUT_BITS_UEV(ps_bitstrm, u4_luma_log2_weight_denom, return_status); ENTROPY_TRACE("luma_log2_weight_denom", u4_luma_log2_weight_denom); if(ps_sps->i1_chroma_format_idc != 0) { /* delta_chroma_log2_weight_denom */ PUT_BITS_SEV( ps_bitstrm, chroma_log2_weight_denom - u4_luma_log2_weight_denom, return_status); ENTROPY_TRACE( "delta_chroma_log2_weight_denom", chroma_log2_weight_denom - u4_luma_log2_weight_denom); } for(i = 0; i < ps_slice_hdr->i1_num_ref_idx_l0_active; i++) { /* luma_weight_l0_flag[ i ] */ PUT_BITS(ps_bitstrm, ps_wt_ofst->i1_luma_weight_l0_flag[i], 1, return_status); i4_wght_count += ps_wt_ofst->i1_luma_weight_l0_flag[i]; assert(i4_wght_count <= 24); ENTROPY_TRACE("luma_weight_l0_flag[ i ]", ps_wt_ofst->i1_luma_weight_l0_flag[i]); } if(ps_sps->i1_chroma_format_idc != 0) { for(i = 0; i < ps_slice_hdr->i1_num_ref_idx_l0_active; i++) { /* chroma_weight_l0_flag[ i ] */ PUT_BITS(ps_bitstrm, ps_wt_ofst->i1_chroma_weight_l0_flag[i], 1, return_status); i4_wght_count += 2 * ps_wt_ofst->i1_chroma_weight_l0_flag[i]; assert(i4_wght_count <= 24); ENTROPY_TRACE("chroma_weight_l0_flag[ i ]", ps_wt_ofst->i1_chroma_weight_l0_flag[i]); } } delta_luma_weight = (1 << u4_luma_log2_weight_denom); delta_chroma_weight = (1 << chroma_log2_weight_denom); for(i = 0; i < ps_slice_hdr->i1_num_ref_idx_l0_active; i++) { if(ps_wt_ofst->i1_luma_weight_l0_flag[i]) { /* delta_luma_weight_l0[ i ] */ PUT_BITS_SEV( ps_bitstrm, ps_wt_ofst->i2_luma_weight_l0[i] - delta_luma_weight, return_status); ENTROPY_TRACE( "delta_luma_weight_l0[ i ]", ps_wt_ofst->i2_luma_weight_l0[i] - delta_luma_weight); /* luma_offset_l0[ i ] */ PUT_BITS_SEV(ps_bitstrm, ps_wt_ofst->i2_luma_offset_l0[i], return_status); ENTROPY_TRACE("luma_offset_l0[ i ]", ps_wt_ofst->i2_luma_offset_l0[i]); } if(ps_wt_ofst->i1_chroma_weight_l0_flag[i]) { WORD32 shift = (1 << (BIT_DEPTH_CHROMA - 1)); WORD32 delta_chroma_weight_l0[2]; WORD32 delta_chroma_offset_l0[2]; delta_chroma_weight_l0[0] = ps_wt_ofst->i2_chroma_weight_l0_cb[i] - delta_chroma_weight; delta_chroma_weight_l0[1] = ps_wt_ofst->i2_chroma_weight_l0_cr[i] - delta_chroma_weight; delta_chroma_offset_l0[0] = ps_wt_ofst->i2_chroma_offset_l0_cb[i] + ((shift * ps_wt_ofst->i2_chroma_weight_l0_cb[i]) >> chroma_log2_weight_denom) - shift; delta_chroma_offset_l0[1] = ps_wt_ofst->i2_chroma_offset_l0_cr[i] + ((shift * ps_wt_ofst->i2_chroma_weight_l0_cr[i]) >> chroma_log2_weight_denom) - shift; /* delta_chroma_weight_l0[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_weight_l0[0], return_status); ENTROPY_TRACE("delta_chroma_weight_l0[ i ]", delta_chroma_weight_l0[0]); /* delta_chroma_offset_l0[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_offset_l0[0], return_status); ENTROPY_TRACE("delta_chroma_offset_l0[ i ]", delta_chroma_offset_l0[0]); /* delta_chroma_weight_l0[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_weight_l0[1], return_status); ENTROPY_TRACE("delta_chroma_weight_l0[ i ]", delta_chroma_weight_l0[1]); /* delta_chroma_offset_l0[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_offset_l0[1], return_status); ENTROPY_TRACE("delta_chroma_offset_l0[ i ]", delta_chroma_offset_l0[1]); } } if(BSLICE == ps_slice_hdr->i1_slice_type) { for(i = 0; i < ps_slice_hdr->i1_num_ref_idx_l1_active; i++) { /* luma_weight_l1_flag[ i ] */ PUT_BITS(ps_bitstrm, ps_wt_ofst->i1_luma_weight_l1_flag[i], 1, return_status); i4_wght_count += ps_wt_ofst->i1_luma_weight_l1_flag[i]; assert(i4_wght_count <= 24); ENTROPY_TRACE("luma_weight_l1_flag[ i ]", ps_wt_ofst->i1_luma_weight_l1_flag[i]); } if(ps_sps->i1_chroma_format_idc != 0) { for(i = 0; i < ps_slice_hdr->i1_num_ref_idx_l1_active; i++) { /* chroma_weight_l1_flag[ i ] */ PUT_BITS(ps_bitstrm, ps_wt_ofst->i1_chroma_weight_l1_flag[i], 1, return_status); i4_wght_count += ps_wt_ofst->i1_chroma_weight_l1_flag[i]; assert(i4_wght_count <= 24); ENTROPY_TRACE( "chroma_weight_l1_flag[ i ]", ps_wt_ofst->i1_chroma_weight_l1_flag[i]); } } for(i = 0; i < ps_slice_hdr->i1_num_ref_idx_l1_active; i++) { if(ps_wt_ofst->i1_luma_weight_l1_flag[i]) { /* delta_luma_weight_l1[ i ] */ PUT_BITS_SEV( ps_bitstrm, ps_wt_ofst->i2_luma_weight_l1[i] - delta_luma_weight, return_status); ENTROPY_TRACE( "delta_luma_weight_l1[ i ]", ps_wt_ofst->i2_luma_weight_l1[i] - delta_luma_weight); /* luma_offset_l1[ i ] */ PUT_BITS_SEV(ps_bitstrm, ps_wt_ofst->i2_luma_offset_l1[i], return_status); ENTROPY_TRACE("luma_offset_l1[ i ]", ps_wt_ofst->i2_luma_offset_l1[i]); } if(ps_wt_ofst->i1_chroma_weight_l1_flag[i]) { WORD32 shift = (1 << (BIT_DEPTH_CHROMA - 1)); WORD32 delta_chroma_weight_l1[2]; WORD32 delta_chroma_offset_l1[2]; delta_chroma_weight_l1[0] = ps_wt_ofst->i2_chroma_weight_l1_cb[i] - delta_chroma_weight; delta_chroma_weight_l1[1] = ps_wt_ofst->i2_chroma_weight_l1_cr[i] - delta_chroma_weight; delta_chroma_offset_l1[0] = ps_wt_ofst->i2_chroma_offset_l1_cb[i] + ((shift * ps_wt_ofst->i2_chroma_weight_l1_cb[i]) >> chroma_log2_weight_denom) - shift; delta_chroma_offset_l1[1] = ps_wt_ofst->i2_chroma_offset_l1_cr[i] + ((shift * ps_wt_ofst->i2_chroma_weight_l1_cr[i]) >> chroma_log2_weight_denom) - shift; /* delta_chroma_weight_l1[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_weight_l1[0], return_status); ENTROPY_TRACE("delta_chroma_weight_l1[ i ]", delta_chroma_weight_l1[0]); /* delta_chroma_offset_l1[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_offset_l1[0], return_status); ENTROPY_TRACE("delta_chroma_offset_l1[ i ]", delta_chroma_offset_l1[0]); /* delta_chroma_weight_l1[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_weight_l1[1], return_status); ENTROPY_TRACE("delta_chroma_weight_l1[ i ]", delta_chroma_weight_l1[1]); /* delta_chroma_offset_l1[ i ][j] */ PUT_BITS_SEV(ps_bitstrm, delta_chroma_offset_l1[1], return_status); ENTROPY_TRACE("delta_chroma_offset_l1[ i ]", delta_chroma_offset_l1[1]); } } } return return_status; } /** ****************************************************************************** * * @brief Generates AUD (Access Unit Delimiter) * * @par Description * Generate Access Unit Delimiter as per Section 7.3.2.5 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] pic_type * picture type * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_generate_aud(bitstrm_t *ps_bitstrm, WORD32 pic_type) { WORD32 return_status = IHEVCE_SUCCESS; /* Insert the NAL start code */ return_status = ihevce_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ return_status |= ihevce_generate_nal_unit_header(ps_bitstrm, NAL_AUD, 0); /* pic_type */ PUT_BITS(ps_bitstrm, pic_type, 3, return_status); ENTROPY_TRACE("pic type", pic_type); ihevce_put_rbsp_trailing_bits(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Generates EOS (End of Sequence) * * @par Description * Generate End of sequence as per Section 7.3.2.6 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_generate_eos(bitstrm_t *ps_bitstrm) { WORD32 return_status = IHEVCE_SUCCESS; /* Insert the NAL start code */ return_status = ihevce_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ return_status |= ihevce_generate_nal_unit_header(ps_bitstrm, NAL_EOS, 0); ihevce_put_rbsp_trailing_bits(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Generates VPS (Video Parameter Set) * * @par Description * Generate Video Parameter Set as per Section 7.3.2.1 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_vps * pointer to structure containing VPS data * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_generate_vps(bitstrm_t *ps_bitstrm, vps_t *ps_vps) { WORD32 i; WORD8 i1_vps_max_sub_layers_minus1 = ps_vps->i1_vps_max_sub_layers - 1; WORD32 return_status = IHEVCE_SUCCESS; /* Insert Start Code */ ihevce_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ ihevce_generate_nal_unit_header(ps_bitstrm, NAL_VPS, 0); /* video_parameter_set_id */ PUT_BITS(ps_bitstrm, ps_vps->i1_vps_id, 4, return_status); ENTROPY_TRACE("video_parameter_set_id", ps_vps->i1_vps_id); /* vps_reserved_three_2bits */ PUT_BITS(ps_bitstrm, 3, 2, return_status); ENTROPY_TRACE("vps_reserved_three_2bits", 3); /* vps_max_layers_minus1 */ PUT_BITS(ps_bitstrm, 0, 6, return_status); ENTROPY_TRACE("vps_max_layers_minus1 ", 3); /* vps_max_sub_layers_minus1 */ PUT_BITS(ps_bitstrm, i1_vps_max_sub_layers_minus1, 3, return_status); ENTROPY_TRACE("vps_max_sub_layers_minus1", i1_vps_max_sub_layers_minus1); /* vps_temporal_id_nesting_flag */ PUT_BITS(ps_bitstrm, ps_vps->i1_vps_temporal_id_nesting_flag, 1, return_status); ENTROPY_TRACE("vps_temporal_id_nesting_flag", ps_vps->i1_vps_temporal_id_nesting_flag); /* vps_reserved_0xffff_16bits */ PUT_BITS(ps_bitstrm, 0xffff, 16, return_status); ENTROPY_TRACE("vps_reserved_0xffff_16bits", 0xffff); /* profile-tier and level info */ ihevce_generate_profile_tier_level(ps_bitstrm, &ps_vps->s_ptl, 1, i1_vps_max_sub_layers_minus1); /* vps_sub_layer_ordering_info_present_flag */ PUT_BITS(ps_bitstrm, ps_vps->i1_sub_layer_ordering_info_present_flag, 1, return_status); ENTROPY_TRACE( "vps_sub_layer_ordering_info_present_flag", ps_vps->i1_sub_layer_ordering_info_present_flag); i = ps_vps->i1_sub_layer_ordering_info_present_flag ? 0 : i1_vps_max_sub_layers_minus1; for(; i <= i1_vps_max_sub_layers_minus1; i++) { /* vps_max_dec_pic_buffering[i] */ PUT_BITS_UEV(ps_bitstrm, ps_vps->ai1_vps_max_dec_pic_buffering[i], return_status); ENTROPY_TRACE( "vps_max_dec_pic_buffering_minus1[i]", ps_vps->ai1_vps_max_dec_pic_buffering[i]); /* vps_num_reorder_pics[i] */ PUT_BITS_UEV(ps_bitstrm, ps_vps->ai1_vps_max_num_reorder_pics[i], return_status); ENTROPY_TRACE("ai1_vps_max_num_reorder_pics[i]", ps_vps->ai1_vps_max_num_reorder_pics[i]); /* vps_max_latency_increase[i] */ PUT_BITS_UEV(ps_bitstrm, ps_vps->ai1_vps_max_latency_increase[i], return_status); ENTROPY_TRACE("ai1_vps_max_latency_increase[i]", ps_vps->ai1_vps_max_latency_increase[i]); } /* vps_max_layer_id */ PUT_BITS(ps_bitstrm, ps_vps->i1_vps_max_nuh_reserved_zero_layer_id, 6, return_status); ENTROPY_TRACE("vps_max_layer_id", ps_vps->i1_vps_max_nuh_reserved_zero_layer_id); /* vps_num_layer_sets_minus1 */ PUT_BITS_UEV(ps_bitstrm, 0, return_status); ENTROPY_TRACE("vps_num_layer_sets_minus1", 0); /* vps_timing_info_present_flag */ PUT_BITS(ps_bitstrm, 0, 1, return_status); ENTROPY_TRACE("vps_timing_info_present_flag", 0); /* vps_extension_flag */ PUT_BITS(ps_bitstrm, 0, 1, return_status); ENTROPY_TRACE("vps_extension_flag", 0); /* rbsp trailing bits */ ihevce_put_rbsp_trailing_bits(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Generates SPS (Video Parameter Set) * * @par Description * Parse Video Parameter Set as per Section 7.3.2.2 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_sps * pointer to structure containing SPS data * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_generate_sps(bitstrm_t *ps_bitstrm, sps_t *ps_sps) { WORD32 i; WORD32 return_status = IHEVCE_SUCCESS; WORD8 i1_max_sub_layers_minus1 = ps_sps->i1_sps_max_sub_layers - 1; UWORD32 u4_log2_max_pic_order_cnt_lsb = (UWORD32)(ps_sps->i1_log2_max_pic_order_cnt_lsb); UWORD32 u4_log2_min_coding_block_size_minus3 = (UWORD32)(ps_sps->i1_log2_min_coding_block_size) - 3; UWORD32 u4_log2_diff_max_min_coding_block_size = (UWORD32)(ps_sps->i1_log2_diff_max_min_coding_block_size); UWORD32 u4_log2_min_transform_block_size_minus2 = (UWORD32)(ps_sps->i1_log2_min_transform_block_size) - 2; UWORD32 u4_log2_diff_max_min_transform_block_size = (UWORD32)(ps_sps->i1_log2_diff_max_min_transform_block_size); /* Insert Start Code */ return_status = ihevce_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ return_status |= ihevce_generate_nal_unit_header(ps_bitstrm, NAL_SPS, 0); /* video_parameter_set_id */ PUT_BITS(ps_bitstrm, ps_sps->i1_vps_id, 4, return_status); ENTROPY_TRACE("video_parameter_set_id", ps_sps->i1_vps_id); /* sps_max_sub_layers_minus1 */ PUT_BITS(ps_bitstrm, i1_max_sub_layers_minus1, 3, return_status); ENTROPY_TRACE("sps_max_sub_layers_minus1", i1_max_sub_layers_minus1); /* sps_temporal_id_nesting_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_sps_temporal_id_nesting_flag, 1, return_status); ENTROPY_TRACE("sps_temporal_id_nesting_flag", ps_sps->i1_sps_temporal_id_nesting_flag); /* profile-tier and level info */ ihevce_generate_profile_tier_level(ps_bitstrm, &ps_sps->s_ptl, 1, i1_max_sub_layers_minus1); /* seq_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_sps_id, return_status); ENTROPY_TRACE("seq_parameter_set_id", ps_sps->i1_sps_id); /* chroma_format_idc */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_chroma_format_idc, return_status); ENTROPY_TRACE("chroma_format_idc", ps_sps->i1_chroma_format_idc); if(CHROMA_FMT_IDC_YUV444 == ps_sps->i1_chroma_format_idc) { /* separate_colour_plane_flag */ PUT_BITS(ps_bitstrm, 1, 1, return_status); ENTROPY_TRACE("separate_colour_plane_flag", 1); } /* pic_width_in_luma_samples */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_width_in_luma_samples, return_status); ENTROPY_TRACE("pic_width_in_luma_samples", ps_sps->i2_pic_width_in_luma_samples); /* pic_height_in_luma_samples */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_height_in_luma_samples, return_status); ENTROPY_TRACE("pic_height_in_luma_samples", ps_sps->i2_pic_height_in_luma_samples); /* pic_cropping_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_pic_cropping_flag, 1, return_status); ENTROPY_TRACE("pic_cropping_flag", ps_sps->i1_pic_cropping_flag); if(ps_sps->i1_pic_cropping_flag) { /* pic_crop_left_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_crop_left_offset, return_status); ENTROPY_TRACE("pic_crop_left_offset", ps_sps->i2_pic_crop_left_offset); /* pic_crop_right_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_crop_right_offset, return_status); ENTROPY_TRACE("pic_crop_right_offset", ps_sps->i2_pic_crop_right_offset); /* pic_crop_top_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_crop_top_offset, return_status); ENTROPY_TRACE("pic_crop_top_offset", ps_sps->i2_pic_crop_top_offset); /* pic_crop_bottom_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_crop_bottom_offset, return_status); ENTROPY_TRACE("pic_crop_bottom_offset", ps_sps->i2_pic_crop_bottom_offset); } /* bit_depth_luma_minus8 */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_bit_depth_luma_minus8, return_status); ENTROPY_TRACE("bit_depth_luma_minus8", ps_sps->i1_bit_depth_luma_minus8); /* bit_depth_chroma_minus8 */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_bit_depth_chroma_minus8, return_status); ENTROPY_TRACE("i1_bit_depth_chroma_minus8", ps_sps->i1_bit_depth_chroma_minus8); /* log2_max_pic_order_cnt_lsb_minus4 */ PUT_BITS_UEV(ps_bitstrm, u4_log2_max_pic_order_cnt_lsb - 4, return_status); ENTROPY_TRACE("log2_max_pic_order_cnt_lsb_minus4", u4_log2_max_pic_order_cnt_lsb - 4); /* sps_sub_layer_ordering_info_present_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_sps_sub_layer_ordering_info_present_flag, 1, return_status); ENTROPY_TRACE( "sps_sub_layer_ordering_info_present_flag", ps_sps->i1_sps_sub_layer_ordering_info_present_flag); i = ps_sps->i1_sps_sub_layer_ordering_info_present_flag ? 0 : i1_max_sub_layers_minus1; for(; i <= i1_max_sub_layers_minus1; i++) { /* max_dec_pic_buffering */ PUT_BITS_UEV(ps_bitstrm, ps_sps->ai1_sps_max_dec_pic_buffering[i], return_status); ENTROPY_TRACE("max_dec_pic_buffering_minus1", ps_sps->ai1_sps_max_dec_pic_buffering[i]); /* num_reorder_pics */ PUT_BITS_UEV(ps_bitstrm, ps_sps->ai1_sps_max_num_reorder_pics[i], return_status); ENTROPY_TRACE("num_reorder_pics", ps_sps->ai1_sps_max_num_reorder_pics[i]); /* max_latency_increase */ PUT_BITS_UEV(ps_bitstrm, ps_sps->ai1_sps_max_latency_increase[i], return_status); ENTROPY_TRACE("max_latency_increase", ps_sps->ai1_sps_max_latency_increase[i]); } /* log2_min_coding_block_size_minus3 */ PUT_BITS_UEV(ps_bitstrm, u4_log2_min_coding_block_size_minus3, return_status); ENTROPY_TRACE("log2_min_coding_block_size_minus3", u4_log2_min_coding_block_size_minus3); /* log2_diff_max_min_coding_block_size */ PUT_BITS_UEV(ps_bitstrm, u4_log2_diff_max_min_coding_block_size, return_status); ENTROPY_TRACE("log2_diff_max_min_coding_block_size", u4_log2_diff_max_min_coding_block_size); /* log2_min_transform_block_size_minus2 */ PUT_BITS_UEV(ps_bitstrm, u4_log2_min_transform_block_size_minus2, return_status); ENTROPY_TRACE("log2_min_transform_block_size_minus2", u4_log2_min_transform_block_size_minus2); /* log2_diff_max_min_transform_block_size */ PUT_BITS_UEV(ps_bitstrm, u4_log2_diff_max_min_transform_block_size, return_status); ENTROPY_TRACE( "log2_diff_max_min_transform_block_size", u4_log2_diff_max_min_transform_block_size); /* max_transform_hierarchy_depth_inter */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_max_transform_hierarchy_depth_inter, return_status); ENTROPY_TRACE( "max_transform_hierarchy_depth_inter", ps_sps->i1_max_transform_hierarchy_depth_inter); /* max_transform_hierarchy_depth_intra */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_max_transform_hierarchy_depth_intra, return_status); ENTROPY_TRACE( "max_transform_hierarchy_depth_intra", ps_sps->i1_max_transform_hierarchy_depth_intra); /* scaling_list_enabled_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_scaling_list_enable_flag, 1, return_status); ENTROPY_TRACE("scaling_list_enabled_flag", ps_sps->i1_scaling_list_enable_flag); if(ps_sps->i1_scaling_list_enable_flag) { /* sps_scaling_list_data_present_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_sps_scaling_list_data_present_flag, 1, return_status); ENTROPY_TRACE( "sps_scaling_list_data_present_flag", ps_sps->i1_sps_scaling_list_data_present_flag); #if 0 /* TODO: Will be enabled once scaling list support is added */ if(ps_sps->i1_sps_scaling_list_data_present_flag) { //TODO ihevce_generate_scaling_list_data(ps_bitstrm); } #endif } /* asymmetric_motion_partitions_enabled_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_amp_enabled_flag, 1, return_status); ENTROPY_TRACE("asymmetric_motion_partitions_enabled_flag", ps_sps->i1_amp_enabled_flag); /* sample_adaptive_offset_enabled_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_sample_adaptive_offset_enabled_flag, 1, return_status); ENTROPY_TRACE( "sample_adaptive_offset_enabled_flag", ps_sps->i1_sample_adaptive_offset_enabled_flag); /* pcm_enabled_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_pcm_enabled_flag, 1, return_status); ENTROPY_TRACE("pcm_enabled_flag", ps_sps->i1_pcm_enabled_flag); if(ps_sps->i1_pcm_enabled_flag) { UWORD32 u4_log2_min_pcm_coding_block_size = (ps_sps->i1_log2_min_pcm_coding_block_size); UWORD32 u4_log2_diff_max_min_pcm_coding_block_size = (ps_sps->i1_log2_diff_max_min_pcm_coding_block_size); /* pcm_sample_bit_depth_luma_minus1 */ PUT_BITS(ps_bitstrm, ps_sps->i1_pcm_sample_bit_depth_luma - 1, 4, return_status); ENTROPY_TRACE("pcm_sample_bit_depth_luma", ps_sps->i1_pcm_sample_bit_depth_luma - 1); /* pcm_sample_bit_depth_chroma_minus1 */ PUT_BITS(ps_bitstrm, ps_sps->i1_pcm_sample_bit_depth_chroma - 1, 4, return_status); ENTROPY_TRACE("pcm_sample_bit_depth_chroma", ps_sps->i1_pcm_sample_bit_depth_chroma - 1); /* log2_min_pcm_coding_block_size_minus3 */ PUT_BITS_UEV(ps_bitstrm, u4_log2_min_pcm_coding_block_size - 3, return_status); ENTROPY_TRACE( "log2_min_pcm_coding_block_size_minus3", u4_log2_min_pcm_coding_block_size - 3); /* log2_diff_max_min_pcm_coding_block_size */ PUT_BITS_UEV(ps_bitstrm, u4_log2_diff_max_min_pcm_coding_block_size, return_status); ENTROPY_TRACE( "log2_diff_max_min_pcm_coding_block_size", u4_log2_diff_max_min_pcm_coding_block_size); /* pcm_loop_filter_disable_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_pcm_loop_filter_disable_flag, 1, return_status); ENTROPY_TRACE("pcm_loop_filter_disable_flag", ps_sps->i1_pcm_loop_filter_disable_flag); } /* num_short_term_ref_pic_sets */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_num_short_term_ref_pic_sets, return_status); ENTROPY_TRACE("num_short_term_ref_pic_sets", ps_sps->i1_num_short_term_ref_pic_sets); for(i = 0; i < ps_sps->i1_num_short_term_ref_pic_sets; i++) { WORD32 i4_NumPocTotalCurr = 0; ihevce_short_term_ref_pic_set( ps_bitstrm, &ps_sps->as_stref_picset[0], ps_sps->i1_num_short_term_ref_pic_sets, i, &i4_NumPocTotalCurr); } /* long_term_ref_pics_present_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_long_term_ref_pics_present_flag, 1, return_status); ENTROPY_TRACE("long_term_ref_pics_present_flag", ps_sps->i1_long_term_ref_pics_present_flag); if(ps_sps->i1_long_term_ref_pics_present_flag) { /* num_long_term_ref_pics_sps */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_num_long_term_ref_pics_sps, return_status); ENTROPY_TRACE("num_long_term_ref_pics_sps", ps_sps->i1_num_long_term_ref_pics_sps); for(i = 0; i < ps_sps->i1_num_long_term_ref_pics_sps; i++) { /* lt_ref_pic_poc_lsb_sps[i] */ PUT_BITS( ps_bitstrm, ps_sps->au2_lt_ref_pic_poc_lsb_sps[i], u4_log2_max_pic_order_cnt_lsb, return_status); ENTROPY_TRACE("lt_ref_pic_poc_lsb_sps[i]", ps_sps->au2_lt_ref_pic_poc_lsb_sps[i]); /* used_by_curr_pic_lt_sps_flag[i] */ PUT_BITS(ps_bitstrm, ps_sps->ai1_used_by_curr_pic_lt_sps_flag[i], 1, return_status); ENTROPY_TRACE( "used_by_curr_pic_lt_sps_flag[i]", ps_sps->ai1_used_by_curr_pic_lt_sps_flag[i]); } } /* sps_temporal_mvp_enable_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_sps_temporal_mvp_enable_flag, 1, return_status); ENTROPY_TRACE("sps_temporal_mvp_enable_flag", ps_sps->i1_sps_temporal_mvp_enable_flag); #if !HM_8DOT1_SYNTAX /* strong_intra_smoothing_enable_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_strong_intra_smoothing_enable_flag, 1, return_status); ENTROPY_TRACE( "sps_strong_intra_smoothing_enable_flag", ps_sps->i1_strong_intra_smoothing_enable_flag); #endif /* vui_parameters_present_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_vui_parameters_present_flag, 1, return_status); ENTROPY_TRACE("vui_parameters_present_flag", ps_sps->i1_vui_parameters_present_flag); ENTROPY_TRACE("----------- vui_parameters -----------", 0); if(ps_sps->i1_vui_parameters_present_flag) { /* Add vui parameters to the bitstream */ ihevce_generate_vui(ps_bitstrm, ps_sps, ps_sps->s_vui_parameters); } /* sps_extension_flag */ PUT_BITS(ps_bitstrm, 0, 1, return_status); ENTROPY_TRACE("sps_extension_flag", 0); /* rbsp trailing bits */ ihevce_put_rbsp_trailing_bits(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Generates PPS (Picture Parameter Set) * * @par Description * Generate Picture Parameter Set as per Section 7.3.2.3 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_pps * pointer to structure containing PPS data * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_generate_pps(bitstrm_t *ps_bitstrm, pps_t *ps_pps) { WORD32 i; WORD32 return_status = IHEVCE_SUCCESS; /* Insert the NAL start code */ return_status = ihevce_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ return_status |= ihevce_generate_nal_unit_header(ps_bitstrm, NAL_PPS, 0); /* pic_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_pps_id, return_status); ENTROPY_TRACE("pic_parameter_set_id", ps_pps->i1_pps_id); /* seq_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_sps_id, return_status); ENTROPY_TRACE("seq_parameter_set_id", ps_pps->i1_sps_id); /* dependent_slices_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_dependent_slice_enabled_flag, 1, return_status); ENTROPY_TRACE("dependent_slices_enabled_flag", ps_pps->i1_dependent_slice_enabled_flag); /* output_flag_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_output_flag_present_flag, 1, return_status); ENTROPY_TRACE("output_flag_present_flag", ps_pps->i1_output_flag_present_flag); /* num_extra_slice_header_bits */ PUT_BITS(ps_bitstrm, ps_pps->i1_num_extra_slice_header_bits, 3, return_status); ENTROPY_TRACE("num_extra_slice_header_bits", ps_pps->i1_num_extra_slice_header_bits); /* sign_data_hiding_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_sign_data_hiding_flag, 1, return_status); ENTROPY_TRACE("sign_data_hiding_flag", ps_pps->i1_sign_data_hiding_flag); /* cabac_init_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_cabac_init_present_flag, 1, return_status); ENTROPY_TRACE("cabac_init_present_flag", ps_pps->i1_cabac_init_present_flag); /* num_ref_idx_l0_default_active_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_num_ref_idx_l0_default_active - 1, return_status); ENTROPY_TRACE( "num_ref_idx_l0_default_active_minus1", ps_pps->i1_num_ref_idx_l0_default_active - 1); /* num_ref_idx_l1_default_active_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_num_ref_idx_l1_default_active - 1, return_status); ENTROPY_TRACE( "num_ref_idx_l1_default_active_minus1", ps_pps->i1_num_ref_idx_l1_default_active - 1); /* pic_init_qp_minus26 */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_pic_init_qp - 26, return_status); ENTROPY_TRACE("pic_init_qp_minus26", ps_pps->i1_pic_init_qp - 26); /* constrained_intra_pred_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_constrained_intra_pred_flag, 1, return_status); ENTROPY_TRACE("constrained_intra_pred_flag", ps_pps->i1_constrained_intra_pred_flag); /* transform_skip_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_transform_skip_enabled_flag, 1, return_status); ENTROPY_TRACE("transform_skip_enabled_flag", ps_pps->i1_transform_skip_enabled_flag); /* cu_qp_delta_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_cu_qp_delta_enabled_flag, 1, return_status); ENTROPY_TRACE("cu_qp_delta_enabled_flag", ps_pps->i1_cu_qp_delta_enabled_flag); if(ps_pps->i1_cu_qp_delta_enabled_flag) { /* diff_cu_qp_delta_depth */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_diff_cu_qp_delta_depth, return_status); ENTROPY_TRACE("diff_cu_qp_delta_depth", ps_pps->i1_diff_cu_qp_delta_depth); } /* cb_qp_offset */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_pic_cb_qp_offset, return_status); ENTROPY_TRACE("cb_qp_offset", ps_pps->i1_pic_cb_qp_offset); /* cr_qp_offset */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_pic_cr_qp_offset, return_status); ENTROPY_TRACE("cr_qp_offset", ps_pps->i1_pic_cr_qp_offset); /* slicelevel_chroma_qp_flag */ PUT_BITS( ps_bitstrm, ps_pps->i1_pic_slice_level_chroma_qp_offsets_present_flag, 1, return_status); ENTROPY_TRACE( "slicelevel_chroma_qp_flag", ps_pps->i1_pic_slice_level_chroma_qp_offsets_present_flag); /* weighted_pred_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_weighted_pred_flag, 1, return_status); ENTROPY_TRACE("weighted_pred_flag", ps_pps->i1_weighted_pred_flag); /* weighted_bipred_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_weighted_bipred_flag, 1, return_status); ENTROPY_TRACE("weighted_bipred_flag", ps_pps->i1_weighted_bipred_flag); /* transquant_bypass_enable_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_transquant_bypass_enable_flag, 1, return_status); ENTROPY_TRACE("transquant_bypass_enable_flag", ps_pps->i1_transquant_bypass_enable_flag); /* tiles_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_tiles_enabled_flag, 1, return_status); ENTROPY_TRACE("tiles_enabled_flag", ps_pps->i1_tiles_enabled_flag); /* entropy_coding_sync_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_entropy_coding_sync_enabled_flag, 1, return_status); ENTROPY_TRACE("entropy_coding_sync_enabled_flag", ps_pps->i1_entropy_coding_sync_enabled_flag); if(ps_pps->i1_tiles_enabled_flag) { /* num_tile_columns_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_num_tile_columns - 1, return_status); ENTROPY_TRACE("num_tile_columns_minus1", ps_pps->i1_num_tile_columns - 1); /* num_tile_rows_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_num_tile_rows - 1, return_status); ENTROPY_TRACE("num_tile_rows_minus1", ps_pps->i1_num_tile_rows - 1); /* uniform_spacing_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_uniform_spacing_flag, 1, return_status); ENTROPY_TRACE("uniform_spacing_flag", ps_pps->i1_uniform_spacing_flag); if(!ps_pps->i1_uniform_spacing_flag) { for(i = 0; i < ps_pps->i1_num_tile_columns - 1; i++) { /* column_width_minus1[i] */ PUT_BITS_UEV(ps_bitstrm, ps_pps->ps_tile[i].u2_wd - 1, return_status); ENTROPY_TRACE("column_width_minus1[i]", ps_pps->ps_tile[i].u2_wd - 1); } for(i = 0; i < ps_pps->i1_num_tile_rows - 1; i++) { /* row_height_minus1[i] */ PUT_BITS_UEV(ps_bitstrm, ps_pps->ps_tile[i].u2_ht - 1, return_status); ENTROPY_TRACE("row_height_minus1[i]", ps_pps->ps_tile[i].u2_ht - 1); } } /* loop_filter_across_tiles_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_loop_filter_across_tiles_enabled_flag, 1, return_status); ENTROPY_TRACE( "loop_filter_across_tiles_enabled_flag", ps_pps->i1_loop_filter_across_tiles_enabled_flag); } /* loop_filter_across_slices_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_loop_filter_across_slices_enabled_flag, 1, return_status); ENTROPY_TRACE( "loop_filter_across_slices_enabled_flag", ps_pps->i1_loop_filter_across_slices_enabled_flag); /* deblocking_filter_control_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_deblocking_filter_control_present_flag, 1, return_status); ENTROPY_TRACE( "deblocking_filter_control_present_flag", ps_pps->i1_deblocking_filter_control_present_flag); if(ps_pps->i1_deblocking_filter_control_present_flag) { /* deblocking_filter_override_enabled_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_deblocking_filter_override_enabled_flag, 1, return_status); ENTROPY_TRACE( "deblocking_filter_override_enabled_flag", ps_pps->i1_deblocking_filter_override_enabled_flag); /* pic_disable_deblocking_filter_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_pic_disable_deblocking_filter_flag, 1, return_status); ENTROPY_TRACE( "pic_disable_deblocking_filter_flag", ps_pps->i1_pic_disable_deblocking_filter_flag); if(!ps_pps->i1_pic_disable_deblocking_filter_flag) { /* beta_offset_div2 */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_beta_offset_div2 >> 1, return_status); ENTROPY_TRACE("beta_offset_div2", ps_pps->i1_beta_offset_div2 >> 1); /* tc_offset_div2 */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_tc_offset_div2 >> 1, return_status); ENTROPY_TRACE("tc_offset_div2", ps_pps->i1_tc_offset_div2 >> 1); } } /* pps_scaling_list_data_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_pps_scaling_list_data_present_flag, 1, return_status); ENTROPY_TRACE( "pps_scaling_list_data_present_flag", ps_pps->i1_pps_scaling_list_data_present_flag); #if 0 /* TODO: Will be enabled once scaling list support is added */ if(ps_pps->i1_pps_scaling_list_data_present_flag ) { //TODO ihevce_scaling_list_data(); } #endif /* lists_modification_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_lists_modification_present_flag, 1, return_status); ENTROPY_TRACE("lists_modification_present_flag", ps_pps->i1_lists_modification_present_flag); { UWORD32 u4_log2_parallel_merge_level_minus2 = ps_pps->i1_log2_parallel_merge_level; u4_log2_parallel_merge_level_minus2 -= 2; /* log2_parallel_merge_level_minus2 */ PUT_BITS_UEV(ps_bitstrm, u4_log2_parallel_merge_level_minus2, return_status); ENTROPY_TRACE("log2_parallel_merge_level_minus2", u4_log2_parallel_merge_level_minus2); } /* slice_header_extension_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_slice_header_extension_present_flag, 1, return_status); ENTROPY_TRACE( "slice_header_extension_present_flag", ps_pps->i1_slice_header_extension_present_flag); /* pps_extension_flag */ PUT_BITS(ps_bitstrm, 0, 1, return_status); ENTROPY_TRACE("pps_extension_flag", 0); ihevce_put_rbsp_trailing_bits(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Generates Slice Header * * @par Description * Generate Slice Header as per Section 7.3.5.1 * * @param[inout] ps_bitstrm * pointer to bitstream context for generating slice header * * @param[in] i1_nal_unit_type * nal unit type * * @param[in] ps_slice_hdr * pointer to slice header params * * @param[in] ps_pps * pointer to pps params referred by slice * * @param[in] ps_sps * pointer to sps params referred by slice * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_generate_slice_header( bitstrm_t *ps_bitstrm, WORD8 i1_nal_unit_type, slice_header_t *ps_slice_hdr, pps_t *ps_pps, sps_t *ps_sps, bitstrm_t *ps_dup_bit_strm_ent_offset, UWORD32 *pu4_first_slice_start_offset, ihevce_tile_params_t *ps_tile_params, WORD32 i4_next_slice_seg_x, WORD32 i4_next_slice_seg_y) { WORD32 i; WORD32 return_status = IHEVCE_SUCCESS; WORD32 RapPicFlag = (i1_nal_unit_type >= NAL_BLA_W_LP) && (i1_nal_unit_type <= NAL_RSV_RAP_VCL23); WORD32 idr_pic_flag = (NAL_IDR_W_LP == i1_nal_unit_type) || (NAL_IDR_N_LP == i1_nal_unit_type); WORD32 disable_deblocking_filter_flag; WORD32 i4_NumPocTotalCurr = 0; /* Initialize the pic width and pic height from sps parameters */ WORD32 pic_width = ps_sps->i2_pic_width_in_luma_samples; WORD32 pic_height = ps_sps->i2_pic_height_in_luma_samples; /* Initialize the CTB size from sps parameters */ WORD32 log2_ctb_size = ps_sps->i1_log2_min_coding_block_size + ps_sps->i1_log2_diff_max_min_coding_block_size; WORD32 ctb_size = (1 << log2_ctb_size); /* Update ps_slice_hdr->i2_slice_address based on tile position in frame */ WORD32 num_ctb_in_row = (pic_width + ctb_size - 1) >> log2_ctb_size; /* Overwrite i2_slice_address here as pre-enc didn't had tile structure available in it's scope. Otherwise i2_slice_address would be set in populate_slice_header() itself */ if(1 == ps_tile_params->i4_tiles_enabled_flag) { ps_slice_hdr->i2_slice_address = ps_tile_params->i4_first_ctb_y * num_ctb_in_row + ps_tile_params->i4_first_ctb_x; } else { ps_slice_hdr->i2_slice_address = i4_next_slice_seg_x + i4_next_slice_seg_y * num_ctb_in_row; } /* Overwrite i1_first_slice_in_pic_flag here as pre-enc didn't had tile structure available in it's scope. Otherwise i1_first_slice_in_pic_flag would be set in populate_slice_header() itself */ ps_slice_hdr->i1_first_slice_in_pic_flag = (ps_slice_hdr->i2_slice_address == 0); /* Currently if dependent slices are enabled, then all slices after first slice of picture, are made dependent slices */ if((1 == ps_pps->i1_dependent_slice_enabled_flag) && (0 == ps_slice_hdr->i1_first_slice_in_pic_flag)) { ps_slice_hdr->i1_dependent_slice_flag = 1; } else { ps_slice_hdr->i1_dependent_slice_flag = 0; } /* Insert start code */ return_status |= ihevce_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ return_status |= ihevce_generate_nal_unit_header( ps_bitstrm, i1_nal_unit_type, ps_slice_hdr->u4_nuh_temporal_id); //TEMPORALA_SCALABILITY CHANGES /* first_slice_in_pic_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_first_slice_in_pic_flag, 1, return_status); ENTROPY_TRACE("first_slice_in_pic_flag", ps_slice_hdr->i1_first_slice_in_pic_flag); if(RapPicFlag) { /* no_output_of_prior_pics_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_no_output_of_prior_pics_flag, 1, return_status); ENTROPY_TRACE( "no_output_of_prior_pics_flag", ps_slice_hdr->i1_no_output_of_prior_pics_flag); } /* pic_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_pps_id, return_status); ENTROPY_TRACE("pic_parameter_set_id", ps_slice_hdr->i1_pps_id); /* If ps_pps->i1_dependent_slice_enabled_flag is enabled and curent slice is not the first slice of picture then put i1_dependent_slice_flag into the bitstream */ if((ps_pps->i1_dependent_slice_enabled_flag) && (!ps_slice_hdr->i1_first_slice_in_pic_flag)) { /* dependent_slice_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_dependent_slice_flag, 1, return_status); ENTROPY_TRACE("dependent_slice_flag", ps_slice_hdr->i1_dependent_slice_flag); } if(!ps_slice_hdr->i1_first_slice_in_pic_flag) { WORD32 num_bits; WORD32 num_ctb_in_pic; /* ctbs in frame ceiled for width / height not multiple of ctb size */ num_ctb_in_pic = ((pic_width + (ctb_size - 1)) >> log2_ctb_size) * ((pic_height + (ctb_size - 1)) >> log2_ctb_size); /* Use CLZ to compute Ceil( Log2( PicSizeInCtbsY ) ) */ num_bits = 32 - CLZ(num_ctb_in_pic - 1); /* slice_address */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i2_slice_address, num_bits, return_status); ENTROPY_TRACE("slice_address", ps_slice_hdr->i2_slice_address); } if(!ps_slice_hdr->i1_dependent_slice_flag) { for(i = 0; i < ps_pps->i1_num_extra_slice_header_bits; i++) { /* slice_reserved_undetermined_flag */ PUT_BITS(ps_bitstrm, 0, 1, return_status); ENTROPY_TRACE("slice_reserved_undetermined_flag", 0); } /* slice_type */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_slice_type, return_status); ENTROPY_TRACE("slice_type", ps_slice_hdr->i1_slice_type); if(ps_pps->i1_output_flag_present_flag) { /* pic_output_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_pic_output_flag, 1, return_status); ENTROPY_TRACE("pic_output_flag", ps_slice_hdr->i1_pic_output_flag); } if(!idr_pic_flag) { /* pic_order_cnt_lsb */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i4_pic_order_cnt_lsb, ps_sps->i1_log2_max_pic_order_cnt_lsb, return_status); ENTROPY_TRACE("pic_order_cnt_lsb", ps_slice_hdr->i4_pic_order_cnt_lsb); /* short_term_ref_pic_set_sps_flag */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_short_term_ref_pic_set_sps_flag, 1, return_status); ENTROPY_TRACE( "short_term_ref_pic_set_sps_flag", ps_slice_hdr->i1_short_term_ref_pic_set_sps_flag); if(!ps_slice_hdr->i1_short_term_ref_pic_set_sps_flag) { ihevce_short_term_ref_pic_set( ps_bitstrm, &ps_slice_hdr->s_stref_picset, 1, 0, &i4_NumPocTotalCurr); } else { WORD32 num_bits = 32 - CLZ(ps_sps->i1_num_short_term_ref_pic_sets); /* short_term_ref_pic_set_idx */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_short_term_ref_pic_set_idx, num_bits, return_status); ENTROPY_TRACE( "short_term_ref_pic_set_idx", ps_slice_hdr->i1_short_term_ref_pic_set_idx); } if(ps_sps->i1_long_term_ref_pics_present_flag) { if(ps_sps->i1_num_long_term_ref_pics_sps > 0) { /* num_long_term_sps */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_num_long_term_sps, return_status); ENTROPY_TRACE("num_long_term_sps", ps_slice_hdr->i1_num_long_term_sps); } /* num_long_term_pics */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_num_long_term_pics, return_status); ENTROPY_TRACE("num_long_term_pics", ps_slice_hdr->i1_num_long_term_pics); for(i = 0; i < (ps_slice_hdr->i1_num_long_term_sps + ps_slice_hdr->i1_num_long_term_pics); i++) { if(i < ps_slice_hdr->i1_num_long_term_sps) { /* Use CLZ to compute Ceil( Log2 ( num_long_term_ref_pics_sps ) ) */ WORD32 num_bits = 32 - CLZ(ps_sps->i1_num_long_term_ref_pics_sps); /* lt_idx_sps[i] */ PUT_BITS( ps_bitstrm, ps_slice_hdr->ai1_lt_idx_sps[i], num_bits, return_status); ENTROPY_TRACE("lt_idx_sps[i]", ps_slice_hdr->ai1_lt_idx_sps[i]); } else { /* poc_lsb_lt[i] */ PUT_BITS( ps_bitstrm, ps_slice_hdr->ai4_poc_lsb_lt[i], ps_sps->i1_log2_max_pic_order_cnt_lsb, return_status); ENTROPY_TRACE("poc_lsb_lt[i]", ps_slice_hdr->ai4_poc_lsb_lt[i]); /* used_by_curr_pic_lt_flag[i] */ PUT_BITS( ps_bitstrm, ps_slice_hdr->ai1_used_by_curr_pic_lt_flag[i], 1, return_status); ENTROPY_TRACE( "used_by_curr_pic_lt_flag[i]", ps_slice_hdr->ai1_used_by_curr_pic_lt_flag[i]); } /* delta_poc_msb_present_flag[i] */ PUT_BITS( ps_bitstrm, ps_slice_hdr->ai1_delta_poc_msb_present_flag[i], 1, return_status); ENTROPY_TRACE( "delta_poc_msb_present_flag[i]", ps_slice_hdr->ai1_delta_poc_msb_present_flag[i]); if(ps_slice_hdr->ai1_delta_poc_msb_present_flag[i]) { /* delata_poc_msb_cycle_lt[i] */ PUT_BITS_UEV( ps_bitstrm, ps_slice_hdr->ai1_delta_poc_msb_cycle_lt[i], return_status); ENTROPY_TRACE( "delata_poc_msb_cycle_lt", ps_slice_hdr->ai1_delta_poc_msb_cycle_lt[i]); } } } if(ps_sps->i1_sps_temporal_mvp_enable_flag) { /* slice_temporal_mvp_enable_flag */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_slice_temporal_mvp_enable_flag, 1, return_status); ENTROPY_TRACE( "slice_temporal_mvp_enable_flag", ps_slice_hdr->i1_slice_temporal_mvp_enable_flag); } } if(ps_sps->i1_sample_adaptive_offset_enabled_flag) { /* slice_sao_luma_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_slice_sao_luma_flag, 1, return_status); ENTROPY_TRACE("slice_sao_luma_flag", ps_slice_hdr->i1_slice_sao_luma_flag); /* slice_sao_chroma_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_slice_sao_chroma_flag, 1, return_status); ENTROPY_TRACE("slice_sao_chroma_flag", ps_slice_hdr->i1_slice_sao_chroma_flag); } if((PSLICE == ps_slice_hdr->i1_slice_type) || (BSLICE == ps_slice_hdr->i1_slice_type)) { /* num_ref_idx_active_override_flag */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_num_ref_idx_active_override_flag, 1, return_status); ENTROPY_TRACE( "num_ref_idx_active_override_flag", ps_slice_hdr->i1_num_ref_idx_active_override_flag); if(ps_slice_hdr->i1_num_ref_idx_active_override_flag) { /* i1_num_ref_idx_l0_active_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_num_ref_idx_l0_active - 1, return_status); ENTROPY_TRACE( "i1_num_ref_idx_l0_active_minus1", ps_slice_hdr->i1_num_ref_idx_l0_active - 1); if(BSLICE == ps_slice_hdr->i1_slice_type) { /* i1_num_ref_idx_l1_active */ PUT_BITS_UEV( ps_bitstrm, ps_slice_hdr->i1_num_ref_idx_l1_active - 1, return_status); ENTROPY_TRACE( "i1_num_ref_idx_l1_active", ps_slice_hdr->i1_num_ref_idx_l1_active - 1); } } if(ps_pps->i1_lists_modification_present_flag && i4_NumPocTotalCurr > 1) { ref_pic_list_modification(ps_bitstrm, ps_slice_hdr, i4_NumPocTotalCurr); } if(BSLICE == ps_slice_hdr->i1_slice_type) { /* mvd_l1_zero_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_mvd_l1_zero_flag, 1, return_status); ENTROPY_TRACE("mvd_l1_zero_flag", ps_slice_hdr->i1_mvd_l1_zero_flag); } if(ps_pps->i1_cabac_init_present_flag) { /* cabac_init_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_cabac_init_flag, 1, return_status); ENTROPY_TRACE("cabac_init_flag", ps_slice_hdr->i1_cabac_init_flag); } if(ps_slice_hdr->i1_slice_temporal_mvp_enable_flag) { if(BSLICE == ps_slice_hdr->i1_slice_type) { /* collocated_from_l0_flag */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_collocated_from_l0_flag, 1, return_status); ENTROPY_TRACE( "collocated_from_l0_flag", ps_slice_hdr->i1_collocated_from_l0_flag); } if((ps_slice_hdr->i1_collocated_from_l0_flag && (ps_slice_hdr->i1_num_ref_idx_l0_active > 1)) || (!ps_slice_hdr->i1_collocated_from_l0_flag && (ps_slice_hdr->i1_num_ref_idx_l1_active > 1))) { /* collocated_ref_idx */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_collocated_ref_idx, return_status); ENTROPY_TRACE("collocated_ref_idx", ps_slice_hdr->i1_collocated_ref_idx); } } if((ps_pps->i1_weighted_pred_flag && (PSLICE == ps_slice_hdr->i1_slice_type)) || (ps_pps->i1_weighted_bipred_flag && (BSLICE == ps_slice_hdr->i1_slice_type))) { ihevce_generate_pred_weight_table(ps_bitstrm, ps_sps, ps_pps, ps_slice_hdr); } #if !HM_8DOT1_SYNTAX /* five_minus_max_num_merge_cand */ PUT_BITS_UEV(ps_bitstrm, 5 - ps_slice_hdr->i1_max_num_merge_cand, return_status); ENTROPY_TRACE("five_minus_max_num_merge_cand", 5 - ps_slice_hdr->i1_max_num_merge_cand); #endif } #if HM_8DOT1_SYNTAX /* five_minus_max_num_merge_cand */ PUT_BITS_UEV(ps_bitstrm, 5 - ps_slice_hdr->i1_max_num_merge_cand, return_status); ENTROPY_TRACE("five_minus_max_num_merge_cand", 5 - ps_slice_hdr->i1_max_num_merge_cand); #endif /* slice_qp_delta */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_slice_qp_delta, return_status); ENTROPY_TRACE("slice_qp_delta", ps_slice_hdr->i1_slice_qp_delta); if(ps_pps->i1_pic_slice_level_chroma_qp_offsets_present_flag) { /* slice_cb_qp_offset */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_slice_cb_qp_offset, return_status); ENTROPY_TRACE("slice_cb_qp_offset", ps_slice_hdr->i1_slice_cb_qp_offset); /* slice_cr_qp_offset */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_slice_cr_qp_offset, return_status); ENTROPY_TRACE("slice_cr_qp_offset", ps_slice_hdr->i1_slice_cr_qp_offset); } if(ps_pps->i1_deblocking_filter_control_present_flag) { if(ps_pps->i1_deblocking_filter_override_enabled_flag) { /* deblocking_filter_override_flag */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_deblocking_filter_override_flag, 1, return_status); ENTROPY_TRACE( "deblocking_filter_override_flag", ps_slice_hdr->i1_deblocking_filter_override_flag); } if(ps_slice_hdr->i1_deblocking_filter_override_flag) { /* slice_disable_deblocking_filter_flag */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_slice_disable_deblocking_filter_flag, 1, return_status); ENTROPY_TRACE( "slice_disable_deblocking_filter_flag", ps_slice_hdr->i1_slice_disable_deblocking_filter_flag); if(!ps_slice_hdr->i1_slice_disable_deblocking_filter_flag) { /* beta_offset_div2 */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_beta_offset_div2 >> 1, return_status); ENTROPY_TRACE("beta_offset_div2", ps_slice_hdr->i1_beta_offset_div2 >> 1); /* tc_offset_div2 */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_tc_offset_div2 >> 1, return_status); ENTROPY_TRACE("tc_offset_div2", ps_slice_hdr->i1_tc_offset_div2 >> 1); } } } disable_deblocking_filter_flag = ps_slice_hdr->i1_slice_disable_deblocking_filter_flag | ps_pps->i1_pic_disable_deblocking_filter_flag; if(ps_pps->i1_loop_filter_across_slices_enabled_flag && (ps_slice_hdr->i1_slice_sao_luma_flag || ps_slice_hdr->i1_slice_sao_chroma_flag || !disable_deblocking_filter_flag)) { /* slice_loop_filter_across_slices_enabled_flag */ PUT_BITS( ps_bitstrm, ps_slice_hdr->i1_slice_loop_filter_across_slices_enabled_flag, 1, return_status); ENTROPY_TRACE( "slice_loop_filter_across_slices_enabled_flag", ps_slice_hdr->i1_slice_loop_filter_across_slices_enabled_flag); } } if((ps_pps->i1_tiles_enabled_flag) || (ps_pps->i1_entropy_coding_sync_enabled_flag)) { /* num_entry_point_offsets */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i4_num_entry_point_offsets, return_status); ENTROPY_TRACE("num_entry_point_offsets", ps_slice_hdr->i4_num_entry_point_offsets); /*copy the bitstream state at this stage, later once all the offset are known the duplicated state is used to write offset in bitstream*/ memcpy(ps_dup_bit_strm_ent_offset, ps_bitstrm, sizeof(bitstrm_t)); if(ps_slice_hdr->i4_num_entry_point_offsets > 0) { /* offset_len_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_offset_len - 1, return_status); ENTROPY_TRACE("offset_len_minus1", ps_slice_hdr->i1_offset_len - 1); /*check the bitstream offset here, the first offset will be fixed here based on num_entry_offset and maximum possible emulaiton prevention bytes*/ /*This offset is used to generate bitstream, In the end of frame processing actual offset are updated and if there was no emulation bits the extra bytes shall be filled with 0xFF so that decoder discards it as part of slice header extension*/ /*assume one byte of emulation preention for every offset we signal*/ /*considering emulation prevention bytes and assuming incomplete word(4 bytes) that is yet to filled and offset length(4 bytes) that will be calc based on max offset length after frame is encoded*/ pu4_first_slice_start_offset[0] = ps_bitstrm->u4_strm_buf_offset + ((ps_slice_hdr->i4_num_entry_point_offsets * ps_slice_hdr->i1_offset_len) >> 3) + ps_slice_hdr->i4_num_entry_point_offsets + 4 + 4; ps_slice_hdr->pu4_entry_point_offset[0] = (*pu4_first_slice_start_offset); for(i = 0; i < ps_slice_hdr->i4_num_entry_point_offsets; i++) { /* entry_point_offset[i] */ PUT_BITS( ps_bitstrm, ps_slice_hdr->pu4_entry_point_offset[i], ps_slice_hdr->i1_offset_len, return_status); ENTROPY_TRACE("entry_point_offset[i]", ps_slice_hdr->pu4_entry_point_offset[i]); } } } if(ps_pps->i1_slice_header_extension_present_flag) { /* slice_header_extension_length */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i2_slice_header_extension_length, return_status); ENTROPY_TRACE( "slice_header_extension_length", ps_slice_hdr->i2_slice_header_extension_length); for(i = 0; i < ps_slice_hdr->i2_slice_header_extension_length; i++) { /* slice_header_extension_data_byte[i] */ PUT_BITS(ps_bitstrm, 0, 8, return_status); ENTROPY_TRACE("slice_header_extension_data_byte[i]", 0); } } BYTE_ALIGNMENT(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Populates vps structure * * @par Description * All the parameters in vps are currently hard coded * * @param[out] ps_vps * pointer to vps params that needs to be populated * * @param[in] ps_src_params * pointer to source config params; resolution, frame rate etc * * @param[in] ps_out_strm_params * pointer to output stream config params * * @param[in] ps_coding_params * pointer to coding params; to enable/disable various toolsets in pps * * @param[in] ps_config_prms * pointer to configuration params like bitrate, HRD buffer sizes, cu, tu sizes * * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_populate_vps( enc_ctxt_t *ps_enc_ctxt, vps_t *ps_vps, ihevce_src_params_t *ps_src_params, ihevce_out_strm_params_t *ps_out_strm_params, ihevce_coding_params_t *ps_coding_params, ihevce_config_prms_t *ps_config_prms, ihevce_static_cfg_params_t *ps_stat_cfg_prms, WORD32 i4_resolution_id) { WORD8 *pi1_profile_compatiblity_flags; WORD32 i; WORD32 i4_field_pic = ps_src_params->i4_field_pic; WORD32 i4_codec_level_index; ps_vps->i1_vps_id = DEFAULT_VPS_ID; (void)ps_config_prms; /* default sub layers is 1 */ ps_vps->i1_vps_max_sub_layers = 1; if(1 == ps_stat_cfg_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability) { ps_vps->i1_vps_max_sub_layers = 2; } for(i = 0; i < ps_vps->i1_vps_max_sub_layers; i++) { /* currently bit rate and pic rate signalling is disabled */ ps_vps->ai1_bit_rate_info_present_flag[i] = 0; ps_vps->ai1_pic_rate_info_present_flag[i] = 0; if(ps_vps->ai1_bit_rate_info_present_flag[i]) { /* TODO: Add support for bitrate and max bitrate */ ps_vps->au2_avg_bit_rate[i] = 0; ps_vps->au2_max_bit_rate[i] = 0; } if(ps_vps->ai1_pic_rate_info_present_flag[i]) { /* TODO: Add support for pic rate idc and avg pic rate */ } } /* default sub layer ordering info present flag */ ps_vps->i1_sub_layer_ordering_info_present_flag = VPS_SUB_LAYER_ORDERING_INFO_ABSENT; /* hrd and temporal id nesting not supported for now */ ps_vps->i1_vps_num_hrd_parameters = 0; if(ps_vps->i1_vps_max_sub_layers == 1) { ps_vps->i1_vps_temporal_id_nesting_flag = 1; } else { ps_vps->i1_vps_temporal_id_nesting_flag = 0; } /* populate the general profile, tier and level information */ ps_vps->s_ptl.s_ptl_gen.i1_profile_space = 0; // BLU_RAY specific change is default /* set the profile according to user input */ ps_vps->s_ptl.s_ptl_gen.i1_profile_idc = ps_out_strm_params->i4_codec_profile; /***************************************************************/ /* set the profile compatibility flag for current profile to 1 */ /* the rest of the flags are set to 0 */ /***************************************************************/ pi1_profile_compatiblity_flags = &ps_vps->s_ptl.s_ptl_gen.ai1_profile_compatibility_flag[0]; for(i = 0; i < ps_vps->i1_vps_max_sub_layers; i++) //TEMPORALA_SCALABILITY CHANGES { ps_vps->ai1_vps_max_dec_pic_buffering[i] = ps_coding_params->i4_max_reference_frames + (2 << i4_field_pic) - 1; ps_vps->ai1_vps_max_num_reorder_pics[i] = ps_coding_params->i4_max_temporal_layers << i4_field_pic; ps_vps->ai1_vps_max_latency_increase[i] = 0; ps_vps->s_ptl.ai1_sub_layer_level_present_flag[i] = 1; //TEMPORALA_SCALABILITY CHANGES ps_vps->s_ptl.ai1_sub_layer_profile_present_flag[i] = 0; //TEMPORALA_SCALABILITY CHANGES ps_vps->s_ptl.as_ptl_sub[i].i1_profile_space = 0; // BLU_RAY specific change is default ps_vps->s_ptl.as_ptl_sub[i].i1_profile_idc = ps_out_strm_params->i4_codec_profile; memset( ps_vps->s_ptl.as_ptl_sub[i].ai1_profile_compatibility_flag, 0, MAX_PROFILE_COMPATBLTY * sizeof(WORD8)); ps_vps->s_ptl.as_ptl_sub[i] .ai1_profile_compatibility_flag[ps_out_strm_params->i4_codec_profile] = 1; ps_vps->s_ptl.as_ptl_sub[i].u1_level_idc = ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_codec_level; if(0 == i) // Only one level temporal scalability suport has been added. { i4_codec_level_index = ihevce_get_level_index( ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_codec_level); if(i4_codec_level_index) i4_codec_level_index -= 1; ps_vps->s_ptl.as_ptl_sub[i].u1_level_idc = (WORD32)g_as_level_data[i4_codec_level_index].e_level; } ps_vps->s_ptl.as_ptl_sub[i].i1_tier_flag = ps_out_strm_params->i4_codec_tier; if(ps_src_params->i4_field_pic == IV_PROGRESSIVE) { ps_vps->s_ptl.as_ptl_sub[i].i1_general_progressive_source_flag = 1; ps_vps->s_ptl.as_ptl_sub[i].i1_general_interlaced_source_flag = 0; } else if(ps_src_params->i4_field_pic == IV_INTERLACED) { ps_vps->s_ptl.as_ptl_sub[i].i1_general_progressive_source_flag = 0; ps_vps->s_ptl.as_ptl_sub[i].i1_general_interlaced_source_flag = 1; } else if(ps_src_params->i4_field_pic == IV_CONTENTTYPE_NA) { ps_vps->s_ptl.as_ptl_sub[i].i1_general_progressive_source_flag = 0; ps_vps->s_ptl.as_ptl_sub[i].i1_general_interlaced_source_flag = 0; } ps_vps->s_ptl.as_ptl_sub[i].i1_general_non_packed_constraint_flag = DEFAULT_NON_PACKED_CONSTRAINT_FLAG; if(ps_enc_ctxt->i4_blu_ray_spec == 1) { ps_vps->s_ptl.as_ptl_sub[i].i1_frame_only_constraint_flag = 1; } else { ps_vps->s_ptl.as_ptl_sub[i].i1_frame_only_constraint_flag = DEFAULT_FRAME_ONLY_CONSTRAINT_FLAG; } } memset(pi1_profile_compatiblity_flags, 0, MAX_PROFILE_COMPATBLTY); pi1_profile_compatiblity_flags[ps_out_strm_params->i4_codec_profile] = 1; /* set the level idc according to user input */ ps_vps->s_ptl.s_ptl_gen.u1_level_idc = ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_codec_level; ps_vps->s_ptl.s_ptl_gen.i1_tier_flag = ps_out_strm_params->i4_codec_tier; if(ps_src_params->i4_field_pic == IV_PROGRESSIVE) { ps_vps->s_ptl.s_ptl_gen.i1_general_progressive_source_flag = 1; ps_vps->s_ptl.s_ptl_gen.i1_general_interlaced_source_flag = 0; } else if(ps_src_params->i4_field_pic == IV_INTERLACED) { ps_vps->s_ptl.s_ptl_gen.i1_general_progressive_source_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_interlaced_source_flag = 1; } else if(ps_src_params->i4_field_pic == IV_CONTENTTYPE_NA) { ps_vps->s_ptl.s_ptl_gen.i1_general_progressive_source_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_interlaced_source_flag = 0; } ps_vps->s_ptl.s_ptl_gen.i1_general_non_packed_constraint_flag = DEFAULT_NON_PACKED_CONSTRAINT_FLAG; if(ps_enc_ctxt->i4_blu_ray_spec == 1) { ps_vps->s_ptl.s_ptl_gen.i1_frame_only_constraint_flag = 1; } else { ps_vps->s_ptl.s_ptl_gen.i1_frame_only_constraint_flag = DEFAULT_FRAME_ONLY_CONSTRAINT_FLAG; } if((ps_out_strm_params->i4_codec_profile == 4) && (ps_src_params->i4_chr_format == IV_YUV_420SP_UV)) { ps_vps->s_ptl.s_ptl_gen.i1_general_max_12bit_constraint_flag = 1; ps_vps->s_ptl.s_ptl_gen.i1_general_max_10bit_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_8bit_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_422chroma_constraint_flag = 1; ps_vps->s_ptl.s_ptl_gen.i1_general_max_420chroma_constraint_flag = 1; ps_vps->s_ptl.s_ptl_gen.i1_general_max_monochrome_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_intra_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_one_picture_only_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_lower_bit_rate_constraint_flag = 1; } else if( (ps_out_strm_params->i4_codec_profile == 4) && (ps_src_params->i4_chr_format == IV_YUV_422SP_UV)) { ps_vps->s_ptl.s_ptl_gen.i1_general_max_12bit_constraint_flag = 1; ps_vps->s_ptl.s_ptl_gen.i1_general_max_10bit_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_8bit_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_422chroma_constraint_flag = 1; ps_vps->s_ptl.s_ptl_gen.i1_general_max_420chroma_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_monochrome_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_intra_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_one_picture_only_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_lower_bit_rate_constraint_flag = 1; } else { ps_vps->s_ptl.s_ptl_gen.i1_general_max_12bit_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_10bit_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_8bit_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_422chroma_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_420chroma_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_max_monochrome_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_intra_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_one_picture_only_constraint_flag = 0; ps_vps->s_ptl.s_ptl_gen.i1_general_lower_bit_rate_constraint_flag = 0; } ps_vps->i1_vps_max_nuh_reserved_zero_layer_id = 0; return IHEVCE_SUCCESS; } /** ****************************************************************************** * * @brief Populates sps structure * * @par Description * Populates sps structure for its use in header generation * * @param[out] ps_sps * pointer to sps params that needs to be populated * * @param[in] ps_vps * pointer to vps params referred by the sps * * @param[in] ps_src_params * pointer to source config params; resolution, frame rate etc * * @param[in] ps_out_strm_params * pointer to output stream config params * * @param[in] ps_coding_params * pointer to coding params; to enable/disable various toolsets in pps * * @param[in] ps_config_prms * pointer to configuration params like bitrate, HRD buffer sizes, cu, tu sizes * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_populate_sps( enc_ctxt_t *ps_enc_ctxt, sps_t *ps_sps, vps_t *ps_vps, ihevce_src_params_t *ps_src_params, ihevce_out_strm_params_t *ps_out_strm_params, ihevce_coding_params_t *ps_coding_params, ihevce_config_prms_t *ps_config_prms, frm_ctb_ctxt_t *ps_frm_ctb_prms, ihevce_static_cfg_params_t *ps_stat_cfg_prms, WORD32 i4_resolution_id) { WORD32 i; WORD32 i4_field_pic = ps_src_params->i4_field_pic; WORD32 i4_quality_preset = ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset; WORD32 i4_codec_level_index; if(i4_quality_preset == IHEVCE_QUALITY_P7) { i4_quality_preset = IHEVCE_QUALITY_P6; } ps_sps->i1_sps_id = DEFAULT_SPS_ID; if(1 == ps_stat_cfg_prms->s_tgt_lyr_prms.i4_mres_single_out) { ps_sps->i1_sps_id = i4_resolution_id; } ps_sps->i1_vps_id = ps_vps->i1_vps_id; ps_sps->i2_pic_height_in_luma_samples = ps_frm_ctb_prms->i4_cu_aligned_pic_ht; ps_sps->i2_pic_width_in_luma_samples = ps_frm_ctb_prms->i4_cu_aligned_pic_wd; ps_sps->i1_amp_enabled_flag = AMP_ENABLED; ps_sps->i1_chroma_format_idc = (ps_src_params->i4_chr_format == IV_YUV_422SP_UV) ? 2 : 1; ps_sps->i1_separate_colour_plane_flag = 0; ps_sps->i1_bit_depth_luma_minus8 = ps_stat_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth - 8; ps_sps->i1_bit_depth_chroma_minus8 = ps_stat_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth - 8; ps_sps->i1_log2_min_coding_block_size = ps_config_prms->i4_min_log2_cu_size; ps_sps->i1_log2_diff_max_min_coding_block_size = ps_config_prms->i4_max_log2_cu_size - ps_config_prms->i4_min_log2_cu_size; ps_sps->i1_log2_ctb_size = ps_sps->i1_log2_min_coding_block_size + ps_sps->i1_log2_diff_max_min_coding_block_size; ps_sps->i1_log2_diff_max_min_transform_block_size = ps_config_prms->i4_max_log2_tu_size - ps_config_prms->i4_min_log2_tu_size; ps_sps->i1_log2_min_transform_block_size = ps_config_prms->i4_min_log2_tu_size; ps_sps->i1_long_term_ref_pics_present_flag = LONG_TERM_REF_PICS_ABSENT; ps_sps->i1_max_transform_hierarchy_depth_inter = ps_config_prms->i4_max_tr_tree_depth_nI; ps_sps->i1_max_transform_hierarchy_depth_intra = ps_config_prms->i4_max_tr_tree_depth_I; ps_sps->i1_pcm_enabled_flag = PCM_DISABLED; ps_sps->i1_pcm_loop_filter_disable_flag = PCM_LOOP_FILTER_DISABLED; ps_sps->i1_pic_cropping_flag = !!ps_coding_params->i4_cropping_mode; if(i4_quality_preset < IHEVCE_QUALITY_P4) { /*** Enable SAO for PQ,HQ,MS presets **/ ps_sps->i1_sample_adaptive_offset_enabled_flag = SAO_ENABLED; } else { ps_sps->i1_sample_adaptive_offset_enabled_flag = SAO_DISABLED; } #if DISABLE_SAO ps_sps->i1_sample_adaptive_offset_enabled_flag = SAO_DISABLED; #endif if(ps_coding_params->i4_use_default_sc_mtx == 1) { ps_sps->i1_scaling_list_enable_flag = SCALING_LIST_ENABLED; } else { ps_sps->i1_scaling_list_enable_flag = SCALING_LIST_DISABLED; } ps_sps->i1_sps_max_sub_layers = DEFAULT_SPS_MAX_SUB_LAYERS; if(1 == ps_stat_cfg_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability) { ps_sps->i1_sps_max_sub_layers = DEFAULT_SPS_MAX_SUB_LAYERS + 1; } ps_sps->i1_sps_sub_layer_ordering_info_present_flag = SPS_SUB_LAYER_ORDERING_INFO_ABSENT; ps_sps->i1_sps_scaling_list_data_present_flag = SCALING_LIST_DATA_ABSENT; if(ps_sps->i1_sps_max_sub_layers == 1) { ps_sps->i1_sps_temporal_id_nesting_flag = 1; //NO_SPS_TEMPORAL_ID_NESTING_DONE; } else { ps_sps->i1_sps_temporal_id_nesting_flag = 0; //NO_SPS_TEMPORAL_ID_NESTING_DONE; } /* short term and long term ref pic set not signalled in sps */ ps_sps->i1_num_short_term_ref_pic_sets = 0; ps_sps->i1_long_term_ref_pics_present_flag = 0; ps_sps->i1_num_long_term_ref_pics_sps = 0; ps_sps->i1_sps_temporal_mvp_enable_flag = !DISABLE_TMVP; ps_sps->i1_strong_intra_smoothing_enable_flag = STRONG_INTRA_SMOOTHING_FLAG_ENABLE; ps_sps->i1_vui_parameters_present_flag = ps_out_strm_params->i4_vui_enable; /*required in generation of slice header*/ ps_sps->i2_pic_ht_in_ctb = ps_frm_ctb_prms->i4_num_ctbs_vert; ps_sps->i2_pic_wd_in_ctb = ps_frm_ctb_prms->i4_num_ctbs_horz; ps_sps->i1_log2_max_pic_order_cnt_lsb = DEFAULT_LOG2_MAX_POC_LSB; if(ps_sps->i1_pic_cropping_flag) { WORD32 num_rows_to_pad_bottom = ps_sps->i2_pic_height_in_luma_samples - ps_stat_cfg_prms->s_src_prms.i4_orig_height; WORD32 num_rows_to_pad_right = ps_sps->i2_pic_width_in_luma_samples - ps_stat_cfg_prms->s_src_prms.i4_orig_width; ps_sps->i2_pic_crop_top_offset = DEFAULT_PIC_CROP_TOP_OFFSET; ps_sps->i2_pic_crop_left_offset = DEFAULT_PIC_CROP_LEFT_OFFSET; /* picture offsets should be signalled in terms of chroma unit */ ps_sps->i2_pic_crop_bottom_offset = num_rows_to_pad_bottom >> 1; /* picture offsets should be signalled in terms of chroma unit */ ps_sps->i2_pic_crop_right_offset = num_rows_to_pad_right >> 1; } for(i = 0; i < (ps_sps->i1_sps_max_sub_layers); i++) { ps_sps->ai1_sps_max_dec_pic_buffering[i] = ps_coding_params->i4_max_reference_frames + (2 << i4_field_pic) - 1; ps_sps->ai1_sps_max_num_reorder_pics[i] = ps_coding_params->i4_max_temporal_layers << i4_field_pic; ps_sps->ai1_sps_max_latency_increase[i] = 0; ps_sps->s_ptl.ai1_sub_layer_level_present_flag[i] = 1; //TEMPORALA_SCALABILITY CHANGES ps_sps->s_ptl.ai1_sub_layer_profile_present_flag[i] = 0; //TEMPORALA_SCALABILITY CHANGES ps_sps->s_ptl.as_ptl_sub[i].i1_profile_space = 0; // BLU_RAY specific change is default ps_sps->s_ptl.as_ptl_sub[i].i1_profile_idc = ps_out_strm_params->i4_codec_profile; memset( ps_sps->s_ptl.as_ptl_sub[i].ai1_profile_compatibility_flag, 0, MAX_PROFILE_COMPATBLTY * sizeof(WORD8)); ps_sps->s_ptl.as_ptl_sub[i] .ai1_profile_compatibility_flag[ps_out_strm_params->i4_codec_profile] = 1; ps_sps->s_ptl.as_ptl_sub[i].u1_level_idc = ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_codec_level; if(0 == i) // Only one level temporal scalability suport has been added. { i4_codec_level_index = ihevce_get_level_index( ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_codec_level); if(i4_codec_level_index) i4_codec_level_index -= 1; ps_sps->s_ptl.as_ptl_sub[i].u1_level_idc = (WORD32)g_as_level_data[i4_codec_level_index].e_level; } ps_sps->s_ptl.as_ptl_sub[i].i1_tier_flag = ps_out_strm_params->i4_codec_tier; if(ps_src_params->i4_field_pic == IV_PROGRESSIVE) { ps_sps->s_ptl.as_ptl_sub[i].i1_general_progressive_source_flag = 1; ps_sps->s_ptl.as_ptl_sub[i].i1_general_interlaced_source_flag = 0; } else if(ps_src_params->i4_field_pic == IV_INTERLACED) { ps_sps->s_ptl.as_ptl_sub[i].i1_general_progressive_source_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_interlaced_source_flag = 1; } else if(ps_src_params->i4_field_pic == IV_CONTENTTYPE_NA) { ps_sps->s_ptl.as_ptl_sub[i].i1_general_progressive_source_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_interlaced_source_flag = 0; } ps_sps->s_ptl.as_ptl_sub[i].i1_general_non_packed_constraint_flag = DEFAULT_NON_PACKED_CONSTRAINT_FLAG; if(ps_enc_ctxt->i4_blu_ray_spec == 1) { ps_sps->s_ptl.as_ptl_sub[i].i1_frame_only_constraint_flag = 1; } else { ps_sps->s_ptl.as_ptl_sub[i].i1_frame_only_constraint_flag = DEFAULT_FRAME_ONLY_CONSTRAINT_FLAG; } if((ps_out_strm_params->i4_codec_profile == 4) && (ps_sps->i1_chroma_format_idc == 1)) { ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_12bit_constraint_flag = 1; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_10bit_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_8bit_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_422chroma_constraint_flag = 1; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_420chroma_constraint_flag = 1; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_monochrome_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_intra_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_one_picture_only_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_lower_bit_rate_constraint_flag = 1; } else if((ps_out_strm_params->i4_codec_profile == 4) && (ps_sps->i1_chroma_format_idc == 2)) { ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_12bit_constraint_flag = 1; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_10bit_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_8bit_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_422chroma_constraint_flag = 1; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_420chroma_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_monochrome_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_intra_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_one_picture_only_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_lower_bit_rate_constraint_flag = 1; } else { ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_12bit_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_10bit_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_8bit_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_422chroma_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_420chroma_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_max_monochrome_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_intra_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_one_picture_only_constraint_flag = 0; ps_sps->s_ptl.as_ptl_sub[i].i1_general_lower_bit_rate_constraint_flag = 0; } } memset( ps_sps->s_ptl.s_ptl_gen.ai1_profile_compatibility_flag, 0, MAX_PROFILE_COMPATBLTY * sizeof(WORD8)); /* populate the general profile, tier and level information */ ps_sps->s_ptl.s_ptl_gen.i1_profile_space = 0; // BLU_RAY specific change is default ps_sps->s_ptl.s_ptl_gen.i1_profile_idc = ps_out_strm_params->i4_codec_profile; ps_sps->s_ptl.s_ptl_gen.ai1_profile_compatibility_flag[ps_out_strm_params->i4_codec_profile] = 1; ps_sps->s_ptl.s_ptl_gen.u1_level_idc = ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_codec_level; ps_sps->s_ptl.s_ptl_gen.i1_tier_flag = ps_out_strm_params->i4_codec_tier; if(ps_src_params->i4_field_pic == IV_PROGRESSIVE) { ps_sps->s_ptl.s_ptl_gen.i1_general_progressive_source_flag = 1; ps_sps->s_ptl.s_ptl_gen.i1_general_interlaced_source_flag = 0; } else if(ps_src_params->i4_field_pic == IV_INTERLACED) { ps_sps->s_ptl.s_ptl_gen.i1_general_progressive_source_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_interlaced_source_flag = 1; } else if(ps_src_params->i4_field_pic == IV_CONTENTTYPE_NA) { ps_sps->s_ptl.s_ptl_gen.i1_general_progressive_source_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_interlaced_source_flag = 0; } ps_sps->s_ptl.s_ptl_gen.i1_general_non_packed_constraint_flag = DEFAULT_NON_PACKED_CONSTRAINT_FLAG; if(ps_enc_ctxt->i4_blu_ray_spec == 1) { ps_sps->s_ptl.s_ptl_gen.i1_frame_only_constraint_flag = 1; } else { ps_sps->s_ptl.s_ptl_gen.i1_frame_only_constraint_flag = DEFAULT_FRAME_ONLY_CONSTRAINT_FLAG; } if((ps_out_strm_params->i4_codec_profile == 4) && (ps_sps->i1_chroma_format_idc == 1)) { ps_sps->s_ptl.s_ptl_gen.i1_general_max_12bit_constraint_flag = 1; ps_sps->s_ptl.s_ptl_gen.i1_general_max_10bit_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_8bit_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_422chroma_constraint_flag = 1; ps_sps->s_ptl.s_ptl_gen.i1_general_max_420chroma_constraint_flag = 1; ps_sps->s_ptl.s_ptl_gen.i1_general_max_monochrome_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_intra_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_one_picture_only_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_lower_bit_rate_constraint_flag = 1; } else if((ps_out_strm_params->i4_codec_profile == 4) && (ps_sps->i1_chroma_format_idc == 2)) { ps_sps->s_ptl.s_ptl_gen.i1_general_max_12bit_constraint_flag = 1; ps_sps->s_ptl.s_ptl_gen.i1_general_max_10bit_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_8bit_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_422chroma_constraint_flag = 1; ps_sps->s_ptl.s_ptl_gen.i1_general_max_420chroma_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_monochrome_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_intra_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_one_picture_only_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_lower_bit_rate_constraint_flag = 1; } else { ps_sps->s_ptl.s_ptl_gen.i1_general_max_12bit_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_10bit_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_8bit_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_422chroma_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_420chroma_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_max_monochrome_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_intra_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_one_picture_only_constraint_flag = 0; ps_sps->s_ptl.s_ptl_gen.i1_general_lower_bit_rate_constraint_flag = 0; } return IHEVCE_SUCCESS; } /** ****************************************************************************** * * @brief Populates pps structure based on input cofiguration params * * @par Description * Populates pps structure for its use in header generation * * @param[out] ps_pps * pointer to pps params structure which needs to be populated * * @param[in] ps_sps * pointer to sps params refered by the pps * * @param[in] ps_src_params * pointer to source config params; resolution, frame rate etc * * @param[in] ps_out_strm_params * pointer to output stream config params * * @param[in] ps_coding_params * pointer to coding params; to enable/disable various toolsets in pps * * @param[in] ps_config_prms * pointer to configuration params like bitrate, HRD buffer sizes, cu, tu sizes * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_populate_pps( pps_t *ps_pps, sps_t *ps_sps, ihevce_src_params_t *ps_src_params, ihevce_out_strm_params_t *ps_out_strm_params, ihevce_coding_params_t *ps_coding_params, ihevce_config_prms_t *ps_config_prms, ihevce_static_cfg_params_t *ps_stat_cfg_prms, WORD32 i4_bitrate_instance_id, WORD32 i4_resolution_id, ihevce_tile_params_t *ps_tile_params_base, WORD32 *pi4_column_width_array, WORD32 *pi4_row_height_array) { (void)ps_src_params; (void)ps_out_strm_params; ps_pps->i1_beta_offset_div2 = DEFAULT_BETA_OFFSET; ps_pps->i1_cabac_init_present_flag = CABAC_INIT_ABSENT; ps_pps->i1_constrained_intra_pred_flag = CONSTR_IPRED_DISABLED; /*delta qp can be disabled for constant qp mode to save on qp signalling bits*/ ps_pps->i1_cu_qp_delta_enabled_flag = ps_config_prms->i4_cu_level_rc; ps_pps->i1_deblocking_filter_control_present_flag = DEBLOCKING_FILTER_CONTROL_PRESENT; ps_pps->i1_deblocking_filter_override_enabled_flag = DEBLOCKING_FILTER_OVERRIDE_DISABLED; ps_pps->i1_pic_disable_deblocking_filter_flag = ps_coding_params->i4_deblocking_type; if(0 != ps_stat_cfg_prms->s_slice_params.i4_slice_segment_mode) { ps_pps->i1_dependent_slice_enabled_flag = DEPENDENT_SLICE_ENABLED; } else { ps_pps->i1_dependent_slice_enabled_flag = DEPENDENT_SLICE_DISABLED; } /* Assign the diff_cu_qp_delta_depth with 3,2,1 for making CU_LEVEL_QP_MODULATION limited to 8x8, 16x16, 32x32 respectively : Lokesh */ ps_pps->i1_diff_cu_qp_delta_depth = CU_LEVEL_QP_LIMIT_8x8; if(1 == ps_coding_params->i4_enable_entropy_sync) { ps_pps->i1_entropy_coding_sync_enabled_flag = ENTROPY_CODING_SYNC_ENABLED; } else { ps_pps->i1_entropy_coding_sync_enabled_flag = ENTROPY_CODING_SYNC_DISABLED; } ps_pps->i1_entropy_slice_enabled_flag = ENTROPY_SLICE_DISABLED; ps_pps->i1_lists_modification_present_flag = ps_coding_params->i4_weighted_pred_enable; ps_pps->i1_log2_parallel_merge_level = DEFAULT_PARALLEL_MERGE_LEVEL; ps_pps->i1_num_extra_slice_header_bits = 0; /* SAO_note_01: Currently SAO is implemented is such a way that the loop-filter has to be enabled across syntatical-tiles and slices. Search for <SAO_note_01> in workspace to know more */ ps_pps->i1_loop_filter_across_slices_enabled_flag = LF_ACROSS_SLICES_ENABLED; ps_pps->i1_num_ref_idx_l0_default_active = DEFAULT_NUM_REF_IDX_L0_DEFAULT_ACTIVE; ps_pps->i1_num_ref_idx_l1_default_active = DEFAULT_NUM_REF_IDX_L1_DEFAULT_ACTIVE; if(0 == ps_tile_params_base->i4_tiles_enabled_flag) { ps_pps->i1_num_tile_columns = NUM_TILES_COLS; ps_pps->i1_num_tile_rows = NUM_TILES_ROWS; ps_pps->i1_tiles_enabled_flag = TILES_DISABLED; ps_pps->i1_uniform_spacing_flag = SPACING_IS_UNIFORM; } else { ps_pps->i1_num_tile_columns = ps_tile_params_base->i4_num_tile_cols; ps_pps->i1_num_tile_rows = ps_tile_params_base->i4_num_tile_rows; ps_pps->i1_tiles_enabled_flag = TILES_ENABLED; ps_pps->i1_uniform_spacing_flag = ps_tile_params_base->i4_uniform_spacing_flag; if(SPACING_IS_NONUNIFORM == ps_pps->i1_uniform_spacing_flag) { WORD32 i4_i; for(i4_i = 0; i4_i < ps_tile_params_base->i4_num_tile_cols; i4_i++) { ps_pps->ps_tile[i4_i].u2_wd = pi4_column_width_array[i4_i] >> ps_config_prms->i4_max_log2_cu_size; } for(i4_i = 0; i4_i < ps_tile_params_base->i4_num_tile_rows; i4_i++) { ps_pps->ps_tile[i4_i].u2_ht = pi4_row_height_array[i4_i] >> ps_config_prms->i4_max_log2_cu_size; } } } /* SAO_note_01: Currently SAO is implemented is such a way that the loop-filter has to be enabled across syntatical-tiles and slices. Search for <SAO_note_01> in workspace to know more */ if(0 == ps_tile_params_base->i4_tiles_enabled_flag) { ps_pps->i1_loop_filter_across_tiles_enabled_flag = 1; } else { ps_pps->i1_loop_filter_across_tiles_enabled_flag = 0; } ps_pps->i1_output_flag_present_flag = OUTPUT_FLAG_ABSENT; ps_pps->i1_pic_cb_qp_offset = DEFAULT_PIC_CB_QP_OFFSET; ps_pps->i1_pic_cr_qp_offset = DEFAULT_PIC_CR_QP_OFFSET; /*init qp is different for each bit-rate instance */ ps_pps->i1_pic_init_qp = CLIP3( ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id] .ai4_frame_qp[i4_bitrate_instance_id], ps_config_prms->i4_min_frame_qp, ps_config_prms->i4_max_frame_qp); /* enable chroma QP offset only if stasino or psy rd is present */ if(((ps_coding_params->i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER)) && ((ps_coding_params->i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) || (ps_coding_params->i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_1)) || (ps_coding_params->i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_2)) || (ps_coding_params->i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_3))))) { ps_pps->i1_pic_slice_level_chroma_qp_offsets_present_flag = SLICE_LEVEL_CHROMA_QP_OFFSETS_PRESENT; } else { ps_pps->i1_pic_slice_level_chroma_qp_offsets_present_flag = SLICE_LEVEL_CHROMA_QP_OFFSETS_ABSENT; } ps_pps->i1_pps_id = DEFAULT_PPS_ID; if(1 == ps_stat_cfg_prms->s_tgt_lyr_prms.i4_mres_single_out) { ps_pps->i1_pps_id = i4_resolution_id; } ps_pps->i1_pps_scaling_list_data_present_flag = SCALING_LIST_DATA_ABSENT; if(ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset < IHEVCE_QUALITY_P3) { ps_pps->i1_sign_data_hiding_flag = SIGN_DATA_HIDDEN; } else if( ps_stat_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset == IHEVCE_QUALITY_P3) { ps_pps->i1_sign_data_hiding_flag = SIGN_DATA_UNHIDDEN; } else { ps_pps->i1_sign_data_hiding_flag = SIGN_DATA_UNHIDDEN; } #if DISABLE_SBH ps_pps->i1_sign_data_hiding_flag = SIGN_DATA_UNHIDDEN; #endif ps_pps->i1_slice_extension_present_flag = SLICE_EXTENSION_ABSENT; ps_pps->i1_slice_header_extension_present_flag = SLICE_HEADER_EXTENSION_ABSENT; ps_pps->i1_sps_id = ps_sps->i1_sps_id; ps_pps->i1_tc_offset_div2 = DEFAULT_TC_OFFSET; ps_pps->i1_transform_skip_enabled_flag = TRANSFORM_SKIP_DISABLED; ps_pps->i1_transquant_bypass_enable_flag = TRANSFORM_BYPASS_DISABLED; ps_pps->i1_weighted_bipred_flag = ps_coding_params->i4_weighted_pred_enable; ps_pps->i1_weighted_pred_flag = ps_coding_params->i4_weighted_pred_enable; return IHEVCE_SUCCESS; } /** ****************************************************************************** * * @brief Populates slice header structure * * @par Description * Populates slice header structure for its use in header generation * * @param[out] ps_slice_hdr * pointer to slice header structure that needs to be populated * * @param[in] ps_pps * pointer to pps params structure refered by the slice * * @param[in] ps_sps * pointer to sps params refered by the pps * * @param[in] nal_unit_type * nal unit type for current slice * * @param[in] slice_type * current slice type * * @param[in] ctb_x * x offset of first ctb in current slice (ctb units) * * @param[in] ctb_y * y offset of first ctb in current slice (ctb units) * * @param[in] poc * pic order count for current slice (shall be 0 for IDR pics) * * @param[in] cur_slice_qp * qp for the current slice * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_populate_slice_header( slice_header_t *ps_slice_hdr, pps_t *ps_pps, sps_t *ps_sps, WORD32 nal_unit_type, WORD32 slice_type, WORD32 ctb_x, WORD32 ctb_y, WORD32 poc, WORD32 cur_slice_qp, WORD32 max_merge_candidates, WORD32 i4_rc_pass_num, WORD32 i4_quality_preset, WORD32 stasino_enabled) { WORD32 i; WORD32 return_status = IHEVCE_SUCCESS; WORD32 RapPicFlag = (nal_unit_type >= NAL_BLA_W_LP) && (nal_unit_type <= NAL_RSV_RAP_VCL23); WORD32 idr_pic_flag = (NAL_IDR_W_LP == nal_unit_type) || (NAL_IDR_N_LP == nal_unit_type); WORD32 disable_deblocking_filter_flag; (void)ctb_x; (void)ctb_y; /* first_slice_in_pic_flag */ if(i4_quality_preset == IHEVCE_QUALITY_P7) { i4_quality_preset = IHEVCE_QUALITY_P6; } if(RapPicFlag) { /* no_output_of_prior_pics_flag */ /* TODO:revisit this */ ps_slice_hdr->i1_no_output_of_prior_pics_flag = 0; //BLU_RAY specific already done } /* pic_parameter_set_id */ ps_slice_hdr->i1_pps_id = ps_pps->i1_pps_id; { /* This i1_dependent_slice_flag will further be updated in generate_slice_header() function */ ps_slice_hdr->i1_dependent_slice_flag = 0; } if(!ps_slice_hdr->i1_dependent_slice_flag) { /* slice_type */ ps_slice_hdr->i1_slice_type = (WORD8)slice_type; if(ps_pps->i1_output_flag_present_flag) { /* pic_output_flag */ /* TODO:revisit this */ ps_slice_hdr->i1_pic_output_flag = 0; } /* separate colour plane flag not supported in this encoder */ ASSERT(0 == ps_sps->i1_separate_colour_plane_flag); if(!idr_pic_flag) { WORD32 log2_max_poc_lsb = ps_sps->i1_log2_max_pic_order_cnt_lsb; /* pic_order_cnt_lsb */ ps_slice_hdr->i4_pic_order_cnt_lsb = poc & ((1 << log2_max_poc_lsb) - 1); /* short_term_ref_pic_set_sps_flag */ /* TODO : revisit this */ ps_slice_hdr->i1_short_term_ref_pic_set_sps_flag = 0; if(!ps_slice_hdr->i1_short_term_ref_pic_set_sps_flag) { /* TODO: To populate short term ref pic set for this slice */ } /* long term ref pic flag not supported */ ASSERT(0 == ps_sps->i1_long_term_ref_pics_present_flag); if(ps_sps->i1_long_term_ref_pics_present_flag) { /* TODO : not supported */ } } //ASSERT(0 == ps_sps->i1_sample_adaptive_offset_enabled_flag); if(ps_sps->i1_sample_adaptive_offset_enabled_flag) { /* slice_sao_luma_flag */ ps_slice_hdr->i1_slice_sao_luma_flag = 1; ps_slice_hdr->i1_slice_sao_chroma_flag = 1; } #if DISABLE_LUMA_SAO ps_slice_hdr->i1_slice_sao_luma_flag = 0; #endif #if DISABLE_CHROMA_SAO ps_slice_hdr->i1_slice_sao_chroma_flag = 0; #endif if((PSLICE == ps_slice_hdr->i1_slice_type) || (BSLICE == ps_slice_hdr->i1_slice_type)) { /* TODO: currently temporal mvp disabled, need to enable later */ if(1 == ps_sps->i1_sps_temporal_mvp_enable_flag) { ps_slice_hdr->i1_slice_temporal_mvp_enable_flag = 1; } else { ps_slice_hdr->i1_slice_temporal_mvp_enable_flag = 0; } /* num_ref_idx_active_override_flag */ ps_slice_hdr->i1_num_ref_idx_active_override_flag = 0; if(ps_slice_hdr->i1_num_ref_idx_active_override_flag) { /* TODO revisit this*/ /* i1_num_ref_idx_l0_active_minus1 */ ps_slice_hdr->i1_num_ref_idx_l0_active = 1; if(BSLICE == ps_slice_hdr->i1_slice_type) { /* i1_num_ref_idx_l1_active */ /* TODO revisit this*/ ps_slice_hdr->i1_num_ref_idx_l1_active = 1; } } if(BSLICE == ps_slice_hdr->i1_slice_type) { /* mvd_l1_zero_flag */ ps_slice_hdr->i1_mvd_l1_zero_flag = 0; } { /* cabac_init_flag curently set to 0 */ ps_slice_hdr->i1_cabac_init_flag = ps_pps->i1_cabac_init_present_flag ? 1 : 0; } if(ps_slice_hdr->i1_slice_temporal_mvp_enable_flag) { if(BSLICE == ps_slice_hdr->i1_slice_type) { /* collocated_from_l0_flag */ ps_slice_hdr->i1_collocated_from_l0_flag = 0; } else if(PSLICE == ps_slice_hdr->i1_slice_type) { ps_slice_hdr->i1_collocated_from_l0_flag = 1; } if((ps_slice_hdr->i1_collocated_from_l0_flag && (ps_slice_hdr->i1_num_ref_idx_l0_active > 1)) || (!ps_slice_hdr->i1_collocated_from_l0_flag && (ps_slice_hdr->i1_num_ref_idx_l1_active > 1))) { /* collocated_ref_idx */ /* TODO revisit this*/ ps_slice_hdr->i1_collocated_ref_idx = 0; //ps_slice_hdr->i1_num_ref_idx_l1_active - 1; } } } ps_slice_hdr->i1_max_num_merge_cand = max_merge_candidates; /* TODO : revisit this */ ps_slice_hdr->i1_slice_qp_delta = (WORD8)cur_slice_qp - ps_pps->i1_pic_init_qp; if(!ps_pps->i1_pic_slice_level_chroma_qp_offsets_present_flag || !stasino_enabled) { /* slice_cb_qp_offset */ ps_slice_hdr->i1_slice_cb_qp_offset = 0; /* slice_cr_qp_offset */ ps_slice_hdr->i1_slice_cr_qp_offset = 0; } else /* only noisy regions have lower Chroma QP rating */ { ps_slice_hdr->i1_slice_cb_qp_offset = -2; ps_slice_hdr->i1_slice_cr_qp_offset = -2; } if(ps_pps->i1_deblocking_filter_control_present_flag) { ps_slice_hdr->i1_deblocking_filter_override_flag = 0; if(ps_pps->i1_deblocking_filter_override_enabled_flag) { /* deblocking_filter_override_flag */ ps_slice_hdr->i1_deblocking_filter_override_flag = 0; } if(ps_slice_hdr->i1_deblocking_filter_override_flag) { /* slice_disable_deblocking_filter_flag */ ps_slice_hdr->i1_slice_disable_deblocking_filter_flag = DISABLE_DEBLOCKING_FLAG; if(!ps_slice_hdr->i1_slice_disable_deblocking_filter_flag) { /* beta_offset_div2 */ ps_slice_hdr->i1_beta_offset_div2 = 0; /* tc_offset_div2 */ ps_slice_hdr->i1_tc_offset_div2 = 0; } } } disable_deblocking_filter_flag = ps_slice_hdr->i1_slice_disable_deblocking_filter_flag | ps_pps->i1_pic_disable_deblocking_filter_flag; if(ps_pps->i1_loop_filter_across_slices_enabled_flag && (ps_slice_hdr->i1_slice_sao_luma_flag || ps_slice_hdr->i1_slice_sao_chroma_flag || !disable_deblocking_filter_flag)) { /* slice_loop_filter_across_slices_enabled_flag */ ps_slice_hdr->i1_slice_loop_filter_across_slices_enabled_flag = 1; } } if(1 == ps_pps->i1_entropy_coding_sync_enabled_flag) { /* num_entry_point_offsets, same as NUM of ctb rows to enable entropy sync at start of every CTB */ ps_slice_hdr->i4_num_entry_point_offsets = ps_sps->i2_pic_ht_in_ctb - 1; if(ps_slice_hdr->i4_num_entry_point_offsets > 0) { /* generate offset_len here */ /* fixing the offset lenght assuming 4kx2k is log2(w * h / num_ctb_row) = 20*/ ps_slice_hdr->i1_offset_len = 24; } } else { ps_slice_hdr->i4_num_entry_point_offsets = 0; ps_slice_hdr->i1_offset_len = 0; } /* slice_header_extension_present_flag not supported */ //if(ps_pps->i1_slice_header_extension_present_flag) { /* slice_header_extension_length */ ps_slice_hdr->i2_slice_header_extension_length = 0; for(i = 0; i < ps_slice_hdr->i2_slice_header_extension_length; i++) { /* slice_header_extension_data_byte[i] */ } } /* TODO : hard coding ref pix set for now */ /* Need to update this once the ref pics are known from lap output */ /* NOTE */ /* inter ref pic prediction is too much of logic for few bit savings*/ /* at slice header level this is not supported by the encoder */ ps_slice_hdr->s_stref_picset.i1_inter_ref_pic_set_prediction_flag = 0; /* hardcoding 1 ref pic for now ..... will be updated base on lap output */ ps_slice_hdr->s_stref_picset.i1_num_delta_pocs = 1; ps_slice_hdr->s_stref_picset.i1_num_neg_pics = 1; ps_slice_hdr->s_stref_picset.i1_num_pos_pics = 0; memset( ps_slice_hdr->s_stref_picset.ai2_delta_poc, 0, MAX_DPB_SIZE * sizeof(*ps_slice_hdr->s_stref_picset.ai2_delta_poc)); ps_slice_hdr->s_stref_picset.ai2_delta_poc[0] = 1; return return_status; } /** ****************************************************************************** * * @brief Insert entry point offset * * @par Description * Insert entry point offset in slice header after frame processing is done 7.3.5.1 * * @param[inout] ps_bitstrm * pointer to bitstream context for generating slice header * * @param[in] i1_nal_unit_type * nal unit type * * @param[in] ps_slice_hdr * pointer to slice header params * * @param[in] ps_pps * pointer to pps params referred by slice * * @param[in] ps_sps * pointer to sps params referred by slice * * @return success or failure error code * ****************************************************************************** */ WORD32 ihevce_insert_entry_offset_slice_header( bitstrm_t *ps_bitstrm, slice_header_t *ps_slice_hdr, pps_t *ps_pps, UWORD32 u4_first_slice_start_offset) { WORD32 i; WORD32 return_status = IHEVCE_SUCCESS; UWORD32 max_offset = 0, offset_len = 0, num_bytes_shift = 0; /*entire slice data has to be shifted*/ num_bytes_shift = ps_slice_hdr->pu4_entry_point_offset[ps_slice_hdr->i4_num_entry_point_offsets + 1] - ps_slice_hdr->pu4_entry_point_offset[0]; /*generate relative offset*/ for(i = 0; i < ps_slice_hdr->i4_num_entry_point_offsets; i++) { ps_slice_hdr->pu4_entry_point_offset[i] = ps_slice_hdr->pu4_entry_point_offset[i + 1] - ps_slice_hdr->pu4_entry_point_offset[i]; if(ps_slice_hdr->pu4_entry_point_offset[i] > (WORD32)max_offset) { max_offset = ps_slice_hdr->pu4_entry_point_offset[i]; } } while(1) { if(max_offset & 0x80000000) { break; } max_offset <<= 1; offset_len++; } offset_len = 32 - offset_len; ps_slice_hdr->i1_offset_len = offset_len; if(ps_slice_hdr->i4_num_entry_point_offsets > 0) { /* offset_len_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_offset_len - 1, return_status); ENTROPY_TRACE("offset_len_minus1", ps_slice_hdr->i1_offset_len - 1); } for(i = 0; i < ps_slice_hdr->i4_num_entry_point_offsets; i++) { /* entry_point_offset[i] */ /* entry point offset minus1 is indicated in 10.0 */ PUT_BITS( ps_bitstrm, ps_slice_hdr->pu4_entry_point_offset[i] - 1, ps_slice_hdr->i1_offset_len, return_status); ENTROPY_TRACE("entry_point_offset[i]", ps_slice_hdr->pu4_entry_point_offset[i]); } if(ps_pps->i1_slice_header_extension_present_flag) { /* slice_header_extension_length */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i2_slice_header_extension_length, return_status); ENTROPY_TRACE( "slice_header_extension_length", ps_slice_hdr->i2_slice_header_extension_length); /*calculate slice header extension length to fill in the gap*/ for(i = 0; i < ps_slice_hdr->i2_slice_header_extension_length; i++) { /* slice_header_extension_data_byte[i] */ PUT_BITS(ps_bitstrm, 0xFF, 8, return_status); ENTROPY_TRACE("slice_header_extension_data_byte[i]", 0); } } BYTE_ALIGNMENT(ps_bitstrm); ASSERT(num_bytes_shift > 0); /* copy the bitstream to point where header data has ended*/ memmove( (UWORD8 *)(ps_bitstrm->pu1_strm_buffer + ps_bitstrm->u4_strm_buf_offset), (UWORD8 *)(ps_bitstrm->pu1_strm_buffer + u4_first_slice_start_offset), num_bytes_shift); /*send feedback of actual bytes generated*/ ps_bitstrm->u4_strm_buf_offset += num_bytes_shift; //ASSERT(ps_bitstrm->u4_strm_buf_offset == u4_first_slice_start_offset); return return_status; }