1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2016 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "rc"
7
8 #include <math.h>
9 #include <memory.h>
10
11 #include "mpp_env.h"
12 #include "mpp_mem.h"
13 #include "mpp_list.h"
14 #include "mpp_common.h"
15
16 #include "rc_debug.h"
17 #include "rc.h"
18 #include "rc_api.h"
19 #include "rc_base.h"
20
21 typedef struct MppRcImpl_t {
22 void *ctx;
23 const RcImplApi *api;
24 RcCfg cfg;
25
26 RcFpsCfg fps;
27 RK_S32 frm_cnt;
28
29 RK_U32 frm_send;
30 RK_U32 frm_done;
31 } MppRcImpl;
32
33 RK_U32 rc_debug = 0;
34
35 static const char default_rc_api[] = "default";
36
rc_init(RcCtx * ctx,MppCodingType type,const char ** request_name)37 MPP_RET rc_init(RcCtx *ctx, MppCodingType type, const char **request_name)
38 {
39 MPP_RET ret = MPP_NOK;
40 MppRcImpl *p = NULL;
41 RcImplApi *api = NULL;
42 const char *name = NULL;
43
44 mpp_env_get_u32("rc_debug", &rc_debug, 0);
45
46 if (NULL == request_name || NULL == *request_name)
47 name = default_rc_api;
48 else
49 name = *request_name;
50
51 rc_dbg_func("enter type %x name %s\n", type, name);
52
53 api = rc_api_get(type, name);
54
55 mpp_assert(api);
56
57 if (api) {
58 void *rc_ctx = mpp_calloc_size(void, api->ctx_size);
59
60 p = mpp_calloc(MppRcImpl, 1);
61 if (NULL == p || NULL == rc_ctx) {
62 mpp_err_f("failed to create context size %d\n", api->ctx_size);
63 MPP_FREE(p);
64 MPP_FREE(rc_ctx);
65 ret = MPP_ERR_MALLOC;
66 } else {
67 p->ctx = rc_ctx;
68 p->api = api;
69 p->frm_cnt = -1;
70 if (request_name && *request_name)
71 mpp_log("using rc impl %s\n", api->name);
72 ret = MPP_OK;
73 }
74 }
75
76 *ctx = p;
77 if (request_name)
78 *request_name = name;
79
80 rc_dbg_func("leave %p\n", p);
81
82 return ret;
83 }
84
rc_deinit(RcCtx ctx)85 MPP_RET rc_deinit(RcCtx ctx)
86 {
87 MppRcImpl *p = (MppRcImpl *)ctx;
88 const RcImplApi *api = p->api;
89 MPP_RET ret = MPP_OK;
90
91 rc_dbg_func("enter %p\n", ctx);
92
93 if (api && api->deinit && p->ctx) {
94 ret = api->deinit(p->ctx);
95 MPP_FREE(p->ctx);
96 }
97
98 MPP_FREE(p);
99
100 rc_dbg_func("leave %p\n", ctx);
101
102 return ret;
103 }
104
rc_update_usr_cfg(RcCtx ctx,RcCfg * cfg)105 MPP_RET rc_update_usr_cfg(RcCtx ctx, RcCfg *cfg)
106 {
107 MppRcImpl *p = (MppRcImpl *)ctx;
108 const RcImplApi *api = p->api;
109 MPP_RET ret = MPP_OK;
110
111 rc_dbg_func("enter %p\n", ctx);
112
113 p->cfg = *cfg;
114 p->fps = cfg->fps;
115
116 if (api && api->init && p->ctx)
117 api->init(p->ctx, &p->cfg);
118
119 rc_dbg_func("leave %p\n", ctx);
120
121 return ret;
122 }
123
rc_frm_check_drop(RcCtx ctx,EncRcTask * task)124 MPP_RET rc_frm_check_drop(RcCtx ctx, EncRcTask *task)
125 {
126 MppRcImpl *p = (MppRcImpl *)ctx;
127 const RcImplApi *api = p->api;
128 MPP_RET ret = MPP_OK;
129
130 rc_dbg_func("enter %p\n", ctx);
131
132 if (api && api->check_drop && p->ctx && task) {
133 ret = api->check_drop(p->ctx, task);
134 return ret;
135 } else {
136 RcFpsCfg *cfg = &p->fps;
137 RK_S32 frm_cnt = p->frm_cnt;
138 RK_S32 rate_in = cfg->fps_in_num * cfg->fps_out_denom;
139 RK_S32 rate_out = cfg->fps_out_num * cfg->fps_in_denom;
140 RK_S32 drop = 0;
141
142 mpp_assert(cfg->fps_in_denom >= 1);
143 mpp_assert(cfg->fps_out_denom >= 1);
144 mpp_assert(rate_in >= rate_out);
145
146 // frame counter is inited to (rate_in - rate_out) to encode first frame
147 if (frm_cnt < 0)
148 frm_cnt = rate_in - rate_out;
149
150 frm_cnt += rate_out;
151
152 if (frm_cnt < rate_in)
153 drop = 1;
154 else
155 frm_cnt -= rate_in;
156
157 p->frm_cnt = frm_cnt;
158 task->frm.drop = drop;
159 }
160
161 rc_dbg_func("leave %p drop %d\n", ctx, task->frm.drop);
162
163 return ret;
164 }
165
166 #define MPP_ENC_RC_FUNC(flow, func) \
167 MPP_RET rc_##flow##_##func(RcCtx ctx, EncRcTask *task) \
168 { \
169 MppRcImpl *p = (MppRcImpl *)ctx; \
170 const RcImplApi *api = p->api; \
171 if (!api || !api->flow##_##func || !p->ctx || !task) \
172 return MPP_OK; \
173 return api->flow##_##func(p->ctx, task); \
174 }
175
176 MPP_ENC_RC_FUNC(check, reenc)
177 MPP_ENC_RC_FUNC(frm, start)
178 MPP_ENC_RC_FUNC(frm, end)
179 MPP_ENC_RC_FUNC(hal, start)
180 MPP_ENC_RC_FUNC(hal, end)
181