Files
OpenTXW81X/sdk/app/avi_save_stream/avi_save_stream.c
T
2025-08-27 09:51:58 +01:00

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;
}