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