xref: /OK3568_Linux_fs/external/mpp/mpp/codec/rc/rc_impl.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2016 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "rc_impl"
18 
19 #include <string.h>
20 
21 #include "mpp_env.h"
22 #include "mpp_mem.h"
23 #include "mpp_common.h"
24 
25 #include "rc_debug.h"
26 #include "rc_impl.h"
27 
28 #include "h264e_rc.h"
29 #include "h265e_rc.h"
30 #include "jpege_rc.h"
31 #include "vp8e_rc.h"
32 #include "rc_model_v2_smt.h"
33 
34 const RcImplApi *rc_apis[] = {
35     &default_h264e,
36     &default_h265e,
37     &default_jpege,
38     &default_vp8e,
39     &smt_h264e,
40     &smt_h265e,
41 };
42 
43 // use class to register RcImplApi
44 typedef struct RcImplApiNode_t {
45     struct list_head    list;
46     char                name[32];
47     MppCodingType       type;
48     RcApiBrief          brief;
49     RcImplApi           api;
50 } RcImplApiNode;
51 
set_node_api(RcImplApiNode * node,const RcImplApi * api)52 static void set_node_api(RcImplApiNode *node, const RcImplApi *api)
53 {
54     node->api = *api;
55     node->type = api->type;
56 
57     strncpy(node->name, api->name, sizeof(node->name) - 1);
58     node->api.name = api->name;
59 
60     node->brief.type = api->type;
61     node->brief.name = api->name;
62 }
63 
RcImplApiService()64 RcImplApiService::RcImplApiService()
65 {
66     RK_U32 i;
67 
68     mpp_env_get_u32("rc_debug", &rc_debug, 0);
69 
70     INIT_LIST_HEAD(&mApis);
71     mApiCount = 0;
72 
73     for (i = 0; i < MPP_ARRAY_ELEMS(rc_apis); i++)
74         api_add(rc_apis[i]);
75 }
76 
~RcImplApiService()77 RcImplApiService::~RcImplApiService()
78 {
79     AutoMutex auto_lock(get_lock());
80     RcImplApiNode *pos, *n;
81 
82     list_for_each_entry_safe(pos, n, &mApis, RcImplApiNode, list) {
83         MPP_FREE(pos);
84         mApiCount--;
85     }
86 
87     mpp_assert(mApiCount == 0);
88 }
89 
api_add(const RcImplApi * api)90 MPP_RET RcImplApiService::api_add(const RcImplApi *api)
91 {
92     AutoMutex auto_lock(get_lock());
93 
94     if (NULL == api) {
95         mpp_err_f("unable to register NULL api\n");
96         return MPP_NOK;
97     }
98 
99     /* search for same node for replacement */
100     RcImplApiNode *node = NULL;
101     RcImplApi *node_api = api_get(api->type, api->name);
102 
103     if (NULL == node_api) {
104         node = mpp_malloc(RcImplApiNode, 1);
105         if (NULL == node) {
106             mpp_err_f("failed to create api node\n");
107             return MPP_NOK;
108         }
109 
110         INIT_LIST_HEAD(&node->list);
111         list_add_tail(&node->list, &mApis);
112 
113         mApiCount++;
114         rc_dbg_impl("rc impl %s type %x is added\n", api->name, api->type);
115     } else {
116         node = container_of(node_api, RcImplApiNode, api);
117         rc_dbg_impl("rc impl %s type %x is updated\n", api->name, api->type);
118     }
119 
120     set_node_api(node, api);
121 
122     return MPP_OK;
123 }
124 
api_get(MppCodingType type,const char * name)125 RcImplApi *RcImplApiService::api_get(MppCodingType type, const char *name)
126 {
127     AutoMutex auto_lock(get_lock());
128 
129     if (!mApiCount)
130         return NULL;
131 
132     if (name) {
133         RcImplApiNode *pos, *n;
134 
135         list_for_each_entry_safe(pos, n, &mApis, RcImplApiNode, list) {
136             if (type == pos->type &&
137                 !strncmp(name, pos->name, sizeof(pos->name) - 1)) {
138                 rc_dbg_impl("rc impl %s is selected\n", pos->name);
139                 return &pos->api;
140             }
141         }
142     }
143 
144     rc_dbg_impl("failed to find rc impl %s type %x\n", name, type);
145 
146     return NULL;
147 }
148 
api_get_all(RcApiBrief * brief,RK_S32 * count,RK_S32 max_count)149 MPP_RET RcImplApiService::api_get_all(RcApiBrief *brief, RK_S32 *count, RK_S32 max_count)
150 {
151     RK_S32 cnt = 0;
152     RcImplApiNode *pos, *n;
153 
154     AutoMutex auto_lock(get_lock());
155 
156     list_for_each_entry_safe(pos, n, &mApis, RcImplApiNode, list) {
157         if (cnt >= max_count)
158             break;
159 
160         brief[cnt++] = pos->brief;
161     }
162 
163     *count = cnt;
164 
165     return MPP_OK;
166 }
167 
api_get_by_type(RcApiBrief * brief,RK_S32 * count,RK_S32 max_count,MppCodingType type)168 MPP_RET RcImplApiService::api_get_by_type(RcApiBrief *brief, RK_S32 *count,
169                                           RK_S32 max_count, MppCodingType type)
170 {
171     RK_S32 cnt = 0;
172     RcImplApiNode *pos, *n;
173 
174     AutoMutex auto_lock(get_lock());
175 
176     list_for_each_entry_safe(pos, n, &mApis, RcImplApiNode, list) {
177         if (cnt >= max_count)
178             break;
179 
180         if (pos->type != type)
181             continue;
182 
183         brief[cnt++] = pos->brief;
184     }
185 
186     *count = cnt;
187 
188     return MPP_OK;
189 }
190 
rc_api_add(const RcImplApi * api)191 MPP_RET rc_api_add(const RcImplApi *api)
192 {
193     return RcImplApiService::get_instance()->api_add(api);
194 }
195 
rc_brief_get_all(RcApiQueryAll * query)196 MPP_RET rc_brief_get_all(RcApiQueryAll *query)
197 {
198     if (NULL == query) {
199         mpp_err_f("invalide NULL query input\n");
200         return MPP_ERR_NULL_PTR;
201     }
202 
203     RcApiBrief *brief = query->brief;
204     RK_S32 *count = &query->count;
205     RK_S32 max_count = query->max_count;
206 
207     if (NULL == brief || max_count <= 0) {
208         mpp_err_f("invalide brief buffer %p max count %d\n", brief, max_count);
209         return MPP_NOK;
210     }
211 
212     return RcImplApiService::get_instance()->api_get_all(brief, count, max_count);
213 }
214 
rc_brief_get_by_type(RcApiQueryType * query)215 MPP_RET rc_brief_get_by_type(RcApiQueryType *query)
216 {
217     if (NULL == query) {
218         mpp_err_f("invalide NULL query input\n");
219         return MPP_ERR_NULL_PTR;
220     }
221 
222     RcApiBrief *brief = query->brief;
223     RK_S32 *count = &query->count;
224     RK_S32 max_count = query->max_count;
225     MppCodingType type = query->type;
226 
227     if (NULL == brief || max_count <= 0) {
228         mpp_err_f("invalide brief buffer %p max count %d type %x\n",
229                   brief, max_count, type);
230         return MPP_NOK;
231     }
232 
233     return RcImplApiService::get_instance()->api_get_by_type(brief, count, max_count, type);
234 }
235