pure sdk for main
This commit is contained in:
@@ -0,0 +1,323 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "dev/jpg/hgjpg.h"
|
||||
#include "app_lcd.h"
|
||||
#include "decode/recv_jpg_yuv_demo.h"
|
||||
#include "yuv_stream.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
|
||||
//创建一个线程,专门是处理lcd显示
|
||||
struct osd_show_s
|
||||
{
|
||||
struct lcdc_device *lcd_dev;
|
||||
stream *s;
|
||||
struct data_structure *last_show_data_s;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//如果说workqueue确定没有一些耗时的任务,这个也是可以放到workqueue去处理,节省线程的内存
|
||||
void lcd_thread(void *d)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = (struct app_lcd_s *)d;
|
||||
struct lcdc_device *lcd_dev = lcd_s->lcd_dev;
|
||||
stream *p1_s = lcd_s->video_p1_s;
|
||||
stream *p0_s = lcd_s->video_p0_s;
|
||||
stream *s = lcd_s->osd_show_s;
|
||||
struct osd_show_s *osd_show = (struct osd_show_s *)s->priv;
|
||||
struct recv_jpg_yuv_s *yuv_p1 = (struct recv_jpg_yuv_s *)p1_s->priv;
|
||||
|
||||
struct yuv_stream_s *yuv_p0 = (struct yuv_stream_s *)p0_s->priv;
|
||||
|
||||
struct data_structure *osd_data_s;
|
||||
struct data_structure *video_p1_data_s;
|
||||
struct data_structure *video_p0_data_s;
|
||||
|
||||
uint32_t p0_w=0,p0_h=0,p1_w=0,p1_h=0;
|
||||
struct yuv_arg_s *yuv_msg;
|
||||
uint32_t y_off = 0,uv_off = 0;
|
||||
|
||||
|
||||
//是否要启动显示,只要有osd或者video显示,都要启动硬件模块
|
||||
//如果是mcu屏,内部可以增加其他逻辑,判断显示是否有变化决定是否刷屏
|
||||
//如果是rgb屏,无论内容是否发生变化,都要刷新,否则会有问题
|
||||
uint8_t flag = 0;
|
||||
uint8_t p0_p1_enable = 0;
|
||||
while(!lcd_s->thread_exit)
|
||||
{
|
||||
//ready
|
||||
p0_p1_enable = 0;
|
||||
if(lcd_s->hardware_ready)
|
||||
{
|
||||
//显示osd
|
||||
{
|
||||
osd_data_s = recv_real_data(s);
|
||||
if(osd_data_s)
|
||||
{
|
||||
//os_printf("%s:%d\tosd_data_s:%X\n",__FUNCTION__,__LINE__,osd_data_s);
|
||||
if(osd_show->last_show_data_s)
|
||||
{
|
||||
free_data(osd_show->last_show_data_s);
|
||||
osd_show->last_show_data_s = NULL;
|
||||
}
|
||||
osd_show->last_show_data_s = osd_data_s;
|
||||
}
|
||||
else
|
||||
{
|
||||
osd_data_s = osd_show->last_show_data_s;
|
||||
}
|
||||
//os_printf("data_s len:%d\t%X\n",get_stream_real_data_len(osd_data_s),osd_data_s);
|
||||
if(osd_data_s)
|
||||
{
|
||||
lcdc_set_osd_dma_addr(lcd_dev,(uint32)get_stream_real_data(osd_data_s));
|
||||
lcdc_set_osd_dma_len(lcd_dev,get_stream_real_data_len(osd_data_s));
|
||||
lcdc_set_osd_en(lcd_dev,1);
|
||||
//os_printf("encode osd len:%d\n",get_stream_real_data_len(osd_data_s));
|
||||
flag++;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcdc_set_osd_en(lcd_dev,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//显示video p1
|
||||
//这里是video_p1的显示
|
||||
{
|
||||
lcd_thread_get_video_p1_again:
|
||||
video_p1_data_s = recv_real_data(p1_s);
|
||||
|
||||
//有新的yuv数据要显示
|
||||
if(video_p1_data_s)
|
||||
{
|
||||
//os_printf("%s:%d\tvideo_p1_data_s:%X\n",__FUNCTION__,__LINE__,video_p1_data_s);
|
||||
//移除原来的数据
|
||||
if(yuv_p1->last_data_s)
|
||||
{
|
||||
free_data(yuv_p1->last_data_s);
|
||||
}
|
||||
yuv_p1->last_data_s = video_p1_data_s;
|
||||
}
|
||||
else if(yuv_p1->last_data_s)
|
||||
{
|
||||
video_p1_data_s = yuv_p1->last_data_s;
|
||||
}
|
||||
|
||||
//判断一下显示时间,如果过时的,就不显示了
|
||||
if(video_p1_data_s)
|
||||
{
|
||||
uint32_t show_time =stream_self_cmd_func(p1_s,GET_LVGL_YUV_UPDATE_TIME,(uint32_t)0);
|
||||
if(show_time > get_stream_data_timestamp(video_p1_data_s))
|
||||
{
|
||||
free_data(yuv_p1->last_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
goto lcd_thread_get_video_p1_again;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(video_p1_data_s)
|
||||
{
|
||||
yuv_msg = (struct yuv_arg_s *)stream_self_cmd_func(video_p1_data_s->s,YUV_ARG,(uint32_t)video_p1_data_s);
|
||||
|
||||
//错误的图片,可能不需要显示或者发送错误
|
||||
if(yuv_msg)
|
||||
{
|
||||
|
||||
//需要删除
|
||||
if(yuv_msg->del && *yuv_msg->del)
|
||||
{
|
||||
free_data(video_p1_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
os_printf("%s:%d p1 del:%X\n",__FUNCTION__,__LINE__,video_p1_data_s);
|
||||
goto lcd_thread_get_video_p1_again;
|
||||
}
|
||||
|
||||
p1_w = yuv_msg->out_w;
|
||||
p1_h = yuv_msg->out_h;
|
||||
uint8_t *yuv_buf = get_stream_real_data(video_p1_data_s);
|
||||
if(lcd_s->rotate == LCD_ROTATE_180)
|
||||
{
|
||||
y_off = p1_w*(p1_h-1);
|
||||
uv_off= ((p1_w/2+3)/4)*4 * (p1_h/2-1);
|
||||
}
|
||||
lcdc_set_p1_rotate_y_src_addr(lcd_dev,(uint32)yuv_buf+y_off/**/);
|
||||
lcdc_set_p1_rotate_u_src_addr(lcd_dev,(uint32)yuv_buf+yuv_msg->y_size+uv_off/**/);
|
||||
lcdc_set_p1_rotate_v_src_addr(lcd_dev,(uint32)yuv_buf+yuv_msg->y_size+yuv_msg->y_size/4+uv_off/**/);
|
||||
p0_p1_enable |= BIT(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d\tlvgl video yuv err\n",__FUNCTION__,__LINE__);
|
||||
os_printf("%s:%d\tvideo_p1_data_s:%X\tname:%s\n",__FUNCTION__,__LINE__,video_p1_data_s,video_p1_data_s->s->name);
|
||||
free_data(yuv_p1->last_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//强行显示一下p0的数据
|
||||
{
|
||||
lcd_thread_get_video_p0_again:
|
||||
video_p0_data_s = recv_real_data(p0_s);
|
||||
//有新的yuv数据要显示
|
||||
if(video_p0_data_s)
|
||||
{
|
||||
//os_printf("%s:%d\tvideo_p1_data_s:%X\n",__FUNCTION__,__LINE__,video_p1_data_s);
|
||||
//移除原来的数据
|
||||
if(yuv_p0->last_data_s)
|
||||
{
|
||||
free_data(yuv_p0->last_data_s);
|
||||
}
|
||||
yuv_p0->last_data_s = video_p0_data_s;
|
||||
}
|
||||
else if(yuv_p0->last_data_s)
|
||||
{
|
||||
video_p0_data_s = yuv_p0->last_data_s;
|
||||
}
|
||||
|
||||
|
||||
//判断一下显示时间,如果过时的,就不显示了
|
||||
if(video_p0_data_s)
|
||||
{
|
||||
uint32_t show_time =stream_self_cmd_func(p0_s,GET_LVGL_YUV_UPDATE_TIME,(uint32_t)0);
|
||||
if(show_time > get_stream_data_timestamp(video_p0_data_s))
|
||||
{
|
||||
free_data(video_p0_data_s);
|
||||
yuv_p0->last_data_s = NULL;
|
||||
goto lcd_thread_get_video_p0_again;
|
||||
}
|
||||
}
|
||||
|
||||
if(video_p0_data_s)
|
||||
{
|
||||
yuv_msg = (struct yuv_arg_s *)stream_self_cmd_func(video_p0_data_s->s,YUV_ARG,(uint32_t)video_p0_data_s);
|
||||
if(yuv_msg)
|
||||
{
|
||||
//需要删除
|
||||
if(yuv_msg->del && *yuv_msg->del)
|
||||
{
|
||||
free_data(video_p0_data_s);
|
||||
yuv_p0->last_data_s = NULL;
|
||||
os_printf("%s:%d p0 del:%X\n",__FUNCTION__,__LINE__,video_p0_data_s);
|
||||
goto lcd_thread_get_video_p0_again;
|
||||
}
|
||||
uint8_t *p_buf = (uint8_t*)get_stream_real_data(video_p0_data_s);
|
||||
p0_w = yuv_msg->out_w;
|
||||
p0_h = yuv_msg->out_h;
|
||||
if(lcd_s->rotate == LCD_ROTATE_180)
|
||||
{
|
||||
y_off = p0_w*(p0_h-1);
|
||||
uv_off= ((p0_w/2+3)/4)*4 * (p0_h/2-1);
|
||||
}
|
||||
|
||||
lcdc_set_p0_rotate_y_src_addr(lcd_dev,(uint32)p_buf+y_off);
|
||||
lcdc_set_p0_rotate_u_src_addr(lcd_dev,(uint32)p_buf+yuv_msg->y_size+uv_off);
|
||||
lcdc_set_p0_rotate_v_src_addr(lcd_dev,(uint32)p_buf+yuv_msg->y_size+yuv_msg->y_size/4+uv_off);
|
||||
|
||||
p0_p1_enable |= BIT(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//打开video
|
||||
if(p0_p1_enable)
|
||||
{
|
||||
//检查一下line_buf是否已经申请了,申请空间就是w*line_num的空间(w应该是和屏旋转有关)
|
||||
if(!lcd_s->line_buf)
|
||||
{
|
||||
uint16_t rotate_w;
|
||||
rotate_w = lcd_s->screen_w;
|
||||
lcd_s->line_buf = (void*)custom_malloc(lcd_s->line_buf_num*rotate_w*2);
|
||||
//这里理论要申请到空间,如果申请失败,重新申请一下(否则要就额外处理资源数据)
|
||||
while(!lcd_s->line_buf)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
lcd_s->line_buf = (void*)custom_malloc(lcd_s->line_buf_num*rotate_w*2);
|
||||
}
|
||||
lcdc_set_rotate_linebuf_y_addr(lcd_dev,(uint32)lcd_s->line_buf );
|
||||
lcdc_set_rotate_linebuf_u_addr(lcd_dev,(uint32)lcd_s->line_buf +rotate_w*lcd_s->line_buf_num);
|
||||
lcdc_set_rotate_linebuf_v_addr(lcd_dev,(uint32)lcd_s->line_buf +rotate_w*lcd_s->line_buf_num+(rotate_w/2)*lcd_s->line_buf_num);
|
||||
}
|
||||
lcdc_set_rotate_p0p1_size(lcd_dev,p0_w,p0_h,p1_w,p1_h);
|
||||
lcdc_set_rotate_mirror(lcd_dev,0,lcd_s->video_rotate);
|
||||
lcdc_set_p0p1_enable(lcd_dev,p0_p1_enable&BIT(0),p0_p1_enable&BIT(1));
|
||||
lcdc_set_video_en(lcd_dev,1);
|
||||
flag++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//如果不需要显示video,则空间释放吧
|
||||
if(lcd_s->line_buf)
|
||||
{
|
||||
custom_free(lcd_s->line_buf);
|
||||
lcd_s->line_buf = NULL;
|
||||
|
||||
}
|
||||
lcdc_set_video_en(lcd_dev,0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//lcd模块已经启动,hardware_ready清0
|
||||
if(flag)
|
||||
{
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
lcd_s->hardware_ready = 0;
|
||||
|
||||
lcdc_set_start_run(lcd_dev);
|
||||
flag = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//不需要显示,则休眠1ms重新检查
|
||||
//这里暂时没有用信号量唤醒,主要考虑到osd和video都有可能需要显示,要考虑如何监听osd和video的数据才可以用信号量
|
||||
//这里用sleep,会占用一点点cpu
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free_data(yuv_p0->last_data_s);
|
||||
yuv_p0->last_data_s = NULL;
|
||||
|
||||
free_data(yuv_p1->last_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
video_p0_data_s = recv_real_data(p0_s);
|
||||
free_data(video_p0_data_s);
|
||||
os_printf("video_p0_data_s:%X\n",video_p0_data_s);
|
||||
|
||||
}while(video_p0_data_s);
|
||||
|
||||
do
|
||||
{
|
||||
video_p1_data_s = recv_real_data(p1_s);
|
||||
free_data(video_p1_data_s);
|
||||
os_printf("video_p1_data_s:%X\n",video_p1_data_s);
|
||||
|
||||
}while(video_p1_data_s);
|
||||
//相当于退出lcd的线程
|
||||
lcd_s->thread_exit = 0;
|
||||
lcd_s->thread_hdl = NULL;
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user