/*************************************************************************************** * * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. * * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved. * * Redistribution and use in binary forms, with or without modification, are permitted. * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************************/ #include "sys_inc.h" #include "word_analyse.h" #include "hsip.h" #include "sua.h" #include "sip_parse.h" /******************************************************************/ extern HSIP_CLASS hsip; extern HSIP_USER g_user; /******************************************************************/ static RTPMAPE default_rtp_map[96]; /******************************************************************/ void sua_rtp_map_entry_set(RTPMAPE * p_map, int index, const char * name, int channel, int hz, int mtype, int sdp_index) { p_map[index].pt = (uint8)index; strncpy(p_map[index].name, name, sizeof(p_map[index].name) - 1); p_map[index].channel = channel; p_map[index].hz = hz; p_map[index].mtype = mtype; p_map[index].sdp_index = sdp_index; } void sua_default_rtp_map_init() { memset(default_rtp_map, 0, sizeof(default_rtp_map)); // 音频缺省定义 sua_rtp_map_entry_set(default_rtp_map, 0, "PCMU", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 3, "GSM", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 4, "G723", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 5, "DVI4", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 6, "DVI4", 1, 16000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 7, "LPC", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 8, "PCMA", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 9, "G722", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 10, "L16", 2, 44100, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 11, "L16", 1, 44100, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 12, "QCELP", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 13, "CN", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 14, "MPA", 1, 90000, SDP_MEDIA_AUDIO, -1); // The RTP timestamp clock rate is always 90, 000, independent of the sampling rate sua_rtp_map_entry_set(default_rtp_map, 15, "G728", 1, 8000, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 16, "DVI4", 1, 11025, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 17, "DVI4", 1, 22050, SDP_MEDIA_AUDIO, -1); sua_rtp_map_entry_set(default_rtp_map, 18, "G729", 1, 8000, SDP_MEDIA_AUDIO, -1); // 视频缺省定义 sua_rtp_map_entry_set(default_rtp_map, 25, "CelB", 1, 90000, SDP_MEDIA_VIDEO, -1); sua_rtp_map_entry_set(default_rtp_map, 26, "JPEG", 1, 90000, SDP_MEDIA_VIDEO, -1); sua_rtp_map_entry_set(default_rtp_map, 28, "nv", 1, 90000, SDP_MEDIA_VIDEO, -1); sua_rtp_map_entry_set(default_rtp_map, 31, "H261", 1, 90000, SDP_MEDIA_VIDEO, -1); sua_rtp_map_entry_set(default_rtp_map, 32, "MPV", 1, 90000, SDP_MEDIA_VIDEO, -1); sua_rtp_map_entry_set(default_rtp_map, 33, "MP2T", 1, 90000, SDP_MEDIA_VIDEO, -1); sua_rtp_map_entry_set(default_rtp_map, 34, "H263", 1, 90000, SDP_MEDIA_VIDEO, -1); } void sua_r_rtp_map_init(SUA * p_sua) { // 复制缺省的rtp payload type定义,动态类型在sdp解析时填写 memset(p_sua->r_rtp_map, 0, sizeof(p_sua->r_rtp_map)); memcpy(p_sua->r_rtp_map, default_rtp_map, sizeof(default_rtp_map)); } void sua_r_map_update(SUA * p_sua) { int i; for (i = 0; i < p_sua->r_a_cap_cnt; i++) { SDPINFO * p_sdp = &(p_sua->r_a_sdp[i]); p_sua->r_rtp_map[p_sdp->pt].mtype = SDP_MEDIA_AUDIO; p_sua->r_rtp_map[p_sdp->pt].sdp_index = i; p_sua->r_rtp_map[p_sdp->pt].hz = p_sdp->hz; strncpy(p_sua->r_rtp_map[p_sdp->pt].name, p_sdp->encoder, sizeof(p_sua->r_rtp_map[p_sdp->pt].name) - 1); p_sua->r_rtp_map[p_sdp->pt].pt = p_sdp->pt; p_sua->r_rtp_map[p_sdp->pt].channel = p_sdp->chn; } for (i = 0; i < p_sua->r_v_cap_cnt; i++) { SDPINFO * p_sdp = &(p_sua->r_v_sdp[i]); p_sua->r_rtp_map[p_sdp->pt].mtype = SDP_MEDIA_VIDEO; p_sua->r_rtp_map[p_sdp->pt].sdp_index = i; p_sua->r_rtp_map[p_sdp->pt].hz = p_sdp->hz; strncpy(p_sua->r_rtp_map[p_sdp->pt].name, p_sdp->encoder, sizeof(p_sua->r_rtp_map[p_sdp->pt].name) - 1); p_sua->r_rtp_map[p_sdp->pt].pt = p_sdp->pt; p_sua->r_rtp_map[p_sdp->pt].channel = p_sdp->chn; } } BOOL sua_build_sdp_msg(SUA * p_sua, HSIP_MSG * tx_msg) { char tmp_buf[128]; int offset; int index; if (tx_msg == NULL) { return FALSE; } sip_add_tx_msg_sdp_line(tx_msg, "v", "0"); sip_add_tx_msg_sdp_line(tx_msg, "o", "%s 0 0 IN IP4 %s", p_sua->sua_deviceid, p_sua->sua_ipstr); if (p_sua->s_name[0] == '\0') { sip_add_tx_msg_sdp_line(tx_msg, "s", "Play"); } else { sip_add_tx_msg_sdp_line(tx_msg, "s", p_sua->s_name); } if (p_sua->uaf_multicast == 1) { struct in_addr in; in.s_addr = p_sua->multicast_addr; sip_add_tx_msg_sdp_line(tx_msg, "c", "IN IP4 %s", inet_ntoa(in)); } else { sip_add_tx_msg_sdp_line(tx_msg, "c", "IN IP4 %s", p_sua->sua_ipstr); } // if(stricmp(p_sua->s_name, "Playback") == 0 || stricmp(p_sua->s_name, "Download") == 0) if (p_sua->u_name[0] != '\0') { // SDP 带有u=xxxx,海康平台发送ACK之后会立即发送BYE消息断开连接 // sip_add_tx_msg_sdp_line(tx_msg, "u", "%s", p_sua->u_name); sip_add_tx_msg_sdp_line(tx_msg, "t", "%u %u", (uint32)p_sua->st, (uint32)p_sua->et); } else { sip_add_tx_msg_sdp_line(tx_msg, "t", "0 0"); } if (p_sua->uaf_rtp_mux == 1) { if (p_sua->l_mux_id == 0) { p_sua->l_mux_id = 4321; // rand() | sys_os_get_ms(); } if (p_sua->mux_lport == 0) { p_sua->mux_lport = 10010; // p_sua->audio_rtp_media.local_port; } sip_add_tx_msg_sdp_line(tx_msg, "a", "rtpport-mux"); sip_add_tx_msg_sdp_line(tx_msg, "a", "muxid:%u", p_sua->l_mux_id); } if ((p_sua->uaf_uac == 1 && p_sua->l_a_cap_cnt > 0) || // 主叫 (p_sua->l_a_cap_cnt > 0 && p_sua->r_a_cap_cnt > 0)) // 被叫 { offset = 0; for (index = 0; indexl_a_cap_cnt; index++) { offset += sprintf(tmp_buf + offset, "%u ", p_sua->l_a_cap[index]); } if (offset > 0) { tmp_buf[offset - 1] = '\0'; // 去掉后面的空格 } if (p_sua->uaf_a_tcp_rtp == 1) { sip_add_tx_msg_sdp_line(tx_msg, "m", "audio %u TCP/RTP/AVP %s", p_sua->audio_rtp_media.local_port, tmp_buf); if (p_sua->s_a_mode) // 对端主动模式 { sip_add_tx_msg_sdp_line(tx_msg, "a", "setup:passive"); } else { sip_add_tx_msg_sdp_line(tx_msg, "a", "setup:active"); } sip_add_tx_msg_sdp_line(tx_msg, "a", "connection:new"); } else { if (p_sua->uaf_rtp_mux == 1) { sip_add_tx_msg_sdp_line(tx_msg, "m", "audio %u RTP/AVP %s", p_sua->mux_lport, tmp_buf); } else { if (p_sua->uaf_uas == 1 && p_sua->uaf_multicast == 1) { sip_add_tx_msg_sdp_line(tx_msg, "m", "audio %u RTP/AVP %s", p_sua->audio_rtp_media.remote_port, tmp_buf); } else { sip_add_tx_msg_sdp_line(tx_msg, "m", "audio %u RTP/AVP %s", p_sua->audio_rtp_media.local_port, tmp_buf); } } } int sendrecv = -1; for (index = 0; indexl_a_cap_cnt; index++) { SDPINFO * p_sdp = &(p_sua->l_a_sdp[index]); if (p_sdp->is_valid) { if (p_sdp->chn > 1) { sip_add_tx_msg_sdp_line(tx_msg, "a", "rtpmap:%u %s/%d/%d", p_sdp->pt, p_sdp->encoder, p_sdp->hz, p_sdp->chn); } else { sip_add_tx_msg_sdp_line(tx_msg, "a", "rtpmap:%u %s/%d", p_sdp->pt, p_sdp->encoder, p_sdp->hz); } if (p_sdp->desc[0] != '\0') { sip_add_tx_msg_sdp_line(tx_msg, "", "%s", p_sdp->desc); } if (p_sdp->ptime > 0) { sip_add_tx_msg_sdp_line(tx_msg, "a", "ptime:%u", p_sdp->ptime); } if (p_sdp->bps > 0) { sip_add_tx_msg_sdp_line(tx_msg, "b", "TIAS:%u", p_sdp->bps); } if (sendrecv < 0) { sendrecv = p_sdp->sendrecv; } } } if (sendrecv == SDP_SENDRECV_TXONLY) { sip_add_tx_msg_sdp_line(tx_msg, "a", "sendonly"); } else if (sendrecv == SDP_SENDRECV_RXONLY) { sip_add_tx_msg_sdp_line(tx_msg, "a", "recvonly"); } else { } } if ((p_sua->uaf_uac == 1 && p_sua->l_v_cap_cnt > 0) || // 主叫 (p_sua->l_v_cap_cnt > 0 && p_sua->r_v_cap_cnt > 0)) // 被叫 { offset = 0; for (index = 0; indexl_v_cap_cnt; index++) { offset += sprintf(tmp_buf + offset, "%u ", p_sua->l_v_cap[index]); } if (offset > 0) { tmp_buf[offset - 1] = '\0'; // 去掉后面的空格 } if (p_sua->uaf_v_tcp_rtp == 1) { sip_add_tx_msg_sdp_line(tx_msg, "m", "video %u TCP/RTP/AVP %s", p_sua->video_rtp_media.local_port, tmp_buf); if (p_sua->s_v_mode) // 对端主动模式 { sip_add_tx_msg_sdp_line(tx_msg, "a", "setup:passive"); } else { sip_add_tx_msg_sdp_line(tx_msg, "a", "setup:active"); } sip_add_tx_msg_sdp_line(tx_msg, "a", "connection:new"); } else { if (p_sua->uaf_rtp_mux == 1) { sip_add_tx_msg_sdp_line(tx_msg, "m", "video %u RTP/AVP %s", p_sua->mux_lport, tmp_buf); } else { if (p_sua->uaf_uas == 1 && p_sua->uaf_multicast == 1) { sip_add_tx_msg_sdp_line(tx_msg, "m", "video %u RTP/AVP %s", p_sua->video_rtp_media.remote_port, tmp_buf); } else { sip_add_tx_msg_sdp_line(tx_msg, "m", "video %u RTP/AVP %s", p_sua->video_rtp_media.local_port, tmp_buf); } } } int sendrecv = -1; for (index = 0; indexl_v_cap_cnt; index++) { SDPINFO * p_sdp = &(p_sua->l_v_sdp[index]); if (p_sdp->is_valid) { sip_add_tx_msg_sdp_line(tx_msg, "a", "rtpmap:%u %s/%d", p_sdp->pt, p_sdp->encoder, p_sdp->hz); if (p_sdp->desc[0] != '\0') { sip_add_tx_msg_sdp_line(tx_msg, "", "%s", p_sdp->desc); } if (p_sdp->ptime > 0) { sip_add_tx_msg_sdp_line(tx_msg, "a", "ptime:%u", p_sdp->ptime); } if (p_sdp->bps > 0) { sip_add_tx_msg_sdp_line(tx_msg, "b", "TIAS:%u", p_sdp->bps); } if (sendrecv < 0) { sendrecv = p_sdp->sendrecv; } } } if (sendrecv == SDP_SENDRECV_TXONLY) { sip_add_tx_msg_sdp_line(tx_msg, "a", "sendonly"); } else if (sendrecv == SDP_SENDRECV_RXONLY) { sip_add_tx_msg_sdp_line(tx_msg, "a", "recvonly"); } else { } } if (p_sua->y_name[0] != '\0') { sip_add_tx_msg_sdp_line(tx_msg, "y", "%s", p_sua->y_name); } return TRUE; } int sua_calc_sdp_length(HSIP_MSG * tx_msg) { if (tx_msg == NULL) { return 0; } int offset = 0; // 填写SDP消息内容 HDRV * pHdrV = (HDRV *)pps_lookup_start(&(tx_msg->sdp_ctx)); while (pHdrV != NULL) { if (pHdrV->header[0] != '\0') { offset += strlen(pHdrV->header) + strlen(pHdrV->value_string) + 3; } else { offset += strlen(pHdrV->value_string) + 2; } pHdrV = (HDRV *)pps_lookup_next(&(tx_msg->sdp_ctx), pHdrV); } pps_lookup_end(&(tx_msg->sdp_ctx)); return offset; } /******************************************************************\ 从消息获取对端媒体信息,写入SUA中 \******************************************************************/ BOOL sua_get_msg_media_info(SUA * p_sua, HSIP_MSG * rx_msg) { if (rx_msg == NULL || p_sua == NULL) { return FALSE; } if (sip_msg_with_sdp(rx_msg) == FALSE) // 判断是否消息带SDP { return FALSE; } sip_get_sdp_session_name(rx_msg, p_sua->s_name, sizeof(p_sua->s_name)); // 记录媒体信息 if (sip_get_remote_media_ip(rx_msg, &p_sua->remote_media_ip) == FALSE) { return FALSE; } // 组播地址 if (ntohl(p_sua->remote_media_ip) > ntohl(inet_addr("224.0.0.0")) && ntohl(p_sua->remote_media_ip) < ntohl(inet_addr("239.255.255.255"))) { p_sua->uaf_multicast = 1; p_sua->multicast_addr = p_sua->remote_media_ip; } else { p_sua->uaf_multicast = 0; } // UDP端口复用信息 if (sip_get_remote_rtp_mux_info(rx_msg, &p_sua->r_mux_id)) { p_sua->uaf_rtp_mux = 1; } else { p_sua->uaf_rtp_mux = 0; } int i = 0; int is_tcp = 0; uint32 ipv4 = 0; while (1) { BOOL ret; int r_a_cap_cnt; uint8 r_a_cap[MAX_AVN]; SDPINFO r_a_sdp[MAX_AVN]; memset(&r_a_sdp, 0, sizeof(SDPINFO) * MAX_AVN); ret = sip_get_remote_cap(rx_msg, i, "audio", &r_a_cap_cnt, r_a_cap, &(p_sua->audio_rtp_media.remote_port), &is_tcp); if (!ret) { break; } ret = sip_sdp_media_desc_parse(rx_msg, i, "audio", r_a_cap_cnt, r_a_cap, &r_a_sdp[0], &ipv4); if (!ret) { break; } p_sua->audio_rtp_media.conn_addr = ipv4; for (int j = 0; j < r_a_cap_cnt; j++) { sua_add_remote_sdp(p_sua, &r_a_sdp[j]); } i++; } if (ipv4) { // 组播地址判断 if (ntohl(ipv4) > ntohl(inet_addr("224.0.0.0")) && ntohl(ipv4) < ntohl(inet_addr("239.255.255.255"))) { p_sua->uaf_multicast = 1; p_sua->multicast_addr = ipv4; } else { p_sua->uaf_multicast = 0; } } p_sua->uaf_a_tcp_rtp = is_tcp; if (is_tcp) { sip_get_sdp_setup_mode(rx_msg, "audio", &p_sua->s_a_mode); } i = 0; is_tcp = 0; ipv4 = 0; while (1) { BOOL ret; int r_v_cap_cnt; uint8 r_v_cap[MAX_AVN]; SDPINFO r_v_sdp[MAX_AVN]; memset(&r_v_sdp, 0, sizeof(SDPINFO) * MAX_AVN); ret = sip_get_remote_cap(rx_msg, i, "video", &r_v_cap_cnt, r_v_cap, &(p_sua->video_rtp_media.remote_port), &is_tcp); if (!ret) { break; } ret = sip_sdp_media_desc_parse(rx_msg, i, "video", r_v_cap_cnt, r_v_cap, &r_v_sdp[0], &ipv4); if (!ret) { break; } p_sua->video_rtp_media.conn_addr = ipv4; for (int j = 0; j < r_v_cap_cnt; j++) { sua_add_remote_sdp(p_sua, &r_v_sdp[j]); } i++; } if (ipv4) { // 组播地址判断 if (ntohl(ipv4) > ntohl(inet_addr("224.0.0.0")) && ntohl(ipv4) < ntohl(inet_addr("239.255.255.255"))) { p_sua->uaf_multicast = 1; p_sua->multicast_addr = ipv4; } else { p_sua->uaf_multicast = 0; } } p_sua->uaf_v_tcp_rtp = is_tcp; if (is_tcp) { sip_get_sdp_setup_mode(rx_msg, "video", &p_sua->s_v_mode); } // 处理组播媒体方向,被叫方向必须等于主叫的方向,主叫收到应该判断是否与其相等 // Similarly, the directionality information in the answer(sendonly, recvonly, or sendrecv) MUST equal that of the offer. if (p_sua->uaf_multicast == 1 && p_sua->uaf_uas == 1) { if (p_sua->r_v_cap_cnt > 0) { for (i = 0; il_v_cap_cnt; i++) p_sua->l_v_sdp[i].sendrecv = p_sua->r_v_sdp[0].sendrecv; } if (p_sua->r_a_cap_cnt > 0) { for (i = 0; il_a_cap_cnt; i++) p_sua->l_a_sdp[i].sendrecv = p_sua->r_a_sdp[0].sendrecv; } } // 复制解析的动态类型到相应的RTP映射单元 for (i = 0; i < p_sua->r_v_cap_cnt; i++) { uint8 pt = p_sua->r_v_cap[i]; if (pt < 96 && p_sua->r_v_sdp[i].encoder[0] == '\0') { // 对方没有填写固定pt的描述,取缺省描述 if (default_rtp_map[pt].pt == pt && default_rtp_map[pt].name[0]) { strcpy(p_sua->r_v_sdp[i].encoder, default_rtp_map[pt].name); p_sua->r_v_sdp[i].hz = default_rtp_map[pt].hz; p_sua->r_v_sdp[i].chn = default_rtp_map[pt].channel; } } } for (i = 0; i < p_sua->r_a_cap_cnt; i++) { uint8 pt = p_sua->r_a_cap[i]; if (pt < 96 && p_sua->r_a_sdp[i].encoder[0] == '\0') { // 对方没有填写固定pt的描述,取缺省描述 if (default_rtp_map[pt].pt == pt && default_rtp_map[pt].name[0]) { strcpy(p_sua->r_a_sdp[i].encoder, default_rtp_map[pt].name); p_sua->r_a_sdp[i].hz = default_rtp_map[pt].hz; p_sua->r_a_sdp[i].chn = default_rtp_map[pt].channel; } } } sip_get_sdp_uname(rx_msg, p_sua->u_name, sizeof(p_sua->u_name)); uint32 st, et; if (sip_get_sdp_ttime(rx_msg, &st, &et)) { p_sua->st = st; p_sua->et = et; } if (sip_get_sdp_yname(rx_msg, p_sua->y_name, sizeof(p_sua->y_name))) { if (strlen(p_sua->y_name) > 0) { p_sua->v_rtp_info.rtp_ssrc = p_sua->a_rtp_info.rtp_ssrc = atoi(p_sua->y_name); } } return TRUE; } /******************************************************************\ 设置本身能力集 \******************************************************************/ void sua_clear_self_sdp(SUA * p_sua, const char * cap_name) { if (strcasecmp(cap_name, "audio") == 0) { p_sua->l_a_cap_cnt = 0; memset(p_sua->l_a_sdp, 0, sizeof(p_sua->l_a_sdp)); } else if (strcasecmp(cap_name, "video") == 0) { p_sua->l_v_cap_cnt = 0; memset(p_sua->l_v_sdp, 0, sizeof(p_sua->l_v_sdp)); } else { } } int sua_add_self_sdp(SUA * p_sua, SDPINFO * p_sdp) { int index = -1; if (p_sua == NULL || p_sdp == NULL) { return index; } if (p_sdp->mtype == SDP_MEDIA_AUDIO) { int i; // 查找重复的能力描述 for (i = 0; i < p_sua->l_a_cap_cnt; i++) { if (strcasecmp(p_sdp->encoder, p_sua->l_a_sdp[i].encoder) == 0) { return i; } } // 添加到数组中 if (p_sua->l_a_cap_cnt < MAX_AVN) { index = p_sua->l_a_cap_cnt; memcpy(&p_sua->l_a_sdp[index], p_sdp, sizeof(SDPINFO)); p_sua->l_a_sdp[index].is_valid = 1; p_sua->l_a_cap[index] = p_sdp->pt; p_sua->l_a_cap_cnt++; } } else if (p_sdp->mtype == SDP_MEDIA_VIDEO) { int i; // 查找重复的能力描述 for (i = 0; i < p_sua->l_v_cap_cnt; i++) { if (strcasecmp(p_sdp->encoder, p_sua->l_v_sdp[i].encoder) == 0) { return i; } } // 添加到数组中 if (p_sua->l_v_cap_cnt < MAX_AVN) { index = p_sua->l_v_cap_cnt; memcpy(&p_sua->l_v_sdp[index], p_sdp, sizeof(SDPINFO)); p_sua->l_v_sdp[index].is_valid = 1; p_sua->l_v_cap[index] = p_sdp->pt; p_sua->l_v_cap_cnt++; } } return index; } int sua_add_remote_sdp(SUA * p_sua, SDPINFO * p_sdp) { int index = -1; if (p_sua == NULL || p_sdp == NULL) { return index; } if (p_sdp->mtype == SDP_MEDIA_AUDIO) { int i; // 查找重复的能力描述 for (i = 0; i < p_sua->r_a_cap_cnt; i++) { if (strcasecmp(p_sdp->encoder, p_sua->r_a_sdp[i].encoder) == 0) { p_sua->r_a_sdp[i].sendrecv |= p_sdp->sendrecv; return i; } } // 添加到数组中 if (p_sua->r_a_cap_cnt < MAX_AVN) { index = p_sua->r_a_cap_cnt; memcpy(&p_sua->r_a_sdp[index], p_sdp, sizeof(SDPINFO)); p_sua->r_a_sdp[index].is_valid = 1; p_sua->r_a_cap[index] = p_sdp->pt; p_sua->r_a_cap_cnt++; } } else if (p_sdp->mtype == SDP_MEDIA_VIDEO) { int i; // 查找重复的能力描述 for (i = 0; i < p_sua->r_v_cap_cnt; i++) { if (strcasecmp(p_sdp->encoder, p_sua->r_v_sdp[i].encoder) == 0) { p_sua->r_v_sdp[i].sendrecv |= p_sdp->sendrecv; return i; } } // 添加到数组中 if (p_sua->r_v_cap_cnt < MAX_AVN) { index = p_sua->r_v_cap_cnt; memcpy(&p_sua->r_v_sdp[index], p_sdp, sizeof(SDPINFO)); p_sua->r_v_sdp[index].is_valid = 1; p_sua->r_v_cap[index] = p_sdp->pt; p_sua->r_v_cap_cnt++; } } return index; } /******************************************************************\ 获取本身音频/视频能力集,index为索引号 \******************************************************************/ int sua_get_video_sdp_cnt(SUA * p_sua, int lr) { if (p_sua == NULL) { return -1; } if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE) { log_print(HT_LOG_ERR, "%s, param p_sua[%p] err!!!\r\n", __FUNCTION__, p_sua); return -1; } if (lr == 0) { return p_sua->l_v_cap_cnt; } else { return p_sua->r_v_cap_cnt; } } int sua_get_video_sdp(SUA * p_sua, int lr, int index, SDPINFO * p_sdp) { if (p_sua == NULL || p_sdp == NULL || index < 0) { return -1; } if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE) { log_print(HT_LOG_ERR, "%s, param p_sua[%p] err!!!\r\n", __FUNCTION__, p_sua); return -1; } if (lr == 0) { if (index >= p_sua->l_v_cap_cnt) { return -1; } memcpy(p_sdp, &p_sua->l_v_sdp[index], sizeof(SDPINFO)); return 0; } else { if (index >= p_sua->r_v_cap_cnt) { return -1; } memcpy(p_sdp, &p_sua->r_v_sdp[index], sizeof(SDPINFO)); return 0; } } int sua_get_audio_sdp_cnt(SUA * p_sua, int lr) { if (p_sua == NULL) { return -1; } if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE) { log_print(HT_LOG_ERR, "%s, param p_sua[%p] err!!!\r\n", __FUNCTION__, p_sua); return -1; } if (lr == 0) { return p_sua->l_a_cap_cnt; } else { return p_sua->r_a_cap_cnt; } } int sua_get_audio_sdp(SUA * p_sua, int lr, int index, SDPINFO * p_sdp) { if (p_sua == NULL || p_sdp == NULL || index < 0) { return -1; } if (pps_safe_node(hsip.sua_fl, p_sua) == FALSE) { log_print(HT_LOG_ERR, "%s, param p_sua[%p] err!!!\r\n", __FUNCTION__, p_sua); return -1; } if (lr == 0) { if (index >= p_sua->l_a_cap_cnt) { return -1; } memcpy(p_sdp, &p_sua->l_a_sdp[index], sizeof(SDPINFO)); return 0; } else { if (index >= p_sua->r_a_cap_cnt) { return -1; } memcpy(p_sdp, &p_sua->r_a_sdp[index], sizeof(SDPINFO)); return 0; } } /******************************************************************\ 获取编码名称对应的rtp类型,例如:H264 --> 96;PCMA --> 8 \******************************************************************/ SDPINFO * sua_get_sdp_by_codec(SUA * p_sua, const char * codec_name) { int i; SDPINFO * p_sdp = NULL; for (i = 0; i < p_sua->l_a_cap_cnt; i++) { if (strcasecmp(p_sua->l_a_sdp[i].encoder, codec_name) == 0) { p_sdp = &p_sua->l_a_sdp[i]; return p_sdp; } } for (i = 0; i < p_sua->l_v_cap_cnt; i++) { if (strcasecmp(p_sua->l_v_sdp[i].encoder, codec_name) == 0) { p_sdp = &p_sua->l_v_sdp[i]; return p_sdp; } } return NULL; } uint8 sua_get_rtp_pt(SUA * p_sua, const char * codec_name) { SDPINFO * p_sdp = sua_get_sdp_by_codec(p_sua, codec_name); if (p_sdp) { return p_sdp->pt; } else { return 255; } } SDPINFO * sua_get_l_sdp_by_pt(SUA * p_sua, const uint8 rtp_pt) { int i; SDPINFO * p_sdp = NULL; for (i = 0; i < p_sua->l_a_cap_cnt; i++) { if (p_sua->l_a_sdp[i].pt == rtp_pt) { p_sdp = &p_sua->l_a_sdp[i]; return p_sdp; } } for (i = 0; i < p_sua->l_v_cap_cnt; i++) { if (p_sua->l_v_sdp[i].pt == rtp_pt) { p_sdp = &p_sua->l_v_sdp[i]; return p_sdp; } } return NULL; } SDPINFO * sua_get_r_sdp_by_pt(SUA * p_sua, const uint8 rtp_pt) { int i; SDPINFO * p_sdp = NULL; for (i = 0; i < p_sua->r_a_cap_cnt; i++) { if (p_sua->r_a_sdp[i].pt == rtp_pt) { p_sdp = &p_sua->r_a_sdp[i]; return p_sdp; } } for (i = 0; i < p_sua->r_v_cap_cnt; i++) { if (p_sua->r_v_sdp[i].pt == rtp_pt) { p_sdp = &p_sua->r_v_sdp[i]; return p_sdp; } } return NULL; } int sua_call_in_sdp_parse(SUA * p_sua, HSIP_MSG * rx_msg) { memset(p_sua->r_a_sdp, 0, sizeof(SDPINFO) * MAX_AVN); memset(p_sua->r_v_sdp, 0, sizeof(SDPINFO) * MAX_AVN); if (sua_get_msg_media_info(p_sua, rx_msg) == FALSE) { return -1; } sua_r_map_update(p_sua); int i; for (i = 0; ir_a_sdp[i].is_valid == 1) { log_print(HT_LOG_INFO, "%s, audio{encoder[%s], hz[%d], chn[%d]}\r\n", __FUNCTION__, p_sua->r_a_sdp[i].encoder, p_sua->r_a_sdp[i].hz, p_sua->r_a_sdp[i].chn); } } for (i = 0; ir_v_sdp[i].is_valid == 1) { log_print(HT_LOG_INFO, "%s, video{encoder[%s], hz[%d], chn[%d]}\r\n", __FUNCTION__, p_sua->r_v_sdp[i].encoder, p_sua->r_v_sdp[i].hz, p_sua->r_v_sdp[i].chn); } } return 0; } /******************************************************************\ 判断相同的音频和视频能力,返回相同能力的总数 \******************************************************************/ int sua_check_same_cap(SUA * p_sua) { int i, j, v_cnt, a_cnt; v_cnt = 0; for (i = 0; i < p_sua->l_v_cap_cnt; i++) { for (j = 0; j < p_sua->r_v_cap_cnt; j++) { if (strcasecmp(p_sua->l_v_sdp[i].encoder, p_sua->r_v_sdp[j].encoder) == 0) { p_sua->same_video_cap[v_cnt] = p_sua->l_v_cap[i]; v_cnt++; break; } } } p_sua->same_video_cap_count = v_cnt; a_cnt = 0; for (i = 0; i < p_sua->l_a_cap_cnt; i++) { for (j = 0; j < p_sua->r_a_cap_cnt; j++) { if (strcasecmp(p_sua->l_a_sdp[i].encoder, p_sua->r_a_sdp[j].encoder) == 0) { p_sua->same_audio_cap[v_cnt] = p_sua->l_a_cap[i]; a_cnt++; break; } } } p_sua->same_audio_cap_count = a_cnt; return (v_cnt + a_cnt); } int sua_adjust_l_sdp_set(SUA * p_sua) { int i, j, match = 0; for (i = 0; i < p_sua->l_v_cap_cnt; i++) { match = 0; for (j = 0; j < p_sua->r_v_cap_cnt; j++) { if (strcasecmp(p_sua->l_v_sdp[i].encoder, p_sua->r_v_sdp[j].encoder) == 0) { p_sua->l_v_sdp[i].pt = p_sua->r_v_sdp[j].pt; p_sua->l_v_cap[i] = p_sua->l_v_sdp[i].pt; match = 1; break; } } // 删除没有匹配上的本地能力 if (match == 0) { p_sua->l_v_sdp[i].is_valid = 0; if (p_sua->l_v_cap_cnt > 1) { memmove(&(p_sua->l_v_cap[i]), &(p_sua->l_v_cap[i + 1]), (p_sua->l_v_cap_cnt - 1)*sizeof(uint8)); memmove(&(p_sua->l_v_sdp[i]), &(p_sua->l_v_sdp[i + 1]), (p_sua->l_v_cap_cnt - 1)*sizeof(SDPINFO)); } p_sua->l_v_cap_cnt--; i--; } } for (i = 0; i < p_sua->l_a_cap_cnt; i++) { match = 0; for (j = 0; j < p_sua->r_a_cap_cnt; j++) { if (strcasecmp(p_sua->l_a_sdp[i].encoder, p_sua->r_a_sdp[j].encoder) == 0) { p_sua->l_a_sdp[i].pt = p_sua->r_a_sdp[j].pt; p_sua->l_a_cap[i] = p_sua->l_a_sdp[i].pt; match = 1; break; } } // 删除没有匹配上的本地能力 if (match == 0) { p_sua->l_a_sdp[i].is_valid = 0; if (p_sua->l_a_cap_cnt > 1) { memmove(&(p_sua->l_a_cap[i]), &(p_sua->l_a_cap[i + 1]), (p_sua->l_a_cap_cnt - 1)*sizeof(uint8)); memmove(&(p_sua->l_a_sdp[i]), &(p_sua->l_a_sdp[i + 1]), (p_sua->l_a_cap_cnt - 1)*sizeof(SDPINFO)); } p_sua->l_a_cap_cnt--; i--; } } if (p_sua->l_v_cap_cnt > 0 || p_sua->l_a_cap_cnt > 0) { return 0; } return -1; }