1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp_meta"
7
8 #include <string.h>
9 #include <endian.h>
10
11 #include "mpp_env.h"
12 #include "mpp_lock.h"
13 #include "mpp_debug.h"
14 #include "mpp_mem_pool.h"
15 #include "mpp_singleton.h"
16
17 #include "mpp_trie.h"
18 #include "mpp_meta_impl.h"
19
20 #define META_DBG_FLOW (0x00000001)
21 #define META_DBG_KEYS (0x00000002)
22
23 #define meta_dbg(flag, fmt, ...) _mpp_dbg(mpp_meta_debug, flag, fmt, ## __VA_ARGS__)
24 #define meta_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_meta_debug, flag, fmt, ## __VA_ARGS__)
25
26 #define meta_dbg_flow(fmt, ...) meta_dbg(META_DBG_FLOW, fmt, ## __VA_ARGS__)
27
28 #define META_VAL_INVALID (0x00000000)
29 #define META_VAL_VALID (0x00000001)
30 #define META_VAL_READY (0x00000002)
31
32 #define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val))
33 #define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
34
35 #define get_srv_meta(caller) \
36 ({ \
37 MppMetaSrv *__tmp; \
38 if (srv_meta || srv_finalized) { \
39 __tmp = srv_meta; \
40 } else { \
41 mpp_meta_srv_init(); \
42 __tmp = srv_meta; \
43 if (!__tmp) { \
44 mpp_err("mpp meta srv not init at %s : %s\n", __FUNCTION__, caller); \
45 } \
46 } \
47 __tmp; \
48 })
49
50 #define get_srv_meta_f() \
51 ({ \
52 MppMetaSrv *__tmp; \
53 if (srv_meta || srv_finalized) { \
54 __tmp = srv_meta; \
55 } else { \
56 mpp_meta_srv_init(); \
57 __tmp = srv_meta; \
58 if (!__tmp) { \
59 mpp_err("mpp meta srv not init at %s\n", __FUNCTION__); \
60 } \
61 } \
62 __tmp; \
63 })
64
65 typedef enum MppMetaDataType_e {
66 /* mpp meta data of normal data type */
67 TYPE_VAL_32 = '3',
68 TYPE_VAL_64 = '6',
69 TYPE_KPTR = 'k',
70 TYPE_UPTR = 'u',
71 TYPE_SPTR = 's',
72 } MppMetaType;
73
META_KEY_TO_U64(RK_U32 key,RK_U32 type)74 static inline RK_U64 META_KEY_TO_U64(RK_U32 key, RK_U32 type)
75 {
76 return (RK_U64)((RK_U32)htobe32(key)) | ((RK_U64)type << 32);
77 }
78
79 #define EXPAND_AS_TRIE(key, type) \
80 do { \
81 RK_U64 val = META_KEY_TO_U64(key, type); \
82 mpp_trie_add_info(srv->trie, (const char *)&val, NULL, 0); \
83 meta_key_count++; \
84 } while (0);
85
86 #define EXPAND_AS_LOG(key, type) \
87 do { \
88 RK_U32 key_val = htobe32(key); \
89 char *str = (char *)&key_val; \
90 mpp_logi("%2d - %-24s (%c%c%c%c) : %-12s\n", \
91 i++, #key, str[0], str[1], str[2], str[3], #type); \
92 } while (0);
93
94 #define META_ENTRY_TABLE(ENTRY) \
95 /* categorized by type */ \
96 /* data flow type */ \
97 ENTRY(KEY_INPUT_FRAME, TYPE_SPTR) \
98 ENTRY(KEY_OUTPUT_FRAME, TYPE_SPTR) \
99 ENTRY(KEY_INPUT_PACKET, TYPE_SPTR) \
100 ENTRY(KEY_OUTPUT_PACKET, TYPE_SPTR) \
101 /* buffer for motion detection */ \
102 ENTRY(KEY_MOTION_INFO, TYPE_SPTR) \
103 /* buffer storing the HDR information for current frame*/ \
104 ENTRY(KEY_HDR_INFO, TYPE_SPTR) \
105 /* the offset of HDR meta data in frame buffer */ \
106 ENTRY(KEY_HDR_META_OFFSET, TYPE_VAL_32) \
107 ENTRY(KEY_HDR_META_SIZE, TYPE_VAL_32) \
108 \
109 ENTRY(KEY_OUTPUT_INTRA, TYPE_VAL_32) \
110 ENTRY(KEY_INPUT_BLOCK, TYPE_VAL_32) \
111 ENTRY(KEY_OUTPUT_BLOCK, TYPE_VAL_32) \
112 ENTRY(KEY_INPUT_IDR_REQ, TYPE_VAL_32) \
113 \
114 /* extra information for tsvc */ \
115 ENTRY(KEY_TEMPORAL_ID, TYPE_VAL_32) \
116 ENTRY(KEY_LONG_REF_IDX, TYPE_VAL_32) \
117 ENTRY(KEY_ENC_AVERAGE_QP, TYPE_VAL_32) \
118 ENTRY(KEY_ENC_START_QP, TYPE_VAL_32) \
119 ENTRY(KEY_ENC_BPS_RT, TYPE_VAL_32) \
120 \
121 ENTRY(KEY_ROI_DATA, TYPE_UPTR) \
122 ENTRY(KEY_ROI_DATA2, TYPE_UPTR) \
123 ENTRY(KEY_JPEG_ROI_DATA, TYPE_UPTR) \
124 ENTRY(KEY_OSD_DATA, TYPE_UPTR) \
125 ENTRY(KEY_OSD_DATA2, TYPE_UPTR) \
126 ENTRY(KEY_OSD_DATA3, TYPE_UPTR) \
127 ENTRY(KEY_USER_DATA, TYPE_UPTR) \
128 ENTRY(KEY_USER_DATAS, TYPE_UPTR) \
129 ENTRY(KEY_QPMAP0, TYPE_SPTR) \
130 /* buffer for super encode v3 */ \
131 ENTRY(KEY_NPU_SOBJ_FLAG, TYPE_SPTR) \
132 ENTRY(KEY_NPU_UOBJ_FLAG, TYPE_UPTR) \
133 ENTRY(KEY_BUFFER_UPSCALE, TYPE_SPTR) \
134 ENTRY(KEY_BUFFER_DOWNSCALE, TYPE_SPTR) \
135 \
136 ENTRY(KEY_LVL64_INTER_NUM, TYPE_VAL_32) \
137 ENTRY(KEY_LVL32_INTER_NUM, TYPE_VAL_32) \
138 ENTRY(KEY_LVL16_INTER_NUM, TYPE_VAL_32) \
139 ENTRY(KEY_LVL8_INTER_NUM, TYPE_VAL_32) \
140 ENTRY(KEY_LVL32_INTRA_NUM, TYPE_VAL_32) \
141 ENTRY(KEY_LVL16_INTRA_NUM, TYPE_VAL_32) \
142 ENTRY(KEY_LVL8_INTRA_NUM, TYPE_VAL_32) \
143 ENTRY(KEY_LVL4_INTRA_NUM, TYPE_VAL_32) \
144 ENTRY(KEY_INPUT_PSKIP, TYPE_VAL_32) \
145 ENTRY(KEY_OUTPUT_PSKIP, TYPE_VAL_32) \
146 ENTRY(KEY_INPUT_PSKIP_NON_REF, TYPE_VAL_32) \
147 ENTRY(KEY_ENC_SSE, TYPE_VAL_64) \
148 \
149 ENTRY(KEY_ENC_MARK_LTR, TYPE_VAL_32) \
150 ENTRY(KEY_ENC_USE_LTR, TYPE_VAL_32) \
151 ENTRY(KEY_ENC_FRAME_QP, TYPE_VAL_32) \
152 ENTRY(KEY_ENC_BASE_LAYER_PID, TYPE_VAL_32) \
153 \
154 ENTRY(KEY_DEC_TBN_EN, TYPE_VAL_32) \
155 ENTRY(KEY_DEC_TBN_Y_OFFSET, TYPE_VAL_32) \
156 ENTRY(KEY_DEC_TBN_UV_OFFSET, TYPE_VAL_32)
157
158 typedef struct MppMetaSrv_t {
159 spinlock_t lock;
160 struct list_head list_meta;
161 MppTrie trie;
162
163 RK_U32 meta_id;
164 RK_S32 meta_count;
165 } MppMetaSrv;
166
167 static MppMetaSrv *srv_meta = NULL;
168 static MppMemPool pool_meta = NULL;
169 static RK_U32 srv_finalized = 0;
170 static RK_U32 meta_key_count = 0;
171 static RK_U32 mpp_meta_debug = 0;
172 static RK_S32 user_data_index = -1;
173 static RK_S32 user_datas_index = -1;
174
175 RK_S32 meta_hdr_offset_index = -1;
176 RK_S32 meta_hdr_size_index = -1;
177
178 static void put_meta(MppMetaSrv *srv, MppMetaImpl *meta);
179 static inline RK_S32 get_index_of_key(MppMetaKey key, MppMetaType type, const char *caller);
180 #define get_index_of_key_f(key, type) get_index_of_key(key, type, __FUNCTION__);
181
mpp_meta_srv_init()182 static void mpp_meta_srv_init()
183 {
184 MppMetaSrv *srv = srv_meta;
185
186 mpp_env_get_u32("mpp_meta_debug", &mpp_meta_debug, 0);
187
188 if (srv)
189 return;
190
191 srv = mpp_calloc(MppMetaSrv, 1);
192 if (!srv) {
193 mpp_err_f("failed to malloc meta service\n");
194 return;
195 }
196
197 srv_meta = srv;
198
199 mpp_spinlock_init(&srv->lock);
200 INIT_LIST_HEAD(&srv->list_meta);
201
202 mpp_trie_init(&srv->trie, "MppMetaDef");
203 if (srv->trie) {
204 meta_key_count = 0;
205 META_ENTRY_TABLE(EXPAND_AS_TRIE)
206 mpp_trie_add_info(srv->trie, NULL, NULL, 0);
207 user_data_index = get_index_of_key_f(KEY_USER_DATA, TYPE_UPTR);
208 user_datas_index = get_index_of_key_f(KEY_USER_DATAS, TYPE_UPTR);
209 meta_hdr_offset_index = get_index_of_key_f(KEY_HDR_META_OFFSET, TYPE_VAL_32);
210 meta_hdr_size_index = get_index_of_key_f(KEY_HDR_META_SIZE, TYPE_VAL_32);
211 }
212
213 pool_meta = mpp_mem_pool_init_f("MppMeta", sizeof(MppMetaImpl) +
214 sizeof(MppMetaVal) * meta_key_count);
215
216 meta_dbg_flow("meta key count %d\n", meta_key_count);
217 if (mpp_meta_debug & META_DBG_KEYS) {
218 RK_S32 i = 0;
219
220 META_ENTRY_TABLE(EXPAND_AS_LOG)
221 }
222 }
223
mpp_meta_srv_deinit()224 static void mpp_meta_srv_deinit()
225 {
226 MppMetaSrv *srv = srv_meta;
227
228 if (!srv)
229 return;
230
231 if (!list_empty(&srv->list_meta)) {
232 MppMetaImpl *pos, *n;
233
234 mpp_log_f("cleaning leaked metadata\n");
235
236 list_for_each_entry_safe(pos, n, &srv->list_meta, MppMetaImpl, list_meta) {
237 put_meta(srv, pos);
238 }
239 }
240
241 mpp_assert(srv->meta_count == 0);
242
243 if (srv->trie) {
244 mpp_trie_deinit(srv->trie);
245 srv->trie = NULL;
246 }
247
248 MPP_FREE(srv_meta);
249
250 if (pool_meta) {
251 mpp_mem_pool_deinit_f(pool_meta);
252 pool_meta = NULL;
253 }
254
255 srv_finalized = 1;
256
257 meta_dbg_flow("meta srv deinited\n");
258 }
259
MPP_SINGLETON(MPP_SGLN_META,mpp_meta,mpp_meta_srv_init,mpp_meta_srv_deinit)260 MPP_SINGLETON(MPP_SGLN_META, mpp_meta, mpp_meta_srv_init, mpp_meta_srv_deinit)
261
262 static inline RK_S32 get_index_of_key(MppMetaKey key, MppMetaType type, const char *caller)
263 {
264 MppMetaSrv *srv = get_srv_meta(caller);
265 MppTrieInfo *info = NULL;
266
267 if (srv) {
268 RK_U64 val = META_KEY_TO_U64(key, type);
269
270 info = mpp_trie_get_info(srv->trie, (const char *)&val);
271 }
272
273 return info ? info->index : -1;
274 }
275
get_meta(MppMetaSrv * srv,const char * tag,const char * caller)276 static MppMetaImpl *get_meta(MppMetaSrv *srv, const char *tag, const char *caller)
277 {
278 MppMetaImpl *impl = (MppMetaImpl *)mpp_mem_pool_get(pool_meta, caller);
279
280 if (impl) {
281 const char *tag_src = (tag) ? (tag) : (MODULE_TAG);
282 RK_U32 i;
283
284 strncpy(impl->tag, tag_src, sizeof(impl->tag) - 1);
285 impl->caller = caller;
286 impl->meta_id = MPP_FETCH_ADD(&srv->meta_id, 1);
287 INIT_LIST_HEAD(&impl->list_meta);
288 impl->ref_count = 1;
289 impl->node_count = 0;
290
291 for (i = 0; i < meta_key_count; i++)
292 impl->vals[i].state = 0;
293
294 mpp_spinlock_lock(&srv->lock);
295 list_add_tail(&impl->list_meta, &srv->list_meta);
296 mpp_spinlock_unlock(&srv->lock);
297 MPP_FETCH_ADD(&srv->meta_count, 1);
298 } else {
299 mpp_err_f("failed to malloc meta data\n");
300 }
301
302 return impl;
303 }
304
clean_user_data(MppMetaImpl * impl)305 static void clean_user_data(MppMetaImpl *impl)
306 {
307 MPP_FREE(impl->user_data.pdata);
308 impl->user_data.len = 0;
309 }
310
clean_user_datas(MppMetaImpl * impl)311 static void clean_user_datas(MppMetaImpl *impl)
312 {
313 MPP_FREE(impl->user_data_set.datas);
314 impl->user_data_set.count = 0;
315 impl->datas_buf_size = 0;
316 }
317
put_meta(MppMetaSrv * srv,MppMetaImpl * meta)318 static void put_meta(MppMetaSrv *srv, MppMetaImpl *meta)
319 {
320 RK_S32 ref_count;
321
322 if (!srv)
323 return;
324
325 ref_count = MPP_SUB_FETCH(&meta->ref_count, 1);
326 if (ref_count > 0)
327 return;
328
329 if (ref_count < 0) {
330 mpp_err_f("invalid negative ref_count %d\n", ref_count);
331 return;
332 }
333
334 mpp_spinlock_lock(&srv->lock);
335 clean_user_data(meta);
336 clean_user_datas(meta);
337 list_del_init(&meta->list_meta);
338 mpp_spinlock_unlock(&srv->lock);
339 MPP_FETCH_SUB(&srv->meta_count, 1);
340
341 if (pool_meta)
342 mpp_mem_pool_put_f(pool_meta, meta);
343 }
344
mpp_meta_get_with_tag(MppMeta * meta,const char * tag,const char * caller)345 MPP_RET mpp_meta_get_with_tag(MppMeta *meta, const char *tag, const char *caller)
346 {
347 MppMetaSrv *srv = get_srv_meta(caller);
348 MppMetaImpl *impl;
349
350 if (!srv)
351 return MPP_NOK;
352
353 if (!meta) {
354 mpp_err_f("found NULL input\n");
355 return MPP_ERR_NULL_PTR;
356 }
357
358 impl = get_meta(srv, tag, caller);
359 *meta = (MppMeta) impl;
360 return (impl) ? (MPP_OK) : (MPP_NOK);
361 }
362
mpp_meta_put(MppMeta meta)363 MPP_RET mpp_meta_put(MppMeta meta)
364 {
365 MppMetaImpl *impl = (MppMetaImpl *)meta;
366
367 if (!impl) {
368 mpp_err_f("found NULL input\n");
369 return MPP_ERR_NULL_PTR;
370 }
371
372 put_meta(get_srv_meta_f(), impl);
373 return MPP_OK;
374 }
375
mpp_meta_inc_ref(MppMeta meta)376 MPP_RET mpp_meta_inc_ref(MppMeta meta)
377 {
378 MppMetaImpl *impl = (MppMetaImpl *)meta;
379
380 if (!impl) {
381 mpp_err_f("found NULL input\n");
382 return MPP_ERR_NULL_PTR;
383 }
384
385 MPP_FETCH_ADD(&impl->ref_count, 1);
386 return MPP_OK;
387 }
388
mpp_meta_size(MppMeta meta)389 RK_S32 mpp_meta_size(MppMeta meta)
390 {
391 MppMetaImpl *impl = (MppMetaImpl *)meta;
392
393 if (!impl) {
394 mpp_err_f("found NULL input\n");
395 return -1;
396 }
397
398 return MPP_FETCH_ADD(&impl->node_count, 0);
399 }
400
set_user_data(MppMetaImpl * impl,void * user_data)401 static MPP_RET set_user_data(MppMetaImpl *impl, void *user_data)
402 {
403 MppEncUserData *src = (MppEncUserData *)user_data;
404
405 if (!src) {
406 clean_user_data(impl);
407 return MPP_OK;
408 }
409
410 if (!src->pdata || !src->len) {
411 mpp_err_f("invalid user data %p pdata %p len %d\n", user_data, src->pdata, src->len);
412 return MPP_ERR_NULL_PTR;
413 }
414
415 if (impl->user_data.len < src->len) {
416 void *buf_ptr = mpp_realloc(impl->user_data.pdata, RK_U8, src->len);
417
418 if (!buf_ptr) {
419 mpp_err_f("failed to realloc user data buf size %d\n", src->len);
420 impl->user_data.len = 0;
421 return MPP_ERR_MALLOC;
422 }
423 impl->user_data.pdata = buf_ptr;
424 }
425
426 memcpy(impl->user_data.pdata, src->pdata, src->len);
427 impl->user_data.len = src->len;
428
429 return MPP_OK;
430 }
431
set_user_datas(MppMetaImpl * impl,void * user_data)432 static MPP_RET set_user_datas(MppMetaImpl *impl, void *user_data)
433 {
434 MppEncUserDataSet *src_set = (MppEncUserDataSet *)user_data;
435 MppEncUserDataFull *dst_set = NULL;
436 void *buf_ptr = NULL;
437 RK_U32 data_size = 0;
438 RK_U32 struct_size = 0;
439 RK_U32 buf_size = 0;
440 RK_U32 i = 0;
441
442 if (!src_set) {
443 clean_user_datas(impl);
444 return MPP_OK;
445 }
446
447 if (!src_set->datas || !src_set->count) {
448 mpp_err_f("invalid user data %p datas %p count %d\n", src_set, src_set->datas, src_set->count);
449 return MPP_ERR_NULL_PTR;
450 }
451
452 struct_size = sizeof(MppEncUserDataFull) * src_set->count;
453 for (i = 0; i < src_set->count; i++) {
454 MppEncUserDataFull *src = &src_set->datas[i];
455
456 if (src->uuid)
457 data_size += strlen((const char *)src->uuid) + 1;
458 data_size += src->len;
459 }
460 buf_size = struct_size + data_size;
461
462 if (impl->datas_buf_size < buf_size) {
463 buf_ptr = mpp_realloc(impl->user_data_set.datas, RK_U8, buf_size);
464 if (!buf_ptr) {
465 mpp_err_f("failed to realloc user data buf size %d\n", buf_size);
466 impl->user_data_set.count = 0;
467 impl->datas_buf_size = 0;
468 return MPP_ERR_MALLOC;
469 }
470 impl->user_data_set.datas = (MppEncUserDataFull *)buf_ptr;
471 }
472
473 impl->datas_buf_size = buf_size;
474 dst_set = impl->user_data_set.datas;
475 buf_ptr = (void *)dst_set + struct_size;
476
477 for (i = 0; i < src_set->count; i++) {
478 MppEncUserDataFull *src = &src_set->datas[i];
479 MppEncUserDataFull *dst = &dst_set[i];
480
481 dst->len = src->len;
482 if (src->uuid) {
483 size_t uuid_len = strlen((const char *)src->uuid) + 1;
484
485 dst->uuid = (RK_U8 *)buf_ptr;
486 memcpy(buf_ptr, src->uuid, uuid_len);
487 buf_ptr += uuid_len;
488 } else {
489 dst->uuid = NULL;
490 }
491 if (src->pdata) {
492 dst->pdata = buf_ptr;
493 memcpy(buf_ptr, src->pdata, src->len);
494 buf_ptr += src->len;
495 } else {
496 dst->pdata = NULL;
497 }
498 }
499 impl->user_data_set.count = src_set->count;
500
501 return MPP_OK;
502 }
503
get_user_data(MppMetaImpl * impl,void ** val)504 static MPP_RET get_user_data(MppMetaImpl *impl, void **val)
505 {
506 if (impl->user_data.pdata) {
507 *val = &impl->user_data;
508 return MPP_OK;
509 }
510
511 *val = NULL;
512 return MPP_NOK;
513 }
514
get_user_datas(MppMetaImpl * impl,void ** val)515 static MPP_RET get_user_datas(MppMetaImpl *impl, void **val)
516 {
517 if (impl->user_data_set.datas) {
518 *val = &impl->user_data_set;
519 return MPP_OK;
520 }
521
522 *val = NULL;
523 return MPP_NOK;
524 }
525
mpp_meta_dup(MppMeta meta)526 MppMeta mpp_meta_dup(MppMeta meta)
527 {
528 MppMetaSrv *srv = get_srv_meta_f();
529 MppMetaImpl *impl = (MppMetaImpl *)meta;
530 MppMetaImpl *ret;
531
532 if (!srv || !meta)
533 return NULL;
534
535 ret = get_meta(srv, impl->tag, __FUNCTION__);
536 if (ret) {
537 memcpy(ret->vals, impl->vals, meta_key_count * sizeof(MppMetaVal));
538 if (ret->user_data.len) {
539 memset(&ret->user_data, 0, sizeof(ret->user_data));
540 set_user_data(ret, (void *)(intptr_t)&impl->user_data);
541 }
542 if (ret->user_data_set.count) {
543 memset(&ret->user_data, 0, sizeof(ret->user_data));
544 set_user_datas(impl, (void *)(intptr_t)&impl->user_data_set);
545 }
546 ret->node_count = impl->node_count;
547 }
548
549 return ret;
550 }
551
mpp_meta_dump(MppMeta meta)552 MPP_RET mpp_meta_dump(MppMeta meta)
553 {
554 MppMetaSrv *srv = get_srv_meta_f();
555 MppMetaImpl *impl = (MppMetaImpl *)meta;
556 MppTrieInfo *root;
557
558 if (!impl) {
559 mpp_err_f("found NULL input\n");
560 return MPP_ERR_NULL_PTR;
561 }
562
563 mpp_logi("dumping meta %d node count %d\n", impl->meta_id, impl->node_count);
564
565 if (!srv || !srv->trie)
566 return MPP_NOK;
567
568 root = mpp_trie_get_info_first(srv->trie);
569 if (root) {
570 MppTrieInfo *node = root;
571 const char *key = NULL;
572 char log_str[256];
573 RK_S32 pos;
574
575 do {
576 if (mpp_trie_info_is_self(node))
577 continue;
578
579 key = mpp_trie_info_name(node);
580
581 pos = snprintf(log_str, sizeof(log_str) - 1, "key %c%c%c%c - ",
582 key[0], key[1], key[2], key[3]);
583
584 switch (key[4]) {
585 case '3' : {
586 snprintf(log_str + pos, sizeof(log_str) - pos - 1, "s32 - %d",
587 impl->vals[node->index].val_s32);
588 } break;
589 case '6' : {
590 snprintf(log_str + pos, sizeof(log_str) - pos - 1, "s64 - %lld",
591 impl->vals[node->index].val_s64);
592 } break;
593 case 'k' :
594 case 'u' :
595 case 's' : {
596 snprintf(log_str + pos, sizeof(log_str) - pos - 1, "ptr - %p",
597 impl->vals[node->index].val_ptr);
598 } break;
599 default : {
600 } break;
601 }
602
603 mpp_logi("%s\n", log_str);
604 } while ((node = mpp_trie_get_info_next(srv->trie, node)));
605 }
606
607 return MPP_OK;
608 }
609
610 #define MPP_META_ACCESSOR(func_type, arg_type, key_type, key_field) \
611 MPP_RET mpp_meta_set_##func_type(MppMeta meta, MppMetaKey key, arg_type val) \
612 { \
613 MppMetaImpl *impl = (MppMetaImpl *)meta; \
614 MppMetaVal *meta_val; \
615 RK_S32 index; \
616 if (!impl) { \
617 mpp_err_f("found NULL input\n"); \
618 return MPP_ERR_NULL_PTR; \
619 } \
620 index = get_index_of_key_f(key, key_type); \
621 if (index < 0) \
622 return MPP_NOK; \
623 meta_val = &impl->vals[index]; \
624 if (MPP_BOOL_CAS(&meta_val->state, META_VAL_INVALID, META_VAL_VALID)) \
625 MPP_FETCH_ADD(&impl->node_count, 1); \
626 if (index == user_data_index) { \
627 set_user_data(impl, (void *)(intptr_t)val); \
628 } else if (index == user_datas_index) { \
629 set_user_datas(impl, (void *)(intptr_t)val); \
630 } else { \
631 meta_val->key_field = val; \
632 } \
633 MPP_FETCH_OR(&meta_val->state, META_VAL_READY); \
634 return MPP_OK; \
635 } \
636 MPP_RET mpp_meta_get_##func_type(MppMeta meta, MppMetaKey key, arg_type *val) \
637 { \
638 MppMetaImpl *impl = (MppMetaImpl *)meta; \
639 MppMetaVal *meta_val; \
640 RK_S32 index; \
641 MPP_RET ret = MPP_NOK; \
642 if (!impl) { \
643 mpp_err_f("found NULL input\n"); \
644 return MPP_ERR_NULL_PTR; \
645 } \
646 index = get_index_of_key_f(key, key_type); \
647 if (index < 0) \
648 return MPP_NOK; \
649 meta_val = &impl->vals[index]; \
650 if (MPP_BOOL_CAS(&meta_val->state, META_VAL_VALID | META_VAL_READY, META_VAL_INVALID)) { \
651 if (index == user_data_index) \
652 get_user_data(impl, (void**)val); \
653 else if (index == user_datas_index) \
654 get_user_datas(impl, (void**)val); \
655 else \
656 *val = meta_val->key_field; \
657 MPP_FETCH_SUB(&impl->node_count, 1); \
658 ret = MPP_OK; \
659 } \
660 return ret; \
661 } \
662 MPP_RET mpp_meta_get_##func_type##_d(MppMeta meta, MppMetaKey key, arg_type *val, arg_type def) \
663 { \
664 MppMetaImpl *impl = (MppMetaImpl *)meta; \
665 MppMetaVal *meta_val; \
666 RK_S32 index; \
667 MPP_RET ret = MPP_NOK; \
668 if (!impl) { \
669 mpp_err_f("found NULL input\n"); \
670 return MPP_ERR_NULL_PTR; \
671 } \
672 index = get_index_of_key_f(key, key_type); \
673 if (index < 0) \
674 return MPP_NOK; \
675 meta_val = &impl->vals[index]; \
676 if (MPP_BOOL_CAS(&meta_val->state, META_VAL_VALID | META_VAL_READY, META_VAL_INVALID)) { \
677 if (index == user_data_index) \
678 get_user_data(impl, (void**)val); \
679 else if (index == user_datas_index) \
680 get_user_datas(impl, (void**)val); \
681 else \
682 *val = meta_val->key_field; \
683 MPP_FETCH_SUB(&impl->node_count, 1); \
684 ret = MPP_OK; \
685 } else { \
686 *val = def; \
687 } \
688 return ret; \
689 }
690
MPP_META_ACCESSOR(s32,RK_S32,TYPE_VAL_32,val_s32)691 MPP_META_ACCESSOR(s32, RK_S32, TYPE_VAL_32, val_s32)
692 MPP_META_ACCESSOR(s64, RK_S64, TYPE_VAL_64, val_s64)
693 MPP_META_ACCESSOR(ptr, void *, TYPE_UPTR, val_ptr)
694 MPP_META_ACCESSOR(frame, MppFrame, TYPE_SPTR, frame)
695 MPP_META_ACCESSOR(packet, MppPacket, TYPE_SPTR, packet)
696 MPP_META_ACCESSOR(buffer, MppBuffer, TYPE_SPTR, buffer)
697
698 RK_S32 mpp_meta_s32_read(MppMeta meta, RK_S32 index, RK_S32 *val)
699 {
700 MppMetaImpl *impl = (MppMetaImpl *)meta;
701 MppMetaVal *meta_val;
702 MPP_RET ret = MPP_NOK;
703
704 if (!impl || index < 0 || index >= meta_key_count) {
705 mpp_err_f("found NULL input meta %p index %d\n", meta, index);
706 return MPP_ERR_NULL_PTR;
707 }
708
709 meta_val = &impl->vals[index];
710 if (meta_val->state == (META_VAL_VALID | META_VAL_READY)) {
711 *val = meta_val->val_s32;
712 ret = MPP_OK;
713 }
714
715 return ret;
716 }
717