doubao_chat/apps/wifi_ipc/get_yuv_data.c

197 lines
4.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "system/includes.h"
#include "os/os_api.h"
#include "app_config.h"
#include "get_yuv_data.h"
#include "asm/isc.h"
#include "video_ioctl.h"
#include "device.h"
#include "video.h"
#if (defined CONFIG_VIDEO_ENABLE && (__SDRAM_SIZE__ >= (2 * 1024 * 1024)))
#define YUV_TEST 0
#define YUV_BLOCK_SCAN 0
#if YUV_BLOCK_SCAN
static u8 isc_buf[YUV_DATA_WIDTH * 64 * 3 / 2] SEC(.sram) ALIGNE(32);
#endif
//static u8 yuv_buf[YUV_DATA_WIDTH * YUV_DATA_HEIGHT * 3 / 2] ALIGNE(32) SEC(.sram);
static u8 yuv_buf[YUV_DATA_WIDTH * YUV_DATA_HEIGHT * 3 / 2] ALIGNE(32);
static get_yuv_cfg __info;
static int yuv420_block_scan(void *info)
{
struct yuv_block_info *yuv_info = (struct yuv_block_info *)info;
/*
*算法处理,禁止加延时函数!
*/
if (yuv_info->start) { //帧起始第一个分块
} else {
}
return 0;
}
static void get_yuv_task(void *priv)
{
int err;
struct video_format f = {0};
struct yuv_image yuv = {0};
void *dev;
void (*cb)(u8 * data, u32 len, int width, int height);
/*
*step 1
*/
dev = dev_open(YUV_DATA_SOURCE, NULL);
if (!dev) {
printf("open video err !!!!\n\n");
return;
}
#if 0
/********************YUV内部加外部双BUF,上层处理时间可长一些************************/
/*
*step 2
*/
f.type = VIDEO_BUF_TYPE_VIDEO_OVERLAY;
f.pixelformat = VIDEO_PIX_FMT_YUV420;
#if YUV_BLOCK_SCAN
f.static_buf = (u8 *)isc_buf;
f.sbuf_size = sizeof(isc_buf);
f.block_done_cb = yuv420_block_scan;
#endif
err = dev_ioctl(dev, VIDIOC_SET_FMT, (u32)&f);
if (err) {
goto error;
}
/*
*step 3
*/
//BUFF配置1:使用外部BUFF,上层处理时间最大为摄像头的帧率时间 - 15ms,GC0308默认驱动处理最大时间35m
#if 1 //YUV分块(行)回调,用不到yuv一帧,则关闭
yuv.addr = (u8 *)yuv_buf;
yuv.size = sizeof(yuv_buf);
#endif
err = dev_ioctl(dev, VIDIOC_SET_OVERLAY, (u32)&yuv);
if (err) {
goto error;
}
#else
/********************YUV支持外部静态BUF,上层处理时间较短************************/
/*
*step 2
*/
f.type = VIDEO_BUF_TYPE_VIDEO_OVERLAY;
f.pixelformat = VIDEO_PIX_FMT_YUV420;
f.static_buf = (u8 *)yuv_buf;
f.sbuf_size = sizeof(yuv_buf);
#if YUV_BLOCK_SCAN
f.block_done_cb = yuv420_block_scan;
#endif
err = dev_ioctl(dev, VIDIOC_SET_FMT, (u32)&f);
if (err) {
goto error;
}
//BUFF配置2:使用内部BUFF,内存节省450K,上层处理时间最大为摄像头的帧结束到帧起始时间,需要看摄像头帧同步信号波形测量,GC0308默认驱动处理最大时间16ms
err = dev_ioctl(dev, VIDIOC_SET_OVERLAY, (u32)0);
if (err) {
goto error;
}
#endif
#if YUV_TEST
FILE *fd = fopen(CONFIG_ROOT_PATH"yuv_1.yuv", "wb+");
int cnt = 0;
#endif
while (1) {
if (thread_kill_req()) {
break;
}
cb = __info.cb;
/*
*step 4
*/
err = dev_ioctl(dev, VIDIOC_GET_OVERLAY, (u32)&yuv);
if (!err) {
//do something in this step
#if YUV_TEST
if (fd) {
cnt++;
fwrite(yuv.addr, 1, yuv.size, fd);
if (cnt > 100) {
fclose(fd);
fd = NULL;
}
printf("write file ok : %d \n", cnt);
}
#else
if (cb) {
cb(yuv.addr, yuv.size, YUV_DATA_WIDTH, YUV_DATA_HEIGHT);
}
#endif
}
#if YUV_TEST
else if (fd) {
fclose(fd);
fd = NULL;
}
#endif
/*
*step 5
*/
dev_ioctl(dev, VIDIOC_CLEAR_OVERLAY, 0);
}
error:
/*
*step 6
*/
dev_close(dev);
__info.init = 0;
}
void get_yuv_init(void (*cb)(u8 *data, u32 len, int width, int height))
{
if (__info.init) {
return;
}
__info.init = 1;
__info.cb = cb;
#ifdef CONFIG_QR_CODE_NET_CFG
extern u8 is_in_config_network_state(void);
if (is_in_config_network_state()) { //二维码配网时才需要大堆栈
thread_fork("GET_YUV_TASK", 8, 1024 * 5, 0, &__info.pid, get_yuv_task, NULL);
} else
#endif
{
thread_fork("GET_YUV_TASK", 4, 1024, 0, &__info.pid, get_yuv_task, NULL);
}
}
void get_yuv_uninit(void)
{
if (!__info.init) {
return;
}
thread_kill(&__info.pid, KILL_WAIT);
__info.cb = NULL;
__info.init = 0;
}
void set_get_yuv_data_cb(void (*cb)(u8 *data, u32 len, int width, int height))
{
__info.cb = cb;
}
#endif