Changeset 215 for pjproject/trunk/pjmedia/src/pjmedia/stream.c
- Timestamp:
- Feb 22, 2006 12:06:39 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r214 r215 22 22 #include <pjmedia/rtcp.h> 23 23 #include <pjmedia/jbuf.h> 24 #include <pj/array.h> 25 #include <pj/assert.h> 26 #include <pj/ctype.h> 27 #include <pj/compat/socket.h> 28 #include <pj/errno.h> 29 #include <pj/log.h> 24 30 #include <pj/os.h> 25 #include <pj/ ctype.h>26 #include <pj/ log.h>31 #include <pj/pool.h> 32 #include <pj/sock_select.h> 27 33 #include <pj/string.h> /* memcpy() */ 28 #include <pj/pool.h>29 #include <pj/assert.h>30 #include <pj/compat/socket.h>31 #include <pj/sock_select.h>32 #include <pj/errno.h>33 #include <stdlib.h>34 34 35 35 … … 69 69 int event; 70 70 pj_uint32_t start_ts; 71 pj_uint32_t end_ts;72 71 }; 73 72 … … 87 86 pjmedia_dir dir; /**< Stream direction. */ 88 87 pjmedia_stream_stat stat; /**< Stream statistics. */ 88 void *user_data; /**< User data. */ 89 89 90 90 pjmedia_codec_mgr *codec_mgr; /**< Codec manager instance. */ … … 104 104 105 105 /* RFC 2833 DTMF transmission queue: */ 106 int dtmf_count; /**< # of digits in queue. */ 107 struct dtmf dtmf_queue[32];/**< Outgoing dtmf queue. */ 106 int tx_event_pt; /**< Outgoing pt for dtmf. */ 107 int tx_dtmf_count; /**< # of digits in tx dtmf buf.*/ 108 struct dtmf tx_dtmf_buf[32];/**< Outgoing dtmf queue. */ 109 110 /* Incoming DTMF: */ 111 int rx_event_pt; /**< Incoming pt for dtmf. */ 112 int last_dtmf; /**< Current digit, or -1. */ 113 pj_uint32_t last_dtmf_dur; /**< Start ts for cur digit. */ 114 unsigned rx_dtmf_count; /**< # of digits in dtmf rx buf.*/ 115 char rx_dtmf_buf[32];/**< Incoming DTMF buffer. */ 108 116 }; 109 117 … … 194 202 * Transmit DTMF 195 203 */ 196 static void transmit_dtmf(pjmedia_stream *stream,204 static void create_dtmf_payload(pjmedia_stream *stream, 197 205 struct pjmedia_frame *frame_out) 198 206 { 199 207 pjmedia_rtp_dtmf_event *event; 200 struct dtmf *digit = &stream->dtmf_queue[0]; 208 struct dtmf *digit = &stream->tx_dtmf_buf[0]; 209 unsigned duration; 201 210 pj_uint32_t cur_ts; 211 212 pj_assert(sizeof(pjmedia_rtp_dtmf_event) == 4); 202 213 203 214 event = frame_out->buf; 204 215 cur_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); 216 duration = cur_ts - digit->start_ts; 205 217 206 218 event->event = (pj_uint8_t)digit->event; 207 219 event->e_vol = 10; 208 event->duration = pj_htonl(cur_ts - digit->start_ts); 220 event->duration = pj_htons((pj_uint16_t)duration); 221 222 if (duration >= PJMEDIA_DTMF_DURATION) { 223 event->e_vol |= 0x80; 224 225 /* Prepare next digit. */ 226 pj_mutex_lock(stream->jb_mutex); 227 pj_array_erase(stream->tx_dtmf_buf, sizeof(stream->tx_dtmf_buf[0]), 228 stream->tx_dtmf_count, 0); 229 --stream->tx_dtmf_count; 230 231 stream->tx_dtmf_buf[0].start_ts = cur_ts; 232 pj_mutex_unlock(stream->jb_mutex); 233 } 234 235 frame_out->size = 4; 209 236 } 210 237 … … 228 255 pj_ssize_t sent; 229 256 230 231 257 /* Check if stream is quitting. */ 232 258 if (stream->quit_flag) … … 242 268 * Otherwise encode the PCM buffer. 243 269 */ 244 if (stream->dtmf_count) { 245 transmit_dtmf(stream, &frame_out); 270 if (stream->tx_dtmf_count) { 271 272 create_dtmf_payload(stream, &frame_out); 273 274 /* Encapsulate. */ 275 status = pjmedia_rtp_encode_rtp( &channel->rtp, 276 stream->tx_event_pt, 0, 277 frame_out.size, ts_len, 278 (const void**)&rtphdr, 279 &rtphdrlen); 280 246 281 } else { 247 282 unsigned max_size; … … 255 290 return status; 256 291 } 257 } 258 259 /* Encapsulate. */ 260 status = pjmedia_rtp_encode_rtp( &channel->rtp, 261 channel->pt, 0, 262 frame_out.size, ts_len, 263 (const void**)&rtphdr, &rtphdrlen); 292 293 /* Encapsulate. */ 294 status = pjmedia_rtp_encode_rtp( &channel->rtp, 295 channel->pt, 0, 296 frame_out.size, ts_len, 297 (const void**)&rtphdr, 298 &rtphdrlen); 299 } 300 264 301 if (status != 0) { 265 302 TRACE_((THIS_FILE, "RTP encode_rtp() error", status)); … … 290 327 } 291 328 292 329 #if 0 293 330 static void dump_bin(const char *buf, unsigned len) 294 331 { … … 313 350 PJ_LOG(3,(THIS_FILE, "end dump")); 314 351 } 352 #endif 353 354 /* 355 * Handle incoming DTMF digits. 356 */ 357 static void handle_incoming_dtmf( pjmedia_stream *stream, 358 const void *payload, unsigned payloadlen) 359 { 360 static const char digitmap[16] = { '0', '1', '2', '3', 361 '4', '5', '6', '7', 362 '8', '9', '*', '#', 363 'A', 'B', 'C', 'D'}; 364 const pjmedia_rtp_dtmf_event *event = payload; 365 366 /* Check compiler packing. */ 367 pj_assert(sizeof(pjmedia_rtp_dtmf_event)==4); 368 369 /* Must have sufficient length before we proceed. */ 370 if (payloadlen < sizeof(pjmedia_rtp_dtmf_event)) 371 return; 372 373 //dump_bin(payload, payloadlen); 374 375 /* Check if this is the same/current digit of the last packet. */ 376 if (stream->last_dtmf != -1 && 377 event->event == stream->last_dtmf && 378 pj_ntohs(event->duration) >= stream->last_dtmf_dur) 379 { 380 /* Yes, this is the same event. */ 381 stream->last_dtmf_dur = pj_ntohs(event->duration); 382 return; 383 } 384 385 /* Ignore unknown event. */ 386 if (event->event > 15) { 387 PJ_LOG(5,(THIS_FILE, "Ignored RTP pkt with bad DTMF event %d", 388 event->event)); 389 return; 390 } 391 392 /* New event! */ 393 PJ_LOG(5,(THIS_FILE, "Received DTMF digit %c, vol=%d", 394 digitmap[event->event], 395 (event->e_vol & 0x3F))); 396 397 stream->last_dtmf = event->event; 398 stream->last_dtmf_dur = pj_ntohs(event->duration); 399 400 /* By convention, we use jitter buffer's mutex to access shared 401 * DTMF variables. 402 */ 403 pj_mutex_lock(stream->jb_mutex); 404 if (stream->rx_dtmf_count >= PJ_ARRAY_SIZE(stream->rx_dtmf_buf)) { 405 /* DTMF digits overflow. Discard the oldest digit. */ 406 pj_array_erase(stream->rx_dtmf_buf, sizeof(stream->rx_dtmf_buf[0]), 407 stream->rx_dtmf_count, 0); 408 --stream->rx_dtmf_count; 409 } 410 stream->rx_dtmf_buf[stream->rx_dtmf_count++] = digitmap[event->event]; 411 pj_mutex_unlock(stream->jb_mutex); 412 } 413 315 414 316 415 /* … … 377 476 } 378 477 379 #if 1 380 if (hdr->pt == 101) {381 dump_bin((char*)payload, payloadlen);478 /* Handle incoming DTMF. */ 479 if (hdr->pt == stream->rx_event_pt) { 480 handle_incoming_dtmf(stream, payload, payloadlen); 382 481 continue; 383 482 } 384 #endif385 483 386 484 status = pjmedia_rtp_session_update(&channel->rtp, hdr); … … 521 619 pj_pool_t *pool, 522 620 const pjmedia_stream_info *info, 621 void *user_data, 523 622 pjmedia_stream **p_stream) 524 623 … … 553 652 554 653 stream->dir = info->dir; 654 stream->user_data = user_data; 555 655 stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 556 656 stream->skinfo = info->sock_info; 557 657 stream->rem_rtp_addr = info->rem_addr; 658 stream->tx_event_pt = info->tx_event_pt; 659 stream->rx_event_pt = info->rx_event_pt; 660 stream->last_dtmf = -1; 661 558 662 559 663 PJ_TODO(INITIALIZE_RTCP_REMOTE_ADDRESS); … … 825 929 PJ_ASSERT_RETURN(stream && digit_char, PJ_EINVAL); 826 930 931 /* Check that remote can receive DTMF events. */ 932 if (stream->tx_event_pt < 0) { 933 return PJMEDIA_RTP_EINDTMF; 934 } 935 827 936 pj_mutex_lock(stream->jb_mutex); 828 937 829 if (stream-> dtmf_count+digit_char->slen >=830 PJ_ARRAY_SIZE(stream-> dtmf_queue))938 if (stream->tx_dtmf_count+digit_char->slen >= 939 PJ_ARRAY_SIZE(stream->tx_dtmf_buf)) 831 940 { 832 941 status = PJ_ETOOMANY; … … 864 973 } 865 974 866 stream->dtmf_queue[stream->dtmf_count+1].event = pt; 867 stream->dtmf_queue[stream->dtmf_count+1].start_ts = start_ts; 868 stream->dtmf_queue[stream->dtmf_count+1].end_ts = 869 start_ts + PJMEDIA_DTMF_DURATION; 870 871 start_ts += PJMEDIA_DTMF_DURATION + 320; 975 stream->tx_dtmf_buf[stream->tx_dtmf_count+i].event = pt; 872 976 } 873 977 … … 875 979 goto on_return; 876 980 877 if (stream->dtmf_count ==0) { 981 /* Init start_ts and end_ts only for the first digit. 982 * Subsequent digits are initialized on the fly. 983 */ 984 if (stream->tx_dtmf_count ==0) { 878 985 pj_uint32_t start_ts; 879 986 880 987 start_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); 881 stream->dtmf_queue[0].start_ts = start_ts; 882 stream->dtmf_queue[0].end_ts = start_ts + PJMEDIA_DTMF_DURATION; 988 stream->tx_dtmf_buf[0].start_ts = start_ts; 883 989 } 884 990 885 991 /* Increment digit count only if all digits are valid. */ 886 stream-> dtmf_count += digit_char->slen;992 stream->tx_dtmf_count += digit_char->slen; 887 993 888 994 } … … 894 1000 } 895 1001 1002 1003 /* 1004 * See if we have DTMF digits in the rx buffer. 1005 */ 1006 PJ_DEF(pj_bool_t) pjmedia_stream_check_dtmf(pjmedia_stream *stream) 1007 { 1008 return stream->rx_dtmf_count != 0; 1009 } 1010 1011 1012 /* 1013 * Retrieve incoming DTMF digits from the stream's DTMF buffer. 1014 */ 1015 PJ_DEF(pj_status_t) pjmedia_stream_get_dtmf( pjmedia_stream *stream, 1016 char *digits, 1017 unsigned *size) 1018 { 1019 PJ_ASSERT_RETURN(stream && digits && size, PJ_EINVAL); 1020 1021 pj_assert(sizeof(stream->rx_dtmf_buf[0]) == 0); 1022 1023 /* By convention, we use jitter buffer's mutex to access DTMF 1024 * digits resources. 1025 */ 1026 pj_mutex_lock(stream->jb_mutex); 1027 1028 if (stream->rx_dtmf_count < *size) 1029 *size = stream->rx_dtmf_count; 1030 1031 if (*size) { 1032 pj_memcpy(digits, stream->rx_dtmf_buf, *size); 1033 stream->rx_dtmf_count -= *size; 1034 if (stream->rx_dtmf_count) { 1035 pj_memmove(stream->rx_dtmf_buf, 1036 &stream->rx_dtmf_buf[*size], 1037 stream->rx_dtmf_count); 1038 } 1039 } 1040 1041 pj_mutex_unlock(stream->jb_mutex); 1042 1043 return PJ_SUCCESS; 1044 }
Note: See TracChangeset
for help on using the changeset viewer.