Changeset 5820
- Timestamp:
- Jul 12, 2018 8:22:31 AM (6 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 2 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/pjmedia.vcproj
r5597 r5820 5636 5636 </File> 5637 5637 <File 5638 RelativePath="..\src\pjmedia\rtcp_fb.c" 5639 > 5640 </File> 5641 <File 5638 5642 RelativePath="..\src\pjmedia\rtcp_xr.c" 5639 5643 > … … 7601 7605 </File> 7602 7606 <File 7607 RelativePath="..\include\pjmedia\rtcp_fb.h" 7608 > 7609 </File> 7610 <File 7603 7611 RelativePath="..\include\pjmedia\rtcp_xr.h" 7604 7612 > -
pjproject/trunk/pjmedia/include/pjmedia/config.h
r5786 r5820 568 568 569 569 /** 570 * Specify the maximum number of RTCP Feedback capability definition. 571 * 572 * Default: 16 573 */ 574 #ifndef PJMEDIA_RTCP_FB_MAX_CAP 575 # define PJMEDIA_RTCP_FB_MAX_CAP 16 576 #endif 577 578 579 /** 570 580 * Specify how long (in miliseconds) the stream should suspend the 571 581 * silence detector/voice activity detector (VAD) during the initial -
pjproject/trunk/pjmedia/include/pjmedia/sdp.h
r5748 r5820 603 603 604 604 /** 605 * Get media transport protocol info, i.e: base transport and profiles, 606 * from the provided SDP media transport name string. 607 * 608 * @param tp The SDP media transport name. 609 * 610 * @return Media transport info, combination of transport protocol 611 * and profile bit flag defined in pjmedia_tp_proto. 612 */ 613 PJ_DECL(pj_uint32_t) pjmedia_sdp_transport_get_proto(const pj_str_t *tp); 614 615 616 /** 605 617 * Deactivate SDP media. 606 618 * -
pjproject/trunk/pjmedia/include/pjmedia/stream.h
r5788 r5820 32 32 #include <pjmedia/port.h> 33 33 #include <pjmedia/rtcp.h> 34 #include <pjmedia/rtcp_fb.h> 34 35 #include <pjmedia/transport.h> 35 36 #include <pjmedia/vid_codec.h> … … 110 111 this will be ignored. */ 111 112 #endif 113 pjmedia_rtcp_fb_info loc_rtcp_fb; /**< Local RTCP-FB info. */ 114 pjmedia_rtcp_fb_info rem_rtcp_fb; /**< Remote RTCP-FB info. */ 112 115 pjmedia_codec_info fmt; /**< Incoming codec format info. */ 113 116 pjmedia_codec_param *param; /**< Optional codec param. */ -
pjproject/trunk/pjmedia/include/pjmedia/types.h
r5166 r5820 73 73 74 74 /** 75 * Media transport protocol .75 * Media transport protocol and profile. 76 76 */ 77 77 typedef enum pjmedia_tp_proto 78 78 { 79 /* Basic transports */ 80 79 81 /** No transport type */ 80 PJMEDIA_TP_PROTO_NONE = 0, 82 PJMEDIA_TP_PROTO_NONE = 0, 83 84 /** Transport unknown */ 85 PJMEDIA_TP_PROTO_UNKNOWN = (1 << 0), 86 87 /** UDP transport */ 88 PJMEDIA_TP_PROTO_UDP = (1 << 1), 89 90 /** RTP transport */ 91 PJMEDIA_TP_PROTO_RTP = (1 << 2), 92 93 /** DTLS transport */ 94 PJMEDIA_TP_PROTO_DTLS = (1 << 3), 95 96 97 /* Basic profiles */ 98 99 /** RTCP Feedback profile */ 100 PJMEDIA_TP_PROFILE_RTCP_FB = (1 << 13), 101 102 /** Secure RTP profile */ 103 PJMEDIA_TP_PROFILE_SRTP = (1 << 14), 104 105 /** Audio/video profile */ 106 PJMEDIA_TP_PROFILE_AVP = (1 << 15), 107 108 109 /* Predefined transport profiles (commonly used) */ 81 110 82 111 /** RTP using A/V profile */ 83 PJMEDIA_TP_PROTO_RTP_AVP, 84 85 /** Secure RTP */ 86 PJMEDIA_TP_PROTO_RTP_SAVP, 87 88 /** Unknown */ 89 PJMEDIA_TP_PROTO_UNKNOWN 112 PJMEDIA_TP_PROTO_RTP_AVP = (PJMEDIA_TP_PROTO_RTP | 113 PJMEDIA_TP_PROFILE_AVP), 114 115 /** Secure RTP using A/V profile */ 116 PJMEDIA_TP_PROTO_RTP_SAVP = (PJMEDIA_TP_PROTO_RTP_AVP | 117 PJMEDIA_TP_PROFILE_SRTP), 118 119 /** Secure RTP using A/V profile and DTLS-SRTP keying */ 120 PJMEDIA_TP_PROTO_DTLS_SRTP = (PJMEDIA_TP_PROTO_DTLS | 121 PJMEDIA_TP_PROTO_RTP_SAVP), 122 123 /** RTP using A/V and RTCP feedback profile */ 124 PJMEDIA_TP_PROTO_RTP_AVPF = (PJMEDIA_TP_PROTO_RTP_AVP | 125 PJMEDIA_TP_PROFILE_RTCP_FB), 126 127 /** Secure RTP using A/V and RTCP feedback profile */ 128 PJMEDIA_TP_PROTO_RTP_SAVPF = (PJMEDIA_TP_PROTO_RTP_SAVP | 129 PJMEDIA_TP_PROFILE_RTCP_FB), 130 131 /** Secure RTP using A/V and RTCP feedback profile and DTLS-SRTP keying */ 132 PJMEDIA_TP_PROTO_DTLS_SRTPF = (PJMEDIA_TP_PROTO_DTLS_SRTP | 133 PJMEDIA_TP_PROFILE_RTCP_FB), 90 134 91 135 } pjmedia_tp_proto; 92 136 137 /** 138 * Macro helper for checking if a transport protocol contains specific 139 * transport and profile flags. 140 */ 141 #define PJMEDIA_TP_PROTO_HAS_FLAG(TP_PROTO, FLAGS) \ 142 (((TP_PROTO) & (FLAGS)) == (FLAGS)) 143 144 /** 145 * Macro helper for excluding specific flags in transport protocol. 146 */ 147 #define PJMEDIA_TP_PROTO_TRIM_FLAG(TP_PROTO, FLAGS) ((TP_PROTO) &= ~(FLAGS)) 93 148 94 149 /** -
pjproject/trunk/pjmedia/src/pjmedia/sdp.c
r5753 r5820 1642 1642 const pj_str_t *t2) 1643 1643 { 1644 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 1645 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 1644 pj_uint32_t t1_proto, t2_proto; 1646 1645 1647 1646 /* Exactly equal? */ … … 1649 1648 return PJ_SUCCESS; 1650 1649 1650 /* Check if boths are RTP/AVP based */ 1651 t1_proto = pjmedia_sdp_transport_get_proto(t1); 1652 t2_proto = pjmedia_sdp_transport_get_proto(t2); 1653 if (PJMEDIA_TP_PROTO_HAS_FLAG(t1_proto, PJMEDIA_TP_PROTO_RTP_AVP) && 1654 PJMEDIA_TP_PROTO_HAS_FLAG(t2_proto, PJMEDIA_TP_PROTO_RTP_AVP)) 1655 { 1656 return PJ_SUCCESS; 1657 } 1658 1651 1659 /* Compatible? */ 1652 if ((!pj_stricmp(t1, &ID_RTP_AVP) || !pj_stricmp(t1, &ID_RTP_SAVP)) && 1653 (!pj_stricmp(t2, &ID_RTP_AVP) || !pj_stricmp(t2, &ID_RTP_SAVP))) 1654 return PJ_SUCCESS; 1660 //{ 1661 // static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 1662 // static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 1663 // if ((!pj_stricmp(t1, &ID_RTP_AVP) || !pj_stricmp(t1, &ID_RTP_SAVP)) && 1664 // (!pj_stricmp(t2, &ID_RTP_AVP) || !pj_stricmp(t2, &ID_RTP_SAVP))) 1665 // return PJ_SUCCESS; 1666 //} 1655 1667 1656 1668 return PJMEDIA_SDP_ETPORTNOTEQUAL; 1669 } 1670 1671 1672 /* 1673 * Get media transport info, e.g: protocol and profile. 1674 */ 1675 PJ_DEF(pj_uint32_t) pjmedia_sdp_transport_get_proto(const pj_str_t *tp) 1676 { 1677 pj_str_t token, rest = {0}; 1678 pj_ssize_t idx; 1679 1680 PJ_ASSERT_RETURN(tp, PJMEDIA_TP_PROTO_NONE); 1681 1682 idx = pj_strtok2(tp, "/", &token, 0); 1683 if (idx != tp->slen) 1684 pj_strset(&rest, tp->ptr + token.slen + 1, tp->slen - token.slen - 1); 1685 1686 if (pj_stricmp2(&token, "RTP") == 0) { 1687 /* Starts with "RTP" */ 1688 1689 /* RTP/AVP */ 1690 if (pj_stricmp2(&rest, "AVP") == 0) 1691 return PJMEDIA_TP_PROTO_RTP_AVP; 1692 1693 /* RTP/SAVP */ 1694 if (pj_stricmp2(&rest, "SAVP") == 0) 1695 return PJMEDIA_TP_PROTO_RTP_SAVP; 1696 1697 /* RTP/AVPF */ 1698 if (pj_stricmp2(&rest, "AVPF") == 0) 1699 return PJMEDIA_TP_PROTO_RTP_AVPF; 1700 1701 /* RTP/SAVPF */ 1702 if (pj_stricmp2(&rest, "SAVPF") == 0) 1703 return PJMEDIA_TP_PROTO_RTP_SAVPF; 1704 1705 } else if (pj_stricmp2(&token, "UDP") == 0) { 1706 /* Starts with "UDP" */ 1707 1708 /* Plain UDP */ 1709 if (rest.slen == 0) 1710 return PJMEDIA_TP_PROTO_UDP; 1711 1712 /* DTLS-SRTP */ 1713 if (pj_stricmp2(&rest, "TLS/RTP/SAVP") == 0) 1714 return PJMEDIA_TP_PROTO_DTLS_SRTP; 1715 1716 /* DTLS-SRTP with RTCP-FB */ 1717 if (pj_stricmp2(&rest, "TLS/RTP/SAVPF") == 0) 1718 return PJMEDIA_TP_PROTO_DTLS_SRTPF; 1719 } 1720 1721 /* Unknown transport */ 1722 return PJMEDIA_TP_PROTO_UNKNOWN; 1657 1723 } 1658 1724 -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r5813 r5820 97 97 int ebit_cnt; /**< # of E bit transmissions */ 98 98 }; 99 99 100 100 101 /** … … 246 247 pj_uint32_t rtp_rx_last_ts; /**< Last received RTP timestamp*/ 247 248 pj_status_t rtp_rx_last_err; /**< Last RTP recv() error */ 249 250 /* RTCP Feedback */ 251 pj_bool_t send_rtcp_fb_nack;/**< Should we send NACK? */ 252 pjmedia_rtcp_fb_nack rtcp_fb_nack; /**< NACK state. */ 253 254 248 255 }; 249 256 … … 278 285 pj_bool_t with_sdes, 279 286 pj_bool_t with_bye, 280 pj_bool_t with_xr); 287 pj_bool_t with_xr, 288 pj_bool_t with_fb); 281 289 282 290 … … 461 469 462 470 /* Send RTCP */ 463 send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE );471 send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_FALSE); 464 472 465 473 /* Update stats in case the stream is paused */ … … 992 1000 993 1001 1002 static pj_status_t build_rtcp_fb(pjmedia_stream *stream, void *buf, 1003 pj_size_t *length) 1004 { 1005 pj_status_t status; 1006 1007 /* Generic NACK */ 1008 if (stream->send_rtcp_fb_nack && stream->rtcp_fb_nack.pid >= 0) 1009 { 1010 status = pjmedia_rtcp_fb_build_nack(&stream->rtcp, buf, length, 1, 1011 &stream->rtcp_fb_nack); 1012 if (status != PJ_SUCCESS) 1013 return status; 1014 1015 /* Reset Packet ID */ 1016 stream->rtcp_fb_nack.pid = -1; 1017 } 1018 1019 return PJ_SUCCESS; 1020 } 1021 1022 994 1023 static pj_status_t send_rtcp(pjmedia_stream *stream, 995 1024 pj_bool_t with_sdes, 996 1025 pj_bool_t with_bye, 997 pj_bool_t with_xr) 1026 pj_bool_t with_xr, 1027 pj_bool_t with_fb) 998 1028 { 999 1029 void *sr_rr_pkt; … … 1009 1039 #endif 1010 1040 1011 if (with_sdes || with_bye || with_xr ) {1041 if (with_sdes || with_bye || with_xr || with_fb) { 1012 1042 pkt = (pj_uint8_t*) stream->out_rtcp_pkt; 1013 1043 pj_memcpy(pkt, sr_rr_pkt, len); … … 1017 1047 max_len = len; 1018 1048 } 1049 1050 /* RTCP FB must be sent in compound (i.e: with RR/SR and SDES) */ 1051 if (with_fb) 1052 with_sdes = PJ_TRUE; 1019 1053 1020 1054 /* Build RTCP SDES packet */ … … 1036 1070 } 1037 1071 1072 if (with_fb) { 1073 pj_size_t fb_len = max_len - len; 1074 status = build_rtcp_fb(stream, pkt+len, &fb_len); 1075 if (status != PJ_SUCCESS) { 1076 PJ_PERROR(4,(stream->port.info.name.ptr, status, 1077 "Error generating RTCP FB")); 1078 } else { 1079 len += (int)fb_len; 1080 } 1081 } 1082 1038 1083 /* Build RTCP XR packet */ 1039 1084 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) … … 1137 1182 1138 1183 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE, 1139 with_xr );1184 with_xr, PJ_FALSE); 1140 1185 if (status != PJ_SUCCESS) { 1141 1186 PJ_PERROR(4,(stream->port.info.name.ptr, status, … … 1680 1725 const void *payload; 1681 1726 unsigned payloadlen; 1682 pjmedia_rtp_status seq_st ;1727 pjmedia_rtp_status seq_st = {0}; 1683 1728 pj_status_t status; 1684 1729 pj_bool_t pkt_discarded = PJ_FALSE; … … 2006 2051 pj_ntohl(hdr->ts), payloadlen, pkt_discarded); 2007 2052 2053 /* RTCP-FB generic NACK */ 2054 if (stream->rtcp.received >= 10 && seq_st.diff > 1 && 2055 stream->send_rtcp_fb_nack && pj_ntohs(hdr->seq) >= seq_st.diff) 2056 { 2057 int i; 2058 pj_bzero(&stream->rtcp_fb_nack, sizeof(stream->rtcp_fb_nack)); 2059 stream->rtcp_fb_nack.pid = pj_ntohs(hdr->seq) - seq_st.diff + 1; 2060 for (i = 0; i < (seq_st.diff - 1); ++i) { 2061 stream->rtcp_fb_nack.blp <<= 1; 2062 stream->rtcp_fb_nack.blp |= 1; 2063 } 2064 2065 /* Send it immediately */ 2066 status = send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_TRUE); 2067 if (status != PJ_SUCCESS) { 2068 PJ_PERROR(4,(stream->port.info.name.ptr, status, 2069 "Error sending RTCP FB generic NACK")); 2070 } else { 2071 stream->initial_rr = PJ_TRUE; 2072 } 2073 } 2074 2008 2075 /* Send RTCP RR and SDES after we receive some RTP packets */ 2009 2076 if (stream->rtcp.received >= 10 && !stream->initial_rr) { 2010 2077 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, 2011 PJ_FALSE, PJ_FALSE );2078 PJ_FALSE, PJ_FALSE, PJ_FALSE); 2012 2079 if (status != PJ_SUCCESS) { 2013 2080 PJ_PERROR(4,(stream->port.info.name.ptr, status, … … 2161 2228 PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 2162 2229 stream->own_pool = own_pool; 2230 2231 /* Duplicate stream info */ 2163 2232 pj_memcpy(&stream->si, info, sizeof(*info)); 2164 2233 pj_strdup(pool, &stream->si.fmt.encoding_name, &info->fmt.encoding_name); 2165 2234 if (info->param) 2166 2235 stream->si.param = pjmedia_codec_param_clone(pool, info->param); 2236 pjmedia_rtcp_fb_info_dup(pool, &stream->si.loc_rtcp_fb, 2237 &info->loc_rtcp_fb); 2238 pjmedia_rtcp_fb_info_dup(pool, &stream->si.rem_rtcp_fb, 2239 &info->rem_rtcp_fb); 2167 2240 2168 2241 /* Init stream/port name */ … … 2200 2273 stream->last_dtmf = -1; 2201 2274 stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME; 2275 stream->rtcp_fb_nack.pid = -1; 2202 2276 2203 2277 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 … … 2591 2665 #endif 2592 2666 2667 /* Check if RTCP-FB generic NACK is enabled for this codec */ 2668 if (stream->si.rem_rtcp_fb.cap_count) { 2669 pjmedia_rtcp_fb_info *rfi = &stream->si.rem_rtcp_fb; 2670 char cid[32]; 2671 unsigned i; 2672 2673 pjmedia_codec_info_to_id(&stream->si.fmt, cid, sizeof(cid)); 2674 2675 for (i = 0; i < rfi->cap_count; ++i) { 2676 if (rfi->caps[i].type == PJMEDIA_RTCP_FB_NACK && 2677 (!pj_strcmp2( &rfi->caps[i].codec_id, "*") || 2678 !pj_stricmp2(&rfi->caps[i].codec_id, cid))) 2679 { 2680 stream->send_rtcp_fb_nack = PJ_TRUE; 2681 break; 2682 } 2683 } 2684 } 2685 2593 2686 /* Update the stream info's codec param */ 2594 2687 stream->si.param = &stream->codec_param; … … 2659 2752 /* Send RTCP BYE (also SDES & XR) */ 2660 2753 if (!stream->rtcp_sdes_bye_disabled) { 2661 send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE );2754 send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE, PJ_FALSE); 2662 2755 } 2663 2756 … … 3074 3167 PJ_ASSERT_RETURN(stream, PJ_EINVAL); 3075 3168 3076 return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE );3169 return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_FALSE); 3077 3170 } 3078 3171 … … 3086 3179 3087 3180 if (stream->enc && stream->transport) { 3088 return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE );3181 return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE, PJ_FALSE); 3089 3182 } 3090 3183 -
pjproject/trunk/pjmedia/src/pjmedia/stream_info.c
r5788 r5820 28 28 static const pj_str_t ID_IP4 = { "IP4", 3}; 29 29 static const pj_str_t ID_IP6 = { "IP6", 3}; 30 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };31 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };32 30 //static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 33 31 static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; … … 417 415 return PJMEDIA_SDPNEG_EINVANSTP; 418 416 419 if (pj_stricmp(&local_m->desc.transport, &ID_RTP_AVP) == 0) { 420 421 si->proto = PJMEDIA_TP_PROTO_RTP_AVP; 422 423 } else if (pj_stristr(&local_m->desc.transport, &ID_RTP_SAVP)) { 424 425 si->proto = PJMEDIA_TP_PROTO_RTP_SAVP; 426 427 } else { 428 429 si->proto = PJMEDIA_TP_PROTO_UNKNOWN; 417 /* Get the transport protocol */ 418 si->proto = pjmedia_sdp_transport_get_proto(&local_m->desc.transport); 419 420 /* Just return success if stream is not RTP/AVP compatible */ 421 if (!PJMEDIA_TP_PROTO_HAS_FLAG(si->proto, PJMEDIA_TP_PROTO_RTP_AVP)) 430 422 return PJ_SUCCESS; 431 }432 433 423 434 424 /* Check address family in remote SDP */ … … 602 592 /* Get codec info and param */ 603 593 status = get_audio_codec_info_param(si, pool, mgr, local_m, rem_m); 594 if (status != PJ_SUCCESS) 595 return status; 604 596 605 597 /* Leave SSRC to random. */ … … 609 601 si->jb_init = si->jb_max = si->jb_min_pre = si->jb_max_pre = -1; 610 602 603 /* Get local RTCP-FB info */ 604 status = pjmedia_rtcp_fb_decode_sdp(pool, endpt, NULL, local, stream_idx, 605 &si->loc_rtcp_fb); 606 if (status != PJ_SUCCESS) 607 return status; 608 609 /* Get remote RTCP-FB info */ 610 status = pjmedia_rtcp_fb_decode_sdp(pool, endpt, NULL, remote, stream_idx, 611 &si->rem_rtcp_fb); 612 if (status != PJ_SUCCESS) 613 return status; 614 611 615 return status; 612 616 } -
pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
r5788 r5820 186 186 }; 187 187 188 static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };189 188 static const pj_str_t STR_CANDIDATE = { "candidate", 9}; 190 189 static const pj_str_t STR_REM_CAND = { "remote-candidates", 17 }; … … 1408 1407 */ 1409 1408 if ((tp_ice->media_option & PJMEDIA_TPMED_NO_TRANSPORT_CHECKING) == 0) { 1410 pjmedia_sdp_media *loc_m, *rem_m; 1411 1412 rem_m = rem_sdp? rem_sdp->media[media_index] : NULL; 1413 loc_m = sdp_local->media[media_index]; 1414 1415 if (pj_stricmp(&loc_m->desc.transport, &STR_RTP_AVP) || 1416 (rem_m && pj_stricmp(&rem_m->desc.transport, &STR_RTP_AVP))) 1409 pjmedia_sdp_media *m_rem, *m_loc; 1410 pj_uint32_t tp_proto_loc, tp_proto_rem; 1411 1412 m_rem = rem_sdp? rem_sdp->media[media_index] : NULL; 1413 m_loc = sdp_local->media[media_index]; 1414 1415 tp_proto_loc = pjmedia_sdp_transport_get_proto(&m_loc->desc.transport); 1416 tp_proto_rem = m_rem? 1417 pjmedia_sdp_transport_get_proto(&m_rem->desc.transport) : 0; 1418 PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_loc, PJMEDIA_TP_PROFILE_RTCP_FB); 1419 PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_rem, PJMEDIA_TP_PROFILE_RTCP_FB); 1420 1421 if ((tp_proto_loc != PJMEDIA_TP_PROTO_RTP_AVP) || 1422 (m_rem && tp_proto_rem != PJMEDIA_TP_PROTO_RTP_AVP)) 1417 1423 { 1418 pjmedia_sdp_media_deactivate(sdp_pool, loc_m);1424 pjmedia_sdp_media_deactivate(sdp_pool, m_loc); 1419 1425 return PJMEDIA_SDP_EINPROTO; 1420 1426 } … … 1826 1832 param.addr_len = addr_len; 1827 1833 param.rtp_cb = rtp_cb; 1834 param.rtcp_cb = rtcp_cb; 1828 1835 return transport_attach2(tp, ¶m); 1829 1836 } -
pjproject/trunk/pjmedia/src/pjmedia/transport_srtp_dtls.c
r5794 r5820 1048 1048 pjmedia_sdp_media *m_rem = sdp_remote->media[media_index]; 1049 1049 pjmedia_sdp_attr *attr_setup; 1050 1051 if (pj_stricmp(&m_rem->desc.transport, &ID_TP_DTLS_SRTP)!=0) { 1050 pj_uint32_t rem_proto = 0; 1051 1052 rem_proto = pjmedia_sdp_transport_get_proto(&m_rem->desc.transport); 1053 if (!PJMEDIA_TP_PROTO_HAS_FLAG(rem_proto, PJMEDIA_TP_PROTO_DTLS_SRTP)) 1054 { 1052 1055 /* Remote doesn't signal DTLS-SRTP */ 1053 1056 status = PJMEDIA_SRTP_ESDPINTRANSPORT; -
pjproject/trunk/pjmedia/src/pjmedia/transport_srtp_sdes.c
r5755 r5820 274 274 { 275 275 struct transport_srtp *srtp = (struct transport_srtp*)tp->user_data; 276 pj_uint32_t rem_proto = 0; 276 277 277 278 PJ_UNUSED_ARG(options); … … 281 282 if (!srtp->offerer_side) { 282 283 pjmedia_sdp_media *m = sdp_remote->media[media_index]; 283 if (pj_stricmp(&m->desc.transport, &ID_RTP_AVP) != 0 && 284 pj_stricmp(&m->desc.transport, &ID_RTP_SAVP) != 0) 284 285 /* Get transport protocol and drop any RTCP-FB flag */ 286 rem_proto = pjmedia_sdp_transport_get_proto(&m->desc.transport); 287 PJMEDIA_TP_PROTO_TRIM_FLAG(rem_proto, PJMEDIA_TP_PROFILE_RTCP_FB); 288 if (rem_proto != PJMEDIA_TP_PROTO_RTP_AVP && 289 rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 285 290 { 286 291 return PJMEDIA_SRTP_ESDPINTRANSPORT; … … 292 297 /* As offerer: do nothing. */ 293 298 } else { 294 pjmedia_sdp_media *m_rem = sdp_remote->media[media_index];295 296 299 /* Validate remote media transport based on SRTP usage option. */ 297 300 switch (srtp->setting.use) { 298 301 case PJMEDIA_SRTP_DISABLED: 299 if ( pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)302 if (rem_proto == PJMEDIA_TP_PROTO_RTP_SAVP) 300 303 return PJMEDIA_SRTP_ESDPINTRANSPORT; 301 304 break; … … 303 306 break; 304 307 case PJMEDIA_SRTP_MANDATORY: 305 if ( pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0)308 if (rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 306 309 return PJMEDIA_SRTP_ESDPINTRANSPORT; 307 310 break; … … 334 337 { 335 338 pjmedia_sdp_media *m = sdp_remote? m_rem : m_loc; 336 if (pj_stricmp(&m->desc.transport, &ID_RTP_AVP) != 0 && 337 pj_stricmp(&m->desc.transport, &ID_RTP_SAVP) != 0) 339 pj_uint32_t proto = 0; 340 341 /* Get transport protocol and drop any RTCP-FB flag */ 342 proto = pjmedia_sdp_transport_get_proto(&m->desc.transport); 343 PJMEDIA_TP_PROTO_TRIM_FLAG(proto, PJMEDIA_TP_PROFILE_RTCP_FB); 344 if (proto != PJMEDIA_TP_PROTO_RTP_AVP && 345 proto != PJMEDIA_TP_PROTO_RTP_SAVP) 338 346 { 339 347 return PJMEDIA_SRTP_ESDPINTRANSPORT; … … 409 417 } else { 410 418 /* Answerer side */ 419 pj_uint32_t rem_proto = 0; 411 420 412 421 pj_assert(sdp_remote && m_rem); 422 423 /* Get transport protocol and drop any RTCP-FB flag */ 424 rem_proto = pjmedia_sdp_transport_get_proto(&m_rem->desc.transport); 425 PJMEDIA_TP_PROTO_TRIM_FLAG(rem_proto, PJMEDIA_TP_PROFILE_RTCP_FB); 413 426 414 427 /* Generate transport */ … … 416 429 case PJMEDIA_SRTP_DISABLED: 417 430 /* Should never reach here */ 418 if ( pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0)431 if (rem_proto == PJMEDIA_TP_PROTO_RTP_SAVP) 419 432 return PJMEDIA_SRTP_ESDPINTRANSPORT; 420 433 return PJ_SUCCESS; … … 422 435 break; 423 436 case PJMEDIA_SRTP_MANDATORY: 424 if ( pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0)437 if (rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 425 438 return PJMEDIA_SRTP_ESDPINTRANSPORT; 426 439 break; … … 496 509 */ 497 510 if ((!has_crypto_attr || matched_idx == -1) && 498 pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0)511 rem_proto == PJMEDIA_TP_PROTO_RTP_AVP) 499 512 { 500 513 return PJ_SUCCESS; … … 610 623 611 624 /* Verify media transport, it has to be RTP/AVP or RTP/SAVP */ 612 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) != 0 &&613 pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0)614 625 { 615 return PJMEDIA_SRTP_ESDPINTRANSPORT; 616 } 617 618 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) 619 srtp->peer_use = PJMEDIA_SRTP_MANDATORY; 620 else 621 srtp->peer_use = PJMEDIA_SRTP_OPTIONAL; 626 pj_uint32_t rem_proto; 627 628 /* Get transport protocol and drop any RTCP-FB flag */ 629 rem_proto = pjmedia_sdp_transport_get_proto(&m_rem->desc.transport); 630 PJMEDIA_TP_PROTO_TRIM_FLAG(rem_proto, PJMEDIA_TP_PROFILE_RTCP_FB); 631 if (rem_proto != PJMEDIA_TP_PROTO_RTP_AVP && 632 rem_proto != PJMEDIA_TP_PROTO_RTP_SAVP) 633 { 634 return PJMEDIA_SRTP_ESDPINTRANSPORT; 635 } 636 637 /* Also check if peer signal SRTP as mandatory */ 638 if (rem_proto == PJMEDIA_TP_PROTO_RTP_SAVP) 639 srtp->peer_use = PJMEDIA_SRTP_MANDATORY; 640 else 641 srtp->peer_use = PJMEDIA_SRTP_OPTIONAL; 642 } 622 643 623 644 /* For answerer side, this function will just have to start SRTP as … … 647 668 fill_local_crypto(srtp->pool, m_loc, loc_crypto, &loc_cryto_cnt); 648 669 } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 649 if ( pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP)) {670 if (srtp->peer_use != PJMEDIA_SRTP_MANDATORY) { 650 671 DEACTIVATE_MEDIA(pool, m_loc); 651 672 return PJMEDIA_SDP_EINPROTO; -
pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
r5788 r5820 37 37 /* Maximum pending write operations */ 38 38 #define MAX_PENDING 4 39 40 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };41 39 42 40 /* Pending write buffer */ … … 1031 1029 if ((udp->media_options & PJMEDIA_TPMED_NO_TRANSPORT_CHECKING) == 0) { 1032 1030 pjmedia_sdp_media *m_rem, *m_loc; 1031 pj_uint32_t tp_proto_loc, tp_proto_rem; 1033 1032 1034 1033 m_rem = rem_sdp? rem_sdp->media[media_index] : NULL; 1035 1034 m_loc = sdp_local->media[media_index]; 1036 1035 1037 if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) || 1038 (m_rem && pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP))) 1036 tp_proto_loc = pjmedia_sdp_transport_get_proto(&m_loc->desc.transport); 1037 tp_proto_rem = m_rem? 1038 pjmedia_sdp_transport_get_proto(&m_rem->desc.transport) : 0; 1039 PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_loc, PJMEDIA_TP_PROFILE_RTCP_FB); 1040 PJMEDIA_TP_PROTO_TRIM_FLAG(tp_proto_rem, PJMEDIA_TP_PROFILE_RTCP_FB); 1041 1042 if ((tp_proto_loc != PJMEDIA_TP_PROTO_RTP_AVP) || 1043 (m_rem && tp_proto_rem != PJMEDIA_TP_PROTO_RTP_AVP)) 1039 1044 { 1040 1045 pjmedia_sdp_media_deactivate(pool, m_loc); -
pjproject/trunk/pjmedia/src/pjmedia/vid_stream_info.c
r5788 r5820 29 29 static const pj_str_t ID_IP4 = { "IP4", 3}; 30 30 static const pj_str_t ID_IP6 = { "IP6", 3}; 31 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };32 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };33 31 //static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 34 32 static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; … … 240 238 return PJMEDIA_SDPNEG_EINVANSTP; 241 239 242 if (pj_stricmp(&local_m->desc.transport, &ID_RTP_AVP) == 0) { 243 244 si->proto = PJMEDIA_TP_PROTO_RTP_AVP; 245 246 } else if (pj_stristr(&local_m->desc.transport, &ID_RTP_SAVP)) { 247 248 si->proto = PJMEDIA_TP_PROTO_RTP_SAVP; 249 250 } else { 251 252 si->proto = PJMEDIA_TP_PROTO_UNKNOWN; 240 /* Get the transport protocol */ 241 si->proto = pjmedia_sdp_transport_get_proto(&local_m->desc.transport); 242 243 /* Return success if transport protocol is not RTP/AVP compatible */ 244 if (!PJMEDIA_TP_PROTO_HAS_FLAG(si->proto, PJMEDIA_TP_PROTO_RTP_AVP)) 253 245 return PJ_SUCCESS; 254 }255 246 256 247 -
pjproject/trunk/pjsip-apps/src/swig/symbols.i
r5807 r5820 110 110 typedef enum pjmedia_vid_packing {PJMEDIA_VID_PACKING_UNKNOWN, PJMEDIA_VID_PACKING_PACKETS = 1, PJMEDIA_VID_PACKING_WHOLE = 2} pjmedia_vid_packing; 111 111 112 typedef enum pjmedia_rtcp_fb_type {PJMEDIA_RTCP_FB_ACK, PJMEDIA_RTCP_FB_NACK, PJMEDIA_RTCP_FB_TRR_INT, PJMEDIA_RTCP_FB_OTHER} pjmedia_rtcp_fb_type; 113 112 114 typedef enum pjsip_cred_data_type {PJSIP_CRED_DATA_PLAIN_PASSWD = 0, PJSIP_CRED_DATA_DIGEST = 1, PJSIP_CRED_DATA_EXT_AKA = 16} pjsip_cred_data_type; 113 115 -
pjproject/trunk/pjsip-apps/src/swig/symbols.lst
r5755 r5820 18 18 pjmedia/format.h pjmedia_format_id 19 19 pjmedia/vid_codec.h pjmedia_vid_packing 20 pjmedia/rtcp_fb.h pjmedia_rtcp_fb_type 20 21 21 22 pjsip/sip_auth.h pjsip_cred_data_type -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r5792 r5820 3913 3913 pj_bool_t enable_rtcp_mux; 3914 3914 3915 /** 3916 * RTCP Feedback configuration. 3917 */ 3918 pjmedia_rtcp_fb_setting rtcp_fb_cfg; 3919 3915 3920 } pjsua_acc_config; 3916 3921 -
pjproject/trunk/pjsip/include/pjsua2/account.hpp
r5801 r5820 738 738 typedef std::vector<SrtpCrypto> SrtpCryptoVector; 739 739 740 /** 741 * SRTP settings. 742 */ 740 743 struct SrtpOpt : public PersistentObject 741 744 { … … 772 775 */ 773 776 pjsua_srtp_opt toPj() const; 777 778 public: 779 /** 780 * Read this object from a container node. 781 * 782 * @param node Container to read values from. 783 */ 784 virtual void readObject(const ContainerNode &node) throw(Error); 785 786 /** 787 * Write this object to a container node. 788 * 789 * @param node Container to write values to. 790 */ 791 virtual void writeObject(ContainerNode &node) const throw(Error); 792 }; 793 794 /** 795 * RTCP Feedback capability. 796 */ 797 struct RtcpFbCap 798 { 799 /** 800 * Specify the codecs to which the capability is applicable. Codec ID is 801 * using the same format as in pjmedia_codec_mgr_find_codecs_by_id() and 802 * pjmedia_vid_codec_mgr_find_codecs_by_id(), e.g: "L16/8000/1", "PCMU", 803 * "H264". This can also be an asterisk ("*") to represent all codecs. 804 */ 805 string codecId; 806 807 /** 808 * Specify the RTCP Feedback type. 809 */ 810 pjmedia_rtcp_fb_type type; 811 812 /** 813 * Specify the type name if RTCP Feedback type is PJMEDIA_RTCP_FB_OTHER. 814 */ 815 string typeName; 816 817 /** 818 * Specify the RTCP Feedback parameters. 819 */ 820 string param; 821 822 public: 823 /** 824 * Constructor. 825 */ 826 RtcpFbCap() : type(PJMEDIA_RTCP_FB_OTHER) 827 {} 828 829 /** 830 * Convert from pjsip 831 */ 832 void fromPj(const pjmedia_rtcp_fb_cap &prm); 833 834 /** 835 * Convert to pjsip 836 */ 837 pjmedia_rtcp_fb_cap toPj() const; 838 }; 839 840 /* Array of RTCP Feedback capabilities. */ 841 typedef std::vector<RtcpFbCap> RtcpFbCapVector; 842 843 844 /** 845 * RTCP Feedback settings. 846 */ 847 struct RtcpFbConfig : public PersistentObject 848 { 849 /** 850 * Specify whether transport protocol in SDP media description uses 851 * RTP/AVP instead of RTP/AVPF. Note that the standard mandates to signal 852 * AVPF profile, but it may cause SDP negotiation failure when negotiating 853 * with endpoints that does not support RTCP Feedback (including older 854 * version of PJSIP). 855 * 856 * Default: false. 857 */ 858 bool dontUseAvpf; 859 860 /** 861 * RTCP Feedback capabilities. 862 */ 863 RtcpFbCapVector caps; 864 865 public: 866 /** 867 * Constructor. 868 */ 869 RtcpFbConfig(); 870 871 /** 872 * Convert from pjsip 873 */ 874 void fromPj(const pjmedia_rtcp_fb_setting &prm); 875 876 /** 877 * Convert to pjsip 878 */ 879 pjmedia_rtcp_fb_setting toPj() const; 774 880 775 881 public: … … 854 960 */ 855 961 bool rtcpMuxEnabled; 962 963 /** 964 * RTCP Feedback settings. 965 */ 966 RtcpFbConfig rtcpFbConfig; 856 967 857 968 public: -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
r5805 r5820 141 141 142 142 pj_strdup(pool, &dst->ka_data, &src->ka_data); 143 144 pjmedia_rtcp_fb_setting_dup(pool, &dst->rtcp_fb_cfg, &src->rtcp_fb_cfg); 143 145 } 144 146 … … 1433 1435 acc->cfg.ip_change_cfg.hangup_calls = cfg->ip_change_cfg.hangup_calls; 1434 1436 acc->cfg.ip_change_cfg.reinvite_flags = cfg->ip_change_cfg.reinvite_flags; 1437 1438 /* RTCP-FB config */ 1439 pjmedia_rtcp_fb_setting_dup(acc->pool, &acc->cfg.rtcp_fb_cfg, 1440 &cfg->rtcp_fb_cfg); 1435 1441 1436 1442 on_return: -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r5813 r5820 292 292 pjsua_transport_config_default(&cfg->rtp_cfg); 293 293 cfg->rtp_cfg.port = DEFAULT_RTP_PORT; 294 pjmedia_rtcp_fb_setting_default(&cfg->rtcp_fb_cfg); 294 295 295 296 pjsua_media_config_default(&med_cfg); -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r5788 r5820 2258 2258 pj_sockaddr origin; 2259 2259 pjsua_call *call = &pjsua_var.calls[call_id]; 2260 pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; 2260 2261 pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL; 2261 2262 unsigned mi; … … 2484 2485 } 2485 2486 } 2487 2488 /* Add RTCP-FB info in SDP if we are offerer */ 2489 if (rem_sdp == NULL && acc->cfg.rtcp_fb_cfg.cap_count) { 2490 status = pjmedia_rtcp_fb_encode_sdp(pool, pjsua_var.med_endpt, 2491 &acc->cfg.rtcp_fb_cfg, sdp, 2492 mi, rem_sdp); 2493 if (status != PJ_SUCCESS) { 2494 PJ_PERROR(3,(THIS_FILE, status, 2495 "Call %d media %d: Failed to encode RTCP-FB " 2496 "setting to SDP", 2497 call_id, mi)); 2498 } 2499 } 2486 2500 } 2487 2501 … … 2529 2543 sdp->bandw[sdp->bandw_count++] = b; 2530 2544 } 2531 2532 2545 2533 2546 #if DISABLED_FOR_TICKET_1185 && defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) … … 2961 2974 #endif 2962 2975 2963 /* Applying media count limitation. Note that in generating SDP answer, 2964 * no media count limitation applied, as we didn't know yet which media 2965 * would pass the SDP negotiation. 2976 /* We need to re-nego SDP or modify our answer when: 2977 * - media count exceeds the configured limit, 2978 * - RTCP-FB is enabled (so a=rtcp-fb will only be printed for negotiated 2979 * codecs) 2966 2980 */ 2967 if (maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt) 2981 if (!pjmedia_sdp_neg_was_answer_remote(call->inv->neg) && 2982 ((maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt) || 2983 (acc->cfg.rtcp_fb_cfg.cap_count))) 2968 2984 { 2969 pjmedia_sdp_session *local_sdp2; 2970 2971 maudcnt = PJ_MIN(maudcnt, call->opt.aud_cnt); 2972 mvidcnt = PJ_MIN(mvidcnt, call->opt.vid_cnt); 2973 local_sdp2 = pjmedia_sdp_session_clone(tmp_pool, local_sdp); 2974 2975 for (mi=0; mi < local_sdp2->media_count; ++mi) { 2976 pjmedia_sdp_media *m = local_sdp2->media[mi]; 2977 2978 if (m->desc.port == 0 || 2979 pj_memchr(maudidx, mi, maudcnt*sizeof(maudidx[0])) || 2980 pj_memchr(mvididx, mi, mvidcnt*sizeof(mvididx[0]))) 2981 { 2982 continue; 2983 } 2984 2985 /* Deactivate this media */ 2986 pjmedia_sdp_media_deactivate(tmp_pool, m); 2987 } 2988 2989 local_sdp = local_sdp2; 2985 pjmedia_sdp_session *local_sdp_renego = NULL; 2986 2987 local_sdp_renego = pjmedia_sdp_session_clone(tmp_pool, local_sdp); 2988 local_sdp = local_sdp_renego; 2990 2989 need_renego_sdp = PJ_TRUE; 2990 2991 /* Add RTCP-FB info into local SDP answer */ 2992 if (acc->cfg.rtcp_fb_cfg.cap_count) { 2993 for (mi=0; mi < local_sdp_renego->media_count; ++mi) { 2994 status = pjmedia_rtcp_fb_encode_sdp( 2995 tmp_pool, pjsua_var.med_endpt, 2996 &acc->cfg.rtcp_fb_cfg, 2997 local_sdp_renego, mi, remote_sdp); 2998 if (status != PJ_SUCCESS) { 2999 PJ_PERROR(3,(THIS_FILE, status, 3000 "Call %d media %d: Failed to encode RTCP-FB " 3001 "setting to SDP", 3002 call_id, mi)); 3003 } 3004 } 3005 } 3006 3007 /* Applying media count limitation. Note that in generating SDP 3008 * answer, no media count limitation applied as we didn't know yet 3009 * which media would pass the SDP negotiation. 3010 */ 3011 if (maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt) 3012 { 3013 maudcnt = PJ_MIN(maudcnt, call->opt.aud_cnt); 3014 mvidcnt = PJ_MIN(mvidcnt, call->opt.vid_cnt); 3015 3016 for (mi=0; mi < local_sdp_renego->media_count; ++mi) { 3017 pjmedia_sdp_media *m = local_sdp_renego->media[mi]; 3018 3019 if (m->desc.port == 0 || 3020 pj_memchr(maudidx, mi, maudcnt*sizeof(maudidx[0])) || 3021 pj_memchr(mvididx, mi, mvidcnt*sizeof(mvididx[0]))) 3022 { 3023 continue; 3024 } 3025 3026 /* Deactivate this excess media */ 3027 pjmedia_sdp_media_deactivate(tmp_pool, m); 3028 } 3029 } 2991 3030 } 2992 3031 … … 3389 3428 sizeof(call->media_prov[0]) * call->med_prov_cnt); 3390 3429 3391 /* Perform SDP re-negotiation if some media have just got disabled 3392 * in this function due to media count limit settings. 3393 */ 3430 /* Perform SDP re-negotiation. */ 3394 3431 if (got_media && need_renego_sdp) { 3395 3432 pjmedia_sdp_neg *neg = call->inv->neg; 3396 3433 3397 /* This should only happen when we are the answerer. */3398 PJ_ASSERT_RETURN(neg && !pjmedia_sdp_neg_was_answer_remote(neg),3399 PJMEDIA_SDPNEG_EINSTATE);3400 3401 3434 status = pjmedia_sdp_neg_set_remote_offer(tmp_pool, neg, remote_sdp); 3402 3435 if (status != PJ_SUCCESS) -
pjproject/trunk/pjsip/src/pjsua2/account.cpp
r5801 r5820 27 27 28 28 #define THIS_FILE "account.cpp" 29 30 /////////////////////////////////////////////////////////////////////////////// 31 32 void RtcpFbCap::fromPj(const pjmedia_rtcp_fb_cap &prm) 33 { 34 this->codecId = pj2Str(prm.codec_id); 35 this->type = prm.type; 36 this->typeName = pj2Str(prm.type_name); 37 this->param = pj2Str(prm.param); 38 } 39 40 pjmedia_rtcp_fb_cap RtcpFbCap::toPj() const 41 { 42 pjmedia_rtcp_fb_cap cap; 43 44 pj_bzero(&cap, sizeof(cap)); 45 cap.codec_id = str2Pj(this->codecId); 46 cap.type = this->type; 47 cap.type_name = str2Pj(this->typeName); 48 cap.param = str2Pj(this->param); 49 50 return cap; 51 } 52 53 /////////////////////////////////////////////////////////////////////////////// 54 55 RtcpFbConfig::RtcpFbConfig() 56 { 57 pjmedia_rtcp_fb_setting setting; 58 pjmedia_rtcp_fb_setting_default(&setting); 59 fromPj(setting); 60 } 61 62 void RtcpFbConfig::fromPj(const pjmedia_rtcp_fb_setting &prm) 63 { 64 this->dontUseAvpf = PJ2BOOL(prm.dont_use_avpf); 65 this->caps.clear(); 66 for (unsigned i = 0; i < prm.cap_count; ++i) { 67 RtcpFbCap cap; 68 cap.fromPj(prm.caps[i]); 69 this->caps.push_back(cap); 70 } 71 } 72 73 pjmedia_rtcp_fb_setting RtcpFbConfig::toPj() const 74 { 75 pjmedia_rtcp_fb_setting setting; 76 77 pj_bzero(&setting, sizeof(setting)); 78 setting.dont_use_avpf = this->dontUseAvpf; 79 setting.cap_count = this->caps.size(); 80 for (unsigned i = 0; i < setting.cap_count; ++i) { 81 setting.caps[i] = this->caps[i].toPj(); 82 } 83 84 return setting; 85 } 86 87 void RtcpFbConfig::readObject(const ContainerNode &node) throw(Error) 88 { 89 ContainerNode this_node = node.readContainer("RtcpFbConfig"); 90 NODE_READ_BOOL (this_node, dontUseAvpf); 91 92 ContainerNode cap_node = this_node.readArray("caps"); 93 this->caps.clear(); 94 while (cap_node.hasUnread()) { 95 RtcpFbCap cap; 96 NODE_READ_STRING (cap_node, cap.codecId); 97 NODE_READ_NUM_T (cap_node, pjmedia_rtcp_fb_type, cap.type); 98 NODE_READ_STRING (cap_node, cap.typeName); 99 NODE_READ_STRING (cap_node, cap.param); 100 this->caps.push_back(cap); 101 } 102 } 103 104 void RtcpFbConfig::writeObject(ContainerNode &node) const throw(Error) 105 { 106 ContainerNode this_node = node.writeNewContainer("RtcpFbConfig"); 107 NODE_WRITE_BOOL (this_node, dontUseAvpf); 108 109 ContainerNode cap_node = this_node.writeNewArray("caps"); 110 for (unsigned i=0; i<this->caps.size(); ++i) { 111 NODE_WRITE_STRING (cap_node, this->caps[i].codecId); 112 NODE_WRITE_NUM_T (cap_node, pjmedia_rtcp_fb_type, 113 this->caps[i].type); 114 NODE_WRITE_STRING (cap_node, this->caps[i].typeName); 115 NODE_WRITE_STRING (cap_node, this->caps[i].param); 116 } 117 } 29 118 30 119 ///////////////////////////////////////////////////////////////////////////////
Note: See TracChangeset
for help on using the changeset viewer.