| /****************************************************************************** |
| * |
| * 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 bit_allocation.c |
| * |
| * \brief |
| * This file contain bit processing functions |
| * |
| * \date |
| * |
| * \author |
| * ittiam |
| * |
| ****************************************************************************** |
| */ |
| /*****************************************************************************/ |
| /* 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 "ittiam_datatypes.h" |
| #include "mem_req_and_acq.h" |
| #include "rc_common.h" |
| #include "rc_cntrl_param.h" |
| #include "var_q_operator.h" |
| #include "fixed_point_error_bits.h" |
| #include "cbr_buffer_control.h" |
| #include "rc_rd_model.h" |
| #include "est_sad.h" |
| #include "cbr_buffer_control.h" |
| #include "picture_type.h" |
| #include "bit_allocation.h" |
| #include "trace_support.h" |
| #include "rc_frame_info_collector.h" |
| #include "rate_control_api.h" |
| |
| /** Macros **/ |
| #define MIN(x, y) ((x) < (y)) ? (x) : (y) |
| #define MAX(x, y) ((x) < (y)) ? (y) : (x) |
| |
| /* State structure for bit allocation */ |
| typedef struct |
| { |
| WORD32 i4_rem_bits_in_period; |
| /* Storing inputs */ |
| WORD32 i4_tot_frms_in_gop; |
| WORD32 i4_num_intra_frm_interval; |
| WORD32 i4_bits_per_frm; |
| } rem_bit_in_prd_t; |
| |
| typedef struct bit_allocation_t |
| { |
| rem_bit_in_prd_t s_rbip; |
| WORD32 |
| i2_K[MAX_PIC_TYPE]; /* A universal constant giving the relative complexity between pictures */ |
| WORD32 i4_prev_frm_header_bits[MAX_PIC_TYPE]; /* To get a estimate of the header bits consumed */ |
| WORD32 ai4_prev_frm_tot_bits[MAX_PIC_TYPE]; |
| WORD32 ai4_prev_frm_tot_est_bits[MAX_PIC_TYPE]; |
| WORD32 i4_bits_per_frm; |
| WORD32 i4_num_gops_in_period; |
| WORD32 |
| i4_actual_num_gops_in_period; /* Num gops as set by rate control module */ |
| WORD32 i4_saved_bits; |
| WORD32 i4_max_bits_per_frm[MAX_NUM_DRAIN_RATES]; |
| WORD32 i4_min_bits_per_frm; |
| /* Error bits module */ |
| error_bits_handle ps_error_bits; |
| /* Storing frame rate */ |
| WORD32 i4_frame_rate; |
| WORD32 i4_bit_rate; |
| WORD32 ai4_peak_bit_rate[MAX_NUM_DRAIN_RATES]; |
| WORD32 i4_max_tex_bits_for_i; |
| WORD32 i4_pels_in_frame; |
| /* Errors within GOP and across GOP */ |
| WORD32 i4_gop_level_bit_error; |
| WORD32 i4_frame_level_bit_error; |
| WORD32 ai4_cur_frm_est_tex_bits[MAX_NUM_FRAME_PARALLEL]; |
| WORD32 ai4_cur_frm_est_hdr_bits[MAX_NUM_FRAME_PARALLEL]; |
| WORD32 i4_buffer_based_bit_error; |
| WORD32 i4_bits_from_buffer_in_cur_gop; |
| WORD32 i4_excess_bits_from_buffer; |
| |
| WORD32 i4_is_hbr; |
| WORD32 i4_rem_frame_in_period; |
| /*HEVC_RC : this will be updated by rc_interface.c to have number of SCD in lap window. |
| Ni will be incremented using this to bring down buffer level and also back to back scd within lap window*/ |
| WORD32 i4_num_scd_in_lap_window; |
| WORD32 i4_num_frm_b4_scd; |
| WORD32 i4_num_active_pic_type; |
| WORD32 i4_lap_window; |
| WORD32 i4_field_pic; |
| WORD32 i4_ba_rc_pass; |
| void *pv_gop_stat; |
| LWORD64 i8_cur_gop_num; |
| LWORD64 |
| i8_frm_num_in_gop; /*TBD: For enc loop parallel this variable needs to maintained outside rate control since qp will not be queried in actual bitstream order*/ |
| float af_sum_weigh[MAX_PIC_TYPE][3]; |
| LWORD64 i8_cur_gop_bit_consumption; /*To calculate the deviaiton in 2 pass*/ |
| //LWORD64 i8_2pass_gop_error_accum; |
| LWORD64 |
| i8_2pass_alloc_per_frm_bits; /*Per frame bits allocated to GOP in 2 pass*/ |
| //LWORD64 i8_2pass_alloc_per_frm_bits_next_gop; |
| |
| float f_min_complexity_cross_peak_rate; /*complexity of gop beyond which it is clipped to peak rate in 2ns pass*/ |
| WORD32 i4_next_sc_i_in_rc_look_ahead; |
| /*The peak factor is multiplied to get the total bits for a gop based on squashing function*/ |
| float f_cur_peak_factor_2pass; |
| LWORD64 i8_total_bits_allocated; |
| WORD32 i4_luma_pels; |
| WORD32 i4_num_gop; |
| /*The bitrate will keep changing in 2 pass due to error*/ |
| LWORD64 i8_current_bitrate_2_pass; |
| /*i4_flag_no_more_set_rbip - once we have reached the end of total number of frames to be encoded in |
| 2nd pass sliding window bit allocation there is no need to set rbip again*/ |
| WORD32 i4_flag_no_more_set_rbip; |
| /*i8_vbv_based_excess_for_segment will be distributed across the complex segments depending on the |
| ratio of current complexity to f_sum_complexity_segment_cross_peak*/ |
| float f_sum_complexity_segment_cross_peak; |
| /*(i8_vbv_based_excess_for_segment)Buffer play excess is calculated for the entire segment of complex |
| content which may consist of multiple gop's*/ |
| //LWORD64 i8_vbv_based_excess_for_segment; |
| /*I frame bit allocation during scene cuts is dependent on f_curr_i_to_sum which will signal |
| the complexity difference between current i to future i's if present in the same default gop*/ |
| float f_curr_i_to_sum; |
| float f_curr_by_sum_subgop; |
| WORD32 ai4_pic_types_in_subgop[MAX_PIC_TYPE]; |
| WORD32 i4_use_subgop_bit_alloc_flag; |
| WORD32 i4_num_frames_since_last_I_frame; |
| LWORD64 i8_first_pic_bits_pictype[MAX_PIC_TYPE]; |
| LWORD64 i8_avg_bits_pictype[MAX_PIC_TYPE]; |
| WORD32 i4_avg_qscale_gop_first_pass; |
| WORD32 i4_fp_bit_alloc_in_sp; |
| WORD32 i4_frame_level_error_ctr_update_rc; |
| float f_qscale_max_clip_in_second_pass; |
| float f_average_qscale_1st_pass; |
| float f_max_average_qscale_1st_pass; |
| LWORD64 i8_bit_consumption_so_far; |
| WORD32 i4_total_2pass_frames; |
| LWORD64 i8_2pass_avg_bit_rate; |
| WORD32 i4_br_id; |
| } bit_allocation_t; |
| |
| static WORD32 get_actual_num_frames_in_gop(pic_handling_handle ps_pic_handling) |
| { |
| WORD32 i4_tot_frms_in_gop = 0, i; |
| WORD32 ai4_actual_frms_in_gop[MAX_PIC_TYPE]; |
| memset(ai4_actual_frms_in_gop, 0, MAX_PIC_TYPE * sizeof(WORD32)); |
| pic_type_get_actual_frms_in_gop(ps_pic_handling, ai4_actual_frms_in_gop); |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| i4_tot_frms_in_gop += ai4_actual_frms_in_gop[i]; |
| } |
| return (i4_tot_frms_in_gop); |
| } |
| |
| float get_cur_peak_factor_2pass(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->f_cur_peak_factor_2pass); |
| } |
| float get_cur_min_complexity_factor_2pass(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->f_min_complexity_cross_peak_rate); |
| } |
| void set_2pass_total_gops(bit_allocation_t *ps_bit_allocation, WORD32 i4_num_gop) |
| { |
| ps_bit_allocation->i4_num_gop = i4_num_gop; |
| } |
| #if NON_STEADSTATE_CODE |
| /* Module for accessing remaining bits in period */ |
| /***************************************************************************** |
| Function Name : init_rbip |
| Description : Initalises the remaining bits in period structure. |
| Inputs : ps_rbip -remaining bits in period structure |
| ps_pic_handling - Pic handling structure |
| num_intra_frm_interval - num of I frm intervals in this period |
| i4_bits_per_frm - num bits per frm |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static void init_rbip( |
| rem_bit_in_prd_t *ps_rbip, |
| pic_handling_handle ps_pic_handling, |
| WORD32 i4_bits_per_frm, |
| WORD32 i4_num_intra_frm_interval) |
| { |
| WORD32 i4_tot_frms_in_gop = get_actual_num_frames_in_gop(ps_pic_handling); |
| /* WORD32 i4_frm_correction_for_open_gop = 0; */ |
| /* If the GOP is open, then we need to subtract the num_b_frames for the first gop */ |
| /*if(!pic_type_is_gop_closed(ps_pic_handling)) |
| { |
| i4_frm_correction_for_open_gop = pic_type_get_inter_frame_interval(ps_pic_handling)-1; |
| }*/ |
| ps_rbip->i4_rem_bits_in_period = |
| i4_bits_per_frm * |
| (i4_tot_frms_in_gop * i4_num_intra_frm_interval /*- i4_frm_correction_for_open_gop*/); |
| |
| /* Store the total number of frames in GOP value which is |
| * used from module A */ |
| ps_rbip->i4_tot_frms_in_gop = i4_tot_frms_in_gop; |
| ps_rbip->i4_num_intra_frm_interval = i4_num_intra_frm_interval; |
| ps_rbip->i4_bits_per_frm = i4_bits_per_frm; |
| } |
| #endif /* #if NON_STEADSTATE_CODE */ |
| |
| /***************************************************************************** |
| Function Name : check_update_rbip |
| Description : Function for updating rbip. |
| Inputs : ps_rbip -remaining bits in period structure |
| ps_pic_handling - Pic handling structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static void check_update_rbip(rem_bit_in_prd_t *ps_rbip, pic_handling_handle ps_pic_handling) |
| { |
| /* NOTE: Intra frame interval changes aafter the first I frame that is encoded in a GOP */ |
| WORD32 i4_new_tot_frms_in_gop = get_actual_num_frames_in_gop(ps_pic_handling); |
| if(i4_new_tot_frms_in_gop != ps_rbip->i4_tot_frms_in_gop) |
| { |
| WORD32 i4_num_frames_in_period = ps_rbip->i4_num_intra_frm_interval * |
| (i4_new_tot_frms_in_gop - ps_rbip->i4_tot_frms_in_gop); |
| overflow_avoided_summation( |
| &ps_rbip->i4_rem_bits_in_period, (ps_rbip->i4_bits_per_frm * i4_num_frames_in_period)); |
| } |
| /* Updated the new values */ |
| ps_rbip->i4_tot_frms_in_gop = i4_new_tot_frms_in_gop; |
| } |
| /***************************************************************************** |
| Function Name : ret_rbip_default_preenc |
| Description : Function for calculating bits in period. |
| Inputs : ps_rbip -remaining bits in period structure |
| ps_pic_handling - Pic handling structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static WORD32 |
| ret_rbip_default_preenc(rem_bit_in_prd_t *ps_rbip, pic_handling_handle ps_pic_handling) |
| { |
| WORD32 i4_bits_in_period = |
| pic_type_get_intra_frame_interval(ps_pic_handling) * ps_rbip->i4_bits_per_frm; |
| return (i4_bits_in_period); |
| } |
| /***************************************************************************** |
| Function Name : update_rbip |
| Description : Function for updating rbip. |
| Inputs : ps_rbip -remaining bits in period structure |
| ps_pic_handling - Pic handling structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static WORD32 update_rbip( |
| rem_bit_in_prd_t *ps_rbip, pic_handling_handle ps_pic_handling, WORD32 i4_num_of_bits) |
| { |
| check_update_rbip(ps_rbip, ps_pic_handling); |
| overflow_avoided_summation(&ps_rbip->i4_rem_bits_in_period, i4_num_of_bits); |
| return (ps_rbip->i4_rem_bits_in_period); |
| } |
| /***************************************************************************** |
| Function Name : get_rbip_and_num_frames |
| Description : Update rbip and get number of frames. |
| Inputs : ps_rbip -remaining bits in period structure |
| ps_pic_handling - Pic handling structure |
| pi4_num_frames - pointer to update number of frmes |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static LWORD64 get_rbip_and_num_frames( |
| rem_bit_in_prd_t *ps_rbip, |
| pic_handling_handle ps_pic_handling, |
| WORD32 i4_num_of_bits, |
| WORD32 *pi4_num_frames) |
| { |
| check_update_rbip(ps_rbip, ps_pic_handling); |
| overflow_avoided_summation(&ps_rbip->i4_rem_bits_in_period, i4_num_of_bits); |
| *pi4_num_frames = ps_rbip->i4_tot_frms_in_gop; |
| return (ps_rbip->i4_rem_bits_in_period); |
| } |
| /***************************************************************************** |
| Function Name : set_rbip |
| Description : Set rbip |
| Inputs : ps_rbip -remaining bits in period structure |
| i4_error_bits - Error bits |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static WORD32 set_rbip(rem_bit_in_prd_t *ps_rbip, WORD32 i4_error_bits) |
| { |
| ps_rbip->i4_rem_bits_in_period = (ps_rbip->i4_bits_per_frm * ps_rbip->i4_tot_frms_in_gop * |
| ps_rbip->i4_num_intra_frm_interval) + |
| i4_error_bits; |
| |
| return ps_rbip->i4_rem_bits_in_period; |
| } |
| |
| /***************************************************************************** |
| Function Name : multi_pass_set_rbip |
| Description : 2 pass set RBIP, since the gop bits shall not depend on bitrate or framerate, |
| GOP bits is directly obtained from first pass data |
| Inputs : ps_rbip -remaining bits in period structure |
| ps_pic_handling - Pic handling structure |
| i4_cur_gop_bits - bits allocated for the curr gop |
| i4_tot_frm_in_cur_gop - frames in the gop |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static void multi_pass_set_rbip( |
| rem_bit_in_prd_t *ps_rbip, |
| pic_handling_handle ps_pic_handling, |
| WORD32 i4_cur_gop_bits, |
| WORD32 i4_tot_frm_in_cur_gop) |
| { |
| WORD32 i4_num_frames_in_gop = get_actual_num_frames_in_gop(ps_pic_handling); |
| ps_rbip->i4_rem_bits_in_period = |
| (WORD32)((LWORD64)i4_cur_gop_bits * i4_num_frames_in_gop / i4_tot_frm_in_cur_gop); |
| ps_rbip->i4_tot_frms_in_gop = i4_num_frames_in_gop; |
| ps_rbip->i4_bits_per_frm = ps_rbip->i4_rem_bits_in_period / i4_num_frames_in_gop; |
| } |
| static void change_rbip( |
| rem_bit_in_prd_t *ps_rbip, WORD32 i4_new_bits_per_frm, WORD32 i4_new_num_intra_frm_interval) |
| { |
| if(i4_new_bits_per_frm != ps_rbip->i4_bits_per_frm) |
| { |
| WORD32 i4_rem_frms_in_period = |
| (ps_rbip->i4_num_intra_frm_interval) * ps_rbip->i4_tot_frms_in_gop; |
| overflow_avoided_summation( |
| &ps_rbip->i4_rem_bits_in_period, |
| ((i4_new_bits_per_frm - ps_rbip->i4_bits_per_frm) * i4_rem_frms_in_period)); |
| } |
| if(i4_new_num_intra_frm_interval != ps_rbip->i4_num_intra_frm_interval) |
| { |
| overflow_avoided_summation( |
| &ps_rbip->i4_rem_bits_in_period, |
| (i4_new_bits_per_frm * ps_rbip->i4_tot_frms_in_gop * |
| (i4_new_num_intra_frm_interval - ps_rbip->i4_num_intra_frm_interval))); |
| } |
| /* Update the new value */ |
| ps_rbip->i4_num_intra_frm_interval = i4_new_num_intra_frm_interval; |
| ps_rbip->i4_bits_per_frm = i4_new_bits_per_frm; |
| } |
| |
| #if NON_STEADSTATE_CODE |
| WORD32 bit_allocation_num_fill_use_free_memtab( |
| bit_allocation_t **pps_bit_allocation, itt_memtab_t *ps_memtab, ITT_FUNC_TYPE_E e_func_type) |
| { |
| WORD32 i4_mem_tab_idx = 0; |
| static bit_allocation_t s_bit_allocation_temp; |
| |
| /* Hack for al alloc, during which we dont have any state memory. |
| Dereferencing can cause issues */ |
| if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB) |
| (*pps_bit_allocation) = &s_bit_allocation_temp; |
| |
| /*for src rate control state structure*/ |
| if(e_func_type != GET_NUM_MEMTAB) |
| { |
| fill_memtab( |
| &ps_memtab[i4_mem_tab_idx], |
| sizeof(bit_allocation_t), |
| MEM_TAB_ALIGNMENT, |
| PERSISTENT, |
| DDR); |
| use_or_fill_base(&ps_memtab[0], (void **)pps_bit_allocation, e_func_type); |
| } |
| i4_mem_tab_idx++; |
| |
| i4_mem_tab_idx += error_bits_num_fill_use_free_memtab( |
| &pps_bit_allocation[0]->ps_error_bits, &ps_memtab[i4_mem_tab_idx], e_func_type); |
| |
| return (i4_mem_tab_idx); |
| } |
| #endif /* #if NON_STEADSTATE_CODE */ |
| |
| /***************************************************************************** |
| Function Name : get_bits_based_on_complexity |
| Description : function calculates the bits to be allocated for the current |
| picture type given the relative complexity between different |
| picture types |
| Inputs : i4_bits_in_period |
| pi4_frms_in_period - num frames of each pictype in the period |
| pvq_complexity_estimate - complexity for each pictype |
| e_pic_type - current picture type |
| i4_call_type |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| static WORD32 get_bits_based_on_complexity( |
| bit_allocation_t *ps_bit_allocation, |
| WORD32 i4_bits_in_period, |
| WORD32 *pi4_frms_in_period, |
| number_t *pvq_complexity_estimate, |
| picture_type_e e_pic_type, |
| WORD32 i4_call_type) |
| { |
| WORD32 i, i4_estimated_bits; |
| number_t vq_bits_in_period, vq_frms_in_period[MAX_PIC_TYPE], vq_comp_coeff, |
| vq_est_texture_bits_for_frm; |
| WORD32 i4_num_scd_in_LAP_window = ps_bit_allocation->i4_num_scd_in_lap_window; |
| WORD32 i4_active_pic_types = ps_bit_allocation->i4_num_active_pic_type, |
| i4_field_pic = ps_bit_allocation->i4_field_pic; |
| float af_sum_weigh[MAX_PIC_TYPE][3]; |
| |
| memmove(af_sum_weigh, ps_bit_allocation->af_sum_weigh, ((sizeof(float)) * MAX_PIC_TYPE * 3)); |
| |
| /** Increment I frame count if there is scene cut in LAP window*/ |
| i4_num_scd_in_LAP_window = 0; |
| pi4_frms_in_period[I_PIC] += i4_num_scd_in_LAP_window; |
| /* Converting inputs to var_q format */ |
| SET_VAR_Q(vq_bits_in_period, i4_bits_in_period, 0); |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| SET_VAR_Q(vq_frms_in_period[i], pi4_frms_in_period[i], 0); |
| } |
| /****************************************************************** |
| Estimated texture bits = |
| (remaining bits) * (cur frm complexity) |
| --------------------------------------- |
| (num_i_frm*i_frm_complexity) + (num_p_frm*pfrm_complexity) + (b_frm * b_frm_cm) |
| *******************************************************************/ |
| /*Taking the numerator weight into account*/ |
| if(i4_call_type == 1) |
| { |
| trace_printf("1 CUrr / avg %f", af_sum_weigh[e_pic_type][0]); |
| } |
| if(af_sum_weigh[e_pic_type][0] > 4.0f) |
| af_sum_weigh[e_pic_type][0] = 4.0f; |
| if(af_sum_weigh[e_pic_type][0] < 0.3f) |
| af_sum_weigh[e_pic_type][0] = 0.3f; |
| if(i4_call_type == 1) |
| { |
| trace_printf("2 CUrr / avg %f", af_sum_weigh[e_pic_type][0]); |
| } |
| |
| if((ps_bit_allocation->i4_ba_rc_pass != 2) || (i4_call_type == 0) || |
| (ps_bit_allocation->i4_fp_bit_alloc_in_sp == 0)) |
| { |
| convert_float_to_fix(af_sum_weigh[e_pic_type][0], &vq_comp_coeff); |
| mult32_var_q(vq_bits_in_period, vq_comp_coeff, &vq_bits_in_period); |
| mult32_var_q(vq_bits_in_period, pvq_complexity_estimate[e_pic_type], &vq_bits_in_period); |
| } |
| else |
| { |
| WORD32 i4_frame_num = (WORD32)ps_bit_allocation->i8_frm_num_in_gop, i4_offset; |
| gop_level_stat_t *ps_gop; |
| LWORD64 i8_firs_pass_tot_bits; |
| float f_bits_cur_pic, f_offset; |
| ps_gop = |
| (gop_level_stat_t *)ps_bit_allocation->pv_gop_stat + ps_bit_allocation->i8_cur_gop_num; |
| i8_firs_pass_tot_bits = ps_gop->ai8_tex_bits_consumed[i4_frame_num] + |
| ps_gop->ai8_head_bits_consumed[i4_frame_num]; |
| i4_offset = (ps_gop->ai4_q6_frame_offsets[i4_frame_num] * 1000) >> QSCALE_Q_FAC; |
| f_offset = ((float)i4_offset) / 1000; |
| f_bits_cur_pic = |
| (float)(i8_firs_pass_tot_bits * ps_gop->ai4_first_pass_qscale[i4_frame_num]) / |
| (ps_bit_allocation->i4_avg_qscale_gop_first_pass * f_offset); |
| convert_float_to_fix(f_bits_cur_pic, &vq_comp_coeff); |
| mult32_var_q(vq_bits_in_period, vq_comp_coeff, &vq_bits_in_period); |
| |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| number_t temp; |
| convert_float_to_fix((float)ps_bit_allocation->i8_avg_bits_pictype[i], &temp); |
| pvq_complexity_estimate[i] = temp; |
| } |
| } |
| |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| /*For 2nd pass we will be reducing the num of pictures as they are coded so we dont want to replace 0's*/ |
| if(af_sum_weigh[i][1] == 0.0 && |
| !((i4_call_type == 1) && (ps_bit_allocation->i4_ba_rc_pass == 2))) |
| af_sum_weigh[i][1] = (float)pi4_frms_in_period[i]; |
| |
| convert_float_to_fix(af_sum_weigh[i][1], &vq_comp_coeff); |
| mult32_var_q(vq_comp_coeff, pvq_complexity_estimate[i], &vq_frms_in_period[i]); |
| } |
| |
| /* changed the index range from active_pic to max_pic*/ |
| if(i4_field_pic) |
| { |
| for(i = 1; i < i4_active_pic_types; i++) |
| { |
| add32_var_q(vq_frms_in_period[I_PIC], vq_frms_in_period[i], &vq_frms_in_period[I_PIC]); |
| add32_var_q( |
| vq_frms_in_period[I_PIC], |
| vq_frms_in_period[i + FIELD_OFFSET], |
| &vq_frms_in_period[I_PIC]); |
| } |
| } |
| else /*field case*/ |
| { |
| for(i = 1; i < i4_active_pic_types; i++) |
| { |
| add32_var_q(vq_frms_in_period[I_PIC], vq_frms_in_period[i], &vq_frms_in_period[I_PIC]); |
| } |
| } |
| |
| div32_var_q(vq_bits_in_period, vq_frms_in_period[I_PIC], &vq_est_texture_bits_for_frm); |
| number_t_to_word32(vq_est_texture_bits_for_frm, &i4_estimated_bits); |
| |
| /* If the number of frames are zero then return zero */ |
| if(!pi4_frms_in_period[e_pic_type]) |
| i4_estimated_bits = 0; |
| return (i4_estimated_bits); |
| } |
| /***************************************************************************** |
| Function Name : assign_complexity_coeffs |
| Description : |
| Inputs : af_sum_weigh |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void assign_complexity_coeffs( |
| bit_allocation_t *ps_bit_allocation, float af_sum_weigh[MAX_PIC_TYPE][3]) |
| { |
| WORD32 i; |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| ps_bit_allocation->af_sum_weigh[i][0] = af_sum_weigh[i][0]; |
| ps_bit_allocation->af_sum_weigh[i][1] = af_sum_weigh[i][1]; |
| ps_bit_allocation->af_sum_weigh[i][2] = af_sum_weigh[i][2]; |
| } |
| } |
| /***************************************************************************** |
| Function Name : ba_get_rbip_and_num_frames |
| Description : |
| Inputs : pi4_num_frames |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| LWORD64 ba_get_rbip_and_num_frames( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handling, |
| WORD32 *pi4_num_frames) |
| { |
| return ( |
| get_rbip_and_num_frames(&ps_bit_allocation->s_rbip, ps_pic_handling, 0, pi4_num_frames)); |
| } |
| /***************************************************************************** |
| Function Name : init_prev_header_bits |
| Description : Intialise header bits for each pic type |
| Inputs : ps_bit_allocation |
| ps_pic_handling |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void init_prev_header_bits(bit_allocation_t *ps_bit_allocation, pic_handling_handle ps_pic_handling) |
| { |
| WORD32 i4_rem_bits_in_period, /* ai4_rem_frms_in_period[MAX_PIC_TYPE], */ |
| ai4_frms_in_period[MAX_PIC_TYPE], i, j; |
| number_t avq_complexity_estimate[MAX_PIC_TYPE]; |
| WORD32 i4_field_pic; |
| i4_field_pic = pic_type_get_field_pic(ps_pic_handling); |
| /* Assigning Percentages of I, P and B frame header bits based on actual bits allocated for I, P and B frames */ |
| /* Getting the remaining bits in period */ |
| i4_rem_bits_in_period = update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0); |
| |
| /* Hardcoding the bit ratios between I, P and B */ |
| SET_VAR_Q( |
| avq_complexity_estimate[I_PIC], |
| (I_TO_P_BIT_RATIO * P_TO_B_BIT_RATIO * B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), |
| 0); |
| SET_VAR_Q( |
| avq_complexity_estimate[P_PIC], |
| (P_TO_B_BIT_RATIO * B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), |
| 0); |
| SET_VAR_Q( |
| avq_complexity_estimate[P1_PIC], |
| (P_TO_B_BIT_RATIO * B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), |
| 0); |
| SET_VAR_Q(avq_complexity_estimate[B_PIC], (B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), 0); |
| SET_VAR_Q(avq_complexity_estimate[BB_PIC], (B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), 0); |
| SET_VAR_Q(avq_complexity_estimate[B1_PIC], (B1_TO_B2_BIT_RATIO), 0); |
| SET_VAR_Q( |
| avq_complexity_estimate[B11_PIC], |
| (B1_TO_B2_BIT_RATIO), |
| 0); //temporarliy treat ref and non ref as same |
| SET_VAR_Q(avq_complexity_estimate[B2_PIC], 1, 0); |
| SET_VAR_Q(avq_complexity_estimate[B22_PIC], 1, 0); |
| |
| /* Get the rem_frms_in_gop & the frms_in_gop from the pic_type state struct */ |
| /* pic_type_get_rem_frms_in_gop(ps_pic_handling, ai4_rem_frms_in_period); */ |
| pic_type_get_frms_in_gop(ps_pic_handling, ai4_frms_in_period); |
| |
| /* Depending on the number of gops in a period, find the num_frms_in_prd */ |
| for(j = 0; j < MAX_PIC_TYPE; j++) |
| { |
| ai4_frms_in_period[j] = (ai4_frms_in_period[j] * ps_bit_allocation->i4_num_gops_in_period); |
| } |
| |
| /* Percentage of header bits in teh overall bits allocated to I, P and B frames |
| when the data is not known. Since this value is based on bitrate using a equation |
| to fit the values. Ran the header bit ratio for [1080@30] carnival, ihits and |
| football at 9, 12 and 16 mbps and based on that deriving a equation using bpp. |
| Values obtained are: |
| (bitrate/bpp) I P B |
| 9/2.87 0.358617291155 0.549124350786 0.798772545232 |
| 12/3.83 0.288633642796 0.444797334749 0.693933711801 |
| 16/5.11 0.284241839623 0.330152764298 0.557999732549 |
| Equation for I: |
| if bpp > 3.83 hdr = 0.29 |
| else hdr = -0.073*bpp + 0.569 |
| Equation for P: hdr = -0.098*bpp + 0.825 |
| Equation for B: hdr = -0.108*bpp + 1.108 |
| */ |
| { |
| #define FRAME_HEADER_BITS_Q_FACTOR (10) |
| WORD32 ai4_header_bits_percentage[MAX_PIC_TYPE]; |
| |
| WORD32 i4_bpp; |
| X_PROD_Y_DIV_Z( |
| ps_bit_allocation->i4_bits_per_frm, |
| (1 << FRAME_HEADER_BITS_Q_FACTOR), |
| ps_bit_allocation->i4_pels_in_frame, |
| i4_bpp); |
| //ps_bit_allocation->i4_bits_per_frm*(1<<FRAME_HEADER_BITS_Q_FACTOR)/ps_bit_allocation->i4_pels_in_frame; |
| |
| if(i4_bpp > 131) |
| ai4_header_bits_percentage[I_PIC] = 297; |
| else |
| ai4_header_bits_percentage[I_PIC] = |
| ((-2238 * i4_bpp) >> FRAME_HEADER_BITS_Q_FACTOR) + 583; |
| ai4_header_bits_percentage[P_PIC] = ((-2990 * i4_bpp) >> FRAME_HEADER_BITS_Q_FACTOR) + 845; |
| |
| ai4_header_bits_percentage[B_PIC] = ((-3308 * i4_bpp) >> FRAME_HEADER_BITS_Q_FACTOR) + 1135; |
| |
| /* Changes for 2B subGOP */ |
| ai4_header_bits_percentage[P_PIC] = (ai4_header_bits_percentage[P_PIC] * 13) >> 4; |
| ai4_header_bits_percentage[P1_PIC] = (ai4_header_bits_percentage[P_PIC] * 13) >> 4; |
| ai4_header_bits_percentage[B_PIC] = (ai4_header_bits_percentage[B_PIC] * 12) >> 4; |
| ai4_header_bits_percentage[BB_PIC] = (ai4_header_bits_percentage[B_PIC] * 12) >> 4; |
| /*HEVC_hierarchy: temp change consider same percentage because of insufficient data*/ |
| ai4_header_bits_percentage[B1_PIC] = ai4_header_bits_percentage[B_PIC]; |
| ai4_header_bits_percentage[B11_PIC] = ai4_header_bits_percentage[B_PIC]; |
| ai4_header_bits_percentage[B2_PIC] = ai4_header_bits_percentage[B_PIC]; |
| ai4_header_bits_percentage[B22_PIC] = ai4_header_bits_percentage[B_PIC]; |
| |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| ps_bit_allocation->af_sum_weigh[i][0] = 1.0; |
| ps_bit_allocation->af_sum_weigh[i][1] = 0.0; |
| ps_bit_allocation->af_sum_weigh[i][2] = 0.0; |
| } |
| |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| /* Getting the total bits allocated for each picture type */ |
| WORD32 i4_num_bits_allocated = get_bits_based_on_complexity( |
| ps_bit_allocation, |
| i4_rem_bits_in_period, |
| ai4_frms_in_period, |
| avq_complexity_estimate, |
| (picture_type_e)i, |
| 0); |
| |
| if(ai4_header_bits_percentage[i] < 0) |
| ai4_header_bits_percentage[i] = 0; |
| |
| ps_bit_allocation->i4_prev_frm_header_bits[i] = (WORD32)( |
| ((LWORD64)ai4_header_bits_percentage[i] * i4_num_bits_allocated) >> |
| FRAME_HEADER_BITS_Q_FACTOR); |
| } |
| } |
| } |
| |
| /***************************************************************************** |
| Function Name : init_bit_allocation |
| Description : Initalises the bit_allocation structure. |
| Inputs : intra_frm_interval - num frames between two I frames |
| num_intra_frm_interval - num such intervals |
| i4_bit_rate - num bits per second |
| i4_frm_rate - num frms in 1000 seconds |
| i4_num_active_pic_type |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| #if NON_STEADSTATE_CODE |
| void init_bit_allocation( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handling, |
| WORD32 i4_num_intra_frm_interval, /* num such intervals */ |
| WORD32 i4_bit_rate, /* num bits per second */ |
| WORD32 i4_frm_rate, /* num frms in 1000 seconds */ |
| WORD32 *i4_peak_bit_rate, |
| WORD32 i4_min_bitrate, /* The minimum bit rate that is to be satisfied for a gop */ |
| WORD32 i4_pels_in_frame, |
| WORD32 i4_is_hbr, |
| WORD32 i4_num_active_pic_type, |
| WORD32 i4_lap_window, |
| WORD32 i4_field_pic, |
| WORD32 rc_pass, |
| WORD32 i4_luma_pels, |
| WORD32 i4_fp_bit_alloc_in_sp) |
| { |
| WORD32 i; |
| WORD32 i4_bits_per_frm, i4_max_bits_per_frm[MAX_NUM_DRAIN_RATES]; |
| /* Store the pels in frame value */ |
| ps_bit_allocation->i4_pels_in_frame = i4_pels_in_frame; |
| ps_bit_allocation->i4_num_scd_in_lap_window = 0; |
| ps_bit_allocation->i4_num_frm_b4_scd = 0; |
| ps_bit_allocation->i4_num_active_pic_type = i4_num_active_pic_type; |
| ps_bit_allocation->i4_field_pic = i4_field_pic; |
| ps_bit_allocation->i4_ba_rc_pass = rc_pass; |
| ps_bit_allocation->i4_br_id = 0; /* 0 - peak, 1 - average*/ |
| ps_bit_allocation->i8_cur_gop_num = |
| 0; /*Will be incremented after first frame allocation is done(during init itslef)*/ |
| ps_bit_allocation->i8_frm_num_in_gop = 0; |
| ps_bit_allocation->pv_gop_stat = |
| NULL; /*In 2 pass the gop stat pointer is set API parameter call*/ |
| ps_bit_allocation->f_min_complexity_cross_peak_rate = |
| 1.0; /*In single pass buffer based additional bits movement is disabled, hence set to max complexity |
| Reset to lower value in case of two pass*/ |
| |
| ps_bit_allocation->f_cur_peak_factor_2pass = -1.0; |
| ps_bit_allocation->i8_total_bits_allocated = -1; |
| ps_bit_allocation->i4_luma_pels = i4_luma_pels; |
| ps_bit_allocation->i4_num_gop = -1; |
| ps_bit_allocation->f_sum_complexity_segment_cross_peak = 0.0f; |
| //ps_bit_allocation->i8_vbv_based_excess_for_segment = 0; |
| ps_bit_allocation->i4_flag_no_more_set_rbip = 0; |
| ps_bit_allocation->f_curr_i_to_sum = 1.0f; |
| ps_bit_allocation->i4_fp_bit_alloc_in_sp = i4_fp_bit_alloc_in_sp; |
| |
| /* Calculate the bits per frame */ |
| X_PROD_Y_DIV_Z(i4_bit_rate, 1000, i4_frm_rate, i4_bits_per_frm); |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| { |
| X_PROD_Y_DIV_Z(i4_peak_bit_rate[i], 1000, i4_frm_rate, i4_max_bits_per_frm[i]); |
| } |
| /* Initialize the bits_per_frame */ |
| ps_bit_allocation->i4_bits_per_frm = i4_bits_per_frm; |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| { |
| ps_bit_allocation->i4_max_bits_per_frm[i] = i4_max_bits_per_frm[i]; |
| } |
| X_PROD_Y_DIV_Z(i4_min_bitrate, 1000, i4_frm_rate, ps_bit_allocation->i4_min_bits_per_frm); |
| |
| /* Initialise the rem_bits in period |
| The first gop in case of an OPEN GOP may have fewer B_PICs, |
| That condition is not taken care of */ |
| init_rbip( |
| &ps_bit_allocation->s_rbip, ps_pic_handling, i4_bits_per_frm, i4_num_intra_frm_interval); |
| |
| /* Initialize the num_gops_in_period */ |
| ps_bit_allocation->i4_num_gops_in_period = i4_num_intra_frm_interval; |
| ps_bit_allocation->i4_actual_num_gops_in_period = i4_num_intra_frm_interval; |
| |
| /* Relative complexity between I and P frames */ |
| ps_bit_allocation->i2_K[I_PIC] = (1 << K_Q); |
| ps_bit_allocation->i2_K[P_PIC] = I_TO_P_RATIO; |
| ps_bit_allocation->i2_K[P1_PIC] = I_TO_P_RATIO; |
| ps_bit_allocation->i2_K[B_PIC] = (P_TO_B_RATIO * I_TO_P_RATIO) >> K_Q; |
| ps_bit_allocation->i2_K[BB_PIC] = (P_TO_B_RATIO * I_TO_P_RATIO) >> K_Q; |
| |
| /*HEVC_hierarchy: force qp offset with one high level of hierarchy*/ |
| ps_bit_allocation->i2_K[B1_PIC] = (B_TO_B1_RATIO * P_TO_B_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q); |
| ps_bit_allocation->i2_K[B11_PIC] = (B_TO_B1_RATIO * P_TO_B_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q); |
| ps_bit_allocation->i2_K[B2_PIC] = |
| (B1_TO_B2_RATIO * B_TO_B1_RATIO * P_TO_B_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q + K_Q); |
| ps_bit_allocation->i2_K[B22_PIC] = |
| (B1_TO_B2_RATIO * B_TO_B1_RATIO * P_TO_B_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q + K_Q); |
| |
| /* Initialize the saved bits to 0*/ |
| ps_bit_allocation->i4_saved_bits = 0; |
| |
| /* Update the error bits module with average bits */ |
| init_error_bits(ps_bit_allocation->ps_error_bits, i4_frm_rate, i4_bit_rate); |
| /* Store the input for implementing change in values */ |
| ps_bit_allocation->i4_frame_rate = i4_frm_rate; |
| ps_bit_allocation->i4_bit_rate = i4_bit_rate; |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| ps_bit_allocation->ai4_peak_bit_rate[i] = i4_peak_bit_rate[i]; |
| |
| ps_bit_allocation->i4_is_hbr = i4_is_hbr; |
| /* Initilising the header bits to be used for each picture type */ |
| init_prev_header_bits(ps_bit_allocation, ps_pic_handling); |
| |
| /*HEVC_RC*/ |
| /*remember prev frames tot bit consumption. This is required to calcualte error after first sub gop where estimate is not known*/ |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| ps_bit_allocation->ai4_prev_frm_tot_bits[i] = |
| -1; //-1 indicates that pic type has not been encoded |
| ps_bit_allocation->ai4_prev_frm_tot_est_bits[i] = -1; |
| } |
| |
| /* #define STATIC_I_TO_P_RATIO ((STATIC_I_TO_B_RATIO)/(STATIC_P_TO_B_RATIO)) */ |
| /* Calcualte the max i frame bits */ |
| { |
| WORD32 ai4_frms_in_period[MAX_PIC_TYPE]; |
| WORD32 ai4_actual_frms_in_period[MAX_PIC_TYPE], i4_actual_frms_in_period = 0; |
| WORD32 i4_rem_texture_bits, j, i4_tot_header_bits_est = 0; |
| number_t avq_complexity_estimate[MAX_PIC_TYPE]; |
| WORD32 i4_total_frms; |
| |
| /* Get the rem_frms_in_gop & the frms_in_gop from the pic_type state struct */ |
| pic_type_get_frms_in_gop(ps_pic_handling, ai4_frms_in_period); |
| pic_type_get_actual_frms_in_gop(ps_pic_handling, ai4_actual_frms_in_period); |
| /* Depending on the number of gops in a period, find the num_frms_in_prd */ |
| i4_total_frms = 0; |
| for(j = 0; j < MAX_PIC_TYPE; j++) |
| { |
| ai4_frms_in_period[j] *= ps_bit_allocation->i4_num_gops_in_period; |
| ai4_actual_frms_in_period[j] *= ps_bit_allocation->i4_num_gops_in_period; |
| i4_total_frms += ai4_frms_in_period[j]; |
| i4_actual_frms_in_period += ai4_actual_frms_in_period[j]; |
| } |
| ps_bit_allocation->i4_rem_frame_in_period = i4_actual_frms_in_period; /*i_only*/ |
| |
| for(j = 0; j < MAX_PIC_TYPE; j++) |
| { |
| i4_tot_header_bits_est += |
| ai4_frms_in_period[j] * ps_bit_allocation->i4_prev_frm_header_bits[j]; |
| } |
| /* Remove the header bits from the remaining bits to find how many bits you |
| can transfer.*/ |
| i4_rem_texture_bits = |
| ps_bit_allocation->i4_bits_per_frm * i4_actual_frms_in_period - i4_tot_header_bits_est; |
| |
| /* Set the complexities for static content */ |
| SET_VAR_Q(avq_complexity_estimate[I_PIC], STATIC_I_TO_B2_RATIO, 0); |
| SET_VAR_Q(avq_complexity_estimate[P_PIC], STATIC_P_TO_B2_RATIO, 0); |
| SET_VAR_Q(avq_complexity_estimate[P1_PIC], STATIC_P_TO_B2_RATIO, 0); |
| SET_VAR_Q(avq_complexity_estimate[B_PIC], STATIC_B_TO_B2_RATIO, 0); |
| SET_VAR_Q(avq_complexity_estimate[BB_PIC], STATIC_B_TO_B2_RATIO, 0); |
| SET_VAR_Q(avq_complexity_estimate[B1_PIC], STATIC_B1_TO_B2_RATIO, 0); |
| SET_VAR_Q(avq_complexity_estimate[B11_PIC], STATIC_B1_TO_B2_RATIO, 0); |
| SET_VAR_Q(avq_complexity_estimate[B2_PIC], 1, 0); |
| SET_VAR_Q(avq_complexity_estimate[B22_PIC], 1, 0); |
| /* Get the texture bits required for the current frame */ |
| ps_bit_allocation->i4_max_tex_bits_for_i = get_bits_based_on_complexity( |
| ps_bit_allocation, |
| i4_rem_texture_bits, |
| ai4_frms_in_period, |
| avq_complexity_estimate, |
| I_PIC, |
| 0); |
| } |
| /* initialise the GOP and bit errors to zero */ |
| ps_bit_allocation->i4_gop_level_bit_error = 0; |
| ps_bit_allocation->i4_frame_level_bit_error = 0; |
| for(i = 0; i < MAX_NUM_FRAME_PARALLEL; i++) |
| { |
| ps_bit_allocation->ai4_cur_frm_est_tex_bits[i] = 0; |
| ps_bit_allocation->ai4_cur_frm_est_hdr_bits[i] = 0; |
| } |
| ps_bit_allocation->i4_buffer_based_bit_error = 0; |
| ps_bit_allocation->i4_bits_from_buffer_in_cur_gop = 0; |
| ps_bit_allocation->i4_excess_bits_from_buffer = 0; |
| ps_bit_allocation->i4_lap_window = i4_lap_window; |
| ps_bit_allocation->i8_cur_gop_bit_consumption = 0; |
| //ps_bit_allocation->i8_2pass_gop_error_accum = 0; |
| ps_bit_allocation->f_qscale_max_clip_in_second_pass = (float)0x7FFFFFFF; |
| |
| /*Buffer play for single pass*/ |
| if(rc_pass != 2) |
| { |
| /*Find ps_bit_allocation->f_min_complexity_cross_peak_rate*/ |
| /*Find the complexity which maps to peak bit-rate*/ |
| { |
| ps_bit_allocation->f_min_complexity_cross_peak_rate = ba_get_min_complexity_for_peak_br( |
| i4_peak_bit_rate[0], i4_bit_rate, 10.0f, 1.0f, 0.0f, rc_pass); |
| } |
| } |
| |
| ps_bit_allocation->i4_total_2pass_frames = 0; |
| ps_bit_allocation->i8_2pass_avg_bit_rate = -1; |
| } |
| |
| /***************************************************************************** |
| Function Name : ba_init_stat_data |
| Description : The parsing of stat file is done at the end of init (by that time |
| bit allocation init would have already happened,The memory for gop |
| stat data is alocated inside the parse stat file code. Hence the |
| pointer has to be updated again. |
| Inputs : ps_bit_allocation |
| ps_pic_handling |
| pv_gop_stat - pointer to update |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_init_stat_data( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handling, |
| void *pv_gop_stat, |
| WORD32 *pi4_pic_dist_in_cur_gop, |
| WORD32 i4_total_bits_in_period, |
| WORD32 i4_excess_bits) |
| |
| { |
| WORD32 i4_tot_frames_in_gop = 0, i; |
| |
| ps_bit_allocation->pv_gop_stat = pv_gop_stat; |
| |
| /*Init RBIP*/ |
| /*Get the complexity*/ |
| ASSERT(ps_bit_allocation->i8_cur_gop_num == 0); |
| ASSERT(ps_bit_allocation->i8_frm_num_in_gop == 0); |
| |
| /*INit frames of each type*/ |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| i4_tot_frames_in_gop += pi4_pic_dist_in_cur_gop[i]; |
| } |
| |
| /*ASSERT(i4_tot_frames_in_gop == i4_intra_period);*/ |
| /*Also allocate data for first GOP*/ |
| /*Added for getting actual gop structure*/ |
| pic_type_update_frms_in_gop(ps_pic_handling, pi4_pic_dist_in_cur_gop); |
| |
| multi_pass_set_rbip( |
| &ps_bit_allocation->s_rbip, ps_pic_handling, i4_total_bits_in_period, i4_tot_frames_in_gop); |
| |
| ps_bit_allocation->i8_2pass_alloc_per_frm_bits = |
| (i4_total_bits_in_period + (i4_tot_frames_in_gop >> 1)) / i4_tot_frames_in_gop; |
| ps_bit_allocation->i8_bit_consumption_so_far = 0; |
| |
| ASSERT(ps_bit_allocation->i4_ba_rc_pass == 2); |
| } |
| #endif /* #if NON_STEADSTATE_CODE */ |
| |
| /***************************************************************************** |
| Function Name : bit_alloc_get_intra_bits |
| Description : |
| Inputs : ps_bit_allocation |
| ps_pic_handling |
| pvq_complexity_estimate |
| I_to_avg_rest |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 bit_alloc_get_intra_bits( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handling, |
| cbr_buffer_handle ps_cbr_buf_handling, |
| picture_type_e e_pic_type, |
| number_t *pvq_complexity_estimate, |
| WORD32 i4_is_scd, |
| float I_to_avg_rest, |
| WORD32 i4_call_type, |
| WORD32 i4_non_I_scd, |
| float f_percent_head_bits) |
| { |
| WORD32 ai4_frms_in_period[MAX_PIC_TYPE], ai4_frm_in_gop[MAX_PIC_TYPE], tot_frms_in_period = 0; |
| WORD32 i4_field_pic, |
| i4_safe_margin = 0, |
| i4_lap_window; //margin in buffer to handle I frames that can come immediately after encoding huge static I frame |
| /*obtain buffer size*/ |
| WORD32 i4_buffer_size = |
| ((get_cbr_buffer_size(ps_cbr_buf_handling)) >> 4) * UPPER_THRESHOLD_EBF_Q4; |
| WORD32 i4_cur_buf_pos = get_cbr_ebf(ps_cbr_buf_handling), i4_max_buffer_based, |
| i4_max_buffer_based_I_pic, i, i4_num_scaled_frms = 1; |
| WORD32 i4_bit_alloc_window = |
| (ps_bit_allocation->s_rbip.i4_tot_frms_in_gop * |
| ps_bit_allocation->s_rbip.i4_num_intra_frm_interval); |
| WORD32 i4_num_buf_frms, |
| ai4_frms_in_baw[MAX_PIC_TYPE]; //window for which I frame bit allocation is done |
| WORD32 i4_bits_in_period, i4_frames_in_buf = 0, i4_default_bits_in_period = 0; |
| WORD32 i4_est_bits_for_I, i4_peak_drain_rate, i4_subgop_size; |
| rc_type_e rc_type = get_rc_type(ps_cbr_buf_handling); |
| pic_type_get_actual_frms_in_gop(ps_pic_handling, ai4_frm_in_gop); |
| |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| ai4_frms_in_baw[i] = |
| ai4_frm_in_gop[i] * ps_bit_allocation->s_rbip.i4_num_intra_frm_interval; |
| ai4_frms_in_period[i] = |
| ai4_frm_in_gop[i] * ps_bit_allocation->s_rbip.i4_num_intra_frm_interval; |
| tot_frms_in_period += ai4_frm_in_gop[i]; |
| } |
| |
| if(i4_call_type == 1) |
| { |
| i4_default_bits_in_period = update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0); |
| if((i4_default_bits_in_period + ps_bit_allocation->i4_frame_level_bit_error) < |
| (i4_default_bits_in_period * 0.30)) |
| { |
| ps_bit_allocation->i4_frame_level_bit_error = 0; //-(i4_default_bits_in_period * 0.70); |
| } |
| i4_bits_in_period = i4_default_bits_in_period + ps_bit_allocation->i4_frame_level_bit_error; |
| if(i4_non_I_scd == 0) |
| { |
| /*For the first gop unnecessarily the QP is going high in order to prevent this bits corresponding to full gop instead of gop-subgop*/ |
| |
| WORD32 i4_intra_int = pic_type_get_intra_frame_interval(ps_pic_handling); |
| WORD32 i4_inter_int = pic_type_get_inter_frame_interval(ps_pic_handling); |
| if((tot_frms_in_period == |
| (i4_intra_int - i4_inter_int + (1 << ps_bit_allocation->i4_field_pic))) && |
| (i4_intra_int != 1)) |
| { |
| i4_bits_in_period = |
| (WORD32)(i4_bits_in_period * ((float)i4_intra_int / tot_frms_in_period)); |
| } |
| } |
| trace_printf("\nBits in period %d", i4_bits_in_period); |
| } |
| else |
| { |
| i4_bits_in_period = ret_rbip_default_preenc(&ps_bit_allocation->s_rbip, ps_pic_handling); |
| |
| if(ps_bit_allocation->i4_ba_rc_pass == 2) |
| i4_default_bits_in_period = update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0); |
| } |
| |
| i4_peak_drain_rate = get_buf_max_drain_rate(ps_cbr_buf_handling); |
| i4_num_buf_frms = |
| (get_cbr_buffer_size(ps_cbr_buf_handling) + (ps_bit_allocation->i4_bits_per_frm >> 1)) / |
| ps_bit_allocation->i4_bits_per_frm; |
| /*In VBR encoder buffer will be drained faster, i4_num_buf_frms should correspond to maximum number of bits that can be drained |
| In CBR both peak and average must be same*/ |
| i4_num_buf_frms = i4_num_buf_frms * i4_peak_drain_rate / ps_bit_allocation->i4_bits_per_frm; |
| |
| i4_field_pic = pic_type_get_field_pic(ps_pic_handling); |
| |
| i4_subgop_size = pic_type_get_inter_frame_interval(ps_pic_handling); |
| if(pvq_complexity_estimate == NULL) |
| i4_cur_buf_pos = 0; |
| |
| i4_lap_window = ps_bit_allocation->i4_lap_window; |
| |
| /*assume minimum lap visibilty.A static I frame is given only the bits of duration for which we have visibility*/ |
| if(ps_bit_allocation->i4_lap_window < MINIMUM_VISIBILITY_B4_STATIC_I) |
| { |
| i4_lap_window = MINIMUM_VISIBILITY_B4_STATIC_I; |
| } |
| else |
| { |
| i4_lap_window = ps_bit_allocation->i4_lap_window; |
| /*clip buffer window to max of lap window or buffer window*/ |
| if((i4_lap_window < i4_num_buf_frms) && (i4_call_type == 1)) |
| i4_num_buf_frms = i4_lap_window + i4_subgop_size; |
| } |
| |
| if(i4_lap_window < MINIMUM_FRM_I_TO_REST_LAP_ENABLED) |
| i4_lap_window = MINIMUM_FRM_I_TO_REST_LAP_ENABLED; |
| if(ps_bit_allocation->i4_ba_rc_pass != 2) |
| { |
| if(i4_lap_window < i4_num_buf_frms) |
| i4_num_buf_frms = i4_lap_window; |
| } |
| |
| if(i4_num_buf_frms > tot_frms_in_period) |
| { |
| i4_num_buf_frms = tot_frms_in_period; |
| i4_bit_alloc_window = i4_num_buf_frms; |
| } |
| /*get picture type dist based on bit alloc window*/ |
| if(i4_num_buf_frms < tot_frms_in_period) |
| { |
| for(i = 1; i < ps_bit_allocation->i4_num_active_pic_type; i++) |
| { |
| ai4_frms_in_baw[i] = |
| (ai4_frms_in_period[i] * i4_num_buf_frms + (tot_frms_in_period >> 1)) / |
| tot_frms_in_period; |
| i4_num_scaled_frms += ai4_frms_in_baw[i]; |
| if(ps_bit_allocation->i4_field_pic) |
| { |
| ai4_frms_in_baw[i + FIELD_OFFSET] = ai4_frms_in_baw[i]; |
| i4_num_scaled_frms += ai4_frms_in_baw[i]; |
| } |
| } |
| if(ps_bit_allocation->i4_field_pic) |
| { |
| ai4_frms_in_baw[5]++; |
| i4_num_scaled_frms++; |
| } |
| //if prorating is not exact account for diff with highest layer pic types |
| if(!ps_bit_allocation->i4_field_pic) |
| { |
| ai4_frms_in_baw[ps_bit_allocation->i4_num_active_pic_type - 1] += |
| (i4_num_buf_frms - i4_num_scaled_frms); |
| } |
| else |
| { |
| ai4_frms_in_baw[ps_bit_allocation->i4_num_active_pic_type - 1] += |
| ((i4_num_buf_frms - i4_num_scaled_frms) >> 1); |
| ai4_frms_in_baw[ps_bit_allocation->i4_num_active_pic_type - 1 + FIELD_OFFSET] += |
| ((i4_num_buf_frms - i4_num_scaled_frms) >> 1); |
| } |
| i4_bits_in_period = |
| ((LWORD64)i4_bits_in_period * i4_num_buf_frms + (tot_frms_in_period >> 1)) / |
| tot_frms_in_period; |
| i4_bit_alloc_window = i4_num_buf_frms; |
| } |
| |
| i4_safe_margin = (WORD32)(i4_buffer_size * 0.1); |
| i4_max_buffer_based = ((LWORD64)i4_buffer_size - i4_cur_buf_pos) / |
| ps_bit_allocation->i4_bits_per_frm * i4_peak_drain_rate; |
| i4_max_buffer_based_I_pic = i4_buffer_size - i4_cur_buf_pos; |
| |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| i4_frames_in_buf += ai4_frms_in_baw[i]; |
| } |
| |
| if((rc_type == VBR_STREAMING) && (i4_call_type == 1)) |
| { |
| WORD32 i4_delay_frames = cbr_get_delay_frames(ps_cbr_buf_handling); |
| i4_max_buffer_based = |
| (i4_peak_drain_rate * |
| (ps_bit_allocation->s_rbip.i4_tot_frms_in_gop + (WORD32)(i4_delay_frames * 0.8f)) - |
| i4_cur_buf_pos); |
| |
| /*RBIP is updated once it is restricted for an Intra period */ |
| if(i4_default_bits_in_period > i4_max_buffer_based) |
| update_rbip( |
| &ps_bit_allocation->s_rbip, |
| ps_pic_handling, |
| i4_max_buffer_based - i4_default_bits_in_period); |
| |
| i4_max_buffer_based = |
| (i4_peak_drain_rate * (i4_frames_in_buf + (WORD32)(i4_delay_frames * 0.8f)) - |
| i4_cur_buf_pos); |
| } |
| else |
| { |
| i4_max_buffer_based = |
| ((((LWORD64)i4_buffer_size - i4_cur_buf_pos) / ps_bit_allocation->i4_bits_per_frm) + |
| i4_frames_in_buf) * |
| i4_peak_drain_rate; |
| } |
| |
| /*the estimated bits for total period is clipped to buffer limits*/ |
| if(i4_bits_in_period > i4_max_buffer_based) |
| i4_bits_in_period = i4_max_buffer_based; |
| |
| /*get I pic bits with altered bits in period*/ |
| if((!i4_is_scd) && |
| (ps_bit_allocation->i4_num_frames_since_last_I_frame < |
| (ps_bit_allocation->i4_frame_rate * 2) / 1000) && |
| (ps_bit_allocation->i4_ba_rc_pass != 2)) |
| { |
| /*returns texture bits*/ |
| LWORD64 i8_header_bits_in_previous_period = 0, i8_total_bits_in_previous_period = 0, |
| i4_frames_in_header = 0; |
| WORD32 i4_texture_bits = 0; |
| float f_percent_header_bits = 0.0f; |
| /* Remove the header bits from the remaining bits to find how many bits you |
| can transfer.*/ |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| i8_header_bits_in_previous_period += |
| (ps_bit_allocation->i4_prev_frm_header_bits[i] * ai4_frms_in_baw[i]); |
| i8_total_bits_in_previous_period += |
| (ps_bit_allocation->ai4_prev_frm_tot_bits[i] * ai4_frms_in_baw[i]); |
| i4_frames_in_header += ai4_frms_in_baw[i]; |
| } |
| |
| if((i4_call_type == 1) && (ps_bit_allocation->i4_ba_rc_pass == 2)) |
| { |
| i4_texture_bits = (WORD32)(i4_bits_in_period * (1 - f_percent_head_bits)); |
| } |
| else |
| { |
| f_percent_header_bits = |
| (float)i8_header_bits_in_previous_period / i8_total_bits_in_previous_period; |
| i4_texture_bits = |
| i4_bits_in_period - (WORD32)(f_percent_header_bits * i4_bits_in_period); |
| } |
| |
| if(i4_call_type == 1) |
| { |
| trace_printf( |
| "\nHeader Bits in period %d, total_frames %d " |
| "i4_max_buffer_based %d ", |
| (WORD32)f_percent_header_bits * i4_bits_in_period, |
| i4_frames_in_header, |
| i4_max_buffer_based); |
| } |
| i4_est_bits_for_I = get_bits_based_on_complexity( |
| ps_bit_allocation, |
| i4_texture_bits, |
| ai4_frms_in_baw, |
| pvq_complexity_estimate, |
| e_pic_type, |
| i4_call_type); |
| /*twice the bitrate */ |
| if(i4_est_bits_for_I > ((ps_bit_allocation->i4_bit_rate << 1) - |
| ps_bit_allocation->i4_prev_frm_header_bits[I_PIC])) |
| i4_est_bits_for_I = |
| ((ps_bit_allocation->i4_bit_rate << 1) - |
| ps_bit_allocation->i4_prev_frm_header_bits[I_PIC]); |
| |
| if(i4_est_bits_for_I > |
| (i4_max_buffer_based_I_pic - ps_bit_allocation->i4_prev_frm_header_bits[I_PIC])) |
| { |
| i4_est_bits_for_I = |
| (i4_max_buffer_based_I_pic - ps_bit_allocation->i4_prev_frm_header_bits[I_PIC]); |
| } |
| } |
| else |
| { |
| /*returns total bits incase of scene cut*/ |
| ASSERT(ai4_frms_in_baw[I_PIC] != 0); |
| if((i4_non_I_scd == 1) && (i4_call_type == 1) && |
| (ps_bit_allocation->f_curr_i_to_sum != 1.0f)) |
| ai4_frms_in_baw[I_PIC]++; |
| |
| i4_est_bits_for_I = (WORD32)( |
| (i4_bits_in_period * I_to_avg_rest * ai4_frms_in_baw[I_PIC]) / |
| (ai4_frms_in_baw[I_PIC] * I_to_avg_rest + |
| (i4_bit_alloc_window - ai4_frms_in_baw[I_PIC]))); |
| |
| if(i4_call_type == 1) |
| i4_est_bits_for_I = |
| (WORD32)((float)i4_est_bits_for_I * ps_bit_allocation->f_curr_i_to_sum); |
| else |
| { |
| if(ai4_frms_in_baw[I_PIC] > 0) |
| i4_est_bits_for_I = (WORD32)((float)i4_est_bits_for_I / ai4_frms_in_baw[I_PIC]); |
| } |
| |
| if(i4_call_type == 1) |
| { |
| trace_printf( |
| "bits in period %d I_to_avg_rest %f f_curr_i_to_sum %f i " |
| "frames %d i4_non_I_scd %d ", |
| i4_bits_in_period, |
| I_to_avg_rest, |
| ps_bit_allocation->f_curr_i_to_sum, |
| ai4_frms_in_baw[I_PIC], |
| i4_non_I_scd); |
| } |
| |
| if(i4_est_bits_for_I > (ps_bit_allocation->i4_bit_rate << 1)) |
| i4_est_bits_for_I = (ps_bit_allocation->i4_bit_rate << 1); |
| if(i4_est_bits_for_I > i4_max_buffer_based_I_pic) |
| i4_est_bits_for_I = i4_max_buffer_based_I_pic; |
| } |
| |
| return i4_est_bits_for_I; |
| } |
| |
| /***************************************************************************** |
| Function Name : get_cur_frm_est_texture_bits |
| Description : Based on remaining bits in period and rd_model |
| the number of bits required for the current frame is estimated. |
| Inputs : ps_bit_allocation - bit_allocation structure |
| ps_rd_model - rd model pointer (for all the frame types) |
| e_pic_type - picture type |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 get_cur_frm_est_texture_bits( |
| bit_allocation_t *ps_bit_allocation, |
| rc_rd_model_handle *pps_rd_model, |
| est_sad_handle ps_est_sad, |
| pic_handling_handle ps_pic_handling, |
| cbr_buffer_handle ps_cbr_buffer, |
| picture_type_e e_pic_type, |
| WORD32 i4_use_model, |
| WORD32 i4_is_scd_frame, |
| WORD32 i4_call_type, |
| float i_to_avg_ratio, |
| WORD32 i4_is_model_valid) |
| { |
| WORD32 i, j; |
| WORD32 i4_est_texture_bits_for_frm; |
| WORD32 i4_rem_texture_bits; |
| number_t avq_complexity_estimate[MAX_PIC_TYPE]; |
| WORD32 ai4_frms_in_period[MAX_PIC_TYPE]; |
| WORD32 i4_max_consumable_bits, i4_est_tot_head_bits_period = 0, i4_total_bits_prev_gop = 0; |
| WORD32 i4_field_pic, i4_inter_frame_int; |
| WORD32 complexity_est = 0; |
| float f_percent_head_bits = 0.0f; |
| WORD32 i4_intra_frm_int; |
| i4_intra_frm_int = pic_type_get_actual_intra_frame_interval(ps_pic_handling); |
| i4_inter_frame_int = pic_type_get_inter_frame_interval(ps_pic_handling); |
| i4_field_pic = pic_type_get_field_pic(ps_pic_handling); |
| |
| /* If the complexity estimate is not filled based on |
| 1) Since not using model |
| 2) Using the module but one of the estimate values are zero |
| Then set the complexity estimate based on default values */ |
| // if(!complexity_est) |
| { |
| /* Hardcoding the bit ratios between I, P and B same as during init time*/ |
| SET_VAR_Q( |
| avq_complexity_estimate[I_PIC], |
| (I_TO_P_BIT_RATIO * P_TO_B_BIT_RATIO * B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), |
| 0); |
| SET_VAR_Q( |
| avq_complexity_estimate[P_PIC], |
| (P_TO_B_BIT_RATIO * B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), |
| 0); |
| SET_VAR_Q( |
| avq_complexity_estimate[P1_PIC], |
| (P_TO_B_BIT_RATIO * B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), |
| 0); |
| SET_VAR_Q(avq_complexity_estimate[B_PIC], (B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), 0); |
| SET_VAR_Q(avq_complexity_estimate[BB_PIC], (B_TO_B1_BIT_RATO0 * B1_TO_B2_BIT_RATIO), 0); |
| SET_VAR_Q( |
| avq_complexity_estimate[B1_PIC], |
| (B1_TO_B2_BIT_RATIO), |
| 0); //temporarliy treat ref and non ref as same |
| SET_VAR_Q(avq_complexity_estimate[B11_PIC], (B1_TO_B2_BIT_RATIO), 0); |
| SET_VAR_Q(avq_complexity_estimate[B2_PIC], 1, 0); |
| SET_VAR_Q(avq_complexity_estimate[B22_PIC], 1, 0); |
| } |
| /* Get the rem_frms_in_gop & the frms_in_gop from the pic_type state struct */ |
| /* pic_type_get_rem_frms_in_gop(ps_pic_handling, ai4_rem_frms_in_period); */ |
| pic_type_get_frms_in_gop(ps_pic_handling, ai4_frms_in_period); |
| |
| /* Depending on the number of gops in a period, find the num_frms_in_prd */ |
| for(j = 0; j < MAX_PIC_TYPE; j++) |
| { |
| /* ai4_rem_frms_in_period[j] += (ai4_frms_in_period[j] * (ps_bit_allocation->i4_num_gops_in_period - 1)); */ |
| ai4_frms_in_period[j] *= ps_bit_allocation->i4_num_gops_in_period; |
| } |
| |
| /* If a frame is detected as SCD and bit allocation is asked for the remaining part of the frame |
| we allocate bits assuming that frame as a I frame. So reduce 1 frame from the picture type coming in |
| and add that to I frame */ |
| if(i4_is_scd_frame && e_pic_type != I_PIC) |
| { |
| /* ai4_rem_frms_in_period[0]++;ai4_rem_frms_in_period[e_pic_type]--; */ |
| ai4_frms_in_period[0]++; |
| ai4_frms_in_period[e_pic_type]--; |
| } |
| /*HEVC_hierarchy: calculate header bits for all frames in period*/ |
| for(j = 0; j < MAX_PIC_TYPE; j++) |
| { |
| i4_est_tot_head_bits_period += |
| ai4_frms_in_period[j] * ps_bit_allocation->i4_prev_frm_header_bits[j]; |
| i4_total_bits_prev_gop += |
| ai4_frms_in_period[j] * ps_bit_allocation->ai4_prev_frm_tot_bits[j]; |
| } |
| |
| { |
| WORD32 ai4_actual_frms_in_gop[MAX_PIC_TYPE], i, i4_total_frames = 0; |
| pic_type_get_actual_frms_in_gop(ps_pic_handling, ai4_actual_frms_in_gop); |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| i4_total_frames += ai4_actual_frms_in_gop[i]; |
| } |
| i4_max_consumable_bits = ps_bit_allocation->i4_max_bits_per_frm[0] * i4_total_frames; |
| |
| /* Remove the header bits from the remaining bits to find how many bits you |
| can transfer.*/ |
| if(i4_call_type == 1) |
| { |
| if(ps_bit_allocation->i4_ba_rc_pass == 2) |
| { |
| WORD32 i4_tot_frm_remain = 0, i4_tot_head_bits_in_gop = 0, |
| i4_tot_bits_last_in_gop = 0, i4_use_default_flag = 0; |
| |
| WORD32 i4_rbip = update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0); |
| if((i4_rbip + ps_bit_allocation->i4_frame_level_bit_error) < (i4_rbip * 0.30)) |
| { |
| ps_bit_allocation->i4_frame_level_bit_error = 0; //-(i4_rbip * 0.70); |
| } |
| i4_rem_texture_bits = |
| i4_rbip + |
| ps_bit_allocation->i4_frame_level_bit_error /*- i4_est_tot_head_bits_period*/ |
| ; |
| |
| i4_est_tot_head_bits_period = 0; |
| for(j = 0; j < MAX_PIC_TYPE; j++) |
| { |
| if((WORD32)ps_bit_allocation->af_sum_weigh[j][1] > 0) |
| { |
| i4_tot_frm_remain += (WORD32)ps_bit_allocation->af_sum_weigh[j][1]; |
| i4_tot_head_bits_in_gop += (WORD32)( |
| ps_bit_allocation->i4_prev_frm_header_bits[j] * |
| ps_bit_allocation->af_sum_weigh[j][1]); |
| i4_tot_bits_last_in_gop += (WORD32)( |
| ps_bit_allocation->ai4_prev_frm_tot_bits[j] * |
| ps_bit_allocation->af_sum_weigh[j][1]); |
| if(ps_bit_allocation->ai4_prev_frm_tot_bits[j] == -1) |
| { |
| i4_use_default_flag = 1; |
| } |
| } |
| } |
| |
| if(i4_use_default_flag != 1) |
| { |
| f_percent_head_bits = (float)i4_tot_head_bits_in_gop / i4_tot_bits_last_in_gop; |
| |
| if(f_percent_head_bits > 0.7f) |
| f_percent_head_bits = 0.7f; |
| |
| /*Subtracting a percentage of header bits from the remaining bits in period*/ |
| i4_rem_texture_bits = (WORD32)(i4_rem_texture_bits * (1 - f_percent_head_bits)); |
| } |
| else |
| { |
| /*Assuming 30% of bits will go for header bits in a gop in preenc*/ |
| i4_rem_texture_bits -= (WORD32)((float)i4_rem_texture_bits * 0.3f); |
| } |
| |
| trace_printf( |
| "Remaining texture bits %d fbe %d fphb %f thbg %d tblg %d", |
| i4_rem_texture_bits, |
| ps_bit_allocation->i4_frame_level_bit_error, |
| f_percent_head_bits, |
| i4_tot_head_bits_in_gop, |
| i4_tot_bits_last_in_gop); |
| } |
| else |
| { |
| /* Remove the header bits from the remaining bits to find how many bits you |
| can transfer.*/ |
| WORD32 i4_rbip = update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0); |
| if((i4_rbip + ps_bit_allocation->i4_frame_level_bit_error) < (i4_rbip * 0.30)) |
| { |
| ps_bit_allocation->i4_frame_level_bit_error = 0; //-(i4_rbip * 0.70); |
| } |
| i4_rem_texture_bits = update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0) + |
| ps_bit_allocation->i4_frame_level_bit_error; |
| |
| i4_est_tot_head_bits_period = (WORD32)( |
| ((float)(i4_est_tot_head_bits_period) / (float)i4_total_bits_prev_gop) * |
| i4_rem_texture_bits); |
| |
| if(i4_is_model_valid) |
| { |
| i4_rem_texture_bits = i4_rem_texture_bits - i4_est_tot_head_bits_period; |
| } |
| else |
| { |
| /*inorder to estimate the buffer position for model invalid cases, to control |
| encoder buffer overflow*/ |
| i4_rem_texture_bits = ((i4_rem_texture_bits * 3) >> 1); |
| } |
| |
| trace_printf( |
| "Remaining texture bits %d fbe %d ethp %d", |
| i4_rem_texture_bits, |
| ps_bit_allocation->i4_frame_level_bit_error, |
| i4_est_tot_head_bits_period); |
| } |
| |
| { |
| WORD32 i4_drain_bits_per_frame = get_buf_max_drain_rate(ps_cbr_buffer), i4_ebf; |
| WORD32 i4_delay = cbr_get_delay_frames(ps_cbr_buffer), max_buffer_level = 0, |
| rc_type = get_rc_type(ps_cbr_buffer); |
| |
| if(rc_type == VBR_STREAMING) |
| max_buffer_level = i4_drain_bits_per_frame * i4_delay; |
| else |
| max_buffer_level = get_cbr_buffer_size(ps_cbr_buffer); |
| |
| i4_ebf = get_cbr_ebf(ps_cbr_buffer); |
| |
| if(i4_ebf > (WORD32)(0.8f * max_buffer_level)) |
| { |
| if(ps_bit_allocation->af_sum_weigh[e_pic_type][0] > 1.0f) |
| ps_bit_allocation->af_sum_weigh[e_pic_type][0] = 1.0f; |
| } |
| if(i4_ebf > (WORD32)(0.6f * max_buffer_level)) |
| { |
| if(ps_bit_allocation->af_sum_weigh[e_pic_type][0] > 1.5f) |
| ps_bit_allocation->af_sum_weigh[e_pic_type][0] = 1.5f; |
| } |
| } |
| } |
| else |
| { |
| i4_rem_texture_bits = |
| ret_rbip_default_preenc(&ps_bit_allocation->s_rbip, ps_pic_handling); |
| /*Assuming 30% of bits will go for header bits in a gop in preenc*/ |
| i4_rem_texture_bits -= (WORD32)(i4_rem_texture_bits * 0.3f); |
| } |
| } |
| |
| if(i4_use_model) |
| { |
| /* The bits are then allocated based on the relative complexity of the |
| current frame with respect to that of the rest of the frames in period */ |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| number_t vq_lin_mod_coeff, vq_est_sad, vq_K; |
| |
| if(ai4_frms_in_period[i] > 0) /*Added for field case */ |
| { |
| /* Getting the linear model coefficient */ |
| vq_lin_mod_coeff = get_linear_coefficient(pps_rd_model[i]); |
| /* Getting the estimated SAD */ |
| SET_VAR_Q(vq_est_sad, get_est_sad(ps_est_sad, (picture_type_e)i), 0); |
| /* Making K factor a var Q format */ |
| SET_VAR_Q(vq_K, ps_bit_allocation->i2_K[i], K_Q); |
| /* Complexity_estimate = [ (lin_mod_coeff * estimated_sad) / K factor ] */ |
| mult32_var_q(vq_lin_mod_coeff, vq_est_sad, &vq_lin_mod_coeff); |
| div32_var_q(vq_lin_mod_coeff, vq_K, &avq_complexity_estimate[i]); |
| } |
| } |
| /*flag to check if complexity estimate is available*/ |
| complexity_est = 1; |
| |
| /*HEVC_hierarchy: If complexity estimate = 0 for any pic type then use default ratios*/ |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| if(ai4_frms_in_period[i] > 0) |
| { |
| complexity_est = complexity_est && avq_complexity_estimate[i].sm; |
| } |
| } |
| } |
| |
| /* Make the picture type of the SCD frame a I_PIC */ |
| if(i4_is_scd_frame && e_pic_type != I_PIC) |
| e_pic_type = I_PIC; |
| |
| if(e_pic_type == I_PIC) |
| { |
| /*clip min max values*/ |
| if(i_to_avg_ratio > I_TO_AVG_REST_GOP_BIT_MAX) |
| i_to_avg_ratio = I_TO_AVG_REST_GOP_BIT_MAX; |
| |
| if(i_to_avg_ratio < I_TO_AVG_REST_GOP_BIT_MIN) |
| i_to_avg_ratio = I_TO_AVG_REST_GOP_BIT_MIN; |
| |
| i4_est_texture_bits_for_frm = bit_alloc_get_intra_bits( |
| ps_bit_allocation, |
| ps_pic_handling, |
| ps_cbr_buffer, |
| e_pic_type, |
| avq_complexity_estimate, |
| 0, |
| i_to_avg_ratio, |
| i4_call_type, |
| 0, |
| f_percent_head_bits); |
| } |
| else |
| { |
| /* Get the texture bits required for the current frame */ |
| i4_est_texture_bits_for_frm = get_bits_based_on_complexity( |
| ps_bit_allocation, |
| i4_rem_texture_bits, |
| ai4_frms_in_period, |
| avq_complexity_estimate, |
| e_pic_type, |
| i4_call_type); |
| } |
| |
| ps_bit_allocation->i4_excess_bits_from_buffer = 0; |
| |
| /* If the remaining bits in the period becomes negative then the estimated texture |
| bits would also become negative. This would send a feedback to the model which |
| may go for a toss. Thus sending the minimum possible value = 0 */ |
| if(i4_est_texture_bits_for_frm < 0) |
| i4_est_texture_bits_for_frm = 0; |
| |
| return (i4_est_texture_bits_for_frm); |
| } |
| |
| /***************************************************************************** |
| Function Name : get_cur_frm_est_header_bits |
| Description : Based on remaining bits in period and rd_model |
| the number of bits required for the current frame is estimated. |
| Inputs : ps_bit_allocation - bit_allocation structure |
| ps_rd_model - rd model pointer (for all the frame types) |
| e_pic_type - picture type |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 get_cur_frm_est_header_bits(bit_allocation_t *ps_bit_allocation, picture_type_e e_pic_type) |
| { |
| //ASSERT(ps_bit_allocation->i4_prev_frm_header_bits[e_pic_type] == 0); |
| return (ps_bit_allocation->i4_prev_frm_header_bits[e_pic_type]); |
| } |
| /***************************************************************************** |
| Function Name : get_rem_bits_in_period |
| Description : Get remaining bits in period |
| Inputs : ps_bit_allocation - bit_allocation structure |
| ps_pic_handling |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 |
| get_rem_bits_in_period(bit_allocation_t *ps_bit_allocation, pic_handling_handle ps_pic_handling) |
| { |
| return (update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0)); |
| } |
| /***************************************************************************** |
| Function Name : get_bits_per_frame |
| Description : Get Bits per frame |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 get_bits_per_frame(bit_allocation_t *ps_bit_allocation) |
| { |
| return ((*ps_bit_allocation).i4_bits_per_frm); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_gop_bits |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| LWORD64 ba_get_gop_bits(bit_allocation_t *ps_bit_allocation) |
| { |
| gop_level_stat_t *ps_cur_gop_stat; |
| ps_cur_gop_stat = |
| (gop_level_stat_t *)ps_bit_allocation->pv_gop_stat + ps_bit_allocation->i8_cur_gop_num; |
| return ( |
| ps_cur_gop_stat->i8_bits_allocated_to_gop + |
| ps_cur_gop_stat->i8_buffer_play_bits_allocated_to_gop); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_gop_sad |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| LWORD64 ba_get_gop_sad(bit_allocation_t *ps_bit_allocation) |
| { |
| gop_level_stat_t *ps_cur_gop_stat; |
| ps_cur_gop_stat = |
| (gop_level_stat_t *)ps_bit_allocation->pv_gop_stat + ps_bit_allocation->i8_cur_gop_num; |
| return (ps_cur_gop_stat->i8_acc_gop_sad); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_buffer_play_bits_for_cur_gop |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| LWORD64 ba_get_buffer_play_bits_for_cur_gop(bit_allocation_t *ps_bit_allocation) |
| { |
| gop_level_stat_t *ps_cur_gop_stat; |
| ps_cur_gop_stat = |
| (gop_level_stat_t *)ps_bit_allocation->pv_gop_stat + ps_bit_allocation->i8_cur_gop_num; |
| return (ps_cur_gop_stat->i8_buffer_play_bits_allocated_to_gop); |
| } |
| |
| /***************************************************************************** |
| Function Name : update_cur_frm_consumed_bits |
| Description : Based on remaining bits in period and rd_model |
| the number of bits required for the current frame is estimated. |
| Inputs : ps_bit_allocation - bit_allocation structure |
| ps_rd_model - rd model pointer (for all the frame types) |
| e_pic_type - picture type |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void update_cur_frm_consumed_bits( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handling, |
| cbr_buffer_handle ps_cbr_buf_handle, |
| WORD32 i4_total_frame_bits, |
| WORD32 i4_model_updation_hdr_bits, |
| picture_type_e e_pic_type, |
| UWORD8 u1_is_scd, |
| WORD32 i4_last_frm_in_period, |
| WORD32 i4_lap_comp_bits_reset, |
| WORD32 i4_suppress_bpic_update, |
| WORD32 i4_buffer_based_bit_error, |
| WORD32 i4_stuff_bits, |
| WORD32 i4_lap_window_comp, |
| rc_type_e e_rc_type, |
| WORD32 i4_num_gop, |
| WORD32 i4_is_pause_to_resume, |
| WORD32 i4_est_text_bits_ctr_update_qp, |
| WORD32 *pi4_gop_correction, |
| WORD32 *pi4_new_correction) |
| { |
| WORD32 i4_error_bits = get_error_bits(ps_bit_allocation->ps_error_bits); |
| WORD32 i4_intra_frm_int, i, i4_flag_no_error_calc = 0; /*i_only*/ |
| WORD32 i4_do_correction = 0; |
| i4_intra_frm_int = pic_type_get_intra_frame_interval(ps_pic_handling); |
| ps_bit_allocation->i4_rem_frame_in_period--; |
| |
| /*No frame level bit error for top layer pictures*/ |
| |
| i4_flag_no_error_calc = /*((e_pic_type != B1_PIC && e_pic_type != B11_PIC) && ps_bit_allocation->i4_num_active_pic_type == 4)|| |
| ((e_pic_type != B2_PIC && e_pic_type != B22_PIC) && ps_bit_allocation->i4_num_active_pic_type == 5) &&*/ |
| (i4_is_pause_to_resume == 0); |
| |
| /* Update the remaining bits in period */ |
| ps_bit_allocation->i4_bits_from_buffer_in_cur_gop += |
| ps_bit_allocation->i4_excess_bits_from_buffer; |
| ps_bit_allocation->i4_buffer_based_bit_error -= ps_bit_allocation->i4_excess_bits_from_buffer; |
| ps_bit_allocation->i4_gop_level_bit_error += |
| (-(i4_total_frame_bits + i4_stuff_bits) + i4_error_bits + |
| ps_bit_allocation->i4_bits_per_frm); |
| ps_bit_allocation->i8_cur_gop_bit_consumption += (i4_total_frame_bits + i4_stuff_bits); |
| |
| //if(ps_bit_allocation-> == 2)ASSERT(i4_stuff_bits == 0);//No stuffing in two pass |
| //ASSERT(ps_bit_allocation->i4_prev_frm_header_bits[e_pic_type] == 0); |
| ps_bit_allocation->i4_buffer_based_bit_error += i4_buffer_based_bit_error; |
| ps_bit_allocation->i8_frm_num_in_gop++; |
| if(i4_last_frm_in_period && i4_lap_comp_bits_reset) |
| i4_lap_comp_bits_reset = 0; //end of period is always I frame boundary. |
| |
| if(e_pic_type == I_PIC) |
| ps_bit_allocation->i4_num_frames_since_last_I_frame = 1; |
| else |
| ps_bit_allocation->i4_num_frames_since_last_I_frame++; |
| |
| if((!i4_suppress_bpic_update)) |
| { |
| //if(ps_bit_allocation->ai4_cur_frm_est_tex_bits[i4_est_text_bits_ctr_update_qp] > 0) |
| { |
| ps_bit_allocation->ai4_prev_frm_tot_est_bits[e_pic_type] = |
| ps_bit_allocation->ai4_cur_frm_est_hdr_bits[i4_est_text_bits_ctr_update_qp] + |
| ps_bit_allocation->ai4_cur_frm_est_tex_bits[i4_est_text_bits_ctr_update_qp]; |
| |
| ps_bit_allocation->i4_frame_level_bit_error += |
| (ps_bit_allocation->ai4_cur_frm_est_hdr_bits[i4_est_text_bits_ctr_update_qp] + |
| ps_bit_allocation->ai4_cur_frm_est_tex_bits[i4_est_text_bits_ctr_update_qp] - |
| i4_total_frame_bits); |
| } |
| |
| trace_printf( |
| "Prev frame header %d Total est %d total frame %d", |
| ps_bit_allocation->i4_prev_frm_header_bits[e_pic_type], |
| ps_bit_allocation->ai4_cur_frm_est_tex_bits[i4_est_text_bits_ctr_update_qp], |
| i4_total_frame_bits); |
| } |
| |
| trace_printf( |
| " rbip = %d frame lbe = %d bbbe = %d bfbicg = %d\n", |
| update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0), |
| ps_bit_allocation->i4_frame_level_bit_error, |
| ps_bit_allocation->i4_buffer_based_bit_error, |
| ps_bit_allocation->i4_bits_from_buffer_in_cur_gop); |
| |
| /* Update the header bits so that it can be used as an estimate to the next frame */ |
| if(u1_is_scd) |
| { |
| /* Initilising the header bits to be used for each picture type */ |
| init_prev_header_bits(ps_bit_allocation, ps_pic_handling); |
| |
| /*init tot bits consumed of previous frame*/ |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| ps_bit_allocation->ai4_prev_frm_tot_bits[i] = -1; |
| ps_bit_allocation->ai4_prev_frm_tot_est_bits[i] = -1; |
| } |
| /* In case of SCD, eventhough the frame type is P, it is equivalent to a I frame |
| and so the coresponding header bits is updated */ |
| //ASSERT(i4_model_updation_hdr_bits == 0); |
| ps_bit_allocation->i4_prev_frm_header_bits[I_PIC] = i4_model_updation_hdr_bits; |
| ps_bit_allocation->ai4_prev_frm_tot_bits[I_PIC] = i4_total_frame_bits; |
| ps_bit_allocation->ai4_prev_frm_tot_est_bits[I_PIC] = i4_total_frame_bits; |
| /*SCD allowed only for I_PIC*/ |
| ASSERT(e_pic_type == I_PIC); |
| |
| #define MAX_NUM_GOPS_IN_PERIOD (5) |
| if(ps_bit_allocation->i4_num_gops_in_period != 1 && |
| ps_bit_allocation->i4_num_gops_in_period < MAX_NUM_GOPS_IN_PERIOD) |
| { |
| /* Whenever there is a scene change increase the number of gops by 2 so that |
| the number of bits allocated is not very constrained. */ |
| ps_bit_allocation->i4_num_gops_in_period += 2; |
| /* Add the extra bits in GOP to remaining bits in period */ |
| change_rbip( |
| &ps_bit_allocation->s_rbip, |
| ps_bit_allocation->i4_bits_per_frm, |
| ps_bit_allocation->i4_num_gops_in_period); |
| /* printf((const WORD8*)"SCD rbp %d, ngp %d\n", update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling,0), |
| ps_bit_allocation->i4_num_gops_in_period); */ |
| } |
| } |
| else |
| { |
| //ASSERT(i4_model_updation_hdr_bits == 0); |
| if(!i4_suppress_bpic_update) |
| { |
| ps_bit_allocation->i4_prev_frm_header_bits[e_pic_type] = i4_model_updation_hdr_bits; |
| ps_bit_allocation->ai4_prev_frm_tot_bits[e_pic_type] = i4_total_frame_bits; |
| } |
| } |
| |
| { |
| /* Removng the error due to buffer movement from gop level bit error */ |
| WORD32 i4_gop_correction = 0; |
| WORD32 i4_cur_ebf = get_cbr_ebf(ps_cbr_buf_handle); |
| WORD32 i4_vbv_size = get_cbr_buffer_size(ps_cbr_buf_handle); |
| WORD32 i4_min_vbv_size = (WORD32)(i4_vbv_size * MIN_THRESHOLD_VBV_GOP_ERROR); |
| WORD32 i4_max_vbv_size = (WORD32)(i4_vbv_size * MAX_THRESHOLD_VBV_GOP_ERROR); |
| /*get desired buffer level so that bit error can be calculated. desired buf = 1 - lap window complexity*/ |
| if(ps_bit_allocation->i4_ba_rc_pass != 2) |
| { |
| WORD32 i4_inter_frame_interval = pic_type_get_inter_frame_interval(ps_pic_handling); |
| LWORD64 vbv_buffer_based_excess = 0; |
| WORD32 i4_lap_window_comp_temp = i4_lap_window_comp; |
| if(ps_bit_allocation->i4_lap_window > i4_inter_frame_interval) |
| { |
| if(e_rc_type == VBR_STREAMING) |
| { |
| if(((float)i4_lap_window_comp / 128) > |
| ps_bit_allocation->f_min_complexity_cross_peak_rate) |
| i4_lap_window_comp_temp = |
| (WORD32)(ps_bit_allocation->f_min_complexity_cross_peak_rate * 128); |
| |
| /*Get excess bits if any from vbv buffer*/ |
| vbv_buffer_based_excess = get_vbv_buffer_based_excess( |
| ps_cbr_buf_handle, |
| ps_bit_allocation->f_min_complexity_cross_peak_rate, |
| ((float)i4_lap_window_comp / 128), |
| (i4_intra_frm_int * ps_bit_allocation->s_rbip.i4_num_intra_frm_interval), |
| 1); |
| } |
| |
| i4_do_correction = 1; |
| i4_gop_correction = get_error_bits_for_desired_buf( |
| ps_cbr_buf_handle, |
| i4_lap_window_comp_temp, |
| (i4_intra_frm_int * ps_bit_allocation->s_rbip.i4_num_intra_frm_interval)); |
| /*In case of VBR, don't do buffer based correction if gop_correction is less than 0, as it is less than average*/ |
| if((e_rc_type == VBR_STREAMING) && (i4_gop_correction <= 0)) |
| { |
| i4_do_correction = 0; |
| } |
| |
| /* vbv buffer position based error correction to keep away encoder buffer overflow at GOP (I to I, not user configured)*/ |
| if(i4_do_correction) |
| { |
| WORD32 i4_buffer_err_bits; |
| /*check if the ebf is greater than max ebf, |
| then account for complete error above max ebf in the current GOP itself*/ |
| if(i4_cur_ebf > i4_max_vbv_size) |
| { |
| i4_gop_correction -= (i4_cur_ebf - i4_max_vbv_size); |
| *pi4_new_correction -= (i4_cur_ebf - i4_max_vbv_size); |
| i4_cur_ebf = i4_max_vbv_size; |
| } |
| /* if ebf is above min but less than max, then distribute to the next GOPs*/ |
| if(i4_cur_ebf > i4_min_vbv_size) |
| { |
| WORD32 i4_num_gops; |
| float f_ebf_percent; |
| /*compute the error bits to be distributed over the next GOPs*/ |
| i4_buffer_err_bits = (i4_cur_ebf - i4_min_vbv_size); |
| /*compute number fo GOPs the error to be distributed |
| high error -> few GOPs, less error -> more GOPs*/ |
| f_ebf_percent = ((float)i4_cur_ebf / i4_vbv_size); |
| i4_num_gops = (WORD32)((1.0 - f_ebf_percent) * 10) + 2; |
| /*add the error bits to the period*/ |
| i4_gop_correction -= (WORD32)(i4_buffer_err_bits / i4_num_gops); |
| *pi4_new_correction -= (WORD32)(i4_buffer_err_bits / i4_num_gops); |
| } |
| } |
| *pi4_gop_correction = i4_gop_correction; |
| set_rbip( |
| &ps_bit_allocation->s_rbip, |
| (i4_gop_correction + (WORD32)vbv_buffer_based_excess)); |
| |
| update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0); |
| ASSERT(ps_bit_allocation->i4_bits_from_buffer_in_cur_gop == 0); |
| trace_printf("\nRBIP updated "); |
| } |
| /* initialise the GOP and bit errors to zero */ |
| ps_bit_allocation->i4_gop_level_bit_error = 0; |
| /*frame level error can't be carried over when it is more than VBV buffer size*/ |
| if(ps_bit_allocation->i4_frame_level_bit_error > i4_max_vbv_size) |
| { |
| ps_bit_allocation->i4_frame_level_bit_error = i4_max_vbv_size; |
| } |
| if((i4_last_frm_in_period) || |
| (i4_intra_frm_int == 1 && ps_bit_allocation->i4_rem_frame_in_period == 0)) |
| { /*For 1st pass set the errors to 0 at end of a gop*/ |
| ps_bit_allocation->i8_cur_gop_bit_consumption = 0; |
| ps_bit_allocation->i4_frame_level_bit_error = 0; |
| ps_bit_allocation->i4_bits_from_buffer_in_cur_gop = 0; |
| ps_bit_allocation->i4_rem_frame_in_period = |
| ps_bit_allocation->i4_num_gops_in_period * |
| i4_intra_frm_int; /*TBD: I only case*/ |
| ps_bit_allocation->i8_frm_num_in_gop = 0; |
| } |
| } |
| } |
| |
| if(i4_last_frm_in_period && i4_intra_frm_int != 1) |
| { |
| /* If the number of gops in period has been increased due to scene change, slowly bring in down |
| across the gops */ |
| if(ps_bit_allocation->i4_num_gops_in_period > |
| ps_bit_allocation->i4_actual_num_gops_in_period) |
| { |
| ps_bit_allocation->i4_num_gops_in_period--; |
| change_rbip( |
| &ps_bit_allocation->s_rbip, |
| ps_bit_allocation->i4_bits_per_frm, |
| ps_bit_allocation->i4_num_gops_in_period); |
| } |
| } |
| /*Check for complexity based bits reset in future with GOP*/ |
| |
| /* Update the lower modules */ |
| update_error_bits(ps_bit_allocation->ps_error_bits); |
| } |
| |
| /***************************************************************************** |
| Function Name : change_remaining_bits_in_period |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void change_remaining_bits_in_period( |
| bit_allocation_t *ps_bit_allocation, |
| WORD32 i4_bit_rate, |
| WORD32 i4_frame_rate, |
| WORD32 *i4_peak_bit_rate) |
| { |
| WORD32 i4_new_avg_bits_per_frm, i4_new_peak_bits_per_frm[MAX_NUM_DRAIN_RATES]; |
| int i; |
| |
| /* Calculate the new per frame bits */ |
| X_PROD_Y_DIV_Z(i4_bit_rate, 1000, i4_frame_rate, i4_new_avg_bits_per_frm); |
| |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| { |
| X_PROD_Y_DIV_Z(i4_peak_bit_rate[i], 1000, i4_frame_rate, i4_new_peak_bits_per_frm[i]); |
| } |
| |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| { |
| ps_bit_allocation->i4_max_bits_per_frm[i] = i4_new_peak_bits_per_frm[i]; |
| } |
| |
| /* Get the rem_frms_in_prd & the frms_in_prd from the pic_type state struct */ |
| /* pic_type_get_rem_frms_in_gop(ps_pic_handling, i4_rem_frms_in_period); */ |
| |
| /* If the difference > 0(/ <0), the remaining bits in period needs to be increased(/decreased) |
| based on the remaining number of frames */ |
| change_rbip( |
| &ps_bit_allocation->s_rbip, |
| i4_new_avg_bits_per_frm, |
| ps_bit_allocation->i4_num_gops_in_period); |
| |
| /* Update the new average bits per frame */ |
| ps_bit_allocation->i4_bits_per_frm = i4_new_avg_bits_per_frm; |
| |
| /*change max_bits_per_frame*/ |
| //ps_bit_allocation->i4_max_bits_per_frm[0]=i4_new_avg_bits_per_frm; |
| //ps_bit_allocation->i4_max_bits_per_frm[1]=i4_new_avg_bits_per_frm; |
| ps_bit_allocation->i4_min_bits_per_frm = |
| i4_new_avg_bits_per_frm; /*VBR storage related parameter so this variable is currently not in use*/ |
| /* change the lower modules state */ |
| /*#ifdef DYNAMIC_RC*/ |
| if(i4_bit_rate != ps_bit_allocation->i4_bit_rate) |
| { |
| X_PROD_Y_DIV_Z( |
| ps_bit_allocation->i4_max_tex_bits_for_i, |
| i4_bit_rate, |
| ps_bit_allocation->i4_bit_rate, |
| ps_bit_allocation->i4_max_tex_bits_for_i); |
| } |
| /*#endif*/ |
| |
| change_bitrate_in_error_bits(ps_bit_allocation->ps_error_bits, i4_bit_rate); |
| change_frm_rate_in_error_bits(ps_bit_allocation->ps_error_bits, i4_frame_rate); |
| |
| /* Store the modified frame_rate */ |
| ps_bit_allocation->i4_frame_rate = i4_frame_rate; |
| ps_bit_allocation->i4_bit_rate = i4_bit_rate; |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| ps_bit_allocation->ai4_peak_bit_rate[i] = i4_peak_bit_rate[i]; |
| } |
| /***************************************************************************** |
| Function Name : change_ba_peak_bit_rate |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| ai4_peak_bit_rate |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void change_ba_peak_bit_rate(bit_allocation_t *ps_bit_allocation, WORD32 *ai4_peak_bit_rate) |
| { |
| WORD32 i; |
| /* Calculate the bits per frame */ |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| { |
| X_PROD_Y_DIV_Z( |
| ai4_peak_bit_rate[i], |
| 1000, |
| ps_bit_allocation->i4_frame_rate, |
| ps_bit_allocation->i4_max_bits_per_frm[i]); |
| ps_bit_allocation->ai4_peak_bit_rate[i] = ai4_peak_bit_rate[i]; |
| } |
| } |
| /***************************************************************************** |
| Function Name : check_and_update_bit_allocation |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| ps_pic_handling |
| i4_max_bits_inflow_per_frm |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void check_and_update_bit_allocation( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handling, |
| WORD32 i4_max_bits_inflow_per_frm) |
| { |
| WORD32 i4_max_drain_bits, i4_extra_bits, i4_less_bits, i4_allocated_saved_bits, |
| i4_min_bits_for_period; |
| WORD32 i4_num_frms_in_period = get_actual_num_frames_in_gop(ps_pic_handling); |
| WORD32 i4_rem_bits_in_period = update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, 0); |
| |
| /* If the remaining bits is greater than what can be drained in that period |
| Clip the remaining bits in period to the maximum it can drain in that pariod |
| with the error of current buffer size.Accumulate the saved bits if any. |
| else if the remaining bits is lesser than the minimum bit rate promissed in that period |
| Add the excess bits to remaining bits in period and reduce it from the saved bits |
| Else |
| Provide the extra bits from the "saved bits pool".*/ |
| |
| i4_max_drain_bits = ps_bit_allocation->i4_num_gops_in_period * i4_num_frms_in_period * |
| i4_max_bits_inflow_per_frm; |
| |
| /* Practical DBF = middle of the buffer */ |
| /* NITT TO BE VERIFIED |
| MAx drain bits becomes negative if the buffer underflows |
| i4_max_drain_bits += (i4_cur_buf_size + i4_max_bits_inflow_per_frm - i4_tot_frame_bits); */ |
| |
| i4_min_bits_for_period = ps_bit_allocation->i4_num_gops_in_period * i4_num_frms_in_period * |
| ps_bit_allocation->i4_min_bits_per_frm; |
| |
| /* printf((const WORD8*)" mdb %d, mbfp %d, rbip %d, sb %d \n",i4_max_drain_bits, |
| i4_min_bits_for_period, ps_bit_allocation->i4_rem_bits_in_period, ps_bit_allocation->i4_saved_bits); */ |
| if(i4_rem_bits_in_period > i4_max_drain_bits) |
| { |
| i4_extra_bits = (i4_rem_bits_in_period - i4_max_drain_bits); |
| update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, -1 * i4_extra_bits); |
| overflow_avoided_summation(&ps_bit_allocation->i4_saved_bits, i4_extra_bits); |
| } |
| else if(i4_rem_bits_in_period < i4_min_bits_for_period) |
| { |
| i4_extra_bits = (i4_min_bits_for_period - i4_rem_bits_in_period); |
| update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, i4_extra_bits); |
| overflow_avoided_summation(&ps_bit_allocation->i4_saved_bits, -1 * i4_extra_bits); |
| } |
| else if(ps_bit_allocation->i4_saved_bits > 0) |
| { |
| i4_less_bits = i4_max_drain_bits - i4_rem_bits_in_period; |
| i4_allocated_saved_bits = MIN(i4_less_bits, ps_bit_allocation->i4_saved_bits); |
| update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handling, i4_allocated_saved_bits); |
| ps_bit_allocation->i4_saved_bits -= i4_allocated_saved_bits; |
| } |
| return; |
| } |
| /***************************************************************************** |
| Function Name : ba_get_frame_rate |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_frame_rate(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->i4_frame_rate); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_bit_rate |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_bit_rate(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->i4_bit_rate); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_2pass_avg_bit_rate |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| LWORD64 ba_get_2pass_avg_bit_rate(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->i8_2pass_avg_bit_rate); |
| } |
| /***************************************************************************** |
| Function Name : ba_set_2pass_avg_bit_rate |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_set_2pass_avg_bit_rate(bit_allocation_t *ps_bit_allocation, LWORD64 i8_2pass_avg_bit_rate) |
| { |
| ps_bit_allocation->i8_2pass_avg_bit_rate = i8_2pass_avg_bit_rate; |
| } |
| /***************************************************************************** |
| Function Name : ba_get_peak_bit_rate |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_get_peak_bit_rate(bit_allocation_t *ps_bit_allocation, WORD32 *pi4_peak_bit_rate) |
| { |
| WORD32 i; |
| for(i = 0; i < MAX_NUM_DRAIN_RATES; i++) |
| { |
| pi4_peak_bit_rate[i] = ps_bit_allocation->ai4_peak_bit_rate[i]; |
| } |
| } |
| /***************************************************************************** |
| Function Name : init_intra_header_bits |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void init_intra_header_bits(bit_allocation_t *ps_bit_allocation, WORD32 i4_intra_header_bits) |
| { |
| //ASSERT(i4_intra_header_bits == 0); |
| ps_bit_allocation->i4_prev_frm_header_bits[0] = i4_intra_header_bits; |
| } |
| /***************************************************************************** |
| Function Name : get_prev_header_bits |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 get_prev_header_bits(bit_allocation_t *ps_bit_allocation, WORD32 pic_type) |
| { |
| //ASSERT(ps_bit_allocation->i4_prev_frm_header_bits[pic_type] == 0); |
| return (ps_bit_allocation->i4_prev_frm_header_bits[pic_type]); |
| } |
| |
| #define I_TO_P_RATIO_HI_MO (16) |
| #define P_TO_B_RATIO_HI_MO (18) |
| #define P_TO_B_RATIO_HI_MO_HBR (16) |
| /***************************************************************************** |
| Function Name : set_Kp_Kb_for_hi_motion |
| Description : |
| Inputs : ps_bit_allocation - bit_allocation structure |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void set_Kp_Kb_for_hi_motion(bit_allocation_t *ps_bit_allocation) |
| { |
| ps_bit_allocation->i2_K[I_PIC] = (1 << K_Q); |
| ps_bit_allocation->i2_K[P_PIC] = I_TO_P_RATIO_HI_MO; |
| |
| if(ps_bit_allocation->i4_is_hbr) |
| { |
| ps_bit_allocation->i2_K[B_PIC] = (P_TO_B_RATIO_HI_MO * I_TO_P_RATIO_HI_MO) >> K_Q; |
| } |
| else |
| { |
| ps_bit_allocation->i2_K[B_PIC] = (P_TO_B_RATIO_HI_MO_HBR * I_TO_P_RATIO_HI_MO) >> K_Q; |
| } |
| } |
| /***************************************************************************** |
| Function Name : reset_Kp_Kb |
| Description : I_P_B_B1_B2 QP offset calculation based on hme sad |
| Inputs : |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| |
| void reset_Kp_Kb( |
| bit_allocation_t *ps_bit_allocation, |
| float f_i_to_avg_ratio, |
| WORD32 i4_num_active_pic_type, |
| float f_hme_sad_per_pixel, |
| float f_max_hme_sad_per_pixel, |
| WORD32 *pi4_complexity_bin, |
| WORD32 i4_rc_pass) |
| { |
| WORD32 i, i4_ratio = (WORD32)(f_max_hme_sad_per_pixel / f_hme_sad_per_pixel); |
| WORD32 ai4_offsets[5] = { 0 }; |
| float f_ratio = f_max_hme_sad_per_pixel / f_hme_sad_per_pixel; |
| |
| /*Filling out the offfset array for QP offset 0 - 7*/ |
| const WORD32 ai4_offset_qp[8] = { |
| (1 << K_Q), |
| I_TO_P_RATIO, |
| ((P_TO_B_RATIO * I_TO_P_RATIO) >> K_Q), |
| (B_TO_B1_RATIO * P_TO_B_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q), |
| (B1_TO_B2_RATIO * B_TO_B1_RATIO * P_TO_B_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q + K_Q), |
| (B1_TO_B2_RATIO * B1_TO_B2_RATIO * B_TO_B1_RATIO * P_TO_B_RATIO * I_TO_P_RATIO) >> |
| (K_Q + K_Q + K_Q + K_Q), |
| (B1_TO_B2_RATIO * B1_TO_B2_RATIO * B1_TO_B2_RATIO * B_TO_B1_RATIO * P_TO_B_RATIO * |
| I_TO_P_RATIO) >> |
| (K_Q + K_Q + K_Q + K_Q + K_Q), |
| (B1_TO_B2_RATIO * B1_TO_B2_RATIO * B1_TO_B2_RATIO * B1_TO_B2_RATIO * B_TO_B1_RATIO * |
| P_TO_B_RATIO * I_TO_P_RATIO) >> |
| (K_Q + K_Q + K_Q + K_Q + K_Q + K_Q) |
| }; |
| |
| ba_get_qp_offset_offline_data( |
| ai4_offsets, i4_ratio, f_ratio, i4_num_active_pic_type, pi4_complexity_bin); |
| for(i = 0; i < 5; i++) |
| { |
| ASSERT((ai4_offsets[i] >= 0) && (ai4_offsets[i] <= 7)); |
| ps_bit_allocation->i2_K[i] = ai4_offset_qp[ai4_offsets[i]]; |
| |
| /*For interlaced also we are filling out the offsets*/ |
| if(i > 0) |
| ps_bit_allocation->i2_K[i + 4] = ai4_offset_qp[ai4_offsets[i]]; |
| } |
| } |
| |
| /***************************************************************************** |
| Function Name : ba_get_qp_offset_offline_data |
| Description : Offline model for qp offset calculation |
| Inputs : ai4_offsets |
| i4_ratio |
| f_ratio |
| i4_num_active_pic_type |
| pi4_complexity_bin |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_get_qp_offset_offline_data( |
| WORD32 ai4_offsets[5], |
| WORD32 i4_ratio, |
| float f_ratio, |
| WORD32 i4_num_active_pic_type, |
| WORD32 *pi4_complexity_bin) |
| { |
| WORD32 i4_bin; |
| /*Desired QP offset's for different complexity bins depending on number of temporal layers*/ |
| /*There are 6 complexity bins |
| Max_compl - Max_compl*3/4, |
| Max_compl*3/4 - Max_compl*1/2, |
| Max_compl*1/2 - Max_compl*1/4, |
| Max_compl*1/4 - Max_compl*1/8, |
| Max_compl*1/8 - Max_compl*1/16 |
| <Max_compl*1/16*/ |
| /*The kids_rain content was run on different resolutions and the max value for different temporal configs is the max value used*/ |
| |
| /*First index for complexity bin, second index for pic_types (P,B,B1,B2)*/ |
| const WORD32 ai4_offset_values_7B[7][4] = { { 0, 1, 1, 2 }, { 1, 1, 2, 3 }, { 1, 2, 3, 3 }, |
| { 1, 2, 3, 4 }, { 2, 2, 3, 4 }, { 2, 3, 4, 5 }, |
| { 3, 4, 5, 6 } }; |
| const WORD32 ai4_offset_values_3B[7][3] = { { 0, 1, 2 }, { 1, 2, 2 }, { 1, 2, 3 }, { 2, 2, 3 }, |
| { 2, 3, 4 }, { 2, 4, 5 }, { 3, 4, 5 } }; |
| const WORD32 ai4_offset_values_1B[7][2] = { { 1, 1 }, { 1, 2 }, { 1, 2 }, { 1, 3 }, |
| { 2, 3 }, { 3, 4 }, { 3, 5 } }; |
| const WORD32 ai4_offset_values_0B[7][1] = { { 0 }, { 1 }, { 2 }, { 2 }, { 3 }, { 3 }, { 4 } }; |
| |
| /*The ratio is clipped between 16 and 2 to put it into bins*/ |
| |
| CLIP(i4_ratio, 16, 2); |
| |
| for(i4_bin = 1; i4_bin < 5; i4_bin++) |
| { |
| if((i4_ratio >> i4_bin) == 1) |
| { |
| break; |
| } |
| } |
| switch(i4_bin) |
| { |
| case(1): |
| (f_ratio > 2.0f) ? (i4_bin = 3) : ((f_ratio > 1.33f) ? (i4_bin = 2) : (i4_bin = 1)); |
| break; |
| case(2): |
| i4_bin = 4; |
| break; |
| case(3): |
| (f_ratio > 12.0f) ? (i4_bin = 6) : (i4_bin = 5); |
| break; |
| case(4): |
| i4_bin = 7; |
| break; |
| } |
| |
| /*For the i4_bin == 1, actual ratio could be >2.0,>1.33 or lesser hence putting them into different bins*/ |
| |
| trace_printf("1 bin %d", i4_bin); |
| |
| /*Total 7 bins hence the clip*/ |
| CLIP(i4_bin, 7, 1); |
| |
| *pi4_complexity_bin = i4_bin - 1; |
| |
| switch(i4_num_active_pic_type) |
| { |
| case 5: |
| memmove( |
| &ai4_offsets[1], |
| ai4_offset_values_7B[i4_bin - 1], |
| sizeof(ai4_offset_values_7B[i4_bin - 1])); |
| break; |
| case 4: |
| memmove( |
| &ai4_offsets[1], |
| ai4_offset_values_3B[i4_bin - 1], |
| sizeof(ai4_offset_values_3B[i4_bin - 1])); |
| break; |
| case 3: |
| memmove( |
| &ai4_offsets[1], |
| ai4_offset_values_1B[i4_bin - 1], |
| sizeof(ai4_offset_values_1B[i4_bin - 1])); |
| break; |
| case 2: |
| memmove( |
| &ai4_offsets[1], |
| ai4_offset_values_0B[i4_bin - 1], |
| sizeof(ai4_offset_values_0B[i4_bin - 1])); |
| break; |
| default: |
| memmove( |
| &ai4_offsets[1], |
| ai4_offset_values_0B[i4_bin - 1], |
| sizeof(ai4_offset_values_0B[i4_bin - 1])); |
| break; |
| } |
| |
| trace_printf( |
| "Enc %d,%d,%d,%d,%d offsets", |
| ai4_offsets[0], |
| ai4_offsets[1], |
| ai4_offsets[2], |
| ai4_offsets[3], |
| ai4_offsets[4]); |
| } |
| |
| /***************************************************************************** |
| Function Name : get_Kp_Kb |
| Description : Get the operating Kp and Kp so that scene cut sub gop can go |
| with similar qp offset |
| Inputs : ps_bit_allocation |
| e_pic_type |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| |
| WORD32 get_Kp_Kb(bit_allocation_t *ps_bit_allocation, picture_type_e e_pic_type) |
| { |
| return ps_bit_allocation->i2_K[e_pic_type]; |
| } |
| /***************************************************************************** |
| Function Name : get_scene_change_tot_frm_bits |
| Description : Based on remaining bits in period and default I_TO_B complexity |
| total bit budget for scene cut frame is obtained. |
| Inputs : ps_bit_allocation - bit_allocation structure |
| ps_rd_model - rd model pointer (for all the frame types) |
| e_pic_type - picture type |
| Globals : |
| Processing : |
| Outputs : |
| Returns : |
| Issues : |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 get_scene_change_tot_frm_bits( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handling, |
| cbr_buffer_handle ps_cbr_buf_handling, |
| WORD32 i4_num_pixels, |
| WORD32 i4_f_sim_lap, |
| float i_to_avg_rest, |
| WORD32 i4_call_type, |
| WORD32 i4_non_I_scd, |
| WORD32 i4_is_infinite_gop) |
| { |
| WORD32 j; |
| WORD32 i4_tot_bits_for_scd_frame; |
| WORD32 i4_total_bits_in_period; |
| //number_t avq_complexity_estimate[MAX_PIC_TYPE]; |
| WORD32 /* ai4_rem_frms_in_period[MAX_PIC_TYPE], */ |
| ai4_frms_in_period[MAX_PIC_TYPE]; |
| WORD32 i4_max_consumable_bits; |
| WORD32 i4_intra_frm_int; |
| WORD32 ai4_actual_frms_in_gop[MAX_PIC_TYPE], i, i4_total_frames = 0; |
| float final_ratio, f_sim = (float)i4_f_sim_lap / 128; |
| |
| i4_intra_frm_int = pic_type_get_intra_frame_interval(ps_pic_handling); |
| |
| /* Get the rem_frms_in_gop & the frms_in_gop from the pic_type state struct */ |
| /* pic_type_get_rem_frms_in_gop(ps_pic_handling, ai4_rem_frms_in_period); */ |
| pic_type_get_frms_in_gop(ps_pic_handling, ai4_frms_in_period); |
| |
| /* Depending on the number of gops in a period, find the num_frms_in_prd */ |
| for(j = 0; j < MAX_PIC_TYPE; j++) |
| { |
| /* ai4_rem_frms_in_period[j] += (ai4_frms_in_period[j] * (ps_bit_allocation->i4_num_gops_in_period - 1)); */ |
| ai4_frms_in_period[j] *= ps_bit_allocation->i4_num_gops_in_period; |
| } |
| |
| /* Remove the header bits from the remaining bits to find how many bits you |
| can transfer.*/ |
| { |
| i4_total_bits_in_period = ps_bit_allocation->s_rbip.i4_bits_per_frm * |
| ps_bit_allocation->s_rbip.i4_tot_frms_in_gop; |
| //trace_printf(" SCD_rbip = %d",i4_total_bits_in_period); |
| } |
| //since this marks end of previous GOP it is better to consider actual error than ps_bit_allocation->i4_frame_level_bit_error; |
| |
| { |
| pic_type_get_actual_frms_in_gop(ps_pic_handling, ai4_actual_frms_in_gop); |
| for(i = 0; i < MAX_PIC_TYPE; i++) |
| { |
| i4_total_frames += ai4_frms_in_period[i]; |
| } |
| i4_max_consumable_bits = ps_bit_allocation->i4_max_bits_per_frm[0] * i4_total_frames; |
| } |
| if(i4_total_bits_in_period > 0) |
| { |
| i4_total_bits_in_period = MIN(i4_total_bits_in_period, i4_max_consumable_bits); |
| } |
| final_ratio = i_to_avg_rest; |
| /*If FSIM says the content is static (> 126 is assured to be static*/ |
| /*Very low FSIM safety check*/ |
| if(f_sim < 0.50 && final_ratio > 8) |
| final_ratio = 8; |
| /*Do not apply safety limits if second pass as data is reliable*/ |
| if(ps_bit_allocation->i4_ba_rc_pass != 2) |
| { |
| /*clip min max values*/ |
| if((i4_is_infinite_gop == 1) && (final_ratio > I_TO_AVG_REST_GOP_BIT_MAX_INFINITE)) |
| { |
| final_ratio = I_TO_AVG_REST_GOP_BIT_MAX_INFINITE; |
| } |
| else |
| { |
| if(final_ratio > I_TO_AVG_REST_GOP_BIT_MAX) |
| final_ratio = I_TO_AVG_REST_GOP_BIT_MAX; |
| } |
| if(final_ratio < I_TO_AVG_REST_GOP_BIT_MIN) |
| final_ratio = I_TO_AVG_REST_GOP_BIT_MIN; |
| } |
| else |
| { |
| if(final_ratio > I_TO_AVG_REST_GOP_BIT_MAX_2_PASS) |
| final_ratio = I_TO_AVG_REST_GOP_BIT_MAX_2_PASS; |
| |
| if(final_ratio < I_TO_AVG_REST_GOP_BIT_MIN_2_PASS) |
| final_ratio = I_TO_AVG_REST_GOP_BIT_MIN_2_PASS; |
| } |
| |
| /*based on offline runs to find I_BITS/(AVERAGE_CONSUMPTION_OF_REST_GOP)*/ |
| /* BITS FOR I |
| BITS = I_TO_AVG_REST_GOP * total_bits_period |
| ------------------------------------- |
| N - (num_I_in_period) + (I_TO_AVG_REST_GOP * num_I_in_period) |
| */ |
| i4_tot_bits_for_scd_frame = bit_alloc_get_intra_bits( |
| ps_bit_allocation, |
| ps_pic_handling, |
| ps_cbr_buf_handling, |
| I_PIC, |
| NULL, |
| 1, |
| final_ratio, |
| i4_call_type, |
| i4_non_I_scd, |
| 0.0f); |
| ps_bit_allocation->i4_excess_bits_from_buffer = 0; |
| |
| if(i4_call_type == 1) |
| { |
| trace_printf("I_TO_AVG_REST_GOP_BIT used = %f\n", final_ratio); |
| trace_printf(" SCD DETECTED bits allocated = %d", i4_tot_bits_for_scd_frame); |
| } |
| |
| /* If the remaining bits in the period becomes negative then the estimated texture |
| bits would also become negative. This would send a feedback to the model which |
| may go for a toss. Thus sending the minimum possible value = 0 */ |
| if(i4_tot_bits_for_scd_frame < 0) |
| i4_tot_bits_for_scd_frame = 0; |
| |
| return (i4_tot_bits_for_scd_frame); |
| } |
| |
| /***************************************************************************** |
| Function Name : update_estimate_status |
| Description : Est texture bits in case of scene cut is obtained form offline |
| model. Update bit alloc |
| Inputs : ps_bit_allocation |
| e_pic_type |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| |
| void update_estimate_status( |
| bit_allocation_t *ps_bit_allocation, |
| WORD32 i4_est_texture_bits, |
| WORD32 i4_hdr_bits, |
| WORD32 i4_est_text_bits_ctr_get_qp) |
| { |
| ps_bit_allocation->ai4_cur_frm_est_tex_bits[i4_est_text_bits_ctr_get_qp] = i4_est_texture_bits; |
| ps_bit_allocation->ai4_cur_frm_est_hdr_bits[i4_est_text_bits_ctr_get_qp] = i4_hdr_bits; |
| } |
| |
| /***************************************************************************** |
| Function Name : bit_allocation_set_num_scd_lap_window |
| Description : |
| Inputs : ps_bit_allocation |
| i4_num_scd_in_lap_window |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void bit_allocation_set_num_scd_lap_window( |
| bit_allocation_t *ps_bit_allocation, |
| WORD32 i4_num_scd_in_lap_window, |
| WORD32 i4_num_frames_b4_Scd) |
| { |
| ps_bit_allocation->i4_num_scd_in_lap_window = i4_num_scd_in_lap_window; |
| ps_bit_allocation->i4_num_frm_b4_scd = i4_num_frames_b4_Scd; |
| /*To avoid trashing I frame badly due to back to back scene cut limit the increment in Ni*/ |
| if(ps_bit_allocation->i4_num_scd_in_lap_window > 2) |
| ps_bit_allocation->i4_num_scd_in_lap_window = 2; |
| } |
| /***************************************************************************** |
| Function Name : bit_allocation_set_sc_i_in_rc_look_ahead |
| Description : |
| Inputs : ps_bit_allocation |
| i4_next_sc_i_in_rc_look_ahead |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void bit_allocation_set_sc_i_in_rc_look_ahead( |
| bit_allocation_t *ps_bit_allocation, WORD32 i4_next_sc_i_in_rc_look_ahead) |
| { |
| ps_bit_allocation->i4_next_sc_i_in_rc_look_ahead = i4_next_sc_i_in_rc_look_ahead; |
| } |
| /***************************************************************************** |
| Function Name : bit_allocation_update_gop_level_bit_error |
| Description : |
| Inputs : ps_bit_allocation |
| i4_error_bits |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void bit_allocation_update_gop_level_bit_error( |
| bit_allocation_t *ps_bit_allocation, WORD32 i4_error_bits) |
| { |
| ps_bit_allocation->i4_gop_level_bit_error += i4_error_bits; |
| ps_bit_allocation->i4_frame_level_bit_error += i4_error_bits; |
| /*Error is (rdopt - entropy) Hence for total bit consumption subtract error*/ |
| ps_bit_allocation->i8_cur_gop_bit_consumption -= i4_error_bits; |
| } |
| |
| /****************************************************************************** |
| Function Name : rc_update_bit_distribution_gop_level_2pass |
| Description : This function distributes the bits to all the gops depending |
| on the complexities and the error bits accumulated until now |
| Arguments : ps_rate_control_api - rate control api handle |
| i4_start_gop_number : GOP number from which distribution should happen |
| Return Values : |
| Revision History: |
| |
| |
| Assumptions - |
| |
| Checks - |
| *****************************************************************************/ |
| void rc_update_bit_distribution_gop_level_2pass( |
| bit_allocation_t *ps_bit_allocation, |
| pic_handling_handle ps_pic_handle, |
| void *pv_gop_stat, |
| rc_type_e e_rc_type, |
| WORD32 i4_num_gop, |
| WORD32 i4_start_gop_number, |
| float f_avg_qscale_first_pass, |
| WORD32 i4_max_ebf, |
| WORD32 i4_ebf, |
| LWORD64 i8_tot_bits_sequence, |
| WORD32 i4_comp_error) |
| { |
| float cur_peak_factor, f_bits_per_frame; |
| LWORD64 total_nbp_bits_allocated = 0; |
| LWORD64 total_bp_bits_allocated = 0; |
| LWORD64 total_bits_allocated = 0, prev_total_bits_allocated = -1; |
| WORD32 |
| i4_num_loop_inter_GOP_alloc = 0, ai4_peak_bitrate[MAX_NUM_DRAIN_RATES] = { 0 }, |
| temp_i; /*Loop 20 times to meet precise bitrate, after that exit the loop and distribute remaining bits equally for all GOP*/ |
| gop_level_stat_t *ps_cur_gop; |
| WORD32 i4_num_frames_in_gop, i4_cur_gop_num, i4_num_frm_with_rmax, i4_num_frm_with_rmin; |
| LWORD64 i8_max_bit_for_gop, /*i8_min_bit_for_gop,*/ i8_peak_bitrate, i8_frame_rate, |
| i8_current_bitrate = (LWORD64)ba_get_2pass_avg_bit_rate(ps_bit_allocation); |
| LWORD64 i8_actual_avg_bit_rate = ba_get_bit_rate(ps_bit_allocation); |
| LWORD64 i8_num_frame_remaining = 0, i8_excess_bits = 0; |
| float min_complexity_beyond_peak /*,f_max_complexity = 1.0f,f_min_complexity = 0.0f*/ |
| ; //The minimum complexity for which bit allocation exceeds peak rate but |
| float f_avg_bits_complexity_based; |
| WORD32 i4_num_gop_not_rmax; |
| LWORD64 i8_bits_for_this_gop; |
| |
| #define MAX_LOOP_INTER_GOP_ALLOC \ |
| 20 /*The below loop shall run maximum of this macro once it exits allocate the difference bits equally for all the GOPS*/ |
| |
| i4_ebf = MAX(i4_ebf, 0); |
| //i4_ebf = 0; |
| if(i4_start_gop_number == 0) |
| { |
| cur_peak_factor = 7.0; |
| } |
| else |
| { |
| cur_peak_factor = ps_bit_allocation->f_cur_peak_factor_2pass; |
| } |
| /*Parsing of entire log file is done and summary of GOP level data has been updated in the temp, |
| Iteratively allocate the bits to make it meet bitrate*/ |
| for(temp_i = i4_start_gop_number; temp_i < i4_num_gop; temp_i++) |
| { |
| ps_cur_gop = (gop_level_stat_t *)((gop_level_stat_t *)pv_gop_stat + temp_i); |
| } |
| i8_frame_rate = ba_get_frame_rate(ps_bit_allocation); |
| ba_get_peak_bit_rate(ps_bit_allocation, &ai4_peak_bitrate[0]); |
| i8_peak_bitrate = (LWORD64)ai4_peak_bitrate[0]; |
| |
| /*Modify the bitrate depending on the error bits and total bits*/ |
| //i8_current_bitrate = (LWORD64)((float)i8_tot_bits_sequence*i8_frame_rate/(1000*i8_num_frame_remaining)); |
| |
| f_bits_per_frame = (float)i8_current_bitrate / i8_frame_rate * 1000; |
| ps_bit_allocation->i8_current_bitrate_2_pass = i8_current_bitrate; |
| //printf("\n%d current bitrate",i8_current_bitrate); |
| |
| do |
| { |
| /*Get gop level stat*/ |
| /*recalculate the bits based on new scaling factor*/ |
| total_bits_allocated = 0; |
| total_bp_bits_allocated = 0; |
| total_nbp_bits_allocated = 0; |
| min_complexity_beyond_peak = |
| (float)ps_bit_allocation->ai4_peak_bit_rate[0] / i8_current_bitrate; |
| |
| /*min_complexity_beyond_peak = ba_get_min_complexity_for_peak_br(ps_bit_allocation->ai4_peak_bit_rate[0], |
| (WORD32)i8_current_bitrate, |
| cur_peak_factor, |
| f_max_complexity, |
| f_min_complexity, |
| ps_bit_allocation->i4_ba_rc_pass);*/ |
| |
| for(i4_cur_gop_num = i4_start_gop_number; i4_cur_gop_num < i4_num_gop; i4_cur_gop_num++) |
| { |
| ps_cur_gop = (gop_level_stat_t *)((gop_level_stat_t *)pv_gop_stat + i4_cur_gop_num); |
| ps_cur_gop->f_bits_complexity_l1_based_peak_factor = |
| ps_cur_gop->f_bits_complexity_l1_based * cur_peak_factor; |
| } |
| i4_num_frm_with_rmax = 0; |
| i4_num_frm_with_rmin = 0; |
| f_avg_bits_complexity_based = 0.0; |
| i4_num_gop_not_rmax = 0; |
| i8_num_frame_remaining = 0; |
| for(i4_cur_gop_num = i4_start_gop_number; i4_cur_gop_num < i4_num_gop; i4_cur_gop_num++) |
| { |
| ps_cur_gop = (gop_level_stat_t *)((gop_level_stat_t *)pv_gop_stat + i4_cur_gop_num); |
| if(!ps_cur_gop->i4_peak_br_clip) |
| { |
| f_avg_bits_complexity_based += |
| (ps_cur_gop->f_bits_complexity_l1_based * ps_cur_gop->i4_tot_frm_in_gop); |
| i8_num_frame_remaining += ps_cur_gop->i4_tot_frm_in_gop; |
| i4_num_gop_not_rmax++; |
| } |
| } |
| f_avg_bits_complexity_based = (f_avg_bits_complexity_based / i8_num_frame_remaining); |
| for(i4_cur_gop_num = i4_start_gop_number; i4_cur_gop_num < i4_num_gop; i4_cur_gop_num++) |
| { |
| /*Parse through all the GOP*/ |
| /*get current gop data*/ |
| //i4_num_frames_in_gop = 0; |
| LWORD64 i8_avg_bit_rate_bits; |
| LWORD64 i8_curr_bit_rate_bits; |
| ps_cur_gop = (gop_level_stat_t *)((gop_level_stat_t *)pv_gop_stat + i4_cur_gop_num); |
| |
| if(ps_cur_gop->i4_peak_br_clip) |
| { |
| i4_num_frm_with_rmax++; |
| total_nbp_bits_allocated += ps_cur_gop->i8_bits_allocated_to_gop; |
| continue; |
| } |
| ps_cur_gop->f_buffer_play_complexity = 0.; |
| //ps_cur_gop->f_gop_level_complexity_sum = -1; |
| //ps_cur_gop->i8_buffer_play_bits = 0; |
| ps_cur_gop->i8_buffer_play_bits_allocated_to_gop = 0; |
| i4_num_frames_in_gop = ps_cur_gop->i4_tot_frm_in_gop; |
| |
| if(i4_num_gop_not_rmax == i4_num_gop) |
| { |
| i8_bits_for_this_gop = |
| (LWORD64)((i8_current_bitrate * i4_num_frames_in_gop * 1000) / i8_frame_rate); |
| if(e_rc_type == VBR_STREAMING) |
| { |
| ps_cur_gop->i8_bits_allocated_to_gop = (LWORD64)( |
| (ps_cur_gop->f_bits_complexity_l1_based / (f_avg_bits_complexity_based)) * |
| i8_bits_for_this_gop); |
| } |
| else |
| { |
| ps_cur_gop->i8_bits_allocated_to_gop = |
| (LWORD64)(i8_current_bitrate * i4_num_frames_in_gop / i8_frame_rate * 1000); |
| } |
| } |
| else |
| { |
| //i8_bits_for_this_gop = (LWORD64)((i8_excess_bits * i4_num_frames_in_gop * 1000)/(i8_frame_rate*i4_num_gop_not_rmax)); |
| i8_bits_for_this_gop = |
| (LWORD64)((i8_excess_bits * i4_num_frames_in_gop) / (i8_num_frame_remaining)); |
| if(e_rc_type == VBR_STREAMING) |
| { |
| ps_cur_gop->i8_bits_allocated_to_gop += (LWORD64)( |
| (ps_cur_gop->f_bits_complexity_l1_based / (f_avg_bits_complexity_based)) * |
| i8_bits_for_this_gop); |
| } |
| else |
| { |
| ASSERT(0); |
| } |
| } |
| ps_cur_gop->i8_actual_bits_allocated_to_gop = ps_cur_gop->i8_bits_allocated_to_gop; |
| /*clip based on peak rate*/ |
| i8_max_bit_for_gop = i8_peak_bitrate * i4_num_frames_in_gop * 1000 / i8_frame_rate; |
| ps_cur_gop->i8_max_bit_for_gop = i8_max_bit_for_gop; |
| ps_cur_gop->i4_peak_br_clip = 0; |
| if(ps_cur_gop->i8_bits_allocated_to_gop > i8_max_bit_for_gop) |
| { |
| ps_cur_gop->i8_bits_allocated_to_gop = i8_max_bit_for_gop; |
| ps_cur_gop->i4_peak_br_clip = 1; |
| i4_num_frm_with_rmax++; |
| /*if(ps_cur_gop->f_bits_complexity_l1_based < min_complexity_beyond_peak) |
| min_complexity_beyond_peak = ps_cur_gop->f_bits_complexity_l1_based;*/ |
| } |
| i8_curr_bit_rate_bits = |
| (LWORD64)(i8_current_bitrate * i4_num_frames_in_gop / i8_frame_rate * 1000); |
| i8_avg_bit_rate_bits = |
| (LWORD64)(i8_actual_avg_bit_rate * i4_num_frames_in_gop / i8_frame_rate * 1000); |
| ps_cur_gop->i4_is_below_avg_rate_gop_frame = 0; |
| if(ps_cur_gop->i8_bits_allocated_to_gop < |
| (MIN(i8_curr_bit_rate_bits, ps_cur_gop->i8_minimum_gop_bits))) |
| { |
| ps_cur_gop->i4_is_below_avg_rate_gop_frame = 1; |
| ps_cur_gop->i8_bits_allocated_to_gop = |
| MIN(i8_curr_bit_rate_bits, ps_cur_gop->i8_minimum_gop_bits); |
| i4_num_frm_with_rmin++; |
| } |
| total_nbp_bits_allocated += ps_cur_gop->i8_bits_allocated_to_gop; |
| } |
| i4_num_loop_inter_GOP_alloc++; |
| /*check for tolerance of 0.5% in terms of meeting bitrate, terminate the loop when bitrate is met*/ |
| total_bits_allocated = total_nbp_bits_allocated + total_bp_bits_allocated; |
| if((total_bits_allocated < (1.005 * i8_tot_bits_sequence) && |
| total_bits_allocated > (0.995 * i8_tot_bits_sequence)) || |
| (i4_num_loop_inter_GOP_alloc > MAX_LOOP_INTER_GOP_ALLOC) /*|| (cur_peak_factor <= 1 )*/) |
| { |
| float error_bits = ((float)i8_tot_bits_sequence - total_bits_allocated); |
| WORD32 temp_i; |
| float f_per_frm_bits = ((float)(i8_current_bitrate)) / (i8_frame_rate / 1000); |
| //cur_peak_factor *= (float)i8_tot_bits_sequence/total_bits_allocated; |
| if((i4_comp_error == 1) || ((i4_comp_error == 0) && (error_bits < 0))) |
| { |
| for(temp_i = i4_start_gop_number; temp_i < i4_num_gop; temp_i++) |
| { |
| ps_cur_gop = (gop_level_stat_t *)((gop_level_stat_t *)pv_gop_stat + temp_i); |
| ps_cur_gop->i8_bits_allocated_to_gop += (LWORD64)( |
| (error_bits * ps_cur_gop->i8_bits_allocated_to_gop / total_bits_allocated)); |
| } |
| } |
| for(temp_i = i4_start_gop_number; temp_i < i4_num_gop; temp_i++) |
| { |
| ps_cur_gop = (gop_level_stat_t *)((gop_level_stat_t *)pv_gop_stat + temp_i); |
| ps_cur_gop->f_avg_complexity_factor = (ps_cur_gop->f_bits_complexity_l1_based / |
| ps_cur_gop->i8_bits_allocated_to_gop) * |
| (f_per_frm_bits) * |
| (ps_cur_gop->i4_tot_frm_in_gop); |
| } |
| break; |
| } |
| else |
| { |
| /*Go for next iteration*/ |
| cur_peak_factor *= (float)i8_tot_bits_sequence / total_bits_allocated; |
| //cur_peak_factor = MAX(cur_peak_factor,1); |
| prev_total_bits_allocated = total_bits_allocated; |
| i8_excess_bits = i8_tot_bits_sequence - total_bits_allocated; |
| } |
| |
| } while(1); |
| ps_bit_allocation->f_cur_peak_factor_2pass = cur_peak_factor; |
| ps_bit_allocation->i8_total_bits_allocated = total_bits_allocated; |
| |
| /*Store complexity beyond which bits are clipped to peak rate*/ |
| /*if(i4_start_gop_number == 0)*/ |
| { |
| ps_bit_allocation->f_min_complexity_cross_peak_rate = /*min_complexity_beyond_peak*/ |
| (float)ps_bit_allocation->ai4_peak_bit_rate[0] / i8_current_bitrate; |
| //ba_get_min_complexity_for_peak_br(ps_bit_allocation->ai4_peak_bit_rate[0],ps_bit_allocation->i4_bit_rate,cur_peak_factor,f_max_complexity,f_min_complexity,ps_bit_allocation->i4_ba_rc_pass); |
| } |
| } |
| |
| /***************************************************************************** |
| Function Name : get_prev_frame_total_header_bits |
| Description : |
| Inputs : ps_bit_allocation |
| e_pic_type |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void get_prev_frame_total_header_bits( |
| bit_allocation_t *ps_bit_allocation, |
| WORD32 *pi4_prev_frame_total_bits, |
| WORD32 *pi4_prev_frame_header_bits, |
| picture_type_e e_pic_type) |
| { |
| *pi4_prev_frame_total_bits = ps_bit_allocation->ai4_prev_frm_tot_bits[e_pic_type]; |
| *pi4_prev_frame_header_bits = ps_bit_allocation->i4_prev_frm_header_bits[e_pic_type]; |
| } |
| |
| /***************************************************************************** |
| Function Name : bit_alloc_get_gop_num |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| LWORD64 bit_alloc_get_gop_num(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->i8_cur_gop_num); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_min_bits_per_frame |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_min_bits_per_frame(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->i4_min_bits_per_frm); |
| } |
| /***************************************************************************** |
| Function Name : set_bit_allocation_i_frames |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void set_bit_allocation_i_frames( |
| bit_allocation_t *ps_bit_allocation, |
| cbr_buffer_handle ps_cbr_buffer, |
| pic_handling_handle ps_pic_handle, |
| WORD32 i4_lap_window_comp, |
| WORD32 i4_num_frames) |
| { |
| LWORD64 vbv_buffer_based_excess = 0; |
| WORD32 i4_gop_correction; |
| WORD32 i4_lap_window_comp_temp = i4_lap_window_comp; |
| rc_type_e e_rc_type = get_rc_type(ps_cbr_buffer); |
| if(e_rc_type == VBR_STREAMING) |
| { |
| if(((float)i4_lap_window_comp / 128) > ps_bit_allocation->f_min_complexity_cross_peak_rate) |
| i4_lap_window_comp_temp = |
| (WORD32)(ps_bit_allocation->f_min_complexity_cross_peak_rate * 128); |
| |
| /*Get excess bits if any from vbv buffer*/ |
| vbv_buffer_based_excess = get_vbv_buffer_based_excess( |
| ps_cbr_buffer, |
| ps_bit_allocation->f_min_complexity_cross_peak_rate, |
| ((float)i4_lap_window_comp / 128), |
| i4_num_frames, |
| 1); |
| } |
| i4_gop_correction = |
| get_error_bits_for_desired_buf(ps_cbr_buffer, i4_lap_window_comp_temp, i4_num_frames); |
| |
| update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handle, 0); |
| |
| set_rbip(&ps_bit_allocation->s_rbip, (i4_gop_correction + (WORD32)vbv_buffer_based_excess)); |
| |
| update_rbip(&ps_bit_allocation->s_rbip, ps_pic_handle, 0); |
| } |
| |
| /***************************************************************************** |
| Function Name : bit_alloc_set_curr_i_to_sum_i |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void bit_alloc_set_curr_i_to_sum_i(bit_allocation_t *ps_bit_allocation, float f_curr_i_to_sum) |
| { |
| ps_bit_allocation->f_curr_i_to_sum = f_curr_i_to_sum; |
| } |
| |
| /***************************************************************************** |
| Function Name : ba_set_gop_stat_in_bit_alloc |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_set_gop_stat_in_bit_alloc(bit_allocation_t *ps_bit_allocation, void *pv_gop_stat_summary) |
| { |
| ps_bit_allocation->pv_gop_stat = pv_gop_stat_summary; |
| } |
| /***************************************************************************** |
| Function Name : ba_get_luma_pels |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_luma_pels(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->i4_luma_pels); |
| } |
| /***************************************************************************** |
| Function Name : overflow_avoided_summation |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void overflow_avoided_summation(WORD32 *pi4_accumulator, WORD32 i4_input) |
| { |
| if((pi4_accumulator[0] > 0) && (((int)0x7fffffff - pi4_accumulator[0]) < i4_input)) |
| pi4_accumulator[0] = 0x7fffffff; |
| else if((pi4_accumulator[0] < 0) && (((int)0x80000000 - pi4_accumulator[0]) > i4_input)) |
| pi4_accumulator[0] = 0x80000000; |
| else |
| pi4_accumulator[0] += i4_input; |
| } |
| /***************************************************************************** |
| Function Name : ba_get_sum_complexity_segment_cross_peak |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| float ba_get_sum_complexity_segment_cross_peak(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->f_sum_complexity_segment_cross_peak); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_prev_frame_tot_est_bits |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_prev_frame_tot_est_bits(bit_allocation_t *ps_bit_allocation, WORD32 i4_pic) |
| { |
| return (ps_bit_allocation->ai4_prev_frm_tot_est_bits[i4_pic]); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_prev_frame_tot_bits |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_prev_frame_tot_bits(bit_allocation_t *ps_bit_allocation, WORD32 i4_pic) |
| { |
| return (ps_bit_allocation->ai4_prev_frm_tot_bits[i4_pic]); |
| } |
| /***************************************************************************** |
| Function Name : ba_gop_info_average_qscale_gop_without_offset |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| float ba_gop_info_average_qscale_gop_without_offset(bit_allocation_t *ps_bit_allocation) |
| { |
| gop_level_stat_t *ps_gop_level_stat = |
| (gop_level_stat_t *)ps_bit_allocation->pv_gop_stat + ps_bit_allocation->i8_cur_gop_num; |
| |
| return (ps_gop_level_stat->f_hbd_avg_q_scale_gop_without_offset); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_min_complexity_for_peak_br |
| Description : compute min complexity above which peak rate needs to be given |
| Inputs : i4_peak_bit_rate |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| float ba_get_min_complexity_for_peak_br( |
| WORD32 i4_peak_bit_rate, |
| WORD32 i4_bit_rate, |
| float f_peak_rate_factor, |
| float f_max_val, |
| float f_min_val, |
| WORD32 i4_pass) |
| { |
| float f_target_bits_ratio = (float)i4_peak_bit_rate / i4_bit_rate; |
| float f_at_min_val; |
| float f_at_max_val; |
| float f_avg_val, f_at_avg_val; |
| WORD32 i4_iter = 0, i4_max_iter = 25; |
| |
| f_avg_val = (f_max_val + f_min_val) / 2; |
| /*i4_target_bits_ratio = (-1.7561*(X*X*X*X) + ( 2.5547 * X * X * X) - 0.3408 * (X * X) + (0.5343 * X) - 0.003) * 10;*/ |
| if(i4_pass != 2) |
| { |
| f_at_min_val = COMP_TO_BITS_MAP(f_min_val, f_peak_rate_factor); |
| f_at_max_val = COMP_TO_BITS_MAP(f_max_val, f_peak_rate_factor); |
| f_at_avg_val = COMP_TO_BITS_MAP(f_avg_val, f_peak_rate_factor); |
| } |
| else |
| { |
| f_at_min_val = COMP_TO_BITS_MAP_2_PASS(f_min_val, f_peak_rate_factor); |
| f_at_max_val = COMP_TO_BITS_MAP_2_PASS(f_max_val, f_peak_rate_factor); |
| f_at_avg_val = COMP_TO_BITS_MAP_2_PASS(f_avg_val, f_peak_rate_factor); |
| } |
| |
| do |
| { |
| if((f_at_min_val < f_target_bits_ratio) && (f_target_bits_ratio < f_at_avg_val)) |
| { |
| f_max_val = f_avg_val; |
| } |
| else |
| { |
| f_min_val = f_avg_val; |
| } |
| f_avg_val = (f_max_val + f_min_val) / 2; |
| |
| /*i4_target_bits_ratio = (-1.7561*(X*X*X*X) + ( 2.5547 * X * X * X) - 0.3408 * (X * X) + (0.5343 * X) - 0.003) * 10;*/ |
| if(i4_pass != 2) |
| { |
| f_at_min_val = COMP_TO_BITS_MAP(f_min_val, f_peak_rate_factor); |
| f_at_max_val = COMP_TO_BITS_MAP(f_max_val, f_peak_rate_factor); |
| f_at_avg_val = COMP_TO_BITS_MAP(f_avg_val, f_peak_rate_factor); |
| } |
| else |
| { |
| f_at_min_val = COMP_TO_BITS_MAP_2_PASS(f_min_val, f_peak_rate_factor); |
| f_at_max_val = COMP_TO_BITS_MAP_2_PASS(f_max_val, f_peak_rate_factor); |
| f_at_avg_val = COMP_TO_BITS_MAP_2_PASS(f_avg_val, f_peak_rate_factor); |
| } |
| |
| if(((fabs((float)(f_at_avg_val - f_target_bits_ratio))) <= .0001f) || |
| (i4_iter >= i4_max_iter)) |
| { |
| break; |
| } |
| i4_iter++; |
| } while(1); |
| |
| /*f_min_complexity_across_which pk br is given is unmapped value for 1 pass and mapped value for 2 pass*/ |
| if(i4_pass != 2) |
| return (f_avg_val); |
| else |
| return (f_at_avg_val); |
| } |
| /***************************************************************************** |
| Function Name : get_f_curr_by_sum_subgop |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| float get_f_curr_by_sum_subgop(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->f_curr_by_sum_subgop); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_frame_number_in_gop |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_frame_number_in_gop(bit_allocation_t *ps_bit_allocation) |
| { |
| return ((WORD32)(ps_bit_allocation->i8_frm_num_in_gop)); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_qscale_max_clip_in_second_pass |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| float ba_get_qscale_max_clip_in_second_pass(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->f_qscale_max_clip_in_second_pass); |
| } |
| /***************************************************************************** |
| Function Name : ba_set_avg_qscale_first_pass |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_set_avg_qscale_first_pass( |
| bit_allocation_t *ps_bit_allocation, float f_average_qscale_1st_pass) |
| { |
| ps_bit_allocation->f_average_qscale_1st_pass = f_average_qscale_1st_pass; |
| } |
| /***************************************************************************** |
| Function Name : ba_set_max_avg_qscale_first_pass |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_set_max_avg_qscale_first_pass( |
| bit_allocation_t *ps_bit_allocation, float f_average_qscale_1st_pass) |
| { |
| ps_bit_allocation->f_max_average_qscale_1st_pass = f_average_qscale_1st_pass; |
| } |
| /***************************************************************************** |
| Function Name : ba_get_avg_qscale_first_pass |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| float ba_get_avg_qscale_first_pass(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->f_average_qscale_1st_pass); |
| } |
| /***************************************************************************** |
| Function Name : ba_get_max_avg_qscale_first_pass |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| float ba_get_max_avg_qscale_first_pass(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->f_max_average_qscale_1st_pass); |
| } |
| /***************************************************************************** |
| Function Name : bit_alloc_set_2pass_total_frames |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void bit_alloc_set_2pass_total_frames( |
| bit_allocation_t *ps_bit_allocation, WORD32 i4_total_2pass_frames) |
| { |
| ps_bit_allocation->i4_total_2pass_frames = i4_total_2pass_frames; |
| } |
| /***************************************************************************** |
| Function Name : ba_get_2pass_total_frames |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| WORD32 ba_get_2pass_total_frames(bit_allocation_t *ps_bit_allocation) |
| { |
| return (ps_bit_allocation->i4_total_2pass_frames); |
| } |
| /***************************************************************************** |
| Function Name : ba_set_enable_look_ahead |
| Description : |
| Inputs : ps_bit_allocation |
| |
| Revision History: |
| DD MM YYYY Author(s) Changes (Describe the changes made) |
| *****************************************************************************/ |
| void ba_set_enable_look_ahead(bit_allocation_t *ps_bit_allocation, WORD32 i4_fp_bit_alloc_in_sp) |
| { |
| ps_bit_allocation->i4_fp_bit_alloc_in_sp = i4_fp_bit_alloc_in_sp; |
| } |