731 lines
25 KiB
C
731 lines
25 KiB
C
|
/******************************************************************************
|
||
|
*
|
||
|
* Copyright (C) 2015 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
|
||
|
* ih264e_rate_control.c
|
||
|
*
|
||
|
* @brief
|
||
|
* Contains api function definitions for h264 rate control
|
||
|
*
|
||
|
* @author
|
||
|
* ittiam
|
||
|
*
|
||
|
* @par List of Functions:
|
||
|
* - ih264e_rc_init()
|
||
|
* - ih264e_rc_get_picture_details()
|
||
|
* - ih264e_rc_pre_enc()
|
||
|
* - ih264e_update_rc_mb_info()
|
||
|
* - ih264e_rc_get_buffer_status()
|
||
|
* - ih264e_rc_post_enc()
|
||
|
* - ih264e_update_rc_bits_info()
|
||
|
*
|
||
|
* @remarks
|
||
|
* None
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
/* File Includes */
|
||
|
/*****************************************************************************/
|
||
|
|
||
|
/* User include files */
|
||
|
#include "irc_datatypes.h"
|
||
|
#include "iv2.h"
|
||
|
#include "ive2.h"
|
||
|
#include "ih264e.h"
|
||
|
#include "ih264_defs.h"
|
||
|
#include "ih264_macros.h"
|
||
|
#include "ih264_structs.h"
|
||
|
#include "ih264_trans_quant_itrans_iquant.h"
|
||
|
#include "ih264_inter_pred_filters.h"
|
||
|
#include "ih264_mem_fns.h"
|
||
|
#include "ih264_padding.h"
|
||
|
#include "ih264_intra_pred_filters.h"
|
||
|
#include "ih264_deblk_edge_filters.h"
|
||
|
#include "ih264_common_tables.h"
|
||
|
#include "ih264_cabac_tables.h"
|
||
|
#include "ih264e_defs.h"
|
||
|
#include "ih264e_globals.h"
|
||
|
#include "irc_mem_req_and_acq.h"
|
||
|
#include "irc_cntrl_param.h"
|
||
|
#include "irc_frame_info_collector.h"
|
||
|
#include "irc_rate_control_api.h"
|
||
|
#include "ih264e_time_stamp.h"
|
||
|
#include "ih264e_modify_frm_rate.h"
|
||
|
#include "ih264e_rate_control.h"
|
||
|
#include "ih264e_error.h"
|
||
|
#include "ih264e_bitstream.h"
|
||
|
#include "ime_distortion_metrics.h"
|
||
|
#include "ime_defs.h"
|
||
|
#include "ime_structs.h"
|
||
|
#include "ih264e_cabac_structs.h"
|
||
|
#include "ih264e_structs.h"
|
||
|
#include "ih264e_utils.h"
|
||
|
#include "irc_trace_support.h"
|
||
|
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
/* Function Definitions */
|
||
|
/*****************************************************************************/
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief This function does nothing
|
||
|
*
|
||
|
* @par Description
|
||
|
* This function does nothing
|
||
|
*
|
||
|
* @param[in] variadic function
|
||
|
|
||
|
* @returns none
|
||
|
*
|
||
|
* @remarks This function is used by the rc library for debugging purposes.
|
||
|
* However this function was not part of rc library. So this is defined here
|
||
|
* to resolve link issues.
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
int trace_printf(const WORD8 *format, ...)
|
||
|
{
|
||
|
UNUSED(format);
|
||
|
return(0);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief
|
||
|
* This function initializes rate control context and variables
|
||
|
*
|
||
|
* @par Description
|
||
|
* This function initializes rate control type, source and target frame rate,
|
||
|
* average and peak bitrate, intra-inter frame interval and initial
|
||
|
* quantization parameter
|
||
|
*
|
||
|
* @param[in] pv_rc_api
|
||
|
* Handle to rate control api
|
||
|
*
|
||
|
* @param[in] pv_frame_time
|
||
|
* Handle to frame time context
|
||
|
*
|
||
|
* @param[in] pv_time_stamp
|
||
|
* Handle to time stamp context
|
||
|
*
|
||
|
* @param[in] pv_pd_frm_rate
|
||
|
* Handle to pull down frame time context
|
||
|
*
|
||
|
* @param[in] u4_max_frm_rate
|
||
|
* Maximum frame rate
|
||
|
*
|
||
|
* @param[in] u4_src_frm_rate
|
||
|
* Source frame rate
|
||
|
*
|
||
|
* @param[in] u4_tgt_frm_rate
|
||
|
* Target frame rate
|
||
|
*
|
||
|
* @param[in] e_rate_control_type
|
||
|
* Rate control type
|
||
|
*
|
||
|
* @param[in] u4_avg_bit_rate
|
||
|
* Average bit rate
|
||
|
*
|
||
|
* @param[in] u4_peak_bit_rate
|
||
|
* Peak bit rate
|
||
|
*
|
||
|
* @param[in] u4_max_delay
|
||
|
* Maximum delay between frames
|
||
|
*
|
||
|
* @param[in] u4_intra_frame_interval
|
||
|
* Intra frame interval
|
||
|
*
|
||
|
* @param[in] pu1_init_qp
|
||
|
* Initial qp
|
||
|
*
|
||
|
* @param[in] i4_max_inter_frm_int
|
||
|
* Maximum inter frame interval
|
||
|
*
|
||
|
* @param[in] pu1_min_max_qp
|
||
|
* Array of min/max qp
|
||
|
*
|
||
|
* @param[in] u1_profile_level
|
||
|
* Encoder profile level
|
||
|
*
|
||
|
* @returns none
|
||
|
*
|
||
|
* @remarks
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
void ih264e_rc_init(void *pv_rc_api,
|
||
|
void *pv_frame_time,
|
||
|
void *pv_time_stamp,
|
||
|
void *pv_pd_frm_rate,
|
||
|
UWORD32 u4_max_frm_rate,
|
||
|
UWORD32 u4_src_frm_rate,
|
||
|
UWORD32 u4_tgt_frm_rate,
|
||
|
rc_type_e e_rate_control_type,
|
||
|
UWORD32 u4_avg_bit_rate,
|
||
|
UWORD32 u4_peak_bit_rate,
|
||
|
UWORD32 u4_max_delay,
|
||
|
UWORD32 u4_intra_frame_interval,
|
||
|
WORD32 i4_inter_frm_int,
|
||
|
UWORD8 *pu1_init_qp,
|
||
|
WORD32 i4_max_inter_frm_int,
|
||
|
UWORD8 *pu1_min_max_qp,
|
||
|
UWORD8 u1_profile_level)
|
||
|
{
|
||
|
// UWORD8 u1_is_mb_level_rc_on = 0;
|
||
|
UWORD32 au4_peak_bit_rate[2] = {0,0};
|
||
|
UWORD32 u4_min_bit_rate = 0;
|
||
|
WORD32 i4_is_gop_closed = 1;
|
||
|
// WORD32 i4_use_est_intra_sad = 1;
|
||
|
UWORD32 u4_src_ticks = 0;
|
||
|
UWORD32 u4_tgt_ticks = 0;
|
||
|
UWORD8 u1_level_idx = ih264e_get_lvl_idx(u1_profile_level);
|
||
|
UWORD32 u4_max_cpb_size = 1200 * gas_ih264_lvl_tbl[u1_level_idx].u4_max_cpb_size;
|
||
|
|
||
|
/* Fill the params needed for the RC init */
|
||
|
if (e_rate_control_type == CBR_NLDRC)
|
||
|
{
|
||
|
au4_peak_bit_rate[0] = u4_avg_bit_rate;
|
||
|
au4_peak_bit_rate[1] = u4_avg_bit_rate;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
au4_peak_bit_rate[0] = u4_peak_bit_rate;
|
||
|
au4_peak_bit_rate[1] = u4_peak_bit_rate;
|
||
|
}
|
||
|
|
||
|
/* Initialize frame time computation module*/
|
||
|
ih264e_init_frame_time(pv_frame_time,
|
||
|
u4_src_frm_rate, /* u4_src_frm_rate */
|
||
|
u4_tgt_frm_rate); /* u4_tgt_frm_rate */
|
||
|
|
||
|
/* Initialize the pull_down frame rate */
|
||
|
ih264e_init_pd_frm_rate(pv_pd_frm_rate,
|
||
|
u4_src_frm_rate); /* u4_input_frm_rate */
|
||
|
|
||
|
/* Initialize time stamp structure */
|
||
|
ih264e_init_time_stamp(pv_time_stamp,
|
||
|
u4_max_frm_rate, /* u4_max_frm_rate */
|
||
|
u4_src_frm_rate); /* u4_src_frm_rate */
|
||
|
|
||
|
u4_src_ticks = ih264e_frame_time_get_src_ticks(pv_frame_time);
|
||
|
u4_tgt_ticks = ih264e_frame_time_get_tgt_ticks(pv_frame_time);
|
||
|
|
||
|
/* Init max_inter_frame int */
|
||
|
i4_max_inter_frm_int = (i4_inter_frm_int == 1) ? 2 : (i4_inter_frm_int + 2);
|
||
|
|
||
|
/* Initialize the rate control */
|
||
|
irc_initialise_rate_control(pv_rc_api, /* RC handle */
|
||
|
e_rate_control_type, /* RC algo type */
|
||
|
0, /* MB activity on/off */
|
||
|
u4_avg_bit_rate, /* Avg Bitrate */
|
||
|
au4_peak_bit_rate, /* Peak bitrate array[2]:[I][P] */
|
||
|
u4_min_bit_rate, /* Min Bitrate */
|
||
|
u4_src_frm_rate, /* Src frame_rate */
|
||
|
u4_max_delay, /* Max buffer delay */
|
||
|
u4_intra_frame_interval, /* Intra frm_interval */
|
||
|
i4_inter_frm_int, /* Inter frame interval */
|
||
|
pu1_init_qp, /* Init QP array[3]:[I][P][B] */
|
||
|
u4_max_cpb_size, /* Max VBV/CPB Buffer Size */
|
||
|
i4_max_inter_frm_int, /* Max inter frm_interval */
|
||
|
i4_is_gop_closed, /* Open/Closed GOP */
|
||
|
pu1_min_max_qp, /* Min-max QP array[6]:[Imax][Imin][Pmax][Pmin][Bmax][Bmin] */
|
||
|
0, /* How to calc the I-frame estimated_sad */
|
||
|
u4_src_ticks, /* Src_ticks = LCM(src_frm_rate,tgt_frm_rate)/src_frm_rate */
|
||
|
u4_tgt_ticks); /* Tgt_ticks = LCM(src_frm_rate,tgt_frm_rate)/tgt_frm_rate */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief Function to get picture details
|
||
|
*
|
||
|
* @par Description
|
||
|
* This function returns the Picture type(I/P/B)
|
||
|
*
|
||
|
* @param[in] pv_rc_api
|
||
|
* Handle to Rate control api
|
||
|
*
|
||
|
* @returns
|
||
|
* Picture type
|
||
|
*
|
||
|
* @remarks none
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
picture_type_e ih264e_rc_get_picture_details(void *pv_rc_api,
|
||
|
WORD32 *pi4_pic_id,
|
||
|
WORD32 *pi4_pic_disp_order_no)
|
||
|
{
|
||
|
picture_type_e e_rc_pic_type = P_PIC;
|
||
|
|
||
|
irc_get_picture_details(pv_rc_api, pi4_pic_id, pi4_pic_disp_order_no,
|
||
|
&e_rc_pic_type);
|
||
|
|
||
|
return (e_rc_pic_type);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief Function to get rate control output before encoding
|
||
|
*
|
||
|
* @par Description
|
||
|
* This function is called before queing the current frame. It decides if we should
|
||
|
* skip the current iput buffer due to frame rate mismatch. It also updates RC about
|
||
|
* the acehivble frame rate
|
||
|
*
|
||
|
* @param[in] ps_rate_control_api
|
||
|
* Handle to rate control api
|
||
|
*
|
||
|
* @param[in] ps_pd_frm_rate
|
||
|
* Handle to pull down frm rate context
|
||
|
*
|
||
|
* @param[in] ps_time_stamp
|
||
|
* Handle to time stamp context
|
||
|
*
|
||
|
* @param[in] ps_frame_time
|
||
|
* Handle to frame time context
|
||
|
*
|
||
|
* @param[in] i4_delta_time_stamp
|
||
|
* Time stamp difference between frames
|
||
|
*
|
||
|
* @param[in] i4_total_mb_in_frame
|
||
|
* Total Macro Blocks in frame
|
||
|
*
|
||
|
* @param[in/out] pe_vop_coding_type
|
||
|
* Picture coding type(I/P/B)
|
||
|
*
|
||
|
* @param[in/out] pu1_frame_qp
|
||
|
* QP for current frame
|
||
|
*
|
||
|
* @returns
|
||
|
* Skip or queue the current frame
|
||
|
*
|
||
|
* @remarks
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
WORD32 ih264e_update_rc_framerates(void *ps_rate_control_api,
|
||
|
void *ps_pd_frm_rate,
|
||
|
void *ps_time_stamp,
|
||
|
void *ps_frame_time)
|
||
|
{
|
||
|
WORD8 i4_skip_src = 0;
|
||
|
UWORD32 u4_src_not_skipped_for_dts = 0;
|
||
|
|
||
|
/* Update the time stamp for the current frame */
|
||
|
ih264e_update_time_stamp(ps_time_stamp);
|
||
|
|
||
|
/* Check if a src not needs to be skipped */
|
||
|
i4_skip_src = ih264e_should_src_be_skipped(ps_frame_time,
|
||
|
1,
|
||
|
&u4_src_not_skipped_for_dts);
|
||
|
|
||
|
if (i4_skip_src)
|
||
|
{
|
||
|
/***********************************************************************
|
||
|
*Based on difference in source and target frame rate frames are skipped
|
||
|
***********************************************************************/
|
||
|
/*update the missing frames frm_rate with 0 */
|
||
|
ih264e_update_pd_frm_rate(ps_pd_frm_rate, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WORD32 i4_avg_frm_rate, i4_source_frame_rate;
|
||
|
|
||
|
i4_source_frame_rate = ih264e_frame_time_get_src_frame_rate(
|
||
|
ps_frame_time);
|
||
|
|
||
|
/* Update the frame rate of the frame present with the tgt_frm_rate */
|
||
|
/* If the frm was not skipped due to delta_time_stamp, update the
|
||
|
frame_rate with double the tgt_frame_rate value, so that it makes
|
||
|
up for one of the frames skipped by the application */
|
||
|
ih264e_update_pd_frm_rate(ps_pd_frm_rate, i4_source_frame_rate);
|
||
|
|
||
|
/* Based on the update get the average frame rate */
|
||
|
i4_avg_frm_rate = ih264e_get_pd_avg_frm_rate(ps_pd_frm_rate);
|
||
|
|
||
|
/* Call the RC library function to change the frame_rate to the
|
||
|
actually achieved frm_rate */
|
||
|
irc_change_frm_rate_for_bit_alloc(ps_rate_control_api, i4_avg_frm_rate);
|
||
|
}
|
||
|
|
||
|
return (i4_skip_src);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief Function to update mb info for rate control context
|
||
|
*
|
||
|
* @par Description
|
||
|
* After encoding a mb, information such as mb type, qp used, mb distortion
|
||
|
* resulted in encoding the block and so on needs to be preserved for modeling
|
||
|
* RC. This is preserved via this function call.
|
||
|
*
|
||
|
* @param[in] ps_frame_info
|
||
|
* Handle Frame info context
|
||
|
*
|
||
|
* @param[in] ps_proc
|
||
|
* Process context
|
||
|
*
|
||
|
* @returns
|
||
|
*
|
||
|
* @remarks
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
void ih264e_update_rc_mb_info(frame_info_t *ps_frame_info, void *pv_proc)
|
||
|
{
|
||
|
/* proc ctxt */
|
||
|
process_ctxt_t *ps_proc = pv_proc;
|
||
|
|
||
|
/* is intra or inter */
|
||
|
WORD32 mb_type = !ps_proc->u4_is_intra;
|
||
|
|
||
|
/* distortion */
|
||
|
ps_frame_info->tot_mb_sad[mb_type] += ps_proc->i4_mb_distortion;
|
||
|
|
||
|
/* qp */
|
||
|
ps_frame_info->qp_sum[mb_type] += gau1_h264_to_mpeg2_qmap[ps_proc->u4_mb_qp];
|
||
|
|
||
|
/* mb cnt */
|
||
|
ps_frame_info->num_mbs[mb_type]++;
|
||
|
|
||
|
/* cost */
|
||
|
if (ps_proc->u4_is_intra)
|
||
|
{
|
||
|
ps_frame_info->intra_mb_cost_sum += ps_proc->i4_mb_cost;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief Function to get rate control buffer status
|
||
|
*
|
||
|
* @par Description
|
||
|
* This function is used to get buffer status(underflow/overflow) by rate
|
||
|
* control module
|
||
|
*
|
||
|
* @param[in] pv_rc_api
|
||
|
* Handle to rate control api context
|
||
|
*
|
||
|
* @param[in] i4_total_frame_bits
|
||
|
* Total frame bits
|
||
|
*
|
||
|
* @param[in] u1_pic_type
|
||
|
* Picture type
|
||
|
*
|
||
|
* @param[in] pi4_num_bits_to_prevent_vbv_underflow
|
||
|
* Number of bits to prevent underflow
|
||
|
*
|
||
|
* @param[out] pu1_is_enc_buf_overflow
|
||
|
* Buffer overflow indication flag
|
||
|
*
|
||
|
* @param[out] pu1_is_enc_buf_underflow
|
||
|
* Buffer underflow indication flag
|
||
|
*
|
||
|
* @returns
|
||
|
*
|
||
|
* @remarks
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
void ih264e_rc_get_buffer_status(void *pv_rc_api,
|
||
|
WORD32 i4_total_frame_bits,
|
||
|
picture_type_e e_pic_type,
|
||
|
WORD32 *pi4_num_bits_to_prevent_vbv_underflow,
|
||
|
UWORD8 *pu1_is_enc_buf_overflow,
|
||
|
UWORD8 *pu1_is_enc_buf_underflow)
|
||
|
{
|
||
|
vbv_buf_status_e e_vbv_buf_status = VBV_NORMAL;
|
||
|
|
||
|
e_vbv_buf_status = irc_get_buffer_status(pv_rc_api,
|
||
|
i4_total_frame_bits,
|
||
|
e_pic_type,
|
||
|
pi4_num_bits_to_prevent_vbv_underflow);
|
||
|
|
||
|
if (e_vbv_buf_status == VBV_OVERFLOW)
|
||
|
{
|
||
|
*pu1_is_enc_buf_underflow = 1;
|
||
|
*pu1_is_enc_buf_overflow = 0;
|
||
|
}
|
||
|
else if (e_vbv_buf_status == VBV_UNDERFLOW)
|
||
|
{
|
||
|
*pu1_is_enc_buf_underflow = 0;
|
||
|
*pu1_is_enc_buf_overflow = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pu1_is_enc_buf_underflow = 0;
|
||
|
*pu1_is_enc_buf_overflow = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief Function to update rate control module after encoding
|
||
|
*
|
||
|
* @par Description
|
||
|
* This function is used to update the rate control module after the current
|
||
|
* frame encoding is done with details such as bits consumed, SAD for I/P/B,
|
||
|
* intra cost ,mb type and other
|
||
|
*
|
||
|
* @param[in] ps_rate_control_api
|
||
|
* Handle to rate control api context
|
||
|
*
|
||
|
* @param[in] ps_frame_info
|
||
|
* Handle to frame info context
|
||
|
*
|
||
|
* @param[in] ps_pd_frm_rate
|
||
|
* Handle to pull down frame rate context
|
||
|
*
|
||
|
* @param[in] ps_time_stamp
|
||
|
* Handle to time stamp context
|
||
|
*
|
||
|
* @param[in] ps_frame_time
|
||
|
* Handle to frame time context
|
||
|
*
|
||
|
* @param[in] i4_total_mb_in_frame
|
||
|
* Total mb in frame
|
||
|
*
|
||
|
* @param[in] pe_vop_coding_type
|
||
|
* Picture coding type
|
||
|
*
|
||
|
* @param[in] i4_is_first_frame
|
||
|
* Is first frame
|
||
|
*
|
||
|
* @param[in] pi4_is_post_encode_skip
|
||
|
* Post encoding skip flag
|
||
|
*
|
||
|
* @param[in] u1_frame_qp
|
||
|
* Frame qp
|
||
|
*
|
||
|
* @param[in] pi4_num_intra_in_prev_frame
|
||
|
* Numberf of intra mbs in previous frame
|
||
|
*
|
||
|
* @param[in] pi4_avg_activity
|
||
|
* Average activity
|
||
|
*
|
||
|
* @returns
|
||
|
*
|
||
|
* @remarks
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
WORD32 ih264e_rc_post_enc(void * ps_rate_control_api,
|
||
|
frame_info_t *ps_frame_info,
|
||
|
void * ps_pd_frm_rate,
|
||
|
void * ps_time_stamp,
|
||
|
void * ps_frame_time,
|
||
|
WORD32 i4_total_mb_in_frame,
|
||
|
picture_type_e *pe_vop_coding_type,
|
||
|
WORD32 i4_is_first_frame,
|
||
|
WORD32 *pi4_is_post_encode_skip,
|
||
|
UWORD8 u1_frame_qp,
|
||
|
WORD32 *pi4_num_intra_in_prev_frame,
|
||
|
WORD32 *pi4_avg_activity)
|
||
|
{
|
||
|
/* Variables for the update_frm_level_info */
|
||
|
WORD32 ai4_tot_mb_in_type[MAX_MB_TYPE];
|
||
|
WORD32 ai4_tot_mb_type_qp[MAX_MB_TYPE] = {0, 0};
|
||
|
WORD32 ai4_mb_type_sad[MAX_MB_TYPE] = {0, 0};
|
||
|
WORD32 ai4_mb_type_tex_bits[MAX_MB_TYPE] = {0, 0};
|
||
|
WORD32 i4_total_frame_bits = 0;
|
||
|
WORD32 i4_total_hdr_bits = 0;
|
||
|
WORD32 i4_total_texturebits;
|
||
|
WORD32 i4_avg_mb_activity = 0;
|
||
|
WORD32 i4_intra_frm_cost = 0;
|
||
|
UWORD8 u1_is_scd = 0;
|
||
|
WORD32 i4_cbr_bits_to_stuff = 0;
|
||
|
UWORD32 u4_num_intra_in_prev_frame = *pi4_num_intra_in_prev_frame;
|
||
|
UNUSED(ps_pd_frm_rate);
|
||
|
UNUSED(ps_time_stamp);
|
||
|
UNUSED(ps_frame_time);
|
||
|
UNUSED(u1_frame_qp);
|
||
|
/* Accumulate RC stats */
|
||
|
ai4_tot_mb_in_type[MB_TYPE_INTRA] = irc_fi_get_total_mb(ps_frame_info,MB_TYPE_INTRA);
|
||
|
ai4_tot_mb_in_type[MB_TYPE_INTER] = irc_fi_get_total_mb(ps_frame_info,MB_TYPE_INTER);
|
||
|
/* ai4_tot_mb_type_qp[MB_TYPE_INTRA] = 0;
|
||
|
ai4_tot_mb_type_qp[MB_TYPE_INTER] = ps_enc->pu1_h264_mpg2quant[u1_frame_qp] * i4_total_mb_in_frame;*/
|
||
|
ai4_tot_mb_type_qp[MB_TYPE_INTRA] = irc_fi_get_total_mb_qp(ps_frame_info,MB_TYPE_INTRA);
|
||
|
ai4_tot_mb_type_qp[MB_TYPE_INTER] = irc_fi_get_total_mb_qp(ps_frame_info,MB_TYPE_INTER);
|
||
|
ai4_mb_type_sad[MB_TYPE_INTRA] = irc_fi_get_total_mb_sad(ps_frame_info,MB_TYPE_INTRA);
|
||
|
ai4_mb_type_sad[MB_TYPE_INTER] = irc_fi_get_total_mb_sad(ps_frame_info,MB_TYPE_INTER);
|
||
|
i4_intra_frm_cost = irc_fi_get_total_intra_mb_cost(ps_frame_info);
|
||
|
i4_avg_mb_activity = irc_fi_get_avg_activity(ps_frame_info);
|
||
|
i4_total_hdr_bits = irc_fi_get_total_header_bits(ps_frame_info);
|
||
|
i4_total_texturebits = irc_fi_get_total_mb_texture_bits(ps_frame_info,MB_TYPE_INTRA);
|
||
|
i4_total_texturebits += irc_fi_get_total_mb_texture_bits(ps_frame_info,MB_TYPE_INTER);
|
||
|
i4_total_frame_bits = i4_total_hdr_bits + i4_total_texturebits ;
|
||
|
|
||
|
*pi4_avg_activity = i4_avg_mb_activity;
|
||
|
|
||
|
|
||
|
/* Texture bits are not accumulated. Hence subtracting hdr bits from total bits */
|
||
|
ai4_mb_type_tex_bits[MB_TYPE_INTRA] = 0;
|
||
|
ai4_mb_type_tex_bits[MB_TYPE_INTER] = i4_total_frame_bits - i4_total_hdr_bits;
|
||
|
|
||
|
/* Set post encode skip to zero */
|
||
|
pi4_is_post_encode_skip[0]= 0;
|
||
|
|
||
|
/* For NLDRC, get the buffer status for stuffing or skipping */
|
||
|
if (irc_get_rc_type(ps_rate_control_api) == CBR_NLDRC)
|
||
|
{
|
||
|
WORD32 i4_get_num_bit_to_prevent_vbv_overflow;
|
||
|
UWORD8 u1_enc_buf_overflow,u1_enc_buf_underflow;
|
||
|
|
||
|
/* Getting the buffer status */
|
||
|
ih264e_rc_get_buffer_status(ps_rate_control_api, i4_total_frame_bits,
|
||
|
pe_vop_coding_type[0], &i4_get_num_bit_to_prevent_vbv_overflow,
|
||
|
&u1_enc_buf_overflow,&u1_enc_buf_underflow);
|
||
|
|
||
|
/* We skip the frame if decoder buffer is underflowing. But we never skip first I frame */
|
||
|
if ((u1_enc_buf_overflow == 1) && (i4_is_first_frame != 1))
|
||
|
// if ((u1_enc_buf_overflow == 1) && (i4_is_first_frame != 0))
|
||
|
{
|
||
|
irc_post_encode_frame_skip(ps_rate_control_api, (picture_type_e)pe_vop_coding_type[0]);
|
||
|
// i4_total_frame_bits = imp4_write_skip_frame_header(ps_enc);
|
||
|
i4_total_frame_bits = 0;
|
||
|
|
||
|
*pi4_is_post_encode_skip = 1;
|
||
|
|
||
|
/* Adjust the GOP if in case we skipped an I-frame */
|
||
|
if (*pe_vop_coding_type == I_PIC)
|
||
|
irc_force_I_frame(ps_rate_control_api);
|
||
|
|
||
|
/* Since this frame is skipped by writing 7 bytes header, we say this is a P frame */
|
||
|
// *pe_vop_coding_type = P;
|
||
|
|
||
|
/* Getting the buffer status again,to check if it underflows */
|
||
|
irc_get_buffer_status(ps_rate_control_api, i4_total_frame_bits,
|
||
|
(picture_type_e)pe_vop_coding_type[0], &i4_get_num_bit_to_prevent_vbv_overflow);
|
||
|
|
||
|
}
|
||
|
|
||
|
/* In this case we stuff bytes as buffer is overflowing */
|
||
|
if (u1_enc_buf_underflow == 1)
|
||
|
{
|
||
|
/* The stuffing function is directly pulled out from split controller workspace.
|
||
|
encode_vop_data() function makes sure alignment data is dumped at the end of a
|
||
|
frame. Split controller was identifying this alignment byte, overwriting it with
|
||
|
the stuff data and then finally aligning the buffer. Here every thing is inside
|
||
|
the DSP. So, ideally encode_vop_data needn't align, and we can start stuffing directly.
|
||
|
But in that case, it'll break the logic for a normal frame.
|
||
|
Hence for simplicity, not changing this part since it is ok to align and
|
||
|
then overwrite since stuffing is not done for every frame */
|
||
|
i4_cbr_bits_to_stuff = irc_get_bits_to_stuff(ps_rate_control_api, i4_total_frame_bits, pe_vop_coding_type[0]);
|
||
|
|
||
|
/* Just add extra 32 bits to make sure we don't stuff lesser */
|
||
|
i4_cbr_bits_to_stuff += 32;
|
||
|
|
||
|
/* We can not stuff more than the outbuf size. So have a check here */
|
||
|
/* Add stuffed bits to total bits */
|
||
|
i4_total_frame_bits += i4_cbr_bits_to_stuff;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define ENABLE_SCD 1
|
||
|
#if ENABLE_SCD
|
||
|
/* If number of intra MBs are more than 2/3rd of total MBs, assume it as a scene change */
|
||
|
if ((ai4_tot_mb_in_type[MB_TYPE_INTRA] > ((2 * i4_total_mb_in_frame) / 3)) &&
|
||
|
(*pe_vop_coding_type == P_PIC) &&
|
||
|
(ai4_tot_mb_in_type[MB_TYPE_INTRA] > ((11 * (WORD32)u4_num_intra_in_prev_frame) / 10)))
|
||
|
{
|
||
|
u1_is_scd = 1;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Update num intra mbs of this frame */
|
||
|
if (pi4_is_post_encode_skip[0] == 0)
|
||
|
{
|
||
|
*pi4_num_intra_in_prev_frame = ai4_tot_mb_in_type[MB_TYPE_INTRA];
|
||
|
}
|
||
|
|
||
|
/* Reset intra count to zero, if u encounter an I frame */
|
||
|
if (*pe_vop_coding_type == I_PIC)
|
||
|
{
|
||
|
*pi4_num_intra_in_prev_frame = 0;
|
||
|
}
|
||
|
|
||
|
/* Do an update of rate control after post encode */
|
||
|
irc_update_frame_level_info(ps_rate_control_api, /* RC state */
|
||
|
pe_vop_coding_type[0], /* PIC type */
|
||
|
ai4_mb_type_sad, /* SAD for [Intra/Inter] */
|
||
|
i4_total_frame_bits, /* Total frame bits */
|
||
|
i4_total_hdr_bits, /* header bits for */
|
||
|
ai4_mb_type_tex_bits, /* for MB[Intra/Inter] */
|
||
|
ai4_tot_mb_type_qp, /* for MB[Intra/Inter] */
|
||
|
ai4_tot_mb_in_type, /* for MB[Intra/Inter] */
|
||
|
i4_avg_mb_activity, /* Average mb activity in frame */
|
||
|
u1_is_scd, /* Is a scene change detected */
|
||
|
0, /* Pre encode skip */
|
||
|
(WORD32)i4_intra_frm_cost, /* Intra cost for frame */
|
||
|
0); /* Not done outside */
|
||
|
|
||
|
return (i4_cbr_bits_to_stuff >> 3);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
* @brief Function to update bits consumed info to rate control context
|
||
|
*
|
||
|
* @par Description
|
||
|
* Function to update bits consume info to rate control context
|
||
|
*
|
||
|
* @param[in] ps_frame_info
|
||
|
* Frame info context
|
||
|
*
|
||
|
* @param[in] ps_entropy
|
||
|
* Entropy context
|
||
|
*
|
||
|
* @returns
|
||
|
* total bits consumed by the frame
|
||
|
*
|
||
|
* @remarks
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
void ih264e_update_rc_bits_info(frame_info_t *ps_frame_info, void *pv_entropy)
|
||
|
{
|
||
|
entropy_ctxt_t *ps_entropy = pv_entropy;
|
||
|
|
||
|
ps_frame_info->mb_header_bits[MB_TYPE_INTRA] += ps_entropy->u4_header_bits[MB_TYPE_INTRA];
|
||
|
|
||
|
ps_frame_info->mb_texture_bits[MB_TYPE_INTRA] += ps_entropy->u4_residue_bits[MB_TYPE_INTRA];
|
||
|
|
||
|
ps_frame_info->mb_header_bits[MB_TYPE_INTER] += ps_entropy->u4_header_bits[MB_TYPE_INTER];
|
||
|
|
||
|
ps_frame_info->mb_texture_bits[MB_TYPE_INTER] += ps_entropy->u4_residue_bits[MB_TYPE_INTER];
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|