doubao_chat/apps/demo/demo_video/user_video_rec.c

268 lines
7.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "system/includes.h"
#include "server/video_server.h"
#include "app_config.h"
#include "asm/debug.h"
#include "asm/osd.h"
#include "asm/isc.h"
#include "os/os_api.h"
#include "camera.h"
#include "video_buf_config.h"
#include "stream_protocol.h"
#include "rt_stream_pkg.h"
/***********************************USER VIDEO*******************************************
1、调用user_video_rec0_open,打开摄像头成功后,会回调到video_rt_usr_init
2、数据回调:user_video_frame_callback函数
注意:该函数不能进行延时太长操作,否则丢帧,数据回调用在发送数据或者拷贝数据
3、调用user_video_rec0_close关闭摄像头
****************************************************************************************/
#ifdef CONFIG_USR_VIDEO_ENABLE
struct user_video_hdl {
u8 state;
u8 page_turning;
u8 req_send;
u8 *user_isc_buf;
u8 *user_video_buf;
u8 *user_audio_buf;
struct server *user_video_rec;
};
static struct user_video_hdl user_handler = {0};
#define __this_user (&user_handler)
#define USER_ISC_SBUF_SIZE (CONFIG_VIDEO_IMAGE_W*32*3/2)
#define USER_VIDEO_SBUF_SIZE USER_VREC0_FBUF_SIZE
#define USER_ISC_STATIC_BUFF_ENABLE 1 //1使用静态内部ram
#if USER_ISC_STATIC_BUFF_ENABLE
static u8 user_isc_sbuf[USER_ISC_SBUF_SIZE] SEC(.sram) ALIGNE(32);//必须32对齐
#endif
#endif
#ifdef CONFIG_OSD_ENABLE
static const unsigned char user_osd_format_buf[] = "yyyy-nn-dd hh:mm:ss";//时间OSD
#endif
void set_video_rt_cb(u32(*cb)(void *buf, u32 len, u8 type));
/*
*码率控制,根据具体分辨率设置:1000 - 6000
*/
int user_video_rec_get_abr(u32 width)
{
if (width <= 640) {
return 3000;
} else {
return 4000;
}
}
/*
*音视频数据回调
*/
u32 user_video_frame_callback(void *data, u32 len, u8 type)
{
if (type == JPEG_TYPE_VIDEO) { //jpeg视频
putchar('V');
/*put_buf(data, len);*/
} else if (type == PCM_TYPE_AUDIO) { //PCM音频
putchar('A');
/*put_buf(data, len);*/
}
return 0;
}
/*
*用户VIDEO打开
*/
int user_video_rec0_open(void)
{
int err = 0;
#ifdef CONFIG_USR_VIDEO_ENABLE
union video_req req = {0};
char path[48];
if (__this_user->state) {
printf("user already open \n");
return 0;
}
if (!__this_user->user_video_buf) {
__this_user->user_video_buf = malloc(USER_VIDEO_SBUF_SIZE);
if (!__this_user->user_video_buf) {
puts("no mem \n");
return -1;
}
}
if (!__this_user->user_audio_buf && VIDEO_REC_AUDIO_SAMPLE_RATE) {
__this_user->user_audio_buf = malloc(USER_AUDIO_BUF_SIZE);
if (!__this_user->user_audio_buf) {
puts("no mem \n");
return -1;
}
}
#if USER_ISC_STATIC_BUFF_ENABLE
__this_user->user_isc_buf = user_isc_sbuf;
#else
if (!__this_user->user_isc_buf) {
__this_user->user_isc_buf = malloc(USER_ISC_SBUF_SIZE);
if (!__this_user->user_isc_buf) {
puts("no mem \n");
goto __exit;
}
}
#endif
if (!__this_user->user_video_rec) {
__this_user->user_video_rec = server_open("video_server", "video0.1");
if (!__this_user->user_video_rec) {
goto __exit;
}
}
#ifdef CONFIG_VIDEO_REC_PPBUF_MODE
req.rec.bfmode = VIDEO_PPBUF_MODE;
#endif
#ifdef CONFIG_VIDEO_SPEC_DOUBLE_REC_MODE
req.rec.wl80_spec_mode = VIDEO_WL80_SPEC_DOUBLE_REC_MODE;
#endif
req.rec.picture_mode = 0;//非绘本模式
req.rec.isc_sbuf = __this_user->user_isc_buf;
req.rec.sbuf_size = USER_ISC_SBUF_SIZE;
req.rec.camera_type = VIDEO_CAMERA_NORMAL;
req.rec.channel = 1;
req.rec.width = CONFIG_VIDEO_IMAGE_W;
req.rec.height = CONFIG_VIDEO_IMAGE_H;
req.rec.state = VIDEO_STATE_START;
req.rec.format = USER_VIDEO_FMT_AVI;
req.rec.quality = VIDEO_LOW_Q;//VIDEO_MID_Q;
req.rec.fps = 0;
req.rec.real_fps = 15;//帧率
//需要音频:请写audio.sample_rate和audio.buf、audio.buf_len
req.rec.audio.sample_rate = VIDEO_REC_AUDIO_SAMPLE_RATE;//8000 音频采样率
req.rec.audio.channel = 1;//选择硬件1个MIC数
req.rec.audio.channel_bit_map = 0;//选择第几个MIC,0则是版籍配置文件默认,//LADC_CH_MIC1_P_N
req.rec.audio.volume = 100;//音频增益0-100
req.rec.audio.buf = __this_user->user_audio_buf;//音频BUFF
req.rec.audio.buf_len = USER_AUDIO_BUF_SIZE;//音频BUFF长度
req.rec.abr_kbps = user_video_rec_get_abr(req.rec.width);//JPEG图片码率
req.rec.buf = __this_user->user_video_buf;
req.rec.buf_len = USER_VIDEO_SBUF_SIZE;
req.rec.block_done_cb = 0;
#ifdef CONFIG_OSD_ENABLE
struct video_text_osd text_osd = {0};
text_osd.font_w = OSD_DEFAULT_WIDTH;//必须16对齐
text_osd.font_h = OSD_DEFAULT_HEIGHT;//必须16对齐
text_osd.text_format = user_osd_format_buf;
text_osd.x = (req.rec.width - text_osd.font_w * strlen(text_osd.text_format) + 15) / 16 * 16;
text_osd.y = (req.rec.height - text_osd.font_h + 15) / 16 * 16;
text_osd.osd_yuv = 0xe20095;
req.rec.text_osd = &text_osd;
#endif
#ifdef CONFIG_USR_VIDEO_ENABLE
sprintf(path, "usr://%s", CONFIG_USR_PATH);
#else
sprintf(path, "usr://%s", "192.168.1.1");
#endif
err = server_request(__this_user->user_video_rec, VIDEO_REQ_REC, &req);
if (err != 0) {
puts("user start rec err\n");
goto __exit;
}
req.rec.packet_cb = stream_packet_cb;//注册数据包回调函数进行协议转发
err = server_request(__this_user->user_video_rec, VIDEO_REQ_SET_PACKET_CALLBACK, &req);
if (err != 0) {
puts("stream_packet_cb set err\n");
goto __exit;
}
#if 1 /*需要加上video_rt_usr.c文件则可以创建协议转发任务*/
err = stream_protocol_task_create(path, NULL);//协议转发任务创建
if (err != 0) {
puts("stream_packet_cb set err\n");
goto __exit;
}
set_video_rt_cb(user_video_frame_callback);
#endif
__this_user->state = true;
printf("user video rec open ok\n");
return err;
__exit:
if (__this_user->user_video_rec) {
memset(&req, 0, sizeof(req));
req.rec.channel = 1;
req.rec.state = VIDEO_STATE_STOP;
server_request(__this_user->user_video_rec, VIDEO_REQ_REC, &req);
server_close(__this_user->user_video_rec);
__this_user->user_video_rec = NULL;
}
if (__this_user->user_video_buf) {
free(__this_user->user_video_buf);
__this_user->user_video_buf = NULL;
}
if (__this_user->user_audio_buf) {
free(__this_user->user_audio_buf);
__this_user->user_audio_buf = NULL;
}
#if !USER_ISC_STATIC_BUFF_ENABLE
if (__this_user->user_isc_buf) {
free(__this_user->user_isc_buf);
__this_user->user_isc_buf = NULL;
}
#endif
#endif
return err;
}
/*
*用户VIDEO关闭
*/
int user_video_rec0_close(void)
{
int err = 0;
#ifdef CONFIG_USR_VIDEO_ENABLE
union video_req req = {0};
if (__this_user->user_video_rec) {
req.rec.channel = 1;
req.rec.state = VIDEO_STATE_STOP;
err = server_request(__this_user->user_video_rec, VIDEO_REQ_REC, &req);
if (err != 0) {
printf("\nstop rec err 0x%x\n", err);
return -1;
}
server_close(__this_user->user_video_rec);
#if 1 /*需要加上video_rt_usr.c文件则可删除协议转发任务*/
stream_protocol_task_kill();
#endif
__this_user->user_video_rec = NULL;
__this_user->state = false;
printf("user video rec close ok\n");
}
if (__this_user->user_video_buf) {
free(__this_user->user_video_buf);
__this_user->user_video_buf = NULL;
}
if (__this_user->user_audio_buf) {
free(__this_user->user_audio_buf);
__this_user->user_audio_buf = NULL;
}
#if !USER_ISC_STATIC_BUFF_ENABLE
if (__this_user->user_isc_buf) {
free(__this_user->user_isc_buf);
__this_user->user_isc_buf = NULL;
}
#endif
#endif
return 0;
}