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

211 lines
5.4 KiB
C

//主要作用是独立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;
}