[osal]: change mpp_buffer working flow and buffer limitation interface

git-svn-id: https://10.10.10.66:8443/svn/MediaProcessPlatform/trunk/mpp@136 6e48237b-75ef-9749-8fc9-41990f28c85a
This commit is contained in:
ChenHengming
2015-08-20 09:39:01 +00:00
parent 77632b3fa8
commit 2ac248839b
6 changed files with 208 additions and 53 deletions

View File

@@ -33,37 +33,69 @@
#define SZ_64M (SZ_1M*64) #define SZ_64M (SZ_1M*64)
#define SZ_80M (SZ_1M*80) #define SZ_80M (SZ_1M*80)
/*
* MppBuffer module has several functions:
*
* 1. buffer get / put / reference management / and external commit.
* this part is the basic user interface for MppBuffer.
*
* function:
*
* mpp_buffer_get
* mpp_buffer_put
* mpp_buffer_inc_ref
* mpp_buffer_commit
*
* 2. user buffer working flow control abstraction.
* buffer should attach to certain group, and buffer mode control the buffer usage flow.
* this part is also a part of user interface.
*
* function:
*
* mpp_buffer_group_get
* mpp_buffer_group_normal_get
* mpp_buffer_group_limit_get
* mpp_buffer_group_put
* mpp_buffer_group_limit_config
*
* 3. buffer allocator management
* this part is for allocator on different os, it does not have user interface
* it will support normal buffer, Android ion buffer, Linux v4l2 vb2 buffer
* user can only use MppBufferType to choose.
*
*/
typedef void* MppBuffer; typedef void* MppBuffer;
typedef void* MppBufferGroup; typedef void* MppBufferGroup;
/* /*
* mpp buffer pool support two buffer malloc mode: * mpp buffer group support two work flow mode:
* *
* native mode: all buffer are generated by mpp and buffer type can be read from MppBuffer * normal flow: all buffer are generated by MPP
* under this mode, buffer pool is maintained internally * under this mode, buffer pool is maintained internally
* *
* typical call flow: * typical call flow:
* *
* mpp_buffer_group_get() return A * mpp_buffer_group_get() return A
* mpp_buffer_get(A) return a ref +1 -> used * mpp_buffer_get(A) return a ref +1 -> used
* mpp_buffer_inc_ref(a) ref +1 * mpp_buffer_inc_ref(a) ref +1
* mpp_buffer_put(a) ref -1 * mpp_buffer_put(a) ref -1
* mpp_buffer_put(a) ref -1 -> unused * mpp_buffer_put(a) ref -1 -> unused
* mpp_buffer_group_put(A) * mpp_buffer_group_put(A)
* *
* commit mode: all buffer are commited out of mpp * commit flow: all buffer are commited out of MPP
* under this mode, buffer pool is controlled by external api * under this mode, buffers is commit by external api.
* normally MPP only use it but not generate it.
* *
* typical call flow: * typical call flow:
* *
* ==== external allocator ==== * ==== external allocator ====
* mpp_buffer_group_get() return A * mpp_buffer_group_get() return A
* mpp_buffer_commit(A, x) * mpp_buffer_commit(A, x)
* mpp_buffer_commit(A, y) * mpp_buffer_commit(A, y)
* *
* ======= internal user ====== * ======= internal user ======
* mpp_buffer_get(A) return a * mpp_buffer_get(A) return a
* mpp_buffer_get(A) return b * mpp_buffer_get(A) return b
* mpp_buffer_put(a) * mpp_buffer_put(a)
* mpp_buffer_put(b) * mpp_buffer_put(b)
* *
@@ -72,9 +104,27 @@ typedef void* MppBufferGroup;
* *
* NOTE: commit interface required group handle to record group information * NOTE: commit interface required group handle to record group information
*/ */
/*
* mpp buffer group has two buffer limit mode: normal and limit
*
* normal mode: allows any buffer size and always general new buffer is no unused buffer
* is available.
* This mode normally use with normal flow and is used for table / stream buffer
*
* limit mode : restrict the buffer's size and count in the buffer group. if try to calloc
* buffer with different size or extra count it will fail.
* This mode normally use with commit flow and is used for frame buffer
*/
/*
* NOTE: normal mode is recommanded to work with normal flow, working with limit mode is not.
* limit mode is recommanded to work with commit flow, working with normal mode is not.
*/
typedef enum { typedef enum {
MPP_BUFFER_MODE_NATIVE, MPP_BUFFER_MODE_NORMAL,
MPP_BUFFER_MODE_COMMIT, MPP_BUFFER_MODE_LIMIT,
MPP_BUFFER_MODE_BUTT,
} MppBufferMode; } MppBufferMode;
/* /*
@@ -86,6 +136,7 @@ typedef enum {
typedef enum { typedef enum {
MPP_BUFFER_TYPE_NORMAL, MPP_BUFFER_TYPE_NORMAL,
MPP_BUFFER_TYPE_ION, MPP_BUFFER_TYPE_ION,
MPP_BUFFER_TYPE_V4L2,
MPP_BUFFER_TYPE_BUTT, MPP_BUFFER_TYPE_BUTT,
} MppBufferType; } MppBufferType;
@@ -101,10 +152,16 @@ typedef struct {
MppBufferData data; MppBufferData data;
} MppBufferCommit; } MppBufferCommit;
#define BUFFER_GROUP_SIZE_DEFAULT (SZ_1M*80) #define BUFFER_GROUP_SIZE_DEFAULT (SZ_1M*80)
#define mpp_buffer_get(...) mpp_buffer_get_with_tag(MODULE_TAG, ## __VA_ARGS__) #define mpp_buffer_get(...) \
#define mpp_buffer_group_get(...) mpp_buffer_group_get_with_tag(MODULE_TAG, ## __VA_ARGS__) mpp_buffer_get_with_tag(MODULE_TAG, ## __VA_ARGS__)
#define mpp_buffer_group_normal_get(...) \
mpp_buffer_group_get(MODULE_TAG, MPP_BUFFER_MODE_NORMAL, ## __VA_ARGS__)
#define mpp_buffer_group_limited_get(...) \
mpp_buffer_group_get(MODULE_TAG, MPP_BUFFER_MODE_LIMIT, ## __VA_ARGS__)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -120,9 +177,9 @@ MPP_RET mpp_buffer_get_with_tag(const char *tag, MppBufferGroup group, MppBuffer
MPP_RET mpp_buffer_put(MppBuffer *buffer); MPP_RET mpp_buffer_put(MppBuffer *buffer);
MPP_RET mpp_buffer_inc_ref(MppBuffer buffer); MPP_RET mpp_buffer_inc_ref(MppBuffer buffer);
MPP_RET mpp_buffer_group_get_with_tag(const char *tag, MppBufferGroup *group, MppBufferType type); MPP_RET mpp_buffer_group_get(const char *tag, MppBufferMode mode, MppBufferGroup *group, MppBufferType type);
MPP_RET mpp_buffer_group_put(MppBufferGroup *group); MPP_RET mpp_buffer_group_put(MppBufferGroup *group);
MPP_RET mpp_buffer_group_set_limit(MppBufferGroup group, size_t limit); MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -81,15 +81,18 @@ MPP_RET mpp_buffer_inc_ref(MppBuffer buffer)
} }
MPP_RET mpp_buffer_group_get_with_tag(const char *tag, MppBufferGroup *group, MppBufferType type) MPP_RET mpp_buffer_group_get(const char *tag, MppBufferMode mode,
MppBufferGroup *group, MppBufferType type)
{ {
if (NULL == group || type >= MPP_BUFFER_TYPE_BUTT) { if (NULL == group ||
mpp_err("mpp_buffer_group_get input invalid group %p type %d\n", type >= MPP_BUFFER_MODE_BUTT ||
group, type); type >= MPP_BUFFER_TYPE_BUTT) {
mpp_err("mpp_buffer_group_get input invalid group %p mode %d type %d\n",
group, mode, type);
return MPP_ERR_UNKNOW; return MPP_ERR_UNKNOW;
} }
return mpp_buffer_group_init((MppBufferGroupImpl**)group, tag, type); return mpp_buffer_group_init((MppBufferGroupImpl**)group, tag, mode, type);
} }
MPP_RET mpp_buffer_group_put(MppBufferGroup *group) MPP_RET mpp_buffer_group_put(MppBufferGroup *group)
@@ -105,9 +108,18 @@ MPP_RET mpp_buffer_group_put(MppBufferGroup *group)
return mpp_buffer_group_deinit(p); return mpp_buffer_group_deinit(p);
} }
MPP_RET mpp_buffer_group_set_limit(MppBufferGroup group, size_t limit) MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count)
{ {
if (NULL == group || 0 == size || count <= 0) {
mpp_err("mpp_buffer_group_limit_config input invalid group %p size %d count %d\n",
group, size, count);
return MPP_NOK;
}
MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
return mpp_buffer_group_limit_reset(p, limit); mpp_assert(p->mode == MPP_BUFFER_MODE_LIMIT);
p->limit_size = size;
p->limit_count = count;
return MPP_OK;
} }

View File

@@ -75,16 +75,17 @@ MPP_RET deinit_buffer_no_lock(MppBufferImpl *buffer)
list_del_init(&buffer->list_status); list_del_init(&buffer->list_status);
MppBufferGroupImpl *group = SEARCH_GROUP_NORMAL(buffer->group_id); MppBufferGroupImpl *group = SEARCH_GROUP_NORMAL(buffer->group_id);
if (group) { if (group) {
if (MPP_BUFFER_MODE_NATIVE == buffer->mode) { if (MPP_BUFFER_MODE_NORMAL == buffer->mode) {
group->alloc_api->free(group->allocator, &buffer->data); group->alloc_api->free(group->allocator, &buffer->data);
} }
group->usage -= buffer->size; group->usage -= buffer->size;
} else { } else {
group = SEARCH_GROUP_ORPHAN(buffer->group_id); group = SEARCH_GROUP_ORPHAN(buffer->group_id);
mpp_assert(group); mpp_assert(group);
mpp_assert(buffer->mode == MPP_BUFFER_MODE_NATIVE); mpp_assert(buffer->mode == MPP_BUFFER_MODE_NORMAL);
group->alloc_api->free(group->allocator, &buffer->data); group->alloc_api->free(group->allocator, &buffer->data);
group->usage -= buffer->size; group->usage -= buffer->size;
group->count--;
if (0 == group->usage) if (0 == group->usage)
deinit_group_no_lock(group); deinit_group_no_lock(group);
} }
@@ -149,10 +150,10 @@ MPP_RET mpp_buffer_create(const char *tag, RK_U32 group_id, size_t size, MppBuff
} }
p->data = tmp; p->data = tmp;
p->mode = MPP_BUFFER_MODE_NATIVE; p->mode = MPP_BUFFER_MODE_NORMAL;
} else { } else {
p->data = *data; p->data = *data;
p->mode = MPP_BUFFER_MODE_COMMIT; p->mode = MPP_BUFFER_MODE_LIMIT;
} }
if (NULL == tag) if (NULL == tag)
@@ -161,11 +162,13 @@ MPP_RET mpp_buffer_create(const char *tag, RK_U32 group_id, size_t size, MppBuff
strncpy(p->tag, tag, sizeof(p->tag)); strncpy(p->tag, tag, sizeof(p->tag));
p->group_id = group_id; p->group_id = group_id;
p->size = size; p->size = size;
p->type = group->type;
p->used = 0; p->used = 0;
p->ref_count = 0; p->ref_count = 0;
INIT_LIST_HEAD(&p->list_status); INIT_LIST_HEAD(&p->list_status);
list_add_tail(&p->list_status, &group->list_unused); list_add_tail(&p->list_status, &group->list_unused);
group->usage += size; group->usage += size;
group->count++;
} else { } else {
mpp_free(p); mpp_free(p);
p = NULL; p = NULL;
@@ -248,7 +251,7 @@ MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size)
return buffer; return buffer;
} }
MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, MppBufferType type) MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, MppBufferMode mode, MppBufferType type)
{ {
MppBufferGroupImpl *p = mpp_malloc(MppBufferGroupImpl, 1); MppBufferGroupImpl *p = mpp_malloc(MppBufferGroupImpl, 1);
if (NULL == p) { if (NULL == p) {
@@ -266,9 +269,11 @@ MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, MppBu
list_add_tail(&p->list_group, &service.list_group); list_add_tail(&p->list_group, &service.list_group);
snprintf(p->tag, sizeof(p->tag), "%s_%d", tag, service.group_id); snprintf(p->tag, sizeof(p->tag), "%s_%d", tag, service.group_id);
p->mode = mode;
p->type = type; p->type = type;
p->limit = BUFFER_GROUP_SIZE_DEFAULT; p->limit = BUFFER_GROUP_SIZE_DEFAULT;
p->usage = 0; p->usage = 0;
p->count = 0;
p->group_id = service.group_id; p->group_id = service.group_id;
// avoid group_id reuse // avoid group_id reuse
@@ -314,7 +319,7 @@ MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p)
// if any buffer with mode MPP_BUFFER_MODE_COMMIT found it should be error // if any buffer with mode MPP_BUFFER_MODE_COMMIT found it should be error
MppBufferImpl *pos, *n; MppBufferImpl *pos, *n;
list_for_each_entry_safe(pos, n, &p->list_used, MppBufferImpl, list_status) { list_for_each_entry_safe(pos, n, &p->list_used, MppBufferImpl, list_status) {
mpp_assert(pos->mode != MPP_BUFFER_MODE_COMMIT); mpp_assert(pos->mode != MPP_BUFFER_MODE_LIMIT);
} }
} }
@@ -323,15 +328,3 @@ MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p)
return MPP_OK; return MPP_OK;
} }
MPP_RET mpp_buffer_group_limit_reset(MppBufferGroupImpl *p, size_t limit)
{
mpp_log("mpp_buffer_group %p limit reset from %u to %u\n", p->limit, limit);
MPP_BUFFER_SERVICE_LOCK();
p->limit = limit;
MPP_RET ret = check_buffer_group_limit(p);
MPP_BUFFER_SERVICE_UNLOCK();
return ret;
}

View File

@@ -37,10 +37,12 @@ typedef struct MppBufferGroupImpl_t MppBufferGroupImpl;
struct MppBufferImpl_t { struct MppBufferImpl_t {
char tag[MPP_TAG_SIZE]; char tag[MPP_TAG_SIZE];
RK_U32 group_id; RK_U32 group_id;
size_t size; MppBufferType type;
MppBufferData data;
MppBufferMode mode; MppBufferMode mode;
MppBufferData data;
size_t size;
// used flag is for used/unused list detection // used flag is for used/unused list detection
RK_U32 used; RK_U32 used;
RK_S32 ref_count; RK_S32 ref_count;
@@ -50,9 +52,15 @@ struct MppBufferImpl_t {
struct MppBufferGroupImpl_t { struct MppBufferGroupImpl_t {
char tag[MPP_TAG_SIZE]; char tag[MPP_TAG_SIZE];
RK_U32 group_id; RK_U32 group_id;
MppBufferMode mode;
MppBufferType type; MppBufferType type;
// used in limit mode only
size_t limit_size;
RK_S32 limit_count;
// status record
size_t limit; size_t limit;
size_t usage; size_t usage;
RK_S32 count;
MppAllocator allocator; MppAllocator allocator;
MppAllocatorApi *alloc_api; MppAllocatorApi *alloc_api;
@@ -100,9 +108,8 @@ MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer);
MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer); MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer);
MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size); MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size);
MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, MppBufferType type); MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, MppBufferMode mode, MppBufferType type);
MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p); MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p);
MPP_RET mpp_buffer_group_limit_reset(MppBufferGroupImpl *p, size_t limit);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -45,6 +45,81 @@ static int ion_close(int fd)
return ret; return ret;
} }
static int ion_ioctl(int fd, int req, void *arg)
{
int ret = ioctl(fd, req, arg);
if (ret < 0) {
mpp_err("ion_ioctl %x failed with code %d: %s\n", req,
ret, strerror(errno));
return -errno;
}
return ret;
}
static int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
unsigned int flags, ion_user_handle_t *handle)
{
int ret;
struct ion_allocation_data data = {
.len = len,
.align = align,
.heap_id_mask = heap_mask,
.flags = flags,
};
if (handle == NULL)
return -EINVAL;
ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
if (ret < 0)
return ret;
*handle = data.handle;
return ret;
}
static int ion_free(int fd, ion_user_handle_t handle)
{
struct ion_handle_data data = {
.handle = handle,
};
return ion_ioctl(fd, ION_IOC_FREE, &data);
}
static int ion_share(int fd, ion_user_handle_t handle, int *share_fd)
{
int map_fd;
int ret;
struct ion_fd_data data = {
.handle = handle,
};
if (share_fd == NULL)
return -EINVAL;
ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
if (ret < 0)
return ret;
*share_fd = data.fd;
if (*share_fd < 0) {
mpp_err("share ioctl returned negative fd\n");
return -EINVAL;
}
return ret;
}
static int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask,
unsigned int flags, int *handle_fd) {
ion_user_handle_t handle;
int ret;
ret = ion_alloc(fd, len, align, heap_mask, flags, &handle);
if (ret < 0)
return ret;
ret = ion_share(fd, handle, handle_fd);
ion_free(fd, handle);
return ret;
}
int os_allocator_open(void **ctx, size_t alignment) int os_allocator_open(void **ctx, size_t alignment)
{ {
allocator_ion *p = NULL; allocator_ion *p = NULL;

View File

@@ -34,6 +34,7 @@ int main()
void *commit_ptr[MPP_BUFFER_TEST_COMMIT_COUNT]; void *commit_ptr[MPP_BUFFER_TEST_COMMIT_COUNT];
MppBuffer normal_buffer[MPP_BUFFER_TEST_NORMAL_COUNT]; MppBuffer normal_buffer[MPP_BUFFER_TEST_NORMAL_COUNT];
size_t size = MPP_BUFFER_TEST_SIZE; size_t size = MPP_BUFFER_TEST_SIZE;
RK_S32 count = MPP_BUFFER_TEST_COMMIT_COUNT;
RK_S32 i; RK_S32 i;
mpp_log("mpp_buffer_test start\n"); mpp_log("mpp_buffer_test start\n");
@@ -42,18 +43,20 @@ int main()
memset(commit_buffer, 0, sizeof(commit_buffer)); memset(commit_buffer, 0, sizeof(commit_buffer));
memset(normal_buffer, 0, sizeof(normal_buffer)); memset(normal_buffer, 0, sizeof(normal_buffer));
ret = mpp_buffer_group_get(&group, MPP_BUFFER_TYPE_NORMAL); ret = mpp_buffer_group_limited_get(&group, MPP_BUFFER_TYPE_NORMAL);
if (MPP_OK != ret) { if (MPP_OK != ret) {
mpp_err("mpp_buffer_test mpp_buffer_group_get failed\n"); mpp_err("mpp_buffer_test mpp_buffer_group_get failed\n");
goto MPP_BUFFER_failed; goto MPP_BUFFER_failed;
} }
mpp_buffer_group_limit_config(group, size, count);
mpp_log("mpp_buffer_test commit mode start\n"); mpp_log("mpp_buffer_test commit mode start\n");
commit.type = MPP_BUFFER_TYPE_NORMAL; commit.type = MPP_BUFFER_TYPE_NORMAL;
commit.size = size; commit.size = size;
for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { for (i = 0; i < count; i++) {
commit_ptr[i] = malloc(size); commit_ptr[i] = malloc(size);
if (NULL == commit_ptr[i]) { if (NULL == commit_ptr[i]) {
mpp_err("mpp_buffer_test malloc failed\n"); mpp_err("mpp_buffer_test malloc failed\n");
@@ -69,7 +72,7 @@ int main()
} }
} }
for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { for (i = 0; i < count; i++) {
ret = mpp_buffer_get(group, &commit_buffer[i], size); ret = mpp_buffer_get(group, &commit_buffer[i], size);
if (MPP_OK != ret) { if (MPP_OK != ret) {
mpp_err("mpp_buffer_test mpp_buffer_get commit mode failed\n"); mpp_err("mpp_buffer_test mpp_buffer_get commit mode failed\n");
@@ -77,7 +80,7 @@ int main()
} }
} }
for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { for (i = 0; i < count; i++) {
ret = mpp_buffer_put(&commit_buffer[i]); ret = mpp_buffer_put(&commit_buffer[i]);
if (MPP_OK != ret) { if (MPP_OK != ret) {
mpp_err("mpp_buffer_test mpp_buffer_put commit mode failed\n"); mpp_err("mpp_buffer_test mpp_buffer_put commit mode failed\n");
@@ -85,17 +88,25 @@ int main()
} }
} }
for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { for (i = 0; i < count; i++) {
if (commit_ptr[i]) { if (commit_ptr[i]) {
free(commit_ptr[i]); free(commit_ptr[i]);
commit_ptr[i] = NULL; commit_ptr[i] = NULL;
} }
} }
mpp_buffer_group_put(&group);
mpp_log("mpp_buffer_test commit mode success\n"); mpp_log("mpp_buffer_test commit mode success\n");
mpp_log("mpp_buffer_test normal mode start\n"); mpp_log("mpp_buffer_test normal mode start\n");
ret = mpp_buffer_group_normal_get(&group, MPP_BUFFER_TYPE_NORMAL);
if (MPP_OK != ret) {
mpp_err("mpp_buffer_test mpp_buffer_group_get failed\n");
goto MPP_BUFFER_failed;
}
for (i = 0; i < MPP_BUFFER_TEST_NORMAL_COUNT; i++) { for (i = 0; i < MPP_BUFFER_TEST_NORMAL_COUNT; i++) {
ret = mpp_buffer_get(group, &normal_buffer[i], (i+1)*SZ_1K); ret = mpp_buffer_get(group, &normal_buffer[i], (i+1)*SZ_1K);
if (MPP_OK != ret) { if (MPP_OK != ret) {