aboutsummaryrefslogtreecommitdiff
path: root/encoder/init_qp.c
blob: 993f074200ccb8d1be932361b4df9edc9543f100 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/******************************************************************************
 *
 * 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 */