Files
TAIXIN/sdk/app/app_lcd/osd_encode_msi.c

315 lines
11 KiB
C
Raw Permalink Normal View History

#include "stream_frame.h"
#include "osal/work.h"
#include "basic_include.h"
#include "lib/multimedia/msi.h"
#include "hal/osd_enc.h"
#include "dev/osd_enc/hgosd_enc.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
// data申请空间函数
#define STREAM_MALLOC av_psram_malloc
#define STREAM_FREE av_psram_free
#define STREAM_ZALLOC av_psram_zalloc
// 结构体申请空间函数
#define STREAM_LIBC_MALLOC av_malloc
#define STREAM_LIBC_FREE av_free
#define STREAM_LIBC_ZALLOC av_zalloc
#define MAX_OSD_ENCODE_RX 8
#define MAX_OSD_ENCODE_TX 8
struct osd_encode_msi_s
{
struct os_work work;
struct osdenc_device *osd_enc_dev;
struct msi *msi;
uint8_t *osd_tmp_buf;
uint32_t osd_tmp_buf_size;
struct fbpool tx_pool;
struct framebuff *parent_data_s;
// osd压缩后的数据长度
uint32_t data_len;
uint32_t start_time;
// 解码模块是否可用
uint8_t hardware_ready;
};
static int32 osd_enc_isr_msi(uint32 irq_flag, uint32 irq_data, uint32 param1)
{
struct osd_encode_msi_s *osd_enc = (struct osd_encode_msi_s *)irq_data;
struct osdenc_device *osd_enc_dev;
struct msi *osd_enc_msi = (struct msi *)osd_enc->msi;
osd_enc_dev = osd_enc->osd_enc_dev;
// _os_printf("=");
msi_do_cmd(osd_enc_msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_ENCODE_SET_LEN, osd_enc_dlen(osd_enc_dev));
msi_do_cmd(osd_enc_msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_REAY_CMD, 1);
return 0;
}
static int32 osd_encode_work(struct os_work *work)
{
struct osd_encode_msi_s *osd_encode = (struct osd_encode_msi_s *)work;
struct framebuff *data_s = NULL;
// static int osd_encode_count = 0;
static uint32_t osd_send_times = 0;
// 先检测一下解码模块是否可用
if (osd_encode->hardware_ready)
{
// 检测一下是否有data_s需要先发送出去
if (osd_encode->parent_data_s)
{
// 获取data_s,申请空间,发送数据
data_s = fbpool_get(&osd_encode->tx_pool, 0, osd_encode->msi);
if (data_s)
{
data_s->mtype = F_ERGB; //设置为已经压缩的RGB
data_s->stype = osd_encode->parent_data_s->stype; //子类保持与接收一致
msi_delete_fb(NULL, osd_encode->parent_data_s);
osd_encode->parent_data_s = NULL;
// 为data_s申请空间
data_s->data = (void *)STREAM_MALLOC(osd_encode->data_len);
if (data_s->data)
{
// 先清除cache
sys_dcache_invalid_range((uint32_t *)data_s->data, osd_encode->data_len);
// 拷贝数据
hw_memcpy_no_cache(data_s->data, (const void *)msi_do_cmd(osd_encode->msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_ENCODE_BUF, 0), (uint32_t)osd_encode->data_len);
//sys_dcache_clean_range((uint32_t *)data_s->data, osd_encode->data_len);
// 数据类型保持一致
data_s->len = osd_encode->data_len;
data_s->time = os_jiffies();
// os_printf("osd encode after len:%d\n",data_s->len);
// os_printf("encode spend time:%d\n",(uint32_t)os_jiffies()-osd_encode->start_time);
msi_output_fb(osd_encode->msi, data_s);
//os_printf("success:%d\n",success);
osd_send_times++;
}
// 没有发送成功,则释放data_s先吧,下一次再发送
else
{
msi_delete_fb(osd_encode->msi, data_s);
_os_printf("**********************");
}
data_s = NULL;
}
}
// 重新检测一下,parent_data_s是否还存在,不存在就去看看是否有需要压缩的osd
// 会进入中断
if (!osd_encode->parent_data_s)
{
osd_encode->parent_data_s = msi_get_fb(osd_encode->msi, 0);
if (osd_encode->parent_data_s)
{
// 判断一下osd_tmp_buf_size是否足够,如果足够就不需要重新申请空间,否则重新申请一下空间
if (osd_encode->osd_tmp_buf_size < osd_encode->parent_data_s->len)
{
// 释放原来空间
if (osd_encode->osd_tmp_buf)
{
STREAM_FREE(osd_encode->osd_tmp_buf);
}
// 重新申请一下空间
osd_encode->osd_tmp_buf = (uint8_t *)STREAM_MALLOC(osd_encode->parent_data_s->len);
// 申请失败,不压缩了,丢弃
if (!osd_encode->osd_tmp_buf)
{
osd_encode->osd_tmp_buf_size = 0;
msi_delete_fb(NULL, osd_encode->parent_data_s);
osd_encode->parent_data_s = NULL;
goto osd_encode_work_end;
}
osd_encode->osd_tmp_buf_size = osd_encode->parent_data_s->len;
// 先清除cache
sys_dcache_invalid_range((uint32_t *)osd_encode->osd_tmp_buf, osd_encode->osd_tmp_buf_size);
}
// 硬件模块开始被使用,标志置一下
msi_do_cmd(osd_encode->msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_REAY_CMD, 0);
// 去压缩
osd_enc_addr(osd_encode->osd_enc_dev, (uint32)osd_encode->parent_data_s->data, (uint32)msi_do_cmd(osd_encode->msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_ENCODE_BUF, 0));
osd_enc_src_len(osd_encode->osd_enc_dev, osd_encode->osd_tmp_buf_size);
osd_encode->start_time = os_jiffies();
osd_enc_run(osd_encode->osd_enc_dev);
}
}
}
osd_encode_work_end:
os_run_work_delay(work, 1);
return 0;
}
static int32 osd_encode_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
{
int32_t ret = RET_OK;
struct osd_encode_msi_s *osd_encode = (struct osd_encode_msi_s *)msi->priv;
uint32_t arg = param2;
switch (cmd_id)
{
case MSI_CMD_PRE_DESTROY:
{
os_work_cancle2(&osd_encode->work, 1);
// lcdc_osd_enc_start_run(osd_encode->osd_enc_dev, 0);
// 释放资源空间
if (osd_encode->osd_tmp_buf)
{
STREAM_FREE(osd_encode->osd_tmp_buf);
osd_encode->osd_tmp_buf_size = 0;
osd_encode->osd_tmp_buf = NULL;
}
// 将缓冲区的fb释放
struct framebuff *fb;
while (1)
{
fb = msi_get_fb(osd_encode->msi, 0);
if (fb)
{
msi_delete_fb(NULL, fb);
}
else
{
break;
}
}
if (osd_encode->parent_data_s)
{
msi_delete_fb(NULL, osd_encode->parent_data_s);
osd_encode->parent_data_s = NULL;
}
// 由于tx_pool的fb没有特殊空间,直接释放就好了
fbpool_destroy(&osd_encode->tx_pool);
break;
}
// 暂时没有考虑释放
case MSI_CMD_POST_DESTROY:
{
STREAM_LIBC_FREE(osd_encode);
}
break;
// 接收,判断是类型是否可以支持压缩,暂时默认全部接收
case MSI_CMD_TRANS_FB:
{
struct framebuff *fb = (struct framebuff *)param1;
if(fb->mtype != F_RGB || fb->srcID != FRAMEBUFF_SOURCE_OSD_ENC)
{
ret = RET_ERR;
}
}
break;
case MSI_CMD_FREE_FB:
{
struct framebuff *fb = (struct framebuff *)param1;
if (fb->data)
{
STREAM_FREE(fb->data);
fb->data = NULL;
}
fbpool_put(&osd_encode->tx_pool, fb);
ret = RET_OK + 1;
}
break;
case MSI_CMD_OSD_ENCODE:
{
uint32_t cmd_self = (uint32_t)param1;
switch (cmd_self)
{
case MSI_OSD_HARDWARE_REAY_CMD:
osd_encode->hardware_ready = arg;
break;
case MSI_OSD_HARDWARE_ENCODE_SET_LEN:
osd_encode->data_len = arg;
break;
case MSI_OSD_HARDWARE_ENCODE_GET_LEN:
ret = osd_encode->data_len;
break;
case MSI_OSD_HARDWARE_ENCODE_BUF:
ret = (uint32_t)osd_encode->osd_tmp_buf;
break;
case MSI_OSD_HARDWARE_DEV:
ret = (uint32_t)osd_encode->osd_enc_dev;
break;
case MSI_OSD_HARDWARE_STREAM_RESET:
{
// 硬件模块可用
osd_encode->hardware_ready = 1;
OS_WORK_REINIT(&osd_encode->work);
os_run_work(&osd_encode->work);
}
break;
case MSI_OSD_HARDWARE_STREAM_STOP:
// 停止硬件模块
// lcdc_osd_enc_start_run(osd_encode->osd_enc_dev, 0);
// workqueue停止
os_work_cancle2(&osd_encode->work, 1);
break;
case MSI_OSD_ENC_MSI_ENABLE:
osd_encode->msi->enable = arg;
break;
}
}
break;
default:
break;
}
return ret;
}
// osd压缩是一个模块,所以在这里统一管理自己的模块,所有需要压缩的数据都到这里,然后再发出去
// 然后类型可以跟着父流一致
// 要预先申请一个空间给到osd压缩,最后再读取寄存器看看要拷贝多少压缩的数据
// 所以空间是:w*h*2+压缩的size,压缩的size根据不同ui去压缩的,一般不会超过原来的size
struct msi *osd_encode_msi_init(const char *name)
{
struct msi *msi = msi_new(name, MAX_OSD_ENCODE_RX, NULL); //R_OSD_ENCODE
struct osd_encode_msi_s *osd_encode = (struct osd_encode_msi_s *)msi->priv;
if (!osd_encode)
{
osd_encode = (struct osd_encode_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct osd_encode_msi_s));
msi->priv = (void *)osd_encode;
osd_encode->msi = msi;
fbpool_init(&osd_encode->tx_pool, MAX_OSD_ENCODE_TX);
osd_encode->osd_enc_dev = (struct osdenc_device *)dev_get(HG_OSD_ENC_DEVID);
osd_encode->hardware_ready = 1;
osd_encode->osd_tmp_buf_size = 0;
osd_encode->osd_tmp_buf = NULL;
msi->action = osd_encode_msi_action;
msi->enable = 1;
msi_add_output(osd_encode->msi, NULL, R_LCD_OSD);
osd_enc_open(osd_encode->osd_enc_dev);
osd_enc_tran_config(osd_encode->osd_enc_dev, 0xFFFFFF, 0xFFFFFF, 0x000000, 0x000000);
osd_enc_set_format(osd_encode->osd_enc_dev, 1);
osd_enc_request_irq(osd_encode->osd_enc_dev, ENC_DONE_IRQ, osd_enc_isr_msi, (uint32)osd_encode);
OS_WORK_INIT(&osd_encode->work, osd_encode_work, 0);
os_run_work_delay(&osd_encode->work, 1);
}
return msi;
}