xref: /OK3568_Linux_fs/external/mpp/mpp/base/mpp_dec_cfg.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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