317 lines
7.1 KiB
C
317 lines
7.1 KiB
C
#include "osal/string.h"
|
|
#include "stream_frame.h"
|
|
#include "osal/task.h"
|
|
#include "osal/event.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
|
|
|
|
typedef struct
|
|
{
|
|
const char *video_name;
|
|
const char *audio_name;
|
|
uint16_t video_cache_num;
|
|
uint16_t audio_cache_num;
|
|
uint16_t fps;
|
|
uint16_t frq;
|
|
|
|
}manage_stream_common_s;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
manage_stream_common_s msg;
|
|
stream *video_s;
|
|
stream *audio_s;
|
|
struct os_task task;
|
|
struct os_event evt;
|
|
int flag;
|
|
|
|
}manage_stream_s;
|
|
|
|
|
|
enum
|
|
{
|
|
AVI_STREAM_STOP = BIT(0),
|
|
AVI_STREAM_EXIT = BIT(1),
|
|
};
|
|
|
|
|
|
static int avi_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);
|
|
}
|
|
break;
|
|
case STREAM_OPEN_FAIL:
|
|
break;
|
|
|
|
case STREAM_FILTER_DATA:
|
|
{
|
|
struct data_structure *data = (struct data_structure *)priv;
|
|
//os_printf("%s:%d\tdata:%X\n",__FUNCTION__,__LINE__,data);
|
|
//os_printf("type:%X\n",GET_DATA_TYPE1(data->type));
|
|
if(GET_DATA_TYPE1(data->type) != JPEG)
|
|
{
|
|
res = 1;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
//默认都返回成功
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
static int audio_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);
|
|
}
|
|
break;
|
|
case STREAM_OPEN_FAIL:
|
|
break;
|
|
|
|
case STREAM_FILTER_DATA:
|
|
{
|
|
struct data_structure *data = (struct data_structure *)priv;
|
|
//os_printf("%s:%d\tdata:%X\n",__FUNCTION__,__LINE__,data);
|
|
//os_printf("type:%X\n",GET_DATA_TYPE1(data->type));
|
|
if(GET_DATA_TYPE1(data->type) != SOUND)
|
|
{
|
|
res = 1;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
//默认都返回成功
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
extern uint8_t *get_jpeg_buf(struct data_structure *data,uint32_t *len);
|
|
extern int parse_jpg(uint8_t *jpg_buf,uint32_t maxsize,uint32_t *w,uint32_t *h);
|
|
extern int new_sd_save_avi2(int *exit_flag,stream *s,stream *audio_s,int fps,int audiofrq,int settime,int pic_w,int pic_h);
|
|
static void avi_save_thread(void *d)
|
|
{
|
|
int err = 0;
|
|
uint32_t w = 0;
|
|
uint32_t h = 0;
|
|
struct data_structure *get_f = NULL;
|
|
uint32_t len;
|
|
uint8_t *buf;
|
|
manage_stream_s *manage = (manage_stream_s *)d;
|
|
if(manage->msg.video_name)
|
|
{
|
|
manage->video_s = open_stream_available(manage->msg.video_name,0,manage->msg.video_cache_num,avi_opcode_func,NULL);
|
|
}
|
|
|
|
if(manage->msg.audio_name)
|
|
{
|
|
manage->audio_s = open_stream_available(manage->msg.audio_name,0,manage->msg.audio_cache_num,audio_opcode_func,NULL);
|
|
}
|
|
|
|
if(manage->video_s)
|
|
{
|
|
enable_stream(manage->video_s,1);
|
|
}
|
|
|
|
if(manage->audio_s)
|
|
{
|
|
enable_stream(manage->audio_s,1);
|
|
}
|
|
|
|
while(manage->flag)
|
|
{
|
|
//先去尝试获取第一张图片,分析分辨率
|
|
if(w == 0 || h == 0)
|
|
{
|
|
get_f = recv_real_data(manage->video_s);
|
|
if(get_f)
|
|
{
|
|
buf = get_jpeg_buf(get_f,&len);
|
|
parse_jpg(buf,len,&w,&h);
|
|
os_printf("%s:%d\tw:%d\th:%d\n",__FUNCTION__,__LINE__,w,h);
|
|
free_data(get_f);
|
|
}
|
|
else
|
|
{
|
|
os_sleep_ms(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(manage->video_s)
|
|
{
|
|
enable_stream(manage->video_s,1);
|
|
}
|
|
|
|
if(manage->audio_s)
|
|
{
|
|
enable_stream(manage->audio_s,1);
|
|
}
|
|
|
|
|
|
err = new_sd_save_avi2(&manage->flag,manage->video_s,manage->audio_s,manage->msg.fps,manage->msg.frq,60*1,w,h);
|
|
}
|
|
}
|
|
close_stream(manage->video_s);
|
|
close_stream(manage->audio_s);
|
|
//设置退出
|
|
os_event_set(&manage->evt,AVI_STREAM_EXIT,NULL);
|
|
|
|
}
|
|
|
|
static int opcode_func(stream *s,void *priv,int opcode)
|
|
{
|
|
int res = 0;
|
|
switch(opcode)
|
|
{
|
|
case STREAM_OPEN_ENTER:
|
|
break;
|
|
case STREAM_OPEN_EXIT:
|
|
{
|
|
//创建结构体,创建一个线程
|
|
manage_stream_s *manage = (manage_stream_s*)STREAM_LIBC_ZALLOC(sizeof(manage_stream_s));
|
|
if(priv && manage)
|
|
{
|
|
s->priv = (void*)manage;
|
|
manage_stream_common_s *common = (manage_stream_common_s*)priv;
|
|
os_memcpy(manage,common,sizeof(manage_stream_common_s));
|
|
manage->flag = 1;
|
|
|
|
//初始化事件
|
|
os_event_init(&manage->evt);
|
|
//创建线程
|
|
OS_TASK_INIT(s->name,&manage->task,avi_save_thread,manage,OS_TASK_PRIORITY_NORMAL,1024);
|
|
//创建失败,设置可以退出的标志
|
|
if(!manage->task.hdl)
|
|
{
|
|
os_event_set(&manage->evt,AVI_STREAM_EXIT,NULL);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case STREAM_OPEN_FAIL:
|
|
break;
|
|
|
|
case STREAM_DATA_DIS:
|
|
{
|
|
}
|
|
break;
|
|
|
|
case STREAM_DATA_FREE:
|
|
{
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STREAM_FILTER_DATA:
|
|
{
|
|
}
|
|
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_MARK_GC_END:
|
|
{
|
|
|
|
|
|
}
|
|
break;
|
|
|
|
case STREAM_CLOSE_ENTER:
|
|
{
|
|
manage_stream_s *manage = (manage_stream_s *)s->priv;
|
|
manage->flag = 0;
|
|
os_event_wait(&manage->evt,AVI_STREAM_EXIT,NULL,OS_EVENT_WMODE_OR,-1);
|
|
break;
|
|
}
|
|
|
|
case STREAM_CLOSE_EXIT:
|
|
{
|
|
manage_stream_s *manage = (manage_stream_s *)s->priv;
|
|
os_event_del(&manage->evt);
|
|
STREAM_LIBC_FREE(s->priv);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//默认都返回成功
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
|
|
//创建一个线程,类似录像模块,管理音频和视频接收流的线程
|
|
//这个会由一个流去管理
|
|
stream *avi_save_stream(const char *manage_stream_name,const char *video_name,const char *audio_name,uint16_t video_cache_num,uint16_t audio_cache_num,uint16_t fps,uint16_t frq)
|
|
{
|
|
manage_stream_common_s manage;
|
|
manage.video_name = video_name;
|
|
manage.audio_name = audio_name;
|
|
manage.video_cache_num = video_cache_num;
|
|
manage.audio_cache_num = audio_cache_num;
|
|
manage.fps = fps;
|
|
manage.frq = frq;
|
|
|
|
stream *s = open_stream_available(manage_stream_name,0,0,opcode_func,&manage);
|
|
return s;
|
|
} |