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