Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
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;
|
||||
}
|
||||
Reference in New Issue
Block a user