379 lines
8.9 KiB
C
379 lines
8.9 KiB
C
#include "sys_common.h"
|
|
#include "server/rt_stream_pkg.h"
|
|
#include "lwip.h"
|
|
#include "stream_core.h"
|
|
#include "sock_api/sock_api.h"
|
|
#include "app_config.h"
|
|
|
|
|
|
static u8 inited = 0;//防止重复发送
|
|
static u32 aux_frame_cnt = 0;
|
|
|
|
extern int atoi(const char *__nptr);
|
|
struct cli_info {
|
|
struct list_head entry;
|
|
void *fd;
|
|
struct sockaddr_in addr;
|
|
};
|
|
|
|
|
|
struct video_rt_tcp_server_info {
|
|
struct list_head cli_head;
|
|
struct sockaddr_in local_addr;
|
|
void *fd;
|
|
OS_SEM sem;
|
|
u32 flag;
|
|
u8 cb_flag;
|
|
};
|
|
|
|
static struct video_rt_tcp_server_info server_info = {
|
|
.cli_head = {
|
|
.next = &server_info.cli_head,
|
|
.prev = &server_info.cli_head,
|
|
},
|
|
};
|
|
|
|
static struct cli_info *get_tcp_net_info();
|
|
extern int net_video_rec_get_list_vframe(void);
|
|
extern int net_video_buff_set_frame_cnt(void);
|
|
|
|
|
|
static int path_analyze(struct rt_stream_info *info, const *path)
|
|
{
|
|
|
|
char *tmp = NULL;
|
|
char *tmp2 = NULL;
|
|
char ip[15] = {0};
|
|
u16 port = 0;
|
|
tmp = strstr(path, "tcp://");
|
|
if (!tmp) {
|
|
return -1;
|
|
}
|
|
|
|
tmp += strlen("tcp://");
|
|
|
|
tmp2 = strchr(tmp, ':');
|
|
printf("tmp=%s len=%d\n", tmp, tmp2 - tmp);
|
|
strncpy(ip, tmp, tmp2 - tmp);
|
|
port = atoi(tmp2 + 1);
|
|
|
|
printf("remote ip:%s port:%d\n", ip, port);
|
|
|
|
|
|
info->addr.sin_family = AF_INET;
|
|
info->addr.sin_addr.s_addr = inet_addr(ip);
|
|
info->addr.sin_port = htons(port);
|
|
return 0;
|
|
|
|
}
|
|
static int video_rt_tcp_callback(enum sock_api_msg_type type, void *p)
|
|
{
|
|
//缓存大于2帧丢帧
|
|
struct video_rt_tcp_server_info *server_info = (struct video_rt_tcp_server_info *)p;
|
|
#if 0//暂时关闭,TCP发不完整一包会引起APP花屏
|
|
int vcnt = net_video_rec_get_list_vframe();
|
|
int set_cnt = net_video_buff_set_frame_cnt();
|
|
if (vcnt > set_cnt && set_cnt > 0) {
|
|
if (server_info) {
|
|
server_info->cb_flag = 1;//server_info.cb_flag = 1;
|
|
return -1;
|
|
}
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static void *video_rt_tcp_init(const char *path, const char *mode)
|
|
{
|
|
int ret = 0;
|
|
puts("video_rt_tcp_init\n");
|
|
struct rt_stream_info *r_info = calloc(1, sizeof(struct rt_stream_info));
|
|
|
|
if (r_info == NULL) {
|
|
printf("%s malloc fail\n", __FILE__);
|
|
return NULL;
|
|
}
|
|
|
|
path_analyze(r_info, path);
|
|
|
|
|
|
struct cli_info *info = get_tcp_net_info();
|
|
if (info == NULL) {
|
|
printf("%s get_tcp_net_info\n", __FILE__);
|
|
free(r_info);
|
|
return NULL;
|
|
}
|
|
|
|
sock_clr_quit(info->fd);
|
|
|
|
memcpy((void *)&r_info->addr, (void *)&info->addr, sizeof(struct sockaddr));
|
|
r_info->fd = info->fd;
|
|
|
|
return (void *)r_info;
|
|
}
|
|
|
|
static u32 video_rt_tcp_send(void *hdr, u8 *data, u32 len, u8 type)
|
|
{
|
|
struct rt_stream_info *r_info = (struct rt_stream_info *)hdr;
|
|
int ret;
|
|
char *buffer = NULL;
|
|
static u32 i = 0;
|
|
char mem[64];
|
|
u32 tmp2;
|
|
u32 tmp;
|
|
u32 start_code = 0x01000000;
|
|
|
|
struct frm_head frame_head = {0};
|
|
|
|
//缓存大于2帧丢帧
|
|
int vcnt = net_video_rec_get_list_vframe();
|
|
int set_cnt = net_video_buff_set_frame_cnt();
|
|
if (vcnt > set_cnt && set_cnt > 0) {
|
|
return len;
|
|
}
|
|
|
|
server_info.cb_flag = 0;
|
|
memset(&frame_head, 0, sizeof(struct frm_head));
|
|
|
|
frame_head.type = type ;
|
|
frame_head.seq = (i++);
|
|
|
|
if (aux_frame_cnt < 60) { //前面1.5秒加速播放
|
|
|
|
frame_head.timestamp += 0;
|
|
aux_frame_cnt++;
|
|
} else {
|
|
|
|
frame_head.timestamp += 0;
|
|
}
|
|
|
|
frame_head.timestamp = 0;
|
|
|
|
// frame_head.timestamp = 90000 / 30;
|
|
frame_head.frm_sz = len;
|
|
ret = sock_send(r_info->fd, (char *)&frame_head, sizeof(struct frm_head), 0);
|
|
if (server_info.cb_flag) {
|
|
return len;
|
|
}
|
|
if (ret <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
|
|
if (type == H264_TYPE_VIDEO) {
|
|
|
|
//防止数据源被改
|
|
memcpy(mem, data, 64);
|
|
buffer = mem;
|
|
|
|
if (*((char *)(buffer + 4)) == 0x67) {
|
|
//处理PPS帧和SPS帧 I帧
|
|
memcpy(&tmp, buffer, 4);
|
|
tmp = htonl(tmp);
|
|
memcpy(buffer, &start_code, 4);
|
|
memcpy(&tmp2, buffer + tmp + 4, 4);
|
|
tmp2 = htonl(tmp2);
|
|
memcpy(buffer + tmp + 4, &start_code, 4);
|
|
memcpy(buffer + tmp + tmp2 + 8, &start_code, 4);
|
|
//printf("tmp %d tmp2 %d\n",tmp,tmp2);
|
|
|
|
} else {
|
|
// 处理P帧
|
|
memcpy(buffer, &start_code, 4);
|
|
}
|
|
|
|
ret = sock_send(r_info->fd, mem, 64, 0);
|
|
if (server_info.cb_flag) {
|
|
return len;
|
|
}
|
|
if (ret <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
ret = sock_send(r_info->fd, (char *) data + 64, len - 64, 0);
|
|
if (server_info.cb_flag) {
|
|
return len;
|
|
}
|
|
if (ret <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = sock_send(r_info->fd, (char *)data, len, 0);
|
|
if (server_info.cb_flag) {
|
|
return len;
|
|
}
|
|
if (ret <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
/*static void video_rt_tcp_uninit(void *hdr)*/
|
|
void video_rt_tcp_uninit(void *hdr)
|
|
{
|
|
puts("video_rt_tcp_uninit\n\n\n\n\n\n");
|
|
|
|
/*aux_frame_cnt = 0;*/
|
|
/*struct rt_stream_info *r_info = (struct rt_stream_info *)hdr;*/
|
|
/*free(r_info);*/
|
|
/*puts("video_rt_tcp_uninit\n\n\n\n\n\n");*/
|
|
|
|
struct rt_stream_info *r_info = (struct rt_stream_info *)hdr;
|
|
sock_set_quit(r_info->fd);
|
|
aux_frame_cnt = 0;
|
|
if (r_info) {
|
|
free(r_info);
|
|
r_info = NULL;
|
|
}
|
|
}
|
|
|
|
REGISTER_NET_VIDEO_STREAM_SUDDEV(tcp_video_stream_sub) = {
|
|
.name = "tcp",
|
|
.open = video_rt_tcp_init,
|
|
.write = video_rt_tcp_send,
|
|
.close = video_rt_tcp_uninit,
|
|
};
|
|
|
|
|
|
int TCP_client_socket_quit(int addr)
|
|
{
|
|
struct cli_info *cli = NULL;
|
|
struct list_head *pos = &server_info.cli_head;
|
|
struct sockaddr_in *dest_addr = NULL;
|
|
|
|
list_for_each(pos, &server_info.cli_head) {
|
|
cli = list_entry(pos, struct cli_info, entry);
|
|
if (cli) {
|
|
dest_addr = &cli->addr;
|
|
if (dest_addr->sin_addr.s_addr == addr) {
|
|
sock_set_quit(cli->fd);
|
|
printf("TCP_client_socket_quit \n");
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static struct cli_info *get_tcp_net_info()
|
|
{
|
|
struct list_head *pos = NULL;
|
|
struct cli_info *cli = NULL;
|
|
struct cli_info *old_cli = NULL;
|
|
int count = 0;
|
|
os_sem_pend(&server_info.sem, 50);
|
|
|
|
list_for_each(pos, &server_info.cli_head) {
|
|
cli = list_entry(pos, struct cli_info, entry);
|
|
printf("ip:%s port:%d\n\n", inet_ntoa(cli->addr.sin_addr.s_addr), htons(cli->addr.sin_port));
|
|
count++;
|
|
}
|
|
printf("count = %d\n\n", count);
|
|
if (count > 1) {
|
|
old_cli = list_first_entry(&server_info.cli_head, struct cli_info, entry);
|
|
list_del(&old_cli->entry);
|
|
sock_set_quit(old_cli->fd);
|
|
sock_unreg(old_cli->fd);
|
|
old_cli->fd = NULL;
|
|
free(old_cli);
|
|
}
|
|
|
|
return cli;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __do_sock_accpet(void *arg)
|
|
{
|
|
|
|
socklen_t len = sizeof(server_info.local_addr);
|
|
while (1) {
|
|
|
|
struct cli_info *__cli = calloc(1, sizeof(sizeof(struct cli_info)));
|
|
if (__cli == NULL) {
|
|
printf("malloc fail\n");
|
|
while (1);
|
|
}
|
|
|
|
__cli->fd = sock_accept(server_info.fd, (struct sockaddr *)&__cli->addr, &len, video_rt_tcp_callback, &server_info);
|
|
if (server_info.flag) {
|
|
break;
|
|
}
|
|
if (__cli->fd == NULL) {
|
|
printf("some error in here\n\n");
|
|
continue;
|
|
}
|
|
printf("__do_sock_accpet add client list\n\n");
|
|
list_add_tail(&__cli->entry, &server_info.cli_head);
|
|
|
|
|
|
os_sem_post(&server_info.sem);
|
|
|
|
}
|
|
server_info.flag = 0;
|
|
sock_unreg(server_info.fd);
|
|
}
|
|
|
|
|
|
int video_rt_tcp_server_init(int port)
|
|
{
|
|
int ret = 0;
|
|
puts("video_rt_tcp_server_init\n");
|
|
|
|
memset(&server_info, 0x0, sizeof(server_info));
|
|
os_sem_create(&server_info.sem, 0);
|
|
|
|
server_info.local_addr.sin_family = AF_INET;
|
|
server_info.local_addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
|
|
server_info.local_addr.sin_port = htons(port);
|
|
|
|
|
|
server_info.fd = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL);
|
|
|
|
if (server_info.fd == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
u32 opt = 1;
|
|
if (sock_setsockopt(server_info.fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
|
printf("%s sock_bind fail\n", __FILE__);
|
|
return -1;
|
|
}
|
|
|
|
|
|
if (sock_bind(server_info.fd, (struct sockaddr *)&server_info.local_addr, sizeof(struct sockaddr))) {
|
|
printf("%s sock_bind fail\n", __FILE__);
|
|
return -1;
|
|
}
|
|
sock_listen(server_info.fd, 0x5);
|
|
|
|
INIT_LIST_HEAD(&server_info.cli_head);
|
|
ret = thread_fork("__do_sock_accpet", 25, 256, 0, 0, __do_sock_accpet, NULL);
|
|
if (ret != OS_NO_ERR) {
|
|
printf("%s thread fork fail\n", __FILE__);
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
void video_rt_tcp_server_uninit()
|
|
{
|
|
printf("video_rt_tcp_server_uninit\n");
|
|
server_info.flag = 1;
|
|
sock_set_quit(server_info.fd);
|
|
/*sock_unreg(server_info.fd);*/
|
|
}
|
|
|