Changeset 408 for pjproject/trunk
- Timestamp:
- Apr 24, 2006 11:13:00 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 11 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/jbuf.h
r228 r408 64 64 * 65 65 * @param pool The pool to allocate memory. 66 * @param name Name to identify the jitter buffer for logging 67 * purpose. 66 68 * @param frame_size The size of each frame that will be kept in the 67 69 * jitter buffer. The value here normaly corresponds … … 74 76 * @return PJ_SUCCESS on success. 75 77 */ 76 PJ_DECL(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 77 int frame_size, 78 int init_delay, 79 int max_count, 80 pjmedia_jbuf **p_jb); 78 PJ_DECL(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 79 const pj_str_t *name, 80 int frame_size, 81 int init_delay, 82 int max_count, 83 pjmedia_jbuf **p_jb); 81 84 82 85 /** … … 88 91 */ 89 92 PJ_DECL(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb); 93 94 95 /** 96 * Restart jitter. This function flushes all packets in the buffer and 97 * reset the internal sequence number. 98 * 99 * @param jb The jitter buffer. 100 * 101 * @return PJ_SUCCESS on success. 102 */ 103 PJ_DECL(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb); 90 104 91 105 -
pjproject/trunk/pjmedia/include/pjmedia/rtcp.h
r403 r408 222 222 struct pjmedia_rtcp_session 223 223 { 224 char *name; /**< Name identification. */ 224 225 pjmedia_rtcp_pkt rtcp_pkt; /**< Cached RTCP packet. */ 225 226 … … 254 255 * 255 256 * @param session The session 257 * @param name Optional name to identify the session (for 258 * logging purpose). 256 259 * @param clock_rate Codec clock rate in samples per second. 257 260 * @param samples_per_frame Average number of samples per frame. … … 259 262 */ 260 263 PJ_DECL(void) pjmedia_rtcp_init( pjmedia_rtcp_session *session, 264 char *name, 261 265 unsigned clock_rate, 262 266 unsigned samples_per_frame, -
pjproject/trunk/pjmedia/include/pjmedia/rtp.h
r390 r408 193 193 in other flags. */ 194 194 int badpt:1; /**< Bad payload type. */ 195 int badssrc:1; /**< Bad SSRC */ 195 196 int dup:1; /**< Indicates duplicate packet */ 196 197 int outorder:1; /**< Indicates out of order packet */ -
pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
r229 r408 48 48 struct pjmedia_jbuf 49 49 { 50 pj_str_t name; // jitter buffer name 50 51 jb_framelist jb_framelist; 51 52 pj_size_t jb_frame_size; // frame size … … 94 95 framelist->flist_max_count); 95 96 96 framelist->flist_frame_type = pj_pool_zalloc(pool,97 98 97 framelist->flist_frame_type = 98 pj_pool_zalloc(pool, sizeof(framelist->flist_frame_type[0]) * 99 framelist->flist_max_count); 99 100 100 101 framelist->flist_empty = 1; 101 framelist->flist_head = framelist->flist_tail = framelist->flist_origin = 0;102 102 103 103 return PJ_SUCCESS; … … 129 129 if (!framelist->flist_empty) { 130 130 pj_memcpy(frame, 131 framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 131 framelist->flist_buffer + 132 framelist->flist_head * framelist->flist_frame_size, 132 133 framelist->flist_frame_size); 133 *p_type = (pjmedia_jb_frame_type) framelist->flist_frame_type[framelist->flist_head]; 134 135 pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 134 *p_type = (pjmedia_jb_frame_type) 135 framelist->flist_frame_type[framelist->flist_head]; 136 137 pj_memset(framelist->flist_buffer + 138 framelist->flist_head * framelist->flist_frame_size, 136 139 0, framelist->flist_frame_size); 137 140 framelist->flist_frame_type[framelist->flist_head] = 0; 138 141 139 142 framelist->flist_origin++; 140 framelist->flist_head = ++framelist->flist_head % framelist->flist_max_count; 143 framelist->flist_head = (framelist->flist_head + 1 ) % 144 framelist->flist_max_count; 141 145 if (framelist->flist_head == framelist->flist_tail) 142 146 framelist->flist_empty = PJ_TRUE; … … 173 177 } 174 178 175 pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 179 pj_memset(framelist->flist_buffer + 180 framelist->flist_head * framelist->flist_frame_size, 176 181 0, 177 182 step1*framelist->flist_frame_size); … … 191 196 // update pointers 192 197 framelist->flist_origin += count; 193 framelist->flist_head = (framelist->flist_head+count) % framelist->flist_max_count; 198 framelist->flist_head = (framelist->flist_head + count) % 199 framelist->flist_max_count; 194 200 if (framelist->flist_head == framelist->flist_tail) 195 201 framelist->flist_empty = PJ_TRUE; … … 205 211 unsigned where; 206 212 207 // too late208 if (index < framelist->flist_origin)209 return PJ_FALSE;210 211 // too soon212 if ((index > (framelist->flist_origin + framelist->flist_max_count - 1)) && !framelist->flist_empty)213 return PJ_FALSE;214 215 213 assert(frame_size <= framelist->flist_frame_size); 216 214 217 215 if (!framelist->flist_empty) { 216 unsigned max_index; 218 217 unsigned cur_size; 219 218 220 where = (index - framelist->flist_origin + framelist->flist_head) % framelist->flist_max_count; 219 // too late 220 if (index < framelist->flist_origin) 221 return PJ_FALSE; 222 223 // too soon 224 max_index = framelist->flist_origin + framelist->flist_max_count - 1; 225 if (index > max_index) 226 return PJ_FALSE; 227 228 where = (index - framelist->flist_origin + framelist->flist_head) % 229 framelist->flist_max_count; 221 230 222 231 // update framelist->flist_tail pointer … … 224 233 if (index >= framelist->flist_origin + cur_size) { 225 234 unsigned diff = (index - (framelist->flist_origin + cur_size)); 226 framelist->flist_tail = (framelist->flist_tail + diff + 1) % framelist->flist_max_count; 235 framelist->flist_tail = (framelist->flist_tail + diff + 1) % 236 framelist->flist_max_count; 227 237 } 228 238 } else { 229 239 where = framelist->flist_tail; 230 240 framelist->flist_origin = index; 231 framelist->flist_tail = (++framelist->flist_tail % framelist->flist_max_count); 241 framelist->flist_tail = (framelist->flist_tail + 1) % 242 framelist->flist_max_count; 232 243 framelist->flist_empty = PJ_FALSE; 233 244 } … … 252 263 253 264 PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 265 const pj_str_t *name, 254 266 int frame_size, 255 267 int initial_prefetch, … … 266 278 return status; 267 279 280 pj_strdup_with_null(pool, &jb->name, name); 268 281 jb->jb_frame_size = frame_size; 269 282 jb->jb_last_seq_no = -1; … … 284 297 285 298 299 PJ_DEF(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb) 300 { 301 jb->jb_last_seq_no = -1; 302 jb->jb_level = 0; 303 jb->jb_last_level = 0; 304 jb->jb_last_jitter = 0; 305 jb->jb_last_op = JB_OP_INIT; 306 jb->jb_prefetch_cnt = 0; 307 jb->jb_stable_hist = 0; 308 jb->jb_status = JB_STATUS_INITIALIZING; 309 jb->jb_max_hist_jitter = 0; 310 311 jb_framelist_remove_head(&jb->jb_framelist, 312 jb_framelist_size(&jb->jb_framelist)); 313 return PJ_SUCCESS; 314 } 315 316 286 317 PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb) 287 318 { … … 312 343 313 344 if (jb->jb_op_count >= 100 && 314 (int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) 345 (int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) 315 346 { 316 347 jb_framelist_remove_head(&jb->jb_framelist,1); 317 348 318 PJ_LOG(5,(THIS_FILE, "jbuf prefetch: %d, size=%d", 319 jb->jb_prefetch, 320 jb_framelist_size(&jb->jb_framelist))); 349 PJ_LOG(5,(jb->name.ptr, 350 "jbuf optimizing, prefetch: %d, size=%d", 351 jb->jb_prefetch, 352 jb_framelist_size(&jb->jb_framelist))); 321 353 jb->jb_op_count = 0; 322 354 } … … 324 356 } 325 357 } else { 326 jb->jb_prefetch = PJ_MIN(jb->jb_last_jitter,(int)(jb->jb_max_count*4/5)); 358 jb->jb_prefetch = PJ_MIN(jb->jb_last_jitter, 359 (int)(jb->jb_max_count*4/5)); 327 360 jb->jb_stable_hist = 0; 328 361 jb->jb_max_hist_jitter = 0; 329 362 330 363 if (jb->jb_op_count >= 100) { 331 if ((int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) { 364 if ((int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) 365 { 332 366 jb_framelist_remove_head(&jb->jb_framelist,1); 333 367 334 PJ_LOG(5,(THIS_FILE, "jbuf prefetch: %d, size=%d", 335 jb->jb_prefetch, 336 jb_framelist_size(&jb->jb_framelist))); 368 PJ_LOG(5,(jb->name.ptr, 369 "jbuf optimizing prefetch: %d, size=%d", 370 jb->jb_prefetch, 371 jb_framelist_size(&jb->jb_framelist))); 337 372 } 338 373 … … 378 413 if (seq_diff > 0) { 379 414 380 while (!jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size)) { 381 jb_framelist_remove_head(&jb->jb_framelist,PJ_MAX(jb->jb_max_count/4,1)); 415 while (jb_framelist_put_at(&jb->jb_framelist, 416 frame_seq,frame,min_frame_size) ==PJ_FALSE) 417 { 418 jb_framelist_remove_head(&jb->jb_framelist, 419 PJ_MAX(jb->jb_max_count/4,1) ); 382 420 } 383 421 … … 408 446 } 409 447 410 if ((jb->jb_prefetch_cnt < jb->jb_prefetch) || !jb_framelist_get(&jb->jb_framelist,frame,&ftype)) { 448 if ((jb->jb_prefetch_cnt < jb->jb_prefetch) || 449 jb_framelist_get(&jb->jb_framelist,frame,&ftype) == PJ_FALSE) 450 { 411 451 pj_memset(frame, 0, jb->jb_frame_size); 412 452 *p_frame_type = PJMEDIA_JB_ZERO_FRAME; -
pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
r403 r408 110 110 if (PJ_TIME_VAL_MSEC(diff) >= MIN_DIFF) { 111 111 112 TRACE_(( THIS_FILE, "NTP timestamp corrected by %d ms",112 TRACE_((sess->name, "RTCP NTP timestamp corrected by %d ms", 113 113 PJ_TIME_VAL_MSEC(diff))); 114 114 … … 126 126 127 127 PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *sess, 128 char *name, 128 129 unsigned clock_rate, 129 130 unsigned samples_per_frame, … … 135 136 pj_memset(rtcp_pkt, 0, sizeof(pjmedia_rtcp_pkt)); 136 137 138 /* Name */ 139 sess->name = name ? name : THIS_FILE, 140 137 141 /* Set clock rate */ 138 142 sess->clock_rate = clock_rate; … … 238 242 239 243 /* 240 * Calculate jitter (see RFC 3550 section A.8)244 * Calculate jitter only when sequence is good (see RFC 3550 section A.8) 241 245 */ 242 243 /* Get arrival time and convert timestamp to samples */ 244 pj_get_timestamp(&ts); 245 ts.u64 = ts.u64 * sess->clock_rate / sess->ts_freq.u64; 246 arrival = ts.u32.lo; 247 248 transit = arrival - rtp_ts; 249 250 /* Ignore the first N packets as they normally have bad jitter 251 * due to other threads working to establish the call 252 */ 253 if (sess->transit == 0 || sess->received < 25 ) { 254 sess->transit = transit; 255 sess->stat.rx.jitter.min = 2000; 256 } else { 257 pj_int32_t d; 258 pj_uint32_t jitter; 259 260 d = transit - sess->transit; 261 sess->transit = transit; 262 if (d < 0) 263 d = -d; 264 265 sess->jitter += d - ((sess->jitter + 8) >> 4); 266 267 /* Get jitter in usec */ 268 if (d < 4294) 269 jitter = d * 1000000 / sess->clock_rate; 270 else { 271 jitter = d * 1000 / sess->clock_rate; 272 jitter *= 1000; 246 if (seq_st.diff == 1) { 247 /* Get arrival time and convert timestamp to samples */ 248 pj_get_timestamp(&ts); 249 ts.u64 = ts.u64 * sess->clock_rate / sess->ts_freq.u64; 250 arrival = ts.u32.lo; 251 252 transit = arrival - rtp_ts; 253 254 /* Ignore the first N packets as they normally have bad jitter 255 * due to other threads working to establish the call 256 */ 257 if (sess->transit == 0 || sess->received < 25 ) { 258 sess->transit = transit; 259 sess->stat.rx.jitter.min = 2000; 260 } else { 261 pj_int32_t d; 262 pj_uint32_t jitter; 263 264 d = transit - sess->transit; 265 sess->transit = transit; 266 if (d < 0) 267 d = -d; 268 269 sess->jitter += d - ((sess->jitter + 8) >> 4); 270 271 /* Get jitter in usec */ 272 if (d < 4294) 273 jitter = d * 1000000 / sess->clock_rate; 274 else { 275 jitter = d * 1000 / sess->clock_rate; 276 jitter *= 1000; 277 } 278 279 /* Update jitter stat */ 280 if (jitter < sess->stat.rx.jitter.min) 281 sess->stat.rx.jitter.min = jitter; 282 if (jitter > sess->stat.rx.jitter.max) 283 sess->stat.rx.jitter.max = jitter; 284 sess->stat.rx.jitter.last = jitter; 273 285 } 274 275 /* Update jitter stat */276 if (jitter < sess->stat.rx.jitter.min)277 sess->stat.rx.jitter.min = jitter;278 if (jitter > sess->stat.rx.jitter.max)279 sess->stat.rx.jitter.max = jitter;280 sess->stat.rx.jitter.last = jitter;281 286 } 282 287 } … … 308 313 pj_get_timestamp(&sess->rx_lsr_time); 309 314 310 TRACE_(( THIS_FILE, "Rx RTCP SR: ntp_ts=%p",315 TRACE_((sess->name, "Rx RTCP SR: ntp_ts=%p", 311 316 sess->rx_lsr, 312 317 (pj_uint32_t)(sess->rx_lsr_time.u64*65536/sess->ts_freq.u64))); … … 405 410 } 406 411 407 TRACE_(( THIS_FILE, "Rx RTCP RR: lsr=%p, dlsr=%p (%d:%03dms), "412 TRACE_((sess->name, "Rx RTCP RR: lsr=%p, dlsr=%p (%d:%03dms), " 408 413 "now=%p, rtt=%p", 409 414 lsr, dlsr, dlsr/65536, (dlsr%65536)*1000/65536, … … 416 421 unsigned rtt = (pj_uint32_t)eedelay; 417 422 418 TRACE_(( THIS_FILE, "RTT is set to %d usec", rtt));423 TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt)); 419 424 420 425 if (rtt >= 1000000) { … … 441 446 442 447 } else { 443 PJ_LOG(5, ( THIS_FILE, "InternalNTP clock skew detected: "448 PJ_LOG(5, (sess->name, "Internal RTCP NTP clock skew detected: " 444 449 "lsr=%p, now=%p, dlsr=%p (%d:%03dms), " 445 450 "diff=%d", … … 526 531 rtcp_pkt->sr.ntp_frac = pj_htonl(ntp.lo); 527 532 528 TRACE_(( THIS_FILE, "TX RTCP SR: ntp_ts=%p",533 TRACE_((sess->name, "TX RTCP SR: ntp_ts=%p", 529 534 ((ntp.hi & 0xFFFF) << 16) + ((ntp.lo & 0xFFFF0000) 530 535 >> 16))); … … 559 564 rtcp_pkt->rr.dlsr = pj_htonl(dlsr); 560 565 561 TRACE_(( THIS_FILE,"Tx RTCP RR: lsr=%p, lsr_time=%p, now=%p, dlsr=%p"566 TRACE_((sess->name,"Tx RTCP RR: lsr=%p, lsr_time=%p, now=%p, dlsr=%p" 562 567 "(%ds:%03dms)", 563 568 lsr, -
pjproject/trunk/pjmedia/src/pjmedia/rtp.c
r390 r408 20 20 #include <pjmedia/errno.h> 21 21 #include <pj/log.h> 22 #include <pj/os.h> /* pj_gettimeofday() */23 22 #include <pj/sock.h> /* pj_htonx, pj_htonx */ 24 23 #include <pj/assert.h> 24 #include <pj/rand.h> 25 25 #include <pj/string.h> 26 26 … … 40 40 41 41 PJ_DEF(pj_status_t) pjmedia_rtp_session_init( pjmedia_rtp_session *ses, 42 int default_pt, pj_uint32_t sender_ssrc ) 43 { 44 PJ_LOG(5, (THIS_FILE, "pjmedia_rtp_session_init: ses=%p, default_pt=%d, ssrc=0x%x", 42 int default_pt, 43 pj_uint32_t sender_ssrc ) 44 { 45 PJ_LOG(5, (THIS_FILE, 46 "pjmedia_rtp_session_init: ses=%p, default_pt=%d, ssrc=0x%x", 45 47 ses, default_pt, sender_ssrc)); 46 48 … … 51 53 } 52 54 53 /* If sender_ssrc is not specified, create from timevalue. */55 /* If sender_ssrc is not specified, create from random value. */ 54 56 if (sender_ssrc == 0 || sender_ssrc == (pj_uint32_t)-1) { 55 pj_time_val tv; 56 57 pj_gettimeofday(&tv); 58 sender_ssrc = (pj_uint32_t) pj_htonl(tv.sec); 57 sender_ssrc = pj_htonl(pj_rand()); 59 58 } else { 60 59 sender_ssrc = pj_htonl(sender_ssrc); 61 60 } 62 61 63 /* Initialize session. */ 64 ses->out_extseq = 0; 62 /* Initialize session. 63 * Initial sequence number SHOULD be random, according to RFC 3550. 64 */ 65 ses->out_extseq = pj_rand(); 65 66 ses->peer_ssrc = 0; 66 67 67 /* Sequence number will be initialized when the first RTP packet is receieved. */ 68 /* Sequence number will be initialized when the first RTP packet 69 * is receieved. 70 */ 68 71 69 72 /* Build default header for outgoing RTP packet. */ … … 86 89 87 90 88 PJ_DEF(pj_status_t) pjmedia_rtp_encode_rtp( pjmedia_rtp_session *ses, int pt, int m, 89 int payload_len, int ts_len, 90 const void **rtphdr, int *hdrlen ) 91 { 92 PJ_UNUSED_ARG(payload_len) 93 94 PJ_LOG(6, (THIS_FILE, 95 "pjmedia_rtp_encode_rtp: ses=%p, pt=%d, m=%d, pt_len=%d, ts_len=%d", 96 ses, pt, m, payload_len, ts_len)); 91 PJ_DEF(pj_status_t) pjmedia_rtp_encode_rtp( pjmedia_rtp_session *ses, 92 int pt, int m, 93 int payload_len, int ts_len, 94 const void **rtphdr, int *hdrlen ) 95 { 96 PJ_UNUSED_ARG(payload_len); 97 97 98 98 /* Update timestamp */ … … 122 122 123 123 PJ_DEF(pj_status_t) pjmedia_rtp_decode_rtp( pjmedia_rtp_session *ses, 124 125 126 127 124 const void *pkt, int pkt_len, 125 const pjmedia_rtp_hdr **hdr, 126 const void **payload, 127 unsigned *payloadlen) 128 128 { 129 129 int offset; 130 130 131 PJ_UNUSED_ARG(ses) 132 133 PJ_LOG(6, (THIS_FILE, 134 "pjmedia_rtp_decode_rtp: ses=%p, pkt=%p, pkt_len=%d", 135 ses, pkt, pkt_len)); 131 PJ_UNUSED_ARG(ses); 136 132 137 133 /* Assume RTP header at the start of packet. We'll verify this later. */ … … 140 136 /* Check RTP header sanity. */ 141 137 if ((*hdr)->v != RTP_VERSION) { 142 PJ_LOG(4, (THIS_FILE, " invalid RTP version!"));143 138 return PJMEDIA_RTP_EINVER; 144 139 } … … 149 144 /* Adjust offset if RTP extension is used. */ 150 145 if ((*hdr)->x) { 151 pjmedia_rtp_ext_hdr *ext = (pjmedia_rtp_ext_hdr*) (((pj_uint8_t*)pkt) + offset); 146 pjmedia_rtp_ext_hdr *ext = (pjmedia_rtp_ext_hdr*) 147 (((pj_uint8_t*)pkt) + offset); 152 148 offset += (pj_ntohs(ext->length) * sizeof(pj_uint32_t)); 153 149 } … … 171 167 pjmedia_rtp_status seq_st; 172 168 173 /* Check SSRC. */174 if (ses->peer_ssrc == 0) ses->peer_ssrc = pj_ntohl(hdr->ssrc);175 /*176 if (pj_ntohl(ses->peer_ssrc) != hdr->ssrc) {177 PJ_LOG(4, (THIS_FILE, "pjmedia_rtp_session_update: ses=%p, invalid ssrc 0x%p (!=0x%p)",178 ses, pj_ntohl(hdr->ssrc), ses->peer_ssrc));179 return PJMEDIA_RTP_EINSSRC;180 }181 */182 183 169 /* Init status */ 184 170 seq_st.status.value = 0; 185 171 seq_st.diff = 0; 186 172 173 /* Check SSRC. */ 174 if (ses->peer_ssrc == 0) ses->peer_ssrc = pj_ntohl(hdr->ssrc); 175 176 if (pj_ntohl(hdr->ssrc) != ses->peer_ssrc) { 177 seq_st.status.flag.badssrc = 1; 178 ses->peer_ssrc = pj_ntohl(hdr->ssrc); 179 } 180 187 181 /* Check payload type. */ 188 182 if (hdr->pt != ses->out_pt) { 189 PJ_LOG(4, (THIS_FILE,190 "pjmedia_rtp_session_update: ses=%p, invalid payload "191 "type %d (expecting %d)",192 ses, hdr->pt, ses->out_pt));193 183 if (p_seq_st) { 184 p_seq_st->status.value = seq_st.status.value; 194 185 p_seq_st->status.flag.bad = 1; 195 186 p_seq_st->status.flag.badpt = 1; -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r402 r408 38 38 #define THIS_FILE "stream.c" 39 39 #define ERRLEVEL 1 40 #define TRACE_(expr) stream_perror expr41 #define TRC_(expr) PJ_LOG( 4,expr)40 #define LOGERR_(expr) stream_perror expr 41 #define TRC_(expr) PJ_LOG(5,expr) 42 42 43 43 /** … … 107 107 pj_size_t rtcp_pkt_size; /**< Size of RTCP packet buf. */ 108 108 char rtcp_pkt[512]; /**< RTCP packet buffer. */ 109 pj_uint32_t rtcp_tx_time; /**< RTCP tx time in timestamp */ 109 pj_uint32_t rtcp_last_tx; /**< RTCP tx time in timestamp */ 110 pj_uint32_t rtcp_interval; /**< Interval, in timestamp. */ 110 111 int rtcp_addrlen; /**< Address length. */ 111 112 … … 184 185 channel->pcm_buf_size, &frame_out); 185 186 if (status != 0) { 186 TRACE_((THIS_FILE, "codec decode() error", status));187 LOGERR_((port->info.name.ptr, "codec decode() error", status)); 187 188 188 189 frame->type = PJMEDIA_FRAME_TYPE_NONE; … … 192 193 /* Put in sound buffer. */ 193 194 if (frame_out.size > frame->size) { 194 PJ_LOG(4,(THIS_FILE, "Sound playout buffer truncated %d bytes", 195 PJ_LOG(4,(port->info.name.ptr, 196 "Sound playout buffer truncated %d bytes", 195 197 frame_out.size - frame->size)); 196 198 frame_out.size = frame->size; … … 240 242 241 243 if (stream->tx_dtmf_count) 242 PJ_LOG(5,(THIS_FILE,"Sending DTMF digit id %c", 244 PJ_LOG(5,(stream->port.info.name.ptr, 245 "Sending DTMF digit id %c", 243 246 digitmap[stream->tx_dtmf_buf[0].event])); 244 247 245 248 } else if (duration == 0) { 246 PJ_LOG(5,( THIS_FILE,"Sending DTMF digit id %c",249 PJ_LOG(5,(stream->port.info.name.ptr, "Sending DTMF digit id %c", 247 250 digitmap[digit->event])); 248 251 } … … 252 255 } 253 256 257 254 258 /** 255 * rec_callback()259 * check_tx_rtcp() 256 260 * 257 * This callback is called when the mic device has gathered 258 * enough audio samples. We will encode the audio samples and 259 * send it to remote. 260 */ 261 static pj_status_t put_frame( pjmedia_port *port, 262 const pjmedia_frame *frame ) 263 { 264 pjmedia_stream *stream = port->user_data; 265 pjmedia_channel *channel = stream->enc; 266 pj_status_t status = 0; 267 struct pjmedia_frame frame_out; 268 int ts_len; 269 pj_bool_t has_tx; 270 void *rtphdr; 271 int rtphdrlen; 272 pj_ssize_t sent; 273 274 /* Number of samples in the frame */ 275 ts_len = frame->size / 2; 276 277 /* Init frame_out buffer. */ 278 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 279 280 /* Make compiler happy */ 281 frame_out.size = 0; 282 283 /* If we have DTMF digits in the queue, transmit the digits. 284 * Otherwise encode the PCM buffer. 261 * This function is can be called by either put_frame() or get_frame(), 262 * to transmit periodic RTCP SR/RR report. 263 */ 264 static void check_tx_rtcp(pjmedia_stream *stream, pj_uint32_t timestamp) 265 { 266 /* Note that timestamp may represent local or remote timestamp, 267 * depending on whether this function is called from put_frame() 268 * or get_frame(). 285 269 */ 286 if (stream->tx_dtmf_count) { 287 288 has_tx = PJ_TRUE; 289 create_dtmf_payload(stream, &frame_out); 290 291 /* Encapsulate. */ 292 status = pjmedia_rtp_encode_rtp( &channel->rtp, 293 stream->tx_event_pt, 0, 294 frame_out.size, ts_len, 295 (const void**)&rtphdr, 296 &rtphdrlen); 297 298 } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { 299 unsigned max_size; 300 301 has_tx = PJ_TRUE; 302 max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr); 303 status = stream->codec->op->encode( stream->codec, frame, 304 max_size, 305 &frame_out); 306 if (status != 0) { 307 TRACE_((THIS_FILE, "Codec encode() error", status)); 308 return status; 309 } 310 311 //printf("p"); fflush(stdout); 312 313 /* Encapsulate. */ 314 status = pjmedia_rtp_encode_rtp( &channel->rtp, 315 channel->pt, 0, 316 frame_out.size, ts_len, 317 (const void**)&rtphdr, 318 &rtphdrlen); 319 } else { 320 321 /* Just update RTP session's timestamp. */ 322 has_tx = PJ_FALSE; 323 status = pjmedia_rtp_encode_rtp( &channel->rtp, 324 0, 0, 325 0, ts_len, 326 (const void**)&rtphdr, 327 &rtphdrlen); 328 329 } 330 331 if (status != PJ_SUCCESS) { 332 TRACE_((THIS_FILE, "RTP encode_rtp() error", status)); 333 return status; 334 } 335 336 /* Check if this is the time to transmit RTCP packet */ 337 if (stream->rtcp_tx_time == 0) { 338 unsigned first_interval; 339 340 first_interval = PJMEDIA_RTCP_INTERVAL + (pj_rand() % 2000); 341 stream->rtcp_tx_time = pj_ntohl(channel->rtp.out_hdr.ts) + 342 first_interval* stream->port.info.sample_rate / 343 1000; 344 } else if (pj_ntohl(channel->rtp.out_hdr.ts) >= stream->rtcp_tx_time) { 270 271 272 if (stream->rtcp_last_tx == 0) { 273 274 stream->rtcp_last_tx = timestamp; 275 276 } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) { 345 277 346 278 pjmedia_rtcp_pkt *rtcp_pkt; 347 279 pj_ssize_t size; 348 unsigned interval;349 280 int len; 281 pj_status_t status; 350 282 351 283 pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len); … … 359 291 360 292 pj_strerror(status, errmsg, sizeof(errmsg)); 361 PJ_LOG(4,( THIS_FILE, "Error sending RTCP: %s [%d]",293 PJ_LOG(4,(port->info.name.ptr, "Error sending RTCP: %s [%d]", 362 294 errmsg, status)); 363 295 } 364 296 #endif 365 297 366 interval = PJMEDIA_RTCP_INTERVAL + (pj_rand() % 500); 367 stream->rtcp_tx_time = pj_ntohl(channel->rtp.out_hdr.ts) + 368 interval * stream->port.info.sample_rate / 369 1000; 298 stream->rtcp_last_tx = timestamp; 299 } 300 301 } 302 303 304 /** 305 * put_frame() 306 * 307 * This callback is called by upstream component when it has PCM frame 308 * to transmit. This function encodes the PCM frame, pack it into 309 * RTP packet, and transmit to peer. 310 */ 311 static pj_status_t put_frame( pjmedia_port *port, 312 const pjmedia_frame *frame ) 313 { 314 pjmedia_stream *stream = port->user_data; 315 pjmedia_channel *channel = stream->enc; 316 pj_status_t status = 0; 317 struct pjmedia_frame frame_out; 318 int ts_len; 319 pj_bool_t has_tx; 320 void *rtphdr; 321 int rtphdrlen; 322 pj_ssize_t sent; 323 324 /* Number of samples in the frame */ 325 ts_len = frame->size / 2; 326 327 /* Init frame_out buffer. */ 328 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 329 330 /* Make compiler happy */ 331 frame_out.size = 0; 332 333 /* If we have DTMF digits in the queue, transmit the digits. 334 * Otherwise encode the PCM buffer. 335 */ 336 if (stream->tx_dtmf_count) { 337 338 has_tx = PJ_TRUE; 339 create_dtmf_payload(stream, &frame_out); 340 341 /* Encapsulate. */ 342 status = pjmedia_rtp_encode_rtp( &channel->rtp, 343 stream->tx_event_pt, 0, 344 frame_out.size, ts_len, 345 (const void**)&rtphdr, 346 &rtphdrlen); 347 348 } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { 349 unsigned max_size; 350 351 has_tx = PJ_TRUE; 352 max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr); 353 status = stream->codec->op->encode( stream->codec, frame, 354 max_size, 355 &frame_out); 356 if (status != 0) { 357 LOGERR_((stream->port.info.name.ptr, 358 "Codec encode() error", status)); 359 return status; 360 } 361 362 //printf("p"); fflush(stdout); 363 364 /* Encapsulate. */ 365 status = pjmedia_rtp_encode_rtp( &channel->rtp, 366 channel->pt, 0, 367 frame_out.size, ts_len, 368 (const void**)&rtphdr, 369 &rtphdrlen); 370 } else { 371 372 /* Just update RTP session's timestamp. */ 373 has_tx = PJ_FALSE; 374 status = pjmedia_rtp_encode_rtp( &channel->rtp, 375 0, 0, 376 0, ts_len, 377 (const void**)&rtphdr, 378 &rtphdrlen); 379 380 } 381 382 if (status != PJ_SUCCESS) { 383 LOGERR_((stream->port.info.name.ptr, 384 "RTP encode_rtp() error", status)); 385 return status; 386 } 387 388 /* Check if now is the time to transmit RTCP SR/RR report. 389 * We only do this when stream direction is not "decoding only", because 390 * when it is, check_tx_rtcp() will be handled by get_frame(). 391 */ 392 if (stream->dir != PJMEDIA_DIR_DECODING) { 393 check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts)); 370 394 } 371 395 … … 450 474 /* Ignore unknown event. */ 451 475 if (event->event > 15) { 452 PJ_LOG(5,(THIS_FILE, "Ignored RTP pkt with bad DTMF event %d", 453 event->event)); 476 PJ_LOG(5,(stream->port.info.name.ptr, 477 "Ignored RTP pkt with bad DTMF event %d", 478 event->event)); 454 479 return; 455 480 } 456 481 457 482 /* New event! */ 458 PJ_LOG(5,( THIS_FILE, "Received DTMF digit %c, vol=%d",459 460 483 PJ_LOG(5,(stream->port.info.name.ptr, "Received DTMF digit %c, vol=%d", 484 digitmap[event->event], 485 (event->e_vol & 0x3F))); 461 486 462 487 stream->last_dtmf = event->event; … … 517 542 &hdr, &payload, &payloadlen); 518 543 if (status != PJ_SUCCESS) { 519 TRACE_((THIS_FILE, "RTP decode error", status));544 LOGERR_((stream->port.info.name.ptr, "RTP decode error", status)); 520 545 goto read_next_packet; 521 546 } … … 537 562 */ 538 563 pjmedia_rtp_session_update(&channel->rtp, hdr, &seq_st); 539 if (seq_st.status. flag.bad) {540 TRC_ (( THIS_FILE,541 "RTP s ession_update error: badpt=%d, dup=%d, outorder=%d, "542 " probation=%d, restart=%d",564 if (seq_st.status.value) { 565 TRC_ ((stream->port.info.name.ptr, 566 "RTP status: badpt=%d, badssrc=%d, dup=%d, " 567 "outorder=%d, probation=%d, restart=%d", 543 568 seq_st.status.flag.badpt, 569 seq_st.status.flag.badssrc, 544 570 seq_st.status.flag.dup, 545 571 seq_st.status.flag.outorder, 546 572 seq_st.status.flag.probation, 547 573 seq_st.status.flag.restart)); 574 575 if (seq_st.status.flag.badpt) { 576 PJ_LOG(4,(stream->port.info.name.ptr, 577 "Bad RTP pt %d (expecting %d)", 578 hdr->pt, channel->rtp.out_pt)); 579 } 580 } 581 582 /* Skip bad RTP packet */ 583 if (seq_st.status.flag.bad) 548 584 goto read_next_packet; 549 }550 585 551 586 … … 564 599 stream->rtp_src_cnt = 0; 565 600 566 PJ_LOG(4,(THIS_FILE,"Remote RTP address switched to %s:%d", 601 PJ_LOG(4,(stream->port.info.name.ptr, 602 "Remote RTP address switched to %s:%d", 567 603 pj_inet_ntoa(stream->rtp_src_addr.sin_addr), 568 604 pj_ntohs(stream->rtp_src_addr.sin_port))); … … 571 607 572 608 573 /* Put to jitter buffer. */ 609 610 /* Put "good" packet to jitter buffer, or reset the jitter buffer 611 * when RTP session is restarted. 612 */ 574 613 pj_mutex_lock( stream->jb_mutex ); 575 status = pjmedia_jbuf_put_frame(stream->jb, payload, payloadlen, 576 pj_ntohs(hdr->seq)); 614 if (seq_st.status.flag.restart) { 615 status = pjmedia_jbuf_reset(stream->jb); 616 PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 617 618 } else { 619 status = pjmedia_jbuf_put_frame(stream->jb, payload, payloadlen, 620 pj_ntohs(hdr->seq)); 621 } 577 622 pj_mutex_unlock( stream->jb_mutex ); 578 623 624 625 /* Check if now is the time to transmit RTCP SR/RR report. 626 * We only do this when stream direction is "decoding only", 627 * because otherwise check_tx_rtcp() will be handled by put_frame() 628 */ 629 if (stream->dir == PJMEDIA_DIR_DECODING) { 630 check_tx_rtcp(stream, pj_ntohl(hdr->ts)); 631 } 632 579 633 if (status != 0) { 580 TRACE_((THIS_FILE, "Jitter buffer put() error", status)); 634 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error", 635 status)); 581 636 goto read_next_packet; 582 637 } 638 583 639 584 640 read_next_packet: … … 603 659 604 660 pj_strerror(status, errmsg, sizeof(errmsg)); 605 PJ_LOG(4,(THIS_FILE, "Error reading RTP packet: %s [status=%d]. " 606 "RTP stream thread quitting!", 607 errmsg, status)); 661 PJ_LOG(4,(stream->port.info.name.ptr, 662 "Error reading RTP packet: %s [status=%d]. " 663 "RTP stream thread quitting!", 664 errmsg, status)); 608 665 } 609 666 } … … 644 701 645 702 pj_strerror(status, errmsg, sizeof(errmsg)); 646 PJ_LOG(4,(THIS_FILE, "Error reading RTCP packet: %s [status=%d]", 647 errmsg, status)); 703 PJ_LOG(4,(stream->port.info.name.ptr, 704 "Error reading RTCP packet: %s [status=%d]", 705 errmsg, status)); 648 706 } 649 707 … … 743 801 PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 744 802 803 /* Init stream/port name */ 804 stream->port.info.name.ptr = pj_pool_alloc(pool, 24); 805 pj_ansi_sprintf(stream->port.info.name.ptr, 806 "strm%p", stream); 807 stream->port.info.name.slen = pj_ansi_strlen(stream->port.info.name.ptr); 808 745 809 /* Init port. */ 746 stream->port.info.name = pj_str("stream");747 810 stream->port.info.signature = ('S'<<3 | 'T'<<2 | 'R'<<1 | 'M'); 748 811 stream->port.info.type = PJMEDIA_TYPE_AUDIO; … … 768 831 stream->rem_rtcp_addr = stream->rem_rtp_addr; 769 832 stream->rem_rtcp_addr.sin_port = pj_htons(rtcp_port); 770 stream->tx_event_pt = info->tx_event_pt; 771 stream->rx_event_pt = info->rx_event_pt; 833 stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL + (pj_rand() % 8000)) * 834 info->fmt.sample_rate / 1000; 835 836 stream->tx_event_pt = info->tx_event_pt ? info->tx_event_pt : -1; 837 stream->rx_event_pt = info->rx_event_pt ? info->rx_event_pt : -1; 772 838 stream->last_dtmf = -1; 839 773 840 774 841 /* Create mutex to protect jitter buffer: */ … … 813 880 /* Init RTCP session: */ 814 881 815 pjmedia_rtcp_init(&stream->rtcp, info->fmt.sample_rate, 882 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 883 info->fmt.sample_rate, 816 884 stream->port.info.samples_per_frame, 817 885 info->ssrc); … … 820 888 /* Create jitter buffer: */ 821 889 822 status = pjmedia_jbuf_create(pool, stream->frame_size, 15, 100, 890 status = pjmedia_jbuf_create(pool, &stream->port.info.name, 891 stream->frame_size, 15, 100, 823 892 &stream->jb); 824 893 if (status != PJ_SUCCESS) … … 883 952 /* Success! */ 884 953 *p_stream = stream; 954 955 PJ_LOG(5,(THIS_FILE, "Stream %s created", stream->port.info.name.ptr)); 885 956 return PJ_SUCCESS; 886 957 … … 958 1029 stream->enc->paused = 0; 959 1030 //pjmedia_snd_stream_start(stream->enc->snd_stream); 960 PJ_LOG(4,( THIS_FILE, "Encoder stream started"));1031 PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream started")); 961 1032 } else { 962 PJ_LOG(4,( THIS_FILE, "Encoder stream paused"));1033 PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream paused")); 963 1034 } 964 1035 … … 966 1037 stream->dec->paused = 0; 967 1038 //pjmedia_snd_stream_start(stream->dec->snd_stream); 968 PJ_LOG(4,( THIS_FILE, "Decoder stream started"));1039 PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream started")); 969 1040 } else { 970 PJ_LOG(4,( THIS_FILE, "Decoder stream paused"));1041 PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream paused")); 971 1042 } 972 1043 … … 998 1069 if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) { 999 1070 stream->enc->paused = 1; 1000 PJ_LOG(4,( THIS_FILE, "Encoder stream paused"));1071 PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream paused")); 1001 1072 } 1002 1073 1003 1074 if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) { 1004 1075 stream->dec->paused = 1; 1005 PJ_LOG(4,( THIS_FILE, "Decoder stream paused"));1076 PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream paused")); 1006 1077 } 1007 1078 … … 1020 1091 if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) { 1021 1092 stream->enc->paused = 1; 1022 PJ_LOG(4,( THIS_FILE, "Encoder stream resumed"));1093 PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream resumed")); 1023 1094 } 1024 1095 1025 1096 if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) { 1026 1097 stream->dec->paused = 1; 1027 PJ_LOG(4,( THIS_FILE, "Decoder stream resumed"));1098 PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream resumed")); 1028 1099 } 1029 1100 -
pjproject/trunk/pjsip-apps/build/Samples-vc.mak
r407 r408 41 41 $(BINDIR)\confsample.exe $(BINDIR)\sndinfo.exe \ 42 42 $(BINDIR)\level.exe $(BINDIR)\recfile.exe \ 43 $(BINDIR)\resampleplay.exe $(BINDIR)\siprtp.exe $(BINDIR)\stream.exe 43 $(BINDIR)\resampleplay.exe $(BINDIR)\siprtp.exe \ 44 $(BINDIR)\streamutil.exe 44 45 45 46 -
pjproject/trunk/pjsip-apps/build/Samples.mak
r407 r408 40 40 41 41 SAMPLES := simpleua playfile playsine confsample sndinfo level recfile resampleplay \ 42 siprtp stream 42 siprtp streamutil 43 43 44 44 EXES := $(foreach file, $(SAMPLES), $(BINDIR)/$(file)-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(HOST_EXE)) -
pjproject/trunk/pjsip-apps/src/samples/debug.c
r407 r408 28 28 * #include "playfile.c" 29 29 */ 30 #include "stream .c"30 #include "streamutil.c" 31 31 -
pjproject/trunk/pjsip-apps/src/samples/siprtp.c
r407 r408 1247 1247 pj_rand()); 1248 1248 pjmedia_rtp_session_init(&audio->in_sess, audio->si.fmt.pt, 0); 1249 pjmedia_rtcp_init(&audio->rtcp, audio->clock_rate,1249 pjmedia_rtcp_init(&audio->rtcp, "rtcp", audio->clock_rate, 1250 1250 audio->samples_per_frame, 0); 1251 1251 -
pjproject/trunk/pjsip-apps/src/samples/streamutil.c
r407 r408 20 20 21 21 static const char *desc = 22 " stream .c\n"22 " streamutil \n" 23 23 " \n" 24 24 " PURPOSE: \n" … … 28 28 "\n" 29 29 " USAGE: \n" 30 " stream [options]\n"30 " streamutil [options] \n" 31 31 "\n" 32 32 "\n"
Note: See TracChangeset
for help on using the changeset viewer.