xref: /rockchip-linux_mpp/mpp/base/mpp_buffer.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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 }