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_api"
7
8 #include <string.h>
9
10 #include "mpp_env.h"
11 #include "mpp_mem.h"
12 #include "mpp_list.h"
13 #include "mpp_2str.h"
14 #include "mpp_common.h"
15 #include "mpp_singleton.h"
16
17 #include "rc_debug.h"
18 #include "rc_api.h"
19
20 #include "h264e_rc.h"
21 #include "h265e_rc.h"
22 #include "jpege_rc.h"
23 #include "vp8e_rc.h"
24 #include "rc_model_v2_smt.h"
25
26 #define get_srv_rc_api_srv(caller) \
27 ({ \
28 MppRcApiSrv *__tmp; \
29 if (!rc_api_srv) { \
30 rc_api_srv_init(); \
31 } \
32 if (rc_api_srv) { \
33 __tmp = rc_api_srv; \
34 } else { \
35 mpp_err("mpp rc api srv not init at %s : %s\n", __FUNCTION__, caller); \
36 __tmp = NULL; \
37 } \
38 __tmp; \
39 })
40
41 // use class to register RcImplApi
42 typedef struct RcImplApiNode_t {
43 /* list to list in MppRcApiSrv */
44 struct list_head list;
45 char name[64];
46 MppCodingType type;
47 RcApiBrief brief;
48 RcImplApi api;
49 } RcImplApiNode;
50
51 typedef struct MppRcApiSrv_t {
52 MppMutex lock;
53 RK_U32 api_cnt;
54 /* list for list in RcImplApiNode */
55 struct list_head list;
56 } MppRcApiSrv;
57
58 static MppRcApiSrv *rc_api_srv = NULL;
59
rc_api_srv_init()60 static void rc_api_srv_init()
61 {
62 MppRcApiSrv *srv = rc_api_srv;
63
64 mpp_env_get_u32("rc_debug", &rc_debug, 0);
65
66 if (srv)
67 return;
68
69 srv = mpp_malloc(MppRcApiSrv, 1);
70 if (!srv) {
71 mpp_err_f("failed to create rc api srv\n");
72 return;
73 }
74
75 rc_api_srv = srv;
76
77 mpp_mutex_init(&srv->lock);
78 INIT_LIST_HEAD(&srv->list);
79 srv->api_cnt = 0;
80
81 /* add all default rc apis */
82 rc_api_add(&default_h264e);
83 rc_api_add(&default_h265e);
84 rc_api_add(&default_jpege);
85 rc_api_add(&default_vp8e);
86 rc_api_add(&smt_h264e);
87 rc_api_add(&smt_h265e);
88 }
89
rc_api_srv_deinit()90 static void rc_api_srv_deinit()
91 {
92 MppRcApiSrv *srv = rc_api_srv;
93
94 if (!srv)
95 return;
96
97 mpp_mutex_lock(&srv->lock);
98
99 if (srv->api_cnt) {
100 RcImplApiNode *pos, *n;
101
102 list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) {
103 rc_dbg_impl("%-5s rc api %s is removed\n",
104 strof_coding_type(pos->type), pos->name);
105
106 list_del_init(&pos->list);
107 MPP_FREE(pos);
108 srv->api_cnt--;
109 }
110
111 mpp_assert(srv->api_cnt == 0);
112 }
113
114 mpp_mutex_unlock(&srv->lock);
115 mpp_mutex_destroy(&srv->lock);
116 MPP_FREE(srv);
117 rc_api_srv = NULL;
118 }
119
_rc_api_get(MppRcApiSrv * srv,MppCodingType type,const char * name)120 static RcImplApi *_rc_api_get(MppRcApiSrv *srv, MppCodingType type, const char *name)
121 {
122 if (!srv->api_cnt)
123 return NULL;
124
125 if (name) {
126 RcImplApiNode *pos, *n;
127
128 list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) {
129 if (type == pos->type &&
130 !strncmp(name, pos->name, sizeof(pos->name) - 1)) {
131 rc_dbg_impl("%-5s rc api %s is selected\n",
132 strof_coding_type(type), pos->name);
133 return &pos->api;
134 }
135 }
136 }
137
138 rc_dbg_impl("%-5s rc api %s can not be found\n", strof_coding_type(type), name);
139
140 return NULL;
141 }
142
set_node_api(RcImplApiNode * node,const RcImplApi * api)143 static void set_node_api(RcImplApiNode *node, const RcImplApi *api)
144 {
145 node->api = *api;
146 node->type = api->type;
147
148 strncpy(node->name, api->name, sizeof(node->name) - 1);
149 node->api.name = api->name;
150
151 node->brief.type = api->type;
152 node->brief.name = api->name;
153 }
154
rc_api_add(const RcImplApi * api)155 MPP_RET rc_api_add(const RcImplApi *api)
156 {
157 MppRcApiSrv *srv = get_srv_rc_api_srv(__FUNCTION__);
158 RcImplApiNode *node = NULL;
159 RcImplApi *node_api = NULL;
160
161 if (!api) {
162 mpp_err_f("unable to register NULL api\n");
163 return MPP_NOK;
164 }
165
166 if (!srv)
167 return MPP_NOK;
168
169 mpp_mutex_lock(&srv->lock);
170
171 /* search for same node for replacement */
172 node_api = _rc_api_get(srv, api->type, api->name);
173
174 if (!node_api) {
175 node = mpp_malloc(RcImplApiNode, 1);
176 if (!node) {
177 mpp_err_f("failed to create api node\n");
178 mpp_mutex_unlock(&srv->lock);
179 return MPP_NOK;
180 }
181
182 INIT_LIST_HEAD(&node->list);
183 list_add_tail(&node->list, &srv->list);
184
185 srv->api_cnt++;
186 rc_dbg_impl("%-5s rc api %s is added\n", strof_coding_type(api->type), api->name);
187 } else {
188 node = container_of(node_api, RcImplApiNode, api);
189 rc_dbg_impl("%-5s rc api %s is updated\n", strof_coding_type(api->type), api->name);
190 }
191
192 set_node_api(node, api);
193 mpp_mutex_unlock(&srv->lock);
194
195 return MPP_OK;
196 }
197
rc_api_get(MppCodingType type,const char * name)198 RcImplApi *rc_api_get(MppCodingType type, const char *name)
199 {
200 MppRcApiSrv *srv = get_srv_rc_api_srv(__FUNCTION__);
201
202 if (!srv)
203 return NULL;
204
205 return _rc_api_get(srv, type, name);
206 }
207
rc_api_get_all(MppRcApiSrv * srv,RcApiBrief * brief,RK_S32 * count,RK_S32 max_count)208 MPP_RET rc_api_get_all(MppRcApiSrv *srv, RcApiBrief *brief, RK_S32 *count, RK_S32 max_count)
209 {
210 RcImplApiNode *pos, *n;
211 RK_S32 cnt = 0;
212
213 mpp_mutex_lock(&srv->lock);
214
215 list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) {
216 if (cnt >= max_count)
217 break;
218
219 brief[cnt++] = pos->brief;
220 }
221
222 *count = cnt;
223 mpp_mutex_unlock(&srv->lock);
224
225 return MPP_OK;
226 }
227
rc_api_get_by_type(MppRcApiSrv * srv,RcApiBrief * brief,RK_S32 * count,RK_S32 max_count,MppCodingType type)228 MPP_RET rc_api_get_by_type(MppRcApiSrv *srv, RcApiBrief *brief, RK_S32 *count,
229 RK_S32 max_count, MppCodingType type)
230 {
231 RcImplApiNode *pos, *n;
232 RK_S32 cnt = 0;
233
234 mpp_mutex_lock(&srv->lock);
235
236 list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) {
237 if (cnt >= max_count)
238 break;
239
240 if (pos->type != type)
241 continue;
242
243 brief[cnt++] = pos->brief;
244 }
245
246 *count = cnt;
247 mpp_mutex_unlock(&srv->lock);
248
249 return MPP_OK;
250 }
251
rc_brief_get_all(RcApiQueryAll * query)252 MPP_RET rc_brief_get_all(RcApiQueryAll *query)
253 {
254 MppRcApiSrv *srv = rc_api_srv;
255 RcApiBrief *brief;
256 RK_S32 *count;
257 RK_S32 max_count;
258
259 if (!srv)
260 return MPP_NOK;
261
262 if (!query) {
263 mpp_err_f("invalide NULL query input\n");
264 return MPP_ERR_NULL_PTR;
265 }
266
267 brief = query->brief;
268 count = &query->count;
269 max_count = query->max_count;
270
271 if (!brief || max_count <= 0) {
272 mpp_err_f("invalide brief buffer %p max count %d\n", brief, max_count);
273 return MPP_NOK;
274 }
275
276 return rc_api_get_all(srv, brief, count, max_count);
277 }
278
rc_brief_get_by_type(RcApiQueryType * query)279 MPP_RET rc_brief_get_by_type(RcApiQueryType *query)
280 {
281 MppRcApiSrv *srv = rc_api_srv;
282 RcApiBrief *brief;
283 RK_S32 *count;
284 RK_S32 max_count;
285 MppCodingType type;
286
287 if (!srv)
288 return MPP_NOK;
289
290 if (!query) {
291 mpp_err_f("invalide NULL query input\n");
292 return MPP_ERR_NULL_PTR;
293 }
294
295 brief = query->brief;
296 count = &query->count;
297 max_count = query->max_count;
298 type = query->type;
299
300 if (!brief || max_count <= 0) {
301 mpp_err_f("invalide brief buffer %p max count %d type %x\n",
302 brief, max_count, type);
303 return MPP_NOK;
304 }
305
306 return rc_api_get_by_type(srv, brief, count, max_count, type);
307 }
308
309 MPP_SINGLETON(MPP_SGLN_ENC_RC_API, rc_api, rc_api_srv_init, rc_api_srv_deinit)
310