Files
gk-sdk/sample/live_rtsp_server/mbuffer/xcam_mbuf.c
T

859 lines
27 KiB
C
Executable File

/*
* Copyright (c) XCAM. All rights reserved.
*
* This file contains the media buffer implementations for media stream.
*/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include "list.h"
#include "xcam_log.h"
#include "xcam_mbuf.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
/*macro definition */
#define MBUF_DEBUG 0
#define MBUF_INFO(fmt...) XCAM_LOG_INFO_PRINT("MBUF", fmt)
#define MBUF_WARN(fmt...) XCAM_LOG_WARN_PRINT("MBUF", fmt)
#define MBUF_ERROR(fmt...) XCAM_LOG_ERR_PRINT("MBUF", fmt)
#define MBUF_FATAL(fmt...) XCAM_LOG_FATAL_PRINT("MBUF", fmt)
#define MBUF_ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define MBUF_PAYLOAD_READABLE 0x01
#define MBUF_PAYLOAD_WRITABLE 0x02
#define MBUF_INVALID_64BITS_PTS ((xcam_u64)(-1))
#define MBUF_MALLOC(addr) malloc(addr)
#define MBUF_FREE(addr) free(addr)
#define MBUF_MUTEX_LOCK(mutex) pthread_mutex_lock(&mutex)
#define MBUF_MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&mutex)
#define IS_READING(block) (MBUF_BLOCK_READING == block->block_status)
#define IS_WRITING(block) (MBUF_BLOCK_WRITING == block->block_status)
#define IS_FREE(block) (MBUF_BLOCK_FREE == block->block_status)
#define IS_HEAD_OF_LIST(block, inst) (&block->block_node == inst->block_head.next)
#define IS_FULL(inst, size) (inst->free < size)
#define MBUF_ASSERT_RETURN(condition, ret_value) \
do { \
if (!(condition)) { \
MBUF_WARN("[%s %d]assert warning\n",__func__,__LINE__); \
return ret_value; \
} \
}while(0)
#define MBUF_FIND_BLOCK_BY_ADDR(addr, inst, block) \
{ \
struct list_head* pos; \
struct list_head* n; \
cam_mbuf_block_info* tmp; \
list_for_each_safe(pos, n, &inst->block_head) { \
tmp = list_entry(pos, cam_mbuf_block_info, block_node); \
if (addr == tmp->addr) { \
block = tmp; \
break; \
} \
} \
}
#define MBUF_FREE_BLOCK_LIST(inst) \
{ \
struct list_head* pos; \
struct list_head* n; \
list_for_each_safe(pos, n, &inst->block_head) { \
list_del(pos); \
} \
}
#define MBUF_FIND_TAIL_BLOCK(inst, block) \
{ \
block = list_entry(inst->block_head.prev, cam_mbuf_block_info, block_node); \
}
#define MBUF_FIND_HEAD_BLOCK(inst, block) \
{ \
block = list_entry(inst->block_head.next, cam_mbuf_block_info, block_node); \
}
typedef enum {
MBUF_BLOCK_FREE = 0,
MBUF_BLOCK_READING,
MBUF_BLOCK_WRITING,
MBUF_BLOCK_BUTT
} cam_mbuf_block_status;
typedef struct {
xcam_u8 *addr; /* User virtual address */
xcam_u32 size; /* Buffer size, in the unit of byte */
} cam_mbuf_buf_info;
/* Describe a buffer block */
typedef struct {
xcam_u8 *addr; /* base address of block */
xcam_u32 size; /* size of block */
xcam_u64 pts;
xcam_u32 seq;
xcam_u16 payload_type; /* mbuffer data payload type */
xcam_u8 key_frame; /* is used to video */
xcam_u8 pack_count; /* pack_count < XCAM_MBUF_MAX_PACK */
xcam_u32 pack_size[XCAM_MBUF_MAX_PACK]; /* pack size of pre pack */
cam_mbuf_block_status block_status; /* Status of block */
struct list_head block_node; /* Block list node */
} cam_mbuf_block_info;
typedef struct {
xcam_u16 payload_type; /* mbuffer data payload type */
xcam_u8 mode; /* readable,writable */
xcam_u8 pad; /* reserved */
} cam_mbuf_payload_attr;
/* Describe a buffer instance */
typedef struct {
xcam_u8 *addr; /* Start user virtual address of the buffer instance */
xcam_u32 size; /* Size of the buffer instance */
xcam_u32 payload_count; /* payload type count of the mbuffer */
cam_mbuf_payload_attr *payload_attr; /* readable,writable of the payload */
xcam_u32 used; /* Used size */
xcam_u32 free; /* Free size */
xcam_u32 freeze; /* Freeze size */
pthread_mutex_t mutex_lock; /* mutex lock */
struct list_head block_head; /* Buffer manager block list head */
} cam_mbuf_inst;
/*static function */
static xcam_s32 cam_mbuf_get_write_buffer(xcam_handle *handle, cam_mbuf_buf_info *buf_info)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_block_info *block = XCAM_NULL;
cam_mbuf_block_info *block_head = XCAM_NULL;
xcam_u32 read_offset;
xcam_u32 write_offset;
xcam_u32 tail_free;
xcam_u32 head_free;
xcam_u32 acq_size;
xcam_bool is_alloc = XCAM_FALSE;
MBUF_ASSERT_RETURN(buf_info != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(buf_info->size > 0, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
/*Data align*/
buf_info->size = MBUF_ALIGN(buf_info->size,sizeof(xcam_u32));
/* Buffer full */
acq_size = buf_info->size + sizeof(cam_mbuf_block_info);
if (IS_FULL(buf_inst, acq_size)) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_BUFFER_FULL;
}
/* If empty, write from start */
if (list_empty(&buf_inst->block_head)) {
write_offset = read_offset = 0;
} else { /*Find write offset and read offset,only support one writer*/
MBUF_FIND_TAIL_BLOCK(buf_inst, block);
if (IS_WRITING(block)) {
buf_info->addr = block->addr + sizeof(cam_mbuf_block_info);
buf_info->size = block->size - sizeof(cam_mbuf_block_info);
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
MBUF_ERROR("mbuf block is busy:%p,size:%d\n",buf_info->addr,buf_info->size);
return XCAM_ERR_MBUF_BUSY;
}
write_offset = (xcam_u32)block->addr + block->size - (xcam_u32)buf_inst->addr;
MBUF_FIND_HEAD_BLOCK(buf_inst, block_head);
read_offset = (xcam_u32)block_head->addr - (xcam_u32)buf_inst->addr;
}
/* Reverse: write pointer before read pointer, the free area is continuous */
if (write_offset <= read_offset) {
is_alloc = XCAM_TRUE;
} else { /* Normal: write pointer after read pointer, the free area isn't continuous */
tail_free = buf_inst->size - write_offset;
head_free = buf_inst->free - tail_free;
if (tail_free >= acq_size) {
is_alloc = XCAM_TRUE;
} else if (head_free >= acq_size) {
is_alloc = XCAM_TRUE;
/* Alloc from head */
write_offset = 0;
/* Freeze the last area */
buf_inst->freeze = tail_free;
buf_inst->free -= tail_free;
}
}
/* Allocate fail, return */
if (!is_alloc) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_BUFFER_FULL;
}
/* Allocate new block,init block parameter*/
block = (cam_mbuf_block_info *)(buf_inst->addr + write_offset);
block->addr = (xcam_u8 *)block;
buf_info->addr = block->addr + sizeof(cam_mbuf_block_info);
block->size = acq_size;
block->pts = MBUF_INVALID_64BITS_PTS;
block->block_status = MBUF_BLOCK_WRITING;
/* Add block to list */
list_add_tail(&block->block_node, &buf_inst->block_head);
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
static xcam_s32 cam_mbuf_put_write_buffer(xcam_handle *handle, const xcam_mbuf_pack_info *pack_info, cam_mbuf_buf_info *buf_info)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_block_info *block = XCAM_NULL;
xcam_u32 write_size;
xcam_u8 i;
MBUF_ASSERT_RETURN(buf_info != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(buf_info->size > 0, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
/* Find the tail block */
MBUF_FIND_TAIL_BLOCK(buf_inst, block);
write_size = buf_info->size + sizeof(cam_mbuf_block_info);
if (write_size > block->size) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
MBUF_ERROR("Put size err:%d>%d\n", write_size, block->size);
return XCAM_ERR_MBUF_PUT_BUF_FAILED;
}
/* The block must be WRITING status and its address must be right */
if (IS_WRITING(block) && ((xcam_u32)(buf_info->addr - sizeof(cam_mbuf_block_info)) == (xcam_u32)block->addr)) {
/* If size=0, drop this block */
if (0 == buf_info->size) {
/* Delete block from list */
list_del(&block->block_node);
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
block->pts = pack_info->pts;
block->seq = pack_info->seq;
block->key_frame = pack_info->key_frame;
block->payload_type = pack_info->payload_type;
block->pack_count = pack_info->pack_count;
for (i = 0; i < pack_info->pack_count; i++) {
block->pack_size[i] = pack_info->pack_size[i];
}
block->block_status = MBUF_BLOCK_FREE;
} else {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
MBUF_ERROR("Put fail.\n");
return XCAM_ERR_MBUF_PUT_BUF_FAILED;
}
/* Manage instance */
buf_inst->used += write_size;
buf_inst->free -= write_size;
#if (MBUF_DEBUG == 1)
if (buf_inst->size != buf_inst->used + buf_inst->free + buf_inst->freeze) {
MBUF_FATAL("Error:unmatch, size:%d!= used:%d+free:%d+freeze:%d\n",buf_inst->size,buf_inst->used,
buf_inst->free,buf_inst->freeze);
}
#endif
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
static xcam_s32 cam_mbuf_acq_read_buffer(xcam_handle *handle, xcam_u16 payload_type, xcam_mbuf_pack_info *pack_info)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_block_info *buf_block = XCAM_NULL;
xcam_u32 offset;
xcam_u8 i;
MBUF_ASSERT_RETURN(pack_info != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
/* Buffer empty */
if ((0 == buf_inst->used) || (list_empty(&buf_inst->block_head))) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_BUFFER_EMPTY;
}
/* Find head block */
MBUF_FIND_HEAD_BLOCK(buf_inst, buf_block);
/* The block must be FREE status */
if (!IS_FREE(buf_block)) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_BUFFER_EMPTY;
}
/* Read from the block */
pack_info->pts = buf_block->pts;
pack_info->seq = buf_block->seq;
pack_info->key_frame = buf_block->key_frame;
pack_info->payload_type = buf_block->payload_type;
pack_info->pack_count = buf_block->pack_count;
offset = 0;
for (i = 0;i < pack_info->pack_count;i++) {
pack_info->pack_addr[i] = buf_block->addr + sizeof(cam_mbuf_block_info) + offset;
pack_info->pack_size[i] = buf_block->pack_size[i];
offset += buf_block->pack_size[i];
}
/* Change status */
buf_block->block_status = MBUF_BLOCK_READING;
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
static xcam_s32 cam_mbuf_read_buffer_over(xcam_handle *handle, xcam_u16 payload_type)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_block_info *block = XCAM_NULL;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
/* Find head block */
MBUF_FIND_HEAD_BLOCK(buf_inst, block);
if (XCAM_NULL == block) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_RELEASE_FAILED;
}
/* Change status */
if (IS_READING(block)) {
block->block_status = MBUF_BLOCK_FREE;
}
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
xcam_s32 cam_mbuf_release_read_buffer(xcam_handle *handle, cam_mbuf_buf_info *buf_info)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_block_info *block = XCAM_NULL;
MBUF_ASSERT_RETURN(buf_info != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
if (buf_info == XCAM_NULL) {
/* Find head block */
MBUF_FIND_HEAD_BLOCK(buf_inst, block);
} else {
/* Find block by address */
xcam_u8 *addr = buf_info->addr - sizeof(cam_mbuf_block_info);
MBUF_FIND_BLOCK_BY_ADDR(addr, buf_inst, block);
}
if (XCAM_NULL == block) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_READ_FAILED;
}
/* Unfreeze */
if ((0 != buf_inst->freeze) &&
(block->addr + block->size == buf_inst->addr + buf_inst->size - buf_inst->freeze)) {
buf_inst->free += buf_inst->freeze;
buf_inst->freeze = 0;
}
/* Only support free orderly */
if (IS_HEAD_OF_LIST(block, buf_inst) && IS_READING(block)) {
/* Change parameter of instance */
buf_inst->used -= block->size;
buf_inst->free += block->size;
/* Delete block from list */
list_del(&block->block_node);
} else {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_READ_FAILED;
}
#if (MBUF_DEBUG == 1)
if (buf_inst->size != buf_inst->used + buf_inst->free + buf_inst->freeze) {
MBUF_FATAL("Error:unmatch,size:%d!=used:%d+free:%d+freeze:%d\n",buf_inst->size,buf_inst->used,
buf_inst->free,buf_inst->freeze);
}
#endif
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
static xcam_s32 cam_mbuf_release_buffer(xcam_handle *handle, xcam_u16 payload_type)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_block_info *block = XCAM_NULL;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
/* Find head block */
MBUF_FIND_HEAD_BLOCK(buf_inst, block);
if (XCAM_NULL == block) {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_RELEASE_FAILED;
}
/* Unfreeze */
if ((0 != buf_inst->freeze) &&
(block->addr + block->size == buf_inst->addr + buf_inst->size - buf_inst->freeze)) {
buf_inst->free += buf_inst->freeze;
buf_inst->freeze = 0;
}
/* Only support free orderly */
if (IS_READING(block) || IS_FREE(block)) {
/* Change parameter of instance */
buf_inst->used -= block->size;
buf_inst->free += block->size;
/* Delete block from list */
list_del(&block->block_node);
} else {
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_ERR_MBUF_RELEASE_FAILED;
}
#if (MBUF_DEBUG == 1)
if (buf_inst->size != buf_inst->used + buf_inst->free + buf_inst->freeze) {
MBUF_FATAL("Error:unmatch,size:%d!=used:%d+free:%d+freeze:%d\n",buf_inst->size,buf_inst->used,
buf_inst->free,buf_inst->freeze);
}
#endif
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
static xcam_s32 cam_mbuf_reset(xcam_handle *handle)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
/* Free all block */
MBUF_FREE_BLOCK_LIST(buf_inst);
/* Set used/free/freeze size */
buf_inst->used = 0;
buf_inst->free = buf_inst->size;
buf_inst->freeze = 0;
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
static xcam_bool cam_mbuf_check_payload_valid(xcam_handle *handle, xcam_u16 payload_type, xcam_u8 rw_mode)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_payload_attr *attr;
xcam_bool ret = XCAM_FALSE;
xcam_s32 i;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_FALSE);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
buf_inst = (cam_mbuf_inst *)handle;
attr = (cam_mbuf_payload_attr *)buf_inst->payload_attr;
for (i = 0; i < buf_inst->payload_count; i++) {
if ((payload_type == XCAM_MBUF_PAYLOAD_TYPE_ALL) || (payload_type == attr[i].payload_type)) {
if ((attr[i].mode & rw_mode) == rw_mode) {
ret = XCAM_TRUE;
} else {
ret = XCAM_FALSE;
MBUF_ERROR("Payload type:%hu,mode:%hhu is invalid\n",payload_type,attr[i].mode);
}
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return ret;
}
}
MBUF_ERROR("Payload type:%hu not found\n",payload_type);
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return ret;
}
xcam_s32 xcam_mbuf_get_buffer(xcam_handle **handle, xcam_mbuf_cfg *buf_cfg)
{
xcam_u8* buf_addr;
cam_mbuf_inst* buf_inst = XCAM_NULL;
xcam_u32 attr_size;
int ret;
int i;
MBUF_ASSERT_RETURN(buf_cfg != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(buf_cfg->buf_size != 0, XCAM_ERR_MBUF_PARAM_INVALID);
if ((buf_cfg->payload_count == 0) || (buf_cfg->payload_count > XCAM_MBUF_MAX_PACK)) {
return XCAM_ERR_MBUF_PARAM_INVALID;
}
/* Allocate an instance */
attr_size = buf_cfg->payload_count * sizeof(cam_mbuf_payload_attr);
if ((buf_inst = (cam_mbuf_inst*)MBUF_MALLOC(sizeof(cam_mbuf_inst) + attr_size + buf_cfg->buf_size)) == XCAM_NULL) {
MBUF_FATAL("Malloc failed. need buff size=%d KB\n", buf_cfg->buf_size/1024);
return XCAM_ERR_MBUF_ALLOC_FAILED;
}
memset(buf_inst,0,sizeof(cam_mbuf_inst));
buf_addr = (xcam_u8 *)buf_inst + sizeof(cam_mbuf_inst) + attr_size;
/* Init instance parameter */
buf_inst->addr = buf_addr;
buf_inst->size = buf_cfg->buf_size;
buf_inst->payload_count = buf_cfg->payload_count;
buf_inst->payload_attr = (cam_mbuf_payload_attr *)((xcam_u8 *)buf_inst + sizeof(cam_mbuf_inst));
for (i = 0; i < buf_inst->payload_count; i++) {
buf_inst->payload_attr[i].payload_type = XCAM_MBUF_PAYLOAD_TYPE_INVALID;
buf_inst->payload_attr[i].mode = 0;
}
if ((ret = pthread_mutex_init(&buf_inst->mutex_lock,XCAM_NULL)) != 0) {
MBUF_FATAL("pthread_mutex_init error ret : %x\n",ret);
MBUF_FREE(buf_inst);
return XCAM_ERR_MBUF_MUTEX_INIT_FAILED;
}
/* Init block list parameter */
buf_inst->free = buf_inst->size;
buf_inst->freeze = 0;
buf_inst->used = 0;
INIT_LIST_HEAD(&buf_inst->block_head);
*handle = (xcam_void *)buf_inst;
return XCAM_SUCCESS;
}
xcam_s32 xcam_mbuf_release_buffer(xcam_handle *handle)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
/* If has blocks, free them */
if (!list_empty(&buf_inst->block_head)) {
MBUF_FREE_BLOCK_LIST(buf_inst);
}
/* Free resource */
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
MBUF_FREE(buf_inst);
return XCAM_SUCCESS;
}
xcam_s32 xcam_mbuf_register_payload(xcam_handle *handle, xcam_u16 payload_type)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_payload_attr *attr;
xcam_s32 i;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(payload_type != XCAM_MBUF_PAYLOAD_TYPE_INVALID, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
attr = (cam_mbuf_payload_attr *)buf_inst->payload_attr;
for (i = 0; i < buf_inst->payload_count; i++) {
if (attr[i].payload_type == XCAM_MBUF_PAYLOAD_TYPE_INVALID) {
attr[i].payload_type = payload_type;
attr[i].mode = MBUF_PAYLOAD_READABLE | MBUF_PAYLOAD_WRITABLE;
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
}
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
/*Register space is full*/
return XCAM_FAILURE;
}
xcam_s32 xcam_mbuf_unregister_payload(xcam_handle *handle, xcam_u16 payload_type)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_payload_attr *attr;
xcam_s32 i;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(payload_type != XCAM_MBUF_PAYLOAD_TYPE_INVALID, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
attr = (cam_mbuf_payload_attr *)buf_inst->payload_attr;
for (i = 0; i < buf_inst->payload_count; i++) {
if (attr[i].payload_type == payload_type) {
attr[i].payload_type = XCAM_MBUF_PAYLOAD_TYPE_INVALID;
attr[i].mode = 0;
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
}
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_FAILURE;
}
xcam_s32 xcam_mbuf_set_rw_enable(xcam_handle *handle, xcam_u16 payload_type, xcam_bool enable_read, xcam_bool enable_write)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_payload_attr *attr;
xcam_s32 i;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(payload_type != XCAM_MBUF_PAYLOAD_TYPE_INVALID, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
attr = (cam_mbuf_payload_attr *)buf_inst->payload_attr;
for (i = 0; i < buf_inst->payload_count; i++) {
if (attr[i].payload_type == payload_type) {
attr[i].mode = 0;
if (enable_read)
attr[i].mode |= MBUF_PAYLOAD_READABLE;
if (enable_write)
attr[i].mode |= MBUF_PAYLOAD_WRITABLE;
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
}
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
/*Not found payload type*/
return XCAM_ERR_MBUF_NOT_REGISTERED;
}
xcam_s32 xcam_mbuf_get_rw_enable(xcam_handle *handle, xcam_u16 payload_type, xcam_bool *enable_read, xcam_bool *enable_write)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_payload_attr *attr;
xcam_s32 i;
MBUF_ASSERT_RETURN(handle != XCAM_NULL, XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(payload_type != XCAM_MBUF_PAYLOAD_TYPE_INVALID, XCAM_ERR_MBUF_PARAM_INVALID);
*enable_read = XCAM_FALSE;
*enable_write = XCAM_FALSE;
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
attr = (cam_mbuf_payload_attr *)buf_inst->payload_attr;
for (i = 0; i < buf_inst->payload_count; i++) {
if (attr[i].payload_type == payload_type) {
if (attr[i].mode & MBUF_PAYLOAD_READABLE) {
*enable_read = XCAM_TRUE;
}
if (attr[i].mode & MBUF_PAYLOAD_WRITABLE) {
*enable_write = XCAM_TRUE;
}
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
}
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
/*Not found payload type*/
return XCAM_ERR_MBUF_NOT_REGISTERED;
}
xcam_s32 xcam_mbuf_write_pack(xcam_handle *handle, const xcam_mbuf_pack_info *pack_info)
{
xcam_u32 i = 0;
xcam_s32 ret;
cam_mbuf_buf_info buf_info;
xcam_u8 *write_addr;
xcam_u32 offset;
/*Check payload type and rw mode*/
if (!cam_mbuf_check_payload_valid(handle, pack_info->payload_type, MBUF_PAYLOAD_WRITABLE)) {
return XCAM_FAILURE;
}
memset(&buf_info,0,sizeof(cam_mbuf_buf_info));
for (i = 0; i < pack_info->pack_count; i++) {
buf_info.size += pack_info->pack_size[i];
}
/*Get write buffer space*/
ret = cam_mbuf_get_write_buffer(handle, &buf_info);
if (ret == XCAM_ERR_MBUF_BUFFER_FULL) {
MBUF_WARN("Mbuf is full!\n");
cam_mbuf_reset(handle);
ret = cam_mbuf_get_write_buffer(handle, &buf_info);
}
if (XCAM_SUCCESS != ret) {
return ret;
}
write_addr = buf_info.addr;
if (write_addr == XCAM_NULL) {
return XCAM_FAILURE;
}
/*Write package data to buffer space*/
offset = 0;
for (i = 0; i < pack_info->pack_count; i++)
{
memcpy(write_addr + offset, pack_info->pack_addr[i], pack_info->pack_size[i]);
offset += pack_info->pack_size[i];
}
/*Update buffer information*/
ret = cam_mbuf_put_write_buffer(handle,pack_info, &buf_info);
return ret;
}
xcam_s32 xcam_mbuf_read_pack(xcam_handle *handle, xcam_u16 payload_type, xcam_mbuf_pack_info *pack_info)
{
xcam_s32 ret = XCAM_SUCCESS;
/*Check payload type and rw mode*/
if (!cam_mbuf_check_payload_valid(handle, payload_type, MBUF_PAYLOAD_READABLE))
{
return XCAM_ERR_MBUF_PAYLOAD_CHECK_ERR;
}
ret = cam_mbuf_acq_read_buffer(handle, payload_type, pack_info);
return ret;
}
xcam_s32 xcam_mbuf_forward(xcam_handle *handle, xcam_u16 payload_type, xcam_u32 step)
{
xcam_s32 ret = XCAM_SUCCESS;
xcam_s32 i = 0;
/*Restore buffer status from reading to free*/
if (step == 0) {
ret = cam_mbuf_read_buffer_over(handle,payload_type);
return ret;
}
for (i = 0; i < step; i++) {
if ((ret = cam_mbuf_release_buffer(handle, payload_type)) != XCAM_SUCCESS) {
break;
}
}
return ret;
}
xcam_s32 xcam_mbuf_debug(xcam_handle *handle, xcam_u16 payload_type)
{
cam_mbuf_inst *buf_inst = XCAM_NULL;
cam_mbuf_block_info *block = XCAM_NULL;
cam_mbuf_payload_attr *attr;
struct list_head *pos;
struct list_head *n;
xcam_s32 i = 0;
MBUF_ASSERT_RETURN(handle != XCAM_NULL,XCAM_ERR_MBUF_PARAM_INVALID);
MBUF_ASSERT_RETURN(payload_type != XCAM_MBUF_PAYLOAD_TYPE_INVALID, XCAM_ERR_MBUF_PARAM_INVALID);
buf_inst = (cam_mbuf_inst *)handle;
MBUF_MUTEX_LOCK(buf_inst->mutex_lock);
MBUF_INFO("---------------------mbuf info-----------------------\n");
MBUF_INFO("addr:%p,size:%d =? total:%d(used:%d+free:%d+freeze:%d) \n", buf_inst->addr,buf_inst->size,
buf_inst->used+buf_inst->free+buf_inst->freeze,buf_inst->used,buf_inst->free,buf_inst->freeze);
attr = (cam_mbuf_payload_attr *)buf_inst->payload_attr;
MBUF_INFO("register info:\n");
for (i = 0; i < buf_inst->payload_count; i++) {
MBUF_INFO("i:%d,type:%d,mode:%d\n",i,attr[i].payload_type,attr[i].mode);
}
if (list_empty(&buf_inst->block_head)) {
MBUF_INFO("\tNone node\n");
} else {
list_for_each_safe(pos, n, &buf_inst->block_head)
{
block = list_entry(pos, cam_mbuf_block_info, block_node);
MBUF_INFO("\tNode %d: addr=%p size=%d status=%d\n", i++, block->addr, block->size,
block->block_status);
}
}
MBUF_INFO("----------------------------------------------------\n");
MBUF_MUTEX_UNLOCK(buf_inst->mutex_lock);
return XCAM_SUCCESS;
}
xcam_s32 xcam_mbuf_get_pack_data_offset(xcam_handle *handle, const xcam_mbuf_pack_info *pack_info, xcam_u32 *offset)
{
return 0;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */