xref: /rockchip-linux_mpp/mpp/codec/rc/rc_api.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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