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