doubao_chat/apps/wifi_camera/wifi/stream/video_rt_tcp2.c

417 lines
9.6 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/spinlock.h"
#include "os/os_api.h"
#include "server/rt_stream_pkg.h"
#include "lwip.h"
#include "server/net2video.h"
#include "os/os_api.h"
#include "sys_common.h"
#include "sock_api/sock_api.h"
#include "stream_core.h"
#include "app_config.h"
#define H264_CLANNEL 10000
#define JPEG_CLANNEL 10001
#define CMD_CLANNEL 10002
extern int atoi(const char *__nptr);
struct cli_info {
struct list_head entry;
void *fd;
struct sockaddr_in addr;
int id;
};
struct video_rt_tcp_server_info {
struct list_head cli_head;
struct sockaddr_in local_addr;
void *fd;
int inited;
int (*callback)(int cmd, char *buffer, int len, void *priv);
OS_SEM sem;
u32 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(u16 port);
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, "cty://");
if (!tmp) {
return -1;
}
tmp += strlen("cty://");
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 void *video_rt_tcp_init(const char *path, const char *mode)
{
int ret = 0;
u16 port = 0;
log_i("video_rt_tcp_init222\n");
struct rt_stream_info *__dump = calloc(1, sizeof(struct rt_stream_info));
if (__dump == NULL) {
log_e("%s malloc fail\n", __FILE__);
return NULL;
}
path_analyze(__dump, path);
struct cli_info *info = get_tcp_net_info(ntohs(__dump->addr.sin_port));
if (info == NULL) {
log_e("%s get_tcp_net_info\n", __FILE__);
free(__dump);
return NULL;
}
memcpy((void *)&__dump->addr, (void *)&info->addr, sizeof(struct sockaddr));
__dump->fd = info->fd;
return (void *)__dump;
}
static int video_rt_tcp_send(void *file, void *buf, u32 len, u8 type)
{
struct rt_stream_info *__dump = (struct rt_stream_info *)file;
int ret = 0;
u32 data_size = len;
if (type == H264_TYPE_VIDEO || type == JPEG_TYPE_VIDEO) {
data_size |= (1 << 31);
} else if (type == PCM_TYPE_AUDIO) {
data_size &= ~(1 << 31);
}
ret = sock_send(__dump->fd, (char *)&data_size, 4, 0);
if (ret <= 0) {
return ret;
}
ret = sock_send(__dump->fd, buf, len, 0);
return ret;
}
static int video_rt_tcp_uninit(void *file)
{
log_i("video_rt_tcp_uninit2222\n\n\n\n\n\n");
int ret = 0;
struct rt_stream_info *__dump = (struct rt_stream_info *)file;
u32 end_frame = 0x12348765;
ret = sock_send(__dump->fd, (char *)&end_frame, 4, 0);
if (ret <= 0) {
return -1;
}
free(__dump);
return 0;
}
REGISTER_NET_VIDEO_STREAM_SUDDEV(tcp2_video_stream_sub) = {
.name = "cty",
.open = video_rt_tcp_init,
.write = video_rt_tcp_send,
.close = video_rt_tcp_uninit,
};
struct cli_info *get_tcp_net_info(u16 port)
{
struct list_head *pos = NULL;
struct cli_info *cli = NULL;
int count = 0;
list_for_each(pos, &server_info.cli_head) {
cli = list_entry(pos, struct cli_info, entry);
if (port == cli->id) {
log_i("get id:%d ip:%s port:%d\n\n", cli->id, inet_ntoa(cli->addr.sin_addr.s_addr), htons(cli->addr.sin_port));
/* sock_clr_quit(cli->fd); */
return cli;
}
}
log_w("not find cli info \n");
return cli;
}
/*
*命令格式
*|len|cmd|data|
*|4byte|4byte|Nbyte|
*cmd:命令号
*len:总长度
*data:数据(主要是给start_app传给启动video4的参数)
* */
static u8 buffer[1024];
static void cmd_cli_task(void *arg)
{
struct list_head *pos = NULL;
struct cli_info *cli = NULL;
int ret = 0;
int len = 0;
int cmd = 0;
int find = 0;
// 查找是否已经存在
list_for_each(pos, &server_info.cli_head) {
cli = list_entry(pos, struct cli_info, entry);
if (CMD_CLANNEL == cli->id) {
find = 1;
break;
}
}
if (!find) {
return;
}
log_d("find it ip:%s port:%d\n\n", inet_ntoa(cli->addr.sin_addr.s_addr), htons(cli->addr.sin_port));
while (1) {
//总长度
ret = sock_recv(cli->fd, (char *)&len, 4, 0);
if (ret != 4) {
log_e("sock_recv fail1\n");
goto exit_;
}
log_i("len=%d\n", len);
//命令号
ret = sock_recv(cli->fd, (char *)&cmd, 4, 0);
if (ret != 4) {
log_e("sock_recv fail2\n");
goto exit_;
}
log_i("cmd=%d\n", cmd);
//数据
//
memset(buffer, 0, sizeof(buffer));
if (len - 4 != 0) {
ret = sock_recv(cli->fd, buffer, len - 4, 0);
if (ret < 0) {
log_e("sock_recv fail4\n");
goto exit_;
}
}
if (server_info.callback) {
ret = server_info.callback(cmd, buffer, len - 4, NULL);
}
if (ret != CMD_NO_ERR) {
log_e("cmd err=%d\n", ret);
}
}
exit_:
log_d("cmd_cli_task exit\n");
}
int cmd_send(struct cmd_ctl *cinfo)
{
struct list_head *pos = NULL;
struct cli_info *cli = NULL;
int ret = 0;
int len = 0;
// 查找是否已经存在
list_for_each(pos, &server_info.cli_head) {
cli = list_entry(pos, struct cli_info, entry);
if (CMD_CLANNEL == cli->id) {
break;
}
}
log_i("send0\n");
ret = sock_send(cli->fd, (char *)cinfo, 8, 0);
if (ret != 8) {
log_e("sock send fail1111\n");
return -1;
}
log_i("send1 len=%d\n", cinfo->len - 4);
if (cinfo->len - 4 != 0) {
ret = sock_send(cli->fd, cinfo->data, cinfo->len - 4, 0);
if (ret != cinfo->len - 4) {
log_e("sock send fail22222 ret=%d\n", ret);
return -1;
}
}
log_i("send2\n");
return 0;
}
static void __do_sock_accpet(void *arg)
{
u32 find = 0;
struct list_head *pos = NULL;
struct cli_info *cli = NULL;
int ret = 0;
u8 task_name[64];
u32 count = 0;
socklen_t len = sizeof(server_info.local_addr);
while (1) {
struct cli_info *__cli = calloc(1, sizeof(sizeof(struct cli_info)));
if (__cli == NULL) {
log_e("malloc fail\n");
while (1);
}
__cli->fd = sock_accept(server_info.fd, (struct sockaddr *)&__cli->addr, &len, NULL, NULL);
if (__cli->fd == NULL) {
log_w("some error in here\n\n");
free(__cli);
continue;
}
if (server_info.flag) {
free(__cli);
break;
}
ret = sock_recv(__cli->fd, (char *)&__cli->id, 4, 0);
if (ret != 4) {
sock_unreg(__cli->fd);
free(__cli->fd);
continue;
}
log_i("__cli->id = %d\n", __cli->id);
list_add_tail(&__cli->entry, &server_info.cli_head);
//命令通道,另开线程处理
if (__cli->id == CMD_CLANNEL) {
sprintf(task_name, "cmd_cli_task%x", count++);
ret = thread_fork(task_name, 28, 0x1000, 0, 0, cmd_cli_task, NULL);
if (ret != OS_NO_ERR) {
log_e("thread_fork fail\n");
continue;
}
}
}
}
int video_rt_tcp_server_init2(int port, int (*callback)(int, char *, int, void *))
{
int ret = 0;
log_i("video_rt_tcp_server_init2\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) {
log_e("%s sock_bind fail\n", __FILE__);
return -1;
}
if (sock_bind(server_info.fd, (struct sockaddr *)&server_info.local_addr, sizeof(struct sockaddr))) {
log_e("%s sock_bind fail\n", __FILE__);
return -1;
}
sock_listen(server_info.fd, 0x5);
INIT_LIST_HEAD(&server_info.cli_head);
server_info.inited = 1;
server_info.callback = callback;
ret = thread_fork("__do_sock_accpet", 28, 0x1000, 0, 0, __do_sock_accpet, NULL);
if (ret != OS_NO_ERR) {
log_e("%s thread fork fail\n", __FILE__);
return -1;
}
return 0;
}
void video_rt_tcp_server_uninit2()
{
printf("video_rt_tcp_server_uninit\n");
server_info.flag = 1;
sock_set_quit(server_info.fd);
sock_unreg(server_info.fd);
server_info.flag = 0;
// 断开所有客户端和删除链表
}
void video_disconnect_all_cli()
{
struct list_head *pos = NULL, *n = NULL;
struct cli_info *cf = NULL;
if (!server_info.inited) {
return;
}
log_d("disconnect all client\n");
list_for_each_safe(pos, n, &server_info.cli_head) {
cf = list_entry(pos, struct cli_info, entry);
list_del(&cf->entry);
if (cf->fd != NULL) {
sock_unreg(cf->fd);
cf->fd = NULL;
}
if (cf != NULL) {
free(cf);
cf = NULL;
}
}
}