288 lines
7.8 KiB
C
288 lines
7.8 KiB
C
|
|
/***************************************************************************************
|
||
|
|
S_PREVIEW_SCALE3 ----> R_VIDEO_P0(320x180)
|
||
|
|
(scale3) (lcd_video_p0)
|
||
|
|
|
||
|
|
RS_JPG_CONCAT ----> R_LVGL_TAKEPHOTO(1280x720)
|
||
|
|
(mjpeg)
|
||
|
|
***************************************************************************************/
|
||
|
|
#include "lvgl/lvgl.h"
|
||
|
|
#include "lvgl_ui.h"
|
||
|
|
#include "stream_frame.h"
|
||
|
|
#include "keyWork.h"
|
||
|
|
#include "keyScan.h"
|
||
|
|
#include "fatfs/osal_file.h"
|
||
|
|
#include "lib/heap/av_heap.h"
|
||
|
|
#include "lib/heap/av_psram_heap.h"
|
||
|
|
|
||
|
|
//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 LV_OBJ_TAKEPHOTO_FLAG LV_OBJ_FLAG_USER_1
|
||
|
|
|
||
|
|
extern lv_indev_t * indev_keypad;
|
||
|
|
extern lv_style_t g_style;
|
||
|
|
|
||
|
|
struct preview_encode_takephoto_ui_s
|
||
|
|
{
|
||
|
|
lv_group_t *last_group;
|
||
|
|
lv_obj_t *base_ui;
|
||
|
|
lv_group_t *now_group;
|
||
|
|
lv_obj_t *now_ui;
|
||
|
|
lv_timer_t *timer;
|
||
|
|
|
||
|
|
struct msi *s;
|
||
|
|
struct msi *jpg_s;
|
||
|
|
struct msi *takephoto_s;
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
static uint32_t self_key(uint32_t val)
|
||
|
|
{
|
||
|
|
uint32_t key_ret = 0;
|
||
|
|
if(val > 0)
|
||
|
|
{
|
||
|
|
if((val&0xff) == KEY_EVENT_SUP)
|
||
|
|
{
|
||
|
|
switch(val>>8)
|
||
|
|
{
|
||
|
|
case AD_UP:
|
||
|
|
key_ret = 'a';
|
||
|
|
break;
|
||
|
|
case AD_DOWN:
|
||
|
|
key_ret = 's';
|
||
|
|
break;
|
||
|
|
case AD_LEFT:
|
||
|
|
key_ret = 'q';
|
||
|
|
break;
|
||
|
|
case AD_RIGHT:
|
||
|
|
key_ret = 'd';
|
||
|
|
break;
|
||
|
|
case AD_PRESS:
|
||
|
|
key_ret = LV_KEY_ENTER;
|
||
|
|
break;
|
||
|
|
|
||
|
|
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if((val&0xff) == KEY_EVENT_LUP)
|
||
|
|
{
|
||
|
|
|
||
|
|
|
||
|
|
switch(val>>8)
|
||
|
|
{
|
||
|
|
case AD_PRESS:
|
||
|
|
key_ret = 'e';
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return key_ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//生成一个流,专门接收图片,用于拍照的,拍照之前可以将缓冲区的删除,这样可以保证得到最新的图片
|
||
|
|
//要考虑一些问题,如果拍照放在workqueue,要考虑写卡时间是否影响workqueue
|
||
|
|
//这里尝试使用lvgl的timer事件去保存(影响lvgl,如果需要更加好,可能要创建任务去保存)
|
||
|
|
|
||
|
|
static int32 takephoto_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||
|
|
{
|
||
|
|
int32_t ret = RET_OK;
|
||
|
|
//struct preview_encode_takephoto_ui_s *ui_s = (struct preview_encode_takephoto_ui_s *)msi->priv;
|
||
|
|
|
||
|
|
switch (cmd_id)
|
||
|
|
{
|
||
|
|
case MSI_CMD_PRE_DESTROY:
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MSI_CMD_POST_DESTROY:
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case MSI_CMD_FREE_FB:
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
static struct msi *takephoto_stream(const char *name)
|
||
|
|
{
|
||
|
|
//设置接收1,是为了不要接收太多的图片,因为是拍照,需要保持实时性
|
||
|
|
//如果接收过多,如果不处理,会导致源头没有空间产生新的图片
|
||
|
|
//如果要结合录像,则需要在应用层去处理(实际录像时可以创建另一个独立的流)
|
||
|
|
struct msi *msi = msi_new(name, 1, NULL);
|
||
|
|
return msi;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void takephoto_timer(lv_timer_t *t)
|
||
|
|
{
|
||
|
|
struct preview_encode_takephoto_ui_s *ui_s = (struct preview_encode_takephoto_ui_s *)t->user_data;
|
||
|
|
struct framebuff *fb = NULL;
|
||
|
|
//看看对应的流有没有图片,如果有,则保存
|
||
|
|
fb = msi_get_fb(ui_s->takephoto_s, 0);
|
||
|
|
if(fb)
|
||
|
|
{
|
||
|
|
ui_s->takephoto_s->enable = 0;
|
||
|
|
char filename[64];
|
||
|
|
sprintf(filename,"0:/photo/%08d.jpg",(uint32_t)os_jiffies());
|
||
|
|
void *fp = osal_fopen(filename,"wb");
|
||
|
|
if(fp)
|
||
|
|
{
|
||
|
|
osal_fwrite(fb->data,1,fb->len,fp);
|
||
|
|
osal_fclose(fp);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
os_printf("takephoto fail,filename:%s\n",filename);
|
||
|
|
}
|
||
|
|
//保存图片
|
||
|
|
msi_delete_fb(NULL, fb);
|
||
|
|
|
||
|
|
while(fb)
|
||
|
|
{
|
||
|
|
fb = msi_get_fb(ui_s->takephoto_s, 0);
|
||
|
|
if(fb)
|
||
|
|
{
|
||
|
|
msi_delete_fb(NULL, fb);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
os_printf("takephoto success\n");
|
||
|
|
lv_obj_clear_flag(ui_s->now_ui, LV_OBJ_TAKEPHOTO_FLAG);
|
||
|
|
ui_s->timer = NULL;
|
||
|
|
lv_timer_del(t);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//使能拍照
|
||
|
|
static void encode_takephoto_ui(lv_event_t * e)
|
||
|
|
{
|
||
|
|
struct preview_encode_takephoto_ui_s *ui_s = (struct preview_encode_takephoto_ui_s *)lv_event_get_user_data(e);
|
||
|
|
struct msi *s = ui_s->takephoto_s;
|
||
|
|
int32_t c = *((int32_t *)lv_event_get_param(e));
|
||
|
|
if(c == LV_KEY_ENTER)
|
||
|
|
{
|
||
|
|
if(!lv_obj_has_flag(ui_s->now_ui,LV_OBJ_TAKEPHOTO_FLAG))
|
||
|
|
{
|
||
|
|
lv_obj_add_flag(ui_s->now_ui, LV_OBJ_TAKEPHOTO_FLAG);
|
||
|
|
s->enable = 1;
|
||
|
|
//启动timer,10ms检查一次
|
||
|
|
ui_s->timer = lv_timer_create(takephoto_timer, 10, (void*)ui_s);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
//已经在拍照了
|
||
|
|
os_printf("%s already running\n",__FUNCTION__);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static void exit_preview_encode_takephoto_ui(lv_event_t * e)
|
||
|
|
{
|
||
|
|
struct preview_encode_takephoto_ui_s *ui_s = (struct preview_encode_takephoto_ui_s *)lv_event_get_user_data(e);
|
||
|
|
int32_t c = *((int32_t *)lv_event_get_param(e));
|
||
|
|
if(c == 'q')
|
||
|
|
{
|
||
|
|
if(ui_s->timer)
|
||
|
|
{
|
||
|
|
lv_timer_del(ui_s->timer);
|
||
|
|
}
|
||
|
|
struct preview_encode_takephoto_ui_s *ui_s = (struct preview_encode_takephoto_ui_s *)lv_event_get_user_data(e);
|
||
|
|
lv_indev_set_group(indev_keypad, ui_s->last_group);
|
||
|
|
lv_obj_clear_flag(ui_s->base_ui, LV_OBJ_FLAG_HIDDEN);
|
||
|
|
lv_group_del(ui_s->now_group);
|
||
|
|
ui_s->now_group = NULL;
|
||
|
|
msi_destroy(ui_s->s);
|
||
|
|
msi_del_output(ui_s->jpg_s, NULL, R_LVGL_TAKEPHOTO);
|
||
|
|
msi_put(ui_s->jpg_s);
|
||
|
|
msi_destroy(ui_s->takephoto_s);
|
||
|
|
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 0);
|
||
|
|
lv_obj_del(ui_s->now_ui);
|
||
|
|
|
||
|
|
set_lvgl_get_key_func(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
//进入预览的ui,那么就要创建新的ui去显示预览图了
|
||
|
|
static void enter_preview_encode_takephoto_ui(lv_event_t * e)
|
||
|
|
{
|
||
|
|
set_lvgl_get_key_func(self_key);
|
||
|
|
struct preview_encode_takephoto_ui_s *ui_s = (struct preview_encode_takephoto_ui_s *)lv_event_get_user_data(e);
|
||
|
|
lv_obj_add_flag(ui_s->base_ui, LV_OBJ_FLAG_HIDDEN);
|
||
|
|
lv_obj_t *ui = lv_obj_create(lv_scr_act());
|
||
|
|
ui_s->now_ui = ui;
|
||
|
|
lv_obj_add_style(ui, &g_style, 0);
|
||
|
|
lv_obj_set_size(ui, LV_PCT(100), LV_PCT(100));
|
||
|
|
ui_s->s = scale3_msi(S_PREVIEW_SCALE3);
|
||
|
|
//绑定流到Video P0显示
|
||
|
|
if (ui_s->s)
|
||
|
|
{
|
||
|
|
msi_add_output(ui_s->s, NULL, R_VIDEO_P0);
|
||
|
|
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||
|
|
ui_s->s->enable = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
//创建jpg流,设置从vpp_buf0取数据
|
||
|
|
ui_s->jpg_s = msi_find(AUTO_JPG, 1);
|
||
|
|
if(ui_s->jpg_s)
|
||
|
|
{
|
||
|
|
msi_add_output(ui_s->jpg_s, NULL, R_LVGL_TAKEPHOTO);
|
||
|
|
ui_s->jpg_s->enable = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
ui_s->takephoto_s = takephoto_stream(R_LVGL_TAKEPHOTO);
|
||
|
|
if(ui_s->takephoto_s)
|
||
|
|
{
|
||
|
|
ui_s->takephoto_s->action = takephoto_msi_action;
|
||
|
|
ui_s->takephoto_s->priv = ui_s;
|
||
|
|
}
|
||
|
|
|
||
|
|
lv_group_t *group;
|
||
|
|
group = lv_group_create();
|
||
|
|
lv_indev_set_group(indev_keypad, group);
|
||
|
|
|
||
|
|
lv_group_add_obj(group, ui);
|
||
|
|
ui_s->now_group = group;
|
||
|
|
lv_obj_add_event_cb(ui, exit_preview_encode_takephoto_ui, LV_EVENT_KEY, ui_s);
|
||
|
|
|
||
|
|
//拍照的按键事件
|
||
|
|
lv_obj_add_event_cb(ui, encode_takephoto_ui, LV_EVENT_KEY, ui_s);
|
||
|
|
}
|
||
|
|
|
||
|
|
lv_obj_t *preview_encode_takephoto_ui(lv_group_t *group,lv_obj_t *base_ui)
|
||
|
|
{
|
||
|
|
struct preview_encode_takephoto_ui_s *ui_s = (struct preview_encode_takephoto_ui_s*)STREAM_LIBC_ZALLOC(sizeof(struct preview_encode_takephoto_ui_s));
|
||
|
|
ui_s->last_group = group;
|
||
|
|
ui_s->base_ui = base_ui;
|
||
|
|
lv_obj_t *btn = lv_list_add_btn(base_ui, NULL, "preview_encode_takephoto");
|
||
|
|
lv_group_add_obj(group, btn);
|
||
|
|
lv_obj_add_event_cb(btn, enter_preview_encode_takephoto_ui, LV_EVENT_SHORT_CLICKED, ui_s);
|
||
|
|
return btn;
|
||
|
|
}
|