Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
89
sdk/lib/multimedia/msi/fbpool.c
Normal file
89
sdk/lib/multimedia/msi/fbpool.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
|
||||
#ifdef MORE_SRAM
|
||||
#define FBPOOL_MALLOC os_malloc_psram
|
||||
#define FBPOOL_FREE os_free_psram
|
||||
#define FBPOOL_ZALLOC os_zalloc_psram
|
||||
#else
|
||||
#define FBPOOL_MALLOC os_malloc
|
||||
#define FBPOOL_FREE os_free
|
||||
#define FBPOOL_ZALLOC os_zalloc
|
||||
#endif
|
||||
|
||||
int32 fbpool_init(struct fbpool *pool, uint8 size)
|
||||
{
|
||||
uint8 i;
|
||||
if (pool && !pool->inited) {
|
||||
pool->pool = FBPOOL_ZALLOC(sizeof(struct framebuff) * size);
|
||||
ASSERT(pool->pool);
|
||||
pool->inited = 1;
|
||||
pool->size = size;
|
||||
for (i = 0; i < size; i++) {
|
||||
pool->pool[i].index = i;
|
||||
pool->pool[i].used = 0;
|
||||
pool->pool[i].pool = 1;
|
||||
}
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
struct framebuff *fbpool_get(struct fbpool *pool, uint16 type, struct msi *msi)
|
||||
{
|
||||
uint8 i;
|
||||
uint32 flag;
|
||||
struct framebuff *fb = NULL;
|
||||
|
||||
if (pool && pool->inited) {
|
||||
flag = disable_irq();
|
||||
for (i = 0; i < pool->size; i++) {
|
||||
if (!pool->pool[i].used) {
|
||||
fb = &pool->pool[i];
|
||||
fb->mtype = (type >> 8) & 0xff;
|
||||
fb->stype = type & 0xff;
|
||||
fb->msi = msi;
|
||||
fb->used = 1;
|
||||
fb->next = NULL;
|
||||
msi_get(fb->msi);
|
||||
atomic_inc(&fb->users); //GET 加1
|
||||
break;
|
||||
}
|
||||
}
|
||||
enable_irq(flag);
|
||||
}
|
||||
return fb;
|
||||
}
|
||||
|
||||
int32 fbpool_put(struct fbpool *pool, struct framebuff *fb)
|
||||
{
|
||||
uint32 flag;
|
||||
if (pool && pool->inited && fb && fb->pool &&
|
||||
(fb->index < pool->size) && (&pool->pool[fb->index] == fb)) {
|
||||
flag = disable_irq();
|
||||
pool->pool[fb->index].used = 0;
|
||||
pool->pool[fb->index].msi = NULL;
|
||||
pool->pool[fb->index].next = NULL;
|
||||
atomic_set(&fb->users,0);
|
||||
enable_irq(flag);
|
||||
return RET_OK;
|
||||
} else {
|
||||
os_printf(KERN_ERR"fbpool_put error, pool=%p, fb=%p\r\n", pool, fb);
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
int32 fbpool_destroy(struct fbpool *pool)
|
||||
{
|
||||
int32 i = 0;
|
||||
if (pool && pool->inited) {
|
||||
for (i = 0; i < pool->size; i++) {
|
||||
msi_discard_fb(pool->pool[i].msi, &pool->pool[i]);
|
||||
}
|
||||
FBPOOL_FREE(pool->pool);
|
||||
pool->inited = 0;
|
||||
pool->size = 0;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
268
sdk/lib/multimedia/msi/fbqueue.c
Normal file
268
sdk/lib/multimedia/msi/fbqueue.c
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#ifdef MORE_SRAM
|
||||
#define FBQ_MALLOC os_malloc_psram
|
||||
#define FBQ_FREE os_free_psram
|
||||
#define FBQ_ZALLOC os_zalloc_psram
|
||||
#else
|
||||
#define FBQ_MALLOC os_malloc
|
||||
#define FBQ_FREE os_free
|
||||
#define FBQ_ZALLOC os_zalloc
|
||||
#endif
|
||||
|
||||
int32 fbq_init(struct fbqueue *q, uint8 *qbuff, int32 qsize)
|
||||
{
|
||||
if (qbuff == NULL && qsize) {
|
||||
qbuff = (uint8 *)FBQ_MALLOC(sizeof(struct framebuff *) * (qsize + 1));
|
||||
q->alloc = 1;
|
||||
}
|
||||
|
||||
ASSERT(qbuff);
|
||||
if (qbuff && qsize) {
|
||||
RB_INIT_R(&q->rbQ, (qsize + 1), (struct framebuff **)qbuff);
|
||||
os_sema_init(&q->sema, 0);
|
||||
q->reader_max = 1;
|
||||
q->readers = NULL;
|
||||
q->init = 1;
|
||||
return RET_OK;
|
||||
}
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
int32 fbq_destory(struct fbqueue *q)
|
||||
{
|
||||
if (q && q->init) {
|
||||
while (RB_COUNT(&q->rbQ)) {
|
||||
fb_put(fbq_dequeue(q, 0));
|
||||
}
|
||||
if (q->alloc) {
|
||||
FBQ_FREE(q->rbQ.rbq);
|
||||
}
|
||||
if (q->readers) {
|
||||
FBQ_FREE(q->readers);
|
||||
}
|
||||
os_sema_del(&q->sema);
|
||||
q->init = 0;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 fbq_enqueue(struct fbqueue *q, struct framebuff *fb)
|
||||
{
|
||||
int32 ret;
|
||||
uint32 i;
|
||||
uint32 rpos;
|
||||
uint32 flags;
|
||||
struct framebuff *last = NULL;
|
||||
|
||||
if (!q || !q->init || !fb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fb_get(fb);
|
||||
|
||||
if (q->reader_max > 1) {
|
||||
flags = disable_irq();
|
||||
if (RB_FULL(&q->rbQ)) { // FULL ! move rpos.
|
||||
last = q->rbQ.rbq[q->rbQ.rpos];
|
||||
rpos = RB_NPOS(&q->rbQ, rpos, 1);
|
||||
for (i = 0; i < q->reader_max; i++) {
|
||||
if (q->readers[i] == q->rbQ.rpos) {
|
||||
q->readers[i] = rpos;
|
||||
}
|
||||
}
|
||||
q->rbQ.rpos = rpos;
|
||||
}
|
||||
q->rbQ.rbq[q->rbQ.wpos] = fb;
|
||||
q->rbQ.wpos = RB_NPOS(&q->rbQ, wpos, 1);
|
||||
enable_irq(flags);
|
||||
|
||||
fb_put(last);
|
||||
return 1;
|
||||
} else {
|
||||
ret = RB_INT_SET(&q->rbQ, fb);
|
||||
if (ret) {
|
||||
os_sema_up(&q->sema);
|
||||
return 1;
|
||||
} else {
|
||||
fb_put(fb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32 fbq_trace_pos(struct fbqueue *q, struct framebuff *fb, uint32 start, uint32 end, int8 discard)
|
||||
{
|
||||
uint32 pos;
|
||||
for (pos = start; pos < end; pos++) {
|
||||
if (q->rbQ.rbq[pos] == fb) {
|
||||
if (discard) {
|
||||
q->rbQ.rbq[pos] = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 fbq_trace(struct fbqueue *q, struct framebuff *fb, int8 discard)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
uint32 flag;
|
||||
|
||||
if (!q || !q->init || !fb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
flag = disable_irq();
|
||||
if (q->rbQ.rpos <= q->rbQ.wpos) {
|
||||
ret = fbq_trace_pos(q, fb, q->rbQ.rpos, q->rbQ.wpos, discard);
|
||||
} else {
|
||||
ret = fbq_trace_pos(q, fb, 0, q->rbQ.wpos, discard);
|
||||
if (!ret) {
|
||||
ret = fbq_trace_pos(q, fb, q->rbQ.rpos, q->rbQ.qsize, discard);
|
||||
}
|
||||
}
|
||||
enable_irq(flag);
|
||||
|
||||
if (ret && discard) {
|
||||
fb_put(fb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct framebuff *fbq_dequeue(struct fbqueue *q, uint32 tmo_ms)
|
||||
{
|
||||
uint64 jiff;
|
||||
struct framebuff *fb;
|
||||
|
||||
if (!q || !q->init) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
if (!RB_EMPTY(&q->rbQ)) {
|
||||
RB_GET(&q->rbQ, fb);
|
||||
return fb;
|
||||
}
|
||||
|
||||
if(tmo_ms == 0){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jiff = os_jiffies();
|
||||
os_sema_down(&q->sema, tmo_ms);
|
||||
jiff = DIFF_JIFFIES(jiff, os_jiffies());
|
||||
jiff = os_jiffies_to_msecs(jiff);
|
||||
if (jiff >= tmo_ms) {
|
||||
break;
|
||||
}
|
||||
|
||||
tmo_ms -= jiff;
|
||||
} while (tmo_ms);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct framebuff *fbq_dequeue_r(struct fbqueue *q, uint8 reader)
|
||||
{
|
||||
uint32 i = 0;
|
||||
uint32 pos;
|
||||
uint32 flags;
|
||||
struct framebuff *fb = NULL;
|
||||
struct framebuff *last = NULL;
|
||||
|
||||
if (!q || !q->init) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSERT(reader > 0 && reader <= q->reader_max);
|
||||
ASSERT(q->readers[reader - 1] != 0xffffffff);
|
||||
|
||||
reader -= 1;
|
||||
flags = disable_irq();
|
||||
pos = q->readers[reader];
|
||||
|
||||
if (pos == q->rbQ.wpos) { //no fb for this reader
|
||||
enable_irq(flags);
|
||||
return fb;
|
||||
}
|
||||
|
||||
fb = q->rbQ.rbq[pos];
|
||||
q->readers[reader] = NEXT_RPOS(pos, q->rbQ.qsize, 1);
|
||||
|
||||
//move rpos: find min pos.
|
||||
pos = 0xffffffff;
|
||||
for (i = 0; i < q->reader_max; i++) {
|
||||
if (q->readers[i] < pos) {
|
||||
pos = q->readers[i];
|
||||
}
|
||||
}
|
||||
if (pos != 0xffffffff && q->rbQ.rpos != pos) {
|
||||
last = q->rbQ.rbq[q->rbQ.rpos];
|
||||
q->rbQ.rpos = pos;
|
||||
}
|
||||
|
||||
fb_get(fb);
|
||||
enable_irq(flags);
|
||||
|
||||
fb_put(last);
|
||||
return fb;
|
||||
}
|
||||
|
||||
int32 fbq_conf_readers(struct fbqueue *q, uint16 reader_max)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 *ptr;
|
||||
|
||||
if (!q || !q->init || reader_max <= 1 || q->readers) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ptr = (uint32 *)FBQ_MALLOC(reader_max * sizeof(uint32));
|
||||
if (ptr) {
|
||||
for (i = 0; i < q->reader_max; i++) {
|
||||
q->readers[i] = 0xffffffff;
|
||||
}
|
||||
q->readers = ptr;
|
||||
q->reader_max = reader_max;
|
||||
return RET_OK;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int32 fbq_open_reader(struct fbqueue *q)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 flags;
|
||||
|
||||
if (!q || !q->init || !q->readers) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
flags = disable_irq();
|
||||
for (i = 0; i < q->reader_max; i++) {
|
||||
if (q->readers[i] == 0xffffffff) {
|
||||
q->readers[i] = q->rbQ.rpos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
return i < q->reader_max ? (i + 1) : 0;
|
||||
}
|
||||
|
||||
int32 fbq_close_reader(struct fbqueue *q, uint8 reader)
|
||||
{
|
||||
uint32 flags;
|
||||
|
||||
if (!q || !q->init || !q->readers) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ASSERT(reader > 0 && reader <= q->reader_max);
|
||||
flags = disable_irq();
|
||||
q->readers[reader - 1] = 0xffffffff;
|
||||
enable_irq(flags);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
148
sdk/lib/multimedia/msi/framebuff.c
Normal file
148
sdk/lib/multimedia/msi/framebuff.c
Normal file
@@ -0,0 +1,148 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
static void fb_free(struct framebuff *fb)
|
||||
{
|
||||
int32 ret = 0;
|
||||
struct msi *msi;
|
||||
|
||||
if (fb) {
|
||||
ASSERT(atomic_read(&fb->users) > 0);
|
||||
if (!atomic_dec_and_test(&fb->users)) {
|
||||
return;
|
||||
}
|
||||
|
||||
msi = fb->msi;
|
||||
ret = msi_do_cmd(fb->msi, MSI_CMD_FREE_FB, (uint32)fb, 0);
|
||||
msi_put(msi);
|
||||
if (ret == RET_OK) { //不等于OK表示模块自己管理fb,例如预分配的fb
|
||||
ASSERT(!fb->pool); //预分配的framebuff不能执行到这里
|
||||
FB_FREE(fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//framebuff 引用计数加1
|
||||
void fb_get(struct framebuff *fb)
|
||||
{
|
||||
if (fb) {
|
||||
fb_get(fb->next);
|
||||
atomic_inc(&fb->users);
|
||||
}
|
||||
}
|
||||
|
||||
struct framebuff *fb_alloc(uint8 *data, int32 size, uint16 type, struct msi *msi)
|
||||
{
|
||||
int32 len = data ? 0 : size;
|
||||
struct framebuff *fb = FB_ALLOC(sizeof(struct framebuff) + len);
|
||||
if (fb) {
|
||||
os_memset(fb, 0, sizeof(struct framebuff));
|
||||
atomic_set(&fb->users, 1);
|
||||
fb->len = size;
|
||||
fb->msi = msi;
|
||||
fb->mtype = (type >> 8) & 0xff;
|
||||
fb->stype = type & 0xff;
|
||||
msi_get(fb->msi);
|
||||
if (data) {
|
||||
fb->data = data;
|
||||
} else if (size) {
|
||||
fb->data = (uint8 *)(fb + 1);
|
||||
}
|
||||
}
|
||||
return fb;
|
||||
}
|
||||
|
||||
struct framebuff *fb_clone(struct framebuff *fb, uint16 type, struct msi *msi)
|
||||
{
|
||||
struct framebuff *fb_n = FB_ALLOC(sizeof(struct framebuff));
|
||||
if (fb_n) {
|
||||
os_memset(fb_n, 0, sizeof(struct framebuff));
|
||||
atomic_set(&fb_n->users, 1);
|
||||
fb_n->clone = 1;
|
||||
fb_n->msi = msi;
|
||||
fb_n->mtype = (type >> 8) & 0xff;
|
||||
fb_n->stype = type & 0xff;
|
||||
msi_get(fb_n->msi);
|
||||
fb_n->data = fb->data;
|
||||
fb_n->len = fb->len;
|
||||
fb_n->time = fb->time;
|
||||
fb_n->priv = fb->priv;
|
||||
fb_n->srcID = fb->srcID;
|
||||
fb_n->datatag = fb->datatag;
|
||||
fb_get(fb);
|
||||
fb_n->next = fb;
|
||||
}
|
||||
return fb_n;
|
||||
}
|
||||
|
||||
//framebuff 引用计数减1,当计数减至0时会释放空间
|
||||
void fb_put(struct framebuff *fb)
|
||||
{
|
||||
if (fb) {
|
||||
fb_put(fb->next);
|
||||
fb_free(fb);
|
||||
}
|
||||
}
|
||||
|
||||
//使用新的framebuff引用关联另1个framebuff,fb_old引用计数加1
|
||||
void fb_ref(struct framebuff *fb_new, struct framebuff *fb_old)
|
||||
{
|
||||
ASSERT(fb_new->next == NULL);
|
||||
fb_get(fb_old);
|
||||
fb_new->next = fb_old;
|
||||
}
|
||||
|
||||
//获取framebuff链表中指定type的数据的第1个节点
|
||||
struct framebuff *fb_find(struct framebuff *fb, uint8 mtype, uint8 stype)
|
||||
{
|
||||
if (mtype == 0 || fb == NULL || fb->next == NULL) {
|
||||
return fb;
|
||||
}
|
||||
|
||||
while (fb) {
|
||||
if (fb->mtype == mtype && (fb->stype == stype || stype == 0)) {
|
||||
return fb;
|
||||
}
|
||||
fb = fb->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//获取framebuff链表中指定type的数据的总长度
|
||||
uint32 fb_len(struct framebuff *fb, uint8 mtype, uint8 stype)
|
||||
{
|
||||
uint32 len = 0;
|
||||
|
||||
if (mtype == 0 || fb == NULL) {
|
||||
return fb ? fb->len : 0;
|
||||
}
|
||||
|
||||
if (fb->mtype != mtype) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fb) {
|
||||
if (fb->mtype == mtype && (fb->stype == stype || stype == 0)) {
|
||||
len += fb->len;
|
||||
}
|
||||
fb = fb->next;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
//根据fb->mtype 识别fb携带的数据为 视频,音频,图片,字幕
|
||||
MEDIA_DATA_CATEGORY fb_category(struct framebuff *fb)
|
||||
{
|
||||
if (fb->mtype < 32) { //video
|
||||
return MEDIA_DATA_VIDEO;
|
||||
} else if (fb->mtype < 64) { //audio
|
||||
return MEDIA_DATA_AUDIO;
|
||||
} else if (fb->mtype < 96) { //picture
|
||||
return MEDIA_DATA_PICTURE;
|
||||
} else if (fb->mtype < 128) { //text
|
||||
return MEDIA_DATA_TEXT;
|
||||
} else {
|
||||
return MEDIA_DATA_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
463
sdk/lib/multimedia/msi/msi.c
Normal file
463
sdk/lib/multimedia/msi/msi.c
Normal file
@@ -0,0 +1,463 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
#define MSI_MATCH(msi, name) (os_strcmp((msi)->name, name)==0)
|
||||
|
||||
//媒体流组件列表
|
||||
struct msi_core {
|
||||
struct msi *list;
|
||||
struct os_mutex lock;
|
||||
} g_MSI;
|
||||
|
||||
static void msi_free(struct msi *msi);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//局部函数
|
||||
|
||||
void msi_get(struct msi *msi)
|
||||
{
|
||||
if (msi) {
|
||||
atomic_inc(&msi->users);
|
||||
}
|
||||
}
|
||||
|
||||
void msi_put(struct msi *msi)
|
||||
{
|
||||
uint32 bound;
|
||||
uint32 inited;
|
||||
if (msi) {
|
||||
ASSERT(atomic_read(&msi->users) > 0);
|
||||
bound = atomic_read(&msi->bound);
|
||||
inited = atomic_read(&msi->inited);
|
||||
if (atomic_dec_and_test(&msi->users) && inited == 0) {
|
||||
msi_do_cmd(msi, MSI_CMD_POST_DESTROY, 0, 0);
|
||||
msi->priv = NULL;
|
||||
msi->action = NULL;
|
||||
fbq_destory(&msi->fbQ);
|
||||
if (bound == 0) {
|
||||
msi_free(msi);
|
||||
}else{
|
||||
msi->deleted = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32 msi_bound(struct msi *msi, struct msi *o_if)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MSI_OUTIF_MAX; i++) {
|
||||
if (msi->output_list[i] == o_if) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32 msi_bind(struct msi *msi, struct msi *o_if)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (msi_bound(msi, o_if)) {
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
for (i = 0; i < MSI_OUTIF_MAX; i++) {
|
||||
if (msi->output_list[i] == NULL) {
|
||||
atomic_inc(&o_if->bound);
|
||||
msi->output_list[i] = o_if;
|
||||
return RET_OK;
|
||||
}
|
||||
}
|
||||
|
||||
os_printf(KERN_ERR"msi %s bind %s fail!\r\n", msi->name, o_if->name);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
static int32 msi_unbind(struct msi *msi, struct msi *o_if)
|
||||
{
|
||||
int i;
|
||||
uint32 flag;
|
||||
uint32 users;
|
||||
struct msi *out;
|
||||
|
||||
for (i = 0; i < MSI_OUTIF_MAX; i++) {
|
||||
flag = disable_irq();
|
||||
out = msi->output_list[i];
|
||||
if (out && (out == o_if || o_if == NULL)) {
|
||||
msi->output_list[i] = NULL;
|
||||
enable_irq(flag);
|
||||
|
||||
users = atomic_read(&out->users);
|
||||
if (atomic_dec_and_test(&out->bound) && users == 0) {
|
||||
msi_free(out); //引用计数 和 绑定计数都等于0,释放msi
|
||||
}
|
||||
|
||||
if (o_if) {
|
||||
return RET_OK;
|
||||
}
|
||||
}
|
||||
enable_irq(flag);
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
//该函数需要在lock保护下执行
|
||||
static struct msi *msi_find_lock(const char *name)
|
||||
{
|
||||
uint32 flag = disable_irq();
|
||||
struct msi *msi = g_MSI.list;
|
||||
while (msi) {
|
||||
if (MSI_MATCH(msi, name)) {
|
||||
break;
|
||||
}
|
||||
msi = msi->next;
|
||||
}
|
||||
enable_irq(flag);
|
||||
return msi;
|
||||
}
|
||||
|
||||
//该函数需要在lock保护下执行
|
||||
static void msi_list_add(struct msi *msi)
|
||||
{
|
||||
uint32 flag = disable_irq();
|
||||
msi->next = g_MSI.list;
|
||||
g_MSI.list = msi;
|
||||
enable_irq(flag);
|
||||
}
|
||||
|
||||
//该函数需要在lock保护下执行
|
||||
static int32 msi_list_del(struct msi *msi)
|
||||
{
|
||||
struct msi *ptr, *prev;
|
||||
uint32 flag = disable_irq();
|
||||
prev = NULL;
|
||||
ptr = g_MSI.list;
|
||||
while (ptr) {
|
||||
if (ptr == msi) {
|
||||
if (prev) {
|
||||
prev->next = ptr->next;
|
||||
} else {
|
||||
g_MSI.list = ptr->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
enable_irq(flag);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
//该函数需要在lock保护下执行
|
||||
static void msi_notify_up(struct msi *msi, uint32 cmd, uint32 param1, uint32 param2)
|
||||
{
|
||||
struct msi *ptr = g_MSI.list;
|
||||
while (ptr) {
|
||||
if (ptr != msi && msi_bound(ptr, msi)) {
|
||||
msi_do_cmd(ptr, cmd, param1, param2);
|
||||
msi_notify_up(ptr, cmd, param1, param2);
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
//该函数需要在lock保护下执行
|
||||
static struct msi *msi_new_lock(const char *name)
|
||||
{
|
||||
struct msi *msi = msi_find_lock(name);
|
||||
if (msi == NULL) {
|
||||
msi = os_zalloc(sizeof(struct msi));
|
||||
if (msi) {
|
||||
msi->name = name;
|
||||
msi_list_add(msi);
|
||||
}
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
|
||||
static void msi_free(struct msi *msi)
|
||||
{
|
||||
if (msi) {
|
||||
msi_list_del(msi);
|
||||
msi_unbind(msi, NULL); //取消所有关联的组件
|
||||
os_free(msi);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//全局函数
|
||||
struct msi *msi_new(const char *name, uint32 qsize, uint8 *isnew)
|
||||
{
|
||||
struct msi *msi;
|
||||
|
||||
os_mutex_lock(&g_MSI.lock, osWaitForever);
|
||||
msi = msi_new_lock(name);
|
||||
if(msi && msi->deleted){
|
||||
os_printf(KERN_ERR"msi %s destory running ....\r\n", name);
|
||||
msi = NULL;
|
||||
}
|
||||
|
||||
if (msi) {
|
||||
if(isnew) {
|
||||
*isnew = msi->inited.counter == 0;
|
||||
}
|
||||
atomic_inc(&msi->inited);
|
||||
atomic_inc(&msi->users);
|
||||
if (!msi->fbQ.init && qsize) {
|
||||
fbq_init(&msi->fbQ, NULL, qsize+1);
|
||||
}
|
||||
}
|
||||
os_mutex_unlock(&g_MSI.lock);
|
||||
return msi;
|
||||
}
|
||||
|
||||
void msi_destroy(struct msi *msi)
|
||||
{
|
||||
if (msi) {
|
||||
os_printf(KERN_ERR"msi %s destory, lr:%x\r\n", msi->name, RETURN_ADDR());
|
||||
os_mutex_lock(&g_MSI.lock, osWaitForever);
|
||||
if(atomic_dec_and_test(&msi->inited)){
|
||||
msi->enable = 0;
|
||||
msi->deleted = 1;
|
||||
msi_do_cmd(msi, MSI_CMD_PRE_DESTROY, 0, 0);
|
||||
msi_put(msi);
|
||||
}else{
|
||||
atomic_dec(&msi->users);
|
||||
}
|
||||
os_mutex_unlock(&g_MSI.lock);
|
||||
}
|
||||
}
|
||||
|
||||
//根据ID查找是否存在该组件,引用计数为加1,使用后需要执行 msi_put
|
||||
struct msi *msi_find(const char *name, uint8 inited)
|
||||
{
|
||||
struct msi *msi;
|
||||
|
||||
if(name == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_mutex_lock(&g_MSI.lock, osWaitForever);
|
||||
msi = msi_find_lock(name);
|
||||
if(msi && inited && atomic_read(&msi->inited) == 0){
|
||||
msi = NULL;
|
||||
}else{
|
||||
|
||||
msi_get(msi);
|
||||
}
|
||||
os_mutex_unlock(&g_MSI.lock);
|
||||
return msi;
|
||||
}
|
||||
|
||||
//设置该组件的输出组件
|
||||
int32 msi_add_output(struct msi *msi, const char *lname, const char *oname)
|
||||
{
|
||||
int32 ret = RET_ERR;
|
||||
struct msi *l_msi, *o_msi;
|
||||
|
||||
os_mutex_lock(&g_MSI.lock, osWaitForever);
|
||||
l_msi = msi ? msi : msi_new_lock(lname);
|
||||
o_msi = msi_new_lock(oname);
|
||||
if (l_msi && o_msi) {
|
||||
ret = msi_bind(l_msi, o_msi);
|
||||
}
|
||||
os_mutex_unlock(&g_MSI.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//删除该组件的输出组件
|
||||
int32 msi_del_output(struct msi *msi, const char *lname, const char *oname)
|
||||
{
|
||||
int32 ret = RET_ERR;
|
||||
struct msi *l_msi, *o_msi;
|
||||
|
||||
os_mutex_lock(&g_MSI.lock, osWaitForever);
|
||||
l_msi = msi ? msi : msi_find(lname, 0);
|
||||
o_msi = msi_find(oname, 0);
|
||||
if (l_msi && o_msi) {
|
||||
ret = msi_unbind(l_msi, o_msi);
|
||||
}
|
||||
|
||||
if(msi == NULL){
|
||||
msi_put(l_msi);
|
||||
}
|
||||
msi_put(o_msi);
|
||||
os_mutex_unlock(&g_MSI.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//组件输出cmd: 遍历自己的输出组件列表,调用输出组件的 action 接口
|
||||
int32 msi_output_cmd(struct msi *msi, uint32 cmd, uint32 param1, uint32 param2)
|
||||
{
|
||||
int8 i;
|
||||
|
||||
if(!msi){
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
for (i = 0; i < MSI_OUTIF_MAX; i++) {
|
||||
msi_do_cmd(msi->output_list[i], cmd, param1, param2);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
//组件输出framebuff: 输出framebuff给自己的组件列表
|
||||
//注意:fb参数只能是 framebuff链表的第1个节点,不能是中间节点
|
||||
//如果fb为空,就是检查是否有数据流接收(返回0x80000000)
|
||||
int32 msi_output_fb(struct msi *msi, struct framebuff *fb)
|
||||
{
|
||||
int ret = 0;
|
||||
int8 i;
|
||||
uint32 flag;
|
||||
struct msi *out;
|
||||
|
||||
if(!msi || !msi->enable){
|
||||
fb_put(fb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < MSI_OUTIF_MAX; i++) {
|
||||
flag = disable_irq();
|
||||
out = msi->output_list[i];
|
||||
if(out && out->enable){
|
||||
msi_get(out);
|
||||
}else{
|
||||
out = NULL;
|
||||
}
|
||||
enable_irq(flag);
|
||||
|
||||
if(out && out->enable){
|
||||
if(!fb){
|
||||
ret = -1;
|
||||
msi_put(out);
|
||||
break;
|
||||
} else {
|
||||
if(msi_do_cmd(out, MSI_CMD_TRANS_FB, (uint32)fb, 0) == RET_OK){
|
||||
if(out->fbQ.init && fbq_enqueue(&out->fbQ, fb)){
|
||||
msi_do_cmd(out, MSI_CMD_TRANS_FB_END, (uint32)fb, 0);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msi_put(out);
|
||||
}
|
||||
|
||||
fb_put(fb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//组件不输出framebuff,需要删除framebuff
|
||||
//注意:fb参数只能是 framebuff链表的第1个节点,不能是中间节点
|
||||
int32 msi_delete_fb(struct msi *msi, struct framebuff *fb)
|
||||
{
|
||||
fb_put(fb);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
struct framebuff *msi_get_fb(struct msi *msi, uint32 tmo_ms)
|
||||
{
|
||||
if(msi && msi->fbQ.init){
|
||||
return fbq_dequeue(&msi->fbQ, tmo_ms);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct framebuff *msi_get_fb_r(struct msi *msi, uint32 reader)
|
||||
{
|
||||
if(msi && msi->fbQ.init){
|
||||
return fbq_dequeue_r(&msi->fbQ, reader);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//追踪某个framebuff当前在被哪些模块处理
|
||||
static int32 msi_fb_trace_discard(struct msi *msi, struct framebuff *fb, uint8 discard)
|
||||
{
|
||||
int8 i;
|
||||
uint32 flag;
|
||||
struct msi *out;
|
||||
|
||||
if(msi == NULL){
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
if(fbq_trace(&msi->fbQ, fb, discard)){
|
||||
os_printf(KERN_ERR"MSI:%s framebuff %p is here!\r\n", msi->name, fb);
|
||||
}
|
||||
|
||||
for (i = 0; i < MSI_OUTIF_MAX; i++) {
|
||||
flag = disable_irq();
|
||||
out = msi->output_list[i];
|
||||
msi_get(out);
|
||||
enable_irq(flag);
|
||||
|
||||
if(out && out->fbQ.init && fbq_trace(&msi->fbQ, fb, discard)){
|
||||
os_printf(KERN_ERR"MSI:%s framebuff %p is here!\r\n", msi->name, fb);
|
||||
}
|
||||
|
||||
msi_put(out);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
//追踪framebuff:查看指定的framebuff当前在被哪些模块处理
|
||||
int32 msi_trace_fb(struct msi *msi, struct framebuff *fb)
|
||||
{
|
||||
return msi_fb_trace_discard(msi, fb, 0);
|
||||
}
|
||||
|
||||
//通知通路中的各个模块,丢弃指定的framebuff
|
||||
int32 msi_discard_fb(struct msi *msi, struct framebuff *fb)
|
||||
{
|
||||
return msi_fb_trace_discard(msi, fb, 1);
|
||||
}
|
||||
|
||||
//组件产生notify操作,可以向上/向下传递
|
||||
void msi_notify(struct msi *msi, uint32 cmd, uint32 param1, uint32 param2)
|
||||
{
|
||||
os_mutex_lock(&g_MSI.lock, osWaitForever);
|
||||
msi_notify_up(msi, cmd, param1, param2); //向上
|
||||
os_mutex_unlock(&g_MSI.lock);
|
||||
msi_output_cmd(msi, cmd, param1, param2); //向下
|
||||
}
|
||||
|
||||
//组件执行自己的action
|
||||
int32 msi_do_cmd(struct msi *msi, uint32 cmd, uint32 param1, uint32 param2)
|
||||
{
|
||||
uint32 flag;
|
||||
int32 ret = RET_OK;
|
||||
msi_action action;
|
||||
|
||||
if(msi){
|
||||
flag = disable_irq();
|
||||
action = msi->action;
|
||||
enable_irq(flag);
|
||||
if(action){
|
||||
ret = action(msi, cmd, param1, param2);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//指定从某个组件开始执行cmd
|
||||
void msi_cmd(const char *name, uint32 cmd, uint32 param1, uint32 param2)
|
||||
{
|
||||
struct msi *msi = msi_find(name, 0);
|
||||
if (msi) {
|
||||
msi_do_cmd(msi, cmd, param1, param2);
|
||||
msi_output_cmd(msi, cmd, param1, param2);
|
||||
msi_put(msi);
|
||||
}
|
||||
}
|
||||
|
||||
int32 msi_core_init()
|
||||
{
|
||||
os_mutex_init(&g_MSI.lock);
|
||||
return RET_OK;
|
||||
}
|
||||
51
sdk/lib/multimedia/msi/utils.c
Normal file
51
sdk/lib/multimedia/msi/utils.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
|
||||
static int32 msi_rbuffer_fb_exist(struct rbuffer *rb, struct framebuff *fb, uint32 start, uint32 end)
|
||||
{
|
||||
uint32 i = 0;
|
||||
struct framebuff **q = (struct framebuff **)rb->rbq;
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
if (q[i] == fb) {
|
||||
return 1;
|
||||
} else {
|
||||
struct framebuff *next = q[i]->next;
|
||||
while (next) {
|
||||
if (next == fb) {
|
||||
return 1;
|
||||
} else {
|
||||
next = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 msi_rbuffer_trace_fb(struct msi *mif, struct rbuffer *rb, struct framebuff *fb)
|
||||
{
|
||||
uint32 rpos = rb->rpos;
|
||||
uint32 wpos = rb->wpos;
|
||||
|
||||
if (!RB_EMPTY(rb)) {
|
||||
if (rpos < wpos) {
|
||||
if (msi_rbuffer_fb_exist(rb, fb, rpos, wpos)) {
|
||||
os_printf(KERN_NOTICE"MSI %s: FB %p is here!\r\n", mif->name, fb);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (msi_rbuffer_fb_exist(rb, fb, rpos, rb->qsize)) {
|
||||
os_printf(KERN_NOTICE"MSI %s: FB %p is here!\r\n", mif->name, fb);
|
||||
return 1;
|
||||
}
|
||||
if (msi_rbuffer_fb_exist(rb, fb, 0, wpos)) {
|
||||
os_printf(KERN_NOTICE"MSI %s: FB %p is here!\r\n", mif->name, fb);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user