Ticket #513: xr.patch
File xr.patch, 62.9 KB (added by nanang, 17 years ago) |
---|
-
pjmedia/include/pjmedia/config.h
339 339 # define PJMEDIA_RTCP_IGNORE_FIRST_PACKETS 25 340 340 #endif 341 341 342 /** 343 * Specify whether RTCP XR support should be built into PJMEDIA. Disabling 344 * this feature will reduce footprint slightly. Note that even when this 345 * setting is enabled, RTCP XR processing will only be performed in stream 346 * if it is enabled on run-time on per stream basis. See 347 * PJMEDIA_STREAM_ENABLE_XR setting for more info. 348 * 349 * Default: 1 (yes). 350 */ 351 #ifndef PJMEDIA_HAS_RTCP_XR 352 # define PJMEDIA_HAS_RTCP_XR 1 353 #endif 342 354 355 343 356 /** 357 * The RTCP XR feature is activated and used by stream if \a enable_rtcp_xr 358 * field of \a pjmedia_stream_info structure is non-zero. This setting 359 * controls the default value of this field. 360 * 361 * Default: 0 (disabled) 362 */ 363 #ifndef PJMEDIA_STREAM_ENABLE_XR 364 # define PJMEDIA_STREAM_ENABLE_XR 0 365 #endif 366 367 /** 344 368 * Specify how long (in miliseconds) the stream should suspend the 345 369 * silence detector/voice activity detector (VAD) during the initial 346 370 * period of the session. This feature is useful to open bindings in -
pjmedia/include/pjmedia/rtcp_xr.h
1 /* $Id$ */ 2 /* 3 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 #ifndef __PJMEDIA_RTCP_XR_H__ 20 #define __PJMEDIA_RTCP_XR_H__ 21 22 /** 23 * @file rtcp_xr.h 24 * @brief RTCP XR implementation. 25 */ 26 27 #include <pjmedia/types.h> 28 29 30 PJ_BEGIN_DECL 31 32 33 /** 34 * @defgroup PJMED_RTCP_XR RTCP Extended Report (XR) - RFC 3611 35 * @ingroup PJMEDIA_TRANSPORT 36 * @{ 37 * PJMEDIA implements subsets of RTCP XR specification (RFC 3611) to monitor 38 * the quality of the real-time media (audio/video) transmission. 39 */ 40 41 /** 42 * Enumeration of report types of RTCP XR. Useful for user to enable varying 43 * combinations of RTCP XR report blocks. 44 */ 45 typedef enum { 46 PJMEDIA_RTCP_XR_LOSS_RLE = (1 << 0), 47 PJMEDIA_RTCP_XR_DUP_RLE = (1 << 1), 48 PJMEDIA_RTCP_XR_RCPT_TIMES = (1 << 2), 49 PJMEDIA_RTCP_XR_RR_TIME = (1 << 3), 50 PJMEDIA_RTCP_XR_DLRR = (1 << 4), 51 PJMEDIA_RTCP_XR_STATS = (1 << 5), 52 PJMEDIA_RTCP_XR_VOIP_METRICS = (1 << 6) 53 } pjmedia_rtcp_xr_type; 54 55 /** 56 * Enumeration of info need to be updated manually to RTCP XR. Most info 57 * could be updated automatically each time RTP received. 58 */ 59 typedef enum { 60 PJMEDIA_RTCP_XR_INFO_SIGNAL_LVL = 1, 61 PJMEDIA_RTCP_XR_INFO_NOISE_LVL = 2, 62 PJMEDIA_RTCP_XR_INFO_RERL = 3, 63 PJMEDIA_RTCP_XR_INFO_R_FACTOR = 4, 64 PJMEDIA_RTCP_XR_INFO_MOS_LQ = 5, 65 PJMEDIA_RTCP_XR_INFO_MOS_CQ = 6, 66 PJMEDIA_RTCP_XR_INFO_CONF_PLC = 7, 67 PJMEDIA_RTCP_XR_INFO_CONF_JBA = 8, 68 PJMEDIA_RTCP_XR_INFO_CONF_JBR = 9, 69 PJMEDIA_RTCP_XR_INFO_JB_NOM = 10, 70 PJMEDIA_RTCP_XR_INFO_JB_MAX = 11, 71 PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX = 12 72 } pjmedia_rtcp_xr_info; 73 74 /** 75 * Enumeration of PLC types definitions for RTCP XR report. 76 */ 77 typedef enum { 78 PJMEDIA_RTCP_XR_PLC_UNK = 0, 79 PJMEDIA_RTCP_XR_PLC_DIS = 1, 80 PJMEDIA_RTCP_XR_PLC_ENH = 2, 81 PJMEDIA_RTCP_XR_PLC_STD = 3 82 } pjmedia_rtcp_xr_plc_type; 83 84 /** 85 * Enumeration of jitter buffer types definitions for RTCP XR report. 86 */ 87 typedef enum { 88 PJMEDIA_RTCP_XR_JB_UNKNOWN = 0, 89 PJMEDIA_RTCP_XR_JB_FIXED = 2, 90 PJMEDIA_RTCP_XR_JB_ADAPTIVE = 3 91 } pjmedia_rtcp_xr_jb_type; 92 93 94 #pragma pack(1) 95 96 /** 97 * This type declares RTCP XR Report Header. 98 */ 99 typedef struct pjmedia_rtcp_xr_rb_header 100 { 101 pj_uint8_t bt; /**< Block type. */ 102 pj_uint8_t specific; /**< Block specific data. */ 103 pj_uint16_t length; /**< Block length. */ 104 } pjmedia_rtcp_xr_rb_header; 105 106 /** 107 * This type declares RTCP XR Receiver Reference Time Report Block. 108 */ 109 typedef struct pjmedia_rtcp_xr_rb_rr_time 110 { 111 pjmedia_rtcp_xr_rb_header header; /**< Block header. */ 112 pj_uint32_t ntp_sec; /**< NTP time, seconds part. */ 113 pj_uint32_t ntp_frac; /**< NTP time, fractions part. */ 114 } pjmedia_rtcp_xr_rb_rr_time; 115 116 117 /** 118 * This type declares RTCP XR DLRR Report Sub-block 119 */ 120 typedef struct pjmedia_rtcp_xr_rb_dlrr_item 121 { 122 pj_uint32_t ssrc; /**< receiver SSRC */ 123 pj_uint32_t lrr; /**< last receiver report */ 124 pj_uint32_t dlrr; /**< delay since last receiver 125 report */ 126 } pjmedia_rtcp_xr_rb_dlrr_item; 127 128 /** 129 * This type declares RTCP XR DLRR Report Block 130 */ 131 typedef struct pjmedia_rtcp_xr_rb_dlrr 132 { 133 pjmedia_rtcp_xr_rb_header header; /**< Block header. */ 134 pjmedia_rtcp_xr_rb_dlrr_item item; /**< Block contents, 135 variable length list */ 136 } pjmedia_rtcp_xr_rb_dlrr; 137 138 /** 139 * This type declares RTCP XR Statistics Summary Report Block 140 */ 141 typedef struct pjmedia_rtcp_xr_rb_stats 142 { 143 pjmedia_rtcp_xr_rb_header header; /**< Block header. */ 144 pj_uint32_t ssrc; /**< Receiver SSRC */ 145 pj_uint16_t begin_seq; /**< Begin RTP sequence reported */ 146 pj_uint16_t end_seq; /**< End RTP sequence reported */ 147 pj_uint32_t lost; /**< Number of packet lost in this 148 interval */ 149 pj_uint32_t dup; /**< Number of duplicated packet in 150 this interval */ 151 pj_uint32_t jitter_min; /**< Minimum jitter in this interval */ 152 pj_uint32_t jitter_max; /**< Maximum jitter in this interval */ 153 pj_uint32_t jitter_mean; /**< Average jitter in this interval */ 154 pj_uint32_t jitter_dev; /**< Jitter deviation in this 155 interval */ 156 pj_uint32_t toh_min:8; /**< Minimum ToH in this interval */ 157 pj_uint32_t toh_max:8; /**< Maximum ToH in this interval */ 158 pj_uint32_t toh_mean:8; /**< Average ToH in this interval */ 159 pj_uint32_t toh_dev:8; /**< ToH deviation in this interval */ 160 } pjmedia_rtcp_xr_rb_stats; 161 162 /** 163 * This type declares RTCP XR VoIP Metrics Report Block 164 */ 165 typedef struct pjmedia_rtcp_xr_rb_voip_mtc 166 { 167 pjmedia_rtcp_xr_rb_header header; /**< Block header. */ 168 pj_uint32_t ssrc; /**< Receiver SSRC */ 169 pj_uint8_t loss_rate; /**< Packet loss rate */ 170 pj_uint8_t discard_rate; /**< Packet discarded rate */ 171 pj_uint8_t burst_den; /**< Burst density */ 172 pj_uint8_t gap_den; /**< Gap density */ 173 pj_uint16_t burst_dur; /**< Burst duration */ 174 pj_uint16_t gap_dur; /**< Gap duration */ 175 pj_uint16_t rnd_trip_delay;/**< Round trip delay */ 176 pj_uint16_t end_sys_delay; /**< End system delay */ 177 pj_uint8_t signal_lvl; /**< Signal level */ 178 pj_uint8_t noise_lvl; /**< Noise level */ 179 pj_uint8_t rerl; /**< Residual Echo Return Loss */ 180 pj_uint8_t gmin; /**< The gap threshold */ 181 pj_uint8_t r_factor; /**< Voice quality metric carried 182 over this RTP session */ 183 pj_uint8_t ext_r_factor; /**< Voice quality metric carried 184 outside of this RTP session*/ 185 pj_uint8_t mos_lq; /**< Mean Opinion Score for 186 Listening Quality */ 187 pj_uint8_t mos_cq; /**< Mean Opinion Score for 188 Conversation Quality */ 189 pj_uint8_t rx_config; /**< Receiver configuration */ 190 pj_uint8_t reserved2; /**< Not used */ 191 pj_uint16_t jb_nom; /**< Current delay by jitter 192 buffer */ 193 pj_uint16_t jb_max; /**< Maximum delay by jitter 194 buffer */ 195 pj_uint16_t jb_abs_max; /**< Maximum possible delay by 196 jitter buffer */ 197 } pjmedia_rtcp_xr_rb_voip_mtc; 198 199 /** 200 * This structure declares RTCP XR (Extended Report) packet. 201 */ 202 typedef struct pjmedia_rtcp_xr_pkt 203 { 204 struct { 205 #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 206 unsigned version:2; /**< packet type */ 207 unsigned p:1; /**< padding flag */ 208 unsigned count:5; /**< varies by payload type */ 209 unsigned pt:8; /**< payload type */ 210 #else 211 unsigned count:5; /**< varies by payload type */ 212 unsigned p:1; /**< padding flag */ 213 unsigned version:2; /**< packet type */ 214 unsigned pt:8; /**< payload type */ 215 #endif 216 unsigned length:16; /**< packet length */ 217 pj_uint32_t ssrc; /**< SSRC identification */ 218 } common; 219 220 pj_int8_t buf[PJMEDIA_MAX_MTU];/**< Content buffer */ 221 } pjmedia_rtcp_xr_pkt; 222 223 #pragma pack() 224 225 226 /** 227 * This structure describes RTCP XR statitic. 228 */ 229 typedef struct pjmedia_rtcp_xr_stream_stat 230 { 231 struct { 232 pj_uint32_t begin_seq; 233 pj_uint32_t end_seq; 234 unsigned count; /**< Number of packets. */ 235 236 /** 237 * Flags represent whether the such report is valid/updated 238 */ 239 unsigned l:1; /**< Lost flag */ 240 unsigned d:1; /**< Duplicated flag */ 241 unsigned j:1; /**< Jitter flag */ 242 unsigned t:2; /**< TTL or Hop Limit, 243 0=none, 1=TTL, 2=HL */ 244 245 unsigned lost; /**< Number of packets lost */ 246 unsigned dup; /**< Number of duplicated packets */ 247 248 struct { 249 unsigned min; /**< Minimum jitter (in usec) */ 250 unsigned max; /**< Maximum jitter (in usec) */ 251 unsigned dev; /**< Jitter deviation (in usec) */ 252 unsigned mean; /**< Average jitter (in usec) */ 253 unsigned count; /**< Update count */ 254 } jitter; /**< Jitter history. */ 255 256 struct { 257 unsigned min; /**< Minimum ToH */ 258 unsigned max; /**< Maximum ToH */ 259 unsigned dev; /**< ToH deviation */ 260 unsigned mean; /**< Average ToH */ 261 unsigned count; /**< Update count */ 262 } toh; /**< TTL of hop limit history. */ 263 } stat_sum; 264 265 struct { 266 pj_uint8_t loss_rate; /**< Packet loss rate */ 267 pj_uint8_t discard_rate; /**< Packet discarded rate */ 268 pj_uint8_t burst_den; /**< Burst density */ 269 pj_uint8_t gap_den; /**< Gap density */ 270 pj_uint16_t burst_dur; /**< Burst duration */ 271 pj_uint16_t gap_dur; /**< Gap duration */ 272 pj_uint16_t rnd_trip_delay; /**< Round trip delay */ 273 pj_uint16_t end_sys_delay; /**< End system delay */ 274 pj_uint8_t signal_lvl; /**< Signal level */ 275 pj_uint8_t noise_lvl; /**< Noise level */ 276 pj_uint8_t rerl; /**< Residual Echo Return Loss */ 277 pj_uint8_t gmin; /**< The gap threshold */ 278 pj_uint8_t r_factor; /**< Voice quality metric carried 279 over this RTP session */ 280 pj_uint8_t ext_r_factor; /**< Voice quality metric carried 281 outside of this RTP session*/ 282 pj_uint8_t mos_lq; /**< Mean Opinion Score for 283 Listening Quality */ 284 pj_uint8_t mos_cq; /**< Mean Opinion Score for 285 Conversation Quality */ 286 pj_uint8_t rx_config; /**< Receiver configuration */ 287 pj_uint16_t jb_nom; /**< Current delay by jitter 288 buffer */ 289 pj_uint16_t jb_max; /**< Maximum delay by jitter 290 buffer */ 291 pj_uint16_t jb_abs_max; /**< Maximum possible delay by 292 jitter buffer */ 293 } voip_mtc; 294 295 } pjmedia_rtcp_xr_stream_stat; 296 297 typedef struct pjmedia_rtcp_xr_stat 298 { 299 pjmedia_rtcp_xr_stream_stat rx; 300 pjmedia_rtcp_xr_stream_stat tx; 301 302 /* RTT calculated from receiver side */ 303 struct { 304 unsigned min; /**< Minimum round-trip delay (in usec) */ 305 unsigned avg; /**< Average round-trip delay (in usec) */ 306 unsigned max; /**< Maximum round-trip delay (in usec) */ 307 unsigned last; /**< Last round-trip delay (in usec) */ 308 unsigned update_cnt; /**< Nb of times rtt is updated. */ 309 } rtt; /**< Round trip delay history. */ 310 311 } pjmedia_rtcp_xr_stat; 312 313 /** 314 * Forward declaration of RTCP session 315 */ 316 struct pjmedia_rtcp_session; 317 318 /** 319 * RTCP session is used to monitor the RTP session of one endpoint. There 320 * should only be one RTCP session for a bidirectional RTP streams. 321 */ 322 struct pjmedia_rtcp_xr_session 323 { 324 char *name; /**< Name identification. */ 325 pjmedia_rtcp_xr_pkt pkt; /**< Cached RTCP XR packet. */ 326 327 pj_uint32_t rx_lrr; /**< NTP ts in last RR received. */ 328 pj_timestamp rx_lrr_time;/**< Time when last RR is received. */ 329 pj_uint32_t rx_last_rr; /**< # pkt received since last 330 sending RR time. */ 331 332 pjmedia_rtcp_xr_stat stat; /**< RTCP XR statistics. */ 333 334 /* The reference sequence number is an extended sequence number 335 * that serves as the basis for determining whether a new 16 bit 336 * sequence number comes earlier or later in the 32 bit sequence 337 * space. 338 */ 339 pj_uint32_t src_ref_seq; 340 pj_bool_t uninitialized_src_ref_seq; 341 342 /* This structure contains variables needed for calculating 343 * burst metrics. 344 */ 345 struct { 346 pj_uint32_t pkt; 347 pj_uint32_t lost; 348 pj_uint32_t loss_count; 349 pj_uint32_t discard_count; 350 pj_uint32_t c11; 351 pj_uint32_t c13; 352 pj_uint32_t c14; 353 pj_uint32_t c22; 354 pj_uint32_t c23; 355 pj_uint32_t c33; 356 } voip_mtc_stat; 357 358 unsigned ptime; /**< Packet time. */ 359 unsigned frames_per_packet; /**< # frames per packet. */ 360 361 struct pjmedia_rtcp_session *rtcp_session; 362 /**< Parent/RTCP session. */ 363 }; 364 365 typedef struct pjmedia_rtcp_xr_session pjmedia_rtcp_xr_session; 366 367 /** 368 * Build an RTCP XR packet which contains one or more RTCP XR report blocks. 369 * There are seven report types as defined in RFC 3611. 370 * 371 * @param session The RTCP XR session. 372 * @param rpt_types Report types to be included in the packet, report types 373 * are defined in pjmedia_rtcp_xr_type, set this to zero 374 * will make this function build all reports appropriately. 375 * @param rtcp_pkt Upon return, it will contain pointer to the RTCP XR packet. 376 * @param len Upon return, it will indicate the size of the generated 377 * RTCP XR packet. 378 */ 379 PJ_DECL(void) pjmedia_rtcp_build_rtcp_xr( pjmedia_rtcp_xr_session *session, 380 unsigned rpt_types, 381 void **rtcp_pkt, int *len); 382 383 /** 384 * Call this function to manually update some info needed by RTCP XR to 385 * generate report which could not be populated directly when receiving 386 * RTP. 387 * 388 * @param session The RTCP XR session. 389 * @param info Info type to be updated, @see pjmedia_rtcp_xr_info. 390 * @param val Value. 391 */ 392 PJ_DECL(pj_status_t) pjmedia_rtcp_xr_update_info( 393 pjmedia_rtcp_xr_session *session, 394 unsigned info, 395 pj_int32_t val); 396 397 /* 398 * Private APIs: 399 */ 400 401 /** 402 * This function is called internally by RTCP session when RTCP XR is enabled 403 * to initialize the RTCP XR session. 404 * 405 * @param session RTCP XR session. 406 * @param r_session RTCP session. 407 * @param gmin Gmin value (defined in RFC 3611), set to 0 for default (16). 408 * @param ptime Packet time. 409 * @param frames_per_packet 410 Number of frames per packet. 411 */ 412 void pjmedia_rtcp_xr_init( pjmedia_rtcp_xr_session *session, 413 struct pjmedia_rtcp_session *r_session, 414 pj_uint8_t gmin, 415 unsigned frames_per_packet); 416 417 /** 418 * This function is called internally by RTCP session to destroy 419 * the RTCP XR session. 420 * 421 * @param session RTCP XR session. 422 */ 423 void pjmedia_rtcp_xr_fini( pjmedia_rtcp_xr_session *session ); 424 425 /** 426 * This function is called internally by RTCP session when it receives 427 * incoming RTCP XR packets. 428 * 429 * @param session RTCP XR session. 430 * @param rtcp_pkt The received RTCP XR packet. 431 * @param size Size of the incoming packet. 432 */ 433 void pjmedia_rtcp_xr_rx_rtcp_xr( pjmedia_rtcp_xr_session *session, 434 const void *rtcp_xr_pkt, 435 pj_size_t size); 436 437 /** 438 * This function is called internally by RTCP session whenever an RTP packet 439 * is received or lost to let the RTCP XR session update its statistics. 440 * Data passed to this function is a result of analyzation by RTCP and the 441 * jitter buffer. Whenever some info is available, the value should be zero 442 * or more (no negative info), otherwise if info is not available the info 443 * should be -1 so no update will be done for this info in the RTCP XR session. 444 * 445 * @param session RTCP XR session. 446 * @param seq Sequence number of RTP packet. 447 * @param lost Info if this packet is lost. 448 * @param dup Info if this packet is a duplication. 449 * @param discarded Info if this packet is discarded 450 * (not because of duplication). 451 * @param jitter Info jitter of this packet. 452 * @param toh Info Time To Live or Hops Limit of this packet. 453 * @param toh_ipv4 Set PJ_TRUE if packet is transported over IPv4. 454 */ 455 void pjmedia_rtcp_xr_rx_rtp( pjmedia_rtcp_xr_session *session, 456 unsigned seq, 457 int lost, 458 int dup, 459 int discarded, 460 int jitter, 461 int toh, pj_bool_t toh_ipv4); 462 463 /** 464 * This function is called internally by RTCP session whenever an RTP 465 * packet is sent to let the RTCP XR session do its internal calculations. 466 * 467 * @param session RTCP XR session. 468 * @param ptsize Size of RTP payload being sent. 469 */ 470 void pjmedia_rtcp_xr_tx_rtp( pjmedia_rtcp_xr_session *session, 471 unsigned ptsize ); 472 473 /** 474 * @} 475 */ 476 477 PJ_END_DECL 478 479 480 #endif /* __PJMEDIA_RTCP_XR_H__ */ -
pjmedia/include/pjmedia/jbuf.h
76 76 unsigned min_prefetch; /**< Minimum allowed prefetch, in frms. */ 77 77 unsigned max_prefetch; /**< Maximum allowed prefetch, in frms. */ 78 78 unsigned size; /**< Current buffer size, in frames. */ 79 unsigned max_size; /**< Maximum size ever. */ 79 80 }; 80 81 81 82 … … 184 185 */ 185 186 PJ_DECL(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb); 186 187 187 188 188 /** 189 189 * Put a frame to the jitter buffer. If the frame can be accepted (based 190 190 * on the sequence number), the jitter buffer will copy the frame and put … … 198 198 * buffer. 199 199 * @param size The frame size. 200 200 * @param frame_seq The frame sequence number. 201 *202 * @return PJ_SUCCESS on success.203 201 */ 204 202 PJ_DECL(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb, 205 203 const void *frame, … … 207 205 int frame_seq); 208 206 209 207 /** 208 * Put a frame to the jitter buffer. If the frame can be accepted (based 209 * on the sequence number), the jitter buffer will copy the frame and put 210 * it in the appropriate position in the buffer. 211 * 212 * Application MUST manage it's own synchronization when multiple threads 213 * are accessing the jitter buffer at the same time. 214 * 215 * @param jb The jitter buffer. 216 * @param frame Pointer to frame buffer to be stored in the jitter 217 * buffer. 218 * @param size The frame size. 219 * @param frame_seq The frame sequence number. 220 * @param discarded Flag whether the frame is discarded by jitter buffer. 221 */ 222 PJ_DECL(void) pjmedia_jbuf_put_frame2( pjmedia_jbuf *jb, 223 const void *frame, 224 pj_size_t size, 225 int frame_seq, 226 pj_bool_t *discarded); 227 228 /** 210 229 * Get a frame from the jitter buffer. The jitter buffer will return the 211 230 * oldest frame from it's buffer, when it is available. 212 231 * -
pjmedia/include/pjmedia/rtcp.h
25 25 */ 26 26 27 27 #include <pjmedia/types.h> 28 #include <pjmedia/rtcp_xr.h> 28 29 #include <pjmedia/rtp.h> 29 30 30 31 … … 246 247 typedef pj_uint32_t PJMEDIA_AVG_JITTER_TYPE; 247 248 #endif 248 249 249 250 250 /** 251 251 * RTCP session is used to monitor the RTP session of one endpoint. There 252 252 * should only be one RTCP session for a bidirectional RTP streams. … … 254 254 struct pjmedia_rtcp_session 255 255 { 256 256 char *name; /**< Name identification. */ 257 pjmedia_rtcp_sr_pkt rtcp_sr_pkt;/**< Cached RTCP packet. */257 pjmedia_rtcp_sr_pkt rtcp_sr_pkt;/**< Cached RTCP SR packet. */ 258 258 pjmedia_rtcp_rr_pkt rtcp_rr_pkt;/**< Cached RTCP RR packet. */ 259 259 260 260 pjmedia_rtp_seq_session seq_ctrl; /**< RTCP sequence number control. */ … … 281 281 * from being rounded-down to nearest integer. 282 282 */ 283 283 PJMEDIA_AVG_JITTER_TYPE avg_jitter; /**< Average RX jitter. */ 284 285 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 286 /** 287 * Specify whether RTCP XR processing is enabled on this session. 288 */ 289 pj_bool_t xr_enabled; 290 291 /** 292 * RTCP XR session, only valid if RTCP XR processing is enabled 293 * on this session. 294 */ 295 pjmedia_rtcp_xr_session xr_session; 296 #endif 284 297 }; 285 298 286 299 /** … … 342 355 343 356 344 357 /** 358 * Call this function everytime an RTP packet is received to let the RTCP 359 * session do its internal calculations. 360 * 361 * @param session The session. 362 * @param seq The RTP packet sequence number, in host byte order. 363 * @param ts The RTP packet timestamp, in host byte order. 364 * @param payload Size of the payload. 365 * @param discarded Flag to specify whether the packet is discarded. 366 */ 367 PJ_DECL(void) pjmedia_rtcp_rx_rtp2(pjmedia_rtcp_session *session, 368 unsigned seq, 369 unsigned ts, 370 unsigned payload, 371 pj_bool_t discarded); 372 373 374 /** 345 375 * Call this function everytime an RTP packet is sent to let the RTCP session 346 376 * do its internal calculations. 347 377 * … … 385 415 386 416 387 417 /** 418 * Call this function if RTCP XR needs to be enabled/disabled in the 419 * RTCP session. 420 * 421 * @param session The RTCP session. 422 * @param enable Enable/disable RTCP XR. 423 * 424 * @return PJ_SUCCESS on success. 425 */ 426 PJ_DECL(pj_status_t) pjmedia_rtcp_enable_xr( pjmedia_rtcp_session *session, 427 pj_bool_t enable); 428 429 430 /** 388 431 * @} 389 432 */ 390 433 -
pjmedia/src/pjmedia/rtcp_xr.c
1 /* $Id$ */ 2 /* 3 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 #include <pjmedia/rtcp_xr.h> 21 #include <pjmedia/errno.h> 22 #include <pjmedia/rtcp.h> 23 #include <pj/assert.h> 24 #include <pj/log.h> 25 #include <pj/os.h> 26 #include <pj/sock.h> 27 #include <pj/string.h> 28 29 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 30 31 #define THIS_FILE "rtcp_xr.c" 32 33 34 #if PJ_HAS_HIGH_RES_TIMER==0 35 # error "High resolution timer needs to be enabled" 36 #endif 37 38 39 /* RTCP XR payload type */ 40 #define RTCP_XR 207 41 42 /* RTCP XR block types */ 43 #define BT_LOSS_RLE 1 44 #define BT_DUP_RLE 2 45 #define BT_RCPT_TIMES 3 46 #define BT_RR_TIME 4 47 #define BT_DLRR 5 48 #define BT_STATS 6 49 #define BT_VOIP_METRICS 7 50 51 52 #define DEFAULT_GMIN 16 53 54 55 #if 0 56 # define TRACE_(x) PJ_LOG(3,x) 57 #else 58 # define TRACE_(x) ; 59 #endif 60 61 /* Integer square root for calculating standard deviation */ 62 static pj_uint32_t my_isqrt(pj_uint32_t i) 63 { 64 pj_uint32_t res = 1, prev; 65 66 /* Rough guess */ 67 prev = i >> 2; 68 while (prev) { 69 prev >>= 2; 70 res <<= 1; 71 } 72 73 /* Babilonian method */ 74 do { 75 prev = res; 76 res = (prev + i/prev) >> 1; 77 } while ((prev+res)>>1 != res); 78 79 return res; 80 } 81 82 void pjmedia_rtcp_xr_init( pjmedia_rtcp_xr_session *session, 83 struct pjmedia_rtcp_session *parent_session, 84 pj_uint8_t gmin, 85 unsigned frames_per_packet) 86 { 87 pj_bzero(session, sizeof(pjmedia_rtcp_xr_session)); 88 89 session->rtcp_session = parent_session; 90 pj_memcpy(&session->pkt.common, &session->rtcp_session->rtcp_sr_pkt.common, 91 sizeof(pjmedia_rtcp_common)); 92 session->pkt.common.pt = RTCP_XR; 93 94 /* Init config */ 95 session->stat.tx.voip_mtc.gmin = (pj_uint8_t)(gmin? gmin : DEFAULT_GMIN); 96 session->ptime = session->rtcp_session->pkt_size * 1000 / 97 session->rtcp_session->clock_rate; 98 session->frames_per_packet = frames_per_packet; 99 100 /* Init Statistics Summary fields which have non-zero default */ 101 session->stat.tx.stat_sum.jitter.min = (unsigned) -1; 102 session->stat.tx.stat_sum.toh.min = (unsigned) -1; 103 104 /* Init VoIP Metrics fields which have non-zero default */ 105 session->stat.tx.voip_mtc.signal_lvl = 127; 106 session->stat.tx.voip_mtc.noise_lvl = 127; 107 session->stat.tx.voip_mtc.rerl = 127; 108 session->stat.tx.voip_mtc.r_factor = 127; 109 session->stat.tx.voip_mtc.ext_r_factor = 127; 110 session->stat.tx.voip_mtc.mos_lq = 127; 111 session->stat.tx.voip_mtc.mos_cq = 127; 112 } 113 114 void pjmedia_rtcp_xr_fini(pjmedia_rtcp_xr_session *session) 115 { 116 PJ_UNUSED_ARG(session); 117 } 118 119 PJ_DEF(void) pjmedia_rtcp_build_rtcp_xr( pjmedia_rtcp_xr_session *sess, 120 unsigned rpt_types, 121 void **rtcp_pkt, int *len) 122 { 123 pj_uint16_t size = 0; 124 125 /* Receiver Reference Time Report Block */ 126 /* Build this block if we have received packets since last build */ 127 if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_RR_TIME)) && 128 sess->rx_last_rr != sess->rtcp_session->stat.rx.pkt) 129 { 130 pjmedia_rtcp_xr_rb_rr_time *r; 131 pjmedia_rtcp_ntp_rec ntp; 132 133 r = (pjmedia_rtcp_xr_rb_rr_time*) &sess->pkt.buf[size]; 134 pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_rr_time)); 135 136 /* Init block header */ 137 r->header.bt = BT_RR_TIME; 138 r->header.specific = 0; 139 r->header.length = pj_htons(2); 140 141 /* Generate block contents */ 142 pjmedia_rtcp_get_ntp_time(sess->rtcp_session, &ntp); 143 r->ntp_sec = pj_htonl(ntp.hi); 144 r->ntp_frac = pj_htonl(ntp.lo); 145 146 /* Finally */ 147 size += sizeof(pjmedia_rtcp_xr_rb_rr_time); 148 sess->rx_last_rr = sess->rtcp_session->stat.rx.pkt; 149 } 150 151 /* DLRR Report Block */ 152 /* Build this block if we have received RR NTP (rx_lrr) before */ 153 if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_DLRR)) && 154 sess->rx_lrr) 155 { 156 pjmedia_rtcp_xr_rb_dlrr *r; 157 pjmedia_rtcp_xr_rb_dlrr_item *dlrr_item; 158 pj_timestamp ts; 159 160 r = (pjmedia_rtcp_xr_rb_dlrr*) &sess->pkt.buf[size]; 161 pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_dlrr)); 162 163 /* Init block header */ 164 r->header.bt = BT_DLRR; 165 r->header.specific = 0; 166 r->header.length = pj_htons(sizeof(pjmedia_rtcp_xr_rb_dlrr)/4 - 1); 167 168 /* Generate block contents */ 169 dlrr_item = &r->item; 170 dlrr_item->ssrc = pj_htonl(sess->rtcp_session->peer_ssrc); 171 dlrr_item->lrr = pj_htonl(sess->rx_lrr); 172 173 /* Calculate DLRR */ 174 if (sess->rx_lrr != 0) { 175 pj_get_timestamp(&ts); 176 ts.u64 -= sess->rx_lrr_time.u64; 177 178 /* Convert DLRR time to 1/65536 seconds resolution */ 179 ts.u64 = (ts.u64 << 16) / sess->rtcp_session->ts_freq.u64; 180 dlrr_item->dlrr = pj_htonl(ts.u32.lo); 181 } else { 182 dlrr_item->dlrr = 0; 183 } 184 185 /* Finally */ 186 size += sizeof(pjmedia_rtcp_xr_rb_dlrr); 187 } 188 189 /* Statistics Summary Block */ 190 /* Build this block if we have received packets since last build */ 191 if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_STATS)) && 192 sess->stat.tx.stat_sum.count > 0) 193 { 194 pjmedia_rtcp_xr_rb_stats *r; 195 pj_uint8_t specific = 0; 196 197 r = (pjmedia_rtcp_xr_rb_stats*) &sess->pkt.buf[size]; 198 pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_stats)); 199 200 /* Init block header */ 201 specific |= sess->stat.tx.stat_sum.l ? (1 << 7) : 0; 202 specific |= sess->stat.tx.stat_sum.d ? (1 << 6) : 0; 203 specific |= sess->stat.tx.stat_sum.j ? (1 << 5) : 0; 204 specific |= (sess->stat.tx.stat_sum.t & 3) << 3; 205 r->header.bt = BT_STATS; 206 r->header.specific = specific; 207 r->header.length = pj_htons(9); 208 209 /* Generate block contents */ 210 r->ssrc = pj_htonl(sess->rtcp_session->peer_ssrc); 211 r->begin_seq = pj_htons((pj_uint16_t) 212 (sess->stat.tx.stat_sum.begin_seq & 0xFFFF)); 213 r->end_seq = pj_htons((pj_uint16_t) 214 (sess->stat.tx.stat_sum.end_seq & 0xFFFF)); 215 if (sess->stat.tx.stat_sum.l) { 216 r->lost = pj_htonl(sess->stat.tx.stat_sum.lost); 217 } 218 if (sess->stat.tx.stat_sum.d) { 219 r->dup = pj_htonl(sess->stat.tx.stat_sum.dup); 220 } 221 if (sess->stat.tx.stat_sum.j) { 222 r->jitter_min = pj_htonl(sess->stat.tx.stat_sum.jitter.min); 223 r->jitter_max = pj_htonl(sess->stat.tx.stat_sum.jitter.max); 224 r->jitter_mean = pj_htonl(sess->stat.tx.stat_sum.jitter.mean); 225 sess->stat.tx.stat_sum.jitter.dev = 226 my_isqrt(sess->stat.tx.stat_sum.jitter.dev); 227 r->jitter_dev = pj_htonl(sess->stat.tx.stat_sum.jitter.dev); 228 } 229 if (sess->stat.tx.stat_sum.t) { 230 r->toh_min = sess->stat.tx.stat_sum.toh.min; 231 r->toh_max = sess->stat.tx.stat_sum.toh.max; 232 r->toh_mean = sess->stat.tx.stat_sum.toh.mean; 233 sess->stat.tx.stat_sum.toh.dev = 234 my_isqrt(sess->stat.tx.stat_sum.toh.dev); 235 r->toh_dev = sess->stat.tx.stat_sum.toh.dev; 236 } 237 238 /* Reset TX statistics summary each time built */ 239 pj_bzero(&sess->stat.tx.stat_sum, sizeof(sess->stat.tx.stat_sum)); 240 sess->stat.tx.stat_sum.jitter.min = (unsigned) -1; 241 sess->stat.tx.stat_sum.toh.min = (unsigned) -1; 242 243 /* Finally */ 244 size += sizeof(pjmedia_rtcp_xr_rb_stats); 245 } 246 247 /* Voip Metrics Block */ 248 /* Build this block if we have received packets */ 249 if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_VOIP_METRICS)) && 250 sess->rtcp_session->stat.rx.pkt) 251 { 252 pjmedia_rtcp_xr_rb_voip_mtc *r; 253 pj_uint32_t c11; 254 pj_uint32_t c13; 255 pj_uint32_t c14; 256 pj_uint32_t c22; 257 pj_uint32_t c23; 258 pj_uint32_t c31; 259 pj_uint32_t c32; 260 pj_uint32_t c33; 261 pj_uint32_t ctotal, p32, p23, m; 262 263 r = (pjmedia_rtcp_xr_rb_voip_mtc*) &sess->pkt.buf[size]; 264 pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_voip_mtc)); 265 266 /* Init block header */ 267 r->header.bt = BT_VOIP_METRICS; 268 r->header.specific = 0; 269 r->header.length = pj_htons(8); 270 271 /* Calculate additional transition counts. */ 272 c11 = sess->voip_mtc_stat.c11; 273 c13 = sess->voip_mtc_stat.c13; 274 c14 = sess->voip_mtc_stat.c14; 275 c22 = sess->voip_mtc_stat.c22; 276 c23 = sess->voip_mtc_stat.c23; 277 c33 = sess->voip_mtc_stat.c33; 278 c31 = c13; 279 c32 = c23; 280 ctotal = c11 + c14 + c13 + c22 + c23 + c31 + c32 + c33; 281 m = sess->ptime * sess->frames_per_packet; 282 283 /* Calculate burst and densities. */ 284 if (ctotal) { 285 p32 = c32 / (c31 + c32 + c33); 286 if((c22 + c23) < 1) { 287 p23 = 1; 288 } else { 289 p23 = 1 - c22/(c22 + c23); 290 } 291 sess->stat.tx.voip_mtc.burst_den = (pj_uint8_t)(256*p23/(p23 + p32)); 292 sess->stat.tx.voip_mtc.gap_den = (pj_uint8_t)(256*c14/(c11 + c14)); 293 294 /* Calculate burst and gap durations in ms */ 295 sess->stat.tx.voip_mtc.gap_dur = (pj_uint16_t)((c11+c14+c13)*m/c13); 296 sess->stat.tx.voip_mtc.burst_dur = (pj_uint16_t)(ctotal*m/c13 - 297 sess->stat.tx.voip_mtc.gap_dur); 298 } else { 299 /* No burst occurred yet until this time? 300 * Just report full gap. 301 */ 302 ctotal = sess->rtcp_session->stat.rx.pkt; 303 304 sess->stat.tx.voip_mtc.burst_den = 0; 305 sess->stat.tx.voip_mtc.gap_den = (pj_uint8_t)(256 * 306 (sess->voip_mtc_stat.loss_count + 307 sess->voip_mtc_stat.discard_count) / 308 ctotal); 309 310 /* Calculate burst and gap durations in ms */ 311 sess->stat.tx.voip_mtc.gap_dur = (pj_uint16_t)((m*ctotal) < 0xFFFF? 312 (m*ctotal) : 0xFFFF); 313 sess->stat.tx.voip_mtc.burst_dur = 0; 314 } 315 316 /* Calculate loss and discard rates */ 317 sess->stat.tx.voip_mtc.loss_rate = (pj_uint8_t) 318 (256 * sess->voip_mtc_stat.loss_count / ctotal); 319 sess->stat.tx.voip_mtc.discard_rate = (pj_uint8_t) 320 (256 * sess->voip_mtc_stat.discard_count / ctotal); 321 322 /* Set round trip delay (in ms) to RTT calculated after receiving 323 * DLRR or DLSR. 324 */ 325 if (sess->stat.rtt.last) 326 sess->stat.tx.voip_mtc.rnd_trip_delay = (pj_uint16_t) 327 (sess->stat.rtt.last / 1000); 328 else if (sess->rtcp_session->stat.rtt.last) 329 sess->stat.tx.voip_mtc.rnd_trip_delay = (pj_uint16_t) 330 (sess->rtcp_session->stat.rtt.last / 1000); 331 332 /* End system delay estimation = RTT/2 + current jitter buffer size + 333 * EXTRA 334 * EXTRA will cover additional delay introduced by other components of 335 * audio engine, e.g: sound device, codec, AEC, PLC, WSOLA. 336 * Since it is difficult to get the exact value of EXTRA, estimation 337 * is taken to be totally around 50 ms. 338 */ 339 sess->stat.tx.voip_mtc.end_sys_delay = (pj_uint16_t) 340 (sess->stat.tx.voip_mtc.rnd_trip_delay / 2 + 341 sess->stat.tx.voip_mtc.jb_nom + 50); 342 343 /* Generate block contents */ 344 r->ssrc = pj_htonl(sess->rtcp_session->peer_ssrc); 345 r->loss_rate = sess->stat.tx.voip_mtc.loss_rate; 346 r->discard_rate = sess->stat.tx.voip_mtc.discard_rate; 347 r->burst_den = sess->stat.tx.voip_mtc.burst_den; 348 r->gap_den = sess->stat.tx.voip_mtc.gap_den; 349 r->burst_dur = pj_htons(sess->stat.tx.voip_mtc.burst_dur); 350 r->gap_dur = pj_htons(sess->stat.tx.voip_mtc.gap_dur); 351 r->rnd_trip_delay = pj_htons(sess->stat.tx.voip_mtc.rnd_trip_delay); 352 r->end_sys_delay = pj_htons(sess->stat.tx.voip_mtc.end_sys_delay); 353 r->signal_lvl = sess->stat.tx.voip_mtc.signal_lvl; 354 r->noise_lvl = sess->stat.tx.voip_mtc.noise_lvl; 355 r->rerl = sess->stat.tx.voip_mtc.rerl; 356 r->gmin = sess->stat.tx.voip_mtc.gmin; 357 r->r_factor = sess->stat.tx.voip_mtc.r_factor; 358 r->ext_r_factor = sess->stat.tx.voip_mtc.ext_r_factor; 359 r->mos_lq = sess->stat.tx.voip_mtc.mos_lq; 360 r->mos_cq = sess->stat.tx.voip_mtc.mos_cq; 361 r->rx_config = sess->stat.tx.voip_mtc.rx_config; 362 r->jb_nom = pj_htons(sess->stat.tx.voip_mtc.jb_nom); 363 r->jb_max = pj_htons(sess->stat.tx.voip_mtc.jb_max); 364 r->jb_abs_max = pj_htons(sess->stat.tx.voip_mtc.jb_abs_max); 365 366 /* Finally */ 367 size += sizeof(pjmedia_rtcp_xr_rb_voip_mtc); 368 } 369 370 /* Add RTCP XR header size */ 371 size += sizeof(sess->pkt.common); 372 373 /* Set RTCP XR header 'length' to packet size in 32-bit unit minus one */ 374 sess->pkt.common.length = pj_htons((pj_uint16_t)(size/4 - 1)); 375 376 /* Set the return values */ 377 *rtcp_pkt = (void*) &sess->pkt; 378 *len = size; 379 } 380 381 382 void pjmedia_rtcp_xr_rx_rtcp_xr( pjmedia_rtcp_xr_session *sess, 383 const void *pkt, 384 pj_size_t size) 385 { 386 const pjmedia_rtcp_xr_pkt *rtcp_xr = (pjmedia_rtcp_xr_pkt*) pkt; 387 const pjmedia_rtcp_xr_rb_rr_time *rb_rr_time = NULL; 388 const pjmedia_rtcp_xr_rb_dlrr *rb_dlrr = NULL; 389 const pjmedia_rtcp_xr_rb_stats *rb_stats = NULL; 390 const pjmedia_rtcp_xr_rb_voip_mtc *rb_voip_mtc = NULL; 391 const pjmedia_rtcp_xr_rb_header *rb_hdr = (pjmedia_rtcp_xr_rb_header*) 392 rtcp_xr->buf; 393 unsigned pkt_len, rb_len; 394 395 if (rtcp_xr->common.pt != RTCP_XR) 396 return; 397 398 pkt_len = pj_ntohs((pj_uint16_t)rtcp_xr->common.length); 399 400 pj_assert((pkt_len + 1) <= (size / 4)); 401 402 /* Parse report rpt_types */ 403 while ((pj_int32_t*)rb_hdr < (pj_int32_t*)pkt + pkt_len) 404 { 405 rb_len = pj_ntohs((pj_uint16_t)rb_hdr->length); 406 407 /* Just skip any block with length == 0 (no report content) */ 408 if (rb_len) { 409 switch (rb_hdr->bt) { 410 case BT_RR_TIME: 411 rb_rr_time = (pjmedia_rtcp_xr_rb_rr_time*) rb_hdr; 412 break; 413 case BT_DLRR: 414 rb_dlrr = (pjmedia_rtcp_xr_rb_dlrr*) rb_hdr; 415 break; 416 case BT_STATS: 417 rb_stats = (pjmedia_rtcp_xr_rb_stats*) rb_hdr; 418 break; 419 case BT_VOIP_METRICS: 420 rb_voip_mtc = (pjmedia_rtcp_xr_rb_voip_mtc*) rb_hdr; 421 break; 422 default: 423 break; 424 } 425 } 426 rb_hdr = (pjmedia_rtcp_xr_rb_header*) 427 ((pj_int32_t*)rb_hdr + rb_len + 1); 428 } 429 430 /* Receiving RR Time */ 431 if (rb_rr_time) { 432 /* Save LRR from NTP timestamp of the RR time block report */ 433 sess->rx_lrr = ((pj_ntohl(rb_rr_time->ntp_sec) & 0x0000FFFF) << 16) | 434 ((pj_ntohl(rb_rr_time->ntp_frac) >> 16) & 0xFFFF); 435 436 /* Calculate RR arrival time for DLRR */ 437 pj_get_timestamp(&sess->rx_lrr_time); 438 439 TRACE_((sess->name, "Rx RTCP SR: ntp_ts=%p", sess->rx_lrr, 440 (pj_uint32_t)(sess->rx_lrr_time.u64*65536/ 441 sess->rtcp_session->ts_freq.u64))); 442 } 443 444 /* Receiving DLRR */ 445 if (rb_dlrr) { 446 pj_uint32_t lrr, now, dlrr; 447 pj_uint64_t eedelay; 448 pjmedia_rtcp_ntp_rec ntp; 449 450 /* LRR is the middle 32bit of NTP. It has 1/65536 second 451 * resolution 452 */ 453 lrr = pj_ntohl(rb_dlrr->item.lrr); 454 455 /* DLRR is delay since LRR, also in 1/65536 resolution */ 456 dlrr = pj_ntohl(rb_dlrr->item.dlrr); 457 458 /* Get current time, and convert to 1/65536 resolution */ 459 pjmedia_rtcp_get_ntp_time(sess->rtcp_session, &ntp); 460 now = ((ntp.hi & 0xFFFF) << 16) + (ntp.lo >> 16); 461 462 /* End-to-end delay is (now-lrr-dlrr) */ 463 eedelay = now - lrr - dlrr; 464 465 /* Convert end to end delay to usec (keeping the calculation in 466 * 64bit space):: 467 * sess->ee_delay = (eedelay * 1000) / 65536; 468 */ 469 if (eedelay < 4294) { 470 eedelay = (eedelay * 1000000) >> 16; 471 } else { 472 eedelay = (eedelay * 1000) >> 16; 473 eedelay *= 1000; 474 } 475 476 TRACE_((sess->name, "Rx RTCP XR DLRR: lrr=%p, dlrr=%p (%d:%03dms), " 477 "now=%p, rtt=%p", 478 lrr, dlrr, dlrr/65536, (dlrr%65536)*1000/65536, 479 now, (pj_uint32_t)eedelay)); 480 481 /* Only save calculation if "now" is greater than lrr, or 482 * otherwise rtt will be invalid 483 */ 484 if (now-dlrr >= lrr) { 485 unsigned rtt = (pj_uint32_t)eedelay; 486 487 /* Check that eedelay value really makes sense. 488 * We allow up to 30 seconds RTT! 489 */ 490 if (eedelay <= 30 * 1000 * 1000UL) { 491 if (sess->stat.rtt.update_cnt == 0) 492 sess->stat.rtt.min = rtt; 493 494 /* "Normalize" rtt value that is exceptionally high. 495 * For such values, "normalize" the rtt to be three times 496 * the average value. 497 */ 498 if (rtt>(sess->stat.rtt.avg*3) && sess->stat.rtt.update_cnt!=0) 499 { 500 unsigned orig_rtt = rtt; 501 rtt = sess->stat.rtt.avg*3; 502 PJ_LOG(5,(sess->name, 503 "RTT value %d usec is normalized to %d usec", 504 orig_rtt, rtt)); 505 } 506 507 TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt)); 508 509 if (rtt < sess->stat.rtt.min && rtt) 510 sess->stat.rtt.min = rtt; 511 if (rtt > sess->stat.rtt.max) 512 sess->stat.rtt.max = rtt; 513 514 sess->stat.rtt.avg = 515 (sess->stat.rtt.avg * sess->stat.rtt.update_cnt + rtt) / 516 (sess->stat.rtt.update_cnt + 1); 517 518 sess->stat.rtt.last = rtt; 519 sess->stat.rtt.update_cnt++; 520 } 521 } else { 522 PJ_LOG(5, (sess->name, "Internal RTCP NTP clock skew detected: " 523 "lrr=%p, now=%p, dlrr=%p (%d:%03dms), " 524 "diff=%d", 525 lrr, now, dlrr, dlrr/65536, 526 (dlrr%65536)*1000/65536, 527 dlrr-(now-lrr))); 528 } 529 } 530 531 /* Receiving Statistics Summary */ 532 if (rb_stats) { 533 pj_uint8_t flags = rb_stats->header.specific; 534 535 pj_bzero(&sess->stat.rx.stat_sum, sizeof(sess->stat.rx.stat_sum)); 536 537 /* Range of packets sequence reported in this blocks */ 538 sess->stat.rx.stat_sum.begin_seq = pj_ntohs(rb_stats->begin_seq); 539 sess->stat.rx.stat_sum.end_seq = pj_ntohs(rb_stats->end_seq); 540 541 /* Get flags of valid fields */ 542 sess->stat.rx.stat_sum.l = (flags & (1 << 7)) != 0; 543 sess->stat.rx.stat_sum.d = (flags & (1 << 6)) != 0; 544 sess->stat.rx.stat_sum.j = (flags & (1 << 5)) != 0; 545 sess->stat.rx.stat_sum.t = (flags & (3 << 3)) != 0; 546 547 /* Fetch the reports info */ 548 if (sess->stat.rx.stat_sum.l) { 549 sess->stat.rx.stat_sum.lost = pj_ntohl(rb_stats->lost); 550 } 551 552 if (sess->stat.rx.stat_sum.d) { 553 sess->stat.rx.stat_sum.dup = pj_ntohl(rb_stats->dup); 554 } 555 556 if (sess->stat.rx.stat_sum.j) { 557 sess->stat.rx.stat_sum.jitter.min = pj_ntohl(rb_stats->jitter_min); 558 sess->stat.rx.stat_sum.jitter.max = pj_ntohl(rb_stats->jitter_max); 559 sess->stat.rx.stat_sum.jitter.mean = pj_ntohl(rb_stats->jitter_mean); 560 sess->stat.rx.stat_sum.jitter.dev = pj_ntohl(rb_stats->jitter_dev); 561 } 562 563 if (sess->stat.rx.stat_sum.t) { 564 sess->stat.rx.stat_sum.toh.min = rb_stats->toh_min; 565 sess->stat.rx.stat_sum.toh.max = rb_stats->toh_max; 566 sess->stat.rx.stat_sum.toh.mean = rb_stats->toh_mean; 567 sess->stat.rx.stat_sum.toh.dev = rb_stats->toh_dev; 568 } 569 } 570 571 /* Receiving VoIP Metrics */ 572 if (rb_voip_mtc) { 573 sess->stat.rx.voip_mtc.loss_rate = rb_voip_mtc->loss_rate; 574 sess->stat.rx.voip_mtc.discard_rate = rb_voip_mtc->discard_rate; 575 sess->stat.rx.voip_mtc.burst_den = rb_voip_mtc->burst_den; 576 sess->stat.rx.voip_mtc.gap_den = rb_voip_mtc->gap_den; 577 sess->stat.rx.voip_mtc.burst_dur = pj_ntohs(rb_voip_mtc->burst_dur); 578 sess->stat.rx.voip_mtc.gap_dur = pj_ntohs(rb_voip_mtc->gap_dur); 579 sess->stat.rx.voip_mtc.rnd_trip_delay = 580 pj_ntohs(rb_voip_mtc->rnd_trip_delay); 581 sess->stat.rx.voip_mtc.end_sys_delay = 582 pj_ntohs(rb_voip_mtc->end_sys_delay); 583 sess->stat.rx.voip_mtc.signal_lvl = rb_voip_mtc->signal_lvl; 584 sess->stat.rx.voip_mtc.noise_lvl = rb_voip_mtc->noise_lvl; 585 sess->stat.rx.voip_mtc.rerl = rb_voip_mtc->rerl; 586 sess->stat.rx.voip_mtc.gmin = rb_voip_mtc->gmin; 587 sess->stat.rx.voip_mtc.r_factor = rb_voip_mtc->r_factor; 588 sess->stat.rx.voip_mtc.ext_r_factor = rb_voip_mtc->ext_r_factor; 589 sess->stat.rx.voip_mtc.mos_lq = rb_voip_mtc->mos_lq; 590 sess->stat.rx.voip_mtc.mos_cq = rb_voip_mtc->mos_cq; 591 sess->stat.rx.voip_mtc.rx_config = rb_voip_mtc->rx_config; 592 sess->stat.rx.voip_mtc.jb_nom = pj_ntohs(rb_voip_mtc->jb_nom); 593 sess->stat.rx.voip_mtc.jb_max = pj_ntohs(rb_voip_mtc->jb_max); 594 sess->stat.rx.voip_mtc.jb_abs_max = pj_ntohs(rb_voip_mtc->jb_abs_max); 595 } 596 } 597 598 /* Place seq into a 32-bit sequence number space based upon a 599 * heuristic for its most likely location. 600 */ 601 static pj_uint32_t extend_seq(pjmedia_rtcp_xr_session *sess, 602 const pj_uint16_t seq) 603 { 604 605 pj_uint32_t extended_seq, seq_a, seq_b, diff_a, diff_b; 606 if(sess->uninitialized_src_ref_seq) { 607 /* This is the first sequence number received. Place 608 * it in the middle of the extended sequence number 609 * space. 610 */ 611 sess->src_ref_seq = seq | 0x80000000u; 612 sess->uninitialized_src_ref_seq = PJ_FALSE; 613 extended_seq = sess->src_ref_seq; 614 } else { 615 /* Prior sequence numbers have been received. 616 * Propose two candidates for the extended sequence 617 * number: seq_a is without wraparound, seq_b with 618 * wraparound. 619 */ 620 seq_a = seq | (sess->src_ref_seq & 0xFFFF0000u); 621 if(sess->src_ref_seq < seq_a) { 622 seq_b = seq_a - 0x00010000u; 623 diff_a = seq_a - sess->src_ref_seq; 624 diff_b = sess->src_ref_seq - seq_b; 625 } else { 626 seq_b = seq_a + 0x00010000u; 627 diff_a = sess->src_ref_seq - seq_a; 628 diff_b = seq_b - sess->src_ref_seq; 629 } 630 631 /* Choose the closer candidate. If they are equally 632 * close, the choice is somewhat arbitrary: we choose 633 * the candidate for which no rollover is necessary. 634 */ 635 if(diff_a < diff_b) { 636 extended_seq = seq_a; 637 } else { 638 extended_seq = seq_b; 639 } 640 641 /* Set the reference sequence number to be this most 642 * recently-received sequence number. 643 */ 644 sess->src_ref_seq = extended_seq; 645 } 646 647 /* Return our best guess for a 32-bit sequence number that 648 * corresponds to the 16-bit number we were given. 649 */ 650 return extended_seq; 651 } 652 653 void pjmedia_rtcp_xr_rx_rtp( pjmedia_rtcp_xr_session *sess, 654 unsigned seq, 655 int lost, 656 int dup, 657 int discarded, 658 int jitter, 659 int toh, pj_bool_t toh_ipv4) 660 { 661 pj_uint32_t ext_seq; 662 663 /* Get 32 bit version of sequence */ 664 ext_seq = extend_seq(sess, (pj_uint16_t)seq); 665 666 /* Update statistics summary */ 667 sess->stat.tx.stat_sum.count++; 668 669 if (sess->stat.tx.stat_sum.begin_seq == 0 || 670 sess->stat.tx.stat_sum.begin_seq > ext_seq) 671 { 672 sess->stat.tx.stat_sum.begin_seq = ext_seq; 673 } 674 675 if (sess->stat.tx.stat_sum.end_seq == 0 || 676 sess->stat.tx.stat_sum.end_seq < ext_seq) 677 { 678 sess->stat.tx.stat_sum.end_seq = ext_seq; 679 } 680 681 if (lost >= 0) { 682 sess->stat.tx.stat_sum.l = PJ_TRUE; 683 if (lost > 0) 684 sess->stat.tx.stat_sum.lost++; 685 } 686 687 if (dup >= 0) { 688 sess->stat.tx.stat_sum.d = PJ_TRUE; 689 if (dup > 0) 690 sess->stat.tx.stat_sum.dup++; 691 } 692 693 if (jitter >= 0) { 694 pj_int32_t diff; 695 696 sess->stat.tx.stat_sum.j = PJ_TRUE; 697 if (sess->stat.tx.stat_sum.jitter.min > (pj_uint32_t)jitter) 698 sess->stat.tx.stat_sum.jitter.min = jitter; 699 if (sess->stat.tx.stat_sum.jitter.max < (pj_uint32_t)jitter) 700 sess->stat.tx.stat_sum.jitter.max = jitter; 701 sess->stat.tx.stat_sum.jitter.mean = 702 (jitter + sess->stat.tx.stat_sum.jitter.mean * 703 sess->stat.tx.stat_sum.jitter.count) / 704 (sess->stat.tx.stat_sum.jitter.count + 1); 705 706 diff = sess->stat.tx.stat_sum.jitter.mean - jitter; 707 sess->stat.tx.stat_sum.jitter.dev = 708 (diff * diff + sess->stat.tx.stat_sum.jitter.dev * 709 sess->stat.tx.stat_sum.jitter.count) / 710 (sess->stat.tx.stat_sum.jitter.count + 1); 711 712 ++sess->stat.tx.stat_sum.jitter.count; 713 } 714 715 if (toh >= 0) { 716 pj_int32_t diff; 717 718 sess->stat.tx.stat_sum.t = toh_ipv4? 1 : 2; 719 720 if (sess->stat.tx.stat_sum.toh.min > (pj_uint32_t)toh) 721 sess->stat.tx.stat_sum.toh.min = toh; 722 if (sess->stat.tx.stat_sum.toh.max < (pj_uint32_t)toh) 723 sess->stat.tx.stat_sum.toh.max = toh; 724 sess->stat.tx.stat_sum.toh.mean = 725 (toh + sess->stat.tx.stat_sum.toh.mean * 726 sess->stat.tx.stat_sum.toh.count) / 727 (sess->stat.tx.stat_sum.toh.count + 1); 728 729 diff = sess->stat.tx.stat_sum.toh.mean - toh; 730 sess->stat.tx.stat_sum.toh.dev = 731 (diff * diff + sess->stat.tx.stat_sum.toh.dev * 732 sess->stat.tx.stat_sum.toh.count) / 733 (sess->stat.tx.stat_sum.toh.count + 1); 734 735 ++sess->stat.tx.stat_sum.toh.count; 736 } 737 738 /* Update burst metrics. 739 * There are two terms introduced in the RFC 3611: gap & burst. 740 * Gap represents good stream condition, lost+discard rate <= 1/Gmin. 741 * Burst represents the opposite, lost+discard rate > 1/Gmin. 742 */ 743 if (lost >= 0 && discarded >= 0) { 744 if(lost > 0) { 745 sess->voip_mtc_stat.loss_count++; 746 } 747 if(discarded > 0) { 748 sess->voip_mtc_stat.discard_count++; 749 } 750 if(!lost && !discarded) { 751 /* Number of good packets since last lost/discarded */ 752 sess->voip_mtc_stat.pkt++; 753 } 754 else { 755 if(sess->voip_mtc_stat.pkt >= sess->stat.tx.voip_mtc.gmin) { 756 /* Gap condition */ 757 if(sess->voip_mtc_stat.lost == 1) { 758 /* Gap -> Gap */ 759 sess->voip_mtc_stat.c14++; 760 } 761 else { 762 /* Burst -> Gap */ 763 sess->voip_mtc_stat.c13++; 764 } 765 sess->voip_mtc_stat.lost = 1; 766 sess->voip_mtc_stat.c11 += sess->voip_mtc_stat.pkt; 767 } 768 else { 769 /* Burst condition */ 770 sess->voip_mtc_stat.lost++; 771 if(sess->voip_mtc_stat.pkt == 0) { 772 /* Consecutive losts */ 773 sess->voip_mtc_stat.c33++; 774 } 775 else { 776 /* Any good packets, but still bursting */ 777 sess->voip_mtc_stat.c23++; 778 sess->voip_mtc_stat.c22 += (sess->voip_mtc_stat.pkt - 1); 779 } 780 } 781 782 sess->voip_mtc_stat.pkt = 0; 783 } 784 } 785 } 786 787 void pjmedia_rtcp_xr_tx_rtp( pjmedia_rtcp_xr_session *session, 788 unsigned ptsize ) 789 { 790 PJ_UNUSED_ARG(session); 791 PJ_UNUSED_ARG(ptsize); 792 } 793 794 PJ_DEF(pj_status_t) pjmedia_rtcp_xr_update_info( 795 pjmedia_rtcp_xr_session *sess, 796 unsigned info, 797 pj_int32_t val) 798 { 799 int v = val; 800 801 switch(info) { 802 case PJMEDIA_RTCP_XR_INFO_SIGNAL_LVL: 803 sess->stat.tx.voip_mtc.signal_lvl = (pj_uint8_t) v; 804 break; 805 806 case PJMEDIA_RTCP_XR_INFO_NOISE_LVL: 807 sess->stat.tx.voip_mtc.noise_lvl = (pj_uint8_t) v; 808 break; 809 810 case PJMEDIA_RTCP_XR_INFO_RERL: 811 sess->stat.tx.voip_mtc.rerl = (pj_uint8_t) v; 812 break; 813 814 case PJMEDIA_RTCP_XR_INFO_R_FACTOR: 815 sess->stat.tx.voip_mtc.ext_r_factor = (pj_uint8_t) v; 816 break; 817 818 case PJMEDIA_RTCP_XR_INFO_MOS_LQ: 819 sess->stat.tx.voip_mtc.mos_lq = (pj_uint8_t) v; 820 break; 821 822 case PJMEDIA_RTCP_XR_INFO_MOS_CQ: 823 sess->stat.tx.voip_mtc.mos_cq = (pj_uint8_t) v; 824 break; 825 826 case PJMEDIA_RTCP_XR_INFO_CONF_PLC: 827 if (v >= 0 && v <= 3) { 828 sess->stat.tx.voip_mtc.rx_config &= 0x3F; 829 sess->stat.tx.voip_mtc.rx_config |= (pj_uint8_t) (v << 6); 830 } 831 break; 832 833 case PJMEDIA_RTCP_XR_INFO_CONF_JBA: 834 if (v >= 0 && v <= 3) { 835 sess->stat.tx.voip_mtc.rx_config &= 0xCF; 836 sess->stat.tx.voip_mtc.rx_config |= (pj_uint8_t) (v << 4); 837 } 838 break; 839 840 case PJMEDIA_RTCP_XR_INFO_CONF_JBR: 841 if (v >= 0 && v <= 15) { 842 sess->stat.tx.voip_mtc.rx_config &= 0xF0; 843 sess->stat.tx.voip_mtc.rx_config |= (pj_uint8_t) v; 844 } 845 break; 846 847 case PJMEDIA_RTCP_XR_INFO_JB_NOM: 848 sess->stat.tx.voip_mtc.jb_nom = (pj_uint16_t) v; 849 break; 850 851 case PJMEDIA_RTCP_XR_INFO_JB_MAX: 852 sess->stat.tx.voip_mtc.jb_max = (pj_uint16_t) v; 853 break; 854 855 case PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX: 856 sess->stat.tx.voip_mtc.jb_abs_max = (pj_uint16_t) v; 857 break; 858 859 default: 860 return PJ_EINVAL; 861 } 862 863 return PJ_SUCCESS; 864 } 865 866 #endif -
pjmedia/src/pjmedia/jbuf.c
67 67 int jb_max_prefetch; // Maximum allowable prefetch 68 68 int jb_status; // status is 'init' until the first 'put' operation 69 69 70 70 int jb_max_size; // Maximum frames buffered ever 71 71 }; 72 72 73 73 … … 368 368 jb->jb_stable_hist = 0; 369 369 jb->jb_status = JB_STATUS_INITIALIZING; 370 370 jb->jb_max_hist_level = 0; 371 jb->jb_max_size = 0; 371 372 372 373 jb_framelist_remove_head(&jb->jb_framelist, 373 374 jb_framelist_size(&jb->jb_framelist)); … … 383 384 384 385 static void jbuf_calculate_jitter(pjmedia_jbuf *jb) 385 386 { 386 int diff ;387 int diff, cur_size; 387 388 389 /* Update jb_max_size */ 390 cur_size = jb_framelist_size(&jb->jb_framelist); 391 if (cur_size > jb->jb_max_size) 392 jb->jb_max_size = cur_size; 393 388 394 /* Only apply burst-level calculation on PUT operation since if VAD is 389 395 * active the burst-level may not be accurate. 390 396 */ … … 413 419 jb->jb_prefetch = jb->jb_min_prefetch; 414 420 415 421 TRACE__((jb->name.ptr,"jb updated(1), prefetch=%d, size=%d", 416 jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist)));422 jb->jb_prefetch, cur_size)); 417 423 418 424 jb->jb_stable_hist = 0; 419 425 jb->jb_max_hist_level = 0; … … 432 438 jb->jb_max_hist_level = 0; 433 439 434 440 TRACE__((jb->name.ptr,"jb updated(2), prefetch=%d, size=%d", 435 jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist)));441 jb->jb_prefetch, cur_size)); 436 442 } 437 443 438 444 /* Level is unchanged */ … … 442 448 } 443 449 444 450 /* These code is used for shortening the delay in the jitter buffer. */ 445 diff = jb_framelist_size(&jb->jb_framelist)- jb->jb_prefetch;451 diff = cur_size - jb->jb_prefetch; 446 452 if (diff > SAFE_SHRINKING_DIFF) { 447 453 /* Shrink slowly */ 448 454 diff = 1; … … 471 477 pj_size_t frame_size, 472 478 int frame_seq) 473 479 { 480 pjmedia_jbuf_put_frame2(jb, frame, frame_size, frame_seq, NULL); 481 } 482 483 PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb, 484 const void *frame, 485 pj_size_t frame_size, 486 int frame_seq, 487 pj_bool_t *discarded) 488 { 474 489 pj_size_t min_frame_size; 475 490 int seq_diff; 476 491 … … 493 508 if (seq_diff > 0) { 494 509 495 510 while (jb_framelist_put_at(&jb->jb_framelist, 496 frame_seq,frame,min_frame_size) == PJ_FALSE)511 frame_seq,frame,min_frame_size) == PJ_FALSE) 497 512 { 498 513 jb_framelist_remove_head(&jb->jb_framelist, 499 514 PJ_MAX(jb->jb_max_count/4,1) ); … … 502 517 if (jb->jb_prefetch_cnt < jb->jb_prefetch) 503 518 jb->jb_prefetch_cnt += seq_diff; 504 519 520 if (discarded) 521 *discarded = PJ_FALSE; 505 522 } 506 523 else 507 524 { 508 jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size); 525 pj_bool_t res; 526 res = jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame, 527 min_frame_size); 528 if (discarded) 529 *discarded = !res; 509 530 } 510 531 } 511 532 … … 590 611 state->min_prefetch = jb->jb_min_prefetch; 591 612 state->max_prefetch = jb->jb_max_prefetch; 592 613 state->size = jb_framelist_size(&jb->jb_framelist); 614 state->max_size = jb->jb_max_size; 593 615 594 616 return PJ_SUCCESS; 595 617 } -
pjmedia/src/pjmedia/stream.c
470 470 (*stream->transport->op->send_rtcp)(stream->transport, 471 471 rtcp_pkt, len); 472 472 473 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 474 /* Temporarily always send RTCP XR after RTCP */ 475 if (stream->rtcp.xr_enabled) 476 { 477 int i; 478 pjmedia_jb_state jb_state; 479 480 pjmedia_jbuf_get_state(stream->jb, &jb_state); 481 482 i = jb_state.size * stream->codec_param.info.frm_ptime; 483 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 484 PJMEDIA_RTCP_XR_INFO_JB_NOM, 485 i); 486 487 i = jb_state.max_size* stream->codec_param.info.frm_ptime; 488 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 489 PJMEDIA_RTCP_XR_INFO_JB_MAX, 490 i); 491 492 pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0, 493 &rtcp_pkt, &len); 494 495 (*stream->transport->op->send_rtcp)(stream->transport, 496 rtcp_pkt, len); 497 } 498 #endif 499 473 500 stream->rtcp_last_tx = timestamp; 474 501 } 475 476 502 } 477 503 478 504 … … 974 1000 unsigned payloadlen; 975 1001 pjmedia_rtp_status seq_st; 976 1002 pj_status_t status; 1003 pj_bool_t pkt_discarded = PJ_FALSE; 977 1004 978 979 1005 /* Check for errors */ 980 1006 if (bytes_read < 0) { 981 1007 LOGERR_((stream->port.info.name.ptr, "RTP recv() error", -bytes_read)); … … 995 1021 return; 996 1022 } 997 1023 998 999 /* Inform RTCP session */1000 pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq),1001 pj_ntohl(hdr->ts), payloadlen);1002 1003 1024 /* Ignore the packet if decoder is paused */ 1004 1025 if (channel->paused) 1005 return;1026 goto on_return; 1006 1027 1007 1028 /* Update RTP session (also checks if RTP session can accept 1008 1029 * the incoming packet. … … 1025 1046 "Bad RTP pt %d (expecting %d)", 1026 1047 hdr->pt, channel->rtp.out_pt)); 1027 1048 } 1049 1050 if (seq_st.status.flag.badssrc) { 1051 PJ_LOG(4,(stream->port.info.name.ptr, 1052 "Changed RTP peer SSRC %d (previously %d)", 1053 channel->rtp.peer_ssrc, stream->rtcp.peer_ssrc)); 1054 stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc; 1055 } 1056 1057 1028 1058 } 1029 1059 1030 1060 /* Skip bad RTP packet */ 1031 if (seq_st.status.flag.bad) 1032 return; 1061 if (seq_st.status.flag.bad) { 1062 pkt_discarded = PJ_TRUE; 1063 goto on_return; 1064 } 1033 1065 1034 1066 /* Ignore if payloadlen is zero */ 1035 if (payloadlen == 0) 1036 return; 1067 if (payloadlen == 0) { 1068 pkt_discarded = PJ_TRUE; 1069 goto on_return; 1070 } 1037 1071 1038 1072 /* Handle incoming DTMF. */ 1039 1073 if (hdr->pt == stream->rx_event_pt) { … … 1041 1075 * digit. Also ignore duplicate packet as it serves no use. 1042 1076 */ 1043 1077 if (seq_st.status.flag.outorder || seq_st.status.flag.dup) { 1044 return;1078 goto on_return; 1045 1079 } 1046 1080 1047 1081 handle_incoming_dtmf(stream, payload, payloadlen); 1048 return;1082 goto on_return; 1049 1083 } 1050 1084 1051 1085 /* Put "good" packet to jitter buffer, or reset the jitter buffer … … 1151 1185 /* Put each frame to jitter buffer. */ 1152 1186 for (i=0; i<count; ++i) { 1153 1187 unsigned ext_seq; 1188 pj_bool_t discarded; 1154 1189 1155 1190 ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 1156 pjmedia_jbuf_put_frame(stream->jb, frames[i].buf, 1157 frames[i].size, ext_seq); 1158 1191 pjmedia_jbuf_put_frame2(stream->jb, frames[i].buf, frames[i].size, 1192 ext_seq, &discarded); 1193 if (discarded) 1194 pkt_discarded = PJ_TRUE; 1159 1195 } 1160 1196 } 1161 1197 pj_mutex_unlock( stream->jb_mutex ); … … 1172 1208 if (status != 0) { 1173 1209 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error", 1174 1210 status)); 1175 return; 1211 pkt_discarded = PJ_TRUE; 1212 goto on_return; 1176 1213 } 1214 1215 on_return: 1216 /* Update RTCP session */ 1217 if (stream->rtcp.peer_ssrc == 0) 1218 stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc; 1219 1220 pjmedia_rtcp_rx_rtp2(&stream->rtcp, pj_ntohs(hdr->seq), 1221 pj_ntohl(hdr->ts), payloadlen, pkt_discarded); 1177 1222 } 1178 1223 1179 1224 … … 1512 1557 1513 1558 stream->transport = tp; 1514 1559 1560 #if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR 1561 /* Enable RTCP XR and update some settings */ 1562 { 1563 int i; 1564 pjmedia_rtcp_enable_xr(&stream->rtcp, PJ_TRUE); 1515 1565 1566 /* jitter buffer adaptive info */ 1567 i = PJMEDIA_RTCP_XR_JB_ADAPTIVE; 1568 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 1569 PJMEDIA_RTCP_XR_INFO_CONF_JBA, 1570 i); 1571 1572 /* Jitter buffer aggressiveness info (estimated) */ 1573 i = 7; 1574 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 1575 PJMEDIA_RTCP_XR_INFO_CONF_JBR, 1576 i); 1577 1578 /* Jitter buffer absolute maximum delay */ 1579 i = jb_max * stream->codec_param.info.frm_ptime; 1580 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 1581 PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX, 1582 i); 1583 1584 /* PLC info */ 1585 if (stream->codec_param.setting.plc == 0) 1586 i = PJMEDIA_RTCP_XR_PLC_DIS; 1587 else 1588 #if PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA 1589 i = PJMEDIA_RTCP_XR_PLC_ENH; 1590 #else 1591 i = PJMEDIA_RTCP_XR_PLC_DIS; 1592 #endif 1593 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 1594 PJMEDIA_RTCP_XR_INFO_CONF_PLC, 1595 i); 1596 } 1597 #endif 1598 1516 1599 /* Success! */ 1517 1600 *p_stream = stream; 1518 1601 1519 1602 PJ_LOG(5,(THIS_FILE, "Stream %s created", stream->port.info.name.ptr)); 1603 1520 1604 return PJ_SUCCESS; 1521 1605 1522 1606 -
pjmedia/src/pjmedia/rtcp.c
28 28 29 29 #define RTCP_SR 200 30 30 #define RTCP_RR 201 31 #define RTCP_XR 207 31 32 32 33 33 #if PJ_HAS_HIGH_RES_TIMER==0 34 34 # error "High resolution timer needs to be enabled" 35 35 #endif … … 172 172 173 173 PJ_DEF(void) pjmedia_rtcp_fini(pjmedia_rtcp_session *sess) 174 174 { 175 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 176 pjmedia_rtcp_xr_fini(&sess->xr_session); 177 #else 175 178 /* Nothing to do. */ 176 179 PJ_UNUSED_ARG(sess); 180 #endif 177 181 } 178 182 179 183 static void rtcp_init_seq(pjmedia_rtcp_session *sess) … … 185 189 sess->jitter = 0; 186 190 } 187 191 188 PJ_DEF(void) pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *sess, 189 unsigned seq, 190 unsigned rtp_ts, 191 unsigned payload) 192 PJ_DEF(void) pjmedia_rtcp_rx_rtp( pjmedia_rtcp_session *sess, 193 unsigned seq, 194 unsigned rtp_ts, 195 unsigned payload) 196 { 197 pjmedia_rtcp_rx_rtp2(sess, seq, rtp_ts, payload, PJ_FALSE); 198 } 199 200 PJ_DEF(void) pjmedia_rtcp_rx_rtp2(pjmedia_rtcp_session *sess, 201 unsigned seq, 202 unsigned rtp_ts, 203 unsigned payload, 204 pj_bool_t discarded) 192 205 { 193 206 pj_timestamp ts; 194 207 pj_uint32_t arrival; … … 196 209 pjmedia_rtp_status seq_st; 197 210 unsigned last_seq; 198 211 212 #if !defined(PJMEDIA_HAS_RTCP_XR) || (PJMEDIA_HAS_RTCP_XR == 0) 213 PJ_UNUSED_ARG(discarded); 214 #endif 215 199 216 if (sess->stat.rx.pkt == 0) { 200 217 /* Init sequence for the first time. */ 201 218 pjmedia_rtp_seq_init(&sess->seq_ctrl, (pj_uint16_t)seq); … … 224 241 225 242 if (seq_st.status.flag.bad) { 226 243 sess->stat.rx.discard++; 244 245 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 246 pjmedia_rtcp_xr_rx_rtp(&sess->xr_session, seq, 247 -1, /* lost */ 248 (seq_st.status.flag.dup? 1:0), /* dup */ 249 (!seq_st.status.flag.dup? 1:-1), /* discard */ 250 -1, /* jitter */ 251 -1, 0); /* toh */ 252 #endif 253 227 254 TRACE_((sess->name, "Bad packet discarded")); 228 255 return; 229 256 } … … 316 343 sess->stat.rx.jitter.max = jitter; 317 344 318 345 sess->stat.rx.jitter.last = jitter; 346 347 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 348 pjmedia_rtcp_xr_rx_rtp(&sess->xr_session, seq, 349 0, /* lost */ 350 0, /* dup */ 351 discarded, /* discard */ 352 (sess->jitter >> 4), /* jitter */ 353 -1, 0); /* toh */ 354 #endif 319 355 } 356 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 357 } else if (seq_st.diff > 1) { 358 int i; 359 360 /* Report RTCP XR about packet losses */ 361 for (i=seq_st.diff-1; i>0; --i) { 362 pjmedia_rtcp_xr_rx_rtp(&sess->xr_session, seq - i, 363 1, /* lost */ 364 0, /* dup */ 365 0, /* discard */ 366 -1, /* jitter */ 367 -1, 0); /* toh */ 368 } 369 370 /* Report RTCP XR this packet */ 371 pjmedia_rtcp_xr_rx_rtp(&sess->xr_session, seq, 372 0, /* lost */ 373 0, /* dup */ 374 discarded, /* discard */ 375 -1, /* jitter */ 376 -1, 0); /* toh */ 377 #endif 320 378 } 321 379 322 380 /* Update timestamp of last RX RTP packet */ … … 348 406 rr = (pjmedia_rtcp_rr*)(((char*)pkt) + (sizeof(pjmedia_rtcp_common) 349 407 + sizeof(pjmedia_rtcp_sr))); 350 408 } 351 } else if (common->pt == RTCP_RR && common->count > 0) 409 } else if (common->pt == RTCP_RR && common->count > 0) { 352 410 rr = (pjmedia_rtcp_rr*)(((char*)pkt) + sizeof(pjmedia_rtcp_common)); 411 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 412 } else if (common->pt == RTCP_XR) { 413 if (sess->xr_enabled) 414 pjmedia_rtcp_xr_rx_rtcp_xr(&sess->xr_session, pkt, size); 353 415 416 return; 417 #endif 418 } 354 419 420 355 421 if (sr) { 356 422 /* Save LSR from NTP timestamp of RTCP packet */ 357 423 sess->rx_lsr = ((pj_ntohl(sr->ntp_sec) & 0x0000FFFF) << 16) | … … 674 740 sess->stat.rx.update_cnt++; 675 741 } 676 742 677 743 PJ_DEF(pj_status_t) pjmedia_rtcp_enable_xr( pjmedia_rtcp_session *sess, 744 pj_bool_t enable) 745 { 746 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 747 748 /* Check if request won't change anything */ 749 if (!(enable ^ sess->xr_enabled)) 750 return PJ_SUCCESS; 751 752 if (!enable) { 753 sess->xr_enabled = PJ_FALSE; 754 return PJ_SUCCESS; 755 } 756 757 pjmedia_rtcp_xr_init(&sess->xr_session, sess, 0, 1); 758 sess->xr_enabled = PJ_TRUE; 759 760 return PJ_SUCCESS; 761 762 #else 763 764 PJ_UNUSED_ARG(sess); 765 PJ_UNUSED_ARG(enable); 766 return PJ_ENOTSUP; 767 768 #endif 769 }