| /****************************************************************************** |
| * |
| * 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 Name : rc_rd_model.c */ |
| /* */ |
| /* Description : Implall the Functions to Model the */ |
| /* Rate Distortion Behaviour of the Codec over the Last */ |
| /* Few Frames. */ |
| /* */ |
| /* List of Functions : update_frame_rd_model */ |
| /* estimate_mpeg2_qp_for_resbits */ |
| /* */ |
| /* Issues / Problems : None */ |
| /* */ |
| /* Revision History : */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 21 06 2006 ittiam Initial Version */ |
| /****************************************************************************/ |
| /*****************************************************************************/ |
| /* File Includes */ |
| /*****************************************************************************/ |
| /* System include files */ |
| #include <stdarg.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <math.h> |
| |
| /* User include files */ |
| #include "ittiam_datatypes.h" |
| #include "var_q_operator.h" |
| #include "rc_common.h" |
| #include "rc_cntrl_param.h" |
| #include "mem_req_and_acq.h" |
| #include "rc_rd_model.h" |
| #include "rc_rd_model_struct.h" |
| |
| #if RC_FIXED_POINT |
| WORD32 rc_rd_model_num_fill_use_free_memtab( |
| rc_rd_model_t **pps_rc_rd_model, itt_memtab_t *ps_memtab, ITT_FUNC_TYPE_E e_func_type) |
| { |
| WORD32 i4_mem_tab_idx = 0; |
| static rc_rd_model_t s_rc_rd_model_temp; |
| |
| /* Hack for al alloc, during which we dont have any state memory. |
| Dereferencing can cause issues */ |
| if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB) |
| (*pps_rc_rd_model) = &s_rc_rd_model_temp; |
| |
| /*for src rate control state structure*/ |
| if(e_func_type != GET_NUM_MEMTAB) |
| { |
| fill_memtab( |
| &ps_memtab[i4_mem_tab_idx], sizeof(rc_rd_model_t), MEM_TAB_ALIGNMENT, PERSISTENT, DDR); |
| use_or_fill_base(&ps_memtab[0], (void **)pps_rc_rd_model, e_func_type); |
| } |
| i4_mem_tab_idx++; |
| |
| return (i4_mem_tab_idx); |
| } |
| /****************************************************************************** |
| Function Name : init_frm_rc_rd_model |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| void init_frm_rc_rd_model(rc_rd_model_t *ps_rd_model, UWORD8 u1_max_frames_modelled) |
| { |
| /* ps_rd_model = ps_rd_model + u1_pic_type; */ |
| |
| ps_rd_model->u1_num_frms_in_model = 0; |
| ps_rd_model->u1_curr_frm_counter = 0; |
| ps_rd_model->u1_max_frms_to_model = u1_max_frames_modelled; |
| |
| ps_rd_model->model_coeff_a_quad.sm = 0; |
| ps_rd_model->model_coeff_b_quad.sm = 0; |
| ps_rd_model->model_coeff_c_quad.sm = 0; |
| |
| ps_rd_model->model_coeff_a_lin.sm = 0; |
| ps_rd_model->model_coeff_b_lin.sm = 0; |
| ps_rd_model->model_coeff_c_lin.sm = 0; |
| |
| ps_rd_model->model_coeff_a_lin_wo_int.sm = 0; |
| ps_rd_model->model_coeff_b_lin_wo_int.sm = 0; |
| ps_rd_model->model_coeff_c_lin_wo_int.sm = 0; |
| |
| ps_rd_model->model_coeff_a_quad.e = 0; |
| ps_rd_model->model_coeff_b_quad.e = 0; |
| ps_rd_model->model_coeff_c_quad.e = 0; |
| |
| ps_rd_model->model_coeff_a_lin.e = 0; |
| ps_rd_model->model_coeff_b_lin.e = 0; |
| ps_rd_model->model_coeff_c_lin.e = 0; |
| |
| ps_rd_model->model_coeff_a_lin_wo_int.e = 0; |
| ps_rd_model->model_coeff_b_lin_wo_int.e = 0; |
| ps_rd_model->model_coeff_c_lin_wo_int.e = 0; |
| } |
| /****************************************************************************** |
| Function Name : reset_frm_rc_rd_model |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| void reset_frm_rc_rd_model(rc_rd_model_t *ps_rd_model) |
| { |
| ps_rd_model->u1_num_frms_in_model = 0; |
| ps_rd_model->u1_curr_frm_counter = 0; |
| |
| ps_rd_model->model_coeff_a_quad.sm = 0; |
| ps_rd_model->model_coeff_b_quad.sm = 0; |
| ps_rd_model->model_coeff_c_quad.sm = 0; |
| |
| ps_rd_model->model_coeff_a_lin.sm = 0; |
| ps_rd_model->model_coeff_b_lin.sm = 0; |
| ps_rd_model->model_coeff_c_lin.sm = 0; |
| |
| ps_rd_model->model_coeff_a_lin_wo_int.sm = 0; |
| ps_rd_model->model_coeff_b_lin_wo_int.sm = 0; |
| ps_rd_model->model_coeff_c_lin_wo_int.sm = 0; |
| |
| ps_rd_model->model_coeff_a_quad.e = 0; |
| ps_rd_model->model_coeff_b_quad.e = 0; |
| ps_rd_model->model_coeff_c_quad.e = 0; |
| |
| ps_rd_model->model_coeff_a_lin.e = 0; |
| ps_rd_model->model_coeff_b_lin.e = 0; |
| ps_rd_model->model_coeff_c_lin.e = 0; |
| |
| ps_rd_model->model_coeff_a_lin_wo_int.e = 0; |
| ps_rd_model->model_coeff_b_lin_wo_int.e = 0; |
| ps_rd_model->model_coeff_c_lin_wo_int.e = 0; |
| } |
| |
| #if ENABLE_QUAD_MODEL |
| /****************************************************************************** |
| Function Name : find_model_coeffs |
| Description : |
| Arguments : |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| static UWORD8 find_model_coeffs( |
| UWORD32 *pi4_res_bits, |
| LWORD64 *pi8_sad_h264, |
| WORD32 *pi4_avg_mpeg2_qp_q6, |
| UWORD8 u1_num_frms, |
| UWORD8 u1_model_used, |
| WORD8 *pi1_frame_index, |
| number_t *pmc_model_coeff, |
| number_t *pmc_model_coeff_lin, |
| number_t *pmc_model_coeff_lin_wo_int, |
| rc_rd_model_t *ps_rd_model) |
| { |
| UWORD32 i; |
| UWORD8 u1_num_frms_used = 0; |
| UWORD8 u1_frm_indx; |
| |
| number_t sum_y; |
| number_t sum_x_y; |
| number_t sum_x2_y; |
| number_t sum_x; |
| number_t sum_x2; |
| number_t sum_x3; |
| number_t sum_x4; |
| number_t var_x2_y; |
| number_t var_x_y; |
| number_t var_x2_x; |
| number_t var_x2_x2; |
| number_t var_x_x; |
| number_t x0, y0; |
| number_t s_res_bits, s_sad_h264, s_avg_mpeg2_qp; |
| number_t temp, temp1; |
| |
| number_t model_coeff_a, model_coeff_b, model_coeff_c, model_coeff_den; |
| |
| number_t s_num_frms_used; |
| |
| /* initilising */ |
| model_coeff_a.sm = 0; |
| model_coeff_a.e = 0; |
| model_coeff_b.sm = 0; |
| model_coeff_b.e = 0; |
| model_coeff_c.sm = 0; |
| model_coeff_c.e = 0; |
| |
| sum_y.sm = 0; |
| sum_x_y.sm = 0; |
| sum_x2_y.sm = 0; |
| sum_x.sm = 0; |
| sum_x2.sm = 0; |
| sum_x3.sm = 0; |
| sum_x4.sm = 0; |
| var_x2_y.sm = 0; |
| var_x_y.sm = 0; |
| var_x2_x.sm = 0; |
| var_x2_x2.sm = 0; |
| var_x_x.sm = 0; |
| |
| sum_y.e = 0; |
| sum_x_y.e = 0; |
| sum_x2_y.e = 0; |
| sum_x.e = 0; |
| sum_x2.e = 0; |
| sum_x3.e = 0; |
| sum_x4.e = 0; |
| var_x2_y.e = 0; |
| var_x_y.e = 0; |
| var_x2_x.e = 0; |
| var_x2_x2.e = 0; |
| var_x_x.e = 0; |
| |
| for(i = 0; i < u1_num_frms; i++) |
| { |
| LWORD64 i8_local_sad_sm = 0; |
| WORD32 i4_local_e = 0; |
| if(-1 == pi1_frame_index[i]) |
| continue; |
| |
| u1_frm_indx = (UWORD8)pi1_frame_index[i]; |
| |
| s_res_bits.sm = pi4_res_bits[u1_frm_indx]; |
| s_res_bits.e = 0; |
| |
| /*s_sad_h264.sm = pi8_sad_h264[u1_frm_indx]; |
| s_sad_h264.e = 0;*/ |
| i8_local_sad_sm = pi8_sad_h264[u1_frm_indx]; |
| |
| while(i8_local_sad_sm > 0x7FFFFFFF) |
| { |
| i8_local_sad_sm = i8_local_sad_sm / 2; |
| i4_local_e++; |
| } |
| SET_VARQ_FRM_FIXQ(((WORD32)i8_local_sad_sm), s_sad_h264, -i4_local_e); |
| |
| /*fract_quant*/ |
| SET_VARQ_FRM_FIXQ(pi4_avg_mpeg2_qp_q6[u1_frm_indx], s_avg_mpeg2_qp, QSCALE_Q_FAC); |
| |
| y0 = s_res_bits; |
| /*x0 = (float) (pi4_sad_h264[u1_frm_indx] / |
| (float)pui_avg_mpeg2_qp[u1_frm_indx]); */ |
| div32_var_q(s_sad_h264, s_avg_mpeg2_qp, &x0); |
| |
| /* |
| sum_y += y0; |
| sum_x_y += x0 * y0; |
| sum_x2_y += x0 * x0 * y0; |
| sum_x += x0; |
| sum_x2 += x0 * x0; |
| sum_x3 += x0 * x0 * x0; |
| sum_x4 += x0 * x0 * x0 * x0; |
| */ |
| /* sum_y += y0; */ |
| add32_var_q(sum_y, y0, &sum_y); |
| /* sum_x_y += x0 * y0; */ |
| mult32_var_q(x0, y0, &temp); |
| add32_var_q(sum_x_y, temp, &sum_x_y); |
| |
| /* sum_x2_y += x0 * x0 * y0; */ |
| mult32_var_q(x0, temp, &temp); |
| add32_var_q(sum_x2_y, temp, &sum_x2_y); |
| |
| /* sum_x += x0; */ |
| add32_var_q(x0, sum_x, &sum_x); |
| |
| /* sum_x2 += x0 * x0; */ |
| mult32_var_q(x0, x0, &temp); |
| add32_var_q(temp, sum_x2, &sum_x2); |
| |
| /* sum_x3 += x0 * x0 * x0; */ |
| mult32_var_q(x0, temp, &temp); |
| add32_var_q(temp, sum_x3, &sum_x3); |
| |
| /* sum_x4 += x0 * x0 * x0 * x0; */ |
| mult32_var_q(x0, temp, &temp); |
| add32_var_q(temp, sum_x4, &sum_x4); |
| |
| u1_num_frms_used++; |
| } |
| |
| s_num_frms_used.sm = u1_num_frms_used; |
| s_num_frms_used.e = 0; |
| |
| /* sum_y /= u1_num_frms_used; */ |
| div32_var_q(sum_y, s_num_frms_used, &sum_y); |
| /* sum_x_y /= u1_num_frms_used; */ |
| div32_var_q(sum_x_y, s_num_frms_used, &sum_x_y); |
| /* sum_x2_y /= u1_num_frms_used; */ |
| div32_var_q(sum_x2_y, s_num_frms_used, &sum_x2_y); |
| |
| /* sum_x /= u1_num_frms_used; */ |
| div32_var_q(sum_x, s_num_frms_used, &sum_x); |
| |
| /* sum_x2 /= u1_num_frms_used; */ |
| div32_var_q(sum_x2, s_num_frms_used, &sum_x2); |
| |
| /* sum_x3 /= u1_num_frms_used; */ |
| div32_var_q(sum_x3, s_num_frms_used, &sum_x3); |
| |
| /* sum_x4 /= u1_num_frms_used; */ |
| div32_var_q(sum_x4, s_num_frms_used, &sum_x4); |
| |
| #if !QUAD |
| u1_model_used = LIN_MODEL; |
| #endif |
| |
| if((QUAD_MODEL == u1_model_used) && (u1_num_frms_used <= MIN_FRAMES_FOR_QUAD_MODEL)) |
| { |
| u1_model_used = LIN_MODEL; |
| } |
| |
| if(QUAD_MODEL == u1_model_used) |
| { |
| /* var_x2_y = sum_x2_y - sum_x2 * sum_y; */ |
| mult32_var_q(sum_x2, sum_y, &temp); |
| sub32_var_q(sum_x2_y, temp, &var_x2_y); |
| |
| /* var_x_y = sum_x_y - sum_x * sum_y; */ |
| mult32_var_q(sum_x, sum_y, &temp); |
| sub32_var_q(sum_x_y, temp, &var_x_y); |
| |
| /* var_x2_x = sum_x3 - sum_x2 * sum_x; */ |
| mult32_var_q(sum_x2, sum_x, &temp); |
| sub32_var_q(sum_x3, temp, &var_x2_x); |
| |
| /* var_x2_x2 = sum_x4 - sum_x2 * sum_x2; */ |
| mult32_var_q(sum_x2, sum_x2, &temp); |
| sub32_var_q(sum_x4, temp, &var_x2_x2); |
| |
| /* var_x_x = sum_x2 - sum_x * sum_x; */ |
| mult32_var_q(sum_x, sum_x, &temp); |
| sub32_var_q(sum_x2, temp, &var_x_x); |
| |
| /* model_coeff_den = (var_x2_x * var_x2_x - var_x2_x2 * var_x_x); */ |
| mult32_var_q(var_x2_x, var_x2_x, &temp); |
| mult32_var_q(var_x2_x2, var_x_x, &temp1); |
| sub32_var_q(temp, temp1, &model_coeff_den); |
| |
| if(0 != model_coeff_den.sm) |
| { |
| /* model_coeff_b = (var_x_y * var_x2_x - var_x2_y * var_x_x); */ |
| mult32_var_q(var_x_y, var_x2_x, &temp); |
| mult32_var_q(var_x2_y, var_x_x, &temp1); |
| sub32_var_q(temp, temp1, &model_coeff_b); |
| |
| /* model_coeff_b /= model_coeff_den; */ |
| div32_var_q(model_coeff_b, model_coeff_den, &model_coeff_b); |
| |
| /* model_coeff_a = (var_x2_y * var_x2_x - var_x_y * var_x2_x2); */ |
| mult32_var_q(var_x2_y, var_x2_x, &temp); |
| mult32_var_q(var_x_y, var_x2_x2, &temp1); |
| sub32_var_q(temp, temp1, &model_coeff_a); |
| |
| /* model_coeff_a /= model_coeff_den; */ |
| div32_var_q(model_coeff_a, model_coeff_den, &model_coeff_a); |
| |
| /*model_coeff_c = sum_y - (model_coeff_a * sum_x) - |
| (model_coeff_b * sum_x2); */ |
| mult32_var_q(model_coeff_a, sum_x, &temp); |
| mult32_var_q(model_coeff_b, sum_x2, &temp1); |
| sub32_var_q(sum_y, temp, &model_coeff_c); |
| sub32_var_q(model_coeff_c, temp1, &model_coeff_c); |
| /* till here */ |
| } |
| |
| pmc_model_coeff[0] = model_coeff_b; |
| /* pmc_model_coeff[0] = (float)(model_coeff_b.sm /pow(2,model_coeff_b.e)); */ |
| pmc_model_coeff[1] = model_coeff_a; |
| /* pmc_model_coeff[1] = (float)(model_coeff_a.sm /pow(2,model_coeff_a.e)); */ |
| pmc_model_coeff[2] = model_coeff_c; |
| /* pmc_model_coeff[2] = (float)(model_coeff_c.sm /pow(2,model_coeff_c.e)); */ |
| } |
| |
| if(NULL != pmc_model_coeff_lin) |
| { |
| /* var_x_y = sum_x_y - sum_x * sum_y; */ |
| mult32_var_q(sum_x, sum_y, &temp); |
| sub32_var_q(sum_x_y, temp, &var_x_y); |
| |
| /* var_x_x = sum_x2 - sum_x * sum_x; */ |
| mult32_var_q(sum_x, sum_x, &temp); |
| sub32_var_q(sum_x2, temp, &var_x_x); |
| |
| if((0 != var_x_x.sm) && (u1_num_frms > 1)) |
| { |
| /* model_coeff_b = (var_x_y / var_x_x); */ |
| div32_var_q(var_x_y, var_x_x, &model_coeff_b); |
| |
| /* model_coeff_c = sum_y - (model_coeff_b * sum_x); */ |
| mult32_var_q(model_coeff_b, sum_x, &temp); |
| sub32_var_q(sum_y, temp, &model_coeff_c); |
| |
| model_coeff_a = model_coeff_b; |
| |
| pmc_model_coeff_lin[0] = model_coeff_b; |
| /* pmc_model_coeff_lin[0] = (float)(model_coeff_b.sm /pow(2,model_coeff_b.e)); */ |
| |
| pmc_model_coeff_lin[1] = model_coeff_a; |
| /* pmc_model_coeff_lin[1] = (float)(model_coeff_a.sm /pow(2,model_coeff_a.e)); */ |
| |
| pmc_model_coeff_lin[2] = model_coeff_c; |
| /* pmc_model_coeff_lin[2] = (float)(model_coeff_c.sm /pow(2,model_coeff_c.e)); */ |
| } |
| } |
| |
| /* TO DO : FLOAT_TO_FIX */ |
| if(NULL != pmc_model_coeff_lin_wo_int) |
| { |
| UWORD8 u1_curr_frame_index; |
| /* UWORD8 u1_avgqp_prvfrm; */ |
| number_t s_avgqp_prvfrm; |
| /* UWORD32 u4_prevfrm_bits, u4_prevfrm_sad; */ |
| number_t s_prevfrm_bits, s_prevfrm_sad; |
| WORD32 i4_local_e = 0; |
| LWORD64 i8_local_sad_sm = 0; |
| u1_curr_frame_index = ps_rd_model->u1_curr_frm_counter; |
| if(0 == u1_curr_frame_index) |
| u1_curr_frame_index = (UWORD8)(ps_rd_model->u1_max_frms_to_model - 1); |
| else |
| u1_curr_frame_index--; |
| |
| /* u1_avgqp_prvfrm = ps_rd_model->pu1_avg_mp2qp[u1_curr_frame_index]; */ |
| /*fract_quant*/ |
| SET_VARQ_FRM_FIXQ( |
| ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index], s_avgqp_prvfrm, QSCALE_Q_FAC); |
| |
| /* u4_prevfrm_bits = ps_rd_model->pi4_res_bits[u1_curr_frame_index]; */ |
| s_prevfrm_bits.sm = ps_rd_model->pi4_res_bits[u1_curr_frame_index]; |
| s_prevfrm_bits.e = 0; |
| |
| /* u4_prevfrm_sad = ps_rd_model->pi4_sad_h264[u1_curr_frame_index]; */ |
| /*s_prevfrm_sad.sm = ps_rd_model->pi8_sad[u1_curr_frame_index]; |
| s_prevfrm_sad.e = 0;*/ |
| i8_local_sad_sm = ps_rd_model->pi8_sad[u1_curr_frame_index]; |
| while(i8_local_sad_sm > 0x7FFFFFFF) |
| { |
| i8_local_sad_sm = i8_local_sad_sm / 2; |
| i4_local_e++; |
| } |
| SET_VARQ_FRM_FIXQ(((WORD32)i8_local_sad_sm), s_prevfrm_sad, -i4_local_e); |
| |
| if(0 != s_prevfrm_sad.sm) |
| { |
| /* model_coeff_a = (float)(u4_prevfrm_bits * u1_avgqp_prvfrm) / u4_prevfrm_sad; */ |
| mult32_var_q(s_prevfrm_bits, s_avgqp_prvfrm, &model_coeff_a); |
| div32_var_q(model_coeff_a, s_prevfrm_sad, &model_coeff_a); |
| } |
| else |
| { |
| model_coeff_a.sm = 0; |
| model_coeff_a.e = 0; |
| } |
| |
| model_coeff_b.sm = 0; |
| model_coeff_b.e = 0; |
| model_coeff_c.sm = 0; |
| model_coeff_c.e = 0; |
| |
| pmc_model_coeff_lin_wo_int[0] = model_coeff_b; |
| pmc_model_coeff_lin_wo_int[1] = model_coeff_a; |
| pmc_model_coeff_lin_wo_int[2] = model_coeff_c; |
| } |
| /* end of "TO DO : FLOAT_TO_FIX" */ |
| |
| return u1_model_used; |
| } |
| |
| /****************************************************************************** |
| Function Name : refine_set_of_points |
| Description : |
| Arguments : |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| static WORD8 refine_set_of_points( |
| UWORD32 *pi4_res_bits, |
| LWORD64 *pi8_sad_h264, |
| WORD32 *pi4_avg_mpeg2_qp_q6, |
| UWORD8 u1_num_frms, |
| WORD8 *pi1_frame_index, |
| number_t *ps_model_coeff, |
| number_t *ps_avg_deviation) |
| { |
| /* float fl_avg_deviation, fl_estimated_bits, fl_deviation, x_val; */ |
| number_t s_avg_deviation, s_estimated_bits, s_deviation, x_val; |
| /* number_t ps_model_coeff[3]; */ |
| number_t s_sad_h264, s_avg_mpeg2_qp, s_res_bits; |
| number_t temp, temp1; |
| UWORD8 u1_return_value = 1; |
| UWORD32 i; |
| UWORD8 u1_num_frms_used, u1_frm_indx; |
| number_t s_num_frms_used; |
| |
| /* |
| convert_float_to_fix(pmc_model_coeff[0],&ps_model_coeff[0]); |
| convert_float_to_fix(pmc_model_coeff[1],&ps_model_coeff[1]); |
| convert_float_to_fix(pmc_model_coeff[2],&ps_model_coeff[2]); |
| */ |
| |
| u1_num_frms_used = 0; |
| /* fl_avg_deviation = 0; */ |
| s_avg_deviation.sm = 0; |
| s_avg_deviation.e = 0; |
| |
| for(i = 0; i < u1_num_frms; i++) |
| { |
| LWORD64 i8_local_sad_sm = 0; |
| WORD32 i4_local_e = 0; |
| if(-1 == pi1_frame_index[i]) |
| continue; |
| |
| u1_frm_indx = (UWORD8)pi1_frame_index[i]; |
| /*x_val = pi4_sad_h264[u1_frm_indx] / |
| (float) pui_avg_mpeg2_qp[u1_frm_indx]; */ |
| /* s_sad_h264.sm = pi8_sad_h264[u1_frm_indx]; |
| s_sad_h264.e = 0;*/ |
| |
| i8_local_sad_sm = pi8_sad_h264[u1_frm_indx]; |
| while(i8_local_sad_sm > 0x7FFFFFFF) |
| { |
| i8_local_sad_sm = i8_local_sad_sm / 2; |
| i4_local_e++; |
| } |
| SET_VARQ_FRM_FIXQ(((WORD32)i8_local_sad_sm), s_sad_h264, -i4_local_e); |
| |
| /*fract_quant*/ |
| SET_VARQ_FRM_FIXQ(pi4_avg_mpeg2_qp_q6[u1_frm_indx], s_avg_mpeg2_qp, QSCALE_Q_FAC); |
| |
| div32_var_q(s_sad_h264, s_avg_mpeg2_qp, &x_val); |
| |
| /* |
| fl_estimated_bits = (pmc_model_coeff[0] * x_val * x_val ) + |
| (pmc_model_coeff[1] * x_val) + |
| (pmc_model_coeff[2]); |
| */ |
| mult32_var_q(x_val, x_val, &temp); |
| mult32_var_q(temp, ps_model_coeff[0], &temp); |
| mult32_var_q(x_val, ps_model_coeff[1], &temp1); |
| add32_var_q(temp, temp1, &s_estimated_bits); |
| add32_var_q(s_estimated_bits, ps_model_coeff[2], &s_estimated_bits); |
| |
| /* |
| fl_deviation = fabs(pi4_res_bits[u1_frm_indx] - fl_estimated_bits) / |
| (float) pi4_res_bits[u1_frm_indx]; |
| */ |
| s_res_bits.sm = pi4_res_bits[u1_frm_indx]; |
| s_res_bits.e = 0; |
| sub32_var_q(s_res_bits, s_estimated_bits, &temp); |
| temp.sm = (temp.sm > 0) ? temp.sm : (-temp.sm); |
| div32_var_q(temp, s_res_bits, &s_deviation); |
| |
| /* fl_deviation = fl_deviation * fl_deviation; */ |
| mult32_var_q(s_deviation, s_deviation, &s_deviation); |
| |
| /* fl_avg_deviation += fl_deviation;*/ |
| add32_var_q(s_avg_deviation, s_deviation, &s_avg_deviation); |
| |
| u1_num_frms_used++; |
| } |
| |
| /* fl_avg_deviation /= u1_num_frms_used; */ |
| s_num_frms_used.sm = u1_num_frms_used; |
| s_num_frms_used.e = 0; |
| div32_var_q(s_avg_deviation, s_num_frms_used, &s_avg_deviation); |
| |
| /* fl_avg_deviation = sqrt(fl_avg_deviation); */ |
| /* fl_avg_deviation = (fl_avg_deviation); */ |
| |
| for(i = 0; i < u1_num_frms; i++) |
| { |
| LWORD64 i8_local_sad_sm = 0; |
| WORD32 i4_local_e = 0; |
| if ((-1 == pi1_frame_index[i]) /*&& |
| (i != 0)*/) |
| continue; |
| |
| u1_frm_indx = (UWORD8)pi1_frame_index[i]; |
| |
| /* |
| x_val = pi4_sad_h264[u1_frm_indx] / |
| (float) pui_avg_mpeg2_qp[u1_frm_indx]; |
| */ |
| |
| /* s_sad_h264.sm = pi8_sad_h264[u1_frm_indx]; |
| s_sad_h264.e = 0;*/ |
| |
| i8_local_sad_sm = pi8_sad_h264[u1_frm_indx]; |
| while(i8_local_sad_sm > 0x7FFFFFFF) |
| { |
| i8_local_sad_sm = i8_local_sad_sm / 2; |
| i4_local_e++; |
| } |
| SET_VARQ_FRM_FIXQ(((WORD32)i8_local_sad_sm), s_sad_h264, -i4_local_e); |
| |
| /*fract_quant*/ |
| SET_VARQ_FRM_FIXQ(pi4_avg_mpeg2_qp_q6[u1_frm_indx], s_avg_mpeg2_qp, QSCALE_Q_FAC); |
| |
| div32_var_q(s_sad_h264, s_avg_mpeg2_qp, &x_val); |
| |
| /* |
| fl_estimated_bits = (pmc_model_coeff[0] * x_val * x_val ) + |
| (pmc_model_coeff[1] * x_val) + |
| (pmc_model_coeff[2]); |
| */ |
| mult32_var_q(x_val, x_val, &temp); |
| mult32_var_q(temp, ps_model_coeff[0], &temp); |
| mult32_var_q(x_val, ps_model_coeff[1], &temp1); |
| add32_var_q(temp, temp1, &s_estimated_bits); |
| add32_var_q(s_estimated_bits, ps_model_coeff[2], &s_estimated_bits); |
| |
| /* |
| fl_deviation = fabs(pi4_res_bits[u1_frm_indx] - fl_estimated_bits) / |
| (float) pi4_res_bits[u1_frm_indx]; |
| */ |
| s_res_bits.sm = pi4_res_bits[u1_frm_indx]; |
| s_res_bits.e = 0; |
| sub32_var_q(s_res_bits, s_estimated_bits, &temp); |
| temp.sm = (temp.sm > 0) ? temp.sm : (-temp.sm); |
| div32_var_q(temp, s_res_bits, &s_deviation); |
| |
| /* to remove the sqrt function */ |
| /*fl_deviation = fl_deviation * fl_deviation; */ |
| mult32_var_q(s_deviation, s_deviation, &s_deviation); |
| |
| /* |
| if (fl_deviation > (fl_avg_deviation)) |
| { |
| pi1_frame_index[i] = -1; |
| } |
| */ |
| sub32_var_q(s_deviation, s_avg_deviation, &temp); |
| if(temp.sm > 0) |
| { |
| pi1_frame_index[i] = -1; |
| } |
| } |
| |
| { |
| number_t up_thr, lo_thr; |
| |
| /* |
| if (fl_avg_deviation > 0.0625) |
| u1_return_value = 0; |
| */ |
| up_thr.sm = UP_THR_SM; |
| up_thr.e = UP_THR_E; |
| sub32_var_q(s_avg_deviation, up_thr, &temp); |
| if(temp.sm > 0) |
| { |
| u1_return_value = 0; |
| } |
| |
| /* |
| if (fl_avg_deviation < 0.0225) |
| u1_return_value = 2; |
| */ |
| lo_thr.sm = LO_THR_SM; |
| lo_thr.e = LO_THR_E; |
| sub32_var_q(s_avg_deviation, lo_thr, &temp); |
| if(temp.sm < 0) |
| { |
| u1_return_value = 2; |
| } |
| } |
| *ps_avg_deviation = s_avg_deviation; |
| return (u1_return_value); |
| } |
| /****************************************************************************** |
| Function Name : calc_avg_sqr_dev_for_model |
| Description : |
| Arguments : |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| /* TO DO : FLOAT_TO_FIX */ |
| static void calc_avg_sqr_dev_for_model( |
| UWORD32 *pi4_res_bits, |
| LWORD64 *pi8_sad_h264, |
| WORD32 *pi4_avg_mpeg2_qp_q6, |
| UWORD8 u1_num_frms, |
| WORD8 *pi1_frame_index, |
| number_t *ps_model_coeff, |
| number_t *ps_avg_deviation) |
| { |
| /* float fl_avg_deviation, fl_estimated_bits, fl_deviation, x_val; */ |
| number_t s_avg_deviation, s_estimated_bits, s_deviation, x_val; |
| /* UWORD8 u1_return_value = 1; */ |
| UWORD32 i; |
| UWORD8 u1_num_frms_used, u1_frm_indx; |
| |
| number_t s_sad_h264; |
| number_t s_avg_mpeg2_qp; |
| number_t s_res_bits; |
| number_t temp; |
| number_t s_num_frms_used; |
| |
| u1_num_frms_used = 0; |
| /* fl_avg_deviation = 0; */ |
| s_deviation.sm = 0; |
| s_deviation.e = 0; |
| |
| s_avg_deviation.sm = 0; |
| s_avg_deviation.e = 0; |
| |
| for(i = 0; i < u1_num_frms; i++) |
| { |
| LWORD64 i8_local_sad_sm; |
| WORD32 i4_local_e = 0; |
| if(-1 == pi1_frame_index[i]) |
| continue; |
| |
| u1_frm_indx = (UWORD8)pi1_frame_index[i]; |
| |
| u1_frm_indx = (UWORD8)i; |
| /* |
| x_val = pi4_sad_h264[u1_frm_indx] / |
| (float) pui_avg_mpeg2_qp[u1_frm_indx]; |
| */ |
| /* s_sad_h264.sm = pi8_sad_h264[u1_frm_indx]; |
| s_sad_h264.e = 0;*/ |
| i8_local_sad_sm = pi8_sad_h264[u1_frm_indx]; |
| while(i8_local_sad_sm > 0x7FFFFFFF) |
| { |
| i8_local_sad_sm = i8_local_sad_sm / 2; |
| i4_local_e++; |
| } |
| SET_VARQ_FRM_FIXQ(((WORD32)i8_local_sad_sm), s_sad_h264, -i4_local_e); |
| /*fract_quant*/ |
| SET_VARQ_FRM_FIXQ(pi4_avg_mpeg2_qp_q6[u1_frm_indx], s_avg_mpeg2_qp, QSCALE_Q_FAC); |
| |
| div32_var_q(s_sad_h264, s_avg_mpeg2_qp, &x_val); |
| |
| /*fl_estimated_bits = (pmc_model_coeff[1] * x_val) + |
| (pmc_model_coeff[2]); */ |
| mult32_var_q(x_val, ps_model_coeff[1], &s_estimated_bits); |
| add32_var_q(s_estimated_bits, ps_model_coeff[2], &s_estimated_bits); |
| |
| /*fl_deviation = fabs(pi4_res_bits[u1_frm_indx] - fl_estimated_bits) / |
| (float) pi4_res_bits[u1_frm_indx]; */ |
| s_res_bits.sm = pi4_res_bits[u1_frm_indx]; |
| s_res_bits.e = 0; |
| sub32_var_q(s_res_bits, s_estimated_bits, &temp); |
| temp.sm = (temp.sm > 0) ? temp.sm : (-temp.sm); |
| div32_var_q(temp, s_res_bits, &s_deviation); |
| |
| /* fl_deviation = fl_deviation * fl_deviation; */ |
| mult32_var_q(s_deviation, s_deviation, &s_deviation); |
| |
| /* fl_avg_deviation += fl_deviation; */ |
| add32_var_q(s_avg_deviation, s_deviation, &s_avg_deviation); |
| |
| u1_num_frms_used++; |
| } |
| |
| /* fl_avg_deviation /= u1_num_frms_used; */ |
| s_num_frms_used.sm = u1_num_frms_used; |
| s_num_frms_used.e = 0; |
| div32_var_q(s_avg_deviation, s_num_frms_used, &s_avg_deviation); |
| *ps_avg_deviation = s_avg_deviation; |
| } |
| /* end of "TO DO : FLOAT_TO_FIX" */ |
| /****************************************************************************** |
| Function Name : is_qp_available |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| static WORD32 is_qp_available( |
| rc_rd_model_t *ps_rd_model, UWORD8 u1_curr_frame_index, WORD32 i4_num_frames_to_check) |
| { |
| WORD32 i; |
| /*fract_quant*/ |
| WORD32 i4_qp = ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index]; |
| WORD32 i4_num_frms = 0; |
| |
| for(i = 0; i < i4_num_frames_to_check; i++) |
| { |
| u1_curr_frame_index++; |
| if(ps_rd_model->u1_max_frms_to_model == u1_curr_frame_index) |
| u1_curr_frame_index = 0; |
| /*fract_quant*/ |
| if(ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index] == i4_qp) |
| i4_num_frms++; |
| } |
| if(i4_num_frms >= 2) |
| return (1); |
| else |
| return (0); |
| } |
| /****************************************************************************/ |
| /* */ |
| /* Function Name : example_of_a_function */ |
| /* */ |
| /* Description : This function illustrates the use of C coding standards.*/ |
| /* switch/case, if, for, block comments have been shown */ |
| /* here. */ |
| /* Inputs : <What inputs does the function take?> */ |
| /* Globals : <Does it use any global variables?> */ |
| /* Processing : <Describe how the function operates - include algorithm */ |
| /* description> */ |
| /* Outputs : <What does the function produce?> */ |
| /* Returns : <What does the function return?> */ |
| /* */ |
| /* Issues : <List any issues or problems with this function> */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 13 07 2002 Ittiam Draft */ |
| /* */ |
| /****************************************************************************/ |
| static void update_frame_rd_model(rc_rd_model_t *ps_rd_model) |
| { |
| WORD8 pi1_frame_index[MAX_FRAMES_MODELLED]; |
| WORD8 pi1_frame_index_initial[MAX_FRAMES_MODELLED]; |
| UWORD32 u4_num_skips; |
| |
| UWORD8 u1_num_skips_temp; |
| /*UWORD8 u1_avg_mpeg2_qp_temp, u1_min_mpeg2_qp, u1_max_mpeg2_qp; */ |
| /*WORD32 i4_avg_mpeg2_qp_temp, i4_min_mpeg2_qp, i4_max_mpeg2_qp;*/ |
| WORD32 i4_avg_mpeg2_qp_temp_q6, i4_min_mpeg2_qp_q6, i4_max_mpeg2_qp_q6; |
| UWORD8 u1_num_frms_input, u1_num_active_frames, u1_reject_frame; |
| |
| /* UWORD8 u1_min2_mpeg2_qp, u1_max2_mpeg2_qp; */ |
| /* WORD32 i4_min2_mpeg2_qp, i4_max2_mpeg2_qp;*/ |
| WORD32 i4_min2_mpeg2_qp_q6, i4_max2_mpeg2_qp_q6; |
| UWORD8 u1_min_qp_frame_indx, u1_max_qp_frame_indx; |
| |
| number_t model_coeff_array[3], model_coeff_array_lin[3]; |
| number_t model_coeff_array_lin_wo_int[3]; |
| WORD32 i; |
| UWORD8 u1_curr_frame_index; |
| |
| #if RC_MODEL_USED_BUG_FIX |
| UWORD8 u1_lin_model_valid; |
| #endif |
| |
| number_t s_quad_avg_sqr_dev, s_lin_avg_sqr_dev; |
| |
| UWORD8 u1_check_model; |
| |
| model_coeff_array[0].sm = 0; |
| model_coeff_array[0].e = 0; |
| model_coeff_array[1].sm = 0; |
| model_coeff_array[1].e = 0; |
| model_coeff_array[2].sm = 0; |
| model_coeff_array[2].e = 0; |
| |
| model_coeff_array_lin[0].sm = 0; |
| model_coeff_array_lin[0].e = 0; |
| model_coeff_array_lin[1].sm = 0; |
| model_coeff_array_lin[1].e = 0; |
| model_coeff_array_lin[2].sm = 0; |
| model_coeff_array_lin[2].e = 0; |
| |
| model_coeff_array_lin_wo_int[0].sm = 0; |
| model_coeff_array_lin_wo_int[0].e = 0; |
| model_coeff_array_lin_wo_int[1].sm = 0; |
| model_coeff_array_lin_wo_int[1].e = 0; |
| model_coeff_array_lin_wo_int[2].sm = 0; |
| model_coeff_array_lin_wo_int[2].e = 0; |
| |
| /* ps_rd_model += u1_pic_type; */ |
| |
| u1_curr_frame_index = ps_rd_model->u1_curr_frm_counter; |
| |
| ps_rd_model->u1_model_used = QUAD_MODEL; |
| |
| if(0 == u1_curr_frame_index) |
| u1_curr_frame_index = (UWORD8)(ps_rd_model->u1_max_frms_to_model - 1); |
| else |
| u1_curr_frame_index--; |
| |
| /************************************************************************/ |
| /* Rearrange data to be fed into a Linear Regression Module */ |
| /* Module finds a,b,c such that */ |
| /* y = ax + bx^2 + c */ |
| /************************************************************************/ |
| u4_num_skips = 0; |
| u1_num_frms_input = 0; |
| /*memset(ps_rd_model->au1_num_frames, 0, MPEG2_QP_ELEM);*/ |
| memset(pi1_frame_index, -1, MAX_FRAMES_MODELLED); |
| /*i4_min_mpeg2_qp = MAX_MPEG2_QP; |
| i4_max_mpeg2_qp = 0;*/ |
| |
| i4_min_mpeg2_qp_q6 = (MAX_MPEG2_QP << QSCALE_Q_FAC); |
| i4_max_mpeg2_qp_q6 = MIN_QSCALE_Q6; |
| |
| u1_num_active_frames = ps_rd_model->u1_num_frms_in_model; |
| if(u1_num_active_frames > MAX_ACTIVE_FRAMES) |
| u1_num_active_frames = MAX_ACTIVE_FRAMES; |
| |
| /************************************************************************/ |
| /* Choose the set of Points to be used for MSE fit of Quadratic model */ |
| /* Points chosen are spread across the Qp range. Max of 2 points are */ |
| /* chosen for a Qp. */ |
| /************************************************************************/ |
| for(i = 0; i < u1_num_active_frames; i++) |
| { |
| /* WORD32 i4_test1 = 0, i4_test2 = 0; NITT TBD */ |
| u1_reject_frame = 0; |
| u1_num_skips_temp = ps_rd_model->pu1_num_skips[u1_curr_frame_index]; |
| /*fract_quant*/ |
| /*i4_avg_mpeg2_qp_temp = (ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index] >> QSCALE_Q_FAC);*/ |
| i4_avg_mpeg2_qp_temp_q6 = ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index]; |
| |
| if((0 == u4_num_skips) && (0 != u1_num_skips_temp)) |
| u1_reject_frame = 1; |
| if((1 == u4_num_skips) && (u1_num_skips_temp > 1)) |
| u1_reject_frame = 1; |
| /* If there is already a frame having same qp reject the current frame */ |
| if(is_qp_available(ps_rd_model, u1_curr_frame_index, i)) |
| u1_reject_frame = 1; |
| /*if (ps_rd_model->au1_num_frames[i4_avg_mpeg2_qp_temp] >= 2) |
| { |
| u1_reject_frame = 1; |
| i4_test2 = 1; |
| } |
| if(i4_test2 != i4_test1) |
| { |
| printf("Why am I here??\n"); |
| }*/ |
| |
| if(0 == i) |
| u1_reject_frame = 0; |
| |
| if(0 == u1_reject_frame) |
| { |
| pi1_frame_index[u1_num_frms_input] = (WORD8)u1_curr_frame_index; |
| /* ps_rd_model->au1_num_frames[i4_avg_mpeg2_qp_temp] += 1; */ |
| |
| /*if (i4_min_mpeg2_qp > i4_avg_mpeg2_qp_temp) i4_min_mpeg2_qp = i4_avg_mpeg2_qp_temp; |
| if (i4_max_mpeg2_qp < i4_avg_mpeg2_qp_temp) i4_max_mpeg2_qp = i4_avg_mpeg2_qp_temp;*/ |
| |
| if(i4_min_mpeg2_qp_q6 > i4_avg_mpeg2_qp_temp_q6) |
| i4_min_mpeg2_qp_q6 = i4_avg_mpeg2_qp_temp_q6; |
| if(i4_max_mpeg2_qp_q6 < i4_avg_mpeg2_qp_temp_q6) |
| i4_max_mpeg2_qp_q6 = i4_avg_mpeg2_qp_temp_q6; |
| u1_num_frms_input++; |
| } |
| |
| if(0 == u1_curr_frame_index) |
| u1_curr_frame_index = (UWORD8)(ps_rd_model->u1_max_frms_to_model - 1); |
| else |
| u1_curr_frame_index--; |
| } |
| |
| /************************************************************************/ |
| /* Add Pivot Points to the Data set to be used for finding Quadratic */ |
| /* Model Coeffs. These will help in constraining the shape of Quadratic*/ |
| /* to adapt too much to the Local deviations. */ |
| /************************************************************************/ |
| /*i4_min2_mpeg2_qp = i4_min_mpeg2_qp; |
| i4_max2_mpeg2_qp = i4_max_mpeg2_qp;*/ |
| |
| i4_min2_mpeg2_qp_q6 = i4_min_mpeg2_qp_q6; |
| i4_max2_mpeg2_qp_q6 = i4_max_mpeg2_qp_q6; |
| |
| u1_min_qp_frame_indx = INVALID_FRAME_INDEX; |
| u1_max_qp_frame_indx = INVALID_FRAME_INDEX; |
| |
| /* Loop runnning over the Stored Frame Level Data |
| to find frames of MinQp and MaxQp */ |
| for(; i < ps_rd_model->u1_num_frms_in_model; i++) |
| { |
| u1_num_skips_temp = ps_rd_model->pu1_num_skips[u1_curr_frame_index]; |
| /*fract_quant*/ |
| //i4_avg_mpeg2_qp_temp = ps_rd_model->ai4_avg_qp[u1_curr_frame_index]; |
| |
| //i4_avg_mpeg2_qp_temp = (ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index] >> QSCALE_Q_FAC); |
| |
| i4_avg_mpeg2_qp_temp_q6 = ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index]; |
| |
| if(((0 == u4_num_skips) && (0 != u1_num_skips_temp)) || |
| ((1 == u4_num_skips) && (u1_num_skips_temp > 1))) |
| continue; |
| /* |
| if (i4_min2_mpeg2_qp > i4_avg_mpeg2_qp_temp) |
| { |
| i4_min2_mpeg2_qp = i4_avg_mpeg2_qp_temp; |
| u1_min_qp_frame_indx = u1_curr_frame_index; |
| } |
| if (i4_max2_mpeg2_qp < i4_avg_mpeg2_qp_temp) |
| { |
| i4_max2_mpeg2_qp = i4_avg_mpeg2_qp_temp; |
| u1_max_qp_frame_indx = u1_curr_frame_index; |
| } |
| */ |
| |
| if(i4_min2_mpeg2_qp_q6 > i4_avg_mpeg2_qp_temp_q6) |
| { |
| i4_min2_mpeg2_qp_q6 = i4_avg_mpeg2_qp_temp_q6; |
| u1_min_qp_frame_indx = u1_curr_frame_index; |
| } |
| if(i4_max2_mpeg2_qp_q6 < i4_avg_mpeg2_qp_temp_q6) |
| { |
| i4_max2_mpeg2_qp_q6 = i4_avg_mpeg2_qp_temp_q6; |
| u1_max_qp_frame_indx = u1_curr_frame_index; |
| } |
| |
| if(0 == u1_curr_frame_index) |
| u1_curr_frame_index = (UWORD8)(ps_rd_model->u1_max_frms_to_model - 1); |
| else |
| u1_curr_frame_index--; |
| } |
| |
| /* Add the Chosen Points to the regression data set */ |
| if(INVALID_FRAME_INDEX != u1_min_qp_frame_indx) |
| { |
| pi1_frame_index[u1_num_frms_input] = (WORD8)u1_min_qp_frame_indx; |
| u1_num_frms_input++; |
| } |
| if(INVALID_FRAME_INDEX != u1_max_qp_frame_indx) |
| { |
| pi1_frame_index[u1_num_frms_input] = (WORD8)u1_max_qp_frame_indx; |
| u1_num_frms_input++; |
| } |
| |
| /* memcpy(pi1_frame_index_initial, pi1_frame_index, MAX_FRAMES_MODELLED); */ |
| { |
| UWORD8 u1_k; |
| for(u1_k = 0; u1_k < MAX_FRAMES_MODELLED; u1_k++) |
| { |
| pi1_frame_index_initial[u1_k] = pi1_frame_index[u1_k]; |
| } |
| } |
| |
| if(QUAD_MODEL == ps_rd_model->u1_model_used) |
| { |
| if(u1_num_frms_input < (MIN_FRAMES_FOR_QUAD_MODEL)) |
| ps_rd_model->u1_model_used = LIN_MODEL; |
| if((WORD32)i4_max_mpeg2_qp_q6 < ((WORD32)(21 * i4_min_mpeg2_qp_q6) >> 4)) |
| ps_rd_model->u1_model_used = LIN_MODEL; |
| } |
| |
| if(LIN_MODEL == ps_rd_model->u1_model_used) |
| { |
| if(u1_num_frms_input < MIN_FRAMES_FOR_LIN_MODEL) |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| if((WORD32)i4_max_mpeg2_qp_q6 < ((WORD32)(19 * i4_min_mpeg2_qp_q6) >> 4)) |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| } |
| |
| /***** Call the Module to Return the Coeffs for the Fed Data *****/ |
| ps_rd_model->u1_model_used = find_model_coeffs( |
| ps_rd_model->pi4_res_bits, |
| ps_rd_model->pi8_sad, |
| ps_rd_model->ai4_avg_qp_q6, |
| u1_num_frms_input, |
| ps_rd_model->u1_model_used, |
| pi1_frame_index, |
| model_coeff_array, |
| model_coeff_array_lin, |
| model_coeff_array_lin_wo_int, |
| ps_rd_model); |
| |
| if((model_coeff_array_lin[2].sm > 0) || (model_coeff_array_lin[0].sm < 0)) |
| { |
| #if RC_MODEL_USED_BUG_FIX |
| u1_lin_model_valid = 0; |
| #endif |
| } |
| else |
| { |
| #if RC_MODEL_USED_BUG_FIX |
| u1_lin_model_valid = 1; |
| #endif |
| /* lin deviation calculation */ |
| calc_avg_sqr_dev_for_model( |
| ps_rd_model->pi4_res_bits, |
| ps_rd_model->pi8_sad, |
| ps_rd_model->ai4_avg_qp_q6, |
| u1_num_frms_input, |
| pi1_frame_index_initial, |
| model_coeff_array_lin, |
| &s_lin_avg_sqr_dev); |
| } |
| |
| if(QUAD_MODEL == ps_rd_model->u1_model_used) |
| { |
| u1_check_model = refine_set_of_points( |
| ps_rd_model->pi4_res_bits, |
| ps_rd_model->pi8_sad, |
| ps_rd_model->ai4_avg_qp_q6, |
| u1_num_frms_input, |
| pi1_frame_index, |
| model_coeff_array, |
| &s_quad_avg_sqr_dev); |
| |
| if(2 == u1_check_model) |
| { |
| ps_rd_model->u1_model_used = QUAD_MODEL; |
| } |
| else |
| { |
| /*******************************************************************/ |
| /* Make sure that some of the Pivot Points are used in the Refined */ |
| /* data set. 1. Previous Frame */ |
| /*******************************************************************/ |
| /* pi1_frame_index[0] = ps_rd_model->u1_curr_frm_counter; */ |
| |
| ps_rd_model->u1_model_used = find_model_coeffs( |
| ps_rd_model->pi4_res_bits, |
| ps_rd_model->pi8_sad, |
| ps_rd_model->ai4_avg_qp_q6, |
| u1_num_frms_input, |
| ps_rd_model->u1_model_used, |
| pi1_frame_index, |
| model_coeff_array, |
| NULL, |
| NULL, |
| ps_rd_model); |
| |
| u1_check_model = refine_set_of_points( |
| ps_rd_model->pi4_res_bits, |
| ps_rd_model->pi8_sad, |
| ps_rd_model->ai4_avg_qp_q6, |
| u1_num_frms_input, |
| pi1_frame_index, |
| model_coeff_array, |
| &s_quad_avg_sqr_dev); |
| |
| if((0 == u1_check_model)) |
| { |
| #if RC_MODEL_USED_BUG_FIX |
| if((s_lin_avg_sqr_dev < s_quad_avg_sqr_dev) && (1 == u1_lin_model_valid)) |
| #endif |
| ps_rd_model->u1_model_used = LIN_MODEL; |
| } |
| } |
| } |
| |
| if(QUAD_MODEL == ps_rd_model->u1_model_used) |
| { |
| /* min_res_bits = model_coeff_c - */ |
| /* ((model_coeff_a * model_coeff_a) / (4 * model_coeff_b)); */ |
| |
| if(model_coeff_array[0].sm < 0) |
| ps_rd_model->u1_model_used = LIN_MODEL; |
| |
| /* if ((model_coeff_a * model_coeff_b) > 0) */ |
| /* u1_model_used = LIN_MODEL; */ |
| |
| ps_rd_model->model_coeff_b_quad = model_coeff_array[0]; |
| ps_rd_model->model_coeff_a_quad = model_coeff_array[1]; |
| ps_rd_model->model_coeff_c_quad = model_coeff_array[2]; |
| } |
| if(LIN_MODEL == ps_rd_model->u1_model_used) |
| { |
| if((model_coeff_array_lin[2].sm > 0) || (model_coeff_array_lin[0].sm < 0)) |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| } |
| /* TO DO : FLOAT_TO_FIX */ |
| #if RC_MODEL_USED_BUG_FIX |
| { |
| number_t s_quad_dev_thr; |
| number_t s_lin_dev_thr; |
| number_t s_diff; |
| |
| s_quad_dev_thr.sm = QUAD_DEV_THR_SM; |
| s_quad_dev_thr.e = QUAD_DEV_THR_E; |
| |
| /* (s_quad_avg_sqr_dev > .25) */ |
| sub32_var_q(s_quad_avg_sqr_dev, s_quad_dev_thr, &s_diff); |
| |
| /* Another threshold of .25 on deviation i.e. deviation greater than 25% */ |
| if((QUAD_MODEL == ps_rd_model->u1_model_used) && (s_diff.sm > 0)) |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| |
| s_lin_dev_thr.sm = LIN_DEV_THR_SM; |
| s_lin_dev_thr.e = LIN_DEV_THR_E; |
| |
| /* (s_lin_avg_sqr_dev > .25) */ |
| sub32_var_q(s_lin_avg_sqr_dev, s_lin_dev_thr, &s_diff); |
| |
| if((LIN_MODEL == ps_rd_model->u1_model_used) && (s_diff.sm > 0)) |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| } |
| #endif /* #if RC_MODEL_USED_BUG_FIX */ |
| /* end of "TO DO : FLOAT_TO_FIX" */ |
| ps_rd_model->model_coeff_b_lin = model_coeff_array_lin[0]; |
| ps_rd_model->model_coeff_a_lin = model_coeff_array_lin[1]; |
| ps_rd_model->model_coeff_c_lin = model_coeff_array_lin[2]; |
| ps_rd_model->model_coeff_b_lin_wo_int = model_coeff_array_lin_wo_int[0]; |
| ps_rd_model->model_coeff_a_lin_wo_int = model_coeff_array_lin_wo_int[1]; |
| ps_rd_model->model_coeff_c_lin_wo_int = model_coeff_array_lin_wo_int[2]; |
| /* ps_rd_model->u1_model_used = PREV_FRAME_MODEL; */ |
| } |
| #endif |
| |
| /****************************************************************************** |
| Function Name : estimate_bits_for_qp |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| UWORD32 |
| estimate_bits_for_qp(rc_rd_model_t *ps_rd_model, UWORD32 u4_estimated_sad, WORD32 i4_avg_qp_q6) |
| { |
| /* float fl_num_bits; */ |
| number_t s_num_bits; |
| number_t s_estimated_sad, s_avg_qp; |
| |
| /* number_t s_model_coeff_a, s_model_coeff_b, s_model_coeff_c; */ |
| WORD32 i4_temp; |
| number_t x_val; |
| |
| /* ps_rd_model += u1_curr_pic_type; */ |
| s_estimated_sad.sm = u4_estimated_sad; |
| s_estimated_sad.e = 0; |
| /*fract_quant*/ |
| SET_VARQ_FRM_FIXQ(i4_avg_qp_q6, s_avg_qp, QSCALE_Q_FAC); |
| /* initilising s_num_bits */ |
| s_num_bits.sm = 0; |
| s_num_bits.e = 0; |
| |
| /* |
| convert_float_to_fix(ps_rd_model->model_coeff_a, &s_model_coeff_a); |
| convert_float_to_fix(ps_rd_model->model_coeff_b, &s_model_coeff_b); |
| convert_float_to_fix(ps_rd_model->model_coeff_c, &s_model_coeff_c); |
| */ |
| div32_var_q(s_estimated_sad, s_avg_qp, &x_val); |
| { |
| /* TO DO : FLOAT_TO_FIX */ |
| /* fl_num_bits = ps_rd_model->model_coeff_a_lin_wo_int * x_val; */ |
| mult32_var_q(ps_rd_model->model_coeff_a_lin_wo_int, x_val, &s_num_bits); |
| /* end of "TO DO : FLOAT_TO_FIX" */ |
| } |
| |
| /* return ((UWORD32) fl_num_bits); */ |
| number_t_to_word32(s_num_bits, &i4_temp); |
| if(i4_temp < 0) |
| i4_temp = 0; |
| return ((UWORD32)i4_temp); |
| } |
| |
| /****************************************************************************** |
| Function Name : find_qp_for_target_bits |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| WORD32 find_qp_for_target_bits( |
| rc_rd_model_handle ps_rd_model, |
| UWORD32 u4_target_res_bits, |
| UWORD32 u4_estimated_sad, |
| WORD32 i4_max_qp_q6, |
| WORD32 i4_min_qp_q6) |
| { |
| WORD32 i4_qp_q6; |
| /* float x_value, f_qp; */ |
| number_t x_value, s_qp; |
| /* number_t s_model_coeff_a, s_model_coeff_b, s_model_coeff_c; */ |
| number_t s_target_res_bits; |
| number_t s_estimated_sad; |
| number_t temp, temp3; |
| number_t temp2, temp1; |
| |
| /* ps_rd_model += u1_curr_pic_type; */ |
| |
| s_target_res_bits.sm = u4_target_res_bits; |
| s_target_res_bits.e = 0; |
| |
| s_estimated_sad.sm = u4_estimated_sad; |
| s_estimated_sad.e = 0; |
| |
| /* initilising default value */ |
| x_value.sm = 0; |
| x_value.e = 0; |
| |
| /* |
| convert_float_to_fix(ps_rd_model->model_coeff_a, &(ps_rd_model->s_model_coeff_a)); |
| convert_float_to_fix(ps_rd_model->model_coeff_b, &(ps_rd_model->s_model_coeff_b)); |
| convert_float_to_fix(ps_rd_model->model_coeff_c, &(ps_rd_model->s_model_coeff_c)); |
| */ |
| |
| #if ENABLE_QUAD_MODEL |
| if(QUAD_MODEL == ps_rd_model->u1_model_used) |
| { |
| /* float det; */ |
| number_t det; |
| |
| /* |
| det = (ps_rd_model->model_coeff_a * ps_rd_model->model_coeff_a) - |
| (4 * (ps_rd_model->model_coeff_b) * |
| (ps_rd_model->model_coeff_c - u4_target_res_bits)); |
| */ |
| mult32_var_q(ps_rd_model->model_coeff_a_quad, ps_rd_model->model_coeff_a_quad, &temp); |
| temp3.sm = 4; |
| temp3.e = 0; |
| mult32_var_q(temp3, ps_rd_model->model_coeff_b_quad, &temp1); |
| sub32_var_q(ps_rd_model->model_coeff_c_quad, s_target_res_bits, &temp2); |
| mult32_var_q(temp1, temp2, &temp1); |
| sub32_var_q(temp, temp1, &det); |
| |
| /* x_value = sqrt(det); */ |
| sqrt32_var_q(det, &x_value); |
| |
| /* x_value = (x_value - ps_rd_model->model_coeff_a) / |
| (2 * ps_rd_model->model_coeff_b); |
| */ |
| sub32_var_q(x_value, ps_rd_model->model_coeff_a_quad, &temp); |
| temp3.sm = 2; |
| temp3.e = 0; |
| mult32_var_q(temp3, ps_rd_model->model_coeff_b_quad, &temp1); |
| div32_var_q(temp, temp1, &x_value); |
| |
| if(det.sm < 0 || x_value.sm < 0) |
| { |
| /* x_value = 0; */ |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| } |
| } |
| |
| if(LIN_MODEL == ps_rd_model->u1_model_used) |
| { |
| /* |
| x_value = ((float)u4_target_res_bits - ps_rd_model->model_coeff_c) / |
| (ps_rd_model->model_coeff_b); |
| */ |
| sub32_var_q(s_target_res_bits, ps_rd_model->model_coeff_c_lin, &temp); |
| div32_var_q(temp, ps_rd_model->model_coeff_b_lin, &x_value); |
| if(x_value.sm < 0) |
| { |
| /* x_value = 0; */ |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| } |
| } |
| #else |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| #endif |
| if(PREV_FRAME_MODEL == ps_rd_model->u1_model_used) |
| { |
| /* TO DO : FLOAT_TO_FIX */ |
| /* x_value = (float) u4_target_res_bits / ps_rd_model->model_coeff_a_lin_wo_int; */ |
| div32_var_q(s_target_res_bits, ps_rd_model->model_coeff_a_lin_wo_int, &x_value); |
| /* end of "TO DO : FLOAT_TO_FIX" */ |
| } |
| |
| if(0 != x_value.sm) |
| { |
| /* f_qp = u4_estimated_sad / x_value; */ |
| div32_var_q(s_estimated_sad, x_value, &s_qp); |
| } |
| else |
| { |
| s_qp.sm = MAX_MPEG2_QP; |
| s_qp.e = 0; |
| } |
| |
| /* |
| if (f_qp > MAX_MPEG2_QP) |
| f_qp = MAX_MPEG2_QP; |
| */ |
| temp3.sm = MAX_MPEG2_QP; |
| temp3.e = 0; |
| sub32_var_q(s_qp, temp3, &temp); |
| if(temp.sm > 0) |
| { |
| s_qp = temp3; |
| } |
| convert_varq_to_fixq(s_qp, &i4_qp_q6, (WORD32)QSCALE_Q_FAC); |
| /* Truncating the QP to the Max and Min Qp values possible */ |
| if(i4_qp_q6 < i4_min_qp_q6) |
| { |
| i4_qp_q6 = i4_min_qp_q6; |
| } |
| if(i4_qp_q6 > i4_max_qp_q6) |
| { |
| i4_qp_q6 = i4_max_qp_q6; |
| } |
| return (i4_qp_q6); |
| } |
| /****************************************************************************** |
| Function Name : add_frame_to_rd_model |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| void add_frame_to_rd_model( |
| rc_rd_model_t *ps_rd_model, |
| UWORD32 i4_res_bits, |
| WORD32 i4_avg_mp2qp_q6, |
| LWORD64 i8_sad_h264, |
| UWORD8 u1_num_skips) |
| { |
| UWORD8 u1_curr_frame_index, i4_same_bit_count = 0; |
| /* ps_rd_model += u1_curr_pic_type; */ |
| u1_curr_frame_index = ps_rd_model->u1_curr_frm_counter; |
| |
| { |
| WORD32 i; |
| |
| i = ps_rd_model->u1_num_frms_in_model - 1; |
| while(i >= 0) |
| { |
| if(ps_rd_model->pi4_res_bits[i] == i4_res_bits) |
| i4_same_bit_count++; |
| i--; |
| } |
| } |
| /* - the condition check is a temporary fix to avoid feeding zero into model. |
| The change should be done so that 0 is not at all fed into model. When texture bit consumption becomes zero next frame qp should be explicitly decreased so that finite amount of texture |
| bits is consumed and feeds valid data to model to come out of deadlock*/ |
| |
| if(i4_same_bit_count < 3) |
| { |
| /*** Insert the Present Frame Data into the RD Model State Memory ***/ |
| ps_rd_model->pi4_res_bits[u1_curr_frame_index] = i4_res_bits; |
| ps_rd_model->pi8_sad[u1_curr_frame_index] = i8_sad_h264; |
| ps_rd_model->pu1_num_skips[u1_curr_frame_index] = u1_num_skips; |
| ps_rd_model->ai4_avg_qp[u1_curr_frame_index] = (i4_avg_mp2qp_q6 >> QSCALE_Q_FAC); |
| ps_rd_model->ai4_avg_qp_q6[u1_curr_frame_index] = i4_avg_mp2qp_q6; |
| |
| ps_rd_model->u1_curr_frm_counter++; |
| if(ps_rd_model->u1_max_frms_to_model == ps_rd_model->u1_curr_frm_counter) |
| ps_rd_model->u1_curr_frm_counter = 0; |
| |
| if(ps_rd_model->u1_num_frms_in_model < ps_rd_model->u1_max_frms_to_model) |
| { |
| ps_rd_model->u1_num_frms_in_model++; |
| } |
| update_frame_rd_model(ps_rd_model); |
| } |
| } |
| /****************************************************************************** |
| Function Name : get_linear_coefficient |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| number_t get_linear_coefficient(rc_rd_model_t *ps_rd_model) |
| { |
| return (ps_rd_model->model_coeff_a_lin_wo_int); |
| } |
| /****************************************************************************** |
| Function Name : set_linear_coefficient |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| void set_linear_coefficient(rc_rd_model_t *ps_rd_model, number_t model_coeff_a_lin_wo_int) |
| { |
| ps_rd_model->model_coeff_a_lin_wo_int = model_coeff_a_lin_wo_int; |
| ps_rd_model->u1_model_used = PREV_FRAME_MODEL; |
| } |
| /****************************************************************************** |
| Function Name : is_model_valid |
| Description : |
| Arguments : ps_rd_model |
| Return Values : void |
| Revision History: |
| Creation |
| *****************************************************************************/ |
| WORD32 is_model_valid(rc_rd_model_t *ps_rd_model) |
| { |
| /*return 1 if atleast one data point is availbale: this is required because frames with zero texture consumption is not updated in model*/ |
| if(ps_rd_model->u1_num_frms_in_model > 0) |
| { |
| return 1; |
| } |
| else |
| { |
| return 0; |
| } |
| } |
| |
| #endif /* #if RC_FIXED_POINT */ |