Files

464 lines
11 KiB
C
Raw Permalink Normal View History

#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;
}