diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2012-01-27 09:12:59 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2012-01-27 09:12:59 +0000 |
commit | 9944702e692e3dc8ab6afb53c78c1e66da6bff9f (patch) | |
tree | 30acc3d59bdc59f0f6bca3aaa4406b553fc5e8c8 | |
parent | d3d6518fe7176c4312394686275e11788200fbc1 (diff) |
Re #1244: Added bandwidth info in SDP ("b=" lines) based on codec bitrate settings. Two SDP bandwidth types/modifiers are used: AS in session level & TIAS in media level.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3945 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r-- | pjmedia/include/pjmedia/errno.h | 5 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/sdp.h | 7 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/endpoint.c | 39 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/errno.c | 1 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/sdp.c | 48 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 33 |
6 files changed, 131 insertions, 2 deletions
diff --git a/pjmedia/include/pjmedia/errno.h b/pjmedia/include/pjmedia/errno.h index 3c27e35f..063e5437 100644 --- a/pjmedia/include/pjmedia/errno.h +++ b/pjmedia/include/pjmedia/errno.h @@ -171,6 +171,11 @@ PJ_BEGIN_DECL * Invalid SDP media transport protocol. */ #define PJMEDIA_SDP_EINPROTO (PJMEDIA_ERRNO_START+36) /* 220036 */ +/** + * @hideinitializer + * Invalid SDP bandwidth info (b=) line. + */ +#define PJMEDIA_SDP_EINBANDW (PJMEDIA_ERRNO_START+37) /* 220037 */ /************************************************************ diff --git a/pjmedia/include/pjmedia/sdp.h b/pjmedia/include/pjmedia/sdp.h index cd89b847..c3f67823 100644 --- a/pjmedia/include/pjmedia/sdp.h +++ b/pjmedia/include/pjmedia/sdp.h @@ -614,8 +614,11 @@ struct pjmedia_sdp_session pj_str_t addr; /**< The address. */ } origin; - pj_str_t name; /**< Subject line (s=) */ - pjmedia_sdp_conn *conn; /**< Connection line (c=) */ + pj_str_t name; /**< Subject line (s=) */ + pjmedia_sdp_conn *conn; /**< Connection line (c=) */ + unsigned bandw_count; /**< Number of bandwidth info (b=) */ + pjmedia_sdp_bandw *bandw[PJMEDIA_MAX_SDP_BANDW]; + /**< Bandwidth info array (b=) */ /** Session time (t= line) */ struct diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c index 535e0c5c..b9ebe69a 100644 --- a/pjmedia/src/pjmedia/endpoint.c +++ b/pjmedia/src/pjmedia/endpoint.c @@ -372,6 +372,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt, pjmedia_sdp_media *m; pjmedia_sdp_attr *attr; unsigned i; + unsigned max_bitrate = 0; pj_status_t status; PJ_UNUSED_ARG(options); @@ -493,6 +494,10 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt, attr->value = pj_strdup3(pool, buf); m->attr[m->attr_count++] = attr; } + + /* Find maximum bitrate in this media */ + if (max_bitrate < codec_param.info.max_bps) + max_bitrate = codec_param.info.max_bps; } #if defined(PJMEDIA_RTP_PT_TELEPHONE_EVENTS) && \ @@ -519,6 +524,19 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt, } #endif + /* Put bandwidth info in media level using bandwidth modifier "TIAS" + * (RFC3890). + */ + if (max_bitrate) { + const pj_str_t STR_BANDW_MODIFIER = { "TIAS", 4 }; + pjmedia_sdp_bandw *b; + + b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw); + b->modifier = STR_BANDW_MODIFIER; + b->value = max_bitrate; + m->bandw[m->bandw_count++] = b; + } + *p_m = m; return PJ_SUCCESS; } @@ -541,6 +559,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt, unsigned codec_prio[PJMEDIA_VID_CODEC_MGR_MAX_CODECS]; pjmedia_sdp_attr *attr; unsigned cnt, i; + unsigned max_bitrate = 0; pj_status_t status; PJ_UNUSED_ARG(options); @@ -568,6 +587,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt, pjmedia_sdp_rtpmap rtpmap; pjmedia_vid_codec_param codec_param; pj_str_t *fmt; + pjmedia_video_format_detail *vfd; pj_bzero(&rtpmap, sizeof(rtpmap)); @@ -660,6 +680,25 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt, attr->value = pj_strdup3(pool, buf); m->attr[m->attr_count++] = attr; } + + /* Find maximum bitrate in this media */ + vfd = pjmedia_format_get_video_format_detail(&codec_param.enc_fmt, + PJ_TRUE); + if (vfd && max_bitrate < vfd->max_bps) + max_bitrate = vfd->max_bps; + } + + /* Put bandwidth info in media level using bandwidth modifier "TIAS" + * (RFC3890). + */ + if (max_bitrate) { + const pj_str_t STR_BANDW_MODIFIER = { "TIAS", 4 }; + pjmedia_sdp_bandw *b; + + b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw); + b->modifier = STR_BANDW_MODIFIER; + b->value = max_bitrate; + m->bandw[m->bandw_count++] = b; } *p_m = m; diff --git a/pjmedia/src/pjmedia/errno.c b/pjmedia/src/pjmedia/errno.c index 788f7431..7a8538eb 100644 --- a/pjmedia/src/pjmedia/errno.c +++ b/pjmedia/src/pjmedia/errno.c @@ -66,6 +66,7 @@ static const struct 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" ), + PJ_BUILD_ERR( PJMEDIA_SDP_EINBANDW, "Invalid SDP bandwidth info line" ), /* SDP negotiator errors. */ PJ_BUILD_ERR( PJMEDIA_SDPNEG_EINSTATE, "Invalid SDP negotiator state for operation" ), diff --git a/pjmedia/src/pjmedia/sdp.c b/pjmedia/src/pjmedia/sdp.c index 417a3dfe..629500c7 100644 --- a/pjmedia/src/pjmedia/sdp.c +++ b/pjmedia/src/pjmedia/sdp.c @@ -59,6 +59,8 @@ static void parse_generic_line(pj_scanner *scanner, pj_str_t *str, parse_context *ctx); static void parse_connection_info(pj_scanner *scanner, pjmedia_sdp_conn *conn, parse_context *ctx); +static void parse_bandwidth_info(pj_scanner *scanner, pjmedia_sdp_bandw *bandw, + parse_context *ctx); static pjmedia_sdp_attr *parse_attr(pj_pool_t *pool, pj_scanner *scanner, parse_context *ctx); static void parse_media(pj_scanner *scanner, pjmedia_sdp_media *med, @@ -810,6 +812,14 @@ static int print_session(const pjmedia_sdp_session *ses, p += printed; } + /* print optional bandwidth info. */ + for (i=0; i<ses->bandw_count; ++i) { + printed = print_bandw(ses->bandw[i], p, end-p); + if (printed < 1) { + return -1; + } + p += printed; + } /* Time */ if ((end-p) < 24) { @@ -991,6 +1001,28 @@ static void parse_connection_info(pj_scanner *scanner, pjmedia_sdp_conn *conn, pj_scan_skip_line(scanner); } +static void parse_bandwidth_info(pj_scanner *scanner, pjmedia_sdp_bandw *bandw, + parse_context *ctx) +{ + pj_str_t str; + + ctx->last_error = PJMEDIA_SDP_EINBANDW; + + /* b= */ + pj_scan_advance_n(scanner, 2, SKIP_WS); + + /* modifier */ + pj_scan_get_until_ch(scanner, ':', &bandw->modifier); + pj_scan_get_char(scanner); + + /* value */ + pj_scan_get_until_chr(scanner, " \t\r\n", &str); + bandw->value = pj_strtoul(&str); + + /* We've got what we're looking for, skip anything until newline */ + pj_scan_skip_line(scanner); +} + static void parse_media(pj_scanner *scanner, pjmedia_sdp_media *med, parse_context *ctx) { @@ -1180,6 +1212,7 @@ PJ_DEF(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool, pjmedia_sdp_media *media = NULL; pjmedia_sdp_attr *attr; pjmedia_sdp_conn *conn; + pjmedia_sdp_bandw *bandw; pj_str_t dummy; int cur_name = 254; parse_context ctx; @@ -1253,6 +1286,15 @@ PJ_DEF(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool, pj_scan_get_char(&scanner); } break; + case 'b': + bandw = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_bandw); + parse_bandwidth_info(&scanner, bandw, &ctx); + if (media) { + media->bandw[media->bandw_count++] = bandw; + } else { + session->bandw[session->bandw_count++] = bandw; + } + break; default: if (cur_name >= 'a' && cur_name <= 'z') parse_generic_line(&scanner, &dummy, &ctx); @@ -1332,6 +1374,12 @@ PJ_DEF(pjmedia_sdp_session*) pjmedia_sdp_session_clone( pj_pool_t *pool, PJ_ASSERT_RETURN(sess->conn != NULL, NULL); } + /* Duplicate bandwidth info */ + sess->bandw_count = rhs->bandw_count; + for (i=0; i<rhs->bandw_count; ++i) { + sess->bandw[i] = pjmedia_sdp_bandw_clone(pool, rhs->bandw[i]); + } + /* Clone time line. */ sess->time.start = rhs->time.start; sess->time.stop = rhs->time.stop; diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 66cecf58..917dadcb 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -1938,6 +1938,7 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, pjsua_call *call = &pjsua_var.calls[call_id]; pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL; unsigned mi; + unsigned tot_bandw_tias = 0; pj_status_t status; if (pjsua_get_state() != PJSUA_STATE_RUNNING) @@ -2011,6 +2012,7 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, pjsua_call_media *call_med = &call->media[mi]; pjmedia_sdp_media *m = NULL; pjmedia_transport_info tpinfo; + unsigned i; if (rem_sdp && mi >= rem_sdp->media_count) { /* Remote might have removed some media lines. */ @@ -2108,6 +2110,17 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, if (sdp->conn == NULL) { sdp->conn = pjmedia_sdp_conn_clone(pool, m->conn); } + + + /* Find media bandwidth info */ + for (i = 0; i < m->bandw_count; ++i) { + const pj_str_t STR_BANDW_MODIFIER_TIAS = { "TIAS", 4 }; + if (!pj_stricmp(&m->bandw[i]->modifier, &STR_BANDW_MODIFIER_TIAS)) + { + tot_bandw_tias += m->bandw[i]->value; + break; + } + } } /* Add NAT info in the SDP */ @@ -2135,6 +2148,26 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, } + /* Add bandwidth info in session level using bandwidth modifier "AS". */ + if (tot_bandw_tias) { + unsigned bandw; + const pj_str_t STR_BANDW_MODIFIER_AS = { "AS", 2 }; + pjmedia_sdp_bandw *b; + + /* AS bandwidth = RTP bitrate + RTCP bitrate. + * RTP bitrate = payload bitrate (total TIAS) + overheads (~16kbps). + * RTCP bitrate = est. 5% of RTP bitrate. + * Note that AS bandwidth is in kbps. + */ + bandw = tot_bandw_tias + 16000; + bandw += bandw * 5 / 100; + b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw); + b->modifier = STR_BANDW_MODIFIER_AS; + b->value = bandw / 1000; + sdp->bandw[sdp->bandw_count++] = b; + } + + #if DISABLED_FOR_TICKET_1185 && defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) /* Check if SRTP is in optional mode and configured to use duplicated * media, i.e: secured and unsecured version, in the SDP offer. |