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.
4242 lines
168 KiB
4242 lines
168 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 rate_control_api.c
|
|
*
|
|
* \brief
|
|
* This file contain rate control API functions
|
|
*
|
|
* \date
|
|
*
|
|
* \author
|
|
* ittiam
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
/*****************************************************************************/
|
|
/* File Includes */
|
|
/*****************************************************************************/
|
|
/* System include files */
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
|
|
/* User include files */
|
|
#include "ittiam_datatypes.h"
|
|
/* Lower module include files. These inclusion can be removed by having
|
|
fwd declaration for each and every module*/
|
|
#include "rc_common.h"
|
|
#include "rc_cntrl_param.h"
|
|
#include "mem_req_and_acq.h"
|
|
#include "var_q_operator.h"
|
|
#include "rc_rd_model.h"
|
|
#include "est_sad.h"
|
|
#include "fixed_point_error_bits.h"
|
|
#include "vbr_storage_vbv.h"
|
|
#include "picture_type.h"
|
|
#include "cbr_buffer_control.h"
|
|
#include "bit_allocation.h"
|
|
#include "mb_model_based.h"
|
|
#include "vbr_str_prms.h"
|
|
#include "init_qp.h"
|
|
#include "rc_sad_acc.h"
|
|
#include "rc_frame_info_collector.h"
|
|
#include "rate_control_api.h"
|
|
#include "rate_control_api_structs.h"
|
|
#include "trace_support.h"
|
|
|
|
/** Macros **/
|
|
#define MIN(x, y) ((x) < (y)) ? (x) : (y)
|
|
#define MAX(x, y) ((x) < (y)) ? (y) : (x)
|
|
#define CLIP3RC(x, min, max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
|
|
|
|
#define DEV_Q 4 /*Q format(Shift) for Deviation range factor */
|
|
#define HI_DEV_FCTR 26 //23//32 /* 1.4*16 */
|
|
#define LO_DEV_B_FCTR 10 //temp change to avoid stuffing12 /* 0.75*16 */
|
|
#define LO_DEV_FCTR_1B 14 //8 /* 0.75*16 */
|
|
//#define LO_DEV_FCTR_7B 10//8 /* 0.75*16 */
|
|
#define LO_DEV_FCTR_3B 12 //8 /* 0.75*16 */
|
|
#define LO_DEV_FCTR_7B 12 //8 /* 0.75*16 */
|
|
#define GET_HI_DEV_QP(Qprev) ((((WORD32)Qprev) * HI_DEV_FCTR + (1 << (DEV_Q - 1))) >> DEV_Q)
|
|
|
|
#define GET_LO_DEV_QP(Qprev, i4_num_active_pic_types)((i4_num_active_pic_types <= B1_PIC)?(((((WORD32) Qprev)*LO_DEV_FCTR_1B + (1<<(DEV_Q-1)))>>DEV_Q): \
|
|
((i4_num_active_pic_types == B2_PIC)? ((((WORD32) Qprev)*LO_DEV_FCTR_3B + (1<<(DEV_Q-1)))>>DEV_Q) \
|
|
((((WORD32) Qprev)*LO_DEV_FCTR_7B + (1<<(DEV_Q-1)))>>DEV_Q))))
|
|
|
|
#define GET_LO_DEV_QP_B(Qprev) ((((WORD32)Qprev) * LO_DEV_B_FCTR + (1 << (DEV_Q - 1))) >> DEV_Q)
|
|
#define CLIP_QP(Qc, hi_d, lo_d) (((Qc) < (lo_d)) ? ((lo_d)) : (((Qc) > (hi_d)) ? (hi_d) : (Qc)))
|
|
|
|
/*below macors are used when qp is already in q format so adding 0.5 for rounding is not required*/
|
|
#define GET_HI_DEV_QP_QFAC(Qprev) ((((WORD32)Qprev) * HI_DEV_FCTR) >> DEV_Q)
|
|
#define GET_LO_DEV_QP_QFAC(Qprev, i4_num_active_pic_types) \
|
|
((i4_num_active_pic_types <= B1_PIC) \
|
|
? ((((WORD32)Qprev) * LO_DEV_FCTR_1B) >> DEV_Q) \
|
|
: ((i4_num_active_pic_types == B2_PIC) ? ((((WORD32)Qprev) * LO_DEV_FCTR_3B) >> DEV_Q) \
|
|
: ((((WORD32)Qprev) * LO_DEV_FCTR_7B) >> DEV_Q)))
|
|
|
|
#define GET_LO_DEV_QP_QFAC_B_PIC(Qprev) ((((WORD32)Qprev) * LO_DEV_FCTR_3B) >> DEV_Q)
|
|
|
|
#define GET_LO_DEV_QP_B_QFAC(Qprev) ((((WORD32)Qprev) * LO_DEV_B_FCTR) >> DEV_Q)
|
|
|
|
#define P_TO_I_RATIO_Q_FACTOR (9)
|
|
#define MULT_FACTOR_SATD (4)
|
|
#define GET_L0_SATD_BY_ACT_MAX_PER_PIXEL(i4_num_pixel) \
|
|
((5.4191f * i4_num_pixel + 4000000.0f) / i4_num_pixel)
|
|
#define GET_WEIGH_FACTOR_FOR_MIN_SCD_Q_SCALE(normal_satd_act, f_satd_by_Act_norm) \
|
|
(MULT_FACTOR_SATD * normal_satd_act + f_satd_by_Act_norm) / \
|
|
(normal_satd_act + MULT_FACTOR_SATD * f_satd_by_Act_norm)
|
|
|
|
void SET_NETRA_TRACE(UWORD8 tag[], WORD32 value);
|
|
#define NETRA_TRACE (0)
|
|
#if NETRA_TRACE
|
|
#else
|
|
#define SET_NETRA_TRACE(x, y)
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* Restricts the quantisation parameter variation within delta */
|
|
/*****************************************************************************/
|
|
/* static WORD32 restrict_swing(WORD32 cur_qp, WORD32 prev_qp, WORD32 delta_qp)
|
|
{
|
|
if((cur_qp) - (prev_qp) > (delta_qp)) (cur_qp) = (prev_qp) + (delta_qp) ;
|
|
if((prev_qp) - (cur_qp) > (delta_qp)) (cur_qp) = (prev_qp) - (delta_qp) ;
|
|
return cur_qp;
|
|
}*/
|
|
|
|
/*****************************************************************************
|
|
Function Name : rate_control_get_init_free_memtab
|
|
Description : Takes or gives memtab
|
|
Inputs : pps_rate_control_api - pointer to RC api pointer
|
|
ps_memtab - Memtab pointer
|
|
i4_use_base - Set during init, else 0
|
|
i4_fill_base - Set during free, else 0
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
#if NON_STEADSTATE_CODE
|
|
WORD32 rate_control_num_fill_use_free_memtab(
|
|
rate_control_handle *pps_rate_control_api, itt_memtab_t *ps_memtab, ITT_FUNC_TYPE_E e_func_type)
|
|
{
|
|
WORD32 i4_mem_tab_idx = 0, i;
|
|
static rate_control_api_t s_temp_rc_api;
|
|
|
|
/* 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_rate_control_api) = &s_temp_rc_api;
|
|
|
|
/*for src rate control state structure*/
|
|
if(e_func_type != GET_NUM_MEMTAB)
|
|
{
|
|
fill_memtab(
|
|
&ps_memtab[i4_mem_tab_idx],
|
|
sizeof(rate_control_api_t),
|
|
MEM_TAB_ALIGNMENT,
|
|
PERSISTENT,
|
|
DDR);
|
|
use_or_fill_base(&ps_memtab[0], (void **)pps_rate_control_api, e_func_type);
|
|
}
|
|
i4_mem_tab_idx++;
|
|
|
|
/* Get the memory requirement of lower modules */
|
|
i4_mem_tab_idx += bit_allocation_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_bit_allocation, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
|
|
i4_mem_tab_idx += cbr_buffer_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_cbr_buffer, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
|
|
i4_mem_tab_idx += est_sad_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_est_sad, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
|
|
i4_mem_tab_idx += mbrc_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_mb_rate_control, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
|
|
i4_mem_tab_idx += vbr_vbv_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_vbr_storage_vbv, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
|
|
i4_mem_tab_idx += init_qp_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_init_qp, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
|
|
i4_mem_tab_idx += sad_acc_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_sad_acc, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
i4_mem_tab_idx += rc_rd_model_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->aps_rd_model[i], &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
}
|
|
i4_mem_tab_idx += pic_handling_num_fill_use_free_memtab(
|
|
&pps_rate_control_api[0]->ps_pic_handling, &ps_memtab[i4_mem_tab_idx], e_func_type);
|
|
return (i4_mem_tab_idx);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function Name : initialise_rate_control
|
|
Description : Initialise the rate control structure
|
|
Inputs : ps_rate_control_api - api struct
|
|
e_rate_control_type - VBR, CBR (NLDRC/LDRC), VBR_STREAMING
|
|
u1_is_mb_level_rc_on - enabling mb level RC
|
|
u4_avg_bit_rate - bit rate to achieved across the entire file size
|
|
u4_peak_bit_rate - max possible drain rate
|
|
u4_frame_rate - number of frames in 1000 seconds
|
|
u4_intra_frame_interval - num frames between two I frames
|
|
*au1_init_qp - init_qp for I,P,B
|
|
|
|
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void initialise_rate_control(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
rc_type_e e_rate_control_type,
|
|
UWORD8 u1_is_mb_level_rc_on,
|
|
UWORD32 u4_avg_bit_rate,
|
|
UWORD32 *pu4_peak_bit_rate,
|
|
UWORD32 u4_min_bit_rate,
|
|
UWORD32 u4_frame_rate,
|
|
UWORD32 u4_max_delay,
|
|
UWORD32 u4_intra_frame_interval,
|
|
UWORD32 u4_idr_period,
|
|
WORD32 *pi4_init_qp,
|
|
UWORD32 u4_max_vbv_buff_size,
|
|
WORD32 i4_max_inter_frm_int,
|
|
WORD32 i4_is_gop_closed,
|
|
WORD32 *pi4_min_max_qp,
|
|
WORD32 i4_use_est_intra_sad,
|
|
UWORD32 u4_src_ticks,
|
|
UWORD32 u4_tgt_ticks,
|
|
WORD32 i4_frame_height,
|
|
WORD32 i4_frame_width,
|
|
WORD32 i4_num_active_pic_type,
|
|
WORD32 i4_field_pic,
|
|
WORD32 i4_quality_preset,
|
|
WORD32 i4_lap_window,
|
|
WORD32 i4_initial_decoder_delay_frames,
|
|
float f_max_peak_rate_sustain_dur,
|
|
LWORD64 i8_num_frames_to_encode,
|
|
UWORD32 u4_min_scd_hevc_qp,
|
|
UWORD8 u1_bit_depth,
|
|
FILE *pf_rc_stat_file,
|
|
WORD32 i4_pass_num,
|
|
void *pv_gop_stat,
|
|
LWORD64 i8_num_gop_mem_alloc,
|
|
WORD32 i4_is_infinite_gop,
|
|
WORD32 i4_size_of_lap_out,
|
|
WORD32 i4_size_of_rc_lap_out,
|
|
void *pv_sys_rc_api,
|
|
WORD32 i4_fp_bit_alloc_in_sp,
|
|
WORD32 i4_num_frame_parallel,
|
|
WORD32 i4_capped_vbr_flag)
|
|
{
|
|
WORD32 i, i4_temp;
|
|
UWORD32 u4_frms_in_delay_prd = (u4_frame_rate * u4_max_delay) / 1000000;
|
|
UWORD32 i4_cbr_bit_alloc_period;
|
|
float f_bit_depth_based_max_qp;
|
|
UWORD32 u4_bit_depth_based_max_qp;
|
|
WORD32 i4_pels_in_frame = (3 * (i4_frame_height * i4_frame_width) >> 1);
|
|
|
|
if(u4_intra_frame_interval ==
|
|
1) /*i_only: Set bit allocation period to 15( currently not configurable) for i only mode*/
|
|
{
|
|
i4_cbr_bit_alloc_period = u4_frame_rate / 1000; /*changed */
|
|
}
|
|
else
|
|
{
|
|
i4_cbr_bit_alloc_period = 1;
|
|
}
|
|
|
|
if(CBR_NLDRC_HBR == e_rate_control_type)
|
|
{
|
|
e_rate_control_type = CBR_NLDRC;
|
|
ps_rate_control_api->i4_is_hbr = 1;
|
|
}
|
|
else
|
|
{
|
|
ps_rate_control_api->i4_is_hbr = 0;
|
|
}
|
|
ps_rate_control_api->e_rc_type = e_rate_control_type;
|
|
ps_rate_control_api->i4_capped_vbr_flag = i4_capped_vbr_flag;
|
|
ps_rate_control_api->u1_is_mb_level_rc_on = u1_is_mb_level_rc_on;
|
|
ps_rate_control_api->i4_num_active_pic_type = i4_num_active_pic_type;
|
|
ps_rate_control_api->i4_quality_preset = i4_quality_preset;
|
|
ps_rate_control_api->i4_scd_I_frame_estimated_tot_bits = 0;
|
|
ps_rate_control_api->i4_I_frame_qp_model = 0;
|
|
ps_rate_control_api->u4_min_scd_hevc_qp = u4_min_scd_hevc_qp;
|
|
ps_rate_control_api->pf_rc_stat_file = pf_rc_stat_file;
|
|
ps_rate_control_api->i4_rc_pass = i4_pass_num;
|
|
ps_rate_control_api->i4_max_frame_height = i4_frame_height;
|
|
ps_rate_control_api->i4_max_frame_width = i4_frame_width;
|
|
ps_rate_control_api->i4_underflow_warning = 0;
|
|
ps_rate_control_api->f_p_to_i_comp_ratio = 1.0f;
|
|
ps_rate_control_api->i4_scd_in_period_2_pass = 0;
|
|
ps_rate_control_api->i4_is_infinite_gop = i4_is_infinite_gop;
|
|
ps_rate_control_api->i4_frames_since_last_scd = 0;
|
|
ps_rate_control_api->i4_num_frame_parallel = i4_num_frame_parallel;
|
|
|
|
/*The memory for gop level summary struct is stored only for 2 pass*/
|
|
if(i4_pass_num == 2)
|
|
{
|
|
ps_rate_control_api->pv_2pass_gop_summary = pv_gop_stat;
|
|
}
|
|
else
|
|
{
|
|
ps_rate_control_api->pv_2pass_gop_summary = NULL;
|
|
}
|
|
/*Initialize the call back funcitons for file related operations*/
|
|
ps_rate_control_api->pv_rc_sys_api = pv_sys_rc_api;
|
|
|
|
ps_rate_control_api->u1_bit_depth = u1_bit_depth;
|
|
|
|
f_bit_depth_based_max_qp = (float)((51 + (6 * (u1_bit_depth - 8))) - 4) / 6;
|
|
u4_bit_depth_based_max_qp = (UWORD32)pow(2.0f, f_bit_depth_based_max_qp);
|
|
|
|
ps_rate_control_api->u4_bit_depth_based_max_qp = u4_bit_depth_based_max_qp;
|
|
|
|
trace_printf("RC type = %d\n", e_rate_control_type);
|
|
|
|
/* Set the avg_bitrate_changed flag for each pic_type to 0 */
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
ps_rate_control_api->au1_avg_bitrate_changed[i] = 0;
|
|
}
|
|
|
|
/* Initialize the pic_handling module */
|
|
init_pic_handling(
|
|
ps_rate_control_api->ps_pic_handling, /*ps_pic_handling*/
|
|
(WORD32)u4_intra_frame_interval, /*i4_intra_frm_int,*/
|
|
i4_max_inter_frm_int, /*i4_max_inter_frm_int,*/
|
|
i4_is_gop_closed,
|
|
(WORD32)u4_idr_period,
|
|
ps_rate_control_api->i4_num_active_pic_type,
|
|
i4_field_pic); /*gop_struct_e*/
|
|
|
|
/* initialise the init Qp module */
|
|
init_init_qp(
|
|
ps_rate_control_api->ps_init_qp,
|
|
pi4_min_max_qp,
|
|
i4_pels_in_frame,
|
|
ps_rate_control_api->i4_is_hbr);
|
|
|
|
/*** Initialize the rate control modules ***/
|
|
if(ps_rate_control_api->e_rc_type != CONST_QP)
|
|
{
|
|
UWORD32 au4_num_pics_in_delay_prd[MAX_PIC_TYPE] = { 0 };
|
|
|
|
/* Initialise the model parameter structures */
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
init_frm_rc_rd_model(ps_rate_control_api->aps_rd_model[i], MAX_FRAMES_MODELLED);
|
|
}
|
|
|
|
/* Initialize the buffer mechanism */
|
|
if((ps_rate_control_api->e_rc_type == VBR_STORAGE) ||
|
|
(ps_rate_control_api->e_rc_type == VBR_STORAGE_DVD_COMP))
|
|
{
|
|
/* Assuming both the peak bit rates are same for a VBR_STORAGE and
|
|
VBR_STORAGE_DVD_COMP */
|
|
if(pu4_peak_bit_rate[0] != pu4_peak_bit_rate[1])
|
|
{
|
|
trace_printf("For VBR_STORAGE and VBR_STORAGE_DVD_COMP the peak bit "
|
|
"rates should be same\n");
|
|
}
|
|
init_vbr_vbv(
|
|
ps_rate_control_api->ps_vbr_storage_vbv,
|
|
(WORD32)pu4_peak_bit_rate[0],
|
|
(WORD32)u4_frame_rate,
|
|
(WORD32)u4_max_vbv_buff_size);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == CBR_NLDRC)
|
|
{
|
|
UWORD32 u4_avg_bit_rate_copy[MAX_NUM_DRAIN_RATES];
|
|
for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
|
|
{
|
|
u4_avg_bit_rate_copy[i] = u4_avg_bit_rate;
|
|
}
|
|
|
|
init_cbr_buffer(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
u4_max_delay,
|
|
u4_frame_rate,
|
|
u4_avg_bit_rate,
|
|
au4_num_pics_in_delay_prd,
|
|
u4_max_vbv_buff_size,
|
|
u4_intra_frame_interval,
|
|
ps_rate_control_api->e_rc_type,
|
|
pu4_peak_bit_rate[0],
|
|
i4_initial_decoder_delay_frames,
|
|
f_max_peak_rate_sustain_dur,
|
|
i8_num_frames_to_encode,
|
|
i4_max_inter_frm_int,
|
|
i4_pass_num,
|
|
0 /*capped vbr off */);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == VBR_STREAMING)
|
|
{
|
|
init_vbv_str_prms(
|
|
&ps_rate_control_api->s_vbr_str_prms,
|
|
u4_intra_frame_interval,
|
|
u4_src_ticks,
|
|
u4_tgt_ticks,
|
|
u4_frms_in_delay_prd);
|
|
|
|
init_cbr_buffer(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
u4_max_delay,
|
|
u4_frame_rate,
|
|
u4_avg_bit_rate,
|
|
au4_num_pics_in_delay_prd,
|
|
u4_max_vbv_buff_size,
|
|
u4_intra_frame_interval,
|
|
ps_rate_control_api->e_rc_type,
|
|
pu4_peak_bit_rate[0],
|
|
i4_initial_decoder_delay_frames,
|
|
f_max_peak_rate_sustain_dur,
|
|
i8_num_frames_to_encode,
|
|
i4_max_inter_frm_int,
|
|
i4_pass_num,
|
|
ps_rate_control_api->i4_capped_vbr_flag);
|
|
}
|
|
|
|
/* Initalise the SAD estimation module */
|
|
init_est_sad(ps_rate_control_api->ps_est_sad, i4_use_est_intra_sad);
|
|
|
|
/* Initialise the bit allocation module according to VBR or CBR */
|
|
if((ps_rate_control_api->e_rc_type == VBR_STORAGE) ||
|
|
(ps_rate_control_api->e_rc_type == VBR_STREAMING) ||
|
|
(ps_rate_control_api->e_rc_type == VBR_STORAGE_DVD_COMP))
|
|
{
|
|
/*UWORD32 u4_scaled_avg_bit_rate;*/
|
|
/*X_PROD_Y_DIV_Z (u4_avg_bit_rate,1126,1024,u4_scaled_avg_bit_rate);*/
|
|
init_bit_allocation(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
i4_cbr_bit_alloc_period,
|
|
u4_avg_bit_rate /*u4_scaled_avg_bit_rate*/,
|
|
u4_frame_rate,
|
|
(WORD32 *)pu4_peak_bit_rate,
|
|
u4_min_bit_rate,
|
|
i4_pels_in_frame,
|
|
ps_rate_control_api->i4_is_hbr,
|
|
ps_rate_control_api->i4_num_active_pic_type,
|
|
i4_lap_window,
|
|
i4_field_pic,
|
|
i4_pass_num,
|
|
(i4_frame_height * i4_frame_width),
|
|
i4_fp_bit_alloc_in_sp);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == CBR_NLDRC)
|
|
{
|
|
init_bit_allocation(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
i4_cbr_bit_alloc_period, //i_onlyCBR_BIT_ALLOC_PERIOD,
|
|
u4_avg_bit_rate,
|
|
u4_frame_rate,
|
|
(WORD32 *)pu4_peak_bit_rate,
|
|
u4_min_bit_rate,
|
|
i4_pels_in_frame,
|
|
ps_rate_control_api->i4_is_hbr,
|
|
ps_rate_control_api->i4_num_active_pic_type,
|
|
i4_lap_window,
|
|
i4_field_pic,
|
|
i4_pass_num,
|
|
(i4_frame_height * i4_frame_width),
|
|
i4_fp_bit_alloc_in_sp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UWORD32 au4_num_pics_in_delay_prd[MAX_PIC_TYPE];
|
|
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
au4_num_pics_in_delay_prd[i] = 0;
|
|
|
|
init_cbr_buffer(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
u4_max_delay,
|
|
u4_frame_rate,
|
|
u4_avg_bit_rate,
|
|
au4_num_pics_in_delay_prd,
|
|
u4_max_vbv_buff_size,
|
|
u4_intra_frame_interval,
|
|
ps_rate_control_api->e_rc_type,
|
|
pu4_peak_bit_rate[0],
|
|
i4_initial_decoder_delay_frames,
|
|
f_max_peak_rate_sustain_dur,
|
|
i8_num_frames_to_encode,
|
|
i4_max_inter_frm_int,
|
|
i4_pass_num,
|
|
0 /*capped vbr off */);
|
|
}
|
|
|
|
/* Initialize the init_qp */
|
|
for(i4_temp = 0; i4_temp < MAX_SCENE_NUM_RC; i4_temp++)
|
|
{
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_temp][i] = 0x7FFFFFFF; //pi4_init_qp[i];
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_temp][i] =
|
|
0x7FFFFFFF; //pi4_init_qp[i] << QSCALE_Q_FAC;
|
|
ps_rate_control_api->ai4_min_qp[i] = pi4_min_max_qp[(i << 1)];
|
|
ps_rate_control_api->ai4_max_qp[i] = pi4_min_max_qp[(i << 1) + 1];
|
|
}
|
|
}
|
|
/*init min and max qp in qscale*/
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
ps_rate_control_api->ai4_min_qp_q6[i] = MIN_QSCALE_Q6;
|
|
//ps_rate_control_api->ai4_max_qp_q6[i] = (228 << QSCALE_Q_FAC);
|
|
ps_rate_control_api->ai4_max_qp_q6[i] = (u4_bit_depth_based_max_qp << QSCALE_Q_FAC);
|
|
}
|
|
|
|
/* Initialize the is_first_frm_encoded */
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
ps_rate_control_api->au1_is_first_frm_coded[i] = 0;
|
|
}
|
|
ps_rate_control_api->u1_is_first_frm = 1;
|
|
ps_rate_control_api->i4_prev_ref_is_scd = 0;
|
|
|
|
for(i = 0; i < MAX_NUM_FRAME_PARALLEL; i++)
|
|
{
|
|
ps_rate_control_api->ai4_est_tot_bits[i] =
|
|
get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
}
|
|
|
|
/* Control flag for delayed impact after a change in peak bitrate has been made */
|
|
ps_rate_control_api->u4_frms_in_delay_prd_for_peak_bit_rate_change = 0;
|
|
for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
|
|
{
|
|
ps_rate_control_api->au4_new_peak_bit_rate[i] = pu4_peak_bit_rate[i];
|
|
}
|
|
|
|
/* initialise the mb level rate control module */
|
|
init_mb_level_rc(ps_rate_control_api->ps_mb_rate_control);
|
|
ps_rate_control_api->i4_prev_frm_est_bits = u4_avg_bit_rate / (u4_frame_rate / 1000);
|
|
|
|
ps_rate_control_api->prev_ref_pic_type = I_PIC;
|
|
ps_rate_control_api->i4_P_to_I_ratio = (1 << (P_TO_I_RATIO_Q_FACTOR + K_Q)) / I_TO_P_RATIO;
|
|
|
|
/* Initialise sad accumulator */
|
|
init_sad_acc(ps_rate_control_api->ps_sad_acc);
|
|
|
|
rc_get_max_hme_sad_per_pixel(ps_rate_control_api, i4_frame_height * i4_frame_width);
|
|
}
|
|
#endif /* #if NON_STEADSTATE_CODE */
|
|
|
|
/****************************************************************************
|
|
*Function Name : add_picture_to_stack
|
|
*Description : calls add_pic_to_stack
|
|
*Inputs :
|
|
*Globals :
|
|
*Processing :
|
|
*Outputs :
|
|
*Returns :
|
|
*Issues :
|
|
*Revision History:d
|
|
*DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*
|
|
*****************************************************************************/
|
|
void add_picture_to_stack(
|
|
rate_control_api_t *rate_control_api, WORD32 i4_enc_pic_id, WORD32 i4_rc_in_pic)
|
|
{
|
|
/* Call the routine to add the pic to stack in encode order */
|
|
add_pic_to_stack(rate_control_api->ps_pic_handling, i4_enc_pic_id, i4_rc_in_pic);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : add_picture_to_stack_re_enc
|
|
Description :
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void add_picture_to_stack_re_enc(
|
|
rate_control_api_t *rate_control_api, WORD32 i4_enc_pic_id, picture_type_e e_pic_type)
|
|
{
|
|
/* In case of a re-encoder, the pics will come in the encode order itself.
|
|
So, there is no need to buffer the pics up */
|
|
add_pic_to_stack_re_enc(rate_control_api->ps_pic_handling, i4_enc_pic_id, e_pic_type);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_picture_details
|
|
Description : decides the picture type based on the state
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void get_picture_details(
|
|
rate_control_handle rate_control_api,
|
|
WORD32 *pi4_pic_id,
|
|
WORD32 *pi4_pic_disp_order_no,
|
|
picture_type_e *pe_pic_type,
|
|
WORD32 *pi4_is_scd)
|
|
{
|
|
/* Call to get the pic_details */
|
|
get_pic_from_stack(
|
|
rate_control_api->ps_pic_handling,
|
|
pi4_pic_id,
|
|
pi4_pic_disp_order_no,
|
|
pe_pic_type,
|
|
pi4_is_scd);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_min_max_bits_based_on_buffer
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
static void get_min_max_bits_based_on_buffer(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
WORD32 *pi4_min_bits,
|
|
WORD32 *pi4_max_bits,
|
|
WORD32 i4_get_error)
|
|
{
|
|
WORD32 i4_min_bits = 0, i4_max_bits = 0;
|
|
|
|
cbr_modify_ebf_estimate(ps_rate_control_api->ps_cbr_buffer, i4_get_error); //ELP_RC
|
|
|
|
/* Find the min and max bits that can be consumed based on the buffer condition */
|
|
if(ps_rate_control_api->e_rc_type == VBR_STORAGE)
|
|
{
|
|
i4_max_bits = get_max_target_bits(ps_rate_control_api->ps_vbr_storage_vbv);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == VBR_STORAGE_DVD_COMP)
|
|
{
|
|
WORD32 i4_rem_bits_in_gop, i4_rem_frms_in_gop;
|
|
/* WORD32 ai4_rem_frms_in_gop[MAX_PIC_TYPE]; */
|
|
i4_rem_frms_in_gop = pic_type_get_rem_frms_in_gop(ps_rate_control_api->ps_pic_handling);
|
|
i4_rem_bits_in_gop = rc_get_rem_bits_in_period(ps_rate_control_api);
|
|
|
|
i4_max_bits = get_max_tgt_bits_dvd_comp(
|
|
ps_rate_control_api->ps_vbr_storage_vbv,
|
|
i4_rem_bits_in_gop,
|
|
i4_rem_frms_in_gop,
|
|
e_pic_type);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == CBR_NLDRC)
|
|
{
|
|
cbr_buffer_constraint_check(
|
|
ps_rate_control_api->ps_cbr_buffer, 0, e_pic_type, &i4_max_bits, &i4_min_bits);
|
|
}
|
|
else /* if(ps_rate_control_api->e_rc_type == VBR_STREAMING) */
|
|
{
|
|
vbr_stream_buffer_constraint_check(
|
|
ps_rate_control_api->ps_cbr_buffer, 0, e_pic_type, &i4_max_bits, &i4_min_bits);
|
|
}
|
|
/* Fill the min and max bits consumed */
|
|
if(1 != ps_rate_control_api->i4_capped_vbr_flag)
|
|
{
|
|
pi4_min_bits[0] = i4_min_bits;
|
|
}
|
|
else
|
|
{
|
|
/* Capped VBR case */
|
|
pi4_min_bits[0] = 0;
|
|
}
|
|
pi4_max_bits[0] = i4_max_bits;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : is_first_frame_coded
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 is_first_frame_coded(rate_control_handle ps_rate_control_api)
|
|
{
|
|
WORD32 i4_is_first_frame_coded = 1, i;
|
|
/* Check whether atleast one frame of a each picture type gets encoded */
|
|
/* Check whether it is an IPP or IPB kind of encoding */
|
|
if(pic_type_get_intra_frame_interval(ps_rate_control_api->ps_pic_handling) == 1)
|
|
{
|
|
i4_is_first_frame_coded = ps_rate_control_api->au1_is_first_frm_coded[I_PIC];
|
|
}
|
|
else /*HEVC_hierarchy*/
|
|
{
|
|
if(pic_type_get_field_pic(ps_rate_control_api->ps_pic_handling))
|
|
{
|
|
i4_is_first_frame_coded &= ps_rate_control_api->au1_is_first_frm_coded[I_PIC];
|
|
|
|
for(i = 1; i < ps_rate_control_api->i4_num_active_pic_type; i++)
|
|
{
|
|
i4_is_first_frame_coded &= ps_rate_control_api->au1_is_first_frm_coded[i];
|
|
i4_is_first_frame_coded &=
|
|
ps_rate_control_api->au1_is_first_frm_coded[i + FIELD_OFFSET];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i = 0; i < ps_rate_control_api->i4_num_active_pic_type; i++)
|
|
{
|
|
i4_is_first_frame_coded &= ps_rate_control_api->au1_is_first_frm_coded[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return i4_is_first_frame_coded;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_min_max_qp
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
|
|
static void get_min_max_qp(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
WORD32 *pi4_hi_dev_qp_q6,
|
|
WORD32 *pi4_lo_dev_qp_q6,
|
|
WORD32 i4_complexity_bin,
|
|
WORD32 i4_scene_num)
|
|
{
|
|
WORD32 prev_qp_q6, prev_I_qp_q6;
|
|
WORD32 hi_dev_qp_q6, lo_dev_qp_q6, hi_dev_qp_temp_q6;
|
|
WORD32 i4_intra_frm_int, prev_qp_for_high_dev_q6,
|
|
use_I_frame_qp_high_dev = 0; /*i_only : to detect i only case*/
|
|
float per_pixel_p_hme_sad =
|
|
(float)ps_rate_control_api->i8_per_pixel_p_frm_hme_sad_q10 / (1 << 10);
|
|
|
|
i4_intra_frm_int = pic_type_get_intra_frame_interval(ps_rate_control_api->ps_pic_handling);
|
|
|
|
/* Restricting the Quant swing */
|
|
prev_qp_q6 = ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][ps_rate_control_api->prev_ref_pic_type];
|
|
prev_qp_for_high_dev_q6 = prev_qp_q6;
|
|
prev_I_qp_q6 = ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC];
|
|
if(ps_rate_control_api->prev_ref_pic_type != e_pic_type)
|
|
{
|
|
if(e_pic_type == I_PIC)
|
|
{
|
|
/* Constrain I-frame QP to be within specified limit of prev_ref_qp/Kp */
|
|
// SS - suppressing this assuming re-encode will take care
|
|
/* prev_qp = i4_frame_qp; */
|
|
prev_qp_q6 = (ps_rate_control_api->i4_P_to_I_ratio * (LWORD64)prev_qp_q6) >>
|
|
P_TO_I_RATIO_Q_FACTOR;
|
|
}
|
|
else if(e_pic_type == P_PIC || e_pic_type == P1_PIC)
|
|
{
|
|
/* Constrain P-frame QP to be within specified limit of Kp*prev_ref_qp */
|
|
prev_qp_q6 = (I_TO_P_RATIO * (LWORD64)prev_qp_q6) >> K_Q;
|
|
use_I_frame_qp_high_dev = 1;
|
|
}
|
|
else if(ps_rate_control_api->prev_ref_pic_type == P_PIC)
|
|
{
|
|
/* current frame is B-pic */
|
|
/* Constrain B-frame QP to be within specified limit of prev_ref_qp/Kb */
|
|
if(!ps_rate_control_api->i4_is_hbr)
|
|
{
|
|
prev_qp_q6 = (P_TO_B_RATIO * (LWORD64)prev_qp_q6) >> (K_Q);
|
|
}
|
|
else
|
|
{
|
|
prev_qp_q6 = (P_TO_B_RATIO_HBR * (LWORD64)prev_qp_q6) >> (K_Q);
|
|
}
|
|
}
|
|
else /* if(ps_rate_control_api->prev_ref_pic_type == I_PIC) */
|
|
{
|
|
/* current frame is B-pic */
|
|
/* Constrain B-frame QP to be within specified limit of prev_ref_qp/Kb */
|
|
if(!ps_rate_control_api->i4_is_hbr)
|
|
{
|
|
prev_qp_q6 = (P_TO_B_RATIO * I_TO_P_RATIO * (LWORD64)prev_qp_q6) >> (K_Q + K_Q);
|
|
}
|
|
else
|
|
{
|
|
prev_qp_q6 = (P_TO_B_RATIO_HBR * I_TO_P_RATIO * (LWORD64)prev_qp_q6) >> (K_Q + K_Q);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*if (1)//e_pic_type != B_PIC)*/
|
|
{
|
|
if(use_I_frame_qp_high_dev)
|
|
{
|
|
/*For P pic if previous reference was I then pre_qp = I qp + 1, Then +4 high dev is allowed. To avoid P frame to be +5 off comapared to previous I*/
|
|
hi_dev_qp_q6 = GET_HI_DEV_QP_QFAC(prev_qp_for_high_dev_q6);
|
|
}
|
|
else
|
|
{
|
|
hi_dev_qp_q6 = GET_HI_DEV_QP_QFAC(prev_qp_q6);
|
|
}
|
|
|
|
if(e_pic_type == I_PIC || e_pic_type == P_PIC || e_pic_type == P1_PIC)
|
|
{
|
|
lo_dev_qp_q6 =
|
|
GET_LO_DEV_QP_QFAC(prev_qp_q6, ps_rate_control_api->i4_num_active_pic_type);
|
|
}
|
|
else
|
|
{
|
|
lo_dev_qp_q6 = GET_LO_DEV_QP_QFAC_B_PIC(prev_qp_q6);
|
|
}
|
|
}
|
|
/* For lower QPs due to scale factor and fixed point arithmetic, the
|
|
hi_dev_qp can be same as that of the prev qp and in which case it gets stuck
|
|
in the lower most qp and thus not allowing QPs not to change. To avoid this,
|
|
for lower qps the hi_dev_qp should be made slightly more than prev_qp */
|
|
if(prev_qp_q6 == hi_dev_qp_q6)
|
|
{
|
|
hi_dev_qp_q6 = ((LWORD64)hi_dev_qp_q6 * 18) >> 4;
|
|
}
|
|
/*minimum qp should atleast be 1 less than previous*/
|
|
if(prev_qp_q6 == lo_dev_qp_q6 && lo_dev_qp_q6 > (1 << QSCALE_Q_FAC))
|
|
{
|
|
lo_dev_qp_q6 = ((LWORD64)lo_dev_qp_q6 * 14) >> 4;
|
|
}
|
|
/*for shorter GOP make sure the P does not get better than I , NEED TO BE REVIEWED as gains seen in bq terrace after this change was with wrong config*/
|
|
/*Anything with per pixel sad < 1 is considered static. Since the hme sad is at L1 resolution, the threshold chosen is 0.25*/
|
|
if((per_pixel_p_hme_sad < 0.25f) && (ps_rate_control_api->i4_is_infinite_gop != 1))
|
|
{
|
|
if(e_pic_type == P_PIC && ps_rate_control_api->i4_I_frame_qp_model)
|
|
{
|
|
/*P is not allowed to get too better compared to previous I in static content*/
|
|
if(lo_dev_qp_q6<(prev_I_qp_q6 * 14)>> 4)
|
|
lo_dev_qp_q6 = ((LWORD64)prev_I_qp_q6 * 14) >> 4;
|
|
/*If previous reference is I then it cannot get better than I in static case*/
|
|
if(lo_dev_qp_q6 < prev_I_qp_q6)
|
|
lo_dev_qp_q6 = prev_I_qp_q6;
|
|
}
|
|
}
|
|
if(e_pic_type == I_PIC &&
|
|
i4_intra_frm_int !=
|
|
1) /*i_only: In this case P frame Qp will be arbitrary value hence avoiding max_dev_qp to be independent of it*/
|
|
{
|
|
//WORD32 i4_p_qp = ps_rate_control_api->ai4_prev_frm_qp[P_PIC];
|
|
WORD32 i4_p_qp_q6 = ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][P_PIC];
|
|
switch(i4_complexity_bin)
|
|
{
|
|
case 0:
|
|
hi_dev_qp_temp_q6 = (WORD32)(
|
|
((LWORD64)i4_p_qp_q6 * I_TO_P_RATIO * I_TO_P_RATIO * I_TO_P_RATIO) >>
|
|
(K_Q + K_Q + K_Q));
|
|
break;
|
|
case 1:
|
|
hi_dev_qp_temp_q6 =
|
|
(WORD32)(((LWORD64)i4_p_qp_q6 * I_TO_P_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q));
|
|
break;
|
|
case 2:
|
|
hi_dev_qp_temp_q6 = (WORD32)(((LWORD64)i4_p_qp_q6 * I_TO_P_RATIO) >> (K_Q));
|
|
break;
|
|
case 3:
|
|
hi_dev_qp_temp_q6 = i4_p_qp_q6;
|
|
break;
|
|
default:
|
|
hi_dev_qp_temp_q6 = (WORD32)(((LWORD64)i4_p_qp_q6 * P_TO_I_RATIO) >> (K_Q));
|
|
break;
|
|
}
|
|
hi_dev_qp_q6 = (hi_dev_qp_q6 > hi_dev_qp_temp_q6) ? hi_dev_qp_temp_q6 : hi_dev_qp_q6;
|
|
}
|
|
pi4_hi_dev_qp_q6[0] = hi_dev_qp_q6;
|
|
pi4_lo_dev_qp_q6[0] = lo_dev_qp_q6;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_min
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
static WORD32 get_min(WORD32 a, WORD32 b, WORD32 c, WORD32 d)
|
|
{
|
|
WORD32 min = a;
|
|
if(b < min)
|
|
min = b;
|
|
if(c < min)
|
|
min = c;
|
|
if(d < min)
|
|
min = d;
|
|
return min;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_max
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
static WORD32 get_max(WORD32 a, WORD32 b, WORD32 c)
|
|
{
|
|
WORD32 max = a;
|
|
if(b > max)
|
|
max = b;
|
|
if(c > max)
|
|
max = c;
|
|
return max;
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_modify_est_tot
|
|
Description : Adds latest Estimated total bits to the loop .
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void rc_modify_est_tot(rate_control_api_t *ps_rate_control_api, WORD32 i4_tot_est_bits) //ELP_RC
|
|
{
|
|
WORD32 i4_num_frm_parallel, i;
|
|
i4_num_frm_parallel = ps_rate_control_api->i4_num_frame_parallel;
|
|
|
|
if(i4_num_frm_parallel) //for CPU i4_num_frm_parallel=0
|
|
{
|
|
for(i = 1; i < (i4_num_frm_parallel - 1); i++)
|
|
{
|
|
ps_rate_control_api->ai4_est_tot_bits[i - 1] = ps_rate_control_api->ai4_est_tot_bits[i];
|
|
}
|
|
ps_rate_control_api->ai4_est_tot_bits[i - 1] = i4_tot_est_bits;
|
|
}
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_estimate_bit_error
|
|
Description : function returns the estimated bit error using estimated total
|
|
bits for the Enc Loop Parallelism based Encoder.
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
static WORD32 rc_get_estimate_bit_error(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
WORD32 i4_error_bits = 0, i, i4_bits_per_frame;
|
|
i4_bits_per_frame = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
if(ps_rate_control_api->i4_num_frame_parallel >
|
|
0) // for CPU ps_rate_control_api->i4_num_frame_parallel =0;
|
|
{
|
|
for(i = 0; i < (ps_rate_control_api->i4_num_frame_parallel - 1); i++)
|
|
{
|
|
i4_error_bits += (ps_rate_control_api->ai4_est_tot_bits[i] - i4_bits_per_frame);
|
|
}
|
|
}
|
|
return i4_error_bits;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_est_hdr_bits
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 get_est_hdr_bits(rate_control_api_t *ps_rate_control_api, picture_type_e e_pic_type)
|
|
{
|
|
return (get_cur_frm_est_header_bits(ps_rate_control_api->ps_bit_allocation, e_pic_type));
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : model_availability
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 model_availability(rate_control_api_t *ps_rate_control_api, picture_type_e e_pic_type)
|
|
{
|
|
return (is_model_valid(ps_rate_control_api->aps_rd_model[e_pic_type]));
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : clip_qp_based_on_prev_ref
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 clip_qp_based_on_prev_ref(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
WORD32 i4_call_type,
|
|
WORD32 i4_scene_num)
|
|
{
|
|
/* WORD32 i4_bpp_based_qp; */
|
|
/* If the number pf pels is set to zero it uses the value set during init time */
|
|
/* i4_frame_qp = get_init_qp_using_pels_bits_per_frame(ps_rate_control_api->ps_init_qp,
|
|
e_pic_type, i4_est_tex_bits, 0); */
|
|
WORD32 i4_frame_qp, i4_frame_qp_q6 = 0, i4_min_Kp_Kb_factor = 0;
|
|
WORD32 Kp_kb_factor = get_Kp_Kb(ps_rate_control_api->ps_bit_allocation, e_pic_type);
|
|
WORD32 kp_kb_ref_ref =
|
|
get_Kp_Kb(ps_rate_control_api->ps_bit_allocation, ps_rate_control_api->prev_ref_pic_type);
|
|
|
|
{
|
|
WORD32 i4_drain_bits_per_frame = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer),
|
|
i4_ebf;
|
|
WORD32 i4_delay = cbr_get_delay_frames(ps_rate_control_api->ps_cbr_buffer),
|
|
max_buffer_level = 0, rc_type = get_rc_type(ps_rate_control_api->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_rate_control_api->ps_cbr_buffer);
|
|
|
|
i4_ebf = get_cbr_ebf(ps_rate_control_api->ps_cbr_buffer);
|
|
|
|
if(i4_ebf > (WORD32)(0.9f * max_buffer_level))
|
|
{
|
|
switch(e_pic_type)
|
|
{
|
|
case P_PIC:
|
|
case P1_PIC:
|
|
i4_min_Kp_Kb_factor = I_TO_P_RATIO;
|
|
break;
|
|
case B_PIC:
|
|
case BB_PIC:
|
|
i4_min_Kp_Kb_factor = I_TO_B_RATIO;
|
|
break;
|
|
case B1_PIC:
|
|
case B11_PIC:
|
|
i4_min_Kp_Kb_factor = I_TO_B1_RATIO;
|
|
break;
|
|
default:
|
|
i4_min_Kp_Kb_factor = I_TO_B2_RATIO;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if((e_pic_type == I_PIC) &&
|
|
(ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] == 0x7FFFFFFF))
|
|
{
|
|
/*Is this a valid case?*/
|
|
ASSERT(0);
|
|
}
|
|
/*If there is a scene cut I frame followed by a scene cut I frame, non scene cut I frame
|
|
better assume the Qp of the I frame same as before instead of using bpp based qp*/
|
|
else if(
|
|
(e_pic_type == I_PIC) &&
|
|
(ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] != 0x7FFFFFFF))
|
|
{
|
|
i4_frame_qp = ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC];
|
|
i4_frame_qp_q6 = ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC];
|
|
}
|
|
else /*! ISlice*/
|
|
{
|
|
if((Kp_kb_factor < i4_min_Kp_Kb_factor) && (i4_call_type == 1))
|
|
{
|
|
Kp_kb_factor = i4_min_Kp_Kb_factor;
|
|
trace_printf("Kp_kb_factor %d", Kp_kb_factor);
|
|
}
|
|
if((kp_kb_ref_ref > Kp_kb_factor) && (i4_call_type == 1))
|
|
{
|
|
kp_kb_ref_ref = Kp_kb_factor;
|
|
}
|
|
|
|
if(ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][ps_rate_control_api->prev_ref_pic_type] ==
|
|
0x7FFFFFFF)
|
|
{
|
|
ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][ps_rate_control_api->prev_ref_pic_type] =
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC];
|
|
kp_kb_ref_ref = 16;
|
|
}
|
|
|
|
i4_frame_qp_q6 =
|
|
((ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][ps_rate_control_api->prev_ref_pic_type] *
|
|
Kp_kb_factor) /
|
|
kp_kb_ref_ref);
|
|
}
|
|
return i4_frame_qp_q6;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_frame_level_qp
|
|
Description : Get frame qp from the estimated bits
|
|
Inputs : ps_rate_control_api
|
|
i_to_avg_ratio
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 get_frame_level_qp(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
WORD32 i4_ud_max_bits,
|
|
WORD32 *pi4_cur_est_texture_bits,
|
|
float af_sum_weigh[MAX_PIC_TYPE][3],
|
|
WORD32 i4_call_type,
|
|
float i_to_avg_ratio,
|
|
frame_info_t *ps_frame_stat,
|
|
WORD32 i4_complexity_bin,
|
|
WORD32 i4_scene_num,
|
|
WORD32 *pi4_tot_bits_estimated,
|
|
WORD32 *pi4_is_model_valid,
|
|
WORD32 *pi4_vbv_buf_max_bits,
|
|
WORD32 *pi4_est_tex_bits,
|
|
WORD32 *pi4_cur_est_header_bits,
|
|
WORD32 *pi4_maxEbfQP,
|
|
WORD32 *pi4_modelQP,
|
|
WORD32 *pi4_estimate_to_calc_frm_error)
|
|
{
|
|
/* UWORD8 u1_frame_qp; */
|
|
WORD32 i4_frame_qp /*,i4_min_frame_qp = 1,i4_max_frame_qp = MAX_MPEG2_QP*/;
|
|
WORD32 i4_max_frame_qp_q6 = (MAX_MPEG2_QP << QSCALE_Q_FAC),
|
|
i4_min_frame_qp_q6 = MIN_QSCALE_Q6; /*0.707 in q6 corresponds to hevc qp = 1*/
|
|
WORD32 i4_is_first_frame_coded = 1;
|
|
WORD32 i4_is_model_valid = 0;
|
|
WORD32 i4_frame_qp_q6, i4_cur_est_header_bits, i4_frame_qp_q6_based_max_vbv_bits;
|
|
WORD32 i4_bit_alloc_est_tex_bits = 0, i4_bit_alloc_est_tex_bits_for_invalid_model = 0,
|
|
i4_est_tex_bits, i4_qp_based_min_est_tex_bits, i4_qp_based_max_est_tex_bits,
|
|
i4_buf_based_min_bits, i4_buf_based_max_bits;
|
|
UWORD32 u4_estimated_sad;
|
|
WORD32 i4_buffer_based_max_qp_clip_flag = 0;
|
|
WORD32 i4_min_Kp_Kb_factor = 0;
|
|
WORD32 i4_steady_state_texture_case = 0;
|
|
|
|
if(i4_call_type == 1)
|
|
{
|
|
*pi4_maxEbfQP = INVALID_QP;
|
|
*pi4_modelQP = INVALID_QP;
|
|
}
|
|
|
|
if((ps_rate_control_api->e_rc_type != VBR_STORAGE) &&
|
|
(ps_rate_control_api->e_rc_type != VBR_STORAGE_DVD_COMP) &&
|
|
(ps_rate_control_api->e_rc_type != CBR_NLDRC) &&
|
|
(ps_rate_control_api->e_rc_type != CONST_QP) &&
|
|
(ps_rate_control_api->e_rc_type != VBR_STREAMING))
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
i4_is_first_frame_coded = is_first_frame_coded(ps_rate_control_api);
|
|
|
|
assign_complexity_coeffs(ps_rate_control_api->ps_bit_allocation, af_sum_weigh);
|
|
|
|
if(ps_rate_control_api->e_rc_type == CONST_QP)
|
|
{
|
|
i4_frame_qp = ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][e_pic_type];
|
|
i4_frame_qp_q6 =
|
|
(ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][e_pic_type] >> QSCALE_Q_FAC);
|
|
}
|
|
else
|
|
{
|
|
i4_cur_est_header_bits =
|
|
get_cur_frm_est_header_bits(ps_rate_control_api->ps_bit_allocation, e_pic_type);
|
|
u4_estimated_sad = get_est_sad(ps_rate_control_api->ps_est_sad, e_pic_type);
|
|
/* Constraining the qp variations based on bits allocated */
|
|
/* Step 1: Getting the bits based on bit allocation module */
|
|
/*check if model has atleast one data point, otherwise go with default qp*/
|
|
i4_is_model_valid = is_model_valid(ps_rate_control_api->aps_rd_model[e_pic_type]);
|
|
|
|
if(i4_is_model_valid == 1)
|
|
{
|
|
i4_bit_alloc_est_tex_bits = get_cur_frm_est_texture_bits(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->aps_rd_model,
|
|
ps_rate_control_api->ps_est_sad,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
e_pic_type,
|
|
i4_is_first_frame_coded,
|
|
0,
|
|
i4_call_type,
|
|
i_to_avg_ratio,
|
|
i4_is_model_valid);
|
|
if(i4_call_type == 1)
|
|
{
|
|
*pi4_estimate_to_calc_frm_error =
|
|
i4_bit_alloc_est_tex_bits + i4_cur_est_header_bits;
|
|
}
|
|
|
|
/* vbv buffer position based error correction to keep away encoder buffer overflow at layer 0 pictures*/
|
|
if(e_pic_type == I_PIC || e_pic_type == P_PIC || e_pic_type == P1_PIC)
|
|
{
|
|
WORD32 i4_cur_ebf = get_cbr_ebf(ps_rate_control_api->ps_cbr_buffer);
|
|
WORD32 i4_vbv_size = get_cbr_buffer_size(ps_rate_control_api->ps_cbr_buffer);
|
|
WORD32 i4_max_ebf = (WORD32)(i4_vbv_size * MAX_THRESHOLD_VBV_FRM_ERROR);
|
|
WORD32 i4_drain_rate = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
WORD32 i4_total_bits_allocted = i4_bit_alloc_est_tex_bits + i4_cur_est_header_bits;
|
|
WORD32 i4_total_bits_to_be_alloc;
|
|
WORD32 i4_expected_ebf = (i4_cur_ebf + i4_total_bits_allocted - i4_drain_rate);
|
|
/*if expected ebf is greater than max threashold, correct the allocation such that it never cross max
|
|
but if it less than drain rate, atleast give drainrate bits*/
|
|
if(i4_expected_ebf > i4_max_ebf)
|
|
{
|
|
i4_total_bits_to_be_alloc = MAX(
|
|
i4_drain_rate, (i4_total_bits_allocted - (i4_expected_ebf - i4_max_ebf)));
|
|
i4_bit_alloc_est_tex_bits = i4_total_bits_to_be_alloc - i4_cur_est_header_bits;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i4_bit_alloc_est_tex_bits_for_invalid_model = get_cur_frm_est_texture_bits(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->aps_rd_model,
|
|
ps_rate_control_api->ps_est_sad,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
e_pic_type,
|
|
i4_is_first_frame_coded,
|
|
0,
|
|
i4_call_type,
|
|
i_to_avg_ratio,
|
|
i4_is_model_valid);
|
|
if(i4_call_type == 1)
|
|
{
|
|
*pi4_estimate_to_calc_frm_error =
|
|
i4_bit_alloc_est_tex_bits_for_invalid_model + i4_cur_est_header_bits;
|
|
}
|
|
}
|
|
|
|
#if 1 /*model_low_bitrate_bug*/
|
|
/* This condition is added to use the model for cases when the estimated bits is less than zero.
|
|
We assume some bits of the header are used for texture and calcualte the qp */
|
|
if(i4_bit_alloc_est_tex_bits <= (i4_cur_est_header_bits >> 3))
|
|
{
|
|
i4_bit_alloc_est_tex_bits = (i4_cur_est_header_bits >> 3);
|
|
}
|
|
#endif
|
|
|
|
/* Step 2: Getting the min and max texture bits based on min and max qp */
|
|
if(i4_is_model_valid && ps_rate_control_api->au1_avg_bitrate_changed[e_pic_type] == 0)
|
|
{
|
|
WORD32 /*i4_min_qp, i4_max_qp,*/ i4_max_qp_q6, i4_min_qp_q6;
|
|
number_t s_lin_coeff_wo_int =
|
|
get_linear_coefficient(ps_rate_control_api->aps_rd_model[e_pic_type]);
|
|
|
|
if(s_lin_coeff_wo_int.sm != 0)
|
|
{
|
|
/* Get the min and max qp deviation allowed based on prev frame qp */
|
|
get_min_max_qp(
|
|
ps_rate_control_api,
|
|
e_pic_type,
|
|
&i4_max_qp_q6,
|
|
&i4_min_qp_q6,
|
|
i4_complexity_bin,
|
|
i4_scene_num);
|
|
|
|
/* Estimate the max bits based on min qp */
|
|
i4_qp_based_min_est_tex_bits = estimate_bits_for_qp(
|
|
ps_rate_control_api->aps_rd_model[e_pic_type], u4_estimated_sad, i4_max_qp_q6);
|
|
/* Estimate the min bits based on max qp */
|
|
i4_qp_based_max_est_tex_bits = estimate_bits_for_qp(
|
|
ps_rate_control_api->aps_rd_model[e_pic_type], u4_estimated_sad, i4_min_qp_q6);
|
|
/*disable qp based min and max swing restriction*/
|
|
i4_min_frame_qp_q6 = i4_min_qp_q6;
|
|
i4_max_frame_qp_q6 = i4_max_qp_q6;
|
|
i4_qp_based_max_est_tex_bits = i4_bit_alloc_est_tex_bits;
|
|
i4_qp_based_min_est_tex_bits = i4_bit_alloc_est_tex_bits;
|
|
}
|
|
else
|
|
{
|
|
i4_qp_based_min_est_tex_bits = i4_bit_alloc_est_tex_bits;
|
|
i4_qp_based_max_est_tex_bits = i4_bit_alloc_est_tex_bits;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i4_qp_based_min_est_tex_bits = i4_bit_alloc_est_tex_bits_for_invalid_model;
|
|
i4_qp_based_max_est_tex_bits = i4_bit_alloc_est_tex_bits_for_invalid_model;
|
|
ps_rate_control_api->au1_avg_bitrate_changed[e_pic_type] = 0;
|
|
}
|
|
|
|
/* Step 3: Getting the min and max texture bits based on buffer fullness */
|
|
|
|
if(i4_call_type == 1)
|
|
{
|
|
WORD32 i4_get_error;
|
|
|
|
i4_get_error = rc_get_estimate_bit_error(ps_rate_control_api);
|
|
|
|
get_min_max_bits_based_on_buffer(
|
|
ps_rate_control_api,
|
|
e_pic_type,
|
|
&i4_buf_based_min_bits,
|
|
&i4_buf_based_max_bits,
|
|
i4_get_error);
|
|
|
|
/*In case buffer limitation will come, no need to reduce the QP further because of warning flag*/
|
|
if(i4_bit_alloc_est_tex_bits < (i4_buf_based_min_bits - i4_cur_est_header_bits))
|
|
ps_rate_control_api->i4_underflow_warning = 0;
|
|
|
|
if(i4_buf_based_max_bits < (i4_bit_alloc_est_tex_bits + i4_cur_est_header_bits))
|
|
{
|
|
i4_buffer_based_max_qp_clip_flag = 1;
|
|
}
|
|
trace_printf(
|
|
"i4_buf_based_min_bits %d i4_buf_based_max_bits %d",
|
|
i4_buf_based_min_bits,
|
|
i4_buf_based_max_bits);
|
|
trace_printf(
|
|
"Prev I frame qp q6 %d P frame qp q6 %d",
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[I_PIC],
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[P_PIC]);
|
|
}
|
|
else
|
|
{
|
|
i4_buf_based_min_bits = i4_qp_based_min_est_tex_bits;
|
|
i4_buf_based_max_bits = i4_qp_based_max_est_tex_bits;
|
|
}
|
|
/* for I frame the max bits is not restricted based on the user input */
|
|
if(e_pic_type == I_PIC)
|
|
{
|
|
i4_ud_max_bits = 0x7fffffff; /* i4_bit_alloc_est_tex_bits + i4_cur_est_header_bits; */
|
|
}
|
|
|
|
/* Step 4: Clip the bits allocated based on
|
|
1) FinalBits = Max of (BitallocBits, MinBitsMaxQp, MinBufferBits)
|
|
2) FinalBits = Min of (MaxBitsMinQp, MaxBufferBits, MaxUserDefBits, FinalBits)
|
|
Note that max is done after min to prevent over-consumption */
|
|
/* Finding the max of all the minimum bits */
|
|
i4_est_tex_bits = get_max(
|
|
i4_bit_alloc_est_tex_bits,
|
|
i4_qp_based_min_est_tex_bits,
|
|
(i4_buf_based_min_bits - i4_cur_est_header_bits));
|
|
i4_est_tex_bits = get_min(
|
|
i4_est_tex_bits,
|
|
i4_qp_based_max_est_tex_bits,
|
|
(i4_ud_max_bits - i4_cur_est_header_bits),
|
|
(i4_buf_based_max_bits - i4_cur_est_header_bits));
|
|
|
|
/*Highest priority given to min and max qp followed by buffer based min and max to prevent overconsumption in process of preventing stuffing*/
|
|
CLIP(
|
|
i4_est_tex_bits,
|
|
i4_buf_based_max_bits - i4_cur_est_header_bits,
|
|
i4_buf_based_min_bits - i4_cur_est_header_bits);
|
|
|
|
{
|
|
WORD32 i4_drain_bits_per_frame =
|
|
get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer),
|
|
i4_ebf;
|
|
WORD32 i4_delay = cbr_get_delay_frames(ps_rate_control_api->ps_cbr_buffer),
|
|
max_buffer_level = 0, rc_type = get_rc_type(ps_rate_control_api->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_rate_control_api->ps_cbr_buffer);
|
|
|
|
i4_ebf = get_cbr_ebf(ps_rate_control_api->ps_cbr_buffer);
|
|
|
|
if(i4_ebf > (WORD32)(0.9f * max_buffer_level))
|
|
{
|
|
i4_buffer_based_max_qp_clip_flag = 1;
|
|
switch(e_pic_type)
|
|
{
|
|
case P_PIC:
|
|
case P1_PIC:
|
|
i4_min_Kp_Kb_factor = I_TO_P_RATIO;
|
|
break;
|
|
case B_PIC:
|
|
case BB_PIC:
|
|
i4_min_Kp_Kb_factor = I_TO_B_RATIO;
|
|
break;
|
|
case B1_PIC:
|
|
case B11_PIC:
|
|
i4_min_Kp_Kb_factor = I_TO_B1_RATIO;
|
|
break;
|
|
default:
|
|
i4_min_Kp_Kb_factor = I_TO_B2_RATIO;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/*i4_is_first_frame_coded will be considered only in 2 pass, since 2 pass precise I to rest is calcuated considering first sug-gop and full sub-gop complexity separately. Using offset based
|
|
qp instead of single frame model(with default bit allocation)*/
|
|
/* Step 6: Estimate the qp generated for the given texture bits */
|
|
if((!i4_is_first_frame_coded /* && ps_rate_control_api->i4_rc_pass == 2*/) ||
|
|
!i4_is_model_valid) //ELP_RC
|
|
{
|
|
/* WORD32 i4_bpp_based_qp; */
|
|
/* If the number pf pels is set to zero it uses the value set during init time */
|
|
/* i4_frame_qp = get_init_qp_using_pels_bits_per_frame(ps_rate_control_api->ps_init_qp,
|
|
e_pic_type, i4_est_tex_bits, 0); */
|
|
WORD32 Kp_kb_factor = get_Kp_Kb(ps_rate_control_api->ps_bit_allocation, e_pic_type);
|
|
WORD32 kp_kb_ref_ref = get_Kp_Kb(
|
|
ps_rate_control_api->ps_bit_allocation, ps_rate_control_api->prev_ref_pic_type);
|
|
|
|
if(e_pic_type == I_PIC &&
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] == 0x7FFFFFFF)
|
|
{
|
|
/*Is this a valid case?*/
|
|
ASSERT(0);
|
|
i4_frame_qp = get_init_qp_using_pels_bits_per_frame(
|
|
ps_rate_control_api->ps_init_qp, e_pic_type, i4_est_tex_bits, 0);
|
|
i4_frame_qp_q6 = i4_frame_qp << QSCALE_Q_FAC;
|
|
}
|
|
/*If there is a scene cut I frame followed by a scene cut I frame, non scene cut I frame
|
|
better assume the Qp of the I frame same as before instead of using bpp based qp*/
|
|
else if(
|
|
e_pic_type == I_PIC &&
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] != 0x7FFFFFFF)
|
|
{
|
|
i4_frame_qp = ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC];
|
|
i4_frame_qp_q6 = ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC];
|
|
}
|
|
else /*! ISlice*/
|
|
{
|
|
if((Kp_kb_factor < i4_min_Kp_Kb_factor) && (i4_call_type == 1))
|
|
{
|
|
Kp_kb_factor = i4_min_Kp_Kb_factor;
|
|
trace_printf("Kp_kb_factor %d", Kp_kb_factor);
|
|
}
|
|
if((kp_kb_ref_ref > Kp_kb_factor) && (i4_call_type == 1))
|
|
{
|
|
kp_kb_ref_ref = Kp_kb_factor;
|
|
}
|
|
|
|
if(ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][ps_rate_control_api->prev_ref_pic_type] ==
|
|
0x7FFFFFFF)
|
|
{
|
|
ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][ps_rate_control_api->prev_ref_pic_type] =
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC];
|
|
kp_kb_ref_ref = 16;
|
|
}
|
|
|
|
i4_frame_qp_q6 =
|
|
((ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][ps_rate_control_api->prev_ref_pic_type] *
|
|
Kp_kb_factor) /
|
|
kp_kb_ref_ref);
|
|
}
|
|
|
|
/*HEVC_hierarchy: Breaks pause to resume logic if any and also the HBR mode concept as bit ratios are not known. It is now quaranteed that all frames
|
|
encoded after scene cut will belong to new scene(B pic of first sub-gop)Hence the below logic of using max of either current estimate
|
|
or previous B frame qp is not required*/
|
|
/* Since precise SCD position at B-pic level is not known, take the MAX of earlier B-QP and scaled I_QP after SCD */
|
|
/*HEVC_RC : Since precise SCD location is known and it is guranteed that pic encoded after I pic belongs to new scene*/
|
|
|
|
{
|
|
WORD32 i4_bits_per_frame;
|
|
i4_bits_per_frame = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
if(i4_call_type == 1)
|
|
{
|
|
rc_modify_est_tot(ps_rate_control_api, i4_bits_per_frame);
|
|
}
|
|
}
|
|
}
|
|
/* The check is becaue the model gives a negative QP when the
|
|
i4_est_tex_bits is less than or equal to 0
|
|
[This is a bug in the model]. As a temporary fix, the frame QP
|
|
is being set to the max QP allowed */
|
|
else if(i4_est_tex_bits > 0)
|
|
{
|
|
if(i4_call_type == 1)
|
|
{
|
|
rc_modify_est_tot(ps_rate_control_api, (i4_est_tex_bits + i4_cur_est_header_bits));
|
|
}
|
|
i4_steady_state_texture_case = 1;
|
|
/* Query the model for the Qp for the corresponding frame*/
|
|
i4_frame_qp_q6_based_max_vbv_bits = find_qp_for_target_bits(
|
|
ps_rate_control_api->aps_rd_model[e_pic_type],
|
|
i4_buf_based_max_bits - i4_cur_est_header_bits,
|
|
u4_estimated_sad,
|
|
(ps_rate_control_api->ai4_max_qp_q6[e_pic_type]),
|
|
(ps_rate_control_api->ai4_min_qp_q6[e_pic_type]));
|
|
if(i4_call_type == 1)
|
|
{
|
|
*pi4_maxEbfQP = ihevce_rc_get_scaled_hevce_qp_q6(
|
|
i4_frame_qp_q6_based_max_vbv_bits, ps_rate_control_api->u1_bit_depth);
|
|
}
|
|
/* Query the model for the Qp for the corresponding frame*/
|
|
i4_frame_qp_q6 = find_qp_for_target_bits(
|
|
ps_rate_control_api->aps_rd_model[e_pic_type],
|
|
i4_est_tex_bits,
|
|
u4_estimated_sad,
|
|
(ps_rate_control_api->ai4_max_qp_q6[e_pic_type]),
|
|
(ps_rate_control_api->ai4_min_qp_q6[e_pic_type]));
|
|
i4_frame_qp = ((i4_frame_qp_q6 + (1 << (QSCALE_Q_FAC - 1))) >> QSCALE_Q_FAC);
|
|
}
|
|
else
|
|
{
|
|
{
|
|
WORD32 i4_bits_per_frame;
|
|
i4_bits_per_frame = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
if(i4_call_type == 1)
|
|
{
|
|
rc_modify_est_tot(ps_rate_control_api, i4_bits_per_frame);
|
|
}
|
|
}
|
|
i4_frame_qp = ps_rate_control_api->ai4_max_qp[e_pic_type];
|
|
i4_frame_qp_q6 = ps_rate_control_api->ai4_max_qp_q6[e_pic_type];
|
|
}
|
|
if(i4_call_type == 1)
|
|
{
|
|
*pi4_modelQP =
|
|
ihevce_rc_get_scaled_hevce_qp_q6(i4_frame_qp_q6, ps_rate_control_api->u1_bit_depth);
|
|
}
|
|
{
|
|
/*This clip is added to prevent the change in qp close to scene cuts i.e even though the buffer
|
|
allows the qp to go low the bit alloc model has a problem of having the denominator considering
|
|
the previous subgop complexity and giving bits*/
|
|
WORD32 i4_clip_flag =
|
|
((i4_call_type == 1) && (i4_is_model_valid == 1) &&
|
|
(ps_rate_control_api->i4_rc_pass == 2) &&
|
|
(i4_buf_based_max_bits > i4_est_tex_bits));
|
|
WORD32 i4_ebf = rc_get_ebf(ps_rate_control_api),
|
|
i4_max_ebf = i4_ebf + i4_buf_based_max_bits;
|
|
WORD32 i4_inter_frame_interval =
|
|
pic_type_get_inter_frame_interval(ps_rate_control_api->ps_pic_handling);
|
|
float f_buffer_fullness = (float)i4_ebf / i4_max_ebf;
|
|
i4_clip_flag = i4_clip_flag && (ps_rate_control_api->i4_scd_in_period_2_pass == 1);
|
|
i4_clip_flag = i4_clip_flag && (i4_ebf < (i4_max_ebf * 0.5f));
|
|
i4_clip_flag = i4_clip_flag && (ps_rate_control_api->e_rc_type == VBR_STREAMING);
|
|
|
|
i4_clip_flag = i4_clip_flag && (ps_rate_control_api->i4_frames_since_last_scd >
|
|
i4_inter_frame_interval);
|
|
|
|
if(i4_clip_flag == 1)
|
|
{
|
|
WORD32 i4_prev_frame_tot_est_bits = ba_get_prev_frame_tot_est_bits(
|
|
ps_rate_control_api->ps_bit_allocation, (WORD32)ps_rate_control_api->e_rc_type);
|
|
WORD32 i4_prev_frame_tot_bits = ba_get_prev_frame_tot_bits(
|
|
ps_rate_control_api->ps_bit_allocation, (WORD32)ps_rate_control_api->e_rc_type);
|
|
float i4_consumption_ratio =
|
|
(float)i4_prev_frame_tot_bits / i4_prev_frame_tot_est_bits;
|
|
if(i4_consumption_ratio > 0.7f && i4_consumption_ratio < 1.5f)
|
|
i4_clip_flag = 1;
|
|
else
|
|
i4_clip_flag = 0;
|
|
}
|
|
if(i4_clip_flag == 1)
|
|
{
|
|
trace_printf("Clipped");
|
|
trace_printf("Before %d", i4_frame_qp_q6);
|
|
if(af_sum_weigh[e_pic_type][0] > 1.0f)
|
|
{
|
|
/*Complex followed by simple*/
|
|
if(i4_frame_qp_q6 >
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][e_pic_type])
|
|
{
|
|
if(f_buffer_fullness < 0.3f)
|
|
{
|
|
i4_frame_qp_q6 =
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][e_pic_type];
|
|
}
|
|
else
|
|
{
|
|
if(i4_frame_qp_q6 >
|
|
(ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][e_pic_type] *
|
|
72 * 3))
|
|
i4_frame_qp_q6 =
|
|
(ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[i4_scene_num][e_pic_type] *
|
|
72 * 3);
|
|
}
|
|
}
|
|
}
|
|
if(af_sum_weigh[e_pic_type][0] < 1.0f)
|
|
{
|
|
/*Simple followed by complex*/
|
|
if(i4_frame_qp_q6 <
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][e_pic_type])
|
|
{
|
|
/*i4_frame_qp_q6 = ps_rate_control_api->ai4_prev_frm_qp_q6[e_pic_type];*/
|
|
}
|
|
}
|
|
trace_printf("After %d", i4_frame_qp_q6);
|
|
}
|
|
}
|
|
|
|
/*swing restriciton based on previous frame qp swing*/
|
|
{
|
|
if(i4_call_type == 1)
|
|
{
|
|
trace_printf(
|
|
"Before i4_frame_qp_q6 = %d min qp = %d max_qp = %d "
|
|
"bufclip %d",
|
|
i4_frame_qp_q6,
|
|
(i4_min_frame_qp_q6),
|
|
(i4_max_frame_qp_q6),
|
|
i4_buffer_based_max_qp_clip_flag);
|
|
}
|
|
if(i4_frame_qp_q6 < i4_min_frame_qp_q6)
|
|
i4_frame_qp_q6 = i4_min_frame_qp_q6;
|
|
|
|
/*removed low side clipping to avoid HRD compliance issue*/
|
|
if(i4_steady_state_texture_case)
|
|
{
|
|
if(i4_frame_qp_q6 > i4_max_frame_qp_q6)
|
|
{
|
|
if(i4_max_frame_qp_q6 > (i4_frame_qp_q6_based_max_vbv_bits))
|
|
{
|
|
i4_frame_qp_q6 = i4_max_frame_qp_q6;
|
|
}
|
|
else
|
|
{
|
|
i4_frame_qp_q6 = i4_frame_qp_q6_based_max_vbv_bits;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(i4_call_type == 1)
|
|
{
|
|
trace_printf("After i4_frame_qp_q6 = %d", i4_frame_qp_q6);
|
|
}
|
|
|
|
/* SS - Following done to restore this after pause to resume detect - 0.25 is for syntax bits */
|
|
ps_rate_control_api->i4_orig_frm_est_bits = (i4_est_tex_bits * 5) >> 2;
|
|
ps_rate_control_api->i4_prev_frm_est_bits = (i4_est_tex_bits + i4_cur_est_header_bits);
|
|
pi4_cur_est_texture_bits[0] = i4_est_tex_bits;
|
|
|
|
/*For frames after SCD, when neither online or offline model can estimate the bits,
|
|
use the remaining bits in period as max bits*/
|
|
*pi4_is_model_valid = i4_is_model_valid;
|
|
|
|
if(0 == i4_is_model_valid)
|
|
{
|
|
*pi4_tot_bits_estimated =
|
|
i4_bit_alloc_est_tex_bits_for_invalid_model; //(i4_buf_based_max_bits * 0.80);
|
|
}
|
|
else
|
|
{
|
|
*pi4_tot_bits_estimated = i4_est_tex_bits + i4_cur_est_header_bits;
|
|
}
|
|
|
|
/*For B pics assigning a non-zero value to avoid asser */
|
|
if(*pi4_tot_bits_estimated == 0)
|
|
{
|
|
*pi4_tot_bits_estimated = 1;
|
|
}
|
|
ASSERT(*pi4_tot_bits_estimated != 0);
|
|
/*Underflow prevention*/
|
|
if((ps_rate_control_api->i4_underflow_warning == 1) &&
|
|
(i4_est_tex_bits < (i4_buf_based_max_bits - i4_cur_est_header_bits)) &&
|
|
(i4_call_type == 1))
|
|
{
|
|
//printf("\nUnderflow warning\n");
|
|
/*Decrement the hevc_qp by 1 for underflow prevention*/
|
|
i4_frame_qp_q6 = (WORD32)((float)i4_frame_qp_q6 / (float)1.125f);
|
|
ps_rate_control_api->i4_underflow_warning = 0;
|
|
if(i4_call_type == 1)
|
|
{
|
|
trace_printf("\nUnderflow warning");
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Clip the frame qp within Min and Max QP */
|
|
if(i4_frame_qp_q6 < ps_rate_control_api->ai4_min_qp_q6[e_pic_type])
|
|
{
|
|
i4_frame_qp_q6 = ps_rate_control_api->ai4_min_qp_q6[e_pic_type];
|
|
}
|
|
else if(i4_frame_qp_q6 > ps_rate_control_api->ai4_max_qp_q6[e_pic_type])
|
|
{
|
|
i4_frame_qp_q6 = ps_rate_control_api->ai4_max_qp_q6[e_pic_type];
|
|
}
|
|
if(i4_call_type == 1)
|
|
{
|
|
*pi4_vbv_buf_max_bits = i4_buf_based_max_bits;
|
|
*pi4_est_tex_bits = i4_est_tex_bits;
|
|
*pi4_cur_est_header_bits = i4_cur_est_header_bits;
|
|
}
|
|
return (i4_frame_qp_q6);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_bits_for_final_qp
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
|
|
void get_bits_for_final_qp(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 *pi4_modelQP,
|
|
WORD32 *pi4_maxEbfQP,
|
|
LWORD64 *pi8_bits_from_finalQP,
|
|
WORD32 i4_clipQP,
|
|
WORD32 i4_frame_qp_q6,
|
|
WORD32 i4_cur_est_header_bits,
|
|
WORD32 i4_est_tex_bits,
|
|
WORD32 i4_buf_based_max_bits,
|
|
picture_type_e e_pic_type,
|
|
WORD32 i4_display_num)
|
|
{
|
|
UWORD32 u4_estimated_sad;
|
|
u4_estimated_sad = get_est_sad(ps_rate_control_api->ps_est_sad, e_pic_type);
|
|
{
|
|
//printf("%d:\ti4_modelQP = %d\t i4_maxEbfQP = %d\t i4_clipQP = %d\t bits = %d\n",i4_display_num,*pi4_modelQP,*pi4_maxEbfQP,i4_clipQP,*pi8_bits_from_finalQP);
|
|
if((*pi4_modelQP != INVALID_QP) && (*pi4_maxEbfQP != INVALID_QP) &&
|
|
/*(*pi4_modelQP >= i4_clipQP) &&*/
|
|
(i4_clipQP > *pi4_maxEbfQP))
|
|
{
|
|
WORD32 i4_loop = 0, i4_error, i4_prev_error = 0x7FFFFFFF;
|
|
WORD32 i4_frame_qp_q6_temp;
|
|
WORD32 i4_buf_max_text_bits = i4_buf_based_max_bits - i4_cur_est_header_bits;
|
|
WORD32 i4_min_bits = i4_est_tex_bits, i4_max_bits = i4_buf_max_text_bits;
|
|
WORD32 i4_temp_bits = (i4_min_bits + i4_max_bits) >> 1;
|
|
if(*pi4_modelQP == i4_clipQP)
|
|
{
|
|
*pi8_bits_from_finalQP = i4_est_tex_bits + i4_cur_est_header_bits;
|
|
//printf("%d:\ti4_modelQP = %d\t i4_maxEbfQP = %d\t i4_clipQP = %d\t bits = %d\n",i4_display_num,*pi4_modelQP,*pi4_maxEbfQP,i4_clipQP,*pi8_bits_from_finalQP);
|
|
return;
|
|
}
|
|
//printf("%d:\ti4_modelQP = %d\t i4_maxEbfQP = %d\t i4_clipQP = %d\t bits = %d\n",i4_display_num,*pi4_modelQP,*pi4_maxEbfQP,i4_clipQP,*pi8_bits_from_finalQP);
|
|
/*binary search to find out bits corresponds to final QP(clipped)*/
|
|
while(i4_loop < 30)
|
|
{
|
|
i4_frame_qp_q6_temp = find_qp_for_target_bits(
|
|
ps_rate_control_api->aps_rd_model[e_pic_type],
|
|
i4_temp_bits,
|
|
u4_estimated_sad,
|
|
(ps_rate_control_api->ai4_max_qp_q6[e_pic_type]),
|
|
(ps_rate_control_api->ai4_min_qp_q6[e_pic_type]));
|
|
i4_error = abs(i4_frame_qp_q6_temp - i4_frame_qp_q6);
|
|
if(i4_error < i4_prev_error)
|
|
{
|
|
*pi8_bits_from_finalQP = i4_temp_bits + i4_cur_est_header_bits;
|
|
i4_prev_error = i4_error;
|
|
//printf("*pi8_bits_from_finalQP = %d\n",*pi8_bits_from_finalQP);
|
|
}
|
|
if(i4_frame_qp_q6_temp < i4_frame_qp_q6)
|
|
{
|
|
i4_max_bits = i4_temp_bits;
|
|
}
|
|
else
|
|
{
|
|
i4_min_bits = i4_temp_bits;
|
|
}
|
|
i4_temp_bits = (i4_min_bits + i4_max_bits) >> 1;
|
|
i4_loop++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* when est bits is less than 0 , max ebfQP is not updated, hence invalid
|
|
as estimated bits are less it will not cause any buffer trouble*/
|
|
if(((*pi4_maxEbfQP == INVALID_QP) && (*pi4_modelQP == i4_clipQP)))
|
|
{
|
|
*pi8_bits_from_finalQP = i4_est_tex_bits + i4_cur_est_header_bits;
|
|
}
|
|
else
|
|
{
|
|
*pi8_bits_from_finalQP = i4_buf_based_max_bits;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/****************************************************************************
|
|
*Function Name : get_buffer_status
|
|
*Description : Gets the state of VBV buffer
|
|
*Inputs : Rate control API , header and texture bits
|
|
*Globals :
|
|
*Processing :
|
|
*Outputs : 0 = normal, 1 = underflow, 2= overflow
|
|
*Returns : vbv_buf_status_e
|
|
*Issues :
|
|
*Revision History:
|
|
*DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*
|
|
********************************************************************************/
|
|
vbv_buf_status_e get_buffer_status(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 i4_total_frame_bits, /* Total frame bits consumed */
|
|
picture_type_e e_pic_type,
|
|
WORD32 *pi4_num_bits_to_prevent_vbv_underflow)
|
|
{
|
|
vbv_buf_status_e e_buf_status = VBV_NORMAL;
|
|
|
|
/* Get the buffer status for the current total consumed bits and error bits*/
|
|
if(ps_rate_control_api->e_rc_type == VBR_STORAGE_DVD_COMP)
|
|
{
|
|
e_buf_status = get_vbv_buffer_status(
|
|
ps_rate_control_api->ps_vbr_storage_vbv,
|
|
i4_total_frame_bits,
|
|
pi4_num_bits_to_prevent_vbv_underflow);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == VBR_STORAGE)
|
|
{
|
|
/* For VBR case since there is not underflow returning the max value */
|
|
pi4_num_bits_to_prevent_vbv_underflow[0] =
|
|
get_max_vbv_buf_size(ps_rate_control_api->ps_vbr_storage_vbv);
|
|
e_buf_status = VBV_NORMAL;
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == CBR_NLDRC)
|
|
{
|
|
e_buf_status = get_cbr_buffer_status(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
i4_total_frame_bits,
|
|
pi4_num_bits_to_prevent_vbv_underflow,
|
|
e_pic_type,
|
|
ps_rate_control_api->e_rc_type);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == VBR_STREAMING)
|
|
{
|
|
/* For VBR_streaming the error bits are computed according to peak bitrate*/
|
|
e_buf_status = get_cbr_buffer_status(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
i4_total_frame_bits,
|
|
pi4_num_bits_to_prevent_vbv_underflow,
|
|
e_pic_type,
|
|
ps_rate_control_api->e_rc_type);
|
|
}
|
|
return e_buf_status;
|
|
}
|
|
/****************************************************************************
|
|
Function Name : update_pic_handling_state
|
|
Description : If the forward path and the backward path of rate control
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
KJN Original
|
|
*****************************************************************************/
|
|
void update_pic_handling_state(rate_control_api_t *ps_rate_control_api, picture_type_e e_pic_type)
|
|
{
|
|
WORD32 i4_is_non_ref_pic = 0;
|
|
update_pic_handling(ps_rate_control_api->ps_pic_handling, e_pic_type, i4_is_non_ref_pic, 0);
|
|
}
|
|
LWORD64 get_gop_bits(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ba_get_gop_bits(ps_rate_control_api->ps_bit_allocation));
|
|
}
|
|
LWORD64 get_gop_sad(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ba_get_gop_sad(ps_rate_control_api->ps_bit_allocation));
|
|
}
|
|
WORD32 check_if_current_GOP_is_simple(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
LWORD64 i8_buffer_play_bits =
|
|
ba_get_buffer_play_bits_for_cur_gop(ps_rate_control_api->ps_bit_allocation);
|
|
if(i8_buffer_play_bits)
|
|
{
|
|
if((i8_buffer_play_bits + get_cbr_ebf(ps_rate_control_api->ps_cbr_buffer)) >
|
|
(0.6 * get_cbr_buffer_size(ps_rate_control_api->ps_cbr_buffer)))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
LWORD64 rc_get_rbip_and_num_frames(rate_control_api_t *ps_rate_control_api, WORD32 *pi4_num_frames)
|
|
{
|
|
return (ba_get_rbip_and_num_frames(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
pi4_num_frames));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : update_frame_level_info
|
|
Description : Updates the frame level information into the rate control structure
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
KJN Original
|
|
25 04 2008 Sushmita Added support to get different bits for model
|
|
updation & buffer updation.May be used,in case encoder
|
|
decides to follow strict VBV compliance and hence
|
|
skips a picture after encoding it.Since it has
|
|
statistics of the current picture also we update
|
|
the model based on the discarded picture's stats
|
|
and the buffer model on the basis of actual bits
|
|
consumed by skipped picture
|
|
*****************************************************************************/
|
|
void update_frame_level_info(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
LWORD64 *pi8_mb_type_sad, /* Frame level SAD for each type of MB[Intra/Inter] */
|
|
WORD32 i4_total_frame_bits, /* Total frame bits actually consumed */
|
|
WORD32 i4_model_updation_hdr_bits, /*header bits for model updation*/
|
|
WORD32 *
|
|
pi4_mb_type_tex_bits, /* Total texture bits consumed for each type of MB[Intra/Inter] used for model */
|
|
LWORD64 *pi8_tot_mb_type_qp_q6, /* Total qp of all MBs based on mb type */
|
|
WORD32 *pi4_tot_mb_in_type, /* total number of mbs in each mb type */
|
|
WORD32 i4_avg_activity, /* Average mb activity in frame */
|
|
UWORD8 u1_is_scd, /* Is a scene change detected at the current frame */
|
|
WORD32 i4_is_it_a_skip,
|
|
WORD32 i4_intra_frm_cost,
|
|
WORD32
|
|
i4_is_pic_handling_done, /* If picture handling is not done then update pic handling module. Special case for staggered endcoding */
|
|
WORD32 i4_suppress_bpic_update,
|
|
WORD32 i4_bits_to_be_stuffed,
|
|
WORD32 i4_is_pause_to_resume,
|
|
WORD32 i4_lap_window_comp,
|
|
WORD32 i4_is_end_of_period,
|
|
WORD32 i4_lap_based_comp_reset,
|
|
frame_info_t *ps_frame_info,
|
|
WORD32 i4_is_rc_model_needs_to_be_updated,
|
|
WORD8 i1_qp_offset,
|
|
WORD32 i4_scene_num,
|
|
WORD32 i4_num_frm_enc_in_scene,
|
|
WORD32 i4_est_text_bits_ctr_update_qp)
|
|
{
|
|
UWORD8 u1_num_skips = 0;
|
|
WORD32 i;
|
|
/*picture_type_e e_orig_pic_type = e_pic_type;*/
|
|
LWORD64 i8_frame_sad = 0; /* Frame level SAD */
|
|
WORD32 i4_tot_texture_bits = 0; /* Total texture bits consumed */
|
|
WORD32 i4_tot_mbs = 0; /* Total number of mbs in frame */
|
|
LWORD64 i8_avg_qp = 0, i8_avg_qp_q6 = 0;
|
|
WORD32 i4_flag_rc_model_update = (i4_is_rc_model_needs_to_be_updated == 1);
|
|
WORD32 i4_gop_correction = 0, i4_new_correction = 0;
|
|
|
|
ps_frame_info->i4_flag_rc_model_update = i4_flag_rc_model_update;
|
|
ps_frame_info->i4_num_entries++;
|
|
trace_printf(
|
|
"update pic_type = %d tbc = %d hbc = %d\n",
|
|
e_pic_type,
|
|
(i4_total_frame_bits - i4_model_updation_hdr_bits),
|
|
i4_model_updation_hdr_bits);
|
|
/* NOTE KJN: SCD not supported in case of B Frames */
|
|
if(u1_is_scd && (e_pic_type != I_PIC && e_pic_type != P_PIC))
|
|
{
|
|
u1_is_scd = 0;
|
|
}
|
|
|
|
/*if both pause to resume and scene cut is signalled then ignore pause to resume flag*/
|
|
if(u1_is_scd && i4_is_pause_to_resume)
|
|
i4_is_pause_to_resume = 0;
|
|
|
|
if(!i4_is_it_a_skip && !i4_is_pic_handling_done)
|
|
{
|
|
/* Update the pic_handling struct */
|
|
/*: do not update pic handling even in case of non-reference B-PIC*/
|
|
update_pic_handling(
|
|
ps_rate_control_api->ps_pic_handling, e_pic_type, i4_suppress_bpic_update, u1_is_scd);
|
|
}
|
|
{
|
|
WORD32 *pi4_qp_array =
|
|
ps_rate_control_api
|
|
->ai4_prev_frm_qp[(i4_scene_num + HALF_MAX_SCENE_NUM_RC) % MAX_SCENE_NUM_RC];
|
|
WORD32 *pi4_qp_array_q6 =
|
|
ps_rate_control_api
|
|
->ai4_prev_frm_qp_q6[(i4_scene_num + HALF_MAX_SCENE_NUM_RC) % MAX_SCENE_NUM_RC];
|
|
WORD32 i4_i;
|
|
for(i4_i = 0; i4_i < MAX_PIC_TYPE; i4_i++)
|
|
{
|
|
pi4_qp_array[i4_i] = 0x7FFFFFFF;
|
|
pi4_qp_array_q6[i4_i] = 0x7FFFFFFF;
|
|
}
|
|
}
|
|
|
|
if(ps_rate_control_api->e_rc_type == CONST_QP)
|
|
{
|
|
if(!i4_is_it_a_skip)
|
|
{
|
|
/******************************************************************
|
|
Calculate the total values from the individual values
|
|
******************************************************************/
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i8_frame_sad += pi8_mb_type_sad[i];
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i4_tot_texture_bits += pi4_mb_type_tex_bits[i];
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i8_avg_qp += (pi8_tot_mb_type_qp_q6[i] >> 6);
|
|
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i8_avg_qp_q6 += pi8_tot_mb_type_qp_q6[i];
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i4_tot_mbs += pi4_tot_mb_in_type[i];
|
|
i8_avg_qp /= i4_tot_mbs; /* Calculate the average QP */
|
|
i8_avg_qp_q6 /= i4_tot_mbs;
|
|
|
|
if(ps_rate_control_api->u1_is_mb_level_rc_on)
|
|
{
|
|
/* The model needs to take into consideration the average activity of the
|
|
entire frame while estimating the QP. Thus the frame sad values are scaled by
|
|
the average activity before updating it into the model.*/
|
|
if(!i4_avg_activity)
|
|
i4_avg_activity = 1;
|
|
i4_intra_frm_cost /= i4_avg_activity;
|
|
i8_frame_sad /= i4_avg_activity;
|
|
}
|
|
|
|
ps_frame_info->i8_frame_num = get_num_frms_encoded(ps_rate_control_api->ps_cbr_buffer);
|
|
ps_frame_info->i4_num_entries++;
|
|
|
|
update_cbr_buffer(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
(i4_total_frame_bits + i4_bits_to_be_stuffed),
|
|
e_pic_type);
|
|
}
|
|
}
|
|
|
|
if(ps_rate_control_api->e_rc_type != CONST_QP)
|
|
{
|
|
/* For improving CBR streams quality */
|
|
WORD32 i4_buffer_based_bit_error = 0;
|
|
|
|
if(!i4_is_it_a_skip)
|
|
{
|
|
WORD32 i4_new_period_flag;
|
|
/******************************************************************
|
|
Calculate the total values from the individual values
|
|
******************************************************************/
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i8_frame_sad += pi8_mb_type_sad[i];
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i4_tot_texture_bits += pi4_mb_type_tex_bits[i];
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i8_avg_qp += (pi8_tot_mb_type_qp_q6[i] >> 6);
|
|
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i8_avg_qp_q6 += pi8_tot_mb_type_qp_q6[i];
|
|
for(i = 0; i < MAX_MB_TYPE; i++)
|
|
i4_tot_mbs += pi4_tot_mb_in_type[i];
|
|
i8_avg_qp /= i4_tot_mbs; /* Calculate the average QP */
|
|
i8_avg_qp_q6 /= i4_tot_mbs;
|
|
|
|
if(ps_rate_control_api->u1_is_mb_level_rc_on)
|
|
{
|
|
/* The model needs to take into consideration the average activity of the
|
|
entire frame while estimating the QP. Thus the frame sad values are scaled by
|
|
the average activity before updating it into the model.*/
|
|
if(!i4_avg_activity)
|
|
i4_avg_activity = 1;
|
|
i4_intra_frm_cost /= i4_avg_activity;
|
|
i8_frame_sad /= i4_avg_activity;
|
|
}
|
|
|
|
ps_frame_info->i8_frame_num = get_num_frms_encoded(ps_rate_control_api->ps_cbr_buffer);
|
|
ps_frame_info->i4_num_entries++;
|
|
/******************************************************************
|
|
Update the bit allocation module
|
|
NOTE: For bit allocation module, the pic_type should not be modified
|
|
to that of 'I', in case of a SCD.
|
|
******************************************************************/
|
|
i4_new_period_flag = is_last_frame_in_gop(ps_rate_control_api->ps_pic_handling);
|
|
|
|
update_cur_frm_consumed_bits(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
i4_total_frame_bits,
|
|
/*((ps_rate_control_api->e_rc_type == CBR_NLDRC)?(i4_total_frame_bits + i4_bits_to_be_stuffed):i4_total_frame_bits)*/ //account for stuffing bits even when encoder does not stuff in case of CBR
|
|
i4_model_updation_hdr_bits,
|
|
e_pic_type,
|
|
u1_is_scd,
|
|
i4_is_end_of_period,
|
|
i4_lap_based_comp_reset,
|
|
i4_suppress_bpic_update,
|
|
i4_buffer_based_bit_error,
|
|
i4_bits_to_be_stuffed,
|
|
i4_lap_window_comp,
|
|
ps_rate_control_api->e_rc_type,
|
|
ps_rate_control_api->i4_num_gop,
|
|
i4_is_pause_to_resume,
|
|
i4_est_text_bits_ctr_update_qp,
|
|
&i4_gop_correction,
|
|
&i4_new_correction);
|
|
if(1 == i4_new_period_flag &&
|
|
((ps_rate_control_api->e_rc_type == VBR_STORAGE) ||
|
|
(ps_rate_control_api->e_rc_type == VBR_STORAGE_DVD_COMP)))
|
|
{
|
|
check_and_update_bit_allocation(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
get_max_bits_inflow_per_frm_periode(ps_rate_control_api->ps_vbr_storage_vbv));
|
|
}
|
|
}
|
|
|
|
/******************************************************************
|
|
Update the buffer status
|
|
******************************************************************/
|
|
/* This updation is done after overflow and underflow handling to
|
|
account for the actual bits dumped*/
|
|
if((ps_rate_control_api->e_rc_type == VBR_STORAGE) ||
|
|
(ps_rate_control_api->e_rc_type == VBR_STORAGE_DVD_COMP))
|
|
{
|
|
update_vbr_vbv(ps_rate_control_api->ps_vbr_storage_vbv, i4_total_frame_bits);
|
|
}
|
|
else if(
|
|
ps_rate_control_api->e_rc_type == CBR_NLDRC ||
|
|
ps_rate_control_api->e_rc_type == VBR_STREAMING)
|
|
{
|
|
update_cbr_buffer(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
(i4_total_frame_bits + i4_bits_to_be_stuffed),
|
|
e_pic_type);
|
|
}
|
|
|
|
if(e_pic_type != B_PIC || e_pic_type != B1_PIC || e_pic_type != B2_PIC)
|
|
{
|
|
ps_rate_control_api->i4_prev_ref_is_scd = 0;
|
|
}
|
|
|
|
if(!i4_is_it_a_skip)
|
|
{
|
|
/******************************************************************
|
|
Handle the SCENE CHANGE DETECTED
|
|
1) Make the picture type as I, so that updation happens as if it is
|
|
a I frame
|
|
2) Reset model, SAD and flag to restart the estimation process
|
|
******************************************************************/
|
|
if(u1_is_scd || ps_rate_control_api->u1_is_first_frm)
|
|
{
|
|
e_pic_type = I_PIC;
|
|
|
|
/* Reset the SAD estimation module */
|
|
reset_est_sad(ps_rate_control_api->ps_est_sad);
|
|
|
|
/*remember the previous reference as SCD. This is required to trigger quering model for B
|
|
* frames with delay one sub-gop*/
|
|
ps_rate_control_api->i4_prev_ref_is_scd = 1;
|
|
|
|
/* Reset the MB Rate control */
|
|
init_mb_level_rc(ps_rate_control_api->ps_mb_rate_control);
|
|
|
|
/* Adjust the average QP for the frame based on bits consumption */
|
|
/* Initialize the QP for each picture type according to the average QP of the SCD pic */
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] = (WORD32)i8_avg_qp;
|
|
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC] = (WORD32)i8_avg_qp_q6;
|
|
|
|
ps_rate_control_api->i4_frames_since_last_scd = 0;
|
|
|
|
ps_rate_control_api->f_p_to_i_comp_ratio = 1.0f;
|
|
/* Reset the number of header bits in a scene change */
|
|
//init_prev_header_bits(ps_rate_control_api->ps_bit_allocation, ps_rate_control_api->ps_pic_handling);
|
|
}
|
|
else if(i4_is_pause_to_resume)
|
|
{
|
|
reset_frm_rc_rd_model(ps_rate_control_api->aps_rd_model[e_pic_type]); //ELP_RC
|
|
}
|
|
if(i8_frame_sad && (!i4_suppress_bpic_update))
|
|
{
|
|
/********************************************************************
|
|
Update the model of the correponding picture type
|
|
NOTE: For SCD, we force the frame type from 'P' to that of a 'I'
|
|
*********************************************************************/
|
|
/* For very simple sequences no bits are consumed by texture. These frames
|
|
do not add any information to the model and so not added.
|
|
Update the model only when there is atleast 1 texture bit for every mb in a frame */
|
|
WORD32 i4_tot_texture_bits_added_to_model = i4_tot_texture_bits;
|
|
/*update the model only if bits consumed are zero. If this is zero qp for next frame has to be reduced until
|
|
* it provides some texture bits to update model*/
|
|
|
|
if(i4_tot_texture_bits_added_to_model > 0 && (i4_flag_rc_model_update == 1))
|
|
{
|
|
add_frame_to_rd_model(
|
|
ps_rate_control_api->aps_rd_model[e_pic_type],
|
|
i4_tot_texture_bits_added_to_model,
|
|
(WORD32)i8_avg_qp_q6,
|
|
i8_frame_sad,
|
|
u1_num_skips);
|
|
|
|
{
|
|
number_t temp =
|
|
get_linear_coefficient(ps_rate_control_api->aps_rd_model[e_pic_type]);
|
|
ps_frame_info->model_coeff_a_lin_wo_int.e = temp.e;
|
|
ps_frame_info->model_coeff_a_lin_wo_int.sm = temp.sm;
|
|
}
|
|
}
|
|
|
|
/******************************************************************
|
|
Update the sad estimation module
|
|
NOTE: For SCD, we force the frame type from 'P' to that of a 'I'
|
|
******************************************************************/
|
|
update_actual_sad(
|
|
ps_rate_control_api->ps_est_sad, (UWORD32)i8_frame_sad, e_pic_type);
|
|
/*: This will update I pic sad with current pic intra SAD. Now for non I-PIC the intra sad is coming same as
|
|
*best sad. This will corrupt intra frame sad. So not updating this. I frame SAD is updated only at I pic */
|
|
|
|
/* Atleast one proper frame in added into the model. Until that
|
|
keep using the initial QP */
|
|
|
|
/*B frames immediatly encoded after scene cut may still belong to previous content, When B frames encoded after one P frame after SCD are guranteed to belong
|
|
* new scene, modeling these frames wrt previous B frames might give wrong results. To avoid this model for B frame is not queried unless it is guranteed that one B frame
|
|
* has been modeled with new content. So setting is_first_frm_coded for B frames with delay of one frame*/
|
|
/*In HEVC implementation it is guranteed to encode new scene after scene cut I pic*/
|
|
ps_rate_control_api->au1_is_first_frm_coded[e_pic_type] = 1;
|
|
}
|
|
|
|
if(i4_avg_activity)
|
|
{
|
|
/* Update the mb_level model */
|
|
mb_update_frame_level(ps_rate_control_api->ps_mb_rate_control, i4_avg_activity);
|
|
}
|
|
/* Update the variable which denotes that a frame has been encountered */
|
|
ps_rate_control_api->u1_is_first_frm = 0;
|
|
ps_rate_control_api->i4_frames_since_last_scd++;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/* SGI & Enc Loop Parallelism related changes*/
|
|
/****************************************************************************
|
|
Function Name : update_frame_rc_get_frame_qp_info
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void update_frame_rc_get_frame_qp_info(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
WORD32 i4_is_scd,
|
|
WORD32 i4_is_pause_to_resume,
|
|
WORD32 i4_avg_frame_qp_q6,
|
|
WORD32 i4_suppress_bpic_update,
|
|
WORD32 i4_scene_num,
|
|
WORD32 i4_num_frm_enc_in_scene)
|
|
{
|
|
WORD32 i4_avg_qp = 0, i4_avg_qp_q6 = 0;
|
|
|
|
i4_avg_qp = (i4_avg_frame_qp_q6 >> 6);
|
|
i4_avg_qp_q6 = i4_avg_frame_qp_q6;
|
|
|
|
if(i4_is_scd && (e_pic_type != I_PIC && e_pic_type != P_PIC))
|
|
{
|
|
i4_is_scd = 0;
|
|
}
|
|
|
|
if(e_pic_type == I_PIC)
|
|
{
|
|
ps_rate_control_api->i4_I_frame_qp_model = is_first_frame_coded(ps_rate_control_api);
|
|
}
|
|
if((i4_is_scd && i4_is_pause_to_resume)) //KISH
|
|
i4_is_pause_to_resume = 0;
|
|
|
|
if(i4_is_scd || ps_rate_control_api->u1_is_first_frm)
|
|
{
|
|
/* Save previous B-QP since some B-pics may follow detection of SCD */
|
|
|
|
e_pic_type = I_PIC;
|
|
|
|
/* Reset the SAD estimation module */
|
|
reset_est_sad(ps_rate_control_api->ps_est_sad);
|
|
|
|
/*remember the previous reference as SCD. This is required to trigger quering model for B
|
|
* frames with delay one sub-gop*/
|
|
ps_rate_control_api->i4_prev_ref_is_scd = 1;
|
|
|
|
/* Reset the MB Rate control */
|
|
init_mb_level_rc(ps_rate_control_api->ps_mb_rate_control);
|
|
|
|
/* Adjust the average QP for the frame based on bits consumption */
|
|
/* Initialize the QP for each picture type according to the average QP of the SCD pic */
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] = i4_avg_qp;
|
|
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC] = i4_avg_qp_q6;
|
|
}
|
|
else if(i4_is_pause_to_resume)
|
|
{
|
|
/*pause to resume is guranteed to be P_PIC*/
|
|
ASSERT(e_pic_type != I_PIC);
|
|
|
|
/* re-set all models eccept for I PIC model */
|
|
/*for(i=1;i<MAX_PIC_TYPE;i++)
|
|
{
|
|
reset_frm_rc_rd_model(ps_rate_control_api->aps_rd_model[i]);
|
|
ps_rate_control_api->au1_is_first_frm_coded[i] = 0;
|
|
}*/
|
|
/*resetting only current frame model instead of resetting all models*/
|
|
/*TO DO: i4_is_pause_to_resume is misnomer, as even non I scd are also handled in similar way*/
|
|
//reset_frm_rc_rd_model(ps_rate_control_api->aps_rd_model[e_pic_type]);
|
|
ps_rate_control_api->au1_is_first_frm_coded[e_pic_type] = 0;
|
|
ps_rate_control_api->i4_frames_since_last_scd = 0;
|
|
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][e_pic_type] = i4_avg_qp;
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][e_pic_type] = i4_avg_qp_q6;
|
|
}
|
|
/*also reset previous I pic Qp since it uses I frame qp for qp determination when model is reset*/
|
|
if(e_pic_type == I_PIC)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] = i4_avg_qp;
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC] = i4_avg_qp_q6;
|
|
}
|
|
else if(e_pic_type == P_PIC || e_pic_type == P1_PIC)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp * P_TO_I_RATIO) >> K_Q;
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp_q6 * P_TO_I_RATIO) >> K_Q;
|
|
}
|
|
else if(e_pic_type == B_PIC || e_pic_type == BB_PIC)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp * P_TO_I_RATIO * P_TO_I_RATIO) >> (K_Q + K_Q);
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp_q6 * P_TO_I_RATIO * P_TO_I_RATIO) >> (K_Q + K_Q);
|
|
}
|
|
else if(e_pic_type == B1_PIC || e_pic_type == B11_PIC)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp * P_TO_I_RATIO * P_TO_I_RATIO * P_TO_I_RATIO) >>
|
|
(K_Q + K_Q + K_Q);
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp_q6 * P_TO_I_RATIO * P_TO_I_RATIO * P_TO_I_RATIO) >>
|
|
(K_Q + K_Q + K_Q);
|
|
}
|
|
else if(e_pic_type == B2_PIC || e_pic_type == B22_PIC)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp * P_TO_I_RATIO * P_TO_I_RATIO * P_TO_I_RATIO * P_TO_I_RATIO) >>
|
|
(K_Q + K_Q + K_Q + K_Q);
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][I_PIC] =
|
|
((LWORD64)i4_avg_qp_q6 * P_TO_I_RATIO * P_TO_I_RATIO * P_TO_I_RATIO *
|
|
P_TO_I_RATIO) >>
|
|
(K_Q + K_Q + K_Q + K_Q);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if 1 /* Prev QP updation has happened at the end of the get frame qp call itself */
|
|
/******************************************************************
|
|
Update the Qp used by the current frame
|
|
******************************************************************/
|
|
if(!i4_suppress_bpic_update)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][e_pic_type] = i4_avg_qp;
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][e_pic_type] = i4_avg_qp_q6;
|
|
trace_printf("Prev frame qp q6 update %d pic type %d", i4_avg_qp_q6, e_pic_type);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if(i4_num_frm_enc_in_scene == 1)
|
|
{
|
|
WORD32 i4_i = 0;
|
|
for(i4_i = 0; i4_i < MAX_PIC_TYPE; i4_i++)
|
|
{
|
|
if(ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][i4_i] == 0x7FFFFFFF)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][i4_i] = i4_avg_qp;
|
|
ps_rate_control_api->ai4_prev_frm_qp_q6[i4_scene_num][i4_i] = i4_avg_qp_q6;
|
|
}
|
|
}
|
|
}
|
|
|
|
if((!i4_suppress_bpic_update))
|
|
{
|
|
/*B frames immediatly encoded after scene cut may still belong to previous content, When B frames encoded after one P frame after SCD are guranteed to belong
|
|
* new scene, modeling these frames wrt previous B frames might give wrong results. To avoid this model for B frame is not queried unless it is guranteed that one B frame
|
|
* has been modeled with new content. So setting is_first_frm_coded for B frames with delay of one frame*/
|
|
/*In HEVC implementation it is guranteed to encode new scene after scene cut I pic*/
|
|
//ps_rate_control_api->au1_is_first_frm_coded[e_pic_type] = 1; //KISH_ELP
|
|
}
|
|
|
|
/* Update the variable which denotes that a frame has been encountered */
|
|
ps_rate_control_api->u1_is_first_frm = 0;
|
|
|
|
/* Store the prev encoded picture type for restricting Qp swing */
|
|
if((e_pic_type == I_PIC) || (e_pic_type == P_PIC))
|
|
{
|
|
ps_rate_control_api->prev_ref_pic_type = e_pic_type;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*update previous frame intra sad */
|
|
/****************************************************************************
|
|
Function Name : rc_update_prev_frame_intra_sad
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void rc_update_prev_frame_intra_sad(
|
|
rate_control_api_t *ps_rate_control_api, WORD32 i4_intra_frame_sad)
|
|
{
|
|
update_prev_frame_intra_sad(ps_rate_control_api->ps_est_sad, i4_intra_frame_sad);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_prev_frame_intra_sad
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 rc_get_prev_frame_intra_sad(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return get_prev_frame_intra_sad(ps_rate_control_api->ps_est_sad);
|
|
}
|
|
/*update previous frame sad */
|
|
/****************************************************************************
|
|
Function Name : rc_update_prev_frame_sad
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void rc_update_prev_frame_sad(
|
|
rate_control_api_t *ps_rate_control_api, WORD32 i4_frame_sad, picture_type_e e_pic_type)
|
|
{
|
|
update_prev_frame_sad(ps_rate_control_api->ps_est_sad, i4_frame_sad, e_pic_type);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_prev_frame_sad
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 rc_get_prev_frame_sad(rate_control_api_t *ps_rate_control_api, picture_type_e e_pic_type)
|
|
{
|
|
return get_prev_frame_sad(ps_rate_control_api->ps_est_sad, e_pic_type);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : reset_rc_for_pause_to_play_transition
|
|
Description : In this mode it resets RC only for P and B picture, since the
|
|
sequece has not changed but only the motion related changes would
|
|
take impact
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void reset_rc_for_pause_to_play_transition(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
WORD32 i;
|
|
/* re-set model only for P and B frame */
|
|
for(i = 1; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
reset_frm_rc_rd_model(ps_rate_control_api->aps_rd_model[i]);
|
|
}
|
|
/* Reset flag */
|
|
for(i = 1; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
ps_rate_control_api->au1_is_first_frm_coded[i] = 0;
|
|
}
|
|
}
|
|
/****************************************************************************
|
|
Function Name : get_rc_target_bits
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 get_rc_target_bits(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ps_rate_control_api->i4_prev_frm_est_bits);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : get_orig_rc_target_bits
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 get_orig_rc_target_bits(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ps_rate_control_api->i4_orig_frm_est_bits);
|
|
}
|
|
|
|
#if NON_STEADSTATE_CODE
|
|
/******************************************************************************
|
|
MB Level API functions
|
|
******************************************************************************/
|
|
/****************************************************************************
|
|
Function Name : init_mb_rc_frame_level
|
|
Description : Initialise the frame level details required for a mb level
|
|
Inputs : u1_frame_qp - Frame Qp that is to be used to the current frame
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
|
|
void init_mb_rc_frame_level(rate_control_api_t *ps_rate_control_api, UWORD8 u1_frame_qp)
|
|
{
|
|
mb_init_frame_level(ps_rate_control_api->ps_mb_rate_control, u1_frame_qp);
|
|
}
|
|
#endif /* #if NON_STEADSTATE_CODE */
|
|
|
|
/****************************************************************************
|
|
Function Name : get_bits_to_stuff
|
|
Description : Gets the bits to stuff to prevent Underflow of Encoder Buffer
|
|
Inputs : Rate control API ctxt , total consumed bits
|
|
Globals :
|
|
Processing :
|
|
Outputs : number of bits to stuff
|
|
Returns : i4_bits_to_stuff
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 get_bits_to_stuff(
|
|
rate_control_api_t *ps_rate_control_api, WORD32 i4_tot_consumed_bits, picture_type_e e_pic_type)
|
|
{
|
|
WORD32 i4_bits_to_stuff;
|
|
/* Get the CBR bits to stuff*/
|
|
i4_bits_to_stuff =
|
|
get_cbr_bits_to_stuff(ps_rate_control_api->ps_cbr_buffer, i4_tot_consumed_bits, e_pic_type);
|
|
return i4_bits_to_stuff;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : get_prev_frm_est_bits
|
|
Description : Returns previous frame estimated bits
|
|
Inputs : Rate control API ctxt
|
|
Globals :
|
|
Processing :
|
|
Outputs : previous frame estimated bits
|
|
Returns : i4_prev_frm_est_bits
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 get_prev_frm_est_bits(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ps_rate_control_api->i4_prev_frm_est_bits);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : change_frm_rate_for_bit_alloc
|
|
Description : Does the necessary changes only in the bit_allocation module
|
|
there is a change in frame rate
|
|
Inputs : u4_frame_rate - new frame rate to be used
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void change_frm_rate_for_bit_alloc(rate_control_api_t *ps_rate_control_api, UWORD32 u4_frame_rate)
|
|
{
|
|
if(ps_rate_control_api->e_rc_type != CONST_QP)
|
|
{
|
|
/* Bit Allocation Module: distribute the excess/deficit bits between the
|
|
old and the new frame rate to all the remaining frames */
|
|
change_remaining_bits_in_period(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ba_get_bit_rate(ps_rate_control_api->ps_bit_allocation),
|
|
u4_frame_rate,
|
|
(WORD32 *)(ps_rate_control_api->au4_new_peak_bit_rate));
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Function Name : rc_get_rem_bits_in_gop
|
|
* Description : API call to get remaining bits in GOP
|
|
* *****************************************************************************/
|
|
WORD32 rc_get_rem_bits_in_period(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (get_rem_bits_in_period(
|
|
ps_rate_control_api->ps_bit_allocation, ps_rate_control_api->ps_pic_handling));
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : flush_buf_frames
|
|
Description : API call to flush the buffered up frames
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void flush_buf_frames(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
flush_frame_from_pic_stack(ps_rate_control_api->ps_pic_handling);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_get_prev_header_bits
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 rc_get_prev_header_bits(rate_control_api_t *ps_rate_control_api, WORD32 pic_type)
|
|
{
|
|
return (get_prev_header_bits(ps_rate_control_api->ps_bit_allocation, pic_type));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_prev_P_QP
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 rc_get_prev_P_QP(rate_control_api_t *ps_rate_control_api, WORD32 i4_scene_num)
|
|
{
|
|
WORD32 i4_prev_qp = ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][P_PIC];
|
|
i4_prev_qp =
|
|
(ps_rate_control_api->i4_P_to_I_ratio * i4_prev_qp + (1 << (P_TO_I_RATIO_Q_FACTOR - 1))) >>
|
|
P_TO_I_RATIO_Q_FACTOR;
|
|
return (i4_prev_qp);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_put_sad
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void rc_put_sad(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 i4_cur_intra_sad,
|
|
WORD32 i4_cur_sad,
|
|
WORD32 i4_cur_pic_type)
|
|
{
|
|
sad_acc_put_sad(ps_rate_control_api->ps_sad_acc, i4_cur_intra_sad, i4_cur_sad, i4_cur_pic_type);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_sad
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void rc_get_sad(rate_control_api_t *ps_rate_control_api, WORD32 *pi4_sad)
|
|
{
|
|
sad_acc_get_sad(ps_rate_control_api->ps_sad_acc, pi4_sad);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_update_ppic_sad
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 rc_update_ppic_sad(
|
|
rate_control_api_t *ps_rate_control_api, WORD32 i4_est_sad, WORD32 i4_prev_ppic_sad)
|
|
{
|
|
return (update_ppic_sad(ps_rate_control_api->ps_est_sad, i4_est_sad, i4_prev_ppic_sad));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : change_avg_bit_rate
|
|
Description : Whenever the average bit rate changes, the excess bits is
|
|
between the changed bit rate and the old one is re-distributed
|
|
in the bit allocation module
|
|
Inputs : u4_average_bit_rate - new average bit rate to be used
|
|
: u4_peak_bit_rate - new peak bit rate to be used
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void change_avg_bit_rate(
|
|
rate_control_api_t *ps_rate_control_api, UWORD32 u4_average_bit_rate, UWORD32 u4_peak_bit_rate)
|
|
{
|
|
int i;
|
|
|
|
if(ps_rate_control_api->e_rc_type != CONST_QP)
|
|
{
|
|
if(ps_rate_control_api->e_rc_type == CBR_NLDRC)
|
|
{
|
|
ps_rate_control_api->au4_new_peak_bit_rate[0] = u4_average_bit_rate;
|
|
ps_rate_control_api->au4_new_peak_bit_rate[1] = u4_average_bit_rate;
|
|
}
|
|
else
|
|
{
|
|
ps_rate_control_api->au4_new_peak_bit_rate[0] = u4_peak_bit_rate;
|
|
ps_rate_control_api->au4_new_peak_bit_rate[1] = u4_peak_bit_rate;
|
|
}
|
|
/* Bit Allocation Module: distribute the excess/deficit bits between the
|
|
old and the new frame rate to all the remaining frames */
|
|
change_remaining_bits_in_period(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
u4_average_bit_rate,
|
|
ba_get_frame_rate(ps_rate_control_api->ps_bit_allocation),
|
|
(WORD32 *)(ps_rate_control_api->au4_new_peak_bit_rate));
|
|
}
|
|
//if(ps_rate_control_api->e_rc_type == CBR_NLDRC)
|
|
{
|
|
UWORD32 u4_average_bit_rate_copy[MAX_NUM_DRAIN_RATES];
|
|
/*DYNAMIC_RC*/
|
|
//ps_rate_control_api->au4_new_peak_bit_rate[0]=u4_average_bit_rate;
|
|
//ps_rate_control_api->au4_new_peak_bit_rate[1]=u4_average_bit_rate;
|
|
for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
|
|
{
|
|
u4_average_bit_rate_copy[i] = u4_average_bit_rate;
|
|
}
|
|
change_cbr_vbv_bit_rate(
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
(WORD32 *)(u4_average_bit_rate_copy),
|
|
(WORD32)ps_rate_control_api->au4_new_peak_bit_rate[0]);
|
|
}
|
|
|
|
/* This is done only for average bitrate changing somewhere after the model stabilises.
|
|
Here it is assumed that user will not do this call after first few frames.
|
|
If we dont have this check, what would happen is since the model has not stabilised, also
|
|
bitrate has changed before the first frame, we dont restrict the qp. Qp can go to
|
|
very bad values after init qp since if swing is disabled
|
|
|
|
*/
|
|
if(ps_rate_control_api->u1_is_first_frm == 0)
|
|
{
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
/*This also makes sure the qp swing restrictions wont be applied at boundary of bitrate change*/
|
|
ps_rate_control_api->au1_avg_bitrate_changed[i] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if NON_STEADSTATE_CODE
|
|
/******************************************************************************
|
|
Control Level API functions
|
|
Logic: The control call sets the state structure of the rate control api
|
|
accordingly such that the next process call would implement the same.
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
Function Name : change_inter_frm_int_call
|
|
Description :
|
|
Arguments :
|
|
Return Values : void
|
|
Revision History:
|
|
Creation
|
|
|
|
Assumptions -
|
|
|
|
Checks -
|
|
*****************************************************************************/
|
|
void change_inter_frm_int_call(rate_control_api_t *ps_rate_control_api, WORD32 i4_inter_frm_int)
|
|
{
|
|
pic_handling_register_new_inter_frm_interval(
|
|
ps_rate_control_api->ps_pic_handling, i4_inter_frm_int);
|
|
}
|
|
/******************************************************************************
|
|
Function Name : change_intra_frm_int_call
|
|
Description :
|
|
Arguments :
|
|
Return Values : void
|
|
Revision History:
|
|
Creation
|
|
|
|
Assumptions -
|
|
|
|
Checks -
|
|
*****************************************************************************/
|
|
void change_intra_frm_int_call(rate_control_api_t *ps_rate_control_api, WORD32 i4_intra_frm_int)
|
|
{
|
|
pic_handling_register_new_int_frm_interval(
|
|
ps_rate_control_api->ps_pic_handling, i4_intra_frm_int);
|
|
|
|
if(ps_rate_control_api->e_rc_type == VBR_STREAMING)
|
|
{
|
|
change_vsp_ifi(&ps_rate_control_api->s_vbr_str_prms, i4_intra_frm_int);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : change_frame_rate
|
|
Description : Does the necessary changes whenever there is a change in
|
|
frame rate
|
|
Inputs : u4_frame_rate - new frame rate to be used
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void change_frame_rate(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
UWORD32 u4_frame_rate,
|
|
UWORD32 u4_src_ticks,
|
|
UWORD32 u4_tgt_ticks)
|
|
{
|
|
if(ps_rate_control_api->e_rc_type != CONST_QP)
|
|
{
|
|
UWORD32 u4_frms_in_delay_prd =
|
|
((u4_frame_rate * get_cbr_buffer_delay(ps_rate_control_api->ps_cbr_buffer)) / 1000000);
|
|
if((ps_rate_control_api->e_rc_type == VBR_STORAGE) ||
|
|
(ps_rate_control_api->e_rc_type == VBR_STORAGE_DVD_COMP))
|
|
{
|
|
change_vbr_vbv_frame_rate(ps_rate_control_api->ps_vbr_storage_vbv, u4_frame_rate);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == CBR_NLDRC)
|
|
{
|
|
change_cbr_vbv_tgt_frame_rate(ps_rate_control_api->ps_cbr_buffer, u4_frame_rate);
|
|
}
|
|
else if(ps_rate_control_api->e_rc_type == VBR_STREAMING)
|
|
{
|
|
UWORD32 au4_num_pics_in_delay_prd[MAX_PIC_TYPE];
|
|
change_vsp_tgt_ticks(&ps_rate_control_api->s_vbr_str_prms, u4_tgt_ticks);
|
|
change_vsp_src_ticks(&ps_rate_control_api->s_vbr_str_prms, u4_src_ticks);
|
|
change_vsp_fidp(&ps_rate_control_api->s_vbr_str_prms, u4_frms_in_delay_prd);
|
|
|
|
change_cbr_vbv_tgt_frame_rate(ps_rate_control_api->ps_cbr_buffer, u4_frame_rate);
|
|
change_cbr_vbv_num_pics_in_delay_period(
|
|
ps_rate_control_api->ps_cbr_buffer, au4_num_pics_in_delay_prd);
|
|
}
|
|
|
|
/* Bit Allocation Module: distribute the excess/deficit bits between the
|
|
old and the new frame rate to all the remaining frames */
|
|
change_remaining_bits_in_period(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ba_get_bit_rate(ps_rate_control_api->ps_bit_allocation),
|
|
u4_frame_rate,
|
|
(WORD32 *)(ps_rate_control_api->au4_new_peak_bit_rate));
|
|
}
|
|
}
|
|
/****************************************************************************
|
|
Function Name : change_init_qp
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void change_init_qp(
|
|
rate_control_api_t *ps_rate_control_api, WORD32 *pi4_init_qp, WORD32 i4_scene_num)
|
|
{
|
|
WORD32 i;
|
|
/* Initialize the init_qp */
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
ps_rate_control_api->ai4_prev_frm_qp[i4_scene_num][i] = pi4_init_qp[i];
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : change_min_max_qp
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void change_min_max_qp(rate_control_api_t *ps_rate_control_api, WORD32 *pi4_min_max_qp)
|
|
{
|
|
WORD32 i;
|
|
for(i = 0; i < MAX_PIC_TYPE; i++)
|
|
{
|
|
ps_rate_control_api->ai4_min_qp[i] = pi4_min_max_qp[(i << 1)];
|
|
ps_rate_control_api->ai4_max_qp[i] = pi4_min_max_qp[(i << 1) + 1];
|
|
}
|
|
|
|
change_init_qp_max_qp(ps_rate_control_api->ps_init_qp, pi4_min_max_qp);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_frame_rate
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
/* Getter functions to get the current rate control parameters */
|
|
UWORD32 rc_get_frame_rate(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ba_get_frame_rate(ps_rate_control_api->ps_bit_allocation));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_bit_rate
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
UWORD32 rc_get_bit_rate(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ba_get_bit_rate(ps_rate_control_api->ps_bit_allocation));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_peak_bit_rate
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
UWORD32 rc_get_peak_bit_rate(rate_control_api_t *ps_rate_control_api, WORD32 i4_index)
|
|
{
|
|
return (ps_rate_control_api->au4_new_peak_bit_rate[i4_index]);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_intra_frame_interval
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
UWORD32 rc_get_intra_frame_interval(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (pic_type_get_intra_frame_interval(ps_rate_control_api->ps_pic_handling));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_inter_frame_interval
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
UWORD32 rc_get_inter_frame_interval(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (pic_type_get_inter_frame_interval(ps_rate_control_api->ps_pic_handling));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_rc_type
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
rc_type_e rc_get_rc_type(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ps_rate_control_api->e_rc_type);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_bits_per_frame
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
WORD32 rc_get_bits_per_frame(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
WORD32 i4_bits_per_frm;
|
|
|
|
X_PROD_Y_DIV_Z(
|
|
ba_get_bit_rate(ps_rate_control_api->ps_bit_allocation),
|
|
(UWORD32)1000,
|
|
ba_get_frame_rate(ps_rate_control_api->ps_bit_allocation),
|
|
i4_bits_per_frm);
|
|
|
|
return (i4_bits_per_frm);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_max_delay
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
UWORD32 rc_get_max_delay(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (get_cbr_buffer_delay(ps_rate_control_api->ps_cbr_buffer));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_seq_no
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
UWORD32 rc_get_seq_no(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (pic_type_get_disp_order_no(ps_rate_control_api->ps_pic_handling));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_rem_frames_in_gop
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
UWORD32 rc_get_rem_frames_in_gop(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
/* Get the rem_frms_in_gop & the frms_in_gop from the pic_type state struct */
|
|
return (pic_type_get_rem_frms_in_gop(ps_rate_control_api->ps_pic_handling));
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : flush_buf_frames
|
|
Description : API call to flush the buffered up frames
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void post_encode_frame_skip(rate_control_api_t *ps_rate_control_api, picture_type_e e_pic_type)
|
|
{
|
|
skip_encoded_frame(ps_rate_control_api->ps_pic_handling, e_pic_type);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : force_I_frame
|
|
Description : API call to force an I frame
|
|
*****************************************************************************/
|
|
void force_I_frame(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
set_force_I_frame_flag(ps_rate_control_api->ps_pic_handling);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Function Name : rc_get_vbv_buf_fullness
|
|
* Description : API call to get VBV buffer fullness
|
|
******************************************************************************/
|
|
WORD32 rc_get_vbv_buf_fullness(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (get_cur_vbv_buf_size(ps_rate_control_api->ps_vbr_storage_vbv));
|
|
}
|
|
/****************************************************************************
|
|
* Function Name : rc_get_cur_peak_factor_2pass
|
|
* Description : API call to get current peak factor
|
|
******************************************************************************/
|
|
float rc_get_cur_peak_factor_2pass(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (get_cur_peak_factor_2pass(ps_rate_control_api->ps_bit_allocation));
|
|
}
|
|
/****************************************************************************
|
|
* Function Name : rc_get_min_complexity_factor_2pass
|
|
* Description : API call to get minimm complexity factor
|
|
******************************************************************************/
|
|
float rc_get_min_complexity_factor_2pass(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (get_cur_min_complexity_factor_2pass(ps_rate_control_api->ps_bit_allocation));
|
|
}
|
|
/****************************************************************************
|
|
* Function Name : rc_get_vbv_buf_size
|
|
* Description : API call to get VBV buffer size
|
|
******************************************************************************/
|
|
WORD32 rc_get_vbv_buf_size(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (get_cbr_buffer_size(ps_rate_control_api->ps_cbr_buffer));
|
|
}
|
|
/****************************************************************************
|
|
* Function Name : rc_get_vbv_fulness_with_cur_bits
|
|
* Description : API call to get VBV buffer fullness with current bits
|
|
******************************************************************************/
|
|
WORD32 rc_get_vbv_fulness_with_cur_bits(rate_control_api_t *ps_rate_control_api, UWORD32 u4_bits)
|
|
{
|
|
return (get_vbv_buf_fullness(ps_rate_control_api->ps_vbr_storage_vbv, u4_bits));
|
|
}
|
|
/****************************************************************************
|
|
* Function Name : rc_set_avg_mb_act
|
|
* Description :
|
|
******************************************************************************/
|
|
void rc_set_avg_mb_act(rate_control_api_t *ps_rate_control_api, WORD32 i4_avg_activity)
|
|
{
|
|
mb_update_frame_level(ps_rate_control_api->ps_mb_rate_control, i4_avg_activity);
|
|
return;
|
|
}
|
|
/****************************************************************************
|
|
* Function Name : rc_init_set_ebf
|
|
* Description : API call to set EBF
|
|
******************************************************************************/
|
|
void rc_init_set_ebf(rate_control_api_t *ps_rate_control_api, WORD32 i32_init_ebf)
|
|
{
|
|
set_cbr_ebf(ps_rate_control_api->ps_cbr_buffer, i32_init_ebf);
|
|
}
|
|
#endif /* #if NON_STEADSTATE_CODE */
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_get_qp_scene_change_bits
|
|
Description : HEVC specific function to get scene change qp at scene cut location
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
WORD32 rc_get_qp_scene_change_bits(
|
|
rate_control_handle ps_rate_control_api,
|
|
WORD32 i4_total_bits,
|
|
LWORD64 i8_satd_by_act_accum,
|
|
WORD32 i4_num_pixel,
|
|
void *offline_model_coeff,
|
|
float f_i_to_average_rest,
|
|
WORD32 i4_call_type)
|
|
{
|
|
float f_trial_q_scale;
|
|
WORD32 i4_tex_bits = 0, i4_header_bits = 0;
|
|
WORD32 error = 0, min_error = 0x7FFFFFFF, i4_is_high_bitrate = 0;
|
|
double *model_coeff, min_error_q_scale = (double)127;
|
|
double min_scd_qscale, max_scd_q_scale;
|
|
WORD32 i4_QP, i4_max_Qp, i4_min_Qp, i4_qp_selection_flag = 0;
|
|
WORD32 i4_prev_best = -1;
|
|
|
|
/*The qp calculation here is based on offline generated stat for around 30 frames belonging to different scene
|
|
The I only mode of encode was done for the above sequence for qp range {8,51}. A quadratic and cubic curve was obtained
|
|
based on the stat geneated.
|
|
eq coeff*/
|
|
float coeff_a, coeff_b, coeff_c, coeff_d, X, tex_bpp;
|
|
float min_qp_qscale_multiplier =
|
|
1; /*For fade-in fade-out case where scene starts with blank frame have higher min frame qp*/
|
|
//float head_per;
|
|
float normal_satd_act;
|
|
float bpp = (float)get_bits_per_frame(ps_rate_control_api->ps_bit_allocation) / i4_num_pixel;
|
|
|
|
if(i4_num_pixel > 5000000) /*UHD*/
|
|
{
|
|
if(bpp > 0.12) /*30mbp 2160 30p*/
|
|
i4_is_high_bitrate = 1;
|
|
else if(bpp > 0.06)
|
|
i4_is_high_bitrate = 2;
|
|
else if(bpp > 0.03)
|
|
i4_is_high_bitrate = 3;
|
|
}
|
|
else
|
|
{
|
|
if(bpp > 0.16) /*10mbps 1080 30p*/
|
|
i4_is_high_bitrate = 1;
|
|
else if(bpp > 0.08)
|
|
i4_is_high_bitrate = 2;
|
|
else if(bpp > 0.04)
|
|
i4_is_high_bitrate = 3;
|
|
}
|
|
/*Min qp and Max qp at scene cut is critical since offline models are not reliable always*/
|
|
/*During fade-in fade-out when LAP places I frame on blank pictures but the content slowly changes to complicated content, Due to low
|
|
spatial complxity of I pic a very low SCD qp will be allocated, qp swing restriction will not give enough frames to increase qp to high value
|
|
to encode such fast motion inter pictiures .Hence whenever temporal complexity is very high assume some least spatial complexity so that very low qp
|
|
is not chosen*/
|
|
if(f_i_to_average_rest < I_TO_REST_VVFAST &&
|
|
(i4_is_high_bitrate !=
|
|
1)) /*The I_TO_AVERAGE RATIO generally comes very low, hence this wont be measure of extent on motion in inter pictures*/
|
|
{
|
|
WORD32 i4_min_num_pixel = i4_num_pixel;
|
|
|
|
if(i4_num_pixel > 5000000)
|
|
{
|
|
i4_min_num_pixel = i4_min_num_pixel / 2;
|
|
}
|
|
|
|
if(i8_satd_by_act_accum <
|
|
i4_num_pixel) /*In very fast motion case have min threshold for I frame, Assume atleast one unit per pixel sad*/
|
|
{
|
|
if(i4_is_high_bitrate == 2)
|
|
{
|
|
i8_satd_by_act_accum = (LWORD64)(i4_min_num_pixel / 2);
|
|
}
|
|
else if(i4_is_high_bitrate == 3)
|
|
{
|
|
i8_satd_by_act_accum = (LWORD64)(i4_min_num_pixel * 3.0f / 4.0f);
|
|
}
|
|
else
|
|
i8_satd_by_act_accum = (LWORD64)(i4_min_num_pixel);
|
|
|
|
min_qp_qscale_multiplier = (float)pow(
|
|
(float)1.125f,
|
|
(WORD32)6); //this will make min qp for simple frame with high moiton 24 instead of 18
|
|
}
|
|
}
|
|
min_scd_qscale = pow(2, (double)(ps_rate_control_api->u4_min_scd_hevc_qp - 4) / 6) *
|
|
min_qp_qscale_multiplier;
|
|
max_scd_q_scale = pow(2, (double)(SCD_MAX_HEVC_QP - 4) / 6);
|
|
i4_max_Qp = MAX_HEVC_QP;
|
|
i4_min_Qp = ps_rate_control_api->u4_min_scd_hevc_qp;
|
|
if((ps_rate_control_api->u1_bit_depth > 8) && (i4_call_type == 1))
|
|
{
|
|
i8_satd_by_act_accum = i8_satd_by_act_accum << (ps_rate_control_api->u1_bit_depth - 8);
|
|
i4_max_Qp = i4_max_Qp + (6 * (ps_rate_control_api->u1_bit_depth - 8));
|
|
i4_min_Qp = i4_min_Qp + (6 * (ps_rate_control_api->u1_bit_depth - 8));
|
|
max_scd_q_scale = max_scd_q_scale * (1 << (ps_rate_control_api->u1_bit_depth - 8));
|
|
}
|
|
|
|
normal_satd_act = (float)i8_satd_by_act_accum / i4_num_pixel;
|
|
|
|
{
|
|
/* Max satd/act at L0 was taken at qp 18 for
|
|
480p - 4410520
|
|
720p - 9664235
|
|
1080p - 15735650
|
|
4k - 50316472
|
|
A curve was generated using these points
|
|
*/
|
|
|
|
float f_satd_by_Act_norm = GET_L0_SATD_BY_ACT_MAX_PER_PIXEL(i4_num_pixel);
|
|
float f_weigh_factor = 0.0f;
|
|
f_satd_by_Act_norm = f_satd_by_Act_norm * 0.75f;
|
|
f_weigh_factor = GET_WEIGH_FACTOR_FOR_MIN_SCD_Q_SCALE(normal_satd_act, f_satd_by_Act_norm);
|
|
CLIP(f_weigh_factor, 1.0f, 1.0f / MULT_FACTOR_SATD);
|
|
min_scd_qscale = min_scd_qscale * f_weigh_factor;
|
|
CLIP(min_scd_qscale, max_scd_q_scale, 1);
|
|
}
|
|
|
|
/*coeff value based on input resolution
|
|
1920x1090 -> 207360,1280x720->921600,720x480->345600(unlike for I_REST_AVG_BIT_RATIO here 720x480 was considered as low resolution)
|
|
ultra high res = num_pixek > 5000000
|
|
high_res = num_pxel > 1500000
|
|
mid res = num_pixel > 600000
|
|
low_res = num_pixel < 600000
|
|
The fit is based on HEVC qp value between 18 and 48 inclusive
|
|
*/
|
|
/*adding coeff for ultra HD resolution*/
|
|
/*
|
|
High quality bpp vs nor satd/act/qp
|
|
--------------------------------------
|
|
480p y = -0.1823x3 + 0.5258x2 + 1.7707x - 0.0394
|
|
720p y = -0.1458x3 + 0.4039x2 + 1.8817x - 0.0648
|
|
1080p y = -0.4712x3 + 1.3818x2 + 1.2797x - 0.0262
|
|
2160p y = -1.1234x3 + 2.6328x2 + 0.8817x - 0.0047
|
|
|
|
|
|
Medium speed
|
|
------------
|
|
480p y = -0.1567x3 + 0.4222x2 + 1.8899x - 0.0537
|
|
720p y = -0.1417x3 + 0.3699x2 + 1.9611x - 0.0766
|
|
1080p y = -0.4841x3 + 1.4123x2 + 1.2981x - 0.0321
|
|
2160p y = -1.1989x3 + 2.7935x2 + 0.8648x - 0.0074
|
|
|
|
High speed
|
|
-------------
|
|
480p y = -0.1611x3 + 0.4418x2 + 1.8754x - 0.0524
|
|
720p y = -0.1455x3 + 0.3854x2 + 1.951x - 0.0753
|
|
1080p y = -0.4908x3 + 1.4344x2 + 1.2848x - 0.031
|
|
2160p y = -1.2037x3 + 2.8062x2 + 0.8551x - 0.0067
|
|
*/
|
|
model_coeff = (double *)offline_model_coeff;
|
|
coeff_a = (float)model_coeff[0];
|
|
coeff_b = (float)model_coeff[1];
|
|
coeff_c = (float)model_coeff[2];
|
|
coeff_d = (float)model_coeff[3];
|
|
for(i4_QP = i4_min_Qp; i4_QP < i4_max_Qp; i4_QP++)
|
|
{
|
|
/*needs to use the array for qp to qscale */
|
|
|
|
f_trial_q_scale = (float)(pow(2.0, (i4_QP - 4.0) / 6.0));
|
|
/* curve fit for texture bits*/
|
|
X = (float)normal_satd_act / f_trial_q_scale;
|
|
tex_bpp = ((coeff_a * X * X * X) + (coeff_b * X * X) + (coeff_c * X) + coeff_d);
|
|
if(tex_bpp < (float)((1 << 30)) / i4_num_pixel)
|
|
i4_tex_bits = (tex_bpp * i4_num_pixel);
|
|
else
|
|
i4_tex_bits = (1 << 30);
|
|
i4_header_bits = 0;
|
|
if(i4_tex_bits > 0)
|
|
{
|
|
/*QP increase can't cause increase in bits*/
|
|
if(i4_prev_best != -1 && (i4_tex_bits > i4_prev_best))
|
|
{
|
|
min_error = 0x7FFFFFFF;
|
|
i4_qp_selection_flag = 0;
|
|
}
|
|
/*consider texture bits to get header bits using obtained header percentage. Using header bits on overall bits targetted might not be correct*/
|
|
error = i4_total_bits - (i4_tex_bits + i4_header_bits);
|
|
if(abs(error) < abs(min_error))
|
|
{
|
|
min_error = error;
|
|
min_error_q_scale = f_trial_q_scale;
|
|
i4_qp_selection_flag = 1;
|
|
i4_prev_best = i4_tex_bits;
|
|
}
|
|
}
|
|
}
|
|
if(!i4_qp_selection_flag)
|
|
{
|
|
min_error_q_scale = (WORD32)(min_scd_qscale + 0.5);
|
|
}
|
|
//if((ps_rate_control_api->u1_bit_depth > 8)&& (i4_call_type == 1))
|
|
// min_error_q_scale = min_error_q_scale / (1 << (ps_rate_control_api->u1_bit_depth - 8));
|
|
|
|
/*offline stat generation range considered is mpeg2qp 5 to 161 or hevc qp 18 to 48*/
|
|
CLIP(min_error_q_scale, (WORD32)(max_scd_q_scale + 0.5), (WORD32)(min_scd_qscale + .5));
|
|
return ((WORD32)(min_error_q_scale * (1 << QSCALE_Q_FAC_3)));
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_get_qp_for_scd_frame
|
|
Description : Get qp for a scene cut frame
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
WORD32 rc_get_qp_for_scd_frame(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
LWORD64 i8_satd_act_accum,
|
|
WORD32 i4_num_pels_in_frame,
|
|
WORD32 i4_est_I_pic_head_bits,
|
|
WORD32 i4_f_sim_lap_avg,
|
|
void *offline_model_coeff,
|
|
float i_to_avg_ratio,
|
|
WORD32 i4_true_scd,
|
|
float af_sum_weigh[MAX_PIC_TYPE][3],
|
|
frame_info_t *ps_frame_stat,
|
|
WORD32 i4_rc_2_pass,
|
|
WORD32 i4_is_not_an_I_pic,
|
|
WORD32 i4_ref_first_pass,
|
|
WORD32 i4_call_type,
|
|
WORD32 *pi4_cur_est_tot_bits,
|
|
WORD32 *pi4_tot_bits_estimated,
|
|
WORD32 i4_use_offline_model_2pass,
|
|
LWORD64 *pi8_i_tex_bits,
|
|
float *pf_i_qs,
|
|
WORD32 i4_best_br_id,
|
|
WORD32 *pi4_estimate_to_calc_frm_error)
|
|
{
|
|
WORD32 i4_qs_q3, i4_buf_based_min_bits, i4_buf_based_max_bits, i4_cur_est_tot_bits,
|
|
i4_est_texture_bits, i4_get_error = 0;
|
|
float f_bits_ratio;
|
|
|
|
assign_complexity_coeffs(ps_rate_control_api->ps_bit_allocation, af_sum_weigh);
|
|
|
|
i4_cur_est_tot_bits = get_scene_change_tot_frm_bits(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
i4_num_pels_in_frame,
|
|
i4_f_sim_lap_avg,
|
|
i_to_avg_ratio,
|
|
i4_call_type,
|
|
i4_is_not_an_I_pic,
|
|
ps_rate_control_api->i4_is_infinite_gop);
|
|
if(i4_call_type == 1)
|
|
{
|
|
*pi4_estimate_to_calc_frm_error = i4_cur_est_tot_bits;
|
|
}
|
|
|
|
/* vbv buffer position based error correction to keep away encoder buffer overflow at layer 0 pictures*/
|
|
if(e_pic_type == I_PIC || e_pic_type == P_PIC || e_pic_type == P1_PIC)
|
|
{
|
|
WORD32 i4_cur_ebf = get_cbr_ebf(ps_rate_control_api->ps_cbr_buffer);
|
|
WORD32 i4_vbv_size = get_cbr_buffer_size(ps_rate_control_api->ps_cbr_buffer);
|
|
WORD32 i4_max_ebf = (WORD32)(i4_vbv_size * MAX_THRESHOLD_VBV_FRM_ERROR);
|
|
WORD32 i4_drain_rate = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
WORD32 i4_total_bits_allocted = i4_cur_est_tot_bits;
|
|
WORD32 i4_total_bits_to_be_alloc;
|
|
WORD32 i4_expected_ebf = (i4_cur_ebf + i4_total_bits_allocted - i4_drain_rate);
|
|
/*if expected ebf is greater than max threashold, correct the allocation such that it never cross max
|
|
but if it less than drain rate, atleast give drainrate bits*/
|
|
if(i4_expected_ebf > i4_max_ebf)
|
|
{
|
|
i4_total_bits_to_be_alloc =
|
|
MAX(i4_drain_rate, (i4_total_bits_allocted - (i4_expected_ebf - i4_max_ebf)));
|
|
i4_cur_est_tot_bits = i4_total_bits_to_be_alloc;
|
|
}
|
|
}
|
|
if(i4_call_type == 1)
|
|
{
|
|
i4_get_error = rc_get_estimate_bit_error(ps_rate_control_api);
|
|
}
|
|
if(i4_est_I_pic_head_bits != -1)
|
|
/*get constraints from buffer*/
|
|
{
|
|
get_min_max_bits_based_on_buffer(
|
|
ps_rate_control_api,
|
|
e_pic_type,
|
|
&i4_buf_based_min_bits,
|
|
&i4_buf_based_max_bits,
|
|
i4_get_error);
|
|
if(i4_cur_est_tot_bits > i4_buf_based_max_bits)
|
|
i4_cur_est_tot_bits = i4_buf_based_max_bits;
|
|
if((i4_cur_est_tot_bits < i4_buf_based_min_bits) && (i_to_avg_ratio > 8.0))
|
|
i4_cur_est_tot_bits = i4_buf_based_min_bits;
|
|
}
|
|
if(i4_est_I_pic_head_bits <
|
|
0) //indicates header bits data is not available. Assume default ratio
|
|
{
|
|
i4_est_texture_bits = (i4_cur_est_tot_bits * DEFAULT_TEX_PERCENTAGE_Q5) >> 5;
|
|
i4_est_I_pic_head_bits = i4_cur_est_tot_bits - i4_est_texture_bits;
|
|
}
|
|
if((i4_cur_est_tot_bits - i4_est_I_pic_head_bits) < 0)
|
|
i4_cur_est_tot_bits = i4_est_I_pic_head_bits;
|
|
|
|
*pi4_tot_bits_estimated = i4_cur_est_tot_bits;
|
|
|
|
if(i4_true_scd)
|
|
{
|
|
/*texture bits should be atleast 25% of header bits*/
|
|
if(i4_cur_est_tot_bits < (1.25 * i4_est_I_pic_head_bits))
|
|
i4_cur_est_tot_bits = (WORD32)(1.25 * i4_est_I_pic_head_bits);
|
|
|
|
ps_rate_control_api->i4_scd_I_frame_estimated_tot_bits = i4_cur_est_tot_bits;
|
|
}
|
|
|
|
/* Get qp for scene cut frame based on offline generated data*/
|
|
|
|
i4_qs_q3 = rc_get_qp_scene_change_bits(
|
|
ps_rate_control_api,
|
|
(i4_cur_est_tot_bits - i4_est_I_pic_head_bits),
|
|
i8_satd_act_accum,
|
|
i4_num_pels_in_frame,
|
|
offline_model_coeff,
|
|
i_to_avg_ratio,
|
|
i4_call_type);
|
|
|
|
if(i4_call_type)
|
|
trace_printf(
|
|
"i4_qp %d, i8_satd_act_accum %I64d,i_to_avg_ratio %f, "
|
|
"i4_est_I_pic_head_bits %d i4_cur_est_tot_bits %d\n",
|
|
i4_qp,
|
|
i8_satd_act_accum,
|
|
i_to_avg_ratio,
|
|
i4_est_I_pic_head_bits,
|
|
i4_cur_est_tot_bits);
|
|
|
|
*pi4_cur_est_tot_bits = i4_cur_est_tot_bits;
|
|
|
|
return (i4_qs_q3);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_set_num_scd_in_lap_window
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_set_num_scd_in_lap_window(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 i4_num_scd_in_lap_window,
|
|
WORD32 i4_num_frames_b4_scd)
|
|
{
|
|
bit_allocation_set_num_scd_lap_window(
|
|
ps_rate_control_api->ps_bit_allocation, i4_num_scd_in_lap_window, i4_num_frames_b4_scd);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_next_sc_i_in_rc_look_ahead
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_set_next_sc_i_in_rc_look_ahead(
|
|
rate_control_api_t *ps_rate_control_api, WORD32 i4_next_sc_i_in_rc_look_ahead)
|
|
{
|
|
bit_allocation_set_sc_i_in_rc_look_ahead(
|
|
ps_rate_control_api->ps_bit_allocation, i4_next_sc_i_in_rc_look_ahead);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Function Name : rc_update_mismatch_error
|
|
* Description : API call to update remaining bits in period based on error
|
|
* between rdopt bits estimate and actual bits produced in entorpy
|
|
* *****************************************************************************/
|
|
void rc_update_mismatch_error(rate_control_api_t *ps_rate_control_api, WORD32 i4_error_bits)
|
|
{
|
|
bit_allocation_update_gop_level_bit_error(
|
|
ps_rate_control_api->ps_bit_allocation, i4_error_bits);
|
|
/*Also alter the encoder buffer fullness based on the error*/
|
|
/*error = rdopt - entropy hence subtract form current buffer fullness*/
|
|
update_cbr_buf_mismatch_bit(ps_rate_control_api->ps_cbr_buffer, i4_error_bits);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_estimate_status
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
WORD32 rc_set_estimate_status(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 i4_tex_bits,
|
|
WORD32 i4_hdr_bits,
|
|
WORD32 i4_est_text_bits_ctr_get_qp)
|
|
{
|
|
update_estimate_status(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
i4_tex_bits,
|
|
i4_hdr_bits,
|
|
i4_est_text_bits_ctr_get_qp);
|
|
|
|
return i4_tex_bits;
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_bpp_based_scene_cut_qp
|
|
Description : bpp based qp for a scene cut frame
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
WORD32 rc_get_bpp_based_scene_cut_qp(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
picture_type_e e_pic_type,
|
|
WORD32 i4_num_pels_in_frame,
|
|
WORD32 i4_f_sim_lap,
|
|
float af_sum_weigh[MAX_PIC_TYPE][3],
|
|
WORD32 i4_call_type)
|
|
{
|
|
WORD32 i4_cur_est_texture_bits, i4_cur_est_header_bits, i4_qp, i4_tot_bits,
|
|
i4_buf_based_min_bits, i4_buf_based_max_bits;
|
|
|
|
/* Reset the number of header bits in a scene change */
|
|
//init_prev_header_bits(ps_rate_control_api->ps_bit_allocation, ps_rate_control_api->ps_pic_handling);
|
|
|
|
/* Get the estimated header bits for the current encoded frame */
|
|
|
|
assign_complexity_coeffs(ps_rate_control_api->ps_bit_allocation, af_sum_weigh);
|
|
i4_cur_est_header_bits =
|
|
get_cur_frm_est_header_bits(ps_rate_control_api->ps_bit_allocation, e_pic_type);
|
|
|
|
/*get estimate of total bits that can be allocated to I frame based on offline generated data*/
|
|
i4_tot_bits = get_scene_change_tot_frm_bits(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
i4_num_pels_in_frame,
|
|
i4_f_sim_lap,
|
|
(float)8.00,
|
|
0,
|
|
0,
|
|
ps_rate_control_api->i4_is_infinite_gop);
|
|
|
|
/* Getting the min and max texture bits based on buffer fullness and constraining the
|
|
bit allocation based on this */
|
|
if(i4_call_type == 1)
|
|
{
|
|
get_min_max_bits_based_on_buffer(
|
|
ps_rate_control_api, e_pic_type, &i4_buf_based_min_bits, &i4_buf_based_max_bits, 0);
|
|
if(i4_tot_bits > i4_buf_based_max_bits)
|
|
i4_tot_bits = i4_buf_based_max_bits;
|
|
if(i4_tot_bits < i4_buf_based_min_bits)
|
|
i4_tot_bits = i4_buf_based_min_bits;
|
|
}
|
|
/*Assume 30 percent header bits*/
|
|
i4_cur_est_texture_bits = (i4_tot_bits * DEFAULT_TEX_PERCENTAGE_Q5) >> 5;
|
|
|
|
/* Get the texture bits assigned to the current frame */
|
|
i4_cur_est_header_bits = i4_tot_bits - i4_cur_est_texture_bits;
|
|
|
|
if(i4_cur_est_texture_bits < 0)
|
|
i4_cur_est_texture_bits = 0;
|
|
|
|
/* Get the qp for the remaining bits allocated for that frame based on buffer status */
|
|
i4_qp = get_init_qp_using_pels_bits_per_frame(
|
|
ps_rate_control_api->ps_init_qp, I_PIC, i4_cur_est_texture_bits, i4_num_pels_in_frame);
|
|
/* Make sure the qp is with in range */
|
|
if(i4_qp < ps_rate_control_api->ai4_min_qp[e_pic_type])
|
|
{
|
|
i4_qp = ps_rate_control_api->ai4_min_qp[e_pic_type];
|
|
}
|
|
else if(i4_qp > ps_rate_control_api->ai4_max_qp[e_pic_type])
|
|
{
|
|
i4_qp = ps_rate_control_api->ai4_max_qp[e_pic_type];
|
|
}
|
|
|
|
return (i4_qp);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_reset_pic_model
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_reset_pic_model(rate_control_api_t *ps_rate_control_api, picture_type_e pic_type)
|
|
{
|
|
reset_frm_rc_rd_model(ps_rate_control_api->aps_rd_model[pic_type]);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_reset_first_frame_coded_flag
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_reset_first_frame_coded_flag(
|
|
rate_control_api_t *ps_rate_control_api, picture_type_e pic_type)
|
|
{
|
|
ps_rate_control_api->au1_is_first_frm_coded[pic_type] = 0;
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_scene_change_est_header_bits
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
WORD32 rc_get_scene_change_est_header_bits(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 i4_num_pixels,
|
|
WORD32 i4_fsim_lap,
|
|
float af_sum_weigh[MAX_PIC_TYPE][3],
|
|
float i_to_avg_ratio)
|
|
{
|
|
WORD32 i4_est_tot_bits;
|
|
|
|
assign_complexity_coeffs(ps_rate_control_api->ps_bit_allocation, af_sum_weigh);
|
|
|
|
i4_est_tot_bits = get_scene_change_tot_frm_bits(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
ps_rate_control_api->ps_pic_handling,
|
|
ps_rate_control_api->ps_cbr_buffer,
|
|
i4_num_pixels,
|
|
i4_fsim_lap,
|
|
i_to_avg_ratio,
|
|
0,
|
|
0,
|
|
ps_rate_control_api->i4_is_infinite_gop);
|
|
/*return header bits based on default percentage*/
|
|
return (i4_est_tot_bits - ((i4_est_tot_bits * DEFAULT_TEX_PERCENTAGE_Q5) >> 5));
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_put_temp_comp_lap
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_put_temp_comp_lap(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 i4_lap_fsim,
|
|
LWORD64 i8_per_pixel_frm_hme_sad_q10,
|
|
picture_type_e e_pic_type)
|
|
{
|
|
ps_rate_control_api->i4_lap_f_sim = i4_lap_fsim;
|
|
if(e_pic_type == P_PIC)
|
|
{
|
|
ps_rate_control_api->i8_per_pixel_p_frm_hme_sad_q10 = i8_per_pixel_frm_hme_sad_q10;
|
|
}
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_pic_distribution
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_get_pic_distribution(rate_control_api_t *ps_rate_control_api, WORD32 *ai4_pic_type)
|
|
{
|
|
pic_type_get_frms_in_gop(ps_rate_control_api->ps_pic_handling, ai4_pic_type);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_actual_pic_distribution
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_get_actual_pic_distribution(rate_control_api_t *ps_rate_control_api, WORD32 *ai4_pic_type)
|
|
{
|
|
pic_type_get_actual_frms_in_gop(ps_rate_control_api->ps_pic_handling, ai4_pic_type);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_reset_Kp_Kb
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_reset_Kp_Kb(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
float f_i_to_avg_rest,
|
|
WORD32 i4_num_active_pic_type,
|
|
float f_curr_hme_sad_per_pixel,
|
|
WORD32 *pi4_complexity_bin,
|
|
WORD32 i4_rc_pass)
|
|
{
|
|
reset_Kp_Kb(
|
|
ps_rate_control_api->ps_bit_allocation,
|
|
f_i_to_avg_rest,
|
|
i4_num_active_pic_type,
|
|
f_curr_hme_sad_per_pixel,
|
|
ps_rate_control_api->f_max_hme_sad_per_pixel,
|
|
pi4_complexity_bin,
|
|
i4_rc_pass);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_reset_Kp_Kb
|
|
Description : Get Kp and Kb values for offset at scene cut
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
WORD32 rc_get_kp_kb(rate_control_api_t *ps_rate_control_api, picture_type_e e_pic_type)
|
|
{
|
|
return get_Kp_Kb(ps_rate_control_api->ps_bit_allocation, e_pic_type);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_ebf
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
WORD32 rc_get_ebf(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (get_cbr_ebf(ps_rate_control_api->ps_cbr_buffer));
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_get_offline_normalized_complexity
|
|
Description : The complexities of L1 are normalized with the highest offline
|
|
global complexity
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
float rc_get_offline_normalized_complexity(
|
|
WORD32 i4_intra_period, WORD32 i4_luma_pels, float f_per_pixel_complexity, WORD32 i4_pass_number)
|
|
{
|
|
{
|
|
if((i4_luma_pels) > 1500000)
|
|
{
|
|
if(i4_intra_period == 1)
|
|
{
|
|
f_per_pixel_complexity /= (float)3.69;
|
|
}
|
|
else
|
|
{
|
|
/*Full HD and above: Based on running few content, exact data needs to be plugged in*/
|
|
f_per_pixel_complexity /= (float)2.25;
|
|
}
|
|
}
|
|
else if((i4_luma_pels) > 700000)
|
|
{
|
|
if(i4_intra_period == 1)
|
|
{
|
|
f_per_pixel_complexity /= (float)4.28;
|
|
}
|
|
else
|
|
{
|
|
f_per_pixel_complexity /=
|
|
(float)2.6109; //the max complexity observed for 720p content of netflix_fountain
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(i4_intra_period == 1)
|
|
f_per_pixel_complexity /= (float)4.91;
|
|
else
|
|
f_per_pixel_complexity /=
|
|
(float)3; //the max complexity observed for 720p content of netflix_fountain
|
|
}
|
|
}
|
|
if(f_per_pixel_complexity > 1.0)
|
|
f_per_pixel_complexity = 1;
|
|
return f_per_pixel_complexity;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_bit_alloc_detect_ebf_stuff_scenario
|
|
Description : To estimate whether there will be a case of underflow based on
|
|
estimated bit consumption and drain rate if there is probability
|
|
of underflow then we will lower the HEVC qp's by 1 based
|
|
on the warning flag.
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
|
|
void rc_bit_alloc_detect_ebf_stuff_scenario(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 i4_num_frm_bef_scd_lap2,
|
|
LWORD64 i8_total_bits_est_consu_lap2,
|
|
WORD32 i4_max_inter_frm_int)
|
|
{
|
|
WORD32 i4_peak_drain_rate;
|
|
LWORD64 i8_ebf, i8_estimate_ebf_at_end;
|
|
i4_peak_drain_rate = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
i8_ebf = rc_get_ebf(ps_rate_control_api);
|
|
i8_estimate_ebf_at_end =
|
|
i8_ebf - (i4_num_frm_bef_scd_lap2 * i4_peak_drain_rate) + i8_total_bits_est_consu_lap2;
|
|
|
|
ps_rate_control_api->i4_underflow_warning = 0;
|
|
|
|
if(i8_estimate_ebf_at_end < (i4_max_inter_frm_int * i4_peak_drain_rate))
|
|
{
|
|
/*If underflow is imminent give a flag*/
|
|
ps_rate_control_api->i4_underflow_warning = 1;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : bit_alloc_get_estimated_bits_for_pic
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
WORD32 bit_alloc_get_estimated_bits_for_pic(
|
|
rate_control_api_t *ps_rate_contro_api,
|
|
WORD32 i4_cur_frm_est_cl_sad,
|
|
WORD32 i4_prev_frm_cl_sad,
|
|
picture_type_e e_pic_type)
|
|
{
|
|
WORD32 i4_prev_frame_bits, i4_curnt_frame_est_bits, i4_prev_frame_header_bits;
|
|
get_prev_frame_total_header_bits(
|
|
ps_rate_contro_api->ps_bit_allocation,
|
|
&i4_prev_frame_bits,
|
|
&i4_prev_frame_header_bits,
|
|
e_pic_type);
|
|
|
|
i4_curnt_frame_est_bits = (WORD32)(
|
|
((float)(i4_prev_frame_bits - i4_prev_frame_header_bits) * (float)i4_cur_frm_est_cl_sad /
|
|
(float)i4_prev_frm_cl_sad) +
|
|
i4_prev_frame_header_bits);
|
|
return (i4_curnt_frame_est_bits);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_get_max_hme_sad_per_pixel
|
|
Description : At init time based on parameters we pick the max hme sad per pixel.
|
|
Inputs :
|
|
Globals :
|
|
Processing :
|
|
Outputs :
|
|
Returns :
|
|
Issues :
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
|
|
*****************************************************************************/
|
|
void rc_get_max_hme_sad_per_pixel(rate_control_api_t *ps_rate_control_api, WORD32 i4_total_pixels)
|
|
{
|
|
WORD32 i, i4_error = 0x7FFFFFFF, i4_temp_error, i4_res_index = 0, i4_br_index = 0;
|
|
WORD32 i4_num_temporal_layers;
|
|
/*Max hme sad per pixel based on resolutions, num. of temporal layers (0-3) and also bpp-> whether low bitrate or high bitrate*/
|
|
float af_offline_hme_sad_per_pixel_480p[4][2] = {
|
|
{ 2.94f, 2.63f }, { 2.96f, 2.44f }, { 2.72f, 1.94f }, { 2.70f, 2.04f }
|
|
};
|
|
float af_offline_hme_sad_per_pixel_720p[4][2] = {
|
|
{ 3.37f, 2.97f }, { 3.35f, 2.77f }, { 3.18f, 2.40f }, { 2.94f, 1.83f }
|
|
};
|
|
float af_offline_hme_sad_per_pixel_1080p[4][2] = {
|
|
{ 3.24f, 2.78f }, { 3.17f, 2.46f }, { 2.91f, 1.98f }, { 2.75f, 1.65f }
|
|
};
|
|
float af_offline_hme_sad_per_pixel_2160p[4][2] = {
|
|
{ 2.56f, 2.11f }, { 2.47f, 1.92f }, { 2.19f, 1.46f }, { 2.00f, 1.21f }
|
|
};
|
|
|
|
/*Low BR or HBR is decided by comparing the bpp values as below*/
|
|
float af_offline_bpp[4][2] = {
|
|
{ 0.30f, 0.09f }, { 0.25f, 0.06f }, { 0.16f, 0.04f }, { 0.12f, 0.02f }
|
|
};
|
|
|
|
/*Number of pixels in the picture for picking the closest resolution*/
|
|
WORD32 ai4_pixels_res[4] = { 307200, 921600, 2073600, 8294400 };
|
|
|
|
float f_bpp =
|
|
(float)get_bits_per_frame(ps_rate_control_api->ps_bit_allocation) / i4_total_pixels;
|
|
float f_max_hme_sad_per_pixel;
|
|
|
|
i4_num_temporal_layers = ps_rate_control_api->i4_num_active_pic_type - 2;
|
|
|
|
CLIP(i4_num_temporal_layers, 3, 0);
|
|
|
|
/*Pick the closest resolution based on error*/
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
i4_temp_error = abs(i4_total_pixels - ai4_pixels_res[i]);
|
|
|
|
if(i4_temp_error < i4_error)
|
|
{
|
|
i4_error = i4_temp_error;
|
|
i4_res_index = i;
|
|
}
|
|
}
|
|
|
|
/*Decide whether LBR or HBR*/
|
|
if((fabs(af_offline_bpp[i4_res_index][0] - f_bpp)) >
|
|
(fabs(af_offline_bpp[i4_res_index][1] - f_bpp)))
|
|
{
|
|
i4_br_index = 1;
|
|
}
|
|
else
|
|
{
|
|
i4_br_index = 0;
|
|
}
|
|
|
|
/*After that pick the max hme sad*/
|
|
switch(i4_res_index)
|
|
{
|
|
case 0:
|
|
f_max_hme_sad_per_pixel =
|
|
af_offline_hme_sad_per_pixel_480p[i4_num_temporal_layers][i4_br_index];
|
|
break;
|
|
case 1:
|
|
f_max_hme_sad_per_pixel =
|
|
af_offline_hme_sad_per_pixel_720p[i4_num_temporal_layers][i4_br_index];
|
|
break;
|
|
case 2:
|
|
f_max_hme_sad_per_pixel =
|
|
af_offline_hme_sad_per_pixel_1080p[i4_num_temporal_layers][i4_br_index];
|
|
break;
|
|
case 3:
|
|
f_max_hme_sad_per_pixel =
|
|
af_offline_hme_sad_per_pixel_2160p[i4_num_temporal_layers][i4_br_index];
|
|
break;
|
|
default:
|
|
f_max_hme_sad_per_pixel =
|
|
af_offline_hme_sad_per_pixel_1080p[i4_num_temporal_layers][i4_br_index];
|
|
break;
|
|
}
|
|
|
|
ps_rate_control_api->f_max_hme_sad_per_pixel = f_max_hme_sad_per_pixel;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_update_pic_distn_lap_to_rc
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_update_pic_distn_lap_to_rc(
|
|
rate_control_api_t *ps_rate_contro_api, WORD32 ai4_num_pic_type[MAX_PIC_TYPE])
|
|
{
|
|
pic_type_update_frms_in_gop(ps_rate_contro_api->ps_pic_handling, ai4_num_pic_type);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_set_bits_based_on_complexity
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_set_bits_based_on_complexity(
|
|
rate_control_api_t *ps_rate_contro_api, WORD32 i4_lap_window_comp, WORD32 i4_num_frames)
|
|
{
|
|
set_bit_allocation_i_frames(
|
|
ps_rate_contro_api->ps_bit_allocation,
|
|
ps_rate_contro_api->ps_cbr_buffer,
|
|
ps_rate_contro_api->ps_pic_handling,
|
|
i4_lap_window_comp,
|
|
i4_num_frames);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_avg_qscale_first_pass
|
|
Description : Set the average qscale from first pass
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
void rc_set_avg_qscale_first_pass(
|
|
rate_control_api_t *ps_rate_control_api, float f_average_qscale_1st_pass)
|
|
{
|
|
ba_set_avg_qscale_first_pass(ps_rate_control_api->ps_bit_allocation, f_average_qscale_1st_pass);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_max_avg_qscale_first_pass
|
|
Description : Set the maximum avergae Qscale in second pass as average Qscale
|
|
of first pass + 6 This is for simple contents
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
void rc_set_max_avg_qscale_first_pass(
|
|
rate_control_api_t *ps_rate_control_api, float f_max_average_qscale_1st_pass)
|
|
{
|
|
ba_set_max_avg_qscale_first_pass(
|
|
ps_rate_control_api->ps_bit_allocation, f_max_average_qscale_1st_pass);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_i_to_sum_api_ba
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_set_i_to_sum_api_ba(rate_control_api_t *ps_rate_control_api, float f_curr_i_to_sum)
|
|
{
|
|
bit_alloc_set_curr_i_to_sum_i(ps_rate_control_api->ps_bit_allocation, f_curr_i_to_sum);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_p_to_i_complexity_ratio
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_set_p_to_i_complexity_ratio(rate_control_api_t *ps_rate_control_api, float f_p_to_i_ratio)
|
|
{
|
|
ps_rate_control_api->f_p_to_i_comp_ratio = f_p_to_i_ratio;
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_scd_in_period
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_set_scd_in_period(rate_control_api_t *ps_rate_control_api, WORD32 i4_scd_in_period)
|
|
{
|
|
ps_rate_control_api->i4_scd_in_period_2_pass = i4_scd_in_period;
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_ba_get_qp_offset_offline_data
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_ba_get_qp_offset_offline_data(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 ai4_offsets[5],
|
|
float f_hme_sad_per_pixel,
|
|
WORD32 i4_num_active_pic_type,
|
|
WORD32 *pi4_complexity_bin)
|
|
{
|
|
WORD32 i4_ratio;
|
|
float f_ratio;
|
|
|
|
CLIP(f_hme_sad_per_pixel, ps_rate_control_api->f_max_hme_sad_per_pixel, 0.01f);
|
|
|
|
i4_ratio = (WORD32)(ps_rate_control_api->f_max_hme_sad_per_pixel / f_hme_sad_per_pixel);
|
|
f_ratio = ps_rate_control_api->f_max_hme_sad_per_pixel / f_hme_sad_per_pixel;
|
|
|
|
ba_get_qp_offset_offline_data(
|
|
ai4_offsets, i4_ratio, f_ratio, i4_num_active_pic_type, pi4_complexity_bin);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_api_gop_level_averagae_q_scale_without_offset
|
|
Description : Find the GOP level average of the Qscale
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
float rc_api_gop_level_averagae_q_scale_without_offset(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
float f_hbd_qscale =
|
|
ba_gop_info_average_qscale_gop_without_offset(ps_rate_control_api->ps_bit_allocation);
|
|
|
|
return (f_hbd_qscale);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function Name : rc_getprev_ref_pic_type
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
picture_type_e rc_getprev_ref_pic_type(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
return (ps_rate_control_api->prev_ref_pic_type);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_actual_intra_frame_int
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
WORD32 rc_get_actual_intra_frame_int(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
WORD32 i4_int = pic_type_get_actual_intra_frame_interval(ps_rate_control_api->ps_pic_handling);
|
|
return (i4_int);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_get_qscale_max_clip_in_second_pass
|
|
Description : Get maximum qscale that is allowed based on average Qp for simple contents
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
float rc_get_qscale_max_clip_in_second_pass(rate_control_api_t *ps_rate_control_api)
|
|
{
|
|
float i4_max_qscale =
|
|
ba_get_qscale_max_clip_in_second_pass(ps_rate_control_api->ps_bit_allocation);
|
|
return (i4_max_qscale);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_2pass_total_frames
|
|
Description : Set the total number of frames in the stream
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
void rc_set_2pass_total_frames(rate_control_api_t *ps_rate_control_api, WORD32 i4_total_2pass_frames)
|
|
{
|
|
bit_alloc_set_2pass_total_frames(ps_rate_control_api->ps_bit_allocation, i4_total_2pass_frames);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_2pass_avg_bit_rate
|
|
Description : Set the average bit-rate based on consumption so far
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
|
|
void rc_set_2pass_avg_bit_rate(
|
|
rate_control_api_t *ps_rate_control_api, LWORD64 i8_2pass_avg_bit_rate)
|
|
{
|
|
ba_set_2pass_avg_bit_rate(ps_rate_control_api->ps_bit_allocation, i8_2pass_avg_bit_rate);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_set_enable_look_ahead
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_set_enable_look_ahead(rate_control_api_t *ps_rate_control_api, WORD32 i4_enable_look_ahead)
|
|
{
|
|
ba_set_enable_look_ahead(ps_rate_control_api->ps_bit_allocation, i4_enable_look_ahead);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_add_est_tot
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_add_est_tot(rate_control_api_t *ps_rate_control_api, WORD32 i4_tot_tex_bits)
|
|
{
|
|
rc_modify_est_tot(ps_rate_control_api, i4_tot_tex_bits);
|
|
}
|
|
/****************************************************************************
|
|
Function Name : rc_init_buffer_info
|
|
Description :
|
|
Inputs : ps_rate_control_api
|
|
|
|
Revision History:
|
|
DD MM YYYY Author(s) Changes (Describe the changes made)
|
|
*****************************************************************************/
|
|
void rc_init_buffer_info(
|
|
rate_control_api_t *ps_rate_control_api,
|
|
WORD32 *pi4_vbv_buffer_size,
|
|
WORD32 *pi4_currEbf,
|
|
WORD32 *pi4_maxEbf,
|
|
WORD32 *pi4_drain_rate)
|
|
{
|
|
*pi4_vbv_buffer_size = get_cbr_buffer_size(ps_rate_control_api->ps_cbr_buffer);
|
|
*pi4_currEbf = get_cbr_ebf(ps_rate_control_api->ps_cbr_buffer) +
|
|
rc_get_estimate_bit_error(ps_rate_control_api);
|
|
*pi4_maxEbf = get_cbr_max_ebf(ps_rate_control_api->ps_cbr_buffer);
|
|
*pi4_drain_rate = get_buf_max_drain_rate(ps_rate_control_api->ps_cbr_buffer);
|
|
return;
|
|
}
|