Changeset 215
- Timestamp:
- Feb 22, 2006 12:06:39 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/errno.h
r214 r215 294 294 */ 295 295 #define PJMEDIA_EINVALIMEDIATYPE (PJMEDIA_ERRNO_START+104) /* 220104 */ 296 /** 297 * @hideinitializer 298 * Remote does not support DTMF. 299 */ 300 #define PJMEDIA_EREMOTENODTMF (PJMEDIA_ERRNO_START+105) /* 220105 */ 301 /** 302 * @hideinitializer 303 * Invalid DTMF digit. 304 */ 305 #define PJMEDIA_RTP_EINDTMF (PJMEDIA_ERRNO_START+106) /* 220106 */ 296 306 297 307 … … 355 365 */ 356 366 #define PJMEDIA_RTP_ENOCONFIG (PJMEDIA_ERRNO_START+134) /* 220134 */ 357 /**358 * @hideinitializer359 * Invalid DTMF digit.360 */361 #define PJMEDIA_RTP_EINDTMF (PJMEDIA_ERRNO_START+135) /* 220135 */362 367 363 368 -
pjproject/trunk/pjmedia/include/pjmedia/session.h
r205 r215 81 81 * @param local_sdp The SDP describing local capability. 82 82 * @param rem_sdp The SDP describing remote capability. 83 * @param user_data Arbitrary user data to be kept in the session. 83 84 * @param p_session Pointer to receive the media session. 84 85 * … … 92 93 const pjmedia_sdp_session *local_sdp, 93 94 const pjmedia_sdp_session *rem_sdp, 95 void *user_data, 94 96 pjmedia_session **p_session ); 95 97 … … 198 200 199 201 /** 202 * Dial DTMF digit to the stream, using RFC 2833 mechanism. 203 * 204 * @param session The media session. 205 * @param index The stream index. 206 * @param ascii_digits String of ASCII digits (i.e. 0-9*#A-B). 207 * 208 * @return PJ_SUCCESS on success. 209 */ 210 PJ_DECL(pj_status_t) pjmedia_session_dial_dtmf( pjmedia_session *session, 211 unsigned index, 212 const pj_str_t *ascii_digits ); 213 214 215 /** 216 * Check if the specified stream has received DTMF digits. 217 * 218 * @param session The media session. 219 * @param index The stream index. 220 * 221 * @return Non-zero (PJ_TRUE) if the stream has DTMF digits. 222 */ 223 PJ_DECL(pj_status_t) pjmedia_session_check_dtmf( pjmedia_session *session, 224 unsigned index); 225 226 227 /** 228 * Retrieve DTMF digits from the specified stream. 229 * 230 * @param session The media session. 231 * @param index The stream index. 232 * @param ascii_digits Buffer to receive the digits. The length of this 233 * buffer is indicated in the "size" argument. 234 * @param size On input, contains the maximum digits to be copied 235 * to the buffer. 236 * On output, it contains the actual digits that has 237 * been copied to the buffer. 238 * 239 * @return PJ_SUCCESS on success. 240 */ 241 PJ_DECL(pj_status_t) pjmedia_session_get_dtmf( pjmedia_session *session, 242 unsigned index, 243 char *ascii_digits, 244 unsigned *size ); 245 246 /** 200 247 * Destroy media session. 201 248 * -
pjproject/trunk/pjmedia/include/pjmedia/stream.h
r214 r215 72 72 pj_sockaddr_in rem_addr; /**< Remote RTP address */ 73 73 pjmedia_codec_info fmt; /**< Codec format info. */ 74 unsignedtx_event_pt;/**< Outgoing pt for telephone-events. */75 unsignedrx_event_pt;/**< Incoming pt for telephone-events. */74 int tx_event_pt;/**< Outgoing pt for telephone-events. */ 75 int rx_event_pt;/**< Incoming pt for telephone-events. */ 76 76 pj_uint32_t ssrc; /**< RTP SSRC. */ 77 77 int jb_min; /**< Jitter buffer min delay. */ … … 111 111 * buffer needs to preallocate some storage. 112 112 * @param info Stream information. 113 * @param user_data Arbitrary user data (for future callback feature). 113 114 * @param p_stream Pointer to receive the media stream. 114 115 * … … 118 119 pj_pool_t *pool, 119 120 const pjmedia_stream_info *info, 121 void *user_data, 120 122 pjmedia_stream **p_stream); 121 123 … … 192 194 * 193 195 * @param stream The media stream. 194 * @param digit A single digit ('0123456789*#ABCD'). 196 * @param ascii_digit String containing digits to be sent to remote. 197 * Currently the maximum number of digits are 32. 195 198 * 196 199 * @return PJ_SUCCESS on success. 197 200 */ 198 201 PJ_DECL(pj_status_t) pjmedia_stream_dial_dtmf(pjmedia_stream *stream, 199 const pj_str_t *digit_char); 200 202 const pj_str_t *ascii_digit); 203 204 205 /** 206 * Check if the stream has incoming DTMF digits in the incoming DTMF 207 * queue. Incoming DTMF digits received via RFC 2833 mechanism are 208 * saved in the incoming digits queue. 209 * 210 * @param stream The media stream. 211 * 212 * @return Non-zero (PJ_TRUE) if the stream has received DTMF 213 * digits in the . 214 */ 215 PJ_DECL(pj_bool_t) pjmedia_stream_check_dtmf(pjmedia_stream *stream); 216 217 218 /** 219 * Retrieve the incoming DTMF digits from the stream. Note that the digits 220 * buffer will not be NULL terminated. 221 * 222 * @param stream The media stream. 223 * @param ascii_digits Buffer to receive the digits. The length of this 224 * buffer is indicated in the "size" argument. 225 * @param size On input, contains the maximum digits to be copied 226 * to the buffer. 227 * On output, it contains the actual digits that has 228 * been copied to the buffer. 229 * 230 * @return Non-zero (PJ_TRUE) if the stream has received DTMF 231 * digits in the . 232 */ 233 PJ_DECL(pj_status_t) pjmedia_stream_get_dtmf( pjmedia_stream *stream, 234 char *ascii_digits, 235 unsigned *size); 201 236 202 237 -
pjproject/trunk/pjmedia/src/pjmedia/endpoint.c
r214 r215 264 264 265 265 #if 1 266 / /267 // Test: add telephony events268 //266 /* 267 * Add support telephony event 268 */ 269 269 m->desc.fmt[m->desc.fmt_count++] = pj_str("101"); 270 270 /* Add rtpmap. */ -
pjproject/trunk/pjmedia/src/pjmedia/errno.c
r188 r215 90 90 { PJMEDIA_EMISSINGRTPMAP, "Missing rtpmap in media description" }, 91 91 { PJMEDIA_EINVALIMEDIATYPE, "Invalid media type" }, 92 { PJMEDIA_EREMOTENODTMF, "Remote does not support DTMF" }, 93 { PJMEDIA_RTP_EINDTMF, "Invalid DTMF digit" }, 92 94 93 95 /* RTP session errors. */ … … 101 103 { PJMEDIA_RTP_ESESSPROBATION, "RTP session in probation" }, 102 104 { PJMEDIA_RTP_EBADSEQ, "Bad sequence number in RTP packet" }, 103 105 { PJMEDIA_RTP_EBADDEST, "RTP media port destination is not configured" }, 106 { PJMEDIA_RTP_ENOCONFIG, "RTP is not configured" }, 107 108 /* Media port errors: */ 109 { PJMEDIA_ENOTCOMPATIBLE, "Media ports are not compatible" }, 110 { PJMEDIA_ENCCLOCKRATE, "Media ports have incompatible clock rate" }, 111 { PJMEDIA_ENCSAMPLESPFRAME, "Media ports have incompatible samples per frame" }, 112 { PJMEDIA_ENCTYPE, "Media ports have incompatible media type" }, 113 { PJMEDIA_ENCBITS, "Media ports have incompatible bits per sample" }, 114 { PJMEDIA_ENCBYTES, "Media ports have incompatible bytes per frame" }, 104 115 }; 105 116 -
pjproject/trunk/pjmedia/src/pjmedia/session.c
r205 r215 34 34 pjmedia_stream_info stream_info[PJMEDIA_MAX_SDP_MEDIA]; 35 35 pjmedia_stream *stream[PJMEDIA_MAX_SDP_MEDIA]; 36 void *user_data; 36 37 }; 37 38 … … 48 49 static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 49 50 static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; 51 static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 }; 50 52 51 53 static const pj_str_t STR_INACTIVE = { "inactive", 8 }; … … 67 69 const pjmedia_sdp_attr *attr; 68 70 pjmedia_sdp_rtpmap *rtpmap; 71 unsigned i; 69 72 pj_status_t status; 70 73 … … 152 155 * type without rtpmap. 153 156 */ 154 attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP, NULL); 157 attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP, 158 &local_m->desc.fmt[0]); 155 159 if (attr == NULL) 156 160 return PJMEDIA_EMISSINGRTPMAP; … … 166 170 pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); 167 171 si->fmt.sample_rate = rtpmap->clock_rate; 172 173 /* Get local DTMF payload type */ 174 si->tx_event_pt = -1; 175 for (i=0; i<local_m->attr_count; ++i) { 176 pjmedia_sdp_rtpmap r; 177 178 attr = local_m->attr[i]; 179 if (pj_strcmp(&attr->name, &ID_RTPMAP) != 0) 180 continue; 181 if (pjmedia_sdp_attr_get_rtpmap(attr, &r) != PJ_SUCCESS) 182 continue; 183 if (pj_strcmp(&r.enc_name, &ID_TELEPHONE_EVENT) == 0) { 184 si->tx_event_pt = pj_strtoul(&r.pt); 185 break; 186 } 187 } 188 189 /* Get remote DTMF payload type */ 190 si->rx_event_pt = -1; 191 for (i=0; i<rem_m->attr_count; ++i) { 192 pjmedia_sdp_rtpmap r; 193 194 attr = rem_m->attr[i]; 195 if (pj_strcmp(&attr->name, &ID_RTPMAP) != 0) 196 continue; 197 if (pjmedia_sdp_attr_get_rtpmap(attr, &r) != PJ_SUCCESS) 198 continue; 199 if (pj_strcmp(&r.enc_name, &ID_TELEPHONE_EVENT) == 0) { 200 si->rx_event_pt = pj_strtoul(&r.pt); 201 break; 202 } 203 } 204 168 205 169 206 /* Leave SSRC to zero. */ … … 183 220 const pjmedia_sdp_session *local_sdp, 184 221 const pjmedia_sdp_session *rem_sdp, 222 void *user_data, 185 223 pjmedia_session **p_session ) 186 224 { … … 204 242 session->endpt = endpt; 205 243 session->stream_cnt = stream_cnt; 244 session->user_data = user_data; 206 245 207 246 /* Stream count is the lower number of stream_cnt or SDP m= lines count */ … … 240 279 status = pjmedia_stream_create(endpt, session->pool, 241 280 &session->stream_info[i], 281 session, 242 282 &session->stream[i]); 243 283 if (status == PJ_SUCCESS) … … 386 426 387 427 428 /* 429 * Get the port interface. 430 */ 388 431 PJ_DEF(pj_status_t) pjmedia_session_get_port( pjmedia_session *session, 389 432 unsigned index, … … 393 436 } 394 437 395 /* *438 /* 396 439 * Get statistics 397 440 */ … … 407 450 408 451 452 /* 453 * Dial DTMF digit to the stream, using RFC 2833 mechanism. 454 */ 455 PJ_DEF(pj_status_t) pjmedia_session_dial_dtmf( pjmedia_session *session, 456 unsigned index, 457 const pj_str_t *ascii_digits ) 458 { 459 PJ_ASSERT_RETURN(session && ascii_digits, PJ_EINVAL); 460 return pjmedia_stream_dial_dtmf(session->stream[index], ascii_digits); 461 } 462 463 /* 464 * Check if the specified stream has received DTMF digits. 465 */ 466 PJ_DEF(pj_status_t) pjmedia_session_check_dtmf( pjmedia_session *session, 467 unsigned index ) 468 { 469 PJ_ASSERT_RETURN(session, PJ_EINVAL); 470 return pjmedia_stream_check_dtmf(session->stream[index]); 471 } 472 473 474 /* 475 * Retrieve DTMF digits from the specified stream. 476 */ 477 PJ_DEF(pj_status_t) pjmedia_session_get_dtmf( pjmedia_session *session, 478 unsigned index, 479 char *ascii_digits, 480 unsigned *size ) 481 { 482 PJ_ASSERT_RETURN(session && ascii_digits && size, PJ_EINVAL); 483 return pjmedia_stream_get_dtmf(session->stream[index], ascii_digits, 484 size); 485 } -
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 } -
pjproject/trunk/pjsip/src/pjsua/main.c
r212 r215 140 140 puts("| v re-inVite (release hold) | cl List ports | |"); 141 141 puts("| x Xfer call | cc Connect port | |"); 142 puts("| 142 puts("| # Send DTMF string | cd Disconnect port | |"); 143 143 puts("+------------------------------+--------------------------+-------------------+"); 144 144 puts("| q QUIT |"); … … 437 437 } else if (result.uri_result) { 438 438 pjsua_inv_xfer_call( inv_session, result.uri_result); 439 } 440 } 441 break; 442 443 case '#': 444 /* 445 * Send DTMF strings. 446 */ 447 if (inv_session == &pjsua.inv_list) { 448 449 PJ_LOG(3,(THIS_FILE, "No current call")); 450 451 } else if (inv_session->session == NULL) { 452 453 PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); 454 455 } else { 456 pj_str_t digits; 457 pj_status_t status; 458 459 if (!simple_input("DTMF strings to send (0-9*#A-B)", buf, 460 sizeof(buf))) 461 break; 462 463 digits = pj_str(buf); 464 status = pjmedia_session_dial_dtmf(inv_session->session, 0, 465 &digits); 466 if (status != PJ_SUCCESS) { 467 pjsua_perror(THIS_FILE, "Unable to send DTMF", status); 468 } else { 469 puts("DTMF digits enqueued for transmission"); 439 470 } 440 471 } -
pjproject/trunk/pjsip/src/pjsua/pjsua_inv.c
r212 r215 717 717 &pjsua.med_sock_info[inv_data->call_slot], 718 718 local_sdp, remote_sdp, 719 inv_data, 719 720 &inv_data->session ); 720 721 if (status != PJ_SUCCESS) {
Note: See TracChangeset
for help on using the changeset viewer.