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_buffer"
7
8 #include <string.h>
9
10 #include "mpp_mem.h"
11 #include "mpp_debug.h"
12 #include "mpp_dmabuf.h"
13 #include "mpp_buffer_impl.h"
14
mpp_buffer_import_with_tag(MppBufferGroup group,MppBufferInfo * info,MppBuffer * buffer,const char * tag,const char * caller)15 MPP_RET mpp_buffer_import_with_tag(MppBufferGroup group, MppBufferInfo *info, MppBuffer *buffer,
16 const char *tag, const char *caller)
17 {
18 if (NULL == info) {
19 mpp_err("mpp_buffer_commit invalid input: info NULL from %s\n", caller);
20 return MPP_ERR_NULL_PTR;
21 }
22
23 MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
24
25 if (p) {
26 // if group is specified we need to check the parameter
27 if ((p->type & MPP_BUFFER_TYPE_MASK) != info->type ||
28 (p->type & MPP_BUFFER_TYPE_MASK) >= MPP_BUFFER_TYPE_BUTT ||
29 p->mode != MPP_BUFFER_EXTERNAL) {
30 mpp_err("mpp_buffer_commit invalid type found group %d info %d group mode %d from %s\n",
31 p->type, info->type, p->mode, caller);
32 return MPP_ERR_UNKNOW;
33 }
34 } else {
35 // otherwise use default external group to manage them
36 p = mpp_buffer_get_misc_group(MPP_BUFFER_EXTERNAL, info->type);
37 }
38
39 mpp_assert(p);
40
41 MPP_RET ret = MPP_OK;
42 if (buffer) {
43 MppBufferImpl *buf = NULL;
44 ret = mpp_buffer_create(tag, caller, p, info, &buf);
45 *buffer = buf;
46 } else {
47 ret = mpp_buffer_create(tag, caller, p, info, NULL);
48 }
49 return ret;
50 }
51
mpp_buffer_get_with_tag(MppBufferGroup group,MppBuffer * buffer,size_t size,const char * tag,const char * caller)52 MPP_RET mpp_buffer_get_with_tag(MppBufferGroup group, MppBuffer *buffer, size_t size,
53 const char *tag, const char *caller)
54 {
55 if (NULL == buffer || 0 == size) {
56 mpp_err("mpp_buffer_get invalid input: group %p buffer %p size %u from %s\n",
57 group, buffer, size, caller);
58 return MPP_ERR_UNKNOW;
59 }
60
61 if (NULL == group) {
62 // deprecated, only for libvpu support
63 group = mpp_buffer_get_misc_group(MPP_BUFFER_INTERNAL, MPP_BUFFER_TYPE_ION);
64 }
65
66 mpp_assert(group);
67
68 MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
69 // try unused buffer first
70 MppBufferImpl *buf = mpp_buffer_get_unused(p, size, caller);
71 if (NULL == buf && MPP_BUFFER_INTERNAL == p->mode) {
72 MppBufferInfo info = {
73 p->type,
74 size,
75 NULL,
76 NULL,
77 -1,
78 -1,
79 };
80 // if failed try init a new buffer
81 mpp_buffer_create(tag, caller, p, &info, &buf);
82 }
83 *buffer = buf;
84 return (buf) ? (MPP_OK) : (MPP_NOK);
85 }
86
87
mpp_buffer_put_with_caller(MppBuffer buffer,const char * caller)88 MPP_RET mpp_buffer_put_with_caller(MppBuffer buffer, const char *caller)
89 {
90 if (NULL == buffer) {
91 mpp_err("mpp_buffer_put invalid input: buffer NULL from %s\n", caller);
92 return MPP_ERR_UNKNOW;
93 }
94
95 return mpp_buffer_ref_dec((MppBufferImpl*)buffer, caller);
96 }
97
mpp_buffer_inc_ref_with_caller(MppBuffer buffer,const char * caller)98 MPP_RET mpp_buffer_inc_ref_with_caller(MppBuffer buffer, const char *caller)
99 {
100 if (NULL == buffer) {
101 mpp_err("mpp_buffer_inc_ref invalid input: buffer NULL from %s\n", caller);
102 return MPP_ERR_UNKNOW;
103 }
104
105 return mpp_buffer_ref_inc((MppBufferImpl*)buffer, caller);
106 }
107
mpp_buffer_discard_with_caller(MppBuffer buffer,const char * caller)108 MPP_RET mpp_buffer_discard_with_caller(MppBuffer buffer, const char *caller)
109 {
110 if (NULL == buffer) {
111 mpp_err("mpp_buffer_discard invalid input: buffer NULL from %s\n", caller);
112 return MPP_ERR_UNKNOW;
113 }
114
115 return mpp_buffer_discard((MppBufferImpl*)buffer, caller);
116 }
117
mpp_buffer_read_with_caller(MppBuffer buffer,size_t offset,void * data,size_t size,const char * caller)118 MPP_RET mpp_buffer_read_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller)
119 {
120 if (NULL == buffer || NULL == data) {
121 mpp_err("mpp_buffer_read invalid input: buffer %p data %p from %s\n",
122 buffer, data, caller);
123 return MPP_ERR_UNKNOW;
124 }
125
126 if (0 == size)
127 return MPP_OK;
128
129 MppBufferImpl *p = (MppBufferImpl*)buffer;
130 if (NULL == p->info.ptr)
131 mpp_buffer_mmap(p, caller);
132
133 void *src = p->info.ptr;
134 mpp_assert(src != NULL);
135 if (src)
136 memcpy(data, (char*)src + offset, size);
137
138 return MPP_OK;
139 }
140
mpp_buffer_write_with_caller(MppBuffer buffer,size_t offset,void * data,size_t size,const char * caller)141 MPP_RET mpp_buffer_write_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller)
142 {
143 if (NULL == buffer || NULL == data) {
144 mpp_err("mpp_buffer_write invalid input: buffer %p data %p from %s\n",
145 buffer, data, caller);
146 return MPP_ERR_UNKNOW;
147 }
148
149 if (0 == size)
150 return MPP_OK;
151
152 MppBufferImpl *p = (MppBufferImpl*)buffer;
153 if (offset + size > p->info.size)
154 return MPP_ERR_VALUE;
155 if (NULL == p->info.ptr)
156 mpp_buffer_mmap(p, caller);
157
158 void *dst = p->info.ptr;
159 mpp_assert(dst != NULL);
160 if (dst)
161 memcpy((char*)dst + offset, data, size);
162
163 return MPP_OK;
164 }
165
mpp_buffer_get_ptr_with_caller(MppBuffer buffer,const char * caller)166 void *mpp_buffer_get_ptr_with_caller(MppBuffer buffer, const char *caller)
167 {
168 if (NULL == buffer) {
169 mpp_err("mpp_buffer_get_ptr invalid NULL input from %s\n", caller);
170 return NULL;
171 }
172
173 MppBufferImpl *p = (MppBufferImpl*)buffer;
174 if (NULL == p->info.ptr)
175 mpp_buffer_mmap(p, caller);
176
177 mpp_assert(p->info.ptr != NULL);
178 if (NULL == p->info.ptr)
179 mpp_err("mpp_buffer_get_ptr buffer %p ret NULL from %s\n", buffer, caller);
180
181 return p->info.ptr;
182 }
183
mpp_buffer_get_fd_with_caller(MppBuffer buffer,const char * caller)184 int mpp_buffer_get_fd_with_caller(MppBuffer buffer, const char *caller)
185 {
186 if (NULL == buffer) {
187 mpp_err("mpp_buffer_get_fd invalid NULL input from %s\n", caller);
188 return -1;
189 }
190
191 MppBufferImpl *p = (MppBufferImpl*)buffer;
192 int fd = p->info.fd;
193 mpp_assert(fd >= 0);
194 if (fd < 0)
195 mpp_err("mpp_buffer_get_fd buffer %p fd %d from %s\n", buffer, fd, caller);
196
197 return fd;
198 }
199
mpp_buffer_get_size_with_caller(MppBuffer buffer,const char * caller)200 size_t mpp_buffer_get_size_with_caller(MppBuffer buffer, const char *caller)
201 {
202 if (NULL == buffer) {
203 mpp_err("mpp_buffer_get_size invalid NULL input from %s\n", caller);
204 return 0;
205 }
206
207 MppBufferImpl *p = (MppBufferImpl*)buffer;
208 if (p->info.size == 0)
209 mpp_err("mpp_buffer_get_size buffer %p ret zero size from %s\n", buffer, caller);
210
211 return p->info.size;
212 }
213
mpp_buffer_get_index_with_caller(MppBuffer buffer,const char * caller)214 int mpp_buffer_get_index_with_caller(MppBuffer buffer, const char *caller)
215 {
216 if (NULL == buffer) {
217 mpp_err("mpp_buffer_get_index invalid NULL input from %s\n", caller);
218 return -1;
219 }
220
221 MppBufferImpl *p = (MppBufferImpl*)buffer;
222 return p->info.index;
223 }
224
mpp_buffer_set_index_with_caller(MppBuffer buffer,int index,const char * caller)225 MPP_RET mpp_buffer_set_index_with_caller(MppBuffer buffer, int index,
226 const char *caller)
227 {
228 if (NULL == buffer) {
229 mpp_err("mpp_buffer_set_index invalid NULL input from %s\n", caller);
230 return MPP_ERR_UNKNOW;
231 }
232
233 MppBufferImpl *p = (MppBufferImpl*)buffer;
234 p->info.index = index;
235 return MPP_OK;
236 }
237
mpp_buffer_get_offset_with_caller(MppBuffer buffer,const char * caller)238 size_t mpp_buffer_get_offset_with_caller(MppBuffer buffer, const char *caller)
239 {
240 if (NULL == buffer) {
241 mpp_err("mpp_buffer_get_offset invalid NULL input from %s\n", caller);
242 return -1;
243 }
244
245 MppBufferImpl *p = (MppBufferImpl*)buffer;
246 return p->offset;
247 }
248
mpp_buffer_set_offset_with_caller(MppBuffer buffer,size_t offset,const char * caller)249 MPP_RET mpp_buffer_set_offset_with_caller(MppBuffer buffer, size_t offset, const char *caller)
250 {
251 if (NULL == buffer) {
252 mpp_err("mpp_buffer_set_offset invalid NULL input from %s\n", caller);
253 return MPP_ERR_UNKNOW;
254 }
255
256 MppBufferImpl *p = (MppBufferImpl*)buffer;
257 p->offset = offset;
258 return MPP_OK;
259 }
260
mpp_buffer_info_get_with_caller(MppBuffer buffer,MppBufferInfo * info,const char * caller)261 MPP_RET mpp_buffer_info_get_with_caller(MppBuffer buffer, MppBufferInfo *info, const char *caller)
262 {
263 if (NULL == buffer || NULL == info) {
264 mpp_err("mpp_buffer_info_get invalid input buffer %p info %p from %s\n",
265 buffer, info, caller);
266 return MPP_ERR_UNKNOW;
267 }
268
269 MppBufferImpl *p = (MppBufferImpl*)buffer;
270 if (NULL == p->info.ptr)
271 mpp_buffer_mmap(p, caller);
272
273 *info = p->info;
274 (void)caller;
275 return MPP_OK;
276 }
277
check_buf_need_sync(MppBuffer buffer,MPP_RET * ret,const char * caller)278 static MPP_RET check_buf_need_sync(MppBuffer buffer, MPP_RET *ret, const char *caller)
279 {
280 if (NULL == buffer) {
281 mpp_err("check buffer found NULL pointer from %s\n", caller);
282 return MPP_NOK;
283 }
284
285 MppBufferImpl *impl = (MppBufferImpl *)buffer;
286
287 if (impl->info.fd <= 0) {
288 mpp_err("check fd found invalid fd %d from %s\n", impl->info.fd, caller);
289 return MPP_NOK;
290 }
291
292 /* uncached buffer do not need to sync */
293 if (impl->uncached) {
294 *ret = MPP_OK;
295 return MPP_NOK;
296 }
297
298 return MPP_OK;
299 }
300
mpp_buffer_sync_begin_f(MppBuffer buffer,RK_S32 ro,const char * caller)301 MPP_RET mpp_buffer_sync_begin_f(MppBuffer buffer, RK_S32 ro, const char* caller)
302 {
303 MPP_RET ret = MPP_NOK;
304
305 if (check_buf_need_sync(buffer, &ret, caller))
306 return ret;
307
308 MppBufferImpl *impl = (MppBufferImpl *)buffer;
309
310 return mpp_dmabuf_sync_begin(impl->info.fd, ro, caller);
311 }
312
mpp_buffer_sync_end_f(MppBuffer buffer,RK_S32 ro,const char * caller)313 MPP_RET mpp_buffer_sync_end_f(MppBuffer buffer, RK_S32 ro, const char* caller)
314 {
315 MPP_RET ret = MPP_NOK;
316
317 if (check_buf_need_sync(buffer, &ret, caller))
318 return ret;
319
320 MppBufferImpl *impl = (MppBufferImpl *)buffer;
321
322 return mpp_dmabuf_sync_end(impl->info.fd, ro, caller);
323 }
324
mpp_buffer_sync_partial_begin_f(MppBuffer buffer,RK_S32 ro,RK_U32 offset,RK_U32 length,const char * caller)325 MPP_RET mpp_buffer_sync_partial_begin_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller)
326 {
327 MPP_RET ret = MPP_NOK;
328
329 if (check_buf_need_sync(buffer, &ret, caller))
330 return ret;
331
332 MppBufferImpl *impl = (MppBufferImpl *)buffer;
333
334 return mpp_dmabuf_sync_partial_begin(impl->info.fd, ro, impl->offset + offset, length, caller);
335 }
336
mpp_buffer_sync_partial_end_f(MppBuffer buffer,RK_S32 ro,RK_U32 offset,RK_U32 length,const char * caller)337 MPP_RET mpp_buffer_sync_partial_end_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller)
338 {
339 MPP_RET ret = MPP_NOK;
340
341 if (check_buf_need_sync(buffer, &ret, caller))
342 return ret;
343
344 MppBufferImpl *impl = (MppBufferImpl *)buffer;
345
346 return mpp_dmabuf_sync_partial_end(impl->info.fd, ro, impl->offset + offset, length, caller);
347 }
348
mpp_buffer_group_get(MppBufferGroup * group,MppBufferType type,MppBufferMode mode,const char * tag,const char * caller)349 MPP_RET mpp_buffer_group_get(MppBufferGroup *group, MppBufferType type, MppBufferMode mode,
350 const char *tag, const char *caller)
351 {
352 if (NULL == group ||
353 mode >= MPP_BUFFER_MODE_BUTT ||
354 (type & MPP_BUFFER_TYPE_MASK) >= MPP_BUFFER_TYPE_BUTT) {
355 mpp_err_f("input invalid group %p mode %d type %d from %s\n",
356 group, mode, type, caller);
357 return MPP_ERR_UNKNOW;
358 }
359
360 return mpp_buffer_group_init((MppBufferGroupImpl**)group, tag, caller, mode, type);
361 }
362
mpp_buffer_group_put(MppBufferGroup group)363 MPP_RET mpp_buffer_group_put(MppBufferGroup group)
364 {
365 if (NULL == group) {
366 mpp_err_f("input invalid group %p\n", group);
367 return MPP_NOK;
368 }
369
370 return mpp_buffer_group_deinit((MppBufferGroupImpl *)group);
371 }
372
mpp_buffer_group_clear(MppBufferGroup group)373 MPP_RET mpp_buffer_group_clear(MppBufferGroup group)
374 {
375 if (NULL == group) {
376 mpp_err_f("input invalid group %p\n", group);
377 return MPP_NOK;
378 }
379
380 return mpp_buffer_group_reset((MppBufferGroupImpl *)group);
381 }
382
mpp_buffer_group_unused(MppBufferGroup group)383 RK_S32 mpp_buffer_group_unused(MppBufferGroup group)
384 {
385 if (NULL == group) {
386 mpp_err_f("input invalid group %p\n", group);
387 return MPP_NOK;
388 }
389
390 MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
391 RK_S32 unused = 0;
392
393 if (p->mode == MPP_BUFFER_INTERNAL) {
394 if (p->limit_count)
395 unused = p->limit_count - p->count_used;
396 else
397 unused = 3; /* NOTE: 3 for 1 decoding 2 deinterlace buffer */
398 } else
399 unused = p->count_unused;
400
401 return unused;
402 }
403
mpp_buffer_group_usage(MppBufferGroup group)404 size_t mpp_buffer_group_usage(MppBufferGroup group)
405 {
406 if (NULL == group) {
407 mpp_err_f("input invalid group %p\n", group);
408 return MPP_BUFFER_MODE_BUTT;
409 }
410
411 MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
412 return p->usage;
413 }
414
mpp_buffer_group_mode(MppBufferGroup group)415 MppBufferMode mpp_buffer_group_mode(MppBufferGroup group)
416 {
417 if (NULL == group) {
418 mpp_err_f("input invalid group %p\n", group);
419 return MPP_BUFFER_MODE_BUTT;
420 }
421
422 MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
423 return p->mode;
424 }
425
mpp_buffer_group_type(MppBufferGroup group)426 MppBufferType mpp_buffer_group_type(MppBufferGroup group)
427 {
428 if (NULL == group) {
429 mpp_err_f("input invalid group %p\n", group);
430 return MPP_BUFFER_TYPE_BUTT;
431 }
432
433 MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
434 return p->type;
435 }
436
mpp_buffer_group_limit_config(MppBufferGroup group,size_t size,RK_S32 count)437 MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count)
438 {
439 if (NULL == group) {
440 mpp_err_f("input invalid group %p\n", group);
441 return MPP_NOK;
442 }
443
444 MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
445 mpp_assert(p->mode == MPP_BUFFER_INTERNAL);
446 p->limit_size = size;
447 p->limit_count = count;
448 return MPP_OK;
449 }