#include "sys_common.h" #include "system/spinlock.h" #include "os/os_api.h" #include "server/rt_stream_pkg.h" #include "app_config.h" #include "lwip.h" #include "lwip/sockets.h" #include "sock_api/sock_api.h" #include "os/os_api.h" #include "stream_core.h" /* UDP端口:2224 UDP 每片数据包 格式: |1byte 类型 | 1byte 保留 | 2byte payload长度 | 4byte 序号 | 4byte 帧大小 | 4byte 偏移 | 4byte 时间戳 | payload | */ #define UDP_SEND_BUF_SIZE (5*1472) #define MAX_PAYLOAD (1472-sizeof(struct frm_head))//最后4字节属于h264流的 static u32 video_timestramp = 0; static u32 audio_timestramp = 0; static u32 seq = 1; static u32 aux_frame_cnt = 0; static u32 old_times = 0; static u32 new_times = 0; static struct rt_stream_info *rt_info = NULL; extern int atoi(const char *__nptr); 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, "udp://"); if (!tmp) { return -1; } tmp += strlen("udp://"); 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 net_rt_pkg_udp_callback(enum sock_api_msg_type type, void *p) { //缓存大于2帧丢帧 struct rt_stream_info *info = (struct rt_stream_info *)p; 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 (info) { info->cb_flag = 1; } return -1; } return 0; } static void *get_sock_handler(int (*cb_func)(enum sock_api_msg_type type, void *priv), void *priv) { void *fd = NULL; if (0) { //条件链表 //add P2P code } else { fd = sock_reg(AF_INET, SOCK_DGRAM, 0, cb_func, priv); if (fd == NULL) { printf("%s %d->Error in socket()\n", __func__, __LINE__); return NULL; } u32 millsec = 100; sock_setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&millsec, sizeof(millsec)); return fd; } } struct rt_stream_info *net_rt_vpkg_open(const char *path, const char *mode) { int flags = 0; int err; struct rt_stream_info *info = (struct rt_stream_info *)calloc(1, sizeof(struct rt_stream_info)); if (info == NULL) { printf("%s %d->Error in malloc()\n", __func__, __LINE__); return NULL; } info->udp_send_buf = (char *)malloc(UDP_SEND_BUF_SIZE); if (info->udp_send_buf == NULL) { printf("%s %d->Error in malloc()\n", __func__, __LINE__); free(info); return NULL; } if (path_analyze(info, path)) { printf("%s %d->Error in path_analyze\n", __func__, __LINE__); free(info); return NULL; } info->fd = get_sock_handler(net_rt_pkg_udp_callback, info); if (!info->fd) { printf("%s %d->Error get_sock_handler\n", __func__, __LINE__); free(info); return NULL; } rt_info = info; return info; err1: free(info->udp_send_buf); free(info); return NULL; } int net_rt_vpkg_write(struct rt_stream_info *info, char *buffer, size_t len, struct sockaddr *addr, int addrlen) { /* struct sockaddr_in * addr2 = (struct sockaddr_in *)addr; */ return sock_sendto(info->fd, buffer, len, 0, addr, addrlen); } int net_rt_vpkg_close(struct rt_stream_info *info) { video_timestramp = 0; audio_timestramp = 0; aux_frame_cnt = 0; //os_sem_del(&mutex,OS_DEL_ALWAYS); if (info->fd) { sock_unreg(info->fd); } if (info->udp_send_buf) { free(info->udp_send_buf); } free(info); rt_info = NULL; return 0; } int UDP_client_socket_unreg(int addr) { if (rt_info) { printf("UDP_client_socket_quit , addr 0x%x , 0x%x\n", rt_info->addr.sin_addr.s_addr, addr); if (rt_info->addr.sin_addr.s_addr == addr) { video_timestramp = 0; audio_timestramp = 0; aux_frame_cnt = 0; sock_set_quit(rt_info->fd); sock_unreg(rt_info->fd); rt_info->fd = NULL; rt_info = NULL; return 0; } } return -1; } int net_rt_send_frame(struct rt_stream_info *info, char *buffer, size_t len, u8 type) { u16 payload_len = 0; u32 total_udp_send = 0; struct frm_head frame_head = {0}; u32 change_data = 0x01000000; u32 tmp, tmp2, tmp3; int ret; u32 remain_len = len; if (info == NULL || info->udp_send_buf == NULL || info->fd == NULL) { printf("use net_rt_stream_open_pkg\n"); return -1; } //缓存大于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; } info->cb_flag = 0; frame_head.offset = 0; frame_head.frm_sz = len; frame_head.type &= ~LAST_FREG_MAKER; frame_head.type |= type; /* static u32 last_ms; static u32 freq_num; u32 now_ms; freq_num++; now_ms = timer_get_ms(); if (last_ms && now_ms > last_ms && (now_ms - last_ms) / 1000) { //1000ms last_ms = now_ms - (now_ms - last_ms) % 1000; printf("\n ===== send num : %d =======\n", freq_num); freq_num = 0; } else if (now_ms <= last_ms || !last_ms) { last_ms = now_ms; } */ if (frame_head.type == H264_TYPE_VIDEO || frame_head.type == JPEG_TYPE_VIDEO) { //video_timestramp += 90000 / VIDEO_FRQ_30HZ; new_times = timer_get_ms(); if (aux_frame_cnt < 60) { video_timestramp = 0; } else { video_timestramp += 0;//(new_times - old_times) * 100; } /* printf("p=%d\n",new_times-old_times); */ old_times = new_times; frame_head.timestamp = video_timestramp; } else { audio_timestramp = 501; frame_head.timestamp = audio_timestramp; } frame_head.timestamp = 0; frame_head.seq = seq++; while (remain_len) { if (remain_len < MAX_PAYLOAD) { payload_len = remain_len; frame_head.type |= LAST_FREG_MAKER; } else { payload_len = MAX_PAYLOAD; } frame_head.payload_size = payload_len; memcpy(info->udp_send_buf + total_udp_send, &frame_head, sizeof(struct frm_head)); total_udp_send += sizeof(struct frm_head); memcpy(info->udp_send_buf + total_udp_send, buffer + frame_head.offset, payload_len); if (frame_head.offset == 0 && frame_head.type == H264_TYPE_VIDEO) { if (*((char *)(info->udp_send_buf + total_udp_send + 4)) == 0x67) { //处理PPS帧和SPS帧 I帧 memcpy(&tmp, info->udp_send_buf + total_udp_send, 4); tmp = htonl(tmp); memcpy(info->udp_send_buf + total_udp_send, &change_data, 4); memcpy(&tmp2, info->udp_send_buf + total_udp_send + tmp + 4, 4); tmp2 = htonl(tmp2); memcpy(info->udp_send_buf + total_udp_send + tmp + 4, &change_data, 4); memcpy(info->udp_send_buf + total_udp_send + tmp + tmp2 + 8, &change_data, 4); } else { // 处理P帧 memcpy(info->udp_send_buf + total_udp_send, &change_data, 4); } } total_udp_send += payload_len; if ((total_udp_send == UDP_SEND_BUF_SIZE) || (payload_len < MAX_PAYLOAD)) { if ((ret = net_rt_vpkg_write(info, info->udp_send_buf, total_udp_send, (struct sockaddr *)&info->addr, sizeof(struct sockaddr_in))) != total_udp_send) { if (info->cb_flag) { return len; } /* printf("ret:%d total_udp_send:%d\n", ret, total_udp_send); */ puts("rt_stream_sent error!\n"); return -1; } total_udp_send = 0; } remain_len -= payload_len; frame_head.offset += payload_len; } return len; } REGISTER_NET_VIDEO_STREAM_SUDDEV(udp_video_stream_sub) = { .name = "udp", .open = net_rt_vpkg_open, .write = net_rt_send_frame, .close = net_rt_vpkg_close, };