289 lines
7.2 KiB
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;
|
|
}
|