1 /*
2 * Copyright 2020 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 "mpp_dec_cfg"
18
19 #include "rk_vdec_cfg.h"
20 #include <string.h>
21
22 #include "mpp_env.h"
23 #include "mpp_mem.h"
24 #include "mpp_time.h"
25 #include "mpp_debug.h"
26 #include "mpp_common.h"
27 #include "mpp_thread.h"
28
29 #include "mpp_cfg.h"
30 #include "mpp_dec_cfg_impl.h"
31
32 #define MPP_DEC_CFG_DBG_FUNC (0x00000001)
33 #define MPP_DEC_CFG_DBG_INFO (0x00000002)
34 #define MPP_DEC_CFG_DBG_SET (0x00000004)
35 #define MPP_DEC_CFG_DBG_GET (0x00000008)
36
37 #define mpp_dec_cfg_dbg(flag, fmt, ...) _mpp_dbg_f(mpp_dec_cfg_debug, flag, fmt, ## __VA_ARGS__)
38
39 #define mpp_dec_cfg_dbg_func(fmt, ...) mpp_dec_cfg_dbg(MPP_DEC_CFG_DBG_FUNC, fmt, ## __VA_ARGS__)
40 #define mpp_dec_cfg_dbg_info(fmt, ...) mpp_dec_cfg_dbg(MPP_DEC_CFG_DBG_INFO, fmt, ## __VA_ARGS__)
41 #define mpp_dec_cfg_dbg_set(fmt, ...) mpp_dec_cfg_dbg(MPP_DEC_CFG_DBG_SET, fmt, ## __VA_ARGS__)
42 #define mpp_dec_cfg_dbg_get(fmt, ...) mpp_dec_cfg_dbg(MPP_DEC_CFG_DBG_GET, fmt, ## __VA_ARGS__)
43
44 RK_U32 mpp_dec_cfg_debug = 0;
45
46 typedef struct MppDecCfgInfo_t {
47 MppCfgInfoHead head;
48 MppTrieNode trie_node[];
49 /* MppCfgInfoNode is following trie_node */
50 } MppDecCfgInfo;
51
mpp_dec_cfg_find(MppDecCfgInfo * info,const char * name)52 static MppCfgInfoNode *mpp_dec_cfg_find(MppDecCfgInfo *info, const char *name)
53 {
54 MppTrieNode *node;
55
56 if (NULL == info || NULL == name)
57 return NULL;
58
59 node = mpp_trie_get_node(info->trie_node, name);
60 if (NULL == node)
61 return NULL;
62
63 return (MppCfgInfoNode *)(((char *)info->trie_node) + node->id);
64 }
65
66 class MppDecCfgService
67 {
68 private:
69 MppDecCfgService();
70 ~MppDecCfgService();
71 MppDecCfgService(const MppDecCfgService &);
72 MppDecCfgService &operator=(const MppDecCfgService &);
73
74 MppDecCfgInfo *mInfo;
75 RK_S32 mCfgSize;
76
77 public:
get()78 static MppDecCfgService *get() {
79 static Mutex lock;
80 static MppDecCfgService instance;
81
82 AutoMutex auto_lock(&lock);
83 return &instance;
84 }
85
get_info(const char * name)86 MppCfgInfoNode *get_info(const char *name) { return mpp_dec_cfg_find(mInfo, name); };
87 MppCfgInfoNode *get_info_root();
88
get_node_count()89 RK_S32 get_node_count() { return mInfo ? mInfo->head.node_count : 0; };
get_info_count()90 RK_S32 get_info_count() { return mInfo ? mInfo->head.info_count : 0; };
get_info_size()91 RK_S32 get_info_size() { return mInfo ? mInfo->head.info_size : 0; };
get_cfg_size()92 RK_S32 get_cfg_size() { return mCfgSize; };
93 };
94
95 #define EXPAND_AS_API(base, name, cfg_type, in_type, flag, field_change, field_data) \
96 MppCfgApi api_##base##_##name = \
97 { \
98 #base":"#name, \
99 CFG_FUNC_TYPE_##cfg_type, \
100 (RK_U32)((long)&(((MppDecCfgSet *)0)->field_change.change)), \
101 flag, \
102 (RK_U32)((long)&(((MppDecCfgSet *)0)->field_change.field_data)), \
103 sizeof((((MppDecCfgSet *)0)->field_change.field_data)), \
104 };
105
106 #define EXPAND_AS_ARRAY(base, name, cfg_type, in_type, flag, field_change, field_data) \
107 &api_##base##_##name,
108
109 #define ENTRY_TABLE(ENTRY) \
110 /* rc config */ \
111 ENTRY(base, type, U32, MppCtxType, MPP_DEC_CFG_CHANGE_TYPE, base, type) \
112 ENTRY(base, coding, U32, MppCodingType, MPP_DEC_CFG_CHANGE_CODING, base, coding) \
113 ENTRY(base, hw_type, U32, MppCodingType, MPP_DEC_CFG_CHANGE_HW_TYPE, base, hw_type) \
114 ENTRY(base, batch_mode, U32, RK_U32, MPP_DEC_CFG_CHANGE_BATCH_MODE, base, batch_mode) \
115 ENTRY(base, out_fmt, U32, MppFrameFormat, MPP_DEC_CFG_CHANGE_OUTPUT_FORMAT, base, out_fmt) \
116 ENTRY(base, fast_out, U32, RK_U32, MPP_DEC_CFG_CHANGE_FAST_OUT, base, fast_out) \
117 ENTRY(base, fast_parse, U32, RK_U32, MPP_DEC_CFG_CHANGE_FAST_PARSE, base, fast_parse) \
118 ENTRY(base, split_parse, U32, RK_U32, MPP_DEC_CFG_CHANGE_SPLIT_PARSE, base, split_parse) \
119 ENTRY(base, internal_pts, U32, RK_U32, MPP_DEC_CFG_CHANGE_INTERNAL_PTS, base, internal_pts) \
120 ENTRY(base, sort_pts, U32, RK_U32, MPP_DEC_CFG_CHANGE_SORT_PTS, base, sort_pts) \
121 ENTRY(base, disable_error, U32, RK_U32, MPP_DEC_CFG_CHANGE_DISABLE_ERROR, base, disable_error) \
122 ENTRY(base, enable_vproc, U32, RK_U32, MPP_DEC_CFG_CHANGE_ENABLE_VPROC, base, enable_vproc) \
123 ENTRY(base, enable_fast_play, U32, RK_U32, MPP_DEC_CFG_CHANGE_ENABLE_FAST_PLAY, base, enable_fast_play) \
124 ENTRY(base, enable_hdr_meta, U32, RK_U32, MPP_DEC_CFG_CHANGE_ENABLE_HDR_META, base, enable_hdr_meta) \
125 ENTRY(base, enable_thumbnail, U32, RK_U32, MPP_DEC_CFG_CHANGE_ENABLE_THUMBNAIL, base, enable_thumbnail) \
126 ENTRY(base, enable_mvc, U32, RK_U32, MPP_DEC_CFG_CHANGE_ENABLE_MVC, base, enable_mvc) \
127 ENTRY(base, disable_thread, U32, RK_U32, MPP_DEC_CFG_CHANGE_DISABLE_THREAD, base, disable_thread) \
128 ENTRY(cb, pkt_rdy_cb, Ptr, MppExtCbFunc, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_cb) \
129 ENTRY(cb, pkt_rdy_ctx, Ptr, MppExtCbCtx, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_ctx) \
130 ENTRY(cb, pkt_rdy_cmd, S32, RK_S32, MPP_DEC_CB_CFG_CHANGE_PKT_RDY, cb, pkt_rdy_cmd) \
131 ENTRY(cb, frm_rdy_cb, Ptr, MppExtCbFunc, MPP_DEC_CB_CFG_CHANGE_FRM_RDY, cb, frm_rdy_cb) \
132 ENTRY(cb, frm_rdy_ctx, Ptr, MppExtCbCtx, MPP_DEC_CB_CFG_CHANGE_FRM_RDY, cb, frm_rdy_ctx) \
133 ENTRY(cb, frm_rdy_cmd, S32, RK_S32, MPP_DEC_CB_CFG_CHANGE_FRM_RDY, cb, frm_rdy_cmd)
134
mpp_dec_cfg_flaten(MppTrie trie,MppCfgApi ** cfgs)135 static MppDecCfgInfo *mpp_dec_cfg_flaten(MppTrie trie, MppCfgApi **cfgs)
136 {
137 MppDecCfgInfo *info = NULL;
138 MppTrieNode *node_root = mpp_trie_node_root(trie);
139 RK_S32 node_count = mpp_trie_get_node_count(trie);
140 RK_S32 info_count = mpp_trie_get_info_count(trie);
141 MppTrieNode *node_trie;
142 char *buf = NULL;
143 RK_S32 pos = 0;
144 RK_S32 len = 0;
145 RK_S32 i;
146
147 pos += node_count * sizeof(*node_root);
148
149 mpp_dec_cfg_dbg_info("info node offset %d\n", pos);
150
151 /* update info size and string name size */
152 for (i = 0; i < info_count; i++) {
153 const char *name = cfgs[i]->name;
154 const char **info_trie = mpp_trie_get_info(trie, name);
155
156 mpp_assert(*info_trie == name);
157 len = strlen(name);
158 pos += sizeof(MppCfgInfoNode) + MPP_ALIGN(len + 1, sizeof(RK_U64));
159 }
160
161 len = pos + sizeof(*info);
162 mpp_dec_cfg_dbg_info("tire + info size %d total %d\n", pos, len);
163
164 info = mpp_malloc_size(MppDecCfgInfo, len);
165 if (NULL == info)
166 return NULL;
167
168 memcpy(info->trie_node, node_root, sizeof(*node_root) * node_count);
169
170 node_root = info->trie_node;
171 pos = node_count * sizeof(*node_root);
172 buf = (char *)node_root + pos;
173
174 for (i = 0; i < info_count; i++) {
175 MppCfgInfoNode *node_info = (MppCfgInfoNode *)buf;
176 MppCfgApi *api = cfgs[i];
177 const char *name = api->name;
178 RK_S32 node_size;
179
180 node_trie = mpp_trie_get_node(node_root, name);
181 node_trie->id = pos;
182
183 node_info->name_len = MPP_ALIGN(strlen(name) + 1, sizeof(RK_U64));
184 node_info->data_type = api->data_type;
185 node_info->flag_offset = api->flag_offset;
186 node_info->flag_value = api->flag_value;
187 node_info->data_offset = api->data_offset;
188 node_info->data_size = api->data_size;
189 node_info->node_next = 0;
190
191 node_size = node_info->name_len + sizeof(*node_info);
192 node_info->node_size = node_size;
193
194 mpp_cfg_node_fixup_func(node_info);
195
196 strcpy(node_info->name, name);
197
198 mpp_dec_cfg_dbg_info("cfg %s offset %d size %d update %d flag %x\n",
199 node_info->name,
200 node_info->data_offset, node_info->data_size,
201 node_info->flag_offset, node_info->flag_value);
202
203 pos += node_size;
204 buf += node_size;
205 }
206
207 mpp_dec_cfg_dbg_info("total size %d +H %d\n", pos, pos + sizeof(info->head));
208
209 info->head.info_size = pos;
210 info->head.info_count = info_count;
211 info->head.node_count = node_count;
212 info->head.cfg_size = sizeof(MppDecCfgSet);
213
214 return info;
215 }
216
MppDecCfgService()217 MppDecCfgService::MppDecCfgService() :
218 mInfo(NULL),
219 mCfgSize(0)
220 {
221 ENTRY_TABLE(EXPAND_AS_API);
222
223 MppCfgApi *cfgs[] = {
224 ENTRY_TABLE(EXPAND_AS_ARRAY)
225 };
226
227 RK_S32 cfg_cnt = MPP_ARRAY_ELEMS(cfgs);
228 MppTrie trie;
229 MPP_RET ret;
230 RK_S32 i;
231 /*
232 * NOTE: The dec_node_len is not the real node count should be allocated
233 * The max node count should be stream lengthg * 2 if each word is different.
234 */
235 ret = mpp_trie_init(&trie, 334, cfg_cnt);
236 if (ret) {
237 mpp_err_f("failed to init dec cfg set trie\n");
238 return ;
239 }
240 for (i = 0; i < cfg_cnt; i++)
241 mpp_trie_add_info(trie, &cfgs[i]->name);
242
243 mInfo = mpp_dec_cfg_flaten(trie, cfgs);
244 mCfgSize = mInfo->head.cfg_size;
245
246 mpp_trie_deinit(trie);
247 }
248
~MppDecCfgService()249 MppDecCfgService::~MppDecCfgService()
250 {
251 MPP_FREE(mInfo);
252 }
253
get_info_root()254 MppCfgInfoNode *MppDecCfgService::get_info_root()
255 {
256 if (NULL == mInfo)
257 return NULL;
258
259 return (MppCfgInfoNode *)(mInfo->trie_node + mInfo->head.node_count);
260 }
261
mpp_dec_cfg_set_default(MppDecCfgSet * cfg)262 void mpp_dec_cfg_set_default(MppDecCfgSet *cfg)
263 {
264 cfg->base.type = MPP_CTX_BUTT;
265 cfg->base.coding = MPP_VIDEO_CodingUnused;
266 cfg->base.hw_type = -1;
267 cfg->base.fast_parse = 1;
268 #ifdef ENABLE_FASTPLAY_ONCE
269 cfg->base.enable_fast_play = MPP_ENABLE_FAST_PLAY_ONCE;
270 #else
271 cfg->base.enable_fast_play = MPP_ENABLE_FAST_PLAY;
272 #endif
273 }
274
mpp_dec_cfg_init(MppDecCfg * cfg)275 MPP_RET mpp_dec_cfg_init(MppDecCfg *cfg)
276 {
277 MppDecCfgImpl *p = NULL;
278 RK_S32 cfg_size;
279
280 if (NULL == cfg) {
281 mpp_err_f("invalid NULL input config\n");
282 return MPP_ERR_NULL_PTR;
283 }
284
285 cfg_size = MppDecCfgService::get()->get_cfg_size();
286 p = mpp_calloc(MppDecCfgImpl, 1);
287 if (NULL == p) {
288 mpp_err_f("create decoder config failed %p\n", p);
289 *cfg = NULL;
290 return MPP_ERR_NOMEM;
291 }
292
293 mpp_assert(cfg_size == sizeof(p->cfg));
294 p->size = cfg_size;
295 mpp_dec_cfg_set_default(&p->cfg);
296
297 mpp_env_get_u32("mpp_dec_cfg_debug", &mpp_dec_cfg_debug, 0);
298
299 *cfg = p;
300
301 return MPP_OK;
302 }
303
mpp_dec_cfg_deinit(MppDecCfg cfg)304 MPP_RET mpp_dec_cfg_deinit(MppDecCfg cfg)
305 {
306 if (NULL == cfg) {
307 mpp_err_f("invalid NULL input config\n");
308 return MPP_ERR_NULL_PTR;
309 }
310
311 MPP_FREE(cfg);
312
313 return MPP_OK;
314 }
315
316 #define ENC_CFG_SET_ACCESS(func_name, in_type, cfg_type) \
317 MPP_RET func_name(MppDecCfg cfg, const char *name, in_type val) \
318 { \
319 if (NULL == cfg || NULL == name) { \
320 mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \
321 return MPP_ERR_NULL_PTR; \
322 } \
323 MppDecCfgImpl *p = (MppDecCfgImpl *)cfg; \
324 MppCfgInfoNode *info = MppDecCfgService::get()->get_info(name); \
325 if (CHECK_CFG_INFO(info, name, CFG_FUNC_TYPE_##cfg_type)) { \
326 return MPP_NOK; \
327 } \
328 mpp_dec_cfg_dbg_set("name %s type %s\n", info->name, cfg_type_names[info->data_type]); \
329 MPP_RET ret = MPP_CFG_SET_##cfg_type(info, &p->cfg, val); \
330 return ret; \
331 }
332
333 ENC_CFG_SET_ACCESS(mpp_dec_cfg_set_s32, RK_S32, S32);
334 ENC_CFG_SET_ACCESS(mpp_dec_cfg_set_u32, RK_U32, U32);
335 ENC_CFG_SET_ACCESS(mpp_dec_cfg_set_s64, RK_S64, S64);
336 ENC_CFG_SET_ACCESS(mpp_dec_cfg_set_u64, RK_U64, U64);
337 ENC_CFG_SET_ACCESS(mpp_dec_cfg_set_ptr, void *, Ptr);
338 ENC_CFG_SET_ACCESS(mpp_dec_cfg_set_st, void *, St);
339
340 #define ENC_CFG_GET_ACCESS(func_name, in_type, cfg_type) \
341 MPP_RET func_name(MppDecCfg cfg, const char *name, in_type *val) \
342 { \
343 if (NULL == cfg || NULL == name) { \
344 mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \
345 return MPP_ERR_NULL_PTR; \
346 } \
347 MppDecCfgImpl *p = (MppDecCfgImpl *)cfg; \
348 MppCfgInfoNode *info = MppDecCfgService::get()->get_info(name); \
349 if (CHECK_CFG_INFO(info, name, CFG_FUNC_TYPE_##cfg_type)) { \
350 return MPP_NOK; \
351 } \
352 mpp_dec_cfg_dbg_set("name %s type %s\n", info->name, cfg_type_names[info->data_type]); \
353 MPP_RET ret = MPP_CFG_GET_##cfg_type(info, &p->cfg, val); \
354 return ret; \
355 }
356
357 ENC_CFG_GET_ACCESS(mpp_dec_cfg_get_s32, RK_S32, S32);
358 ENC_CFG_GET_ACCESS(mpp_dec_cfg_get_u32, RK_U32, U32);
359 ENC_CFG_GET_ACCESS(mpp_dec_cfg_get_s64, RK_S64, S64);
360 ENC_CFG_GET_ACCESS(mpp_dec_cfg_get_u64, RK_U64, U64);
361 ENC_CFG_GET_ACCESS(mpp_dec_cfg_get_ptr, void *, Ptr);
362 ENC_CFG_GET_ACCESS(mpp_dec_cfg_get_st, void , St);
363
mpp_dec_cfg_show(void)364 void mpp_dec_cfg_show(void)
365 {
366 RK_S32 node_count = MppDecCfgService::get()->get_node_count();
367 RK_S32 info_count = MppDecCfgService::get()->get_info_count();
368 MppCfgInfoNode *info = MppDecCfgService::get()->get_info_root();
369
370 mpp_log("dumping valid configure string start\n");
371
372 if (info) {
373 char *p = (char *)info;
374 RK_S32 i;
375
376 for (i = 0; i < info_count; i++) {
377 info = (MppCfgInfoNode *)p;
378
379 mpp_log("%-25s type %s\n", info->name,
380 cfg_type_names[info->data_type]);
381
382 p += info->node_size;
383 }
384 }
385 mpp_log("dumping valid configure string done\n");
386
387 mpp_log("total cfg count %d with %d node size %d\n",
388 info_count, node_count,
389 MppDecCfgService::get()->get_info_size());
390 }
391