Changeset 3960
- Timestamp:
- Feb 27, 2012 2:41:21 PM (13 years ago)
- Location:
- pjproject/branches/1.x/pjmedia
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/1.x/pjmedia/include/pjmedia/config.h
r3907 r3960 490 490 * PJMEDIA_STREAM_ENABLE_XR setting for more info. 491 491 * 492 * Default: 1 (yes).492 * Default: 0 (no). 493 493 */ 494 494 #ifndef PJMEDIA_HAS_RTCP_XR … … 507 507 # define PJMEDIA_STREAM_ENABLE_XR 0 508 508 #endif 509 510 511 /** 512 * Specify the buffer length for storing any received RTCP SDES text 513 * in a stream session. Usually RTCP contains only the mandatory SDES 514 * field, i.e: CNAME. 515 * 516 * Default: 64 bytes. 517 */ 518 #ifndef PJMEDIA_RTCP_RX_SDES_BUF_LEN 519 # define PJMEDIA_RTCP_RX_SDES_BUF_LEN 64 520 #endif 521 509 522 510 523 /** -
pjproject/branches/1.x/pjmedia/include/pjmedia/rtcp.h
r3553 r3960 55 55 */ 56 56 57 57 58 #pragma pack(1) 58 59 … … 60 61 * RTCP sender report. 61 62 */ 62 struct pjmedia_rtcp_sr63 typedef struct pjmedia_rtcp_sr 63 64 { 64 65 pj_uint32_t ntp_sec; /**< NTP time, seconds part. */ … … 67 68 pj_uint32_t sender_pcount; /**< Sender packet cound. */ 68 69 pj_uint32_t sender_bcount; /**< Sender octet/bytes count. */ 69 }; 70 71 /** 72 * @see pjmedia_rtcp_sr 73 */ 74 typedef struct pjmedia_rtcp_sr pjmedia_rtcp_sr; 70 } pjmedia_rtcp_sr; 71 75 72 76 73 /** 77 74 * RTCP receiver report. 78 75 */ 79 struct pjmedia_rtcp_rr76 typedef struct pjmedia_rtcp_rr 80 77 { 81 78 pj_uint32_t ssrc; /**< SSRC identification. */ … … 95 92 pj_uint32_t lsr; /**< Last SR. */ 96 93 pj_uint32_t dlsr; /**< Delay since last SR. */ 97 }; 98 99 /** 100 * @see pjmedia_rtcp_rr 101 */ 102 typedef struct pjmedia_rtcp_rr pjmedia_rtcp_rr; 94 } pjmedia_rtcp_rr; 103 95 104 96 … … 106 98 * RTCP common header. 107 99 */ 108 struct pjmedia_rtcp_common100 typedef struct pjmedia_rtcp_common 109 101 { 110 102 #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 … … 121 113 unsigned length:16; /**< packet length */ 122 114 pj_uint32_t ssrc; /**< SSRC identification */ 123 }; 124 125 /** 126 * @see pjmedia_rtcp_common 127 */ 128 typedef struct pjmedia_rtcp_common pjmedia_rtcp_common; 115 } pjmedia_rtcp_common; 116 129 117 130 118 /** … … 154 142 155 143 /** 144 * RTCP SDES structure. 145 */ 146 typedef struct pjmedia_rtcp_sdes 147 { 148 pj_str_t cname; /**< RTCP SDES type CNAME. */ 149 pj_str_t name; /**< RTCP SDES type NAME. */ 150 pj_str_t email; /**< RTCP SDES type EMAIL. */ 151 pj_str_t phone; /**< RTCP SDES type PHONE. */ 152 pj_str_t loc; /**< RTCP SDES type LOC. */ 153 pj_str_t tool; /**< RTCP SDES type TOOL. */ 154 pj_str_t note; /**< RTCP SDES type NOTE. */ 155 } pjmedia_rtcp_sdes; 156 157 158 /** 156 159 * NTP time representation. 157 160 */ 158 struct pjmedia_rtcp_ntp_rec161 typedef struct pjmedia_rtcp_ntp_rec 159 162 { 160 163 pj_uint32_t hi; /**< High order 32-bit part. */ 161 164 pj_uint32_t lo; /**< Lo order 32-bit part. */ 162 }; 163 164 /** 165 * @see pjmedia_rtcp_ntp_rec 166 */ 167 typedef struct pjmedia_rtcp_ntp_rec pjmedia_rtcp_ntp_rec; 168 165 } pjmedia_rtcp_ntp_rec; 169 166 170 167 … … 172 169 * Unidirectional RTP stream statistics. 173 170 */ 174 struct pjmedia_rtcp_stream_stat171 typedef struct pjmedia_rtcp_stream_stat 175 172 { 176 173 pj_time_val update; /**< Time of last update. */ … … 191 188 192 189 pj_math_stat jitter; /**< Jitter statistics (in usec) */ 193 }; 194 195 196 /** 197 * @see pjmedia_rtcp_stream_stat 198 */ 199 typedef struct pjmedia_rtcp_stream_stat pjmedia_rtcp_stream_stat; 200 190 191 } pjmedia_rtcp_stream_stat; 201 192 202 193 … … 204 195 * Bidirectional RTP stream statistics. 205 196 */ 206 struct pjmedia_rtcp_stat197 typedef struct pjmedia_rtcp_stat 207 198 { 208 199 pj_time_val start; /**< Time when session was created */ … … 227 218 (in usec). */ 228 219 #endif 229 }; 230 231 232 /** 233 * @see pjmedia_rtcp_stat 234 */ 235 typedef struct pjmedia_rtcp_stat pjmedia_rtcp_stat; 220 221 pjmedia_rtcp_sdes peer_sdes; /**< Peer SDES. */ 222 char peer_sdes_buf_[PJMEDIA_RTCP_RX_SDES_BUF_LEN]; 223 /**< Peer SDES buffer. */ 224 225 } pjmedia_rtcp_stat; 236 226 237 227 … … 240 230 * should only be one RTCP session for a bidirectional RTP streams. 241 231 */ 242 struct pjmedia_rtcp_session232 typedef struct pjmedia_rtcp_session 243 233 { 244 234 char *name; /**< Name identification. */ … … 279 269 pjmedia_rtcp_xr_session xr_session; 280 270 #endif 281 }; 282 283 /** 284 * @see pjmedia_rtcp_session 285 */ 286 typedef struct pjmedia_rtcp_session pjmedia_rtcp_session; 271 } pjmedia_rtcp_session; 287 272 288 273 … … 440 425 441 426 /** 427 * Build an RTCP SDES (source description) packet. This packet can be 428 * appended to other RTCP packets, e.g: RTCP RR/SR, to compose a compound 429 * RTCP packet. 430 * 431 * @param session The RTCP session. 432 * @param buf The buffer to receive RTCP SDES packet. 433 * @param length On input, it will contain the buffer length. 434 * On output, it will contain the generated RTCP SDES 435 * packet length. 436 * @param sdes The source description, see #pjmedia_rtcp_sdes. 437 * 438 * @return PJ_SUCCESS on success. 439 */ 440 PJ_DECL(pj_status_t) pjmedia_rtcp_build_rtcp_sdes( 441 pjmedia_rtcp_session *session, 442 void *buf, 443 pj_size_t *length, 444 const pjmedia_rtcp_sdes *sdes); 445 446 /** 447 * Build an RTCP BYE packet. This packet can be appended to other RTCP 448 * packets, e.g: RTCP RR/SR, to compose a compound RTCP packet. 449 * 450 * @param session The RTCP session. 451 * @param buf The buffer to receive RTCP BYE packet. 452 * @param length On input, it will contain the buffer length. 453 * On output, it will contain the generated RTCP BYE 454 * packet length. 455 * @param reason Optional, the BYE reason. 456 * 457 * @return PJ_SUCCESS on success. 458 */ 459 PJ_DECL(pj_status_t) pjmedia_rtcp_build_rtcp_bye( 460 pjmedia_rtcp_session *session, 461 void *buf, 462 pj_size_t *length, 463 const pj_str_t *reason); 464 465 466 /** 442 467 * Call this function if RTCP XR needs to be enabled/disabled in the 443 468 * RTCP session. -
pjproject/branches/1.x/pjmedia/src/pjmedia/rtcp.c
r3907 r3960 30 30 #define RTCP_SR 200 31 31 #define RTCP_RR 201 32 #define RTCP_SDES 202 33 #define RTCP_BYE 203 32 34 #define RTCP_XR 207 35 36 enum { 37 RTCP_SDES_NULL = 0, 38 RTCP_SDES_CNAME = 1, 39 RTCP_SDES_NAME = 2, 40 RTCP_SDES_EMAIL = 3, 41 RTCP_SDES_PHONE = 4, 42 RTCP_SDES_LOC = 5, 43 RTCP_SDES_TOOL = 6, 44 RTCP_SDES_NOTE = 7 45 }; 33 46 34 47 #if PJ_HAS_HIGH_RES_TIMER==0 … … 474 487 475 488 476 PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess,477 478 489 static void parse_rtcp_report( pjmedia_rtcp_session *sess, 490 const void *pkt, 491 pj_size_t size) 479 492 { 480 493 pjmedia_rtcp_common *common = (pjmedia_rtcp_common*) pkt; … … 653 666 654 667 668 static void parse_rtcp_sdes(pjmedia_rtcp_session *sess, 669 const void *pkt, 670 pj_size_t size) 671 { 672 pjmedia_rtcp_sdes *sdes = &sess->stat.peer_sdes; 673 char *p, *p_end; 674 char *b, *b_end; 675 676 p = (char*)pkt + 8; 677 p_end = (char*)pkt + size; 678 679 pj_bzero(sdes, sizeof(*sdes)); 680 b = sess->stat.peer_sdes_buf_; 681 b_end = b + sizeof(sess->stat.peer_sdes_buf_); 682 683 while (p < p_end) { 684 pj_uint8_t sdes_type, sdes_len; 685 pj_str_t sdes_value = {NULL, 0}; 686 687 sdes_type = *p++; 688 689 /* Check for end of SDES item list */ 690 if (sdes_type == RTCP_SDES_NULL || p == p_end) 691 break; 692 693 sdes_len = *p++; 694 695 /* Check for corrupted SDES packet */ 696 if (p + sdes_len > p_end) 697 break; 698 699 /* Get SDES item */ 700 if (b + sdes_len < b_end) { 701 pj_memcpy(b, p, sdes_len); 702 sdes_value.ptr = b; 703 sdes_value.slen = sdes_len; 704 b += sdes_len; 705 } else { 706 /* Insufficient SDES buffer */ 707 PJ_LOG(5, (sess->name, 708 "Unsufficient buffer to save RTCP SDES type %d:%.*s", 709 sdes_type, sdes_len, p)); 710 p += sdes_len; 711 continue; 712 } 713 714 switch (sdes_type) { 715 case RTCP_SDES_CNAME: 716 sdes->cname = sdes_value; 717 break; 718 case RTCP_SDES_NAME: 719 sdes->name = sdes_value; 720 break; 721 case RTCP_SDES_EMAIL: 722 sdes->email = sdes_value; 723 break; 724 case RTCP_SDES_PHONE: 725 sdes->phone = sdes_value; 726 break; 727 case RTCP_SDES_LOC: 728 sdes->loc = sdes_value; 729 break; 730 case RTCP_SDES_TOOL: 731 sdes->tool = sdes_value; 732 break; 733 case RTCP_SDES_NOTE: 734 sdes->note = sdes_value; 735 break; 736 default: 737 TRACE_((sess->name, "Received unknown RTCP SDES type %d:%.*s", 738 sdes_type, sdes_value.slen, sdes_value.ptr)); 739 break; 740 } 741 742 p += sdes_len; 743 } 744 } 745 746 747 static void parse_rtcp_bye(pjmedia_rtcp_session *sess, 748 const void *pkt, 749 pj_size_t size) 750 { 751 pj_str_t reason = {"-", 1}; 752 753 /* Check and get BYE reason */ 754 if (size > 8) { 755 reason.slen = *((pj_uint8_t*)pkt+8); 756 pj_memcpy(sess->stat.peer_sdes_buf_, ((pj_uint8_t*)pkt+9), 757 reason.slen); 758 reason.ptr = sess->stat.peer_sdes_buf_; 759 } 760 761 /* Just print RTCP BYE log */ 762 PJ_LOG(5, (sess->name, "Received RTCP BYE, reason: %.*s", 763 reason.slen, reason.ptr)); 764 } 765 766 767 PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess, 768 const void *pkt, 769 pj_size_t size) 770 { 771 pj_uint8_t *p, *p_end; 772 773 p = (pj_uint8_t*)pkt; 774 p_end = p + size; 775 while (p < p_end) { 776 pjmedia_rtcp_common *common = (pjmedia_rtcp_common*)p; 777 unsigned len; 778 779 len = (pj_ntohs((pj_uint16_t)common->length)+1) * 4; 780 switch(common->pt) { 781 case RTCP_SR: 782 case RTCP_RR: 783 case RTCP_XR: 784 parse_rtcp_report(sess, p, len); 785 break; 786 case RTCP_SDES: 787 parse_rtcp_sdes(sess, p, len); 788 break; 789 case RTCP_BYE: 790 parse_rtcp_bye(sess, p, len); 791 break; 792 default: 793 /* Ignore unknown RTCP */ 794 TRACE_((sess->name, "Received unknown RTCP packet type=%d", 795 common->pt)); 796 break; 797 } 798 799 p += len; 800 } 801 } 802 803 655 804 PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess, 656 805 void **ret_p_pkt, int *len) … … 805 954 } 806 955 956 957 PJ_DEF(pj_status_t) pjmedia_rtcp_build_rtcp_sdes( 958 pjmedia_rtcp_session *session, 959 void *buf, 960 pj_size_t *length, 961 const pjmedia_rtcp_sdes *sdes) 962 { 963 pjmedia_rtcp_common *hdr; 964 pj_uint8_t *p; 965 unsigned len; 966 967 PJ_ASSERT_RETURN(session && buf && length && sdes, PJ_EINVAL); 968 969 /* Verify SDES item length */ 970 if (sdes->cname.slen > 255 || sdes->name.slen > 255 || 971 sdes->email.slen > 255 || sdes->phone.slen > 255 || 972 sdes->loc.slen > 255 || sdes->tool.slen > 255 || 973 sdes->note.slen > 255) 974 { 975 return PJ_EINVAL; 976 } 977 978 /* Verify buffer length */ 979 len = sizeof(*hdr); 980 if (sdes->cname.slen) len += sdes->cname.slen + 2; 981 if (sdes->name.slen) len += sdes->name.slen + 2; 982 if (sdes->email.slen) len += sdes->email.slen + 2; 983 if (sdes->phone.slen) len += sdes->phone.slen + 2; 984 if (sdes->loc.slen) len += sdes->loc.slen + 2; 985 if (sdes->tool.slen) len += sdes->tool.slen + 2; 986 if (sdes->note.slen) len += sdes->note.slen + 2; 987 len++; /* null termination */ 988 len = ((len+3)/4) * 4; 989 if (len > *length) 990 return PJ_ETOOSMALL; 991 992 /* Build RTCP SDES header */ 993 hdr = (pjmedia_rtcp_common*)buf; 994 pj_memcpy(hdr, &session->rtcp_sr_pkt.common, sizeof(*hdr)); 995 hdr->pt = RTCP_SDES; 996 hdr->length = pj_htons((pj_uint16_t)(len/4 - 1)); 997 998 /* Build RTCP SDES items */ 999 p = (pj_uint8_t*)hdr + sizeof(*hdr); 1000 #define BUILD_SDES_ITEM(SDES_NAME, SDES_TYPE) \ 1001 if (sdes->SDES_NAME.slen) { \ 1002 *p++ = SDES_TYPE; \ 1003 *p++ = (pj_uint8_t)sdes->SDES_NAME.slen; \ 1004 pj_memcpy(p, sdes->SDES_NAME.ptr, sdes->SDES_NAME.slen); \ 1005 p += sdes->SDES_NAME.slen; \ 1006 } 1007 BUILD_SDES_ITEM(cname, RTCP_SDES_CNAME); 1008 BUILD_SDES_ITEM(name, RTCP_SDES_NAME); 1009 BUILD_SDES_ITEM(email, RTCP_SDES_EMAIL); 1010 BUILD_SDES_ITEM(phone, RTCP_SDES_PHONE); 1011 BUILD_SDES_ITEM(loc, RTCP_SDES_LOC); 1012 BUILD_SDES_ITEM(tool, RTCP_SDES_TOOL); 1013 BUILD_SDES_ITEM(note, RTCP_SDES_NOTE); 1014 #undef BUILD_SDES_ITEM 1015 1016 /* Null termination */ 1017 *p++ = 0; 1018 1019 /* Pad to 32bit */ 1020 while ((p-(pj_uint8_t*)buf) % 4) 1021 *p++ = 0; 1022 1023 /* Finally */ 1024 pj_assert((int)len == p-(pj_uint8_t*)buf); 1025 *length = len; 1026 1027 return PJ_SUCCESS; 1028 } 1029 1030 1031 PJ_DEF(pj_status_t) pjmedia_rtcp_build_rtcp_bye(pjmedia_rtcp_session *session, 1032 void *buf, 1033 pj_size_t *length, 1034 const pj_str_t *reason) 1035 { 1036 pjmedia_rtcp_common *hdr; 1037 pj_uint8_t *p; 1038 unsigned len; 1039 1040 PJ_ASSERT_RETURN(session && buf && length, PJ_EINVAL); 1041 1042 /* Verify BYE reason length */ 1043 if (reason && reason->slen > 255) 1044 return PJ_EINVAL; 1045 1046 /* Verify buffer length */ 1047 len = sizeof(*hdr); 1048 if (reason && reason->slen) len += reason->slen + 1; 1049 len = ((len+3)/4) * 4; 1050 if (len > *length) 1051 return PJ_ETOOSMALL; 1052 1053 /* Build RTCP BYE header */ 1054 hdr = (pjmedia_rtcp_common*)buf; 1055 pj_memcpy(hdr, &session->rtcp_sr_pkt.common, sizeof(*hdr)); 1056 hdr->pt = RTCP_BYE; 1057 hdr->length = pj_htons((pj_uint16_t)(len/4 - 1)); 1058 1059 /* Write RTCP BYE reason */ 1060 p = (pj_uint8_t*)hdr + sizeof(*hdr); 1061 if (reason && reason->slen) { 1062 *p++ = (pj_uint8_t)reason->slen; 1063 pj_memcpy(p, reason->ptr, reason->slen); 1064 p += reason->slen; 1065 } 1066 1067 /* Pad to 32bit */ 1068 while ((p-(pj_uint8_t*)buf) % 4) 1069 *p++ = 0; 1070 1071 pj_assert((int)len == p-(pj_uint8_t*)buf); 1072 *length = len; 1073 1074 return PJ_SUCCESS; 1075 } 1076 1077 807 1078 PJ_DEF(pj_status_t) pjmedia_rtcp_enable_xr( pjmedia_rtcp_session *sess, 808 1079 pj_bool_t enable) -
pjproject/branches/1.x/pjmedia/src/pjmedia/stream.c
r3900 r3960 235 235 236 236 237 static pj_status_t send_rtcp(pjmedia_stream *stream, 238 pj_bool_t with_sdes, 239 pj_bool_t with_bye, 240 pj_bool_t with_xr); 241 242 237 243 #if TRACE_JB 238 244 … … 415 421 416 422 /* Send RTCP */ 417 pjmedia_rtcp_build_rtcp(&stream->rtcp, &pkt, &pkt_len); 418 pjmedia_transport_send_rtcp(stream->transport, pkt, pkt_len); 423 send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE); 419 424 420 425 #elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER … … 904 909 905 910 911 static pj_status_t send_rtcp(pjmedia_stream *stream, 912 pj_bool_t with_sdes, 913 pj_bool_t with_bye, 914 pj_bool_t with_xr) 915 { 916 void *sr_rr_pkt; 917 pj_uint8_t *pkt; 918 int len, max_len; 919 pj_status_t status; 920 921 /* Build RTCP RR/SR packet */ 922 pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); 923 924 #if !defined(PJMEDIA_HAS_RTCP_XR) || (PJMEDIA_HAS_RTCP_XR == 0) 925 with_xr = PJ_FALSE; 926 #endif 927 928 if (with_sdes || with_bye || with_xr) { 929 pkt = (pj_uint8_t*) stream->enc->out_pkt; 930 pj_memcpy(pkt, sr_rr_pkt, len); 931 max_len = stream->enc->out_pkt_size; 932 } else { 933 pkt = sr_rr_pkt; 934 max_len = len; 935 } 936 937 /* Build RTCP SDES packet */ 938 if (with_sdes) { 939 pjmedia_rtcp_sdes sdes; 940 unsigned sdes_len; 941 942 pj_bzero(&sdes, sizeof(sdes)); 943 sdes.cname = stream->cname; 944 sdes_len = max_len - len; 945 status = pjmedia_rtcp_build_rtcp_sdes(&stream->rtcp, pkt+len, 946 &sdes_len, &sdes); 947 if (status != PJ_SUCCESS) { 948 PJ_PERROR(4,(stream->port.info.name.ptr, status, 949 "Error generating RTCP SDES")); 950 } else { 951 len += sdes_len; 952 } 953 } 954 955 /* Build RTCP XR packet */ 956 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 957 if (with_xr) { 958 int i; 959 pjmedia_jb_state jb_state; 960 void *xr_pkt; 961 int xr_len; 962 963 /* Update RTCP XR with current JB states */ 964 pjmedia_jbuf_get_state(stream->jb, &jb_state); 965 966 i = jb_state.avg_delay; 967 status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 968 PJMEDIA_RTCP_XR_INFO_JB_NOM, i); 969 pj_assert(status == PJ_SUCCESS); 970 971 i = jb_state.max_delay; 972 status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 973 PJMEDIA_RTCP_XR_INFO_JB_MAX, i); 974 pj_assert(status == PJ_SUCCESS); 975 976 pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0, 977 &xr_pkt, &xr_len); 978 979 if (xr_len + len <= max_len) { 980 pj_memcpy(pkt+len, xr_pkt, xr_len); 981 len += xr_len; 982 983 /* Send the RTCP XR to third-party destination if specified */ 984 if (stream->rtcp_xr_dest_len) { 985 pjmedia_transport_send_rtcp2(stream->transport, 986 &stream->rtcp_xr_dest, 987 stream->rtcp_xr_dest_len, 988 xr_pkt, xr_len); 989 } 990 991 } else { 992 PJ_PERROR(4,(stream->port.info.name.ptr, PJ_ETOOBIG, 993 "Error generating RTCP-XR")); 994 } 995 } 996 #endif 997 998 /* Build RTCP BYE packet */ 999 if (with_bye) { 1000 unsigned bye_len; 1001 1002 bye_len = max_len - len; 1003 status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len, 1004 &bye_len, NULL); 1005 if (status != PJ_SUCCESS) { 1006 PJ_PERROR(4,(stream->port.info.name.ptr, status, 1007 "Error generating RTCP BYE")); 1008 } else { 1009 len += bye_len; 1010 } 1011 } 1012 1013 /* Send! */ 1014 status = pjmedia_transport_send_rtcp(stream->transport, pkt, len); 1015 1016 return status; 1017 } 1018 906 1019 /** 907 1020 * check_tx_rtcp() … … 917 1030 */ 918 1031 919 920 1032 if (stream->rtcp_last_tx == 0) { 921 1033 … … 923 1035 924 1036 } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) { 925 926 void *rtcp_pkt; 927 int len; 1037 pj_bool_t with_xr = PJ_FALSE; 928 1038 pj_status_t status; 929 1039 930 pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len); 931 932 status=pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len); 1040 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 1041 if (stream->rtcp.xr_enabled) { 1042 if (stream->rtcp_xr_last_tx == 0) { 1043 stream->rtcp_xr_last_tx = timestamp; 1044 } else if (timestamp - stream->rtcp_xr_last_tx >= 1045 stream->rtcp_xr_interval) 1046 { 1047 with_xr = PJ_TRUE; 1048 1049 /* Update last tx RTCP XR */ 1050 stream->rtcp_xr_last_tx = timestamp; 1051 } 1052 } 1053 #endif 1054 1055 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE, 1056 with_xr); 933 1057 if (status != PJ_SUCCESS) { 934 1058 PJ_PERROR(4,(stream->port.info.name.ptr, status, 935 1059 "Error sending RTCP")); 936 1060 } 937 1061 938 1062 stream->rtcp_last_tx = timestamp; 939 1063 } 940 941 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)942 if (stream->rtcp.xr_enabled) {943 944 if (stream->rtcp_xr_last_tx == 0) {945 946 stream->rtcp_xr_last_tx = timestamp;947 948 } else if (timestamp - stream->rtcp_xr_last_tx >=949 stream->rtcp_xr_interval)950 {951 int i;952 pjmedia_jb_state jb_state;953 void *rtcp_pkt;954 int len;955 956 /* Update RTCP XR with current JB states */957 pjmedia_jbuf_get_state(stream->jb, &jb_state);958 959 i = jb_state.avg_delay;960 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,961 PJMEDIA_RTCP_XR_INFO_JB_NOM,962 i);963 964 i = jb_state.max_delay;965 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,966 PJMEDIA_RTCP_XR_INFO_JB_MAX,967 i);968 969 /* Build RTCP XR packet */970 pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0,971 &rtcp_pkt, &len);972 973 /* Send the RTCP XR to remote address */974 pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len);975 976 /* Send the RTCP XR to third-party destination if specified */977 if (stream->rtcp_xr_dest_len) {978 pjmedia_transport_send_rtcp2(stream->transport,979 &stream->rtcp_xr_dest,980 stream->rtcp_xr_dest_len,981 rtcp_pkt, len);982 }983 984 /* Update last tx RTCP XR */985 stream->rtcp_xr_last_tx = timestamp;986 }987 }988 #endif989 }990 991 /* Build RTCP SDES packet */992 static unsigned create_rtcp_sdes(pjmedia_stream *stream, pj_uint8_t *pkt,993 unsigned max_len)994 {995 pjmedia_rtcp_common hdr;996 pj_uint8_t *p = pkt;997 998 /* SDES header */999 hdr.version = 2;1000 hdr.p = 0;1001 hdr.count = 1;1002 hdr.pt = 202;1003 hdr.length = 2 + (4+stream->cname.slen+3)/4 - 1;1004 if (max_len < (hdr.length << 2)) {1005 pj_assert(!"Not enough buffer for SDES packet");1006 return 0;1007 }1008 hdr.length = pj_htons((pj_uint16_t)hdr.length);1009 hdr.ssrc = stream->enc->rtp.out_hdr.ssrc;1010 pj_memcpy(p, &hdr, sizeof(hdr));1011 p += sizeof(hdr);1012 1013 /* CNAME item */1014 *p++ = 1;1015 *p++ = (pj_uint8_t)stream->cname.slen;1016 pj_memcpy(p, stream->cname.ptr, stream->cname.slen);1017 p += stream->cname.slen;1018 1019 /* END */1020 *p++ = '\0';1021 *p++ = '\0';1022 1023 /* Pad to 32bit */1024 while ((p-pkt) % 4)1025 *p++ = '\0';1026 1027 return (p - pkt);1028 }1029 1030 /* Build RTCP BYE packet */1031 static unsigned create_rtcp_bye(pjmedia_stream *stream, pj_uint8_t *pkt,1032 unsigned max_len)1033 {1034 pjmedia_rtcp_common hdr;1035 1036 /* BYE header */1037 hdr.version = 2;1038 hdr.p = 0;1039 hdr.count = 1;1040 hdr.pt = 203;1041 hdr.length = 1;1042 if (max_len < (hdr.length << 2)) {1043 pj_assert(!"Not enough buffer for SDES packet");1044 return 0;1045 }1046 hdr.length = pj_htons((pj_uint16_t)hdr.length);1047 hdr.ssrc = stream->enc->rtp.out_hdr.ssrc;1048 pj_memcpy(pkt, &hdr, sizeof(hdr));1049 1050 return sizeof(hdr);1051 1064 } 1052 1065 … … 1832 1845 /* Send RTCP RR and SDES after we receive some RTP packets */ 1833 1846 if (stream->rtcp.received >= 10 && !stream->initial_rr) { 1834 void *sr_rr_pkt; 1835 pj_uint8_t *pkt; 1836 int len; 1837 1838 /* Build RR or SR */ 1839 pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); 1840 1841 if (!stream->rtcp_sdes_bye_disabled) { 1842 pkt = (pj_uint8_t*) stream->enc->out_pkt; 1843 pj_memcpy(pkt, sr_rr_pkt, len); 1844 pkt += len; 1845 1846 /* Append SDES */ 1847 len = create_rtcp_sdes(stream, (pj_uint8_t*)pkt, 1848 stream->enc->out_pkt_size - len); 1849 if (len > 0) { 1850 pkt += len; 1851 len = ((pj_uint8_t*)pkt) - ((pj_uint8_t*)stream->enc->out_pkt); 1852 status = pjmedia_transport_send_rtcp(stream->transport, 1853 stream->enc->out_pkt, 1854 len); 1855 if (status != PJ_SUCCESS) { 1856 PJ_PERROR(4,(stream->port.info.name.ptr, status, 1857 "Error sending RTCP SDES")); 1858 } 1859 } 1860 } else { 1861 status = pjmedia_transport_send_rtcp(stream->transport, 1862 sr_rr_pkt, len); 1863 if (status != PJ_SUCCESS) { 1864 PJ_PERROR(4,(stream->port.info.name.ptr, status, 1865 "Error sending initial RTCP RR")); 1866 } 1867 } 1868 1869 stream->initial_rr = PJ_TRUE; 1847 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, 1848 PJ_FALSE, PJ_FALSE); 1849 if (status != PJ_SUCCESS) { 1850 PJ_PERROR(4,(stream->port.info.name.ptr, status, 1851 "Error sending initial RTCP RR")); 1852 } else { 1853 stream->initial_rr = PJ_TRUE; 1854 } 1870 1855 } 1871 1856 } … … 2401 2386 PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 2402 2387 2403 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 2404 /* Send RTCP XR on stream destroy */ 2405 if (stream->rtcp.xr_enabled) { 2406 int i; 2407 pjmedia_jb_state jb_state; 2408 void *rtcp_pkt; 2409 int len; 2410 2411 /* Update RTCP XR with current JB states */ 2412 pjmedia_jbuf_get_state(stream->jb, &jb_state); 2413 2414 i = jb_state.avg_delay; 2415 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2416 PJMEDIA_RTCP_XR_INFO_JB_NOM, 2417 i); 2418 2419 i = jb_state.max_delay; 2420 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2421 PJMEDIA_RTCP_XR_INFO_JB_MAX, 2422 i); 2423 2424 /* Build RTCP XR packet */ 2425 pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0, 2426 &rtcp_pkt, &len); 2427 2428 /* Send the RTCP XR to remote address */ 2429 pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len); 2430 2431 /* Send the RTCP XR to third-party destination if specified */ 2432 if (stream->rtcp_xr_dest_len) { 2433 pjmedia_transport_send_rtcp2(stream->transport, 2434 &stream->rtcp_xr_dest, 2435 stream->rtcp_xr_dest_len, 2436 rtcp_pkt, len); 2437 } 2438 } 2439 #endif 2440 2441 /* Send RTCP BYE */ 2388 /* Send RTCP BYE (also SDES & XR) */ 2442 2389 if (!stream->rtcp_sdes_bye_disabled) { 2443 pjmedia_stream_send_rtcp_bye(stream);2390 send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE); 2444 2391 } 2445 2392 … … 2795 2742 pjmedia_stream_send_rtcp_sdes( pjmedia_stream *stream ) 2796 2743 { 2797 unsigned len;2798 2799 2744 PJ_ASSERT_RETURN(stream, PJ_EINVAL); 2800 2745 2801 len = create_rtcp_sdes(stream, (pj_uint8_t*)stream->enc->out_pkt, 2802 stream->enc->out_pkt_size); 2803 if (len != 0) { 2804 return pjmedia_transport_send_rtcp(stream->transport, 2805 stream->enc->out_pkt, len); 2806 } 2807 2808 return PJ_SUCCESS; 2746 return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE); 2809 2747 } 2810 2748 … … 2818 2756 2819 2757 if (stream->enc && stream->transport) { 2820 unsigned len; 2821 2822 len = create_rtcp_bye(stream, (pj_uint8_t*)stream->enc->out_pkt, 2823 stream->enc->out_pkt_size); 2824 if (len != 0) { 2825 return pjmedia_transport_send_rtcp(stream->transport, 2826 stream->enc->out_pkt, len); 2827 } 2758 return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE); 2828 2759 } 2829 2760
Note: See TracChangeset
for help on using the changeset viewer.