pure sdk for main
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
//主要作用是独立usb模块创建流,这个主要是转发用
|
||||
//因为usb流的根据usb创建成功自动创建的,所以需要创建一个流专门接收转发,流名字也是固定的
|
||||
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/task.h"
|
||||
#include "decode/jpg_decode_stream.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal_file.h"
|
||||
#include "jpgdef.h"
|
||||
#include "utlist.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
|
||||
//data申请空间函数
|
||||
#define STREAM_MALLOC custom_malloc_psram
|
||||
#define STREAM_FREE custom_free_psram
|
||||
#define STREAM_ZALLOC custom_zalloc_psram
|
||||
|
||||
//结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC custom_malloc
|
||||
#define STREAM_LIBC_FREE custom_free
|
||||
#define STREAM_LIBC_ZALLOC custom_zalloc
|
||||
|
||||
|
||||
//因为是转发的流,获取源头的data长度
|
||||
static uint32_t custom_get_data_len(void *data)
|
||||
{
|
||||
struct data_structure *data_s = (struct data_structure *)data;
|
||||
return get_stream_real_data_len(data_s->data);
|
||||
}
|
||||
|
||||
static void *custom_get_data(void *data)
|
||||
{
|
||||
|
||||
struct data_structure *data_s = (struct data_structure *)data;
|
||||
return get_stream_real_data(data_s->data);
|
||||
}
|
||||
|
||||
static uint32_t custom_get_data_time(void *data)
|
||||
{
|
||||
struct data_structure *data_s = (struct data_structure *)data;
|
||||
return get_stream_data_timestamp(data_s->data);
|
||||
}
|
||||
|
||||
static uint32_t independ_custom_func_psram(void *data,int opcode,void *priv)
|
||||
{
|
||||
struct data_structure *data_s = (struct data_structure *)data;
|
||||
return stream_data_custom_cmd_func(data_s->data,opcode,priv);
|
||||
}
|
||||
|
||||
//这个是转发的流,只是添加一些必要信息,所以这里获取的data信息要更换
|
||||
static const stream_ops_func stream_jpg_ops =
|
||||
{
|
||||
.get_data_len = custom_get_data_len,
|
||||
.get_data = custom_get_data,
|
||||
.get_data_time = custom_get_data_time,
|
||||
.custom_func = independ_custom_func_psram,
|
||||
};
|
||||
|
||||
struct independ_video_usb_s
|
||||
{
|
||||
struct os_work work;
|
||||
stream *s;
|
||||
struct data_structure *data_s;
|
||||
};
|
||||
|
||||
|
||||
static int32 independ_video_usb_work(struct os_work *work)
|
||||
{
|
||||
|
||||
struct independ_video_usb_s *video_usb = (struct independ_video_usb_s *)work;
|
||||
struct data_structure *data_s = NULL;
|
||||
if(video_usb->data_s)
|
||||
{
|
||||
data_s = get_src_data_f(video_usb->s);
|
||||
//准备填好显示、解码参数信息,然后发送到解码的模块去解码,主要如果没有成功要如何处理,这里没有考虑
|
||||
if(data_s)
|
||||
{
|
||||
data_s->data = video_usb->data_s;
|
||||
data_s->type = video_usb->data_s->type;
|
||||
data_s->magic = video_usb->data_s->magic;
|
||||
send_data_to_stream(data_s);
|
||||
video_usb->data_s = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//先获取一下是否有接收到需要解码的图片,下一次才进行解码
|
||||
video_usb->data_s = recv_real_data(video_usb->s);
|
||||
}
|
||||
|
||||
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opcode_func_not_bind(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
struct independ_video_usb_s *video_usb = (struct independ_video_usb_s*)STREAM_LIBC_ZALLOC(sizeof(struct independ_video_usb_s));
|
||||
s->priv = (void*)video_usb;
|
||||
video_usb->s = s;
|
||||
stream_data_dis_mem_custom(s);
|
||||
OS_WORK_INIT(&video_usb->work, independ_video_usb_work, 0);
|
||||
os_run_work_delay(&video_usb->work, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
|
||||
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
|
||||
//如果不想提前申请内存,这里可以使用的时候才申请,主要看自己规划如何去释放
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
data->ops = (stream_ops_func*)&stream_jpg_ops;
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->data)
|
||||
{
|
||||
//因为是转发,所以这里移除的话是交给原来的方法移除
|
||||
free_data(data->data);
|
||||
data->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STREAM_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//os_printf("%s:%d\tdata:%X\ttype:%d\tlen:%d\n",__FUNCTION__,__LINE__,data,GET_DATA_TYPE1(data->type),get_stream_real_data_len(data));
|
||||
if(GET_DATA_TYPE1(data->type) != JPEG)
|
||||
{
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成,可以选择唤醒对应的任务
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
break;
|
||||
|
||||
|
||||
case STREAM_SEND_DATA_START:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
struct independ_video_usb_s *video_usb = (struct independ_video_usb_s *)s->priv;
|
||||
os_work_cancle2(&video_usb->work, 1);
|
||||
if(video_usb->data_s)
|
||||
{
|
||||
free_data(video_usb->data_s);
|
||||
}
|
||||
|
||||
STREAM_LIBC_FREE(video_usb);
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_MARK_GC_END:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//动态绑定,但是名称已经被固定了,因为usb数据流是固定的
|
||||
stream *independ_video_usb()
|
||||
{
|
||||
stream *s = open_stream_available(SR_VIDEO_USB, 8, 8, opcode_func_not_bind,(void*)NULL);
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,890 @@
|
||||
/****************************************************************************************************************
|
||||
根据video_app.c,重写,video_app.c保留是为了旧项目尽可能兼容,所以new_video_app.c和video_app.c实际是互斥的,这个要注意
|
||||
*****************************************************************************************************************/
|
||||
#include "new_video_app.h"
|
||||
|
||||
//临时利用,V200接口需要用到
|
||||
#include "devid.h"
|
||||
|
||||
#if JPG_EN == 1
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "hal/jpeg.h"
|
||||
#include "hal/vpp.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "lib/lcd/gui.h"
|
||||
#include "lib/video/dvp/jpeg/jpg.h"
|
||||
#include "osal/irq.h"
|
||||
typedef int32_t (*jpg_pixel_done_prc)(uint32 irq_flag,uint32 irq_data,uint32 param1,uint32 param2);
|
||||
static const char *g_name = NULL;
|
||||
extern uint32_t get_jpg_default_dpi(uint8_t id);
|
||||
extern void set_jpg_w_h(uint8 jpg_num,uint16_t w,uint16_t h);
|
||||
extern void jpg_cfg_vpp(uint8 jpgid,enum JPG_SRC_FROM src_from);
|
||||
extern void jpg_cfg_prc(uint8 jpgid,enum JPG_SRC_FROM src_from,jpg_pixel_done_prc done_prc,void *dev_id);
|
||||
|
||||
//data申请空间函数
|
||||
#define STREAM_MALLOC custom_malloc_psram
|
||||
#define STREAM_FREE custom_free_psram
|
||||
#define STREAM_ZALLOC custom_zalloc_psram
|
||||
|
||||
//结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC custom_malloc
|
||||
#define STREAM_LIBC_FREE custom_free
|
||||
#define STREAM_LIBC_ZALLOC custom_zalloc
|
||||
|
||||
struct video_app_s
|
||||
{
|
||||
struct os_work work;
|
||||
stream *s;
|
||||
struct jpg_device *jpg_dev;
|
||||
void *prc_done; //保留prc的中断函数
|
||||
void *prc_arg; //保留prc的中断参数
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *arg1;
|
||||
void *arg2;
|
||||
}custom_struct;
|
||||
|
||||
extern void jpg_start_dpi(uint8 jpg_num,uint16_t w,uint16_t h);
|
||||
static void start_jpeg_hardware(struct video_app_s *msg)
|
||||
{
|
||||
//为了尽量保留旧逻辑,这里用宏去隔离,新框架要使用msg参数
|
||||
jpg_recfg(0);
|
||||
if(msg)
|
||||
{
|
||||
jpg_start_dpi(0,msg->w,msg->h);
|
||||
}
|
||||
else
|
||||
{
|
||||
jpg_start(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void stop_jpeg_hardware()
|
||||
{
|
||||
jpg_stop(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct jpg_frame_msg
|
||||
{
|
||||
uint32_t len;
|
||||
void *malloc_mem;
|
||||
};
|
||||
|
||||
static uint32_t get_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
uint32_t len = 0;
|
||||
if(j)
|
||||
{
|
||||
len = j->len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint32_t jpg_custom_func(void *data,int opcode,void *priv);
|
||||
static int32 stream_get_jpg_work(struct os_work *work);
|
||||
|
||||
|
||||
//一次性将节点清除
|
||||
static void free_all_jpg_node(struct list_head *get_f)
|
||||
{
|
||||
|
||||
while(!list_empty(get_f))
|
||||
{
|
||||
del_jpeg_first_node(get_f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const stream_ops_func stream_jpg_ops =
|
||||
{
|
||||
.get_data_len = get_data_len,
|
||||
.custom_func = jpg_custom_func,
|
||||
};
|
||||
|
||||
static uint32_t jpg_custom_func(void *data,int opcode,void *priv)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
uint32_t flags;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
switch(opcode)
|
||||
{
|
||||
case CUSTOM_GET_NODE_LEN:
|
||||
{
|
||||
|
||||
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
res = get_jpg_node_len(0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
res = j->len;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case CUSTOM_GET_NODE_BUF:
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
res = (uint32_t)get_jpeg_node_buf(priv);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
res = (uint32_t)priv;
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case CUSTOM_GET_FIRST_BUF:
|
||||
{
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(data);
|
||||
//头是固定用,next才是真正的数据
|
||||
if(dest_list->next)
|
||||
{
|
||||
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
res =(uint32) get_jpeg_node_buf(dest_list->next->data);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
res =(uint32) dest_list->next->data;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_FREE_NODE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(el->data)
|
||||
{
|
||||
|
||||
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_DEL_NODE:
|
||||
{
|
||||
uint32_t ref;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *el = (struct stream_jpeg_data_s *)priv;
|
||||
flags = disable_irq();
|
||||
ref = --el->ref;
|
||||
enable_irq(flags);
|
||||
if(!ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_GET_NODE_COUNT:
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
//struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
LL_COUNT(dest_list,el,res);
|
||||
res -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint32_t stream_cmd_func(stream *s,int cmd,uint32_t arg)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
//暂时没有考虑重复close jpg_hardware的情况
|
||||
case RESET_MJPEG_DPI:
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
os_work_cancle2(&msg->work,1);
|
||||
stop_jpeg_hardware();
|
||||
uint32_t w_h = (uint32_t)arg;
|
||||
os_printf("w_h:%X\n",w_h);
|
||||
msg->w = w_h>>16;
|
||||
msg->h = w_h&0xffff;
|
||||
start_jpeg_hardware(msg);
|
||||
OS_WORK_REINIT(&msg->work);
|
||||
os_run_work_delay(&msg->work, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
//停止命令
|
||||
case STREAM_STOP_CMD:
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
os_work_cancle2(&msg->work,1);
|
||||
stop_jpeg_hardware();
|
||||
}
|
||||
break;
|
||||
|
||||
case RESET_MJPEG_FROM:
|
||||
{
|
||||
if(arg == 0)
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
jpg_cfg_prc(HG_JPG0_DEVID,SOFT_DATA,(jpg_pixel_done_prc)msg->prc_done,(void*)msg->prc_arg);
|
||||
}
|
||||
else if(arg == 1)
|
||||
{
|
||||
jpg_cfg_vpp(HG_JPG0_DEVID,VPP_DATA0);
|
||||
}
|
||||
else if(arg == 2)
|
||||
{
|
||||
jpg_cfg_vpp(HG_JPG0_DEVID,SCALER_DATA);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case PRC_MJPEG_KICK:
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
jpg_soft_kick(msg->jpg_dev,arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case PRC_REGISTER_ISR:
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
custom_struct *rec_arg = (custom_struct*)arg;
|
||||
msg->prc_done = (void*)rec_arg->arg1;
|
||||
msg->prc_arg = (void*)rec_arg->arg2;
|
||||
|
||||
jpg_cfg_prc(HG_JPG0_DEVID,SOFT_DATA,(jpg_pixel_done_prc)msg->prc_done,(void*)msg->prc_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_CHECK_NAME:
|
||||
//因为这个流要和硬件绑定,所以无论名字是否被改,都只能一个,这里判断如果已经创建了,就返回错误,不要创建
|
||||
//已经创建了,比较一下
|
||||
if(g_name)
|
||||
{
|
||||
//比较一下名字,不同名称,代表已经有创建过了
|
||||
if(strcmp(g_name,(char*)priv))
|
||||
{
|
||||
res = 1;
|
||||
os_printf("new video app err\t%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
g_name = (char*)priv;
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
s->priv = (struct video_app_s*) STREAM_LIBC_ZALLOC(sizeof(struct video_app_s));
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
msg->s = s;
|
||||
msg->jpg_dev = (struct jpg_device *)dev_get(HG_JPG0_DEVID);
|
||||
stream_data_dis_mem_custom(s);
|
||||
register_stream_self_cmd_func(s,stream_cmd_func);
|
||||
//启动jpeg流
|
||||
|
||||
|
||||
//这里实际是为了兼容旧逻辑产生的
|
||||
//设置mjpeg的默认值
|
||||
uint32_t w_h = get_jpg_default_dpi(0);
|
||||
msg->w = w_h>>16;
|
||||
msg->h = w_h&0xffff;
|
||||
start_jpeg_hardware(msg);
|
||||
//启动workqueue
|
||||
OS_WORK_INIT(&msg->work, stream_get_jpg_work, 0);
|
||||
os_run_work_delay(&msg->work, 1);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//注册对应函数
|
||||
data->ops = (stream_ops_func*)&stream_jpg_ops;
|
||||
data->data = NULL;
|
||||
data->priv = (struct jpg_frame_msg*)STREAM_LIBC_MALLOC(sizeof(struct jpg_frame_msg));
|
||||
if(data->priv)
|
||||
{
|
||||
memset(data->priv,0,sizeof(struct jpg_frame_msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("malloc mem fail,%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(data->priv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//如果释放空间,则删除所有的节点
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(dest_list_tmp == el)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(el->data)
|
||||
{
|
||||
//这里只要判断type2,因为默认type1一定是JPEG
|
||||
if(GET_DATA_TYPE2(data->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(data->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data->priv;
|
||||
if(j)
|
||||
{
|
||||
STREAM_LIBC_FREE(j->malloc_mem);
|
||||
j->malloc_mem = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
//每次即将发送到一个流,就调用一次
|
||||
case STREAM_SEND_TO_DEST:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref++;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
//这里只要判断type2,因为默认type1一定是JPEG
|
||||
if(GET_DATA_TYPE2(data->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(data->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//退出,则关闭对应得流
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
os_work_cancle2(&msg->work,1);
|
||||
stop_jpeg_hardware();
|
||||
if(msg)
|
||||
{
|
||||
STREAM_LIBC_FREE(msg);
|
||||
s->priv = NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_MARK_GC_END:
|
||||
//这里代表流已经完毕,也代表整个数据流已经被关闭了
|
||||
g_name = NULL; //代表该硬件已经用完
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void jpeg_in_sram(struct os_work *work,struct list_head *get_f)
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s *)work;
|
||||
stream *s = msg->s;
|
||||
struct list_head *data;
|
||||
int err = 1;
|
||||
if(get_f)
|
||||
{
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
int get_f_count = get_node_count(get_f);
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)STREAM_LIBC_MALLOC((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
|
||||
//节点进行提取到stream里面,如果节点不够,也要删除已经提取的节点(理论节点与jpeg节点一致,不应该不一样)
|
||||
//先判断get_f的节点数量是多少
|
||||
while(m && get_f_count--)
|
||||
{
|
||||
//图片节点提取
|
||||
if(list_empty(get_f))
|
||||
{
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
el = m++;
|
||||
//保存next
|
||||
data = get_f->next;
|
||||
//将next断开
|
||||
list_del(get_f->next);
|
||||
el->data = (void*)data;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
err = 0;
|
||||
//添加到另一个链表
|
||||
LL_APPEND(dest_list,el);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct data_structure *data_s = NULL;
|
||||
//没有错误的情况才去申请空间
|
||||
if(!err)
|
||||
{
|
||||
data_s = get_src_data_f(s);
|
||||
if(data_s)
|
||||
{
|
||||
//设置这个为正常图片的的形式
|
||||
data_s->type = SET_DATA_TYPE(JPEG,JPEG_DVP_NODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(err || !data_s || !data_s->priv)
|
||||
{
|
||||
del_jpeg_frame(get_f);
|
||||
//清除已经提取的图片节点
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref = 0;
|
||||
el->next = NULL;
|
||||
if(el->data)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
el->data = NULL;
|
||||
}
|
||||
STREAM_LIBC_FREE(dest_list);
|
||||
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//数据绑定
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
//设置这个为图片节点形式,接收端需要根据这个去实现读取图片方式
|
||||
data_s->type = SET_DATA_TYPE(JPEG,JPEG_DVP_NODE);
|
||||
set_stream_data_time(data_s,os_jiffies());
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = get_jpeg_len(get_f);
|
||||
j->malloc_mem = dest_list;
|
||||
del_jpeg_frame(get_f);
|
||||
//统一发送数据,这个时候,其他流才有可能获取到数据
|
||||
_os_printf("$");
|
||||
send_data_to_stream(data_s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
static void jpeg_in_psram(struct os_work *work,struct list_head *get_f)
|
||||
{
|
||||
|
||||
struct video_app_s *msg = (struct video_app_s *)work;
|
||||
stream *s = msg->s;
|
||||
uint8_t *tmp_buf;
|
||||
int err = 1;
|
||||
uint32_t jpg_len,jpg_len_tmp,cp_offset,cp_len;
|
||||
uint8_t *jpg_psram_space = NULL;
|
||||
uint32_t node_len;
|
||||
|
||||
if(get_f)
|
||||
{
|
||||
node_len = get_jpg_node_len_new((void*)get_f);
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
jpg_len = get_jpeg_len(get_f);
|
||||
//os_printf("get_f:%X\tjpg_len:%d\n",get_f,jpg_len);
|
||||
//带psram的情况下,这里总是等于1,因为psram空间大,一张图片约30KB的情况,可以尽量保证图片在内存是连续的
|
||||
int get_f_count = 1;
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
|
||||
//与无psram的结构同步,用于兼容
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)STREAM_LIBC_MALLOC((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
jpg_psram_space = (uint8_t*)custom_malloc_psram(jpg_len);
|
||||
jpg_len_tmp = jpg_len;
|
||||
cp_offset = 0;
|
||||
|
||||
if(m)
|
||||
{
|
||||
el = m;
|
||||
//节点先添加
|
||||
el->data = (void*)jpg_psram_space;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
LL_APPEND(dest_list,el);
|
||||
}
|
||||
//节点进行提取到stream里面,如果节点不够,也要删除已经提取的节点(理论节点与jpeg节点一致,不应该不一样)
|
||||
//先判断get_f的节点数量是多少
|
||||
while(jpg_psram_space && m)
|
||||
{
|
||||
|
||||
//图片节点提取
|
||||
if(list_empty(get_f) || jpg_len_tmp == 0)
|
||||
{
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(jpg_len_tmp > node_len)
|
||||
{
|
||||
cp_len = node_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
cp_len = jpg_len_tmp;
|
||||
}
|
||||
jpg_len_tmp -= cp_len;
|
||||
tmp_buf = get_jpeg_first_buf(get_f);
|
||||
|
||||
|
||||
hw_memcpy0(jpg_psram_space+cp_offset,get_jpeg_first_buf(get_f),cp_len);
|
||||
del_jpeg_first_node(get_f);
|
||||
cp_offset += cp_len;
|
||||
}
|
||||
|
||||
struct data_structure *data_s = NULL;
|
||||
//没有错误的情况才去申请空间
|
||||
if(!err)
|
||||
{
|
||||
data_s = get_src_data_f(s);
|
||||
if(data_s)
|
||||
{
|
||||
//设置这个为正常图片的的形式
|
||||
data_s->type = SET_DATA_TYPE(JPEG,JPEG_DVP_FULL);
|
||||
}
|
||||
|
||||
}
|
||||
if(err || !data_s || !data_s->priv || !jpg_psram_space)
|
||||
{
|
||||
del_jpeg_frame(get_f);
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//清除已经提取的图片节点
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref = 0;
|
||||
el->next = NULL;
|
||||
//理论psram的空间在这里释放
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
el->data = NULL;
|
||||
}
|
||||
STREAM_LIBC_FREE(dest_list);
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//数据绑定
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
|
||||
set_stream_data_time(data_s,os_jiffies());
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = jpg_len;
|
||||
j->malloc_mem = dest_list;
|
||||
del_jpeg_frame(get_f);
|
||||
//统一发送数据,这个时候,其他流才有可能获取到数据
|
||||
_os_printf("V");
|
||||
send_data_to_stream(data_s);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32 stream_get_jpg_work(struct os_work *work)
|
||||
{
|
||||
//首先获取节点先
|
||||
uint32_t flags;
|
||||
|
||||
flags = disable_irq();
|
||||
struct list_head *get_f = (void*)get_frame(HG_JPG0_DEVID);
|
||||
enable_irq(flags);
|
||||
|
||||
if(get_f)
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s *)work;
|
||||
//如果流没有使能,就移除节点,这个时候硬件应该是动起来了
|
||||
if(msg->s->enable)
|
||||
{
|
||||
#ifdef PSRAM_HEAP
|
||||
uint32_t jpg_len;
|
||||
jpg_len = get_jpeg_len(get_f);
|
||||
if(jpg_len < 200*1024)
|
||||
{
|
||||
jpeg_in_psram(work,get_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
jpeg_in_sram(work,get_f);
|
||||
}
|
||||
#else
|
||||
jpeg_in_sram(work,get_f);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
free_all_jpg_node(get_f);
|
||||
del_jpeg_frame(get_f);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//创建后,需要使能才能生效(需要手动去绑定一下数据流,然后使能,可以做到动态绑定)
|
||||
stream *new_video_app_stream(const char *name)
|
||||
{
|
||||
stream *src = NULL;
|
||||
src = open_stream_available(name,2,0,opcode_func,NULL);
|
||||
return src;
|
||||
}
|
||||
|
||||
stream *new_video_app_stream_with_mode(const char *name,uint8_t from_vpp,uint16_t w,uint16_t h)
|
||||
{
|
||||
stream *src = NULL;
|
||||
//从vpp那边过来,需要配置一下
|
||||
if(from_vpp == 1)
|
||||
{
|
||||
#if DVP_EN == 1
|
||||
//配置一下数据来源
|
||||
jpg_cfg_vpp(HG_JPG0_DEVID,VPP_DATA0);
|
||||
set_jpg_w_h(0,0,0);
|
||||
src = open_stream_available(name,2,0,opcode_func,NULL);
|
||||
#endif
|
||||
}
|
||||
//从scale过来
|
||||
else if(from_vpp == 2)
|
||||
{
|
||||
set_jpg_w_h(0,w,h);
|
||||
jpg_cfg(HG_JPG0_DEVID,SCALER_DATA);
|
||||
src = open_stream_available(name,2,0,opcode_func,NULL);
|
||||
}
|
||||
else if(from_vpp == 0)
|
||||
{
|
||||
src = open_stream_available(name,2,0,opcode_func,NULL);
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
#else
|
||||
//为了不打开jpg,不会报错
|
||||
stream *new_video_app_stream(const char *name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef __NEW_VIDEO_APP_H
|
||||
#define __NEW_VIDEO_APP_H
|
||||
#include "sys_config.h"
|
||||
#include "tx_platform.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
//自定义内部命令
|
||||
enum
|
||||
{
|
||||
//用于配置图片分辨率
|
||||
NEW_SET_MJPEG_RESOLUTION_PARM_CMD,
|
||||
NEW_RESET_MJPEG_DPI,
|
||||
};
|
||||
|
||||
extern void *get_jpeg_node_buf(void *d);
|
||||
extern int get_node_count(volatile struct list_head *head);
|
||||
extern void del_jpeg_node(void *d,uint32_t jpg_num);
|
||||
extern int get_jpg_node_len();
|
||||
extern uint32 get_jpg_node_len_new(void *get_f);
|
||||
extern void jpg_recfg();
|
||||
extern void jpg_start(uint8 jpgid);
|
||||
extern void jpg_stop(uint32_t jpg_num);
|
||||
extern bool csi_recfg();
|
||||
extern bool csi_open();
|
||||
extern bool csi_close();
|
||||
stream *new_video_app_stream(const char *name);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,928 @@
|
||||
/*
|
||||
在硬件初始化后,这里就是相关video的接口
|
||||
*/
|
||||
#include "video_app.h"
|
||||
|
||||
//临时利用,V200接口需要用到
|
||||
#include "devid.h"
|
||||
|
||||
#if JPG_EN == 1
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "hal/jpeg.h"
|
||||
#include "hal/vpp.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "lib/lcd/gui.h"
|
||||
#include "lib/video/dvp/jpeg/jpg.h"
|
||||
#include "osal/irq.h"
|
||||
|
||||
extern uint32_t get_jpg_default_dpi(uint8_t id);
|
||||
//data申请空间函数
|
||||
#define STREAM_MALLOC custom_malloc_psram
|
||||
#define STREAM_FREE custom_free_psram
|
||||
#define STREAM_ZALLOC custom_zalloc_psram
|
||||
|
||||
//结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC custom_malloc
|
||||
#define STREAM_LIBC_FREE custom_free
|
||||
#define STREAM_LIBC_ZALLOC custom_zalloc
|
||||
|
||||
struct video_app_s
|
||||
{
|
||||
struct os_work work;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
};
|
||||
|
||||
|
||||
static uint8_t video_app_running = 0;
|
||||
static stream *g_jpeg_s = NULL;
|
||||
|
||||
|
||||
//txw81x重写一下,因为有些模块可能被其他模块用
|
||||
#if TXW80X
|
||||
static void start_jpeg_stream()
|
||||
{
|
||||
jpg_recfg();
|
||||
jpg_start(0);
|
||||
|
||||
csi_recfg();
|
||||
csi_open();
|
||||
}
|
||||
|
||||
void stop_jpeg_stream()
|
||||
{
|
||||
csi_close();
|
||||
jpg_stop(0);
|
||||
}
|
||||
#else
|
||||
|
||||
extern volatile uint32 prc_new_frame;
|
||||
uint8 spi_sensor_to_mjpeg_is_run();
|
||||
extern void jpg_start_dpi(uint8 jpg_num,uint16_t w,uint16_t h);
|
||||
static void start_jpeg_stream(struct video_app_s *msg)
|
||||
{
|
||||
//jpg_recfg();
|
||||
//为了尽量保留旧逻辑,这里用宏去隔离,新框架要使用msg参数
|
||||
#if LVGL_STREAM_ENABLE == 1
|
||||
jpg_recfg(0);
|
||||
jpg_start_dpi(0,msg->w,msg->h);
|
||||
#else
|
||||
#if PRC_EN
|
||||
if(spi_sensor_to_mjpeg_is_run()){
|
||||
while(prc_new_frame == 0){
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
jpg_recfg(0);
|
||||
jpg_start(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void stop_jpeg_stream()
|
||||
{
|
||||
//csi_close();
|
||||
jpg_stop(0);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//注意,如果调用这里,new_video_app.c的接口就不能随便调用了
|
||||
//这个文件是旧逻辑,保留是为了旧版本代码可以运行,新代码最好参考new_video_app.c去作改动
|
||||
//实际两个文件是高度相似的
|
||||
void stop_jpeg()
|
||||
{
|
||||
jpeg_stream_deinit();
|
||||
}
|
||||
|
||||
void start_jpeg()
|
||||
{
|
||||
jpeg_stream_init();
|
||||
}
|
||||
|
||||
stream *start_jpeg_return_stream()
|
||||
{
|
||||
return jpeg_stream_init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct jpg_frame_msg
|
||||
{
|
||||
uint32_t len;
|
||||
void *malloc_mem;
|
||||
};
|
||||
|
||||
static uint32_t get_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
uint32_t len = 0;
|
||||
if(j)
|
||||
{
|
||||
len = j->len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint32_t jpg_custom_func(void *data,int opcode,void *priv);
|
||||
static int32 stream_get_jpg_work(struct os_work *work);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const stream_ops_func stream_jpg_ops =
|
||||
{
|
||||
.get_data_len = get_data_len,
|
||||
.custom_func = jpg_custom_func,
|
||||
};
|
||||
|
||||
static uint32_t jpg_custom_func(void *data,int opcode,void *priv)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
uint32_t flags;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
switch(opcode)
|
||||
{
|
||||
case CUSTOM_GET_NODE_LEN:
|
||||
{
|
||||
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
res = get_jpg_node_len(0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
res = j->len;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case CUSTOM_GET_NODE_BUF:
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
res = (uint32_t)get_jpeg_node_buf(priv);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
res = (uint32_t)priv;
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case CUSTOM_GET_FIRST_BUF:
|
||||
{
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(data);
|
||||
//头是固定用,next才是真正的数据
|
||||
if(dest_list->next)
|
||||
{
|
||||
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
res =(uint32) get_jpeg_node_buf(dest_list->next->data);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
res =(uint32) dest_list->next->data;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_FREE_NODE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(el->data)
|
||||
{
|
||||
|
||||
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_DEL_NODE:
|
||||
{
|
||||
uint32_t ref;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *el = (struct stream_jpeg_data_s *)priv;
|
||||
flags = disable_irq();
|
||||
ref = --el->ref;
|
||||
enable_irq(flags);
|
||||
if(!ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(GET_DATA_TYPE2(d->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(d->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_GET_NODE_COUNT:
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
//struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
LL_COUNT(dest_list,el,res);
|
||||
res -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint32_t stream_cmd_func(stream *s,int cmd,uint32_t arg)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case SET_MJPEG_RESOLUTION_PARM_CMD:
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
resolution_parm *gui_cfg = (resolution_parm*)arg;
|
||||
os_printf("dvp_h:%d dvp_w:%d rec_h:%d rec_w:%d\n",gui_cfg->dvp_h,gui_cfg->dvp_w,gui_cfg->rec_h,gui_cfg->rec_w);
|
||||
|
||||
extern uint8 *yuvbuf;
|
||||
#if LCD_EN
|
||||
struct scale_device *scale_dev;
|
||||
struct vpp_device *vpp_dev;
|
||||
scale_dev = (struct scale_device *)dev_get(HG_SCALE1_DEVID);
|
||||
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
|
||||
if(gui_cfg->dvp_h != gui_cfg->rec_h || gui_cfg->dvp_w != gui_cfg->rec_w)
|
||||
{
|
||||
os_work_cancle2(&msg->work,1);
|
||||
stop_jpeg_stream();
|
||||
os_printf("---------SCALE TO MJPEG---------\n");
|
||||
scale_from_vpp_to_jpg(scale_dev,(uint32)yuvbuf,gui_cfg->dvp_w,gui_cfg->dvp_h,gui_cfg->rec_w,gui_cfg->rec_h);
|
||||
jpg_cfg(HG_JPG0_DEVID,SCALER_DATA);
|
||||
vpp_open(vpp_dev);
|
||||
start_jpeg_stream((struct video_app_s*)s->priv);
|
||||
OS_WORK_REINIT(&msg->work);
|
||||
os_run_work_delay(&msg->work, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_work_cancle2(&msg->work,1);
|
||||
stop_jpeg_stream();
|
||||
vpp_close(vpp_dev);
|
||||
os_printf("---------VPP TO MJPEG---------\n");
|
||||
os_sleep_ms(50);
|
||||
jpg_cfg(HG_JPG0_DEVID,VPP_DATA0);
|
||||
vpp_open(vpp_dev);
|
||||
start_jpeg_stream((struct video_app_s*)s->priv);
|
||||
OS_WORK_REINIT(&msg->work);
|
||||
os_run_work_delay(&msg->work, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case RESET_MJPEG_DPI:
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
os_work_cancle2(&msg->work,1);
|
||||
stop_jpeg_stream();
|
||||
uint32_t w_h = (uint32_t)arg;
|
||||
os_printf("w_h:%X\n",w_h);
|
||||
msg->w = w_h>>16;
|
||||
msg->h = w_h&0xffff;
|
||||
start_jpeg_stream(msg);
|
||||
OS_WORK_REINIT(&msg->work);
|
||||
os_run_work_delay(&msg->work, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
s->priv = (struct video_app_s*) STREAM_LIBC_ZALLOC(sizeof(struct video_app_s));
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
stream_data_dis_mem_custom(s);
|
||||
#if 0
|
||||
streamSrc_bind_streamDest(s,R_PSRAM_JPEG);
|
||||
|
||||
#else
|
||||
//注意这里,使用psram的时候不要直接到图传,先到psram变成一帧图,然后psram再发送到图传和录卡流
|
||||
streamSrc_bind_streamDest(s,R_RTP_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_RECORD_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_ALK_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_PHOTO_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_AT_SAVE_PHOTO);
|
||||
streamSrc_bind_streamDest(s,R_AT_AVI_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_LOWPOERRESUME_EVENT);
|
||||
// streamSrc_bind_streamDest(s,SR_OTHER_JPG);
|
||||
#endif
|
||||
register_stream_self_cmd_func(s,stream_cmd_func);
|
||||
//启动jpeg流
|
||||
|
||||
|
||||
//这里实际是为了兼容旧逻辑产生的
|
||||
//设置mjpeg的默认值
|
||||
uint32_t w_h = get_jpg_default_dpi(0);
|
||||
msg->w = w_h>>16;
|
||||
msg->h = w_h&0xffff;
|
||||
start_jpeg_stream(msg);
|
||||
//启动workqueue
|
||||
OS_WORK_INIT(&msg->work, stream_get_jpg_work, 0);
|
||||
os_run_work_delay(&msg->work, 1);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//注册对应函数
|
||||
data->ops = (stream_ops_func*)&stream_jpg_ops;
|
||||
data->data = NULL;
|
||||
data->priv = (struct jpg_frame_msg*)os_malloc(sizeof(struct jpg_frame_msg));
|
||||
if(data->priv)
|
||||
{
|
||||
memset(data->priv,0,sizeof(struct jpg_frame_msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("malloc mem fail,%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->priv)
|
||||
{
|
||||
os_free(data->priv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//如果释放空间,则删除所有的节点
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(dest_list_tmp == el)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(el->data)
|
||||
{
|
||||
//这里只要判断type2,因为默认type1一定是JPEG
|
||||
if(GET_DATA_TYPE2(data->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(data->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data->priv;
|
||||
if(j)
|
||||
{
|
||||
os_free(j->malloc_mem);
|
||||
j->malloc_mem = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
//每次即将发送到一个流,就调用一次
|
||||
case STREAM_SEND_TO_DEST:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref++;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
//这里只要判断type2,因为默认type1一定是JPEG
|
||||
if(GET_DATA_TYPE2(data->type) == JPEG_DVP_NODE)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
else if(GET_DATA_TYPE2(data->type) == JPEG_DVP_FULL)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//退出,则关闭对应得流
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
struct video_app_s *msg = (struct video_app_s*)s->priv;
|
||||
os_work_cancle2(&msg->work,1);
|
||||
stop_jpeg_stream();
|
||||
if(msg)
|
||||
{
|
||||
STREAM_LIBC_FREE(msg);
|
||||
s->priv = NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_MARK_GC_END:
|
||||
//这里代表流已经完毕,也代表整个数据流已经被关闭了
|
||||
video_app_running = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void jpeg_in_sram(struct list_head *get_f)
|
||||
{
|
||||
stream *s = g_jpeg_s;
|
||||
struct list_head *data;
|
||||
int err = 1;
|
||||
if(get_f)
|
||||
{
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
int get_f_count = get_node_count(get_f);
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)os_malloc((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
|
||||
//节点进行提取到stream里面,如果节点不够,也要删除已经提取的节点(理论节点与jpeg节点一致,不应该不一样)
|
||||
//先判断get_f的节点数量是多少
|
||||
while(m && get_f_count--)
|
||||
{
|
||||
//图片节点提取
|
||||
if(list_empty(get_f))
|
||||
{
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
el = m++;
|
||||
//保存next
|
||||
data = get_f->next;
|
||||
//将next断开
|
||||
list_del(get_f->next);
|
||||
el->data = (void*)data;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
err = 0;
|
||||
//添加到另一个链表
|
||||
LL_APPEND(dest_list,el);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct data_structure *data_s = NULL;
|
||||
//没有错误的情况才去申请空间
|
||||
if(!err)
|
||||
{
|
||||
data_s = get_src_data_f(s);
|
||||
if(data_s)
|
||||
{
|
||||
//设置这个为正常图片的的形式
|
||||
data_s->type = SET_DATA_TYPE(JPEG,JPEG_DVP_NODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(err || !data_s || !data_s->priv)
|
||||
{
|
||||
del_jpeg_frame(get_f);
|
||||
//清除已经提取的图片节点
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref = 0;
|
||||
el->next = NULL;
|
||||
if(el->data)
|
||||
{
|
||||
del_jpeg_node(el->data,0);
|
||||
}
|
||||
el->data = NULL;
|
||||
}
|
||||
os_free(dest_list);
|
||||
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//数据绑定
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
//设置这个为图片节点形式,接收端需要根据这个去实现读取图片方式
|
||||
data_s->type = SET_DATA_TYPE(JPEG,JPEG_DVP_NODE);
|
||||
set_stream_data_time(data_s,os_jiffies());
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = get_jpeg_len(get_f);
|
||||
j->malloc_mem = dest_list;
|
||||
del_jpeg_frame(get_f);
|
||||
//统一发送数据,这个时候,其他流才有可能获取到数据
|
||||
_os_printf("$");
|
||||
send_data_to_stream(data_s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
void jpeg_in_psram(struct list_head *get_f)
|
||||
{
|
||||
|
||||
uint8_t *tmp_buf;
|
||||
stream *s = g_jpeg_s;
|
||||
int err = 1;
|
||||
uint32_t jpg_len,jpg_len_tmp,cp_offset,cp_len;
|
||||
uint8_t *jpg_psram_space = NULL;
|
||||
uint32_t node_len;
|
||||
|
||||
if(get_f)
|
||||
{
|
||||
node_len = get_jpg_node_len_new((void*)get_f);
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
jpg_len = get_jpeg_len(get_f);
|
||||
//os_printf("get_f:%X\tjpg_len:%d\n",get_f,jpg_len);
|
||||
//带psram的情况下,这里总是等于1,因为psram空间大,一张图片约30KB的情况,可以尽量保证图片在内存是连续的
|
||||
int get_f_count = 1;
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
|
||||
//与无psram的结构同步,用于兼容
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)os_malloc((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
jpg_psram_space = (uint8_t*)custom_malloc_psram(jpg_len);
|
||||
jpg_len_tmp = jpg_len;
|
||||
cp_offset = 0;
|
||||
|
||||
if(m)
|
||||
{
|
||||
el = m;
|
||||
//节点先添加
|
||||
el->data = (void*)jpg_psram_space;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
LL_APPEND(dest_list,el);
|
||||
}
|
||||
//节点进行提取到stream里面,如果节点不够,也要删除已经提取的节点(理论节点与jpeg节点一致,不应该不一样)
|
||||
//先判断get_f的节点数量是多少
|
||||
while(jpg_psram_space && m)
|
||||
{
|
||||
|
||||
//图片节点提取
|
||||
if(list_empty(get_f) || jpg_len_tmp == 0)
|
||||
{
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(jpg_len_tmp > node_len)
|
||||
{
|
||||
cp_len = node_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
cp_len = jpg_len_tmp;
|
||||
}
|
||||
jpg_len_tmp -= cp_len;
|
||||
tmp_buf = get_jpeg_first_buf(get_f);
|
||||
|
||||
|
||||
hw_memcpy0(jpg_psram_space+cp_offset,get_jpeg_first_buf(get_f),cp_len);
|
||||
del_jpeg_first_node(get_f);
|
||||
cp_offset += cp_len;
|
||||
}
|
||||
|
||||
struct data_structure *data_s = NULL;
|
||||
//没有错误的情况才去申请空间
|
||||
if(!err)
|
||||
{
|
||||
data_s = get_src_data_f(s);
|
||||
if(data_s)
|
||||
{
|
||||
//设置这个为正常图片的的形式
|
||||
data_s->type = SET_DATA_TYPE(JPEG,JPEG_DVP_FULL);
|
||||
}
|
||||
|
||||
}
|
||||
if(err || !data_s || !data_s->priv || !jpg_psram_space)
|
||||
{
|
||||
del_jpeg_frame(get_f);
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//清除已经提取的图片节点
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref = 0;
|
||||
el->next = NULL;
|
||||
//理论psram的空间在这里释放
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
}
|
||||
el->data = NULL;
|
||||
}
|
||||
os_free(dest_list);
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//数据绑定
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
|
||||
set_stream_data_time(data_s,os_jiffies());
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = jpg_len;
|
||||
j->malloc_mem = dest_list;
|
||||
del_jpeg_frame(get_f);
|
||||
//统一发送数据,这个时候,其他流才有可能获取到数据
|
||||
_os_printf("V");
|
||||
send_data_to_stream(data_s);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32 stream_get_jpg_work(struct os_work *work)
|
||||
{
|
||||
//首先获取节点先
|
||||
uint32_t flags;
|
||||
|
||||
flags = disable_irq();
|
||||
struct list_head *get_f = (void*)get_frame(HG_JPG0_DEVID);
|
||||
enable_irq(flags);
|
||||
|
||||
uint32_t jpg_len;
|
||||
|
||||
if(get_f)
|
||||
{
|
||||
#ifdef PSRAM_HEAP
|
||||
jpg_len = get_jpeg_len(get_f);
|
||||
if(jpg_len < 200*1024)
|
||||
{
|
||||
jpeg_in_psram(get_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
jpeg_in_sram(get_f);
|
||||
}
|
||||
#else
|
||||
jpeg_in_sram(get_f);
|
||||
#endif
|
||||
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
stream *jpeg_stream_init()
|
||||
{
|
||||
stream *src = NULL;
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
src = open_stream_available(S_JPEG,2,0,opcode_func,NULL);
|
||||
g_jpeg_s = src;
|
||||
os_printf("src:%X\n",src);
|
||||
if(src)
|
||||
{
|
||||
os_printf("src open_ref:%d\n",src->open_ref);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
void jpeg_stream_deinit(stream *s)
|
||||
{
|
||||
int res;
|
||||
if(g_jpeg_s)
|
||||
{
|
||||
res = close_stream(g_jpeg_s);
|
||||
if(!res)
|
||||
{
|
||||
g_jpeg_s = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jpeg_stream_sync()
|
||||
{
|
||||
while(video_app_running)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
//同步关闭,就是会等到整个流时间被关闭为止,这个用的时候一定要注意,否则会阻塞整个线程
|
||||
//并且不能在中断使用
|
||||
void jpeg_stream_deinit_sync(stream *s)
|
||||
{
|
||||
int res;
|
||||
if(g_jpeg_s)
|
||||
{
|
||||
res = close_stream(g_jpeg_s);
|
||||
if(!res)
|
||||
{
|
||||
g_jpeg_s = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
jpeg_stream_sync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
stream *jpeg_stream_init()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void jpeg_stream_deinit(stream *s)
|
||||
{
|
||||
|
||||
}
|
||||
void stop_jpeg()
|
||||
{
|
||||
}
|
||||
|
||||
void start_jpeg()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef __VIDEO_APP_H
|
||||
#define __VIDEO_APP_H
|
||||
#include "sys_config.h"
|
||||
#include "tx_platform.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
//分辨率配置传参结构体
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dvp_w;
|
||||
uint32_t dvp_h;
|
||||
uint32_t rec_w;
|
||||
uint32_t rec_h;
|
||||
}resolution_parm;
|
||||
|
||||
|
||||
extern void *get_jpeg_node_buf(void *d);
|
||||
extern int get_node_count(volatile struct list_head *head);
|
||||
extern void del_jpeg_node(void *d,uint32_t jpg_num);
|
||||
extern int get_jpg_node_len();
|
||||
extern uint32 get_jpg_node_len_new(void *get_f);
|
||||
extern void jpg_recfg();
|
||||
extern void jpg_start(uint8 jpgid);
|
||||
extern void jpg_stop(uint32_t jpg_num);
|
||||
extern bool csi_recfg();
|
||||
extern bool csi_open();
|
||||
extern bool csi_close();
|
||||
void jpeg_stream_deinit();
|
||||
stream* jpeg_stream_init();
|
||||
void stop_jpeg();
|
||||
void start_jpeg();
|
||||
stream *start_jpeg_return_stream();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
在硬件初始化后,这里就是相关video的接口
|
||||
*/
|
||||
#include "video_app_bbm.h"
|
||||
|
||||
//临时利用,V200接口需要用到
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
|
||||
#include "osal/irq.h"
|
||||
#ifdef PSRAM_HEAP
|
||||
|
||||
|
||||
static stream *g_bbm_net_jpeg_s = NULL;
|
||||
|
||||
struct jpg_frame_msg
|
||||
{
|
||||
uint32_t len;
|
||||
void *malloc_mem;
|
||||
};
|
||||
|
||||
|
||||
static void stram_get_wifi_psram_thread(void *d)
|
||||
{
|
||||
|
||||
uint32_t jpg_len;
|
||||
stream *s = g_bbm_net_jpeg_s;
|
||||
uint32_t delete_frame_num = 4;
|
||||
uint8_t *malloc_buf = NULL;
|
||||
struct data_structure *data_s = NULL;
|
||||
static uint32_t last_timestemp = 0;
|
||||
static uint32_t cur_timestemp = 0;
|
||||
static uint32_t temp = 0;
|
||||
int send_ret = 0;
|
||||
|
||||
|
||||
bbm_net_jpeg_frame* get_f = NULL;
|
||||
|
||||
uint32_t count = 0;
|
||||
|
||||
while(delete_frame_num)
|
||||
{
|
||||
get_f = bbm_get_frame();
|
||||
if(get_f)
|
||||
{
|
||||
os_printf("delete frame:%d\n",get_f->timeinfo);
|
||||
os_sleep_ms(900);
|
||||
bbm_del_frame(get_f);
|
||||
break;
|
||||
}else{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while(1)
|
||||
{
|
||||
get_f = bbm_get_frame();
|
||||
if(get_f)
|
||||
{
|
||||
count++;
|
||||
jpg_len = get_f->frame_len;
|
||||
data_s = get_src_data_f(s);
|
||||
|
||||
if(data_s)
|
||||
{
|
||||
if(!malloc_buf)
|
||||
{
|
||||
malloc_buf = (uint8_t*)custom_malloc_psram(jpg_len);
|
||||
}
|
||||
|
||||
if(malloc_buf)
|
||||
{
|
||||
hw_memcpy(malloc_buf,get_f->data,jpg_len);
|
||||
//这里代表图片收集完成,申请对应链表空间
|
||||
int get_f_count = 1;
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
struct stream_jpeg_data_s *el;//,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)os_malloc((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
|
||||
if(m)
|
||||
{
|
||||
el = m;
|
||||
//节点先添加
|
||||
el->data = (void*)malloc_buf;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
LL_APPEND(dest_list,el);
|
||||
malloc_buf = NULL;
|
||||
}
|
||||
//申请失败,那么去处理掉异常吧
|
||||
else
|
||||
{
|
||||
goto bbm_get_frame_err_deal;
|
||||
}
|
||||
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
data_s->type = 1;
|
||||
set_stream_data_time(data_s,get_f->timeinfo);
|
||||
cur_timestemp = get_f->timeinfo;
|
||||
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = get_f->frame_len;
|
||||
j->malloc_mem = dest_list;
|
||||
|
||||
// _os_printf("W");
|
||||
temp = cur_timestemp - last_timestemp;
|
||||
|
||||
|
||||
// os_printf("video: sleep:%dms cur_timestemp:%d last_timestemp:%d\n",cur_timestemp-last_timestemp,
|
||||
// cur_timestemp,
|
||||
// last_timestemp);
|
||||
|
||||
data_s->type = SET_DATA_TYPE(JPEG,0);
|
||||
send_ret = send_data_to_stream(data_s);
|
||||
last_timestemp = cur_timestemp;
|
||||
data_s = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//申请空间失败,强制删除data_s节点
|
||||
os_printf("malloc buf failed\n");
|
||||
force_del_data(data_s);
|
||||
data_s = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("=");
|
||||
}
|
||||
bbm_del_frame(get_f);
|
||||
get_f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("N");
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bbm_get_frame_err_deal:
|
||||
_os_printf("!");
|
||||
if(get_f)
|
||||
{
|
||||
bbm_del_frame(get_f);
|
||||
get_f = NULL;
|
||||
}
|
||||
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
data_s = NULL;
|
||||
}
|
||||
|
||||
if(malloc_buf)
|
||||
{
|
||||
custom_free_psram(malloc_buf);
|
||||
malloc_buf = NULL;
|
||||
}
|
||||
|
||||
bbm_net_jpeg_psram_stream_deinit(s);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static uint32_t bbm_net_jpg_custom_func_psram(void *data,int opcode,void *priv)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
uint32_t flags;
|
||||
switch(opcode)
|
||||
{
|
||||
case CUSTOM_GET_NODE_LEN:
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
res = j->len;
|
||||
}
|
||||
break;
|
||||
case CUSTOM_GET_NODE_BUF:
|
||||
res = (uint32_t)priv;
|
||||
break;
|
||||
case CUSTOM_GET_FIRST_BUF:
|
||||
{
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(data);
|
||||
//头是固定用,next才是真正的数据
|
||||
if(dest_list->next)
|
||||
{
|
||||
res =(uint32) dest_list->next->data;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_FREE_NODE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_DEL_NODE:
|
||||
{
|
||||
uint32_t ref;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *el = (struct stream_jpeg_data_s *)priv;
|
||||
flags = disable_irq();
|
||||
ref = --el->ref;
|
||||
enable_irq(flags);
|
||||
if(!ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint32_t get_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
uint32_t len = 0;
|
||||
if(j)
|
||||
{
|
||||
len = j->len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static stream_ops_func stream_usb_jpg_ops =
|
||||
{
|
||||
.get_data_len = get_data_len,
|
||||
.custom_func = bbm_net_jpg_custom_func_psram,
|
||||
};
|
||||
|
||||
extern volatile uint8_t uvc_format;
|
||||
#define BBM_PSRAM_MALLOC_SIZE_INIT (30*1024)
|
||||
static int opcode_func_psram(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
|
||||
stream_data_dis_mem(s,3);
|
||||
|
||||
streamSrc_bind_streamDest(s,R_AT_AVI_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_AT_SAVE_PHOTO);
|
||||
#if LVGL_STREAM_ENABLE
|
||||
streamSrc_bind_streamDest(s,SR_OTHER_JPG);
|
||||
#endif
|
||||
os_task_create("bbm_wifi_stream", stram_get_wifi_psram_thread, (void *)s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
data->type = 0x10;//设置声音的类型,后续用宏代替
|
||||
//注册对应函数
|
||||
data->ops = &stream_usb_jpg_ops;
|
||||
data->data = NULL;
|
||||
data->priv = (struct jpg_frame_msg*)os_malloc(sizeof(struct jpg_frame_msg));
|
||||
if(data->priv)
|
||||
{
|
||||
memset(data->priv,0,sizeof(struct jpg_frame_msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("malloc mem fail,%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->priv)
|
||||
{
|
||||
os_free(data->priv);
|
||||
data->priv = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//如果释放空间,则删除所有的节点
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(dest_list_tmp == el)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data->priv;
|
||||
if(j)
|
||||
{
|
||||
os_free(j->malloc_mem);
|
||||
j->malloc_mem = NULL;
|
||||
}
|
||||
data->data = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
//每次即将发送到一个流,就调用一次
|
||||
case STREAM_SEND_TO_DEST:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref++;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//退出,则关闭对应得流
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DEL:
|
||||
{
|
||||
//struct bbm_net_jpeg_frame *userdata = (struct bbm_net_jpeg_frame*)s->priv;
|
||||
}
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
stream *bbm_net_jpeg_psram_stream_init()
|
||||
{
|
||||
stream *src = NULL;
|
||||
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
if(g_bbm_net_jpeg_s)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src = open_stream_available(S_NET_JPEG,3,0,opcode_func_psram,NULL);
|
||||
|
||||
g_bbm_net_jpeg_s = src;
|
||||
os_printf("src:%X\n",src);
|
||||
if(src)
|
||||
{
|
||||
os_printf("src open_ref:%d\n",src->open_ref);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
void bbm_net_jpeg_psram_stream_deinit(stream *s)
|
||||
{
|
||||
int res;
|
||||
os_printf("%s g_bbm_net_jpeg_s:%X\n",__FUNCTION__,g_bbm_net_jpeg_s);
|
||||
if(g_bbm_net_jpeg_s)
|
||||
{
|
||||
res = close_stream(g_bbm_net_jpeg_s);
|
||||
os_printf("%s res:%d\n",__FUNCTION__,res);
|
||||
if(!res)
|
||||
{
|
||||
g_bbm_net_jpeg_s = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bbm_net_jpeg_init()
|
||||
{
|
||||
bbm_net_jpeg_psram_stream_init();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef __VIDEO_APP_BBM_H__
|
||||
#define __VIDEO_APP_BBM_H__
|
||||
|
||||
#include "sys_config.h"
|
||||
#include "tx_platform.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t timeinfo;
|
||||
uint32_t frame_len;
|
||||
uint8_t state; //0:未使用 1:填充完成,待使用 2:使用完成 3:正在使用
|
||||
uint8_t *data;
|
||||
}bbm_net_jpeg_frame;
|
||||
|
||||
extern bbm_net_jpeg_frame* bbm_get_frame();
|
||||
extern void bbm_del_frame(bbm_net_jpeg_frame* get_f);
|
||||
|
||||
stream *bbm_net_jpeg_psram_stream_init();
|
||||
void bbm_net_jpeg_psram_stream_deinit(stream *s);
|
||||
void bbm_net_jpeg_init();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
在硬件初始化后,这里就是相关video的接口
|
||||
*/
|
||||
#include "video_app_usb.h"
|
||||
|
||||
//临时利用,V200接口需要用到
|
||||
#include "devid.h"
|
||||
|
||||
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
#include "osal/irq.h"
|
||||
static stream *g_usb_jpeg_s = NULL;
|
||||
static struct os_work usb_jpeg_stream_work;
|
||||
|
||||
struct jpg_frame_msg
|
||||
{
|
||||
uint32_t len;
|
||||
void *malloc_mem;
|
||||
};
|
||||
|
||||
|
||||
//usb的情况下,如果是在sram,则获取的get_uvc_frame一定是独占,只有等自己释放
|
||||
static int32 stream_get_usb_jpg_work_sram(struct os_work *work)
|
||||
{
|
||||
|
||||
struct list_head* get_f;
|
||||
UVC_MANAGE* uvc_message;
|
||||
UVC_BLANK* data;
|
||||
stream *s = g_usb_jpeg_s;
|
||||
int err = 1;
|
||||
uint32_t flags;
|
||||
|
||||
flags = disable_irq();
|
||||
get_f = get_uvc_frame();
|
||||
enable_irq(flags);
|
||||
|
||||
if(get_f)
|
||||
{
|
||||
|
||||
uvc_message = list_entry(get_f,UVC_MANAGE,list);
|
||||
set_uvc_frame_using(uvc_message);
|
||||
//os_printf("usb jpeg len:%d\n",uvc_message->frame_len);
|
||||
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
int get_f_count = get_usb_node_count(get_f);
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)os_malloc((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
|
||||
//os_printf("get_f_count:%d\n",get_f_count);
|
||||
|
||||
while(m && get_f_count--)
|
||||
{
|
||||
//图片节点提取
|
||||
if(list_empty(&uvc_message->list))
|
||||
{
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
el = m++;
|
||||
//保存next
|
||||
data = list_entry(uvc_message->list.prev,UVC_BLANK,list);
|
||||
list_del((struct list_head *)data);
|
||||
data->list.next = NULL;
|
||||
data->list.prev = NULL;
|
||||
|
||||
el->data = (void*)data;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
err = 0;
|
||||
//添加到另一个链表
|
||||
LL_APPEND(dest_list,el);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
|
||||
|
||||
struct data_structure *data_s = NULL;
|
||||
//没有错误的情况才去申请空间
|
||||
if(!err)
|
||||
{
|
||||
data_s = get_src_data_f(s);
|
||||
}
|
||||
|
||||
|
||||
if(err || !data_s || !data_s->priv)
|
||||
{
|
||||
//清除已经提取的图片节点
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref = 0;
|
||||
el->next = NULL;
|
||||
if(el->data)
|
||||
{
|
||||
free_usb_node(el->data);
|
||||
}
|
||||
el->data = NULL;
|
||||
}
|
||||
os_free(dest_list);
|
||||
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//数据绑定
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
data_s->type = SET_DATA_TYPE(JPEG,JPEG_DVP_NODE);
|
||||
set_stream_data_time(data_s,os_jiffies());
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = uvc_message->frame_len;
|
||||
j->malloc_mem = dest_list;
|
||||
//统一发送数据,这个时候,其他流才有可能获取到数据
|
||||
_os_printf("S");
|
||||
send_data_to_stream(data_s);
|
||||
}
|
||||
|
||||
|
||||
del_usb_frame(get_f);
|
||||
del_uvc_frame(uvc_message);
|
||||
get_f = NULL;
|
||||
|
||||
}
|
||||
os_run_work_delay(&usb_jpeg_stream_work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint32_t usb_jpg_custom_func_sram(void *data,int opcode,void *priv)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
uint32_t flags;
|
||||
switch(opcode)
|
||||
{
|
||||
case CUSTOM_GET_NODE_LEN:
|
||||
res = get_node_uvc_len();
|
||||
break;
|
||||
case CUSTOM_GET_NODE_BUF:
|
||||
res = (uint32_t)get_usb_jpeg_node_buf(priv);
|
||||
break;
|
||||
case CUSTOM_GET_FIRST_BUF:
|
||||
{
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(data);
|
||||
//头是固定用,next才是真正的数据
|
||||
if(dest_list->next)
|
||||
{
|
||||
res =(uint32) get_usb_jpeg_node_buf(dest_list->next->data);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_FREE_NODE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(el->data)
|
||||
{
|
||||
free_usb_node(el->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_DEL_NODE:
|
||||
{
|
||||
uint32_t ref;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *el = (struct stream_jpeg_data_s *)priv;
|
||||
flags = disable_irq();
|
||||
ref = --el->ref;
|
||||
enable_irq(flags);
|
||||
if(!ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
free_usb_node(el->data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint32_t get_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
uint32_t len = 0;
|
||||
if(j)
|
||||
{
|
||||
len = j->len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static stream_ops_func stream_usb_jpg_ops =
|
||||
{
|
||||
.get_data_len = get_data_len,
|
||||
.custom_func = usb_jpg_custom_func_sram,
|
||||
};
|
||||
|
||||
static int opcode_func_sram(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
stream_data_dis_mem_custom(s);
|
||||
|
||||
streamSrc_bind_streamDest(s,R_RTP_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_RECORD_JPEG);
|
||||
|
||||
//启动jpeg流
|
||||
//extern void start_jpeg_stream();
|
||||
//start_jpeg_stream();
|
||||
//启动workqueue
|
||||
OS_WORK_INIT(&usb_jpeg_stream_work, stream_get_usb_jpg_work_sram, 0);
|
||||
os_run_work_delay(&usb_jpeg_stream_work, 1);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//注册对应函数
|
||||
data->ops = &stream_usb_jpg_ops;
|
||||
data->data = NULL;
|
||||
data->priv = (struct jpg_frame_msg*)os_malloc(sizeof(struct jpg_frame_msg));
|
||||
if(data->priv)
|
||||
{
|
||||
memset(data->priv,0,sizeof(struct jpg_frame_msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("malloc mem fail,%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->priv)
|
||||
{
|
||||
os_free(data->priv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//如果释放空间,则删除所有的节点
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(dest_list_tmp == el)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(el->data)
|
||||
{
|
||||
free_usb_node(el->data);
|
||||
}
|
||||
}
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data->priv;
|
||||
if(j)
|
||||
{
|
||||
os_free(j->malloc_mem);
|
||||
j->malloc_mem = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
//每次即将发送到一个流,就调用一次
|
||||
case STREAM_SEND_TO_DEST:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref++;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(el->data)
|
||||
{
|
||||
free_usb_node(el->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//退出,则关闭对应得流
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
extern void stop_jpeg_stream();
|
||||
os_work_cancle2(&usb_jpeg_stream_work,1);
|
||||
//stop_jpeg_stream();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
stream *usb_jpeg_stream_init()
|
||||
{
|
||||
stream *src = NULL;
|
||||
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
src = open_stream_available(S_USB_JPEG,2,0,opcode_func_sram,NULL);
|
||||
|
||||
g_usb_jpeg_s = src;
|
||||
os_printf("src:%X\n",src);
|
||||
if(src)
|
||||
{
|
||||
os_printf("src open_ref:%d\n",src->open_ref);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
void usb_jpeg_stream_deinit()
|
||||
{
|
||||
int res;
|
||||
if(g_usb_jpeg_s)
|
||||
{
|
||||
res = close_stream(g_usb_jpeg_s);
|
||||
if(!res)
|
||||
{
|
||||
g_usb_jpeg_s = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef __VIDEO_APP_USB_H
|
||||
#define __VIDEO_APP_USB_H
|
||||
#include "sys_config.h"
|
||||
#include "tx_platform.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
void set_uvc_frame_using(UVC_MANAGE* uvc);
|
||||
struct list_head* get_uvc_frame();
|
||||
int get_usb_node_count(struct list_head *head);
|
||||
bool free_usb_node(struct list_head *del);
|
||||
void del_usb_frame(void *get_f);
|
||||
void *get_usb_jpeg_node_buf(void *d);
|
||||
void del_uvc_frame(UVC_MANAGE* uvc);
|
||||
int get_node_uvc_len();
|
||||
stream *usb_jpeg_stream_init();
|
||||
void usb_jpeg_stream_deinit();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,921 @@
|
||||
/*
|
||||
在硬件初始化后,这里就是相关video的接口
|
||||
*/
|
||||
#include "video_app_usb_psram.h"
|
||||
|
||||
//临时利用,V200接口需要用到
|
||||
#include "devid.h"
|
||||
|
||||
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "lib/video/uvc/hg_usb_device.h"
|
||||
|
||||
#include "osal/irq.h"
|
||||
#include <csi_kernel.h>
|
||||
void usb_jpeg_psram_stream_close(stream *s);
|
||||
#ifdef PSRAM_HEAP
|
||||
|
||||
#include "usbh_video.h"
|
||||
extern int usb_dma_mjpeg_irq_times;
|
||||
|
||||
static stream *g_usb_jpeg_s = NULL;
|
||||
static struct data_structure *g_usbjpeg_stream_current_data = NULL;
|
||||
static uint8_t *g_usb_current_malloc_buf[2];
|
||||
static struct stream_jpeg_data_s *g_m = NULL;
|
||||
static struct list_head *g_get_frame = NULL;
|
||||
|
||||
|
||||
|
||||
struct jpg_frame_msg
|
||||
{
|
||||
uint32_t len;
|
||||
void *malloc_mem;
|
||||
};
|
||||
|
||||
|
||||
//私有结构体
|
||||
struct usb_jpg_userdata
|
||||
{
|
||||
uint32_t malloc_max_size; //记录当前应该申请的最大size
|
||||
uint32_t current_photo_max_size;
|
||||
//记录的时间与次数主要为了动态修改malloc_max_size,尽可能节约空间
|
||||
uint32_t malloc_time; //记录malloc_max_size修改的size
|
||||
uint32_t malloc_count_near; //记录从记录malloc_max_size开始计算,申请的次数
|
||||
|
||||
uint32_t *task_status;
|
||||
struct uvc_user_arg *uvc_arg;
|
||||
uint32_t uvc_format;
|
||||
};
|
||||
|
||||
|
||||
//usb的情况下,如果是在sram,则获取的get_uvc_frame一定是独占,只有等自己释放
|
||||
static void stream_get_usb_psram_thread(void *d)
|
||||
{
|
||||
//这里为了让usb那边初始化好对应的空间
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
os_sleep_ms(5);
|
||||
stream *s = (stream *)d;
|
||||
struct list_head* get_f;
|
||||
UVC_MANAGE* uvc_message = NULL;
|
||||
UVC_BLANK* uvc_b;
|
||||
int err = 1;
|
||||
uint32_t flags;
|
||||
uint32_t offset = 0;
|
||||
struct data_structure *data_s = NULL;
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata*)s->priv;
|
||||
//uint8_t *buf;
|
||||
uint32_t irq_time = 0;
|
||||
uint8_t *malloc_buf = NULL;
|
||||
uint32_t current_photo_size = 0;
|
||||
uint32_t current_photo_max_size;
|
||||
uint8_t exit_err = 0;
|
||||
struct uvc_user_arg *uvc_arg = userdata->uvc_arg;
|
||||
uint32_t usb_time_out = 0;
|
||||
uint32_t usb_dma_irq_count = 0;
|
||||
uint32_t count_time = 0;
|
||||
uint32_t ctlnum = 0;
|
||||
|
||||
switch (userdata->uvc_format)
|
||||
{
|
||||
case USBH_VIDEO_FORMAT_MJPEG:
|
||||
current_photo_max_size = 80*1024;
|
||||
ctlnum = 30;
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_BASED:
|
||||
current_photo_max_size = 180*1024;
|
||||
ctlnum = 200;
|
||||
break;
|
||||
|
||||
default:
|
||||
current_photo_max_size = 80*1024;
|
||||
ctlnum = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
uvc_get_psram_again:
|
||||
flags = disable_irq();
|
||||
get_f = get_uvc_frame();
|
||||
g_get_frame = get_f;
|
||||
enable_irq(flags);
|
||||
|
||||
//如果其他任务通知,可以在这里判断,然后退出
|
||||
if(uvc_arg->state == 2)
|
||||
{
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
|
||||
if(usb_time_out > 500)
|
||||
{
|
||||
#if RTT_USB_EN
|
||||
if(usb_dma_irq_count == usb_dma_mjpeg_irq_times)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
exit_err = 1;
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
usb_dma_irq_count = usb_dma_mjpeg_irq_times;
|
||||
usb_time_out = 0;
|
||||
#else
|
||||
if(usb_dma_irq_count == usb_dma_irq_times)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
exit_err = 1;
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
usb_dma_irq_count = usb_dma_irq_times;
|
||||
usb_time_out = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!get_f)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
usb_time_out++;
|
||||
goto uvc_get_psram_again;
|
||||
}
|
||||
usb_time_out = 0;
|
||||
err = 0;
|
||||
offset = 0;
|
||||
malloc_buf = NULL;
|
||||
current_photo_size = 0;
|
||||
flags = disable_irq();
|
||||
uvc_message = list_entry(get_f,UVC_MANAGE,list);
|
||||
set_uvc_frame_using(uvc_message);
|
||||
enable_irq(flags);
|
||||
|
||||
|
||||
|
||||
|
||||
extern uint8_t uvc_open;
|
||||
while((uvc_message->frame_end != 2) && ((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)))
|
||||
{
|
||||
if(uvc_open == 0)
|
||||
{
|
||||
count_time++;
|
||||
if(count_time > 1000)
|
||||
{
|
||||
count_time = 0;
|
||||
os_printf("uvc:%X\tend:%d\n",uvc_message,uvc_message->frame_end);
|
||||
}
|
||||
}
|
||||
if(uvc_arg->state == 2)
|
||||
{
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
flags = disable_irq();
|
||||
uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list);
|
||||
enable_irq(flags);
|
||||
if(uvc_b && uvc_b->busy == 2)
|
||||
{
|
||||
//数据头,所以要申请一帧数据
|
||||
if(uvc_b->blank_loop == 0)
|
||||
{
|
||||
//获取是否有节点,有节点的话,才可以填充数据
|
||||
data_s = get_src_data_f(s);
|
||||
g_usbjpeg_stream_current_data = data_s;
|
||||
}
|
||||
//没有帧,那么只能将bank删除,应该是rtsp处理速度不够
|
||||
if(data_s)
|
||||
{
|
||||
//会申请一个连续的空间有可能空间不够,后续会重新申请,如果不够,则丢帧
|
||||
if(!malloc_buf)
|
||||
{
|
||||
_os_printf("#");
|
||||
malloc_buf = (uint8_t*)custom_malloc_psram(userdata->malloc_max_size);
|
||||
g_usb_current_malloc_buf[0] = malloc_buf;
|
||||
userdata->malloc_count_near++;
|
||||
}
|
||||
if(malloc_buf)
|
||||
{
|
||||
//判断一下偏移后是否大于当前最大的size,如果是,则需要重新去申请空间了,这种情况申请大于20%,自动调整,则增加10%
|
||||
if(offset+uvc_b->blank_len > userdata->malloc_max_size)
|
||||
{
|
||||
_os_printf("{}\n");
|
||||
uint32_t last_malloc_size = userdata->malloc_max_size;
|
||||
userdata->malloc_max_size = (uint32_t)((offset+uvc_b->blank_len)<<1);
|
||||
|
||||
userdata->malloc_time = os_jiffies();
|
||||
userdata->malloc_count_near = 0;
|
||||
uint8_t *m_buf = (void*)custom_malloc_psram(userdata->malloc_max_size);
|
||||
g_usb_current_malloc_buf[1] = m_buf;
|
||||
os_printf("userdata->malloc_max_size:%d\t%X\n",userdata->malloc_max_size,m_buf);
|
||||
if(m_buf)
|
||||
{
|
||||
hw_memcpy0(m_buf,malloc_buf,offset);
|
||||
custom_free_psram(malloc_buf );
|
||||
malloc_buf = m_buf;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
userdata->malloc_max_size = last_malloc_size;
|
||||
if(malloc_buf)
|
||||
{
|
||||
custom_free_psram(malloc_buf );
|
||||
malloc_buf = NULL;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//申请不到空间,则要去移除这张图片,并且释放data_s,但是要这张图片接收完成才能进行操作
|
||||
if(!malloc_buf)
|
||||
{
|
||||
err = 1;
|
||||
_os_printf("[");
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
g_usbjpeg_stream_current_data = NULL;
|
||||
data_s = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//申请空间
|
||||
hw_memcpy0(malloc_buf+offset,uvc_b->buf_ptr,uvc_b->blank_len);
|
||||
offset += uvc_b->blank_len;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("=");
|
||||
}
|
||||
free_usb_node((struct list_head *)uvc_b);
|
||||
uvc_b = NULL;
|
||||
irq_time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//释放cpu
|
||||
os_sleep_ms(1);
|
||||
irq_time++;
|
||||
if(irq_time>500)
|
||||
{
|
||||
_os_printf("&");
|
||||
os_printf("uvc_b:%X\n",uvc_b);
|
||||
if(uvc_b)
|
||||
{
|
||||
os_printf("busy:%d\n",uvc_b->busy);
|
||||
}
|
||||
|
||||
os_printf("uvc_message:%X\t%d\n",uvc_message,uvc_message->frame_end);
|
||||
#if RTT_USB_EN
|
||||
#if 1
|
||||
if(usb_dma_irq_count == usb_dma_mjpeg_irq_times)
|
||||
{
|
||||
exit_err = 1;
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
os_printf("usb_dev:%X\n",uvc_arg->usb_dev);
|
||||
//int32 usb_host_uvc_ioctl(struct usb_device *p_usb_d, uint32 cmd, uint32 param1, uint32 param2);
|
||||
//usb_host_uvc_ioctl((struct usb_device *)uvc_arg->usb_dev, USB_HOST_IO_CMD_RESET,0,0);
|
||||
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
#else
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
#endif
|
||||
|
||||
usb_dma_irq_count = usb_dma_mjpeg_irq_times;
|
||||
irq_time = 0;
|
||||
#else
|
||||
#if 1
|
||||
if(usb_dma_irq_count == usb_dma_irq_times)
|
||||
{
|
||||
exit_err = 1;
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
os_printf("usb_dev:%X\n",uvc_arg->usb_dev);
|
||||
//int32 usb_host_uvc_ioctl(struct usb_device *p_usb_d, uint32 cmd, uint32 param1, uint32 param2);
|
||||
//usb_host_uvc_ioctl((struct usb_device *)uvc_arg->usb_dev, USB_HOST_IO_CMD_RESET,0,0);
|
||||
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
#else
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
#endif
|
||||
|
||||
usb_dma_irq_count = usb_dma_irq_times;
|
||||
irq_time = 0;
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(err || !malloc_buf)
|
||||
{
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
|
||||
if(uvc_message->frame_end == 2)
|
||||
{
|
||||
goto uvc_get_psram_err_deal;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//设置状态,等于发送frame
|
||||
if(data_s)
|
||||
{
|
||||
|
||||
//这里代表图片收集完成,申请对应链表空间
|
||||
int get_f_count = 1;
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
struct stream_jpeg_data_s *el;//,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)os_malloc((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
g_m = m;
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
|
||||
if(m)
|
||||
{
|
||||
el = m;
|
||||
//节点先添加
|
||||
el->data = (void*)malloc_buf;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
LL_APPEND(dest_list,el);
|
||||
malloc_buf = NULL;
|
||||
}
|
||||
//申请失败,那么去处理掉异常吧
|
||||
else
|
||||
{
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
|
||||
set_stream_data_time(data_s,os_jiffies());
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = uvc_message->frame_len;
|
||||
j->malloc_mem = dest_list;
|
||||
current_photo_size = uvc_message->frame_len;
|
||||
|
||||
if(current_photo_max_size < current_photo_size)
|
||||
{
|
||||
current_photo_max_size = current_photo_size;
|
||||
}
|
||||
sys_dcache_clean_range((uint32_t*)((uint32_t)(el->data) & CACHE_CIR_INV_ADDR_Msk), j->len + ((uint32_t)(el->data)-((uint32_t)(el->data) & CACHE_CIR_INV_ADDR_Msk)));
|
||||
//os_printf("current_photo_size:%d\tcurrent_photo_max_size:%d\n",current_photo_size,current_photo_max_size);
|
||||
send_data_to_stream(data_s);
|
||||
data_s = NULL;
|
||||
g_usbjpeg_stream_current_data = NULL;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
g_usb_current_malloc_buf[1] = NULL;
|
||||
g_m = NULL;
|
||||
}
|
||||
del_uvc_frame(uvc_message);
|
||||
g_get_frame = NULL;
|
||||
}
|
||||
|
||||
|
||||
if(userdata->malloc_count_near < 2)
|
||||
{
|
||||
os_printf("malloc_max_size:%d\tcurrent_photo_max_size:%d\n",userdata->malloc_max_size,current_photo_max_size);
|
||||
}
|
||||
|
||||
//这里用算法开始对malloc_max_size进行计算,尽量贴近申请的空间大小,在申请超过30次,并且没有调整过后,才考虑将
|
||||
//申请最大内存减少到合适位置,然后重新统计
|
||||
if(userdata->malloc_count_near > ctlnum && current_photo_max_size*1.1 < userdata->malloc_max_size)
|
||||
{
|
||||
//重新调整一下
|
||||
userdata->malloc_max_size = current_photo_max_size*1.1;
|
||||
current_photo_max_size = 0;
|
||||
userdata->malloc_count_near = 0;
|
||||
}
|
||||
//重新统计一下
|
||||
else if(userdata->malloc_count_near > ctlnum)
|
||||
{
|
||||
userdata->malloc_count_near = 0;
|
||||
current_photo_max_size = 0;
|
||||
}
|
||||
//一直要保证图片有10%的冗余度来容纳下一帧可能变化太大的情况,如果这一次调整了,则malloc_count_near清0
|
||||
else if(current_photo_max_size*1.1 > userdata->malloc_max_size)
|
||||
{
|
||||
userdata->malloc_max_size = current_photo_max_size*1.15;
|
||||
userdata->malloc_count_near = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//重新获取图片
|
||||
goto uvc_get_psram_again;
|
||||
|
||||
|
||||
//异常处理,可能是空间不够之类
|
||||
uvc_get_psram_err_deal:
|
||||
_os_printf("!");
|
||||
del_usb_frame(get_f);
|
||||
del_uvc_frame(uvc_message);
|
||||
g_get_frame = NULL;
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
g_usbjpeg_stream_current_data = NULL;
|
||||
data_s = NULL;
|
||||
}
|
||||
if(malloc_buf)
|
||||
{
|
||||
custom_free_psram(malloc_buf );
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
g_usb_current_malloc_buf[1] = NULL;
|
||||
malloc_buf = NULL;
|
||||
}
|
||||
//如果有必要,还要看看是不是usb断开,是不是应该退出线程
|
||||
|
||||
|
||||
//如果其他任务通知,可以在这里判断,然后退出
|
||||
if(uvc_arg->state == 2 || exit_err)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
//代表任务退出,并且将流也退出
|
||||
usb_jpeg_psram_stream_close(s);
|
||||
//标志一下退出标志
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint32_t usb_jpg_custom_func_psram(void *data,int opcode,void *priv)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
uint32_t flags;
|
||||
switch(opcode)
|
||||
{
|
||||
case CUSTOM_GET_NODE_LEN:
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
res = j->len;
|
||||
}
|
||||
break;
|
||||
case CUSTOM_GET_NODE_BUF:
|
||||
res = (uint32_t)priv;
|
||||
break;
|
||||
case CUSTOM_GET_FIRST_BUF:
|
||||
{
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(data);
|
||||
//头是固定用,next才是真正的数据
|
||||
if(dest_list->next)
|
||||
{
|
||||
res =(uint32) dest_list->next->data;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_FREE_NODE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_DEL_NODE:
|
||||
{
|
||||
uint32_t ref;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *el = (struct stream_jpeg_data_s *)priv;
|
||||
flags = disable_irq();
|
||||
ref = --el->ref;
|
||||
enable_irq(flags);
|
||||
if(!ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint32_t get_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
uint32_t len = 0;
|
||||
if(j)
|
||||
{
|
||||
len = j->len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static stream_ops_func stream_usb_jpg_ops =
|
||||
{
|
||||
.get_data_len = get_data_len,
|
||||
.custom_func = usb_jpg_custom_func_psram,
|
||||
};
|
||||
|
||||
k_task_handle_t stream_get_usb_psram_handle;
|
||||
k_task_handle_t *stream_get_usb_psram_hd = NULL;
|
||||
#define UVC_PSRAM_MALLOC_SIZE_INIT (100*1024)
|
||||
static int opcode_func_psram(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
|
||||
//创建流成功,为流创建一个私有结构体,记录信息
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata*)custom_malloc(sizeof(struct usb_jpg_userdata));
|
||||
memset(userdata,0,sizeof(struct usb_jpg_userdata));
|
||||
//设置初始默认申请的最大空间
|
||||
userdata->malloc_max_size = UVC_PSRAM_MALLOC_SIZE_INIT;
|
||||
//记录申请时间以及
|
||||
userdata->malloc_time = os_jiffies();
|
||||
userdata->malloc_count_near = 0;
|
||||
userdata->uvc_arg = (struct uvc_user_arg *)priv;
|
||||
struct uvc_user_arg *uvc_arg = userdata->uvc_arg;
|
||||
userdata->uvc_format = uvc_arg->uvc_format;
|
||||
|
||||
s->priv = (void*)userdata;
|
||||
stream_data_dis_mem_custom(s);
|
||||
|
||||
switch(userdata->uvc_format)
|
||||
{
|
||||
case USBH_VIDEO_FORMAT_UNCOMPRESSED:
|
||||
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_MJPEG:
|
||||
streamSrc_bind_streamDest(s,R_RTP_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_RECORD_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_JPEG_TO_LCD);
|
||||
streamSrc_bind_streamDest(s,SR_OTHER_JPG_USB1);
|
||||
streamSrc_bind_streamDest(s,SR_OTHER_JPG_USB2);
|
||||
streamSrc_bind_streamDest(s,SR_VIDEO_USB);
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_BASED:
|
||||
streamSrc_bind_streamDest(s,R_RECORD_H264);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//要判断一下,如果说任务创建失败,需要将流关闭一下,这里就默认任务创建成功
|
||||
uvc_arg->state = 1;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
g_usb_current_malloc_buf[1] = NULL;
|
||||
if(csi_kernel_task_new((k_task_entry_t)stream_get_usb_psram_thread, "uvc_stream", (void *)s, 25, 0, NULL, 1024, &stream_get_usb_psram_handle)==0)
|
||||
stream_get_usb_psram_hd = &stream_get_usb_psram_handle;
|
||||
// os_task_create("uvc_stream", stream_get_usb_psram_thread, (uint32_t)s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata *)s->priv;
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//设置类型
|
||||
switch(userdata->uvc_format)
|
||||
{
|
||||
case USBH_VIDEO_FORMAT_UNCOMPRESSED:
|
||||
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_MJPEG:
|
||||
data->type = SET_DATA_TYPE(JPEG,JPEG_DVP_NODE);
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_BASED:
|
||||
data->type = SET_DATA_TYPE(H264,0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//注册对应函数
|
||||
data->ops = &stream_usb_jpg_ops;
|
||||
data->data = NULL;
|
||||
data->priv = (struct jpg_frame_msg*)os_malloc(sizeof(struct jpg_frame_msg));
|
||||
if(data->priv)
|
||||
{
|
||||
memset(data->priv,0,sizeof(struct jpg_frame_msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("malloc mem fail,%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->priv)
|
||||
{
|
||||
os_free(data->priv);
|
||||
data->priv = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//如果释放空间,则删除所有的节点
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(dest_list_tmp == el)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data->priv;
|
||||
if(j)
|
||||
{
|
||||
os_free(j->malloc_mem);
|
||||
j->malloc_mem = NULL;
|
||||
}
|
||||
data->data = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
//每次即将发送到一个流,就调用一次
|
||||
case STREAM_SEND_TO_DEST:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref++;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//退出,则关闭对应得流
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DEL:
|
||||
{
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata*)s->priv;
|
||||
if(userdata)
|
||||
{
|
||||
struct uvc_user_arg *uvc_arg = userdata->uvc_arg;
|
||||
uvc_arg->state = 0;
|
||||
custom_free(userdata);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
stream *usb_jpeg_psram_stream_init(struct uvc_user_arg *uvc_arg)
|
||||
{
|
||||
stream *src = NULL;
|
||||
|
||||
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
if(g_usb_jpeg_s)
|
||||
{
|
||||
if(!stream_get_usb_psram_hd) {
|
||||
if(csi_kernel_task_new((k_task_entry_t)stream_get_usb_psram_thread, "uvc_stream", (void *)g_usb_jpeg_s, 25, 0, NULL, 1024, &stream_get_usb_psram_handle)==0)
|
||||
stream_get_usb_psram_hd = &stream_get_usb_psram_handle;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src = open_stream_available(S_USB_JPEG_PSRAM,5,0,opcode_func_psram,uvc_arg);
|
||||
|
||||
g_usb_jpeg_s = src;
|
||||
os_printf("src:%X\n",src);
|
||||
if(src)
|
||||
{
|
||||
os_printf("src open_ref:%d\n",src->open_ref);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
void usb_jpeg_psram_stream_close(stream *s)
|
||||
{
|
||||
int res;
|
||||
os_printf("%s g_usb_jpeg_s:%X\n",__FUNCTION__,g_usb_jpeg_s);
|
||||
if(g_usb_jpeg_s)
|
||||
{
|
||||
res = close_stream(g_usb_jpeg_s);
|
||||
os_printf("%s res:%d\n",__FUNCTION__,res);
|
||||
if(!res)
|
||||
{
|
||||
g_usb_jpeg_s = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
void usb_jpeg_psram_stream_deinit()
|
||||
{
|
||||
extern struct uvc_user_arg uvc_arg;
|
||||
uvc_arg.state = 0;
|
||||
if(stream_get_usb_psram_hd) {
|
||||
csi_kernel_task_del(stream_get_usb_psram_handle);
|
||||
stream_get_usb_psram_hd = NULL;
|
||||
}
|
||||
if(g_get_frame) {
|
||||
UVC_MANAGE* uvc_message = list_entry(g_get_frame,UVC_MANAGE,list);
|
||||
del_usb_frame(g_get_frame);
|
||||
del_uvc_frame(uvc_message);
|
||||
g_get_frame = NULL;
|
||||
}
|
||||
if(g_usbjpeg_stream_current_data) {
|
||||
force_del_data(g_usbjpeg_stream_current_data);
|
||||
printf("force_del_data(g_usbjpeg_stream_current_data)\n");
|
||||
}
|
||||
if(g_usb_current_malloc_buf[0]) {
|
||||
custom_free_psram(g_usb_current_malloc_buf[0]);
|
||||
printf("custom_free_psram(g_usb_current_malloc_buf[0])\n");
|
||||
}
|
||||
if(g_usb_current_malloc_buf[1]) {
|
||||
custom_free_psram(g_usb_current_malloc_buf[1]);
|
||||
printf("custom_free_psram(g_usb_current_malloc_buf[1])\n");
|
||||
}
|
||||
if(g_m) {
|
||||
os_free(g_m);
|
||||
printf("os_free(g_m)\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void usb_host_enum_finish_init_mjpeg(uint32_t uvc_format)
|
||||
{
|
||||
extern struct uvc_user_arg uvc_arg;
|
||||
uint32_t timeout = 0;
|
||||
if(uvc_arg.state == 1)
|
||||
{
|
||||
uvc_arg.state = 2;
|
||||
}
|
||||
while(uvc_arg.state != 0 || timeout > 3000)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
uvc_arg.state = 1;
|
||||
uvc_arg.uvc_format = uvc_format;
|
||||
|
||||
usb_jpeg_psram_stream_init(&uvc_arg);
|
||||
}
|
||||
|
||||
|
||||
//usb host枚举成功后会执行的这个函数
|
||||
void usb_host_enum_finish_init(uint32_t uvc_format)
|
||||
{
|
||||
extern struct uvc_user_arg uvc_arg;
|
||||
uint32_t timeout = 0;
|
||||
if(uvc_arg.state == 1)
|
||||
{
|
||||
uvc_arg.state = 2;
|
||||
}
|
||||
while(uvc_arg.state != 0 || timeout > 3000)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
uvc_arg.state = 1;
|
||||
uvc_arg.uvc_format = uvc_format;
|
||||
|
||||
usb_jpeg_psram_stream_init(&uvc_arg);
|
||||
}
|
||||
|
||||
int uvc_default_dpi()
|
||||
{
|
||||
return UVC_720P;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef __VIDEO_APP_USB_PSRAM_H
|
||||
#define __VIDEO_APP_USB_PSRAM_H
|
||||
#include "sys_config.h"
|
||||
#include "tx_platform.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
|
||||
stream *usb_jpeg_stream_init();
|
||||
struct list_head* get_uvc_frame();
|
||||
void set_uvc_frame_using(UVC_MANAGE* uvc);
|
||||
int get_usb_node_count(struct list_head *head);
|
||||
bool free_usb_node(struct list_head *del);
|
||||
void del_usb_frame(void *get_f);
|
||||
void *get_usb_jpeg_node_buf(void *d);
|
||||
void del_uvc_frame(UVC_MANAGE* uvc);
|
||||
int get_node_uvc_len();
|
||||
extern int usb_dma_irq_times;
|
||||
|
||||
void usb_jpeg_psram_stream_deinit();
|
||||
#endif
|
||||
@@ -0,0 +1,895 @@
|
||||
/*
|
||||
在硬件初始化后,这里就是相关video的接口
|
||||
*/
|
||||
#include "video_app_usb_psram_dual.h"
|
||||
|
||||
//临时利用,V200接口需要用到
|
||||
#include "devid.h"
|
||||
|
||||
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "lib/video/uvc/hg_usb_device.h"
|
||||
|
||||
#include "osal/irq.h"
|
||||
#include <csi_kernel.h>
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#include "usbh_video.h"
|
||||
extern int usb_dma_h264_irq_times;
|
||||
|
||||
static stream *g_usb_dual_s = NULL;
|
||||
static struct data_structure *g_usbjpeg_stream_current_data = NULL;
|
||||
static uint8_t *g_usb_current_malloc_buf[2];
|
||||
static struct stream_jpeg_data_s *g_m = NULL;
|
||||
static struct list_head *g_get_frame = NULL;
|
||||
|
||||
struct jpg_frame_msg
|
||||
{
|
||||
uint32_t len;
|
||||
void *malloc_mem;
|
||||
};
|
||||
|
||||
|
||||
//私有结构体
|
||||
struct usb_jpg_userdata
|
||||
{
|
||||
uint32_t malloc_max_size; //记录当前应该申请的最大size
|
||||
uint32_t current_photo_max_size;
|
||||
//记录的时间与次数主要为了动态修改malloc_max_size,尽可能节约空间
|
||||
uint32_t malloc_time; //记录malloc_max_size修改的size
|
||||
uint32_t malloc_count_near; //记录从记录malloc_max_size开始计算,申请的次数
|
||||
|
||||
uint32_t *task_status;
|
||||
struct uvc_user_arg *uvc_arg_dual;
|
||||
uint32_t uvc_format;
|
||||
};
|
||||
|
||||
|
||||
//usb的情况下,如果是在sram,则获取的get_uvc_frame一定是独占,只有等自己释放
|
||||
static void stream_get_usb_psram_thread2(void *d)
|
||||
{
|
||||
//这里为了让usb那边初始化好对应的空间
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
os_sleep_ms(5);
|
||||
stream *s = (stream *)d;
|
||||
struct list_head* get_f;
|
||||
UVC_MANAGE* uvc_message = NULL;
|
||||
UVC_BLANK* uvc_b;
|
||||
int err = 1;
|
||||
uint32_t flags;
|
||||
uint32_t offset = 0;
|
||||
struct data_structure *data_s = NULL;
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata*)s->priv;
|
||||
//uint8_t *buf;
|
||||
uint32_t irq_time = 0;
|
||||
uint8_t *malloc_buf = NULL;
|
||||
uint32_t current_photo_size = 0;
|
||||
uint32_t current_photo_max_size;
|
||||
uint8_t exit_err = 0;
|
||||
struct uvc_user_arg *uvc_arg_dual = userdata->uvc_arg_dual;
|
||||
uint32_t usb_time_out = 0;
|
||||
uint32_t usb_dma_irq_count = 0;
|
||||
uint32_t count_time = 0;
|
||||
uint32_t ctlnum = 0;
|
||||
|
||||
switch (userdata->uvc_format)
|
||||
{
|
||||
case USBH_VIDEO_FORMAT_MJPEG:
|
||||
current_photo_max_size = 80*1024;
|
||||
ctlnum = 30;
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_BASED:
|
||||
current_photo_max_size = 180*1024;
|
||||
ctlnum = 200;
|
||||
break;
|
||||
|
||||
default:
|
||||
current_photo_max_size = 80*1024;
|
||||
ctlnum = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
uvc_get_psram_again:
|
||||
flags = disable_irq();
|
||||
get_f = get_uvc_frame2();
|
||||
g_get_frame = get_f;
|
||||
enable_irq(flags);
|
||||
|
||||
//如果其他任务通知,可以在这里判断,然后退出
|
||||
if(uvc_arg_dual->state == 2)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
|
||||
if(usb_time_out > 500)
|
||||
{
|
||||
#if RTT_USB_EN
|
||||
if(usb_dma_irq_count == usb_dma_h264_irq_times)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
exit_err = 1;
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
usb_dma_irq_count = usb_dma_h264_irq_times;
|
||||
usb_time_out = 0;
|
||||
#else
|
||||
if(usb_dma_irq_count == usb_dma_irq_times)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
exit_err = 1;
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
usb_dma_irq_count = usb_dma_irq_times;
|
||||
usb_time_out = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!get_f)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
usb_time_out++;
|
||||
goto uvc_get_psram_again;
|
||||
}
|
||||
usb_time_out = 0;
|
||||
err = 0;
|
||||
offset = 0;
|
||||
malloc_buf = NULL;
|
||||
current_photo_size = 0;
|
||||
flags = disable_irq();
|
||||
uvc_message = list_entry(get_f,UVC_MANAGE,list);
|
||||
// os_printf("2 uvc_message:%x\n",uvc_message);
|
||||
set_uvc_frame_using(uvc_message);
|
||||
enable_irq(flags);
|
||||
|
||||
|
||||
|
||||
|
||||
extern uint8_t uvc_open;
|
||||
while((uvc_message->frame_end != 2) && ((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)))
|
||||
{
|
||||
if(uvc_open == 0)
|
||||
{
|
||||
count_time++;
|
||||
if(count_time > 1000)
|
||||
{
|
||||
count_time = 0;
|
||||
os_printf("uvc:%X\tend:%d\n",uvc_message,uvc_message->frame_end);
|
||||
}
|
||||
}
|
||||
if(uvc_arg_dual->state == 2)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
flags = disable_irq();
|
||||
uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list);
|
||||
enable_irq(flags);
|
||||
if(uvc_b && uvc_b->busy == 2)
|
||||
{
|
||||
//数据头,所以要申请一帧数据
|
||||
if(uvc_b->blank_loop == 0)
|
||||
{
|
||||
//获取是否有节点,有节点的话,才可以填充数据
|
||||
data_s = get_src_data_f(s);
|
||||
g_usbjpeg_stream_current_data = data_s;
|
||||
}
|
||||
//没有帧,那么只能将bank删除,应该是rtsp处理速度不够
|
||||
if(data_s)
|
||||
{
|
||||
//会申请一个连续的空间有可能空间不够,后续会重新申请,如果不够,则丢帧
|
||||
if(!malloc_buf)
|
||||
{
|
||||
_os_printf("J");
|
||||
malloc_buf = (uint8_t*)custom_malloc_psram(userdata->malloc_max_size);
|
||||
g_usb_current_malloc_buf[0] = malloc_buf;
|
||||
userdata->malloc_count_near++;
|
||||
}
|
||||
if(malloc_buf)
|
||||
{
|
||||
//判断一下偏移后是否大于当前最大的size,如果是,则需要重新去申请空间了,这种情况申请大于20%,自动调整,则增加10%
|
||||
if(offset+uvc_b->blank_len > userdata->malloc_max_size)
|
||||
{
|
||||
_os_printf("{:}\n");
|
||||
uint32_t last_malloc_size = userdata->malloc_max_size;
|
||||
userdata->malloc_max_size = (uint32_t)((offset+uvc_b->blank_len)<<1);
|
||||
|
||||
userdata->malloc_time = os_jiffies();
|
||||
userdata->malloc_count_near = 0;
|
||||
uint8_t *m_buf = (void*)custom_malloc_psram(userdata->malloc_max_size);
|
||||
g_usb_current_malloc_buf[1] = m_buf;
|
||||
os_printf("userdata->malloc_max_size:%d\t%X\n",userdata->malloc_max_size,m_buf);
|
||||
if(m_buf)
|
||||
{
|
||||
hw_memcpy0(m_buf,malloc_buf,offset);
|
||||
custom_free_psram(malloc_buf );
|
||||
malloc_buf = m_buf;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
userdata->malloc_max_size = last_malloc_size;
|
||||
if(malloc_buf)
|
||||
{
|
||||
custom_free_psram(malloc_buf );
|
||||
malloc_buf = NULL;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//申请不到空间,则要去移除这张图片,并且释放data_s,但是要这张图片接收完成才能进行操作
|
||||
if(!malloc_buf)
|
||||
{
|
||||
err = 1;
|
||||
_os_printf("[:");
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
g_usbjpeg_stream_current_data = NULL;
|
||||
data_s = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//申请空间
|
||||
hw_memcpy0(malloc_buf+offset,uvc_b->buf_ptr,uvc_b->blank_len);
|
||||
offset += uvc_b->blank_len;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("=:");
|
||||
}
|
||||
free_usb_node2((struct list_head *)uvc_b);
|
||||
uvc_b = NULL;
|
||||
irq_time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//释放cpu
|
||||
os_sleep_ms(1);
|
||||
irq_time++;
|
||||
if(irq_time>500)
|
||||
{
|
||||
_os_printf("&");
|
||||
os_printf("uvc_b:%X\n",uvc_b);
|
||||
if(uvc_b)
|
||||
{
|
||||
os_printf("busy:%d\n",uvc_b->busy);
|
||||
}
|
||||
|
||||
os_printf("2 uvc_message:%X\t%d\n",uvc_message,uvc_message->frame_end);
|
||||
#if RTT_USB_EN
|
||||
#if 1
|
||||
if(usb_dma_irq_count == usb_dma_h264_irq_times)
|
||||
{
|
||||
exit_err = 1;
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
os_printf("usb_dev:%X\n",uvc_arg_dual->usb_dev);
|
||||
//int32 usb_host_uvc_ioctl(struct usb_device *p_usb_d, uint32 cmd, uint32 param1, uint32 param2);
|
||||
//usb_host_uvc_ioctl((struct usb_device *)uvc_arg_dual->usb_dev, USB_HOST_IO_CMD_RESET,0,0);
|
||||
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
#else
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
#endif
|
||||
|
||||
usb_dma_irq_count = usb_dma_h264_irq_times;
|
||||
irq_time = 0;
|
||||
#else
|
||||
#if 1
|
||||
if(usb_dma_irq_count == usb_dma_irq_times)
|
||||
{
|
||||
exit_err = 1;
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
os_printf("usb_dev:%X\n",uvc_arg_dual->usb_dev);
|
||||
//int32 usb_host_uvc_ioctl(struct usb_device *p_usb_d, uint32 cmd, uint32 param1, uint32 param2);
|
||||
//usb_host_uvc_ioctl((struct usb_device *)uvc_arg_dual->usb_dev, USB_HOST_IO_CMD_RESET,0,0);
|
||||
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
#else
|
||||
os_printf("%s usb maybe disconnect\n",__FUNCTION__);
|
||||
#endif
|
||||
|
||||
usb_dma_irq_count = usb_dma_irq_times;
|
||||
irq_time = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(err || !malloc_buf)
|
||||
{
|
||||
os_printf("%s:%d err:%d\n",__FUNCTION__,__LINE__,err);
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
|
||||
if(uvc_message->frame_end == 2)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
goto uvc_get_psram_err_deal;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//设置状态,等于发送frame
|
||||
if(data_s)
|
||||
{
|
||||
|
||||
//这里代表图片收集完成,申请对应链表空间
|
||||
int get_f_count = 1;
|
||||
struct stream_jpeg_data_s *m = NULL;
|
||||
struct stream_jpeg_data_s *el;//,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = NULL;
|
||||
if(get_f_count)
|
||||
{
|
||||
//多一个,为了固定头指针
|
||||
m = (struct stream_jpeg_data_s *)os_malloc((get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
g_m = m;
|
||||
memset(m,0,(get_f_count+1)*sizeof(struct stream_jpeg_data_s));
|
||||
el = m;
|
||||
el->next = NULL;
|
||||
el->data = NULL;
|
||||
el->ref = 0;
|
||||
LL_APPEND(dest_list,el);
|
||||
m++;
|
||||
}
|
||||
|
||||
if(m)
|
||||
{
|
||||
el = m;
|
||||
//节点先添加
|
||||
el->data = (void*)malloc_buf;
|
||||
el->ref = 1;
|
||||
el->next = NULL;
|
||||
LL_APPEND(dest_list,el);
|
||||
malloc_buf = NULL;
|
||||
}
|
||||
//申请失败,那么去处理掉异常吧
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
goto uvc_get_psram_err_deal;
|
||||
}
|
||||
|
||||
data_s->data = dest_list;
|
||||
data_s->ref = 0;
|
||||
set_stream_data_time(data_s,os_jiffies());
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data_s->priv;
|
||||
j->len = uvc_message->frame_len;
|
||||
j->malloc_mem = dest_list;
|
||||
current_photo_size = uvc_message->frame_len;
|
||||
|
||||
if(current_photo_max_size < current_photo_size)
|
||||
{
|
||||
current_photo_max_size = current_photo_size;
|
||||
}
|
||||
sys_dcache_clean_range((uint32_t*)((uint32_t)(el->data) & CACHE_CIR_INV_ADDR_Msk), j->len + ((uint32_t)(el->data)-((uint32_t)(el->data) & CACHE_CIR_INV_ADDR_Msk)));
|
||||
//os_printf("current_photo_size:%d\tcurrent_photo_max_size:%d\n",current_photo_size,current_photo_max_size);
|
||||
send_data_to_stream(data_s);
|
||||
data_s = NULL;
|
||||
g_usbjpeg_stream_current_data = NULL;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
g_usb_current_malloc_buf[1] = NULL;
|
||||
g_m = NULL;
|
||||
}
|
||||
del_uvc_frame(uvc_message);
|
||||
g_get_frame = NULL;
|
||||
}
|
||||
|
||||
|
||||
if(userdata->malloc_count_near < 2)
|
||||
{
|
||||
//os_printf("malloc_max_size:%d\tcurrent_photo_max_size:%d\n",userdata->malloc_max_size,current_photo_max_size);
|
||||
}
|
||||
|
||||
//这里用算法开始对malloc_max_size进行计算,尽量贴近申请的空间大小,在申请超过30次,并且没有调整过后,才考虑将
|
||||
//申请最大内存减少到合适位置,然后重新统计
|
||||
if(userdata->malloc_count_near > ctlnum && current_photo_max_size*1.1 < userdata->malloc_max_size)
|
||||
{
|
||||
//重新调整一下
|
||||
userdata->malloc_max_size = current_photo_max_size*1.1;
|
||||
current_photo_max_size = 0;
|
||||
userdata->malloc_count_near = 0;
|
||||
}
|
||||
//重新统计一下
|
||||
else if(userdata->malloc_count_near > ctlnum)
|
||||
{
|
||||
userdata->malloc_count_near = 0;
|
||||
current_photo_max_size = 0;
|
||||
}
|
||||
//一直要保证图片有10%的冗余度来容纳下一帧可能变化太大的情况,如果这一次调整了,则malloc_count_near清0
|
||||
else if(current_photo_max_size*1.1 > userdata->malloc_max_size)
|
||||
{
|
||||
userdata->malloc_max_size = current_photo_max_size*1.15;
|
||||
userdata->malloc_count_near = 0;
|
||||
}
|
||||
|
||||
|
||||
//重新获取图片
|
||||
goto uvc_get_psram_again;
|
||||
|
||||
|
||||
//异常处理,可能是空间不够之类
|
||||
uvc_get_psram_err_deal:
|
||||
_os_printf("!");
|
||||
del_usb_frame2(get_f);
|
||||
del_uvc_frame(uvc_message);
|
||||
g_get_frame = NULL;
|
||||
if(data_s)
|
||||
{
|
||||
force_del_data(data_s);
|
||||
g_usbjpeg_stream_current_data = NULL;
|
||||
data_s = NULL;
|
||||
}
|
||||
if(malloc_buf)
|
||||
{
|
||||
custom_free_psram(malloc_buf );
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
g_usb_current_malloc_buf[1] = NULL;
|
||||
malloc_buf = NULL;
|
||||
}
|
||||
//如果有必要,还要看看是不是usb断开,是不是应该退出线程
|
||||
|
||||
|
||||
//如果其他任务通知,可以在这里判断,然后退出
|
||||
if(uvc_arg_dual->state == 2 || exit_err)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
//代表任务退出,并且将流也退出
|
||||
usb_jpeg_psram_dual_stream_close(s);
|
||||
//标志一下退出标志
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t usb_jpg_custom_func_psram_dual(void *data,int opcode,void *priv)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
uint32_t flags;
|
||||
switch(opcode)
|
||||
{
|
||||
case CUSTOM_GET_NODE_LEN:
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
res = j->len;
|
||||
}
|
||||
break;
|
||||
case CUSTOM_GET_NODE_BUF:
|
||||
res = (uint32_t)priv;
|
||||
break;
|
||||
case CUSTOM_GET_FIRST_BUF:
|
||||
{
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(data);
|
||||
//头是固定用,next才是真正的数据
|
||||
if(dest_list->next)
|
||||
{
|
||||
res =(uint32) dest_list->next->data;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_FREE_NODE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case CUSTOM_DEL_NODE:
|
||||
{
|
||||
uint32_t ref;
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)d->data;
|
||||
struct stream_jpeg_data_s *el = (struct stream_jpeg_data_s *)priv;
|
||||
flags = disable_irq();
|
||||
ref = --el->ref;
|
||||
enable_irq(flags);
|
||||
if(!ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint32_t get_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)d->priv;
|
||||
uint32_t len = 0;
|
||||
if(j)
|
||||
{
|
||||
len = j->len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static stream_ops_func stream_usb_jpg_ops =
|
||||
{
|
||||
.get_data_len = get_data_len,
|
||||
.custom_func = usb_jpg_custom_func_psram_dual,
|
||||
};
|
||||
|
||||
k_task_handle_t stream_get_usb_psram_handle2;
|
||||
k_task_handle_t *stream_get_usb_psram_hd2 = NULL;
|
||||
#define UVC_PSRAM_MALLOC_SIZE_INIT (100*1024)
|
||||
static int opcode_func_psram(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
|
||||
//创建流成功,为流创建一个私有结构体,记录信息
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata*)custom_malloc(sizeof(struct usb_jpg_userdata));
|
||||
memset(userdata,0,sizeof(struct usb_jpg_userdata));
|
||||
//设置初始默认申请的最大空间
|
||||
userdata->malloc_max_size = UVC_PSRAM_MALLOC_SIZE_INIT;
|
||||
//记录申请时间以及
|
||||
userdata->malloc_time = os_jiffies();
|
||||
userdata->malloc_count_near = 0;
|
||||
userdata->uvc_arg_dual = (struct uvc_user_arg *)priv;
|
||||
struct uvc_user_arg *uvc_arg_dual = userdata->uvc_arg_dual;
|
||||
userdata->uvc_format = uvc_arg_dual->uvc_format;
|
||||
|
||||
s->priv = (void*)userdata;
|
||||
stream_data_dis_mem_custom(s);
|
||||
|
||||
switch(userdata->uvc_format)
|
||||
{
|
||||
case USBH_VIDEO_FORMAT_UNCOMPRESSED:
|
||||
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_MJPEG:
|
||||
streamSrc_bind_streamDest(s,R_RTP_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_RECORD_JPEG);
|
||||
streamSrc_bind_streamDest(s,R_JPEG_TO_LCD);
|
||||
streamSrc_bind_streamDest(s,SR_OTHER_JPG_USB1);
|
||||
streamSrc_bind_streamDest(s,SR_OTHER_JPG_USB2);
|
||||
streamSrc_bind_streamDest(s,SR_VIDEO_USB);
|
||||
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_BASED:
|
||||
streamSrc_bind_streamDest(s,R_RECORD_H264);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//要判断一下,如果说任务创建失败,需要将流关闭一下,这里就默认任务创建成功
|
||||
uvc_arg_dual->state = 1;
|
||||
g_usb_current_malloc_buf[0] = NULL;
|
||||
g_usb_current_malloc_buf[1] = NULL;
|
||||
if(csi_kernel_task_new((k_task_entry_t)stream_get_usb_psram_thread2, "uvc_stream2", (void *)s, 25, 0, NULL, 1024, &stream_get_usb_psram_handle2)==0)
|
||||
stream_get_usb_psram_hd2 = &stream_get_usb_psram_handle2;
|
||||
// os_task_create("uvc_stream", stream_get_usb_psram_thread, (uint32_t)s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata *)s->priv;
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//设置类型
|
||||
switch(userdata->uvc_format)
|
||||
{
|
||||
case USBH_VIDEO_FORMAT_UNCOMPRESSED:
|
||||
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_MJPEG:
|
||||
data->type = SET_DATA_TYPE(JPEG,JPEG_DVP_NODE);
|
||||
break;
|
||||
|
||||
case USBH_VIDEO_FORMAT_BASED:
|
||||
data->type = SET_DATA_TYPE(H264,0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//注册对应函数
|
||||
data->ops = &stream_usb_jpg_ops;
|
||||
data->data = NULL;
|
||||
data->priv = (struct jpg_frame_msg*)os_malloc(sizeof(struct jpg_frame_msg));
|
||||
if(data->priv)
|
||||
{
|
||||
memset(data->priv,0,sizeof(struct jpg_frame_msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("malloc mem fail,%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->priv)
|
||||
{
|
||||
os_free(data->priv);
|
||||
data->priv = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//如果释放空间,则删除所有的节点
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(dest_list_tmp == el)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(el->data)
|
||||
{
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
struct jpg_frame_msg *j = (struct jpg_frame_msg*)data->priv;
|
||||
if(j)
|
||||
{
|
||||
os_free(j->malloc_mem);
|
||||
j->malloc_mem = NULL;
|
||||
}
|
||||
data->data = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
//每次即将发送到一个流,就调用一次
|
||||
case STREAM_SEND_TO_DEST:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
el->ref++;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
{
|
||||
//释放data->data里面的图片数据
|
||||
//清除已经提取的图片节点
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
struct stream_jpeg_data_s *dest_list = (struct stream_jpeg_data_s *)data->data;
|
||||
struct stream_jpeg_data_s *dest_list_tmp = dest_list;
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
//释放el->data后,最后将链表释放
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(el == dest_list_tmp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
el->ref--;
|
||||
//是否要释放
|
||||
if(!el->ref)
|
||||
{
|
||||
LL_DELETE(dest_list,el);
|
||||
custom_free_psram(el->data);
|
||||
el->data = NULL;
|
||||
}
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//退出,则关闭对应得流
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DEL:
|
||||
{
|
||||
struct usb_jpg_userdata *userdata = (struct usb_jpg_userdata*)s->priv;
|
||||
if(userdata)
|
||||
{
|
||||
struct uvc_user_arg *uvc_arg_dual = userdata->uvc_arg_dual;
|
||||
uvc_arg_dual->state = 0;
|
||||
custom_free(userdata);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
stream *usb_jpeg_psram_dual_stream_init(struct uvc_user_arg *uvc_arg_dual)
|
||||
{
|
||||
stream *src = NULL;
|
||||
|
||||
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
if(g_usb_dual_s)
|
||||
{
|
||||
if(!stream_get_usb_psram_hd2) {
|
||||
if(csi_kernel_task_new((k_task_entry_t)stream_get_usb_psram_thread2, "uvc_stream2", (void *)g_usb_dual_s, 25, 0, NULL, 1024, &stream_get_usb_psram_handle2)==0)
|
||||
stream_get_usb_psram_hd2 = &stream_get_usb_psram_handle2;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src = open_stream_available(S_USB_DUAL,3,0,opcode_func_psram,uvc_arg_dual);
|
||||
|
||||
g_usb_dual_s = src;
|
||||
os_printf("g_usb_dual_s:%X\n",g_usb_dual_s);
|
||||
if(g_usb_dual_s)
|
||||
{
|
||||
os_printf("src open_ref:%d\n",g_usb_dual_s->open_ref);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
void usb_jpeg_psram_dual_stream_close(stream *s)
|
||||
{
|
||||
int res;
|
||||
os_printf("%s g_usb_dual_s:%X\n",__FUNCTION__,g_usb_dual_s);
|
||||
if(g_usb_dual_s)
|
||||
{
|
||||
res = close_stream(g_usb_dual_s);
|
||||
os_printf("%s res:%d\n",__FUNCTION__,res);
|
||||
if(!res)
|
||||
{
|
||||
g_usb_dual_s = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usb_h264_psram_stream_deinit()
|
||||
{
|
||||
extern struct uvc_user_arg uvc_arg;
|
||||
uvc_arg.state = 0;
|
||||
if(stream_get_usb_psram_hd2) {
|
||||
csi_kernel_task_del(stream_get_usb_psram_handle2);
|
||||
stream_get_usb_psram_hd2 = NULL;
|
||||
}
|
||||
if(g_get_frame) {
|
||||
UVC_MANAGE* uvc_message = list_entry(g_get_frame,UVC_MANAGE,list);
|
||||
del_usb_frame(g_get_frame);
|
||||
del_uvc_frame(uvc_message);
|
||||
g_get_frame = NULL;
|
||||
}
|
||||
if(g_usbjpeg_stream_current_data) {
|
||||
force_del_data(g_usbjpeg_stream_current_data);
|
||||
printf("force_del_data(g_usbjpeg_stream_current_data)\n");
|
||||
}
|
||||
if(g_usb_current_malloc_buf[0]) {
|
||||
custom_free_psram(g_usb_current_malloc_buf[0]);
|
||||
printf("custom_free_psram(g_usb_current_malloc_buf[0])\n");
|
||||
}
|
||||
if(g_usb_current_malloc_buf[1]) {
|
||||
custom_free_psram(g_usb_current_malloc_buf[1]);
|
||||
printf("custom_free_psram(g_usb_current_malloc_buf[1])\n");
|
||||
}
|
||||
if(g_m) {
|
||||
os_free(g_m);
|
||||
printf("os_free(g_m)\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//usb host枚举成功后会执行的这个函数
|
||||
void usb_host_enum_finish_init_h264(uint32_t uvc_format)
|
||||
{
|
||||
extern struct uvc_user_arg uvc_arg_dual;
|
||||
uint32_t timeout = 0;
|
||||
if(uvc_arg_dual.state == 1)
|
||||
{
|
||||
uvc_arg_dual.state = 2;
|
||||
}
|
||||
while(uvc_arg_dual.state != 0 || timeout > 3000)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
uvc_arg_dual.state = 1;
|
||||
uvc_arg_dual.uvc_format = uvc_format;
|
||||
|
||||
usb_jpeg_psram_dual_stream_init(&uvc_arg_dual);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef __VIDEO_APP_USB_PSRAM_DUAL_H
|
||||
#define __VIDEO_APP_USB_PSRAM_DUAL_H
|
||||
#include "sys_config.h"
|
||||
#include "tx_platform.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
|
||||
stream *usb_jpeg_stream_init();
|
||||
struct list_head* get_uvc_frame();
|
||||
struct list_head* get_uvc_frame2();
|
||||
void set_uvc_frame_using(UVC_MANAGE* uvc);
|
||||
int get_usb_node_count(struct list_head *head);
|
||||
bool free_usb_node(struct list_head *del);
|
||||
bool free_usb_node2(struct list_head *del);
|
||||
void del_usb_frame(void *get_f);
|
||||
void del_usb_frame2(void *get_f);
|
||||
void *get_usb_jpeg_node_buf(void *d);
|
||||
void del_uvc_frame(UVC_MANAGE* uvc);
|
||||
int get_node_uvc_len();
|
||||
extern int usb_dma_irq_times;
|
||||
|
||||
void usb_jpeg_psram_dual_stream_close(stream *s);
|
||||
#endif
|
||||
@@ -0,0 +1,247 @@
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "lib/video/uvc/hg_usb_device.h"
|
||||
#include "osal/irq.h"
|
||||
|
||||
|
||||
|
||||
//需要获取usb的句柄
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
|
||||
#include "dev/usb/hgusb20_v1_dev_api.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
static stream *g_usb_to_lcd_s = NULL;
|
||||
uint8_t dispuvc = 0;
|
||||
extern uint8 uvc_dpi;
|
||||
extern uint8_t uvc_open;
|
||||
extern volatile uint8 scale2_finish;
|
||||
extern void uvc_reset_dev(uint8_t en);
|
||||
extern void uvc_stream_open(struct hgusb20_dev *p_dev,uint8 enable);
|
||||
void jpg_decode_to_lcd(uint32 photo,uint32 jpg_w,uint32 jpg_h,uint32 video_w,uint32 video_h);
|
||||
int32_t usb_to_lcd_work(struct os_work *work);
|
||||
struct usb_to_lcd_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct data_structure *get_f;
|
||||
struct data_structure *get_f_tmp;
|
||||
};
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
//_os_printf("%s:%d\topcode:%d\n",__FUNCTION__,__LINE__,opcode);
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
|
||||
s->priv = custom_malloc(sizeof(struct usb_to_lcd_s));
|
||||
memset(s->priv,0,sizeof(struct usb_to_lcd_s));
|
||||
enable_stream(s,1);
|
||||
#if RTT_USB_EN
|
||||
|
||||
#else
|
||||
void *dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
//hgusb20_host_reset_phy(dev);
|
||||
uvc_reset_dev_mjpeg(1);
|
||||
uvc_stream_open((struct hgusb20_dev *)dev,1);
|
||||
#endif
|
||||
|
||||
//启动workqueue中usb_to_lcd事件
|
||||
{
|
||||
struct usb_to_lcd_s *usb_to_lcd = (struct usb_to_lcd_s*)s->priv;
|
||||
OS_WORK_INIT(&usb_to_lcd->work, usb_to_lcd_work, 0);
|
||||
os_run_work_delay(&usb_to_lcd->work, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
if(s->priv)
|
||||
{
|
||||
struct usb_to_lcd_s *usb_to_lcd = (struct usb_to_lcd_s*)s->priv;
|
||||
os_work_cancle2(&usb_to_lcd->work,1);
|
||||
|
||||
if(usb_to_lcd->get_f)
|
||||
{
|
||||
free_data(usb_to_lcd->get_f);
|
||||
usb_to_lcd->get_f = NULL;
|
||||
}
|
||||
|
||||
if(usb_to_lcd->get_f_tmp)
|
||||
{
|
||||
free_data(usb_to_lcd->get_f_tmp);
|
||||
usb_to_lcd->get_f_tmp = NULL;
|
||||
}
|
||||
custom_free(usb_to_lcd);
|
||||
s->priv = NULL;
|
||||
}
|
||||
|
||||
#if RTT_USB_EN
|
||||
|
||||
#else
|
||||
void *dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
uvc_stream_open((struct hgusb20_dev *)dev,0);
|
||||
uvc_reset_dev_mjpeg(0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int32_t usb_to_lcd_work(struct os_work *work)
|
||||
{
|
||||
stream *s = g_usb_to_lcd_s;
|
||||
static uint32_t old_time;
|
||||
static uint32_t timeout;
|
||||
struct usb_to_lcd_s* usb_to_lcd = (struct usb_to_lcd_s*)s->priv;
|
||||
struct stream_jpeg_data_s *dest_list;
|
||||
struct stream_jpeg_data_s *dest_list_tmp;
|
||||
uint32_t total_len;
|
||||
uint32_t uint_len;
|
||||
static uint8_t count = 0;
|
||||
struct stream_jpeg_data_s *el,*tmp;
|
||||
uint8_t *jpeg_buf_addr = NULL;
|
||||
static uint32_t wait_time = 0;
|
||||
|
||||
if((os_jiffies() - old_time) > 1000){
|
||||
old_time = os_jiffies();
|
||||
dispuvc = count;
|
||||
count = 0;
|
||||
}else{
|
||||
if(os_jiffies() < old_time){ //os_jiffies 溢出处理
|
||||
old_time = os_jiffies();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(usb_to_lcd->get_f == NULL)
|
||||
{
|
||||
usb_to_lcd->get_f = recv_real_data(s);
|
||||
}
|
||||
|
||||
|
||||
//准备解码下一帧,释放上一次的
|
||||
if((os_jiffies() - timeout) > 200){
|
||||
if(usb_to_lcd->get_f_tmp )
|
||||
{
|
||||
free_data(usb_to_lcd->get_f_tmp);
|
||||
usb_to_lcd->get_f_tmp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(usb_to_lcd->get_f)
|
||||
{
|
||||
|
||||
if(!scale2_finish)
|
||||
{
|
||||
wait_time++;
|
||||
if(wait_time > 100)
|
||||
{
|
||||
_os_printf("Dcod err\r\n");
|
||||
scale2_finish = 1;
|
||||
wait_time = 0;
|
||||
}
|
||||
goto usb_to_lcd_work_end;
|
||||
}
|
||||
dest_list = (struct stream_jpeg_data_s *)get_stream_real_data(usb_to_lcd->get_f);
|
||||
dest_list_tmp = dest_list;
|
||||
total_len = get_stream_real_data_len(usb_to_lcd->get_f);
|
||||
uint_len = stream_data_custom_cmd_func(usb_to_lcd->get_f,CUSTOM_GET_NODE_LEN,NULL);
|
||||
count++;
|
||||
//准备解码下一帧,释放上一次的
|
||||
if(usb_to_lcd->get_f_tmp )
|
||||
{
|
||||
free_data(usb_to_lcd->get_f_tmp);
|
||||
usb_to_lcd->get_f_tmp = NULL;
|
||||
}
|
||||
usb_to_lcd->get_f_tmp = usb_to_lcd->get_f;
|
||||
timeout = os_jiffies();
|
||||
|
||||
LL_FOREACH_SAFE(dest_list,el,tmp)
|
||||
{
|
||||
if(dest_list_tmp == el)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//读取完毕删除
|
||||
//图片保存起来
|
||||
//理论这里就是一张图片,由于这里是节点形式,所以这里暂时先去实现,后续获取一张图片形式显示
|
||||
|
||||
jpeg_buf_addr = (uint8_t *)stream_data_custom_cmd_func(usb_to_lcd->get_f,CUSTOM_GET_NODE_BUF,el->data);//GET_JPG_SELF_BUF(data,el->data);
|
||||
scale2_finish = 0;
|
||||
_os_printf("M");
|
||||
#if RTT_USB_EN
|
||||
jpg_decode_to_lcd((uint32)jpeg_buf_addr,640,480,320,240);
|
||||
#else
|
||||
if(uvc_dpi == 1){
|
||||
jpg_decode_to_lcd((uint32)jpeg_buf_addr,640,480,160,120);
|
||||
}else if(uvc_dpi == 2){
|
||||
jpg_decode_to_lcd((uint32)jpeg_buf_addr,1280,720,160,120);
|
||||
}
|
||||
#endif
|
||||
|
||||
//jpg_decode_to_lcd((uint32)jpeg_buf_addr,1280,720,160,120);
|
||||
//DEL_JPEG_NODE(usb_to_lcd->get_f,el);
|
||||
break;
|
||||
}
|
||||
wait_time = 0;
|
||||
//读取图片,显示在lcd
|
||||
//free_data(usb_to_lcd->get_f);
|
||||
usb_to_lcd->get_f = NULL;
|
||||
}
|
||||
|
||||
|
||||
usb_to_lcd_work_end:
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t enable_video_usb_to_lcd(uint8_t enable)
|
||||
{
|
||||
if(enable)
|
||||
{
|
||||
stream *s = NULL;
|
||||
s = open_stream_available(R_JPEG_TO_LCD,0,8,opcode_func,NULL);
|
||||
g_usb_to_lcd_s = s;
|
||||
if(s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int res;
|
||||
if(g_usb_to_lcd_s)
|
||||
{
|
||||
res = close_stream(g_usb_to_lcd_s);
|
||||
if(!res)
|
||||
{
|
||||
g_usb_to_lcd_s = NULL;
|
||||
os_printf("%s close end\n",__FUNCTION__);
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef __VIDEO_APP_USB_TO_LCD_H
|
||||
#define __VIDEO_APP_USB_TO_LCD_H
|
||||
void my_user(void *d);
|
||||
#endif
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "jpgdef.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "lib/video/uvc/hg_usb_device.h"
|
||||
#include "osal/irq.h"
|
||||
|
||||
#include "osal_file.h"
|
||||
#include "media.h"
|
||||
|
||||
|
||||
//需要获取usb的句柄
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
|
||||
#include "dev/usb/hgusb20_v1_dev_api.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
#if USB_EN == 1 && SD_SAVE == 1
|
||||
|
||||
extern void uvc_reset_dev(uint8_t en);
|
||||
extern void uvc_stream_open(struct hgusb20_dev *p_dev,uint8 enable);
|
||||
extern void usb_host_h264_uvc_reset();
|
||||
extern int no_frame_record_video_psram(void *fp,void *d,int flen);
|
||||
int32_t usb_to_card_work(struct os_work *work);
|
||||
static struct os_task uvc_h264_task;
|
||||
struct os_semaphore h264_sem;
|
||||
|
||||
#define H264_FNUM 3
|
||||
struct usb_to_card_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct data_structure *get_f;
|
||||
struct data_structure *get_f_tmp;
|
||||
};
|
||||
|
||||
struct h264_msg_s
|
||||
{
|
||||
uint8* addr;
|
||||
uint32 len;
|
||||
uint32 num;
|
||||
};
|
||||
|
||||
struct h264_msg_s h264msg[H264_FNUM];
|
||||
uint8_t *pwsram;
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
//_os_printf("%s:%d\topcode:%d\n",__FUNCTION__,__LINE__,opcode);
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
|
||||
enable_stream(s,1);
|
||||
|
||||
//hgusb20_host_reset_phy(dev);
|
||||
#if RTT_USB_EN
|
||||
|
||||
#else
|
||||
void *dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
uvc_reset_dev_mjpeg(1);
|
||||
usb_host_h264_uvc_reset();
|
||||
uvc_stream_open((struct hgusb20_dev *)dev,1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
|
||||
#if RTT_USB_EN
|
||||
|
||||
#else
|
||||
void *dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
|
||||
uvc_stream_open((struct hgusb20_dev *)dev,0);
|
||||
uvc_reset_dev_mjpeg(0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
//测试写h264,写大概300帧
|
||||
void stream_write_h264_thread2(void *d){
|
||||
void *fp;
|
||||
stream *s = (stream *)d;
|
||||
|
||||
struct data_structure *get_f = NULL;
|
||||
uint32 flen;
|
||||
uint32_t cnt = 0;;
|
||||
fp = create_video_file("0:/DCIM");
|
||||
uint32_t timeout = 0;
|
||||
while(fp)
|
||||
{
|
||||
get_f = recv_real_data(s);
|
||||
if(get_f)
|
||||
{
|
||||
|
||||
timeout = 0;
|
||||
flen = get_stream_real_data_len(get_f);
|
||||
#ifdef PSRAM_HEAP
|
||||
no_frame_record_video_psram(fp,get_f,flen);
|
||||
#endif
|
||||
free_data(get_f);
|
||||
cnt++;
|
||||
os_printf("w:%d",cnt);
|
||||
|
||||
get_f = NULL;
|
||||
if(cnt > 300)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
timeout++;
|
||||
}
|
||||
if(timeout > 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(fp)
|
||||
{
|
||||
osal_fclose(fp);
|
||||
}
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
close_stream(s);
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint8_t enable_video_usb_to_tfcard(uint8_t enable)
|
||||
{
|
||||
if(enable)
|
||||
{
|
||||
stream *s = NULL;
|
||||
s = open_stream_available(R_RECORD_H264,0,8,opcode_func,NULL);
|
||||
if(!s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
OS_TASK_INIT("h264_stream", &uvc_h264_task, stream_write_h264_thread2, s, OS_TASK_PRIORITY_ABOVE_NORMAL, 1024);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int32 demo_atcmd_save_h264(const char *cmd, char *argv[], uint32 argc)
|
||||
{
|
||||
#if USB_EN == 1 && SD_SAVE == 1
|
||||
if(argc < 1)
|
||||
{
|
||||
os_printf("%s argc too small:%d,should more 2 arg\n",__FUNCTION__,argc);
|
||||
return 0;
|
||||
}
|
||||
if(os_atoi(argv[0]) == 1)
|
||||
{
|
||||
enable_video_usb_to_tfcard(1);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user