/******************************************************************************
*
* 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;i<i4_max_qp;i++)
{
ps_init_qp->ai4_bpp_for_qp[i] = (QP_FOR_ONE_BPP*(1<<BPP_Q_FACTOR))/(i+1);
}*/
ps_init_qp->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 */