pure sdk for main

This commit is contained in:
divadiow
2025-08-27 09:51:58 +01:00
parent f0d033f1c9
commit 0571416e7c
3283 changed files with 1577720 additions and 1 deletions
+323
View File
@@ -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;
}