doubao_chat/apps/wifi_ipc/ui_camera_demo/camera_demo.c

246 lines
6.8 KiB
C

#ifdef CONFIG_UI_ENABLE //上电执行则打开app_config.h TCFG_DEMO_UI_RUN = 1
#include "app_config.h"
#include "device/device.h"//u8
#include "storage_device.h"//SD
#include "server/video_dec_server.h"//fopen
#include "system/includes.h"//GPIO
#include "lcd_drive.h"
#include "sys_common.h"
#include "yuv_soft_scalling.h"
#include "asm/jpeg_codec.h"
#include "lcd_te_driver.h"
#include "get_yuv_data.h"
#include "lcd_config.h"
/************视频部分*将摄像头数据显示到lcd上**********************************/
/* 开关打印提示 */
#if 1
#define log_info(x, ...) printf("\n[camera_to_lcd_test]>>>>>>>>>>>>>>>>>>>###" x " \n", ## __VA_ARGS__)
#else
#define log_info(...)
#endif
static void Calculation_frame(void)
{
static u32 tstart = 0, tdiff = 0;
static u8 fps_cnt = 0;
fps_cnt++ ;
if (!tstart) {
tstart = timer_get_ms();
} else {
tdiff = timer_get_ms() - tstart;
if (tdiff >= 1000) {
printf("\n [MSG]fps_count = %d\n", fps_cnt * 1000 / tdiff);
tstart = 0;
fps_cnt = 0;
}
}
}
/********保存JPG图片到SD卡中************/
static void save_jpg_ontime(u8 *buf, u32 len)
{
if (storage_device_ready()) {
char file_name[64];//定义路径存储
snprintf(file_name, 64, CONFIG_ROOT_PATH"JPG/JPG***.JPG");
FILE *fd = fopen(file_name, "wb+");
fwrite(buf, 1, len, fd);
fclose(fd);
log_info("JPG save ok name=JPG\r\n");
}
}
/********保存RGB数据到SD卡中************/
static void get_RGB_save_to_SD(char *RGB, u32 len)
{
if (storage_device_ready()) {
char file_name[64];//定义路径存储
snprintf(file_name, 64, CONFIG_ROOT_PATH"rgb/RGB***.bin");
FILE *fd = fopen(file_name, "wb+");
fwrite(RGB, 1, len, fd);
fclose(fd);
log_info("RGB save ok name=RGB\r\n");
}
}
/********保存YUV数据到SD卡中************/
static void save_YUV_date_ontime(u8 *buf, u32 len)
{
if (storage_device_ready()) {
char file_name[64];//定义路径存储
snprintf(file_name, 64, CONFIG_ROOT_PATH"YUV/YUV***.bin");
FILE *fd = fopen(file_name, "wb+");
fwrite(buf, 1, len, fd);
fclose(fd);
log_info("YUV save ok name=YUV\r\n");
}
}
/********读取JPG数据并保存在SD卡中该数据经过缩放保存大小1280*720********/
#define yuv_out_w 1280
#define yuv_out_h 720
#define in_w 640
#define in_h 480
static void get_JPG_save_to_SD(char *yuv_img_buf)
{
struct jpeg_encode_req req = {0};
u32 buf_len = yuv_out_w * yuv_out_h * 3 / 2 ;
u8 *yuv_out_buf = malloc(buf_len);
u8 err = 0;
if (!yuv_out_buf) {
log_info("jpeg buf not enough err!!!\n");
return;
}
YUV420p_Soft_Scaling(yuv_img_buf, yuv_out_buf, in_w, in_h, yuv_out_w, yuv_out_h);
//q >=2 , size = w*h*q*0.32
req.q = 13; //jepg编码质量(范围0-13),0最小 质量越好,下面的编码buf需要适当增大
req.format = JPG_SAMP_FMT_YUV420;
req.data.buf = yuv_out_buf;
req.data.len = buf_len;
req.width = yuv_out_w ;
req.height = yuv_out_h ;
req.y = yuv_out_buf;
req.u = req.y + (yuv_out_w * yuv_out_h);
req.v = req.u + (yuv_out_w * yuv_out_h) / 4;
err = jpeg_encode_one_image(&req);//获取一张JPG图片
if (!err) {
save_jpg_ontime(req.data.buf, buf_len); //保存图片到SD卡
} else {
log_info("get_jpg err!!!\n");
}
free(yuv_out_buf);
}
/*********摄像头应用部分***********/
static void test_main(u8 *buf, u32 len, yuv_in_w, yuv_in_h)
{
int msg[32];
static u8 time = 0;
if (get_lcd_show_deta_mode() == ui_camera) { //其余模式不需要推摄像头数据
YUV420p_Soft_Scaling(buf, NULL, in_w, in_h, LCD_W, LCD_H);
lcd_show_frame(buf, LCD_YUV420_DATA_SIZE); //240*320*2=153600
}
if (get_lcd_show_deta_mode() == camera) { //其余模式不需要推摄像头数据
YUV420p_Soft_Scaling(buf, NULL, in_w, in_h, LCD_W, LCD_H);
lcd_show_frame(buf, LCD_YUV420_DATA_SIZE); //240*320*2=153600
}
}
void set_video_rt_cb(u32(*cb)(void *, u8 *, u32), void *priv);
int user_net_video_rec_open(char forward);
int user_net_video_rec_close(char forward);
int jpeg2yuv_open(void);
void jpeg2yuv_yuv_callback_register(void (*cb)(u8 *data, u32 len, int width, int height));
int jpeg2yuv_jpeg_frame_write(u8 *buf, u32 len);
void jpeg2yuv_close(void);
static void uvc_video_test(void);
void get_yuv_init(void (*cb)(u8 *data, u32 len, int width, int height));
void camera_to_lcd_init(void)//摄像头选择 并初始化
{
#ifdef CONFIG_UVC_VIDEO2_ENABLE
uvc_video_test();
#else
get_yuv_init(test_main);
#endif
}
void camera_to_lcd_uninit(void)
{
void get_yuv_uninit(void);
get_yuv_uninit();
}
int isc_log_en()//如果定义该函数丢帧信息屏蔽
{
return 0;
}
static void uvc_jpeg_cb(void *hdr, void *data, u32 len)
{
#define JPEG_HEAD 0xE0FFD8FF
#define JPEG_HEAD1 0xC0FFD8FF
u32 *head = (u32 *)data;
if (*head == JPEG_HEAD || *head == JPEG_HEAD1) {
//video
jpeg2yuv_jpeg_frame_write((u8 *)data, len);
} else {
//audio
}
}
static void camera_show_lcd(u8 *buf, u32 size, int width, int height)
{
char *ssid = NULL;
char *pwd = NULL;
#if CONFIG_LCD_QR_CODE_ENABLE
qr_code_get_one_frame_YUV_420(buf, width, height);
qr_get_ssid_pwd(&ssid, &pwd);
printf(">>>>>>>>>>>>>>>sssid = %s, pwd = %s", ssid, pwd);
#endif
YUV420p_Soft_Scaling(buf, NULL, width, height, LCD_W, LCD_H);
lcd_show_frame(buf, LCD_YUV420_DATA_SIZE);
Calculation_frame();
}
static void uvc_video_task(void *priv)
{
int ret;
start:
//0.等待UVC上线
while (!dev_online("uvc")) {
os_time_dly(10);
}
//1.打开jpeg解码YUV
ret = jpeg2yuv_open();
if (ret) {
return;
}
printf(">>>>>>>>>>>>>>>111");
//2.注册YUV数据回调函数
jpeg2yuv_yuv_callback_register(camera_show_lcd);
//3.打开UVC实时流
printf(">>>>>>>>>>>>>>>222");
ret = user_net_video_rec_open(1);
if (ret) {
jpeg2yuv_close();
return;
}
printf(">>>>>>>>>>>>>>>333");
//3.注册jpeg数据回调函数
set_video_rt_cb(uvc_jpeg_cb, NULL);
#if TCFG_LCD_USB_SHOW_COLLEAGUE
void set_tcp_uvc_rt_cb(u32(*cb)(void *priv, void *data, u32 len));
void set_udp_uvc_rt_cb(u32(*cb)(void *priv, void *data, u32 len));
set_udp_uvc_rt_cb(uvc_jpeg_cb); //wifi udp
set_tcp_uvc_rt_cb(uvc_jpeg_cb); //wifi tcp
#endif
//4.检查是否掉线
struct lbuf_test_head *rbuf = NULL;
while (dev_online("uvc")) {
os_time_dly(5);
}
//5.关闭UVC实时流
user_net_video_rec_close(1);
//6.关闭jpeg解码YUV
jpeg2yuv_close();
goto start;
}
static void uvc_video_test(void)
{
thread_fork("uvc_video_task", 5, 1024, 0, 0, uvc_video_task, NULL);
}
#endif