554 lines
20 KiB
C
554 lines
20 KiB
C
|
|
/**********************************************************************************************************
|
|||
|
|
* 虚拟屏幕,支持更多的屏,顶层序号大,底层序号低
|
|||
|
|
* ********************************************************************************************************/
|
|||
|
|
#include "basic_include.h"
|
|||
|
|
|
|||
|
|
#include "lib/multimedia/msi.h"
|
|||
|
|
#include "osal/work.h"
|
|||
|
|
#include "stream_define.h"
|
|||
|
|
#include "lib/heap/av_heap.h"
|
|||
|
|
#include "lib/heap/av_psram_heap.h"
|
|||
|
|
#include "app_lcd/app_lcd.h"
|
|||
|
|
#include "user_work/user_work.h"
|
|||
|
|
|
|||
|
|
extern void yuv_blk_cpy(uint8 *des, uint8* src,uint32 des_w,uint32 des_h, uint32 src_w, uint32_t src_h,uint32 x,uint32 y);
|
|||
|
|
extern void yuv_blk_reduce(uint8 *des, uint8* src,uint32 des_w,uint32 des_h, uint32 src_w, uint32_t src_h,uint32 x,uint32 y);
|
|||
|
|
|
|||
|
|
// 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_RX 8
|
|||
|
|
#define MAX_TX 2
|
|||
|
|
|
|||
|
|
struct window_msg{
|
|||
|
|
uint16_t w;
|
|||
|
|
uint16_t h;
|
|||
|
|
uint16_t x;
|
|||
|
|
uint16_t y;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
struct sim_video_more_msi_s
|
|||
|
|
{
|
|||
|
|
struct os_work work;
|
|||
|
|
struct msi *msi;
|
|||
|
|
struct fbpool tx_pool;
|
|||
|
|
uint16_t w, h;
|
|||
|
|
uint16_t *filter; // 数组去进行过滤,0为结束
|
|||
|
|
struct framebuff **screen; // 不同屏幕的framebuff,屏幕数量与filter数量一致
|
|||
|
|
uint16_t screen_num;
|
|||
|
|
uint32_t bufadr[MAX_TX];
|
|||
|
|
struct framebuff *last_fb;
|
|||
|
|
struct framebuff *last_input_fb;
|
|||
|
|
uint32_t subwindow_cnt[10]; //本地buf所记录的cnt
|
|||
|
|
uint32_t dispwindow_cnt[10]; //显示的buf所记录的cnt
|
|||
|
|
struct window_msg dsp_window_msg[10];
|
|||
|
|
uint8_t video_display_mask[10]; //记录哪个界面打开了独显,正常只可能有一个设备配置上,或者没人配置上
|
|||
|
|
uint8_t lcd_fb_updata;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
//只做双层
|
|||
|
|
static int32 sim_video_more_work(struct os_work *work)
|
|||
|
|
{
|
|||
|
|
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)work;
|
|||
|
|
struct framebuff *fb;
|
|||
|
|
struct framebuff *output_fb;
|
|||
|
|
uint32_t dispbuf;
|
|||
|
|
fb = msi_get_fb(sim_video->msi, 0);
|
|||
|
|
// 接收到一个fb,就需要判断类型(p0,p1),然后申请空间去进行叠层
|
|||
|
|
if (fb)
|
|||
|
|
{
|
|||
|
|
// 查看类型是否匹配(正常到这里一定匹配,因为接收的时候就进行过滤了)
|
|||
|
|
uint16_t match_count = 0;
|
|||
|
|
uint8_t match_flag = 0;
|
|||
|
|
|
|||
|
|
while (match_count < sim_video->screen_num)
|
|||
|
|
{
|
|||
|
|
if (fb->stype == sim_video->filter[match_count]) //类型检查,看一下当前的fb类型是否存在于过滤网内
|
|||
|
|
{
|
|||
|
|
if (sim_video->screen[match_count]) //检查当前的screen是否存在,如果存在,则删除,更新新的fb到screen
|
|||
|
|
{
|
|||
|
|
msi_delete_fb(NULL, sim_video->screen[match_count]);
|
|||
|
|
}
|
|||
|
|
sim_video->screen[match_count] = fb;
|
|||
|
|
match_flag = 1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
match_count++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 没有匹配,删除,并且不需要刷新
|
|||
|
|
if (!match_flag)
|
|||
|
|
{
|
|||
|
|
msi_delete_fb(NULL, fb);
|
|||
|
|
fb = NULL;
|
|||
|
|
goto sim_video_work_end;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
output_fb = fbpool_get(&sim_video->tx_pool, 0, sim_video->msi); //从sim_video的发送池里找到对应的fb
|
|||
|
|
if (!output_fb)
|
|||
|
|
{
|
|||
|
|
goto sim_video_work_end;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if((uint32_t)output_fb->data == sim_video->bufadr[0]){
|
|||
|
|
dispbuf = sim_video->bufadr[1]; //提取当前正在显示的buf地址,用来拷数据
|
|||
|
|
}else{
|
|||
|
|
dispbuf = sim_video->bufadr[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 这个模式是默认都是叠层,不再判断有某些情况不需要叠层的情况(效率低,但是既然应用设定多个屏幕,就应该去实现吧)
|
|||
|
|
// 叠层
|
|||
|
|
{
|
|||
|
|
// 开始尝试叠层
|
|||
|
|
uint16_t tmp = 0;
|
|||
|
|
uint16_t p_w, p_h;
|
|||
|
|
struct yuv_arg_s *yuv_msg = NULL;
|
|||
|
|
while (tmp < sim_video->screen_num)
|
|||
|
|
{
|
|||
|
|
if (sim_video->screen[tmp])
|
|||
|
|
{
|
|||
|
|
yuv_msg = (struct yuv_arg_s *)sim_video->screen[tmp]->priv;
|
|||
|
|
p_w = yuv_msg->out_w;
|
|||
|
|
p_h = yuv_msg->out_h;
|
|||
|
|
|
|||
|
|
|
|||
|
|
yuv_blk_cpy((uint8_t*)output_fb->data, sim_video->screen[tmp]->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y);
|
|||
|
|
}
|
|||
|
|
tmp++;
|
|||
|
|
}
|
|||
|
|
output_fb->mtype = F_YUV;
|
|||
|
|
output_fb->stype = FSTYPE_YUV_P0;
|
|||
|
|
msi_output_fb(sim_video->msi, output_fb);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
sim_video_work_end:
|
|||
|
|
os_run_work_delay(work, 1);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
static int32 sim_video_more_work_more(struct os_work *work)
|
|||
|
|
{
|
|||
|
|
#define REFRESH_LCD_INTERNAL_TIME 10
|
|||
|
|
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)work;
|
|||
|
|
struct framebuff *fb;
|
|||
|
|
struct framebuff *output_fb;
|
|||
|
|
|
|||
|
|
static uint16_t oldbigx,oldbigy;
|
|||
|
|
uint32_t dispbuf;
|
|||
|
|
uint32_t *cache_buf[10];
|
|||
|
|
uint8_t push_lcd_updata=0;
|
|||
|
|
uint8_t display_only = 0;
|
|||
|
|
uint16_t p_w, p_h;
|
|||
|
|
uint16_t max_w;
|
|||
|
|
uint16_t tmp = 0;
|
|||
|
|
struct yuv_arg_s *yuv_msg = NULL;
|
|||
|
|
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
|||
|
|
|
|||
|
|
output_fb = NULL;
|
|||
|
|
|
|||
|
|
if(sim_video->last_input_fb != NULL){
|
|||
|
|
fb = sim_video->last_input_fb;
|
|||
|
|
}else{
|
|||
|
|
fb = msi_get_fb(sim_video->msi, 0);
|
|||
|
|
}
|
|||
|
|
// 接收到一个fb,就需要判断类型(p0,p1),然后申请空间去进行叠层
|
|||
|
|
if (fb)
|
|||
|
|
{
|
|||
|
|
// 查看类型是否匹配(正常到这里一定匹配,因为接收的时候就进行过滤了)
|
|||
|
|
uint16_t match_count = 0;
|
|||
|
|
uint8_t match_flag = 0;
|
|||
|
|
while (match_count < sim_video->screen_num)
|
|||
|
|
{
|
|||
|
|
if (fb->stype == sim_video->filter[match_count]) //类型检查,看一下当前的fb类型是否存在于过滤网内
|
|||
|
|
{
|
|||
|
|
yuv_msg = (struct yuv_arg_s *)fb->priv;
|
|||
|
|
if(sim_video->subwindow_cnt[match_count] != sim_video->dispwindow_cnt[match_count]){ //重复更新,当前要刷的叠层已在备刷区,但又来了新的数据,那要把备刷区推出去
|
|||
|
|
push_lcd_updata = 1;
|
|||
|
|
sim_video->last_input_fb = fb;
|
|||
|
|
output_fb = sim_video->last_fb;
|
|||
|
|
goto sim_video_push_lcd;
|
|||
|
|
}
|
|||
|
|
match_flag = 1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
match_count++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 没有匹配,删除,并且不需要刷新
|
|||
|
|
if (!match_flag)
|
|||
|
|
{
|
|||
|
|
msi_delete_fb(NULL, fb);
|
|||
|
|
if(fb == sim_video->last_input_fb) {
|
|||
|
|
sim_video->last_input_fb = NULL;
|
|||
|
|
}
|
|||
|
|
fb = NULL;
|
|||
|
|
goto sim_video_work_end;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(sim_video->lcd_fb_updata){
|
|||
|
|
sim_video->lcd_fb_updata = 0;
|
|||
|
|
sim_video->last_input_fb = fb;
|
|||
|
|
|
|||
|
|
output_fb = fbpool_get(&sim_video->tx_pool, 0, sim_video->msi); //从sim_video的发送池里找到对应的fb
|
|||
|
|
if(!output_fb){ //需要更新时无法申请到fb,则下次重新申请,直到能申请为止
|
|||
|
|
sim_video->lcd_fb_updata = 1;
|
|||
|
|
goto sim_video_work_end;
|
|||
|
|
}else{ //申请到了,表示当前input_fb可被处理掉,指针清空一下
|
|||
|
|
if((uint32_t)output_fb->data == sim_video->bufadr[0]){
|
|||
|
|
dispbuf = sim_video->bufadr[1]; //提取当前正在显示的buf地址,用来拷数据
|
|||
|
|
}else{
|
|||
|
|
dispbuf = sim_video->bufadr[0];
|
|||
|
|
}
|
|||
|
|
//hw_memcpy(output_fb->data,dispbuf,output_fb->len);
|
|||
|
|
yuv_blk_cpy((uint8_t*)output_fb->data, (uint8_t*)dispbuf, sim_video->w, sim_video->h, sim_video->w,sim_video->h, 0,0);
|
|||
|
|
sim_video->last_input_fb = NULL;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!output_fb)
|
|||
|
|
{
|
|||
|
|
output_fb = sim_video->last_fb;
|
|||
|
|
}else{
|
|||
|
|
sim_video->last_fb = output_fb; //记录当前要修改的fb
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
sim_video->subwindow_cnt[match_count] = yuv_msg->dispcnt;
|
|||
|
|
sim_video->dsp_window_msg[match_count].w = yuv_msg->out_w;
|
|||
|
|
sim_video->dsp_window_msg[match_count].h = yuv_msg->out_h;
|
|||
|
|
sim_video->dsp_window_msg[match_count].x = yuv_msg->x;
|
|||
|
|
sim_video->dsp_window_msg[match_count].y = yuv_msg->y;
|
|||
|
|
sim_video->video_display_mask[match_count] = yuv_msg->video_only;
|
|||
|
|
|
|||
|
|
if((uint32_t)output_fb->data == sim_video->bufadr[0]){
|
|||
|
|
dispbuf = sim_video->bufadr[1]; //提取当前正在显示的buf地址,用来拷数据
|
|||
|
|
}else{
|
|||
|
|
dispbuf = sim_video->bufadr[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
display_only = 0;
|
|||
|
|
tmp = 0;
|
|||
|
|
while (tmp < sim_video->screen_num) { //选出是否配置独显了
|
|||
|
|
if(sim_video->video_display_mask[tmp] != 0){
|
|||
|
|
if(yuv_msg->video_only){ //当前数据流是否就是要显示的数据流
|
|||
|
|
display_only |= BIT(7);
|
|||
|
|
}
|
|||
|
|
display_only++;
|
|||
|
|
}
|
|||
|
|
tmp++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if((display_only&0x7f) > 1){
|
|||
|
|
_os_printf("too much stream set display only mode\r\n");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
max_w = 0;
|
|||
|
|
tmp = 0;
|
|||
|
|
while (tmp < sim_video->screen_num) { //选出最大的图片
|
|||
|
|
if(sim_video->dsp_window_msg[tmp].w > max_w){
|
|||
|
|
max_w = sim_video->dsp_window_msg[tmp].w;
|
|||
|
|
}
|
|||
|
|
tmp++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
yuv_msg = (struct yuv_arg_s *)fb->priv;
|
|||
|
|
p_w = yuv_msg->out_w;
|
|||
|
|
p_h = yuv_msg->out_h;
|
|||
|
|
|
|||
|
|
if(display_only){ //有设备打开了独显
|
|||
|
|
if((display_only&BIT(7)) == BIT(7)){
|
|||
|
|
hw_memset((uint8_t*)output_fb->data, 0, sim_video->w * sim_video->h); //清黑屏
|
|||
|
|
hw_memset((uint8_t*)output_fb->data + sim_video->w * sim_video->h, 0x80, sim_video->w * sim_video->h / 2);
|
|||
|
|
yuv_blk_cpy((uint8_t*)output_fb->data, fb->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y); //把大图拷好
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if(max_w != yuv_msg->out_w){ //如果并非大图
|
|||
|
|
yuv_blk_cpy((uint8_t*)output_fb->data, fb->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y); //拷到对应的位置上
|
|||
|
|
}else{ //如果是大图
|
|||
|
|
tmp = 0;
|
|||
|
|
while(tmp < sim_video->screen_num){
|
|||
|
|
cache_buf[tmp] = NULL;
|
|||
|
|
if( (match_count != tmp) && (sim_video->dsp_window_msg[tmp].w != 0)){
|
|||
|
|
if(sim_video->subwindow_cnt[tmp] > sim_video->dispwindow_cnt[tmp]){ //如果备用区数值是更新的,那就拷出来
|
|||
|
|
cache_buf[tmp] = (uint32_t *)STREAM_MALLOC(sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2); //申请小图空间
|
|||
|
|
sys_dcache_invalid_range(cache_buf[tmp], sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2);
|
|||
|
|
if(cache_buf[tmp] != NULL){
|
|||
|
|
yuv_blk_reduce((uint8_t*)cache_buf[tmp],(uint8_t*)output_fb->data,sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h,sim_video->w,sim_video->h,sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y);
|
|||
|
|
}else{
|
|||
|
|
_os_printf("malloc psram for sim video error1\r\n");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
tmp++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if((oldbigx != yuv_msg->x) || (oldbigy != yuv_msg->y)){
|
|||
|
|
hw_memset((uint8_t*)output_fb->data, 0, sim_video->w * sim_video->h); //大图产生偏移,清黑屏
|
|||
|
|
hw_memset((uint8_t*)output_fb->data + sim_video->w * sim_video->h, 0x80, sim_video->w * sim_video->h / 2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
yuv_blk_cpy((uint8_t*)output_fb->data, fb->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y); //把大图拷好
|
|||
|
|
oldbigx = yuv_msg->x;
|
|||
|
|
oldbigy = yuv_msg->y;
|
|||
|
|
|
|||
|
|
tmp = 0;
|
|||
|
|
while(tmp < sim_video->screen_num){
|
|||
|
|
if( (match_count != tmp) && (sim_video->dsp_window_msg[tmp].w != 0)){
|
|||
|
|
if(cache_buf[tmp]){ //图片是从之前的备用区提取出来的,在缓存中
|
|||
|
|
yuv_blk_cpy((uint8_t*)output_fb->data, (uint8_t*)cache_buf[tmp], sim_video->w, sim_video->h, sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h, sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y); //拷到对应的psram块中
|
|||
|
|
STREAM_FREE((uint8_t*)cache_buf[tmp]);
|
|||
|
|
}
|
|||
|
|
else{ //图片得从刷新区那里提取
|
|||
|
|
cache_buf[tmp] = (uint32_t *)STREAM_MALLOC(sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2);
|
|||
|
|
sys_dcache_invalid_range(cache_buf[tmp],sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2);
|
|||
|
|
if(cache_buf[tmp] != NULL){
|
|||
|
|
yuv_blk_reduce((uint8_t*)cache_buf[tmp],(uint8_t*)dispbuf,sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h,sim_video->w,sim_video->h,sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y);
|
|||
|
|
yuv_blk_cpy((uint8_t*)output_fb->data, (uint8_t*)cache_buf[tmp], sim_video->w, sim_video->h, sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h, sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y);
|
|||
|
|
STREAM_FREE((uint8_t*)cache_buf[tmp]);
|
|||
|
|
}else{
|
|||
|
|
_os_printf("malloc psram for sim video error2\r\n");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
tmp++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
sim_video_push_lcd:
|
|||
|
|
if(push_lcd_updata == 1){
|
|||
|
|
|
|||
|
|
memcpy(sim_video->dispwindow_cnt,sim_video->subwindow_cnt,10*4);
|
|||
|
|
output_fb->mtype = F_YUV;
|
|||
|
|
output_fb->stype = FSTYPE_YUV_P0;
|
|||
|
|
msi_output_fb(sim_video->msi, output_fb); //将当前推屏的fb推出去
|
|||
|
|
sim_video->lcd_fb_updata = 1; //下次提取新的刷屏帧
|
|||
|
|
sim_video->last_fb = NULL;
|
|||
|
|
}else{
|
|||
|
|
msi_delete_fb(NULL, fb); //删除对应的输入到msi video的fb
|
|||
|
|
fb = NULL;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
sim_video_work_end:
|
|||
|
|
if((os_jiffies() - lcd_s->start_time) > (lcd_s->refresh_time - REFRESH_LCD_INTERNAL_TIME)){ //当距离结束刷屏时间为REFRESH_LCD_INTERNAL_TIME时,检查是否需要更新,需要的话,就先更新
|
|||
|
|
if(output_fb){ //先检查推屏的fb是否存在
|
|||
|
|
tmp = 0;
|
|||
|
|
while(tmp < sim_video->screen_num){ //检查各个叠层
|
|||
|
|
if(sim_video->dispwindow_cnt[tmp] != sim_video->subwindow_cnt[tmp]){ //发现有叠层出现更新了
|
|||
|
|
memcpy(sim_video->dispwindow_cnt,sim_video->subwindow_cnt,10*4);
|
|||
|
|
output_fb->mtype = F_YUV;
|
|||
|
|
output_fb->stype = FSTYPE_YUV_P0;
|
|||
|
|
msi_output_fb(sim_video->msi, output_fb); //将当前推屏的fb推出去
|
|||
|
|
sim_video->lcd_fb_updata = 1; //下次提取新的刷屏帧
|
|||
|
|
sim_video->last_fb = NULL;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
tmp++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
os_run_work_delay(work, 1);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int sim_video_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
|||
|
|
{
|
|||
|
|
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)msi->priv;
|
|||
|
|
int ret = RET_OK;
|
|||
|
|
switch (cmd_id)
|
|||
|
|
{
|
|||
|
|
case MSI_CMD_POST_DESTROY:
|
|||
|
|
{
|
|||
|
|
struct framebuff *fb;
|
|||
|
|
// 释放资源fb资源文件,priv是独立申请的
|
|||
|
|
while (1)
|
|||
|
|
{
|
|||
|
|
fb = fbpool_get(&sim_video->tx_pool, 0, NULL);
|
|||
|
|
if (!fb)
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (fb->data)
|
|||
|
|
{
|
|||
|
|
STREAM_FREE(fb->data);
|
|||
|
|
fb->data = NULL;
|
|||
|
|
}
|
|||
|
|
// 预分配空间释放
|
|||
|
|
if (fb->priv)
|
|||
|
|
{
|
|||
|
|
STREAM_LIBC_FREE(fb->priv);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
fbpool_destroy(&sim_video->tx_pool);
|
|||
|
|
STREAM_LIBC_FREE(sim_video);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case MSI_CMD_TRANS_FB:
|
|||
|
|
{
|
|||
|
|
struct framebuff *fb = (struct framebuff *)param1;
|
|||
|
|
|
|||
|
|
if (fb->mtype != F_YUV)
|
|||
|
|
{
|
|||
|
|
// os_printf("not recv fb:%X\tcount:%d\n",fb,fb->users.counter);
|
|||
|
|
ret = RET_ERR;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (sim_video->filter)
|
|||
|
|
{
|
|||
|
|
// 轮询类型是否有一致
|
|||
|
|
ret = RET_ERR;
|
|||
|
|
uint16_t *each = sim_video->filter;
|
|||
|
|
while (*each)
|
|||
|
|
{
|
|||
|
|
// 如果一致,返回OK
|
|||
|
|
if (*each == fb->stype)
|
|||
|
|
{
|
|||
|
|
ret = RET_OK;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
each++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case MSI_CMD_FREE_FB:
|
|||
|
|
{
|
|||
|
|
struct framebuff *fb = (struct framebuff *)param1;
|
|||
|
|
// 如果不是克隆的,就自己释放
|
|||
|
|
if (!fb->clone)
|
|||
|
|
{
|
|||
|
|
// if (fb->data)
|
|||
|
|
// {
|
|||
|
|
// STREAM_FREE(fb->data);
|
|||
|
|
// fb->data = NULL;
|
|||
|
|
// }
|
|||
|
|
fbpool_put(&sim_video->tx_pool, fb);
|
|||
|
|
// 不需要内核去释放fb
|
|||
|
|
ret = RET_OK + 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case MSI_CMD_PRE_DESTROY:
|
|||
|
|
{
|
|||
|
|
os_work_cancle2(&sim_video->work, 1);
|
|||
|
|
uint16_t tmp = 0;
|
|||
|
|
while (tmp < sim_video->screen_num)
|
|||
|
|
{
|
|||
|
|
if (sim_video->screen[tmp])
|
|||
|
|
{
|
|||
|
|
msi_delete_fb(NULL, sim_video->screen[tmp]);
|
|||
|
|
}
|
|||
|
|
tmp++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
while (1)
|
|||
|
|
{
|
|||
|
|
struct framebuff *fb = msi_get_fb(msi, 0);
|
|||
|
|
if (fb) {
|
|||
|
|
msi_delete_fb(NULL, fb);
|
|||
|
|
} else {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (sim_video->last_fb){
|
|||
|
|
msi_delete_fb(NULL, sim_video->last_fb);
|
|||
|
|
sim_video->last_fb = NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(sim_video->last_input_fb){
|
|||
|
|
msi_delete_fb(NULL, sim_video->last_input_fb);
|
|||
|
|
sim_video->last_input_fb = NULL;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
struct msi *sim_video_more_msi(const char *name, uint16_t w, uint16_t h, uint16_t *sim_filter)
|
|||
|
|
{
|
|||
|
|
// 设置1个接收,只是为了可以output_fb给到这个msi
|
|||
|
|
uint16_t count = 0;
|
|||
|
|
uint32_t *buf;
|
|||
|
|
struct msi *msi = msi_new(name, MAX_RX, NULL);
|
|||
|
|
if (msi)
|
|||
|
|
{
|
|||
|
|
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)msi->priv;
|
|||
|
|
if (!sim_video)
|
|||
|
|
{
|
|||
|
|
// 统计sim_filter数量来决定screen的数量
|
|||
|
|
|
|||
|
|
while (*(sim_filter + count))
|
|||
|
|
{
|
|||
|
|
count++;
|
|||
|
|
}
|
|||
|
|
sim_video = (struct sim_video_more_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct sim_video_more_msi_s) + (sizeof(struct framebuff *) * count));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sim_video->w = w;
|
|||
|
|
sim_video->h = h;
|
|||
|
|
sim_video->msi = msi;
|
|||
|
|
sim_video->filter = sim_filter;
|
|||
|
|
sim_video->screen_num = count;
|
|||
|
|
// 申请空间的时候就已经多申请了,所有screen放在末尾
|
|||
|
|
sim_video->screen = (struct framebuff **)(sim_video + 1);
|
|||
|
|
sim_video->lcd_fb_updata = 1;
|
|||
|
|
msi->priv = (void *)sim_video;
|
|||
|
|
msi->action = sim_video_msi_action;
|
|||
|
|
|
|||
|
|
// 预分配结构体空间
|
|||
|
|
uint32_t init_count = 0;
|
|||
|
|
void *priv;
|
|||
|
|
fbpool_init(&sim_video->tx_pool, MAX_TX);
|
|||
|
|
while (init_count < MAX_TX)
|
|||
|
|
{
|
|||
|
|
priv = (void *)STREAM_LIBC_ZALLOC(sizeof(struct yuv_arg_s));
|
|||
|
|
struct yuv_arg_s *yuv_msg = (struct yuv_arg_s *)priv;
|
|||
|
|
buf = (uint32_t *)STREAM_MALLOC(sim_video->w * sim_video->h * 3 / 2);
|
|||
|
|
hw_memset((uint8_t*)buf, 0, sim_video->w * sim_video->h); //清空整个空间,将显示背景显示全黑
|
|||
|
|
hw_memset((uint8_t*)buf + sim_video->w * sim_video->h, 0x80, sim_video->w * sim_video->h / 2);
|
|||
|
|
sys_dcache_invalid_range(buf, sim_video->w * sim_video->h * 3 / 2); //清cache
|
|||
|
|
yuv_msg->out_w = w;
|
|||
|
|
yuv_msg->out_h = h;
|
|||
|
|
yuv_msg->y_size = w * h;
|
|||
|
|
yuv_msg->y_off = 0;
|
|||
|
|
yuv_msg->uv_off = 0;
|
|||
|
|
yuv_msg->del = NULL;
|
|||
|
|
sim_video->bufadr[init_count] = (uint32_t)buf;
|
|||
|
|
FBPOOL_SET_INFO(&sim_video->tx_pool, init_count, (uint8_t*)buf, sim_video->w * sim_video->h * 3 / 2, priv);
|
|||
|
|
init_count++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
msi->enable = 1;
|
|||
|
|
|
|||
|
|
// msi_add_output(sim_video->msi, NULL, R_VIDEO_P0);
|
|||
|
|
|
|||
|
|
OS_WORK_INIT(&sim_video->work, sim_video_more_work_more, 0);
|
|||
|
|
os_run_work_delay(&sim_video->work, 1);
|
|||
|
|
}
|
|||
|
|
return msi;
|
|||
|
|
}
|