Ticket #433: Failure in media negotiation when SDP contains two audio media lines (thanks Arie Velthoen)
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1639 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
d7828228db
commit
91e567e7b1
|
@ -148,6 +148,11 @@ PJ_BEGIN_DECL
|
|||
* Invalid SDP "rtcp" attribute.
|
||||
*/
|
||||
#define PJMEDIA_SDP_EINRTCP (PJMEDIA_ERRNO_START+35) /* 220035 */
|
||||
/**
|
||||
* @hideinitializer
|
||||
* Invalid SDP media transport protocol.
|
||||
*/
|
||||
#define PJMEDIA_SDP_EINPROTO (PJMEDIA_ERRNO_START+36) /* 220036 */
|
||||
|
||||
|
||||
/************************************************************
|
||||
|
|
|
@ -89,6 +89,7 @@ typedef struct pjmedia_channel pjmedia_channel;
|
|||
struct pjmedia_stream_info
|
||||
{
|
||||
pjmedia_type type; /**< Media type (audio, video) */
|
||||
pjmedia_tp_proto proto; /**< Transport protocol (RTP/AVP, etc.) */
|
||||
pjmedia_dir dir; /**< Media direction. */
|
||||
pj_sockaddr rem_addr; /**< Remote RTP address */
|
||||
pj_sockaddr rem_rtcp; /**< Optional remote RTCP address. If
|
||||
|
|
|
@ -68,6 +68,25 @@ typedef enum pjmedia_type
|
|||
} pjmedia_type;
|
||||
|
||||
|
||||
/**
|
||||
* Media transport protocol.
|
||||
*/
|
||||
typedef enum pjmedia_tp_proto
|
||||
{
|
||||
/** No transport type */
|
||||
PJMEDIA_TP_PROTO_NONE = 0,
|
||||
|
||||
/** RTP using A/V profile */
|
||||
PJMEDIA_TP_PROTO_RTP_AVP,
|
||||
|
||||
/** Secure RTP */
|
||||
PJMEDIA_TP_PROTO_RTP_SAVP,
|
||||
|
||||
/** Unknown */
|
||||
PJMEDIA_TP_PROTO_UNKNOWN
|
||||
|
||||
} pjmedia_tp_proto;
|
||||
|
||||
|
||||
/**
|
||||
* Media direction.
|
||||
|
|
|
@ -58,6 +58,7 @@ static const struct
|
|||
PJ_BUILD_ERR( PJMEDIA_SDP_EINPT, "Invalid SDP payload type in media line" ),
|
||||
PJ_BUILD_ERR( PJMEDIA_SDP_EINFMTP, "Invalid SDP fmtp attribute" ),
|
||||
PJ_BUILD_ERR( PJMEDIA_SDP_EINRTCP, "Invalid SDP rtcp attribyte" ),
|
||||
PJ_BUILD_ERR( PJMEDIA_SDP_EINPROTO, "Invalid SDP media transport protocol" ),
|
||||
|
||||
/* SDP negotiator errors. */
|
||||
PJ_BUILD_ERR( PJMEDIA_SDPNEG_EINSTATE, "Invalid SDP negotiator state for operation" ),
|
||||
|
|
|
@ -53,8 +53,9 @@ static const pj_str_t ID_VIDEO = { "video", 5};
|
|||
static const pj_str_t ID_IN = { "IN", 2 };
|
||||
static const pj_str_t ID_IP4 = { "IP4", 3};
|
||||
static const pj_str_t ID_IP6 = { "IP6", 3};
|
||||
/*static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };*/
|
||||
/*static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };*/
|
||||
static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
|
||||
static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };
|
||||
//static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };
|
||||
static const pj_str_t ID_RTPMAP = { "rtpmap", 6 };
|
||||
static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 };
|
||||
|
||||
|
@ -180,6 +181,8 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
|
|||
return PJMEDIA_EINVALIMEDIATYPE;
|
||||
}
|
||||
|
||||
/* Transport protocol */
|
||||
|
||||
/* Transport type must be equal */
|
||||
if (pj_stricmp(&rem_m->desc.transport,
|
||||
&local_m->desc.transport) != 0)
|
||||
|
@ -188,6 +191,21 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
|
|||
return PJMEDIA_SDPNEG_EINVANSTP;
|
||||
}
|
||||
|
||||
if (pj_stricmp(&local_m->desc.transport, &ID_RTP_AVP) == 0) {
|
||||
|
||||
si->proto = PJMEDIA_TP_PROTO_RTP_AVP;
|
||||
|
||||
} else if (pj_stricmp(&local_m->desc.transport, &ID_RTP_SAVP) == 0) {
|
||||
|
||||
si->proto = PJMEDIA_TP_PROTO_RTP_SAVP;
|
||||
|
||||
} else {
|
||||
|
||||
si->proto = PJMEDIA_TP_PROTO_UNKNOWN;
|
||||
return PJMEDIA_SDP_EINPROTO;
|
||||
}
|
||||
|
||||
|
||||
/* Check address family in remote SDP */
|
||||
rem_af = pj_AF_UNSPEC();
|
||||
if (pj_stricmp(&rem_conn->net_type, &ID_IN)==0) {
|
||||
|
|
|
@ -884,9 +884,11 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
|
|||
const pjmedia_sdp_session *local_sdp,
|
||||
const pjmedia_sdp_session *remote_sdp)
|
||||
{
|
||||
unsigned i;
|
||||
int prev_media_st = 0;
|
||||
pjsua_call *call = &pjsua_var.calls[call_id];
|
||||
pjmedia_session_info sess_info;
|
||||
pjmedia_stream_info *si = NULL;
|
||||
pjmedia_port *media_port;
|
||||
pj_str_t port_name;
|
||||
char tmp[PJSIP_MAX_URL_SIZE];
|
||||
|
@ -897,19 +899,37 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
|
|||
stop_media_session(call->index);
|
||||
|
||||
/* Create media session info based on SDP parameters.
|
||||
* We only support one stream per session at the moment
|
||||
*/
|
||||
status = pjmedia_session_info_from_sdp( call->inv->dlg->pool,
|
||||
pjsua_var.med_endpt,
|
||||
1,&sess_info,
|
||||
PJMEDIA_MAX_SDP_MEDIA, &sess_info,
|
||||
local_sdp, remote_sdp);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* Find which session is audio (we only support audio for now) */
|
||||
for (i=0; i < sess_info.stream_cnt; ++i) {
|
||||
if (sess_info.stream_info[i].type == PJMEDIA_TYPE_AUDIO &&
|
||||
sess_info.stream_info[i].proto == PJMEDIA_TP_PROTO_RTP_AVP)
|
||||
{
|
||||
si = &sess_info.stream_info[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (si == NULL) {
|
||||
/* Not found */
|
||||
return PJMEDIA_EINVALIMEDIATYPE;
|
||||
}
|
||||
|
||||
|
||||
/* Reset session info with only one media stream */
|
||||
sess_info.stream_cnt = 1;
|
||||
if (si != &sess_info.stream_info[0])
|
||||
pj_memcpy(&sess_info.stream_info[0], si, sizeof(pjmedia_stream_info));
|
||||
|
||||
/* Check if media is put on-hold */
|
||||
if (sess_info.stream_cnt == 0 ||
|
||||
sess_info.stream_info[0].dir == PJMEDIA_DIR_NONE)
|
||||
if (sess_info.stream_cnt == 0 || si->dir == PJMEDIA_DIR_NONE)
|
||||
{
|
||||
|
||||
/* Determine who puts the call on-hold */
|
||||
|
@ -943,28 +963,28 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
|
|||
|
||||
/* Override ptime, if this option is specified. */
|
||||
if (pjsua_var.media_cfg.ptime != 0) {
|
||||
sess_info.stream_info[0].param->setting.frm_per_pkt = (pj_uint8_t)
|
||||
(pjsua_var.media_cfg.ptime / sess_info.stream_info[0].param->info.frm_ptime);
|
||||
if (sess_info.stream_info[0].param->setting.frm_per_pkt == 0)
|
||||
sess_info.stream_info[0].param->setting.frm_per_pkt = 1;
|
||||
si->param->setting.frm_per_pkt = (pj_uint8_t)
|
||||
(pjsua_var.media_cfg.ptime / si->param->info.frm_ptime);
|
||||
if (si->param->setting.frm_per_pkt == 0)
|
||||
si->param->setting.frm_per_pkt = 1;
|
||||
}
|
||||
|
||||
/* Disable VAD, if this option is specified. */
|
||||
if (pjsua_var.media_cfg.no_vad) {
|
||||
sess_info.stream_info[0].param->setting.vad = 0;
|
||||
si->param->setting.vad = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Optionally, application may modify other stream settings here
|
||||
* (such as jitter buffer parameters, codec ptime, etc.)
|
||||
*/
|
||||
sess_info.stream_info[0].jb_init = pjsua_var.media_cfg.jb_init;
|
||||
sess_info.stream_info[0].jb_min_pre = pjsua_var.media_cfg.jb_min_pre;
|
||||
sess_info.stream_info[0].jb_max_pre = pjsua_var.media_cfg.jb_max_pre;
|
||||
sess_info.stream_info[0].jb_max = pjsua_var.media_cfg.jb_max;
|
||||
si->jb_init = pjsua_var.media_cfg.jb_init;
|
||||
si->jb_min_pre = pjsua_var.media_cfg.jb_min_pre;
|
||||
si->jb_max_pre = pjsua_var.media_cfg.jb_max_pre;
|
||||
si->jb_max = pjsua_var.media_cfg.jb_max;
|
||||
|
||||
/* Set SSRC */
|
||||
sess_info.stream_info[0].ssrc = call->ssrc;
|
||||
si->ssrc = call->ssrc;
|
||||
|
||||
/* Create session based on session info. */
|
||||
status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info,
|
||||
|
@ -1009,7 +1029,7 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
|
|||
|
||||
/* Call's media state is active */
|
||||
call->media_st = PJSUA_CALL_MEDIA_ACTIVE;
|
||||
call->media_dir = sess_info.stream_info[0].dir;
|
||||
call->media_dir = si->dir;
|
||||
}
|
||||
|
||||
/* Print info. */
|
||||
|
|
Loading…
Reference in New Issue