xref: /OK3568_Linux_fs/external/mpp/mpp/base/mpp_meta.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 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_meta"
18 
19 #include <string.h>
20 
21 #include "mpp_mem.h"
22 #include "mpp_list.h"
23 #include "mpp_lock.h"
24 
25 #include "mpp_meta_impl.h"
26 
27 #define META_VAL_INVALID    (0x00000000)
28 #define META_VAL_VALID      (0x00000001)
29 #define META_VAL_READY      (0x00000002)
30 
31 #define WRITE_ONCE(x, val)  ((*(volatile typeof(x) *) &(x)) = (val))
32 #define READ_ONCE(var)      (*((volatile typeof(var) *)(&(var))))
33 
34 static MppMetaDef meta_defs[] = {
35     /* categorized by type */
36     /* data flow type */
37     {   KEY_INPUT_FRAME,        TYPE_FRAME,     },
38     {   KEY_OUTPUT_FRAME,       TYPE_FRAME,     },
39     {   KEY_INPUT_PACKET,       TYPE_PACKET,    },
40     {   KEY_OUTPUT_PACKET,      TYPE_PACKET,    },
41     /* buffer for motion detection */
42     {   KEY_MOTION_INFO,        TYPE_BUFFER,    },
43     /* buffer storing the HDR information for current frame*/
44     {   KEY_HDR_INFO,           TYPE_BUFFER,    },
45     /* the offset of HDR meta data in frame buffer */
46     {   KEY_HDR_META_OFFSET,    TYPE_S32,       },
47     {   KEY_HDR_META_SIZE,      TYPE_S32,       },
48 
49     {   KEY_OUTPUT_INTRA,       TYPE_S32,       },
50     {   KEY_INPUT_BLOCK,        TYPE_S32,       },
51     {   KEY_OUTPUT_BLOCK,       TYPE_S32,       },
52 
53     /* extra information for tsvc */
54     {   KEY_TEMPORAL_ID,        TYPE_S32,       },
55     {   KEY_LONG_REF_IDX,       TYPE_S32,       },
56     {   KEY_ENC_AVERAGE_QP,     TYPE_S32,       },
57 
58     {   KEY_ROI_DATA,           TYPE_PTR,       },
59     {   KEY_ROI_DATA2,          TYPE_PTR,       },
60     {   KEY_OSD_DATA,           TYPE_PTR,       },
61     {   KEY_OSD_DATA2,          TYPE_PTR,       },
62     {   KEY_USER_DATA,          TYPE_PTR,       },
63     {   KEY_USER_DATAS,         TYPE_PTR,       },
64     {   KEY_QPMAP0,             TYPE_BUFFER,    },
65     {   KEY_MV_LIST,            TYPE_PTR,       },
66 
67     {   KEY_ENC_MARK_LTR,       TYPE_S32,       },
68     {   KEY_ENC_USE_LTR,        TYPE_S32,       },
69     {   KEY_ENC_FRAME_QP,       TYPE_S32,       },
70     {   KEY_ENC_BASE_LAYER_PID, TYPE_S32,       },
71 
72     {   KEY_DEC_TBN_EN,         TYPE_S32,       },
73     {   KEY_DEC_TBN_Y_OFFSET,   TYPE_S32,       },
74     {   KEY_DEC_TBN_UV_OFFSET,  TYPE_S32,       },
75 };
76 
77 class MppMetaService
78 {
79 private:
80     // avoid any unwanted function
81     MppMetaService();
82     ~MppMetaService();
83     MppMetaService(const MppMetaService &);
84     MppMetaService &operator=(const MppMetaService &);
85 
86     spinlock_t          mLock;
87     struct list_head    mlist_meta;
88 
89     RK_U32              meta_id;
90     RK_S32              meta_count;
91     RK_U32              finished;
92 
93 public:
get_inst()94     static MppMetaService *get_inst() {
95         static MppMetaService instance;
96         return &instance;
97     }
98 
99     /*
100      * get_index_of_key does two things:
101      * 1. Check the key / type pair is correct or not.
102      *    If failed on check return negative value
103      * 2. Compare all exsisting meta data defines to find the non-negative index
104      */
105     RK_S32 get_index_of_key(MppMetaKey key, MppMetaType type);
106 
107     MppMetaImpl  *get_meta(const char *tag, const char *caller);
108     void          put_meta(MppMetaImpl *meta);
109 };
110 
MppMetaService()111 MppMetaService::MppMetaService()
112     : meta_id(0),
113       meta_count(0),
114       finished(0)
115 {
116     mpp_spinlock_init(&mLock);
117     INIT_LIST_HEAD(&mlist_meta);
118 }
119 
~MppMetaService()120 MppMetaService::~MppMetaService()
121 {
122     if (!list_empty(&mlist_meta)) {
123         MppMetaImpl *pos, *n;
124 
125         mpp_log_f("cleaning leaked metadata\n");
126 
127         list_for_each_entry_safe(pos, n, &mlist_meta, MppMetaImpl, list_meta) {
128             put_meta(pos);
129         }
130     }
131 
132     mpp_assert(meta_count == 0);
133     finished = 1;
134 }
135 
get_index_of_key(MppMetaKey key,MppMetaType type)136 RK_S32 MppMetaService::get_index_of_key(MppMetaKey key, MppMetaType type)
137 {
138     RK_S32 i = 0;
139     RK_S32 num = MPP_ARRAY_ELEMS(meta_defs);
140 
141     for (i = 0; i < num; i++) {
142         if ((meta_defs[i].key == key) && (meta_defs[i].type == type))
143             break;
144     }
145 
146     return (i < num) ? (i) : (-1);
147 }
148 
get_meta(const char * tag,const char * caller)149 MppMetaImpl *MppMetaService::get_meta(const char *tag, const char *caller)
150 {
151     MppMetaImpl *impl = mpp_malloc_size(MppMetaImpl, sizeof(MppMetaImpl) +
152                                         sizeof(MppMetaVal) * MPP_ARRAY_ELEMS(meta_defs));
153     if (impl) {
154         const char *tag_src = (tag) ? (tag) : (MODULE_TAG);
155         RK_U32 i;
156 
157         strncpy(impl->tag, tag_src, sizeof(impl->tag));
158         impl->caller = caller;
159         impl->meta_id = MPP_FETCH_ADD(&meta_id, 1);
160         INIT_LIST_HEAD(&impl->list_meta);
161         impl->ref_count = 1;
162         impl->node_count = 0;
163 
164         for (i = 0; i < MPP_ARRAY_ELEMS(meta_defs); i++)
165             impl->vals[i].state = 0;
166 
167         mpp_spinlock_lock(&mLock);
168         list_add_tail(&impl->list_meta, &mlist_meta);
169         mpp_spinlock_unlock(&mLock);
170         MPP_FETCH_ADD(&meta_count, 1);
171     } else {
172         mpp_err_f("failed to malloc meta data\n");
173     }
174     return impl;
175 }
176 
put_meta(MppMetaImpl * meta)177 void MppMetaService::put_meta(MppMetaImpl *meta)
178 {
179     if (finished)
180         return ;
181 
182     RK_S32 ref_count = MPP_SUB_FETCH(&meta->ref_count, 1);
183 
184     if (ref_count > 0)
185         return;
186 
187     if (ref_count < 0) {
188         mpp_err_f("invalid negative ref_count %d\n", ref_count);
189         return;
190     }
191 
192     mpp_spinlock_lock(&mLock);
193     list_del_init(&meta->list_meta);
194     mpp_spinlock_unlock(&mLock);
195     MPP_FETCH_SUB(&meta_count, 1);
196 
197     mpp_free(meta);
198 }
199 
mpp_meta_get_with_tag(MppMeta * meta,const char * tag,const char * caller)200 MPP_RET mpp_meta_get_with_tag(MppMeta *meta, const char *tag, const char *caller)
201 {
202     if (NULL == meta) {
203         mpp_err_f("found NULL input\n");
204         return MPP_ERR_NULL_PTR;
205     }
206 
207     MppMetaService *service = MppMetaService::get_inst();
208     MppMetaImpl *impl = service->get_meta(tag, caller);
209     *meta = (MppMeta) impl;
210     return (impl) ? (MPP_OK) : (MPP_NOK);
211 }
212 
mpp_meta_put(MppMeta meta)213 MPP_RET mpp_meta_put(MppMeta meta)
214 {
215     if (NULL == meta) {
216         mpp_err_f("found NULL input\n");
217         return MPP_ERR_NULL_PTR;
218     }
219 
220     MppMetaService *service = MppMetaService::get_inst();
221     MppMetaImpl *impl = (MppMetaImpl *)meta;
222 
223     service->put_meta(impl);
224     return MPP_OK;
225 }
226 
mpp_meta_inc_ref(MppMeta meta)227 MPP_RET mpp_meta_inc_ref(MppMeta meta)
228 {
229     if (NULL == meta) {
230         mpp_err_f("found NULL input\n");
231         return MPP_ERR_NULL_PTR;
232     }
233 
234     MppMetaImpl *impl = (MppMetaImpl *)meta;
235 
236     MPP_FETCH_ADD(&impl->ref_count, 1);
237     return MPP_OK;
238 }
239 
mpp_meta_size(MppMeta meta)240 RK_S32 mpp_meta_size(MppMeta meta)
241 {
242     if (NULL == meta) {
243         mpp_err_f("found NULL input\n");
244         return -1;
245     }
246 
247     MppMetaImpl *impl = (MppMetaImpl *)meta;
248 
249     return MPP_FETCH_ADD(&impl->node_count, 0);
250 }
251 
mpp_meta_dump(MppMeta meta)252 MPP_RET mpp_meta_dump(MppMeta meta)
253 {
254     if (NULL == meta) {
255         mpp_err_f("found NULL input\n");
256         return MPP_ERR_NULL_PTR;
257     }
258 
259     MppMetaImpl *impl = (MppMetaImpl *)meta;
260     RK_U32 i;
261 
262     mpp_log("dumping meta %d node count %d\n", impl->meta_id, impl->node_count);
263 
264     for (i = 0; i < MPP_ARRAY_ELEMS(meta_defs); i++) {
265         if (!impl->vals[i].state)
266             continue;
267 
268         const char *key = (const char *)&meta_defs[i].key;
269         const char *type = (const char *)&meta_defs[i].type;
270 
271         mpp_log("key %c%c%c%c type %c%c%c%c\n",
272                 key[3], key[2], key[1], key[0],
273                 type[3], type[2], type[1], type[0]);
274     }
275 
276     return MPP_OK;
277 }
278 
279 #define MPP_META_ACCESSOR(func_type, arg_type, key_type, key_field)  \
280     MPP_RET mpp_meta_set_##func_type(MppMeta meta, MppMetaKey key, arg_type val) \
281     { \
282         if (NULL == meta) { \
283             mpp_err_f("found NULL input\n"); \
284             return MPP_ERR_NULL_PTR; \
285         } \
286         MppMetaService *service = MppMetaService::get_inst(); \
287         RK_S32 index = service->get_index_of_key(key, key_type); \
288         if (index < 0) \
289             return MPP_NOK; \
290         MppMetaImpl *impl = (MppMetaImpl *)meta; \
291         MppMetaVal *meta_val = &impl->vals[index]; \
292         if (MPP_BOOL_CAS(&meta_val->state, META_VAL_INVALID, META_VAL_VALID)) \
293             MPP_FETCH_ADD(&impl->node_count, 1); \
294         meta_val->key_field = val; \
295         MPP_FETCH_OR(&meta_val->state, META_VAL_READY); \
296         return MPP_OK; \
297     } \
298     MPP_RET mpp_meta_get_##func_type(MppMeta meta, MppMetaKey key, arg_type *val) \
299     { \
300         if (NULL == meta) { \
301             mpp_err_f("found NULL input\n"); \
302             return MPP_ERR_NULL_PTR; \
303         } \
304         MppMetaService *service = MppMetaService::get_inst(); \
305         RK_S32 index = service->get_index_of_key(key, key_type); \
306         if (index < 0) \
307             return MPP_NOK; \
308         MppMetaImpl *impl = (MppMetaImpl *)meta; \
309         MppMetaVal *meta_val = &impl->vals[index]; \
310         MPP_RET ret = MPP_NOK; \
311         if (MPP_BOOL_CAS(&meta_val->state, META_VAL_VALID | META_VAL_READY, META_VAL_INVALID)) { \
312             *val = meta_val->key_field; \
313             MPP_FETCH_SUB(&impl->node_count, 1); \
314             ret = MPP_OK; \
315         } \
316         return ret; \
317     } \
318     MPP_RET mpp_meta_get_##func_type##_d(MppMeta meta, MppMetaKey key, arg_type *val, arg_type def) \
319     { \
320         if (NULL == meta) { \
321             mpp_err_f("found NULL input\n"); \
322             return MPP_ERR_NULL_PTR; \
323         } \
324         MppMetaService *service = MppMetaService::get_inst(); \
325         RK_S32 index = service->get_index_of_key(key, key_type); \
326         if (index < 0) \
327             return MPP_NOK; \
328         MppMetaImpl *impl = (MppMetaImpl *)meta; \
329         MppMetaVal *meta_val = &impl->vals[index]; \
330         MPP_RET ret = MPP_NOK; \
331         if (MPP_BOOL_CAS(&meta_val->state, META_VAL_VALID | META_VAL_READY, META_VAL_INVALID)) { \
332             *val = meta_val->key_field; \
333             MPP_FETCH_SUB(&impl->node_count, 1); \
334             ret = MPP_OK; \
335         } else { \
336             *val = def; \
337         } \
338         return ret; \
339     }
340 
341 MPP_META_ACCESSOR(s32, RK_S32, TYPE_S32, val_s32)
342 MPP_META_ACCESSOR(s64, RK_S64, TYPE_S64, val_s64)
343 MPP_META_ACCESSOR(ptr, void *, TYPE_PTR, val_ptr)
344 MPP_META_ACCESSOR(frame, MppFrame, TYPE_FRAME, frame)
345 MPP_META_ACCESSOR(packet, MppPacket, TYPE_PACKET, packet)
346 MPP_META_ACCESSOR(buffer, MppBuffer, TYPE_BUFFER, buffer)
347