1143 lines
26 KiB
C++
1143 lines
26 KiB
C++
/***************************************************************************************
|
||
*
|
||
* 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; index<p_sua->l_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; index<p_sua->l_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; index<p_sua->l_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; index<p_sua->l_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; i<p_sua->l_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; i<p_sua->l_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; i<MAX_AVN; i++)
|
||
{
|
||
if (p_sua->r_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; i<MAX_AVN; i++)
|
||
{
|
||
if (p_sua->r_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;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|