/****************************************************************************** * * 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 init_qp.c * * \brief * This file contain qp initialization functions * * \date * * \author * ittiam * ****************************************************************************** */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* User include files */ #include "ittiam_datatypes.h" #include "rc_cntrl_param.h" #include "var_q_operator.h" #include "mem_req_and_acq.h" #include "rc_common.h" #include "init_qp.h" typedef struct init_qp_t { /* WORD32 ai4_bpp_for_qp[MAX_MPEG2_QP]; */ WORD32 i4_max_qp; WORD32 i4_num_pels_in_frame; WORD32 i4_is_hbr; } init_qp_t; #define BPP_Q_FACTOR (16) #define QP_FOR_ONE_BPP (3) /*(10)*/ #if NON_STEADSTATE_CODE WORD32 init_qp_num_fill_use_free_memtab( init_qp_handle *pps_init_qp, itt_memtab_t *ps_memtab, ITT_FUNC_TYPE_E e_func_type) { WORD32 i4_mem_tab_idx = 0; static init_qp_t s_init_qp; /* 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_init_qp) = &s_init_qp; /*for src rate control state structure*/ if(e_func_type != GET_NUM_MEMTAB) { fill_memtab( &ps_memtab[i4_mem_tab_idx], sizeof(init_qp_t), MEM_TAB_ALIGNMENT, PERSISTENT, DDR); use_or_fill_base(&ps_memtab[0], (void **)pps_init_qp, e_func_type); } i4_mem_tab_idx++; return (i4_mem_tab_idx); } /**************************************************************************** Function Name : init_init_qp Description : Inputs : ps_init_qp Revision History: DD MM YYYY Author(s) Changes (Describe the changes made) *****************************************************************************/ void init_init_qp( init_qp_handle ps_init_qp, WORD32 *pi4_min_max_qp, WORD32 i4_num_pels_in_frame, WORD32 i4_is_hbr) { WORD32 i4_max_qp; /* Finding the max qp among I P and B frame */ i4_max_qp = pi4_min_max_qp[1]; if(i4_max_qp < pi4_min_max_qp[3]) i4_max_qp = pi4_min_max_qp[3]; if(i4_max_qp < pi4_min_max_qp[5]) i4_max_qp = pi4_min_max_qp[5]; /*for(i=0;iai4_bpp_for_qp[i] = (QP_FOR_ONE_BPP*(1<i4_max_qp = i4_max_qp; ps_init_qp->i4_num_pels_in_frame = (!i4_num_pels_in_frame) ? 1 : i4_num_pels_in_frame; ps_init_qp->i4_is_hbr = i4_is_hbr; } #endif /* #if NON_STEADSTATE_CODE */ /* To ensure init_qp for high bit rates is low */ #define QP_FOR_ONE_BPP_HBR (5) /**************************************************************************** Function Name : get_init_qp_using_pels_bits_per_frame Description : Inputs : ps_init_qp Revision History: DD MM YYYY Author(s) Changes (Describe the changes made) *****************************************************************************/ /* If the remaining pels in frame is zero we would be using the init time pixels for calculating the bits per pixel */ WORD32 get_init_qp_using_pels_bits_per_frame( init_qp_handle ps_init_qp, picture_type_e e_pic_type, WORD32 i4_bits_remaining_in_frame, WORD32 i4_rem_pels_in_frame) { WORD32 i4_qp; WORD32 i4_qp_for_one_bpp; if(ps_init_qp->i4_is_hbr) { i4_qp_for_one_bpp = QP_FOR_ONE_BPP_HBR; } else { i4_qp_for_one_bpp = QP_FOR_ONE_BPP; } if(!i4_rem_pels_in_frame) i4_rem_pels_in_frame = ps_init_qp->i4_num_pels_in_frame; if(e_pic_type == P_PIC || e_pic_type == P1_PIC) i4_bits_remaining_in_frame = i4_bits_remaining_in_frame * I_TO_P_BIT_RATIO; if(e_pic_type >= B_PIC && e_pic_type != P1_PIC) i4_bits_remaining_in_frame = i4_bits_remaining_in_frame * (I_TO_P_BIT_RATIO * P_TO_B_BIT_RATIO); /* Assuming a 1 bpp => Qp = 12, So Qp = 1 => 12 bpp. [bpp halves with every doubling of Qp] */ /* x bpp = i4_bits_remaining_in_frame/i4_rem_pels_in_frame 1 bpp = QP_FOR_ONE_BPP QP_FOR_X_BPP = QP_FOR_ONE_BPP/(x) = QP_FOR_ONE_BPP*i4_rem_pels_in_frame/i4_bits_remaining_in_frame */ X_PROD_Y_DIV_Z(i4_qp_for_one_bpp, i4_rem_pels_in_frame, i4_bits_remaining_in_frame, i4_qp); /* Scaling the Qp values based on picture type */ if(e_pic_type == P_PIC || e_pic_type == P1_PIC) i4_qp = ((i4_qp * I_TO_P_RATIO) >> K_Q); if(e_pic_type >= B_PIC && e_pic_type != P1_PIC) { if(!ps_init_qp->i4_is_hbr) { i4_qp = ((i4_qp * P_TO_B_RATIO * I_TO_P_RATIO) >> (K_Q + K_Q)); } else { i4_qp = ((i4_qp * P_TO_B_RATIO_HBR * I_TO_P_RATIO) >> (K_Q + K_Q)); } } if(i4_qp > ps_init_qp->i4_max_qp) i4_qp = ps_init_qp->i4_max_qp; else if(i4_qp == 0) i4_qp = 1; return i4_qp; } #if NON_STEADSTATE_CODE /**************************************************************************** Function Name : change_init_qp_max_qp Description : Inputs : ps_init_qp Revision History: DD MM YYYY Author(s) Changes (Describe the changes made) *****************************************************************************/ void change_init_qp_max_qp(init_qp_handle ps_init_qp, WORD32 *pi4_min_max_qp) { WORD32 i4_max_qp; /* Finding the max qp among I P and B frame */ i4_max_qp = pi4_min_max_qp[1]; if(i4_max_qp < pi4_min_max_qp[3]) i4_max_qp = pi4_min_max_qp[3]; if(i4_max_qp < pi4_min_max_qp[5]) i4_max_qp = pi4_min_max_qp[5]; ps_init_qp->i4_max_qp = i4_max_qp; } #endif /* #if NON_STEADSTATE_CODE */