xref: /OK3568_Linux_fs/external/mpp/mpp/codec/mpp_rc.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2016 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "mpp_rc"
18 
19 #include <math.h>
20 #include <memory.h>
21 
22 #include "mpp_env.h"
23 #include "mpp_mem.h"
24 #include "mpp_common.h"
25 #include "mpp_rc.h"
26 
27 #define MPP_RC_DBG_FUNCTION          (0x00000001)
28 #define MPP_RC_DBG_BPS               (0x00000010)
29 #define MPP_RC_DBG_RC                (0x00000020)
30 #define MPP_RC_DBG_CFG               (0x00000100)
31 #define MPP_RC_DBG_RECORD            (0x00001000)
32 #define MPP_RC_DBG_VBV               (0x00002000)
33 
34 
35 #define mpp_rc_dbg(flag, fmt, ...)   _mpp_dbg(mpp_rc_debug, flag, fmt, ## __VA_ARGS__)
36 #define mpp_rc_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_rc_debug, flag, fmt, ## __VA_ARGS__)
37 
38 #define mpp_rc_dbg_func(fmt, ...)    mpp_rc_dbg_f(MPP_RC_DBG_FUNCTION, fmt, ## __VA_ARGS__)
39 #define mpp_rc_dbg_bps(fmt, ...)     mpp_rc_dbg(MPP_RC_DBG_BPS, fmt, ## __VA_ARGS__)
40 #define mpp_rc_dbg_rc(fmt, ...)      mpp_rc_dbg(MPP_RC_DBG_RC, fmt, ## __VA_ARGS__)
41 #define mpp_rc_dbg_cfg(fmt, ...)     mpp_rc_dbg(MPP_RC_DBG_CFG, fmt, ## __VA_ARGS__)
42 #define mpp_rc_dbg_vbv(fmt, ...)     mpp_rc_dbg(MPP_RC_DBG_VBV, fmt, ## __VA_ARGS__)
43 
44 
45 #define SIGN(a)         ((a) < (0) ? (-1) : (1))
46 #define DIV(a, b)       (((a) + (SIGN(a) * (b)) / 2) / (b))
47 
48 static RK_U32 mpp_rc_debug = 0;
49 
mpp_data_init(MppData ** data,RK_S32 size)50 MPP_RET mpp_data_init(MppData **data, RK_S32 size)
51 {
52     if (NULL == data || size <= 0) {
53         mpp_err_f("invalid data %p size %d\n", data, size);
54         return MPP_ERR_NULL_PTR;
55     }
56 
57     *data = NULL;
58     MppData *p = mpp_malloc_size(MppData, sizeof(MppData) + sizeof(RK_S32) * size);
59     if (NULL == p) {
60         mpp_err_f("malloc size %d failed\n", size);
61         return MPP_ERR_MALLOC;
62     }
63     p->size = size;
64     p->len = 0;
65     p->pos = 0;
66     p->val = (RK_S32 *)(p + 1);
67     *data = p;
68 
69     return MPP_OK;
70 }
71 
mpp_data_deinit(MppData * p)72 void mpp_data_deinit(MppData *p)
73 {
74     if (p)
75         mpp_free(p);
76 }
77 
mpp_data_update(MppData * p,RK_S32 val)78 void mpp_data_update(MppData *p, RK_S32 val)
79 {
80     mpp_assert(p);
81 
82     p->val[p->pos] = val;
83 
84     if (++p->pos >= p->size)
85         p->pos = 0;
86 
87     if (p->len < p->size)
88         p->len++;
89 }
90 
mpp_data_avg(MppData * p,RK_S32 len,RK_S32 num,RK_S32 denorm)91 RK_S32 mpp_data_avg(MppData *p, RK_S32 len, RK_S32 num, RK_S32 denorm)
92 {
93     mpp_assert(p);
94 
95     RK_S32 i;
96     RK_S32 sum = 0;
97     RK_S32 pos = p->pos;
98 
99     if (!p->len)
100         return 0;
101 
102     if (len < 0 || len > p->len)
103         len = p->len;
104 
105     if (num == denorm) {
106         i = len;
107         while (i--) {
108             if (pos)
109                 pos--;
110             else
111                 pos = p->len - 1;
112 
113             sum += p->val[pos];
114         }
115     } else {
116         /* This case is not used so far, but may be useful in the future */
117         mpp_assert(num > denorm);
118         RK_S32 acc_num = num;
119         RK_S32 acc_denorm = denorm;
120 
121         i = len - 1;
122         sum = p->val[--pos];
123         while (i--) {
124             if (pos)
125                 pos--;
126             else
127                 pos = p->len - 1;
128 
129             sum += p->val[pos] * acc_num / acc_denorm;
130             acc_num *= num;
131             acc_denorm *= denorm;
132         }
133     }
134     return DIV(sum, len);
135 }
136 
mpp_pid_reset(MppPIDCtx * p)137 void mpp_pid_reset(MppPIDCtx *p)
138 {
139     p->p = 0;
140     p->i = 0;
141     p->d = 0;
142     p->count = 0;
143 }
144 
mpp_pid_set_param(MppPIDCtx * ctx,RK_S32 coef_p,RK_S32 coef_i,RK_S32 coef_d,RK_S32 div,RK_S32 len)145 void mpp_pid_set_param(MppPIDCtx *ctx, RK_S32 coef_p, RK_S32 coef_i, RK_S32 coef_d, RK_S32 div, RK_S32 len)
146 {
147     ctx->coef_p = coef_p;
148     ctx->coef_i = coef_i;
149     ctx->coef_d = coef_d;
150     ctx->div = div;
151     ctx->len = len;
152     ctx->count = 0;
153 
154     mpp_rc_dbg_rc("RC: pid ctx %p coef: P %d I %d D %d div %d len %d\n",
155                   ctx, coef_p, coef_i, coef_d, div, len);
156 }
157 
mpp_pid_update(MppPIDCtx * ctx,RK_S32 val)158 void mpp_pid_update(MppPIDCtx *ctx, RK_S32 val)
159 {
160     mpp_rc_dbg_rc("RC: pid ctx %p update val %d\n", ctx, val);
161     mpp_rc_dbg_rc("RC: pid ctx %p before update P %d I %d D %d\n", ctx, ctx->p, ctx->i, ctx->d);
162 
163     ctx->d = val - ctx->p;      /* Derivative */
164     ctx->i = val + ctx->i;      /* Integral */
165     ctx->p = val;               /* Proportional */
166 
167     mpp_rc_dbg_rc("RC: pid ctx %p after  update P %d I %d D %d\n", ctx, ctx->p, ctx->i, ctx->d);
168     ctx->count++;
169     /*
170      * pid control is a short time control, it needs periodically reset
171      */
172     if (ctx->count >= ctx->len)
173         mpp_pid_reset(ctx);
174 }
175 
mpp_pid_calc(MppPIDCtx * p)176 RK_S32 mpp_pid_calc(MppPIDCtx *p)
177 {
178     RK_S32 a = p->p * p->coef_p + p->i * p->coef_i + p->d * p->coef_d;
179     RK_S32 b = p->div;
180 
181     mpp_rc_dbg_rc("RC: pid ctx %p p %10d coef %d\n", p, p->p, p->coef_p);
182     mpp_rc_dbg_rc("RC: pid ctx %p i %10d coef %d\n", p, p->i, p->coef_i);
183     mpp_rc_dbg_rc("RC: pid ctx %p d %10d coef %d\n", p, p->d, p->coef_d);
184     mpp_rc_dbg_rc("RC: pid ctx %p a %10d b %d\n", p, a, b);
185 
186     return DIV(a, b);
187 }
188 
mpp_rc_param_ops(struct list_head * head,RK_U32 frm_cnt,RC_PARAM_OPS ops,void * arg)189 MPP_RET mpp_rc_param_ops(struct list_head *head, RK_U32 frm_cnt,
190                          RC_PARAM_OPS ops, void *arg)
191 {
192     MPP_RET ret = MPP_OK;
193 
194     if (mpp_rc_debug & MPP_RC_DBG_RECORD) {
195         RecordNode *pos, *n;
196         RK_U32 found_match = 0;
197 
198         list_for_each_entry_safe(pos, n, head, RecordNode, list) {
199             if (frm_cnt == pos->frm_cnt) {
200                 found_match = 1;
201                 break;
202             }
203         }
204 
205         if (!found_match) {
206             mpp_err("frame %d is not found in list_head %p!\n", frm_cnt, head);
207             ret = MPP_NOK;
208         } else {
209             switch (ops) {
210             case RC_RECORD_REAL_BITS : {
211                 pos->real_bits = *((RK_U32*)arg);
212             } break;
213             case RC_RECORD_QP_SUM : {
214                 pos->qp_sum = *((RK_S32*)arg);
215             } break;
216             case RC_RECORD_QP_MIN : {
217                 pos->qp_min = *((RK_S32*)arg);
218             } break;
219             case RC_RECORD_QP_MAX : {
220                 pos->qp_max = *((RK_S32*)arg);
221             } break;
222             case RC_RECORD_WIN_LEN : {
223                 pos->wlen = *((RK_S32*)arg);
224             } break;
225             case RC_RECORD_SET_QP : {
226                 pos->set_qp = *((RK_S32*)arg);
227             } break;
228             case RC_RECORD_REAL_QP : {
229                 pos->real_qp = *((RK_S32*)arg);
230             } break;
231             case RC_RECORD_SSE_SUM : {
232                 pos->sse_sum = *((RK_S64*)arg);
233             } break;
234             default : {
235                 mpp_err("frame %d found invalid operation code %d\n", frm_cnt, ops);
236                 ret = MPP_NOK;
237             }
238             }
239         }
240     }
241 
242     return ret;
243 }
244 
245 
246