464 lines
11 KiB
C
464 lines
11 KiB
C
#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;
|
||
}
|
||
|