You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3236 lines
136 KiB
3236 lines
136 KiB
/******************************************************************************
|
|
*
|
|
* 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;
|
|
}
|