doubao_chat/apps/wifi_camera/wifi/rt_talk_net.c

289 lines
7.2 KiB
C

#include "app_config.h"
#include "sock_api/sock_api.h"
#include "os/os_api.h"
#include "server/rt_stream_pkg.h"
#include "circular_buf.h"
#define CHECK_CODE 0x88
#define CHECK_CODE_NUM 32
#define DATA_BUF_SIZE 16*1024
#define RECV_TIME_OUT 3*1000
#define AUDIO_TIME_DELAY 100 //ms
/*
static void *rt_talk->sock;
static cbuffer_t rt_talk->cbuf_net_data;
char data_buf[DATA_BUF_SIZE];
static int thread_pid;
static u32 rt_talk->recv_time = 0;
*/
static u32 old_frame_seq = 0;
static u8 rt_talk_status = 0;
struct __rt_talk {
void *sock;
u8 data_buf[DATA_BUF_SIZE];
int thread_pid;
u32 recv_time;
cbuffer_t cbuf_net_data;
};
struct __rt_talk *rt_talk;
extern void rt_talk_voice_play(void);
extern void rt_talk_voice_stop(void);
extern int rt_talk_voice_init(void);
extern int rt_talk_voice_uninit(void);
extern unsigned int time_lapse(unsigned int *handle, unsigned int time_out);
static int bytecmp(unsigned char *p, unsigned char ch, unsigned int num)
{
while (num-- > 0) {
if (*p++ != ch) {
return -1;
}
}
return 0;
}
u8 get_rt_talk_status(void)
{
return rt_talk_status;
}
//图片封包函数
static int get_pcm_packet(char *buf, int len, char *pcm_buf, int *pcm_buf_len)
{
static u32 total_payload_len = 0;
static u8 finish = 0;
u32 position = 0;
u32 frame_head_size = sizeof(struct frm_head);
u8 frame_type;
u32 cur_frame_seq;
u32 frame_offset;
u32 slice_data_len;
u32 frame_size;
if (len < frame_head_size) {
printf("\n%s %d->data err\n", __func__, __LINE__);
goto ERROR;
}
do {
struct frm_head *head_info = (struct frm_head *)(buf + position);
frame_type = head_info->type & 0x7F;
cur_frame_seq = head_info->seq;
frame_offset = head_info->offset;
slice_data_len = head_info->payload_size;
frame_size = head_info->frm_sz;
len -= (frame_head_size + slice_data_len);//如果帧头长+数据长度!=包长度
if (len < 0) {
printf("\n%s %d->data err\n", __func__, __LINE__); //认为是错误的数据包
goto ERROR;
}
switch (frame_type) {
case PCM_TYPE_AUDIO:
if (cur_frame_seq < old_frame_seq) { //如果当前的seq小于旧的seq,说明是旧的数据包,跳过不处理
printf("\n%s %d->recv old seq\n", __func__, __LINE__);
goto continue_deal;
} else if (cur_frame_seq > old_frame_seq) { //如果当前seq大于旧的seq,认为是新的数据包,接收包初始化
if (total_payload_len && (finish == 0)) {
printf("\n%s %d->recv old seq\n", __func__, __LINE__);
}
old_frame_seq = cur_frame_seq;
total_payload_len = 0;
finish = 0;
memset(pcm_buf, CHECK_CODE, 4096);
}
if (bytecmp((unsigned char *)pcm_buf + frame_offset, CHECK_CODE, CHECK_CODE_NUM) != 0) {
printf("\n%s %d->repeat seq\n", __func__, __LINE__);
goto continue_deal;
}
memcpy(pcm_buf + frame_offset, (buf + position) + frame_head_size, slice_data_len);//对应数据放置到对应的位置
total_payload_len += slice_data_len;//累加总长度
if (total_payload_len == frame_size) { //如果数据量相等,说明帧数据接收完成
*pcm_buf_len = total_payload_len;
finish = 1;
//printf("\n%s %d->finish\n",__func__,__LINE__);
return 0;
}
continue_deal:
position += (frame_head_size + slice_data_len);
break;
default:
printf("\n%s %d---type >> %d\n", __func__, __LINE__, frame_type);
break;
}
} while (len > 0);
ERROR:
return -1;
}
u32 read_net_data_cbuf(void *buf, u32 len)
{
u32 rlen;
rlen = cbuf_read(&rt_talk->cbuf_net_data, buf, len);
return rlen;
}
u32 write_net_data_cbuf(void *buf, u32 len)
{
u32 wlen;
wlen = cbuf_write(&rt_talk->cbuf_net_data, buf, len);
return wlen;
}
static void rt_talk_data_recv(void *priv)
{
int recv_len;
u32 w_len;
char recv_buf[4000];
int pcm_buf_len;
char pcm_buf[8000];
void *dev;
while (1) {
recv_len = sock_recvfrom(rt_talk->sock, recv_buf, sizeof(recv_buf), 0, NULL, NULL);
if (recv_len <= 0) {
printf("\n%s %d->exit\n", __func__, __LINE__);
rt_talk_voice_stop();
break;
}
rt_talk->recv_time = 0;
if (get_pcm_packet(recv_buf, recv_len, pcm_buf, &pcm_buf_len) == 0) {
w_len = write_net_data_cbuf(pcm_buf, pcm_buf_len);
if (w_len == 0) {
printf("\n%s %d->cbuf_clear\n", __func__, __LINE__);
cbuf_clear(&rt_talk->cbuf_net_data);
} else {
u32 data_size;
data_size = cbuf_get_data_size(&rt_talk->cbuf_net_data);
if (data_size >= 16 * AUDIO_TIME_DELAY) {
//printf("\n%s %d->play\n",__func__,__LINE__);
rt_talk_voice_play();
} else if (data_size < 16 * 20) {
printf("\n%s %d->stop\n", __func__, __LINE__);
rt_talk_voice_stop();
}
}
}
}
}
static int rt_talk_recv_cb(enum sock_api_msg_type type, void *priv)
{
if (time_lapse(&rt_talk->recv_time, RECV_TIME_OUT)) {
puts("|RT_TALK_NO_RECV_DATA|\n");
rt_talk_voice_stop();
return -1;
}
return 0;
}
int rt_talk_net_init(void)
{
struct sockaddr_in dest_addr;
int err;
if (rt_talk != NULL) {
printf("\nAPP not allow open again\n");
return 0;
}
rt_talk = calloc(sizeof(struct __rt_talk), 1);
if (rt_talk == NULL) {
printf("\nnot enough space\n");
goto EXIT;
}
rt_talk_voice_init();
rt_talk->sock = sock_reg(AF_INET, SOCK_DGRAM, 0, rt_talk_recv_cb, NULL);
if (rt_talk->sock == NULL) {
printf("\n%s %d ->Error in socket()\n", __func__, __LINE__);
goto EXIT;
}
if (sock_set_reuseaddr(rt_talk->sock)) {
printf("%s %d->Error in sock_set_reuseaddr(),errno=%d\n", __func__, __LINE__, errno);
goto EXIT;
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_port = htons(2231);
err = sock_bind(rt_talk->sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
if (err) {
printf("%s %d->Error in bind(),errno=%d\n", __func__, __LINE__, errno);
goto EXIT;
}
cbuf_init(&rt_talk->cbuf_net_data, rt_talk->data_buf, sizeof(rt_talk->data_buf));
old_frame_seq = 0;
rt_talk_status = 1;
thread_fork("RT_RECV_THREAD", 25, 0x1000, 0, &rt_talk->thread_pid, rt_talk_data_recv, NULL);
return 0;
EXIT:
if (rt_talk->sock) {
sock_unreg(rt_talk->sock);
}
return -1;
}
int rt_talk_net_uninit(void)
{
if (rt_talk != NULL) {
sock_unreg(rt_talk->sock);
thread_kill(&rt_talk->thread_pid, 0);
rt_talk_status = 0;
rt_talk_voice_uninit();
free(rt_talk);
rt_talk = NULL;
}
return 0;
}