Changeset 214
- Timestamp:
- Feb 22, 2006 9:21:09 AM (19 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/pjmedia.dsp
r205 r214 66 66 # PROP Target_Dir "" 67 67 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c 68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /D "_DEBUG" /D "PA_NO_ASIO" /D " PA_NO_WIN_DS" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /D "_DEBUG" /D "PA_NO_ASIO" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c 69 69 # SUBTRACT CPP /YX 70 70 # ADD BASE RSC /l 0x409 /d "_DEBUG" -
pjproject/trunk/pjmedia/include/pjmedia/errno.h
r205 r214 355 355 */ 356 356 #define PJMEDIA_RTP_ENOCONFIG (PJMEDIA_ERRNO_START+134) /* 220134 */ 357 /** 358 * @hideinitializer 359 * Invalid DTMF digit. 360 */ 361 #define PJMEDIA_RTP_EINDTMF (PJMEDIA_ERRNO_START+135) /* 220135 */ 357 362 358 363 -
pjproject/trunk/pjmedia/include/pjmedia/rtp.h
r205 r214 123 123 124 124 125 #pragma pack(1) 126 127 /** 128 * Declaration for DTMF telephony-events (RFC2833). 129 */ 130 struct pjmedia_rtp_dtmf_event 131 { 132 pj_uint8_t event; 133 pj_uint8_t e_vol; 134 pj_uint16_t duration; 135 }; 136 137 /** 138 * @see pjmedia_rtp_dtmf_event 139 */ 140 typedef struct pjmedia_rtp_dtmf_event pjmedia_rtp_dtmf_event; 141 142 #pragma pack() 143 144 125 145 /** 126 146 * A generic sequence number management, used by both RTP and RTCP. -
pjproject/trunk/pjmedia/include/pjmedia/stream.h
r205 r214 72 72 pj_sockaddr_in rem_addr; /**< Remote RTP address */ 73 73 pjmedia_codec_info fmt; /**< Codec format info. */ 74 unsigned tx_event_pt;/**< Outgoing pt for telephone-events. */ 75 unsigned rx_event_pt;/**< Incoming pt for telephone-events. */ 74 76 pj_uint32_t ssrc; /**< RTP SSRC. */ 75 77 int jb_min; /**< Jitter buffer min delay. */ … … 184 186 pjmedia_dir dir); 185 187 188 /** 189 * Transmit DTMF to this stream. The DTMF will be transmitted uisng 190 * RTP telephone-events as described in RFC 2833. This operation is 191 * only valid for audio stream. 192 * 193 * @param stream The media stream. 194 * @param digit A single digit ('0123456789*#ABCD'). 195 * 196 * @return PJ_SUCCESS on success. 197 */ 198 PJ_DECL(pj_status_t) pjmedia_stream_dial_dtmf(pjmedia_stream *stream, 199 const pj_str_t *digit_char); 200 201 186 202 187 203 /** -
pjproject/trunk/pjmedia/src/pjmedia/conference.c
r211 r214 747 747 continue; 748 748 749 // 750 // TODO: 751 // When there's no source, not transmit the frame, but instead 752 // transmit a 'silence' frame. This is to allow the 'port' to 753 // do some processing, such as updating timestamp for RTP session 754 // or transmit signal when it's in the middle of transmitting DTMF. 755 // 749 756 750 757 target_buf = (conf_port->cur_tx_buf==conf_port->tx_buf1? -
pjproject/trunk/pjmedia/src/pjmedia/endpoint.c
r176 r214 258 258 } 259 259 260 /* Add sendrec tattribute. */260 /* Add sendrecv attribute. */ 261 261 attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr)); 262 262 attr->name = STR_SENDRECV; 263 263 m->attr[m->attr_count++] = attr; 264 264 265 #if 1 266 // 267 // Test: add telephony events 268 // 269 m->desc.fmt[m->desc.fmt_count++] = pj_str("101"); 270 /* Add rtpmap. */ 271 attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr)); 272 attr->name = pj_str("rtpmap"); 273 attr->value = pj_str(":101 telephone-event/8000"); 274 m->attr[m->attr_count++] = attr; 275 /* Add fmtp */ 276 attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr)); 277 attr->name = pj_str("fmtp"); 278 attr->value = pj_str(":101 0-15"); 279 m->attr[m->attr_count++] = attr; 280 #endif 265 281 266 282 /* Done */ -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r213 r214 23 23 #include <pjmedia/jbuf.h> 24 24 #include <pj/os.h> 25 #include <pj/ctype.h> 25 26 #include <pj/log.h> 26 27 #include <pj/string.h> /* memcpy() */ … … 40 41 #define PJMEDIA_MAX_BUFFER_SIZE_MS 2000 41 42 #define PJMEDIA_MAX_MTU 1500 42 43 #define PJMEDIA_DTMF_DURATION 1600 /* in timestamp */ 43 44 44 45 … … 64 65 65 66 67 struct dtmf 68 { 69 int event; 70 pj_uint32_t start_ts; 71 pj_uint32_t end_ts; 72 }; 73 66 74 /** 67 75 * This structure describes media stream. … … 94 102 pj_bool_t quit_flag; /**< To signal thread exit. */ 95 103 pj_thread_t *thread; /**< Jitter buffer's thread. */ 104 105 /* RFC 2833 DTMF transmission queue: */ 106 int dtmf_count; /**< # of digits in queue. */ 107 struct dtmf dtmf_queue[32];/**< Outgoing dtmf queue. */ 96 108 }; 97 109 … … 179 191 180 192 193 /* 194 * Transmit DTMF 195 */ 196 static void transmit_dtmf(pjmedia_stream *stream, 197 struct pjmedia_frame *frame_out) 198 { 199 pjmedia_rtp_dtmf_event *event; 200 struct dtmf *digit = &stream->dtmf_queue[0]; 201 pj_uint32_t cur_ts; 202 203 event = frame_out->buf; 204 cur_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); 205 206 event->event = (pj_uint8_t)digit->event; 207 event->e_vol = 10; 208 event->duration = pj_htonl(cur_ts - digit->start_ts); 209 } 210 181 211 /** 182 212 * rec_callback() … … 203 233 return -1; 204 234 205 /* Encode. */ 235 /* Number of samples in the frame */ 236 ts_len = frame->size / (channel->snd_info.bits_per_sample / 8); 237 238 /* Init frame_out buffer. */ 206 239 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 207 status = stream->codec->op->encode( stream->codec, frame, 208 channel->out_pkt_size - sizeof(pjmedia_rtp_hdr), 209 &frame_out); 210 if (status != 0) { 211 TRACE_((THIS_FILE, "Codec encode() error", status)); 212 return status; 240 241 /* If we have DTMF digits in the queue, transmit the digits. 242 * Otherwise encode the PCM buffer. 243 */ 244 if (stream->dtmf_count) { 245 transmit_dtmf(stream, &frame_out); 246 } else { 247 unsigned max_size; 248 249 max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr); 250 status = stream->codec->op->encode( stream->codec, frame, 251 max_size, 252 &frame_out); 253 if (status != 0) { 254 TRACE_((THIS_FILE, "Codec encode() error", status)); 255 return status; 256 } 213 257 } 214 258 215 259 /* Encapsulate. */ 216 ts_len = frame->size / (channel->snd_info.bits_per_sample / 8);217 260 status = pjmedia_rtp_encode_rtp( &channel->rtp, 218 261 channel->pt, 0, … … 247 290 } 248 291 292 293 static void dump_bin(const char *buf, unsigned len) 294 { 295 unsigned i; 296 297 PJ_LOG(3,(THIS_FILE, "begin dump")); 298 for (i=0; i<len; ++i) { 299 int j; 300 char bits[9]; 301 unsigned val = buf[i] & 0xFF; 302 303 bits[8] = '\0'; 304 for (j=0; j<8; ++j) { 305 if (val & (1 << (7-j))) 306 bits[j] = '1'; 307 else 308 bits[j] = '0'; 309 } 310 311 PJ_LOG(3,(THIS_FILE, "%2d %s [%d]", i, bits, val)); 312 } 313 PJ_LOG(3,(THIS_FILE, "end dump")); 314 } 249 315 250 316 /* … … 311 377 } 312 378 379 #if 1 380 if (hdr->pt == 101) { 381 dump_bin((char*)payload, payloadlen); 382 continue; 383 } 384 #endif 385 313 386 status = pjmedia_rtp_session_update(&channel->rtp, hdr); 314 387 if (status != 0 && … … 739 812 } 740 813 814 /* 815 * Dial DTMF 816 */ 817 PJ_DEF(pj_status_t) pjmedia_stream_dial_dtmf( pjmedia_stream *stream, 818 const pj_str_t *digit_char) 819 { 820 pj_status_t status = PJ_SUCCESS; 821 822 /* By convention we use jitter buffer mutex to access DTMF 823 * queue. 824 */ 825 PJ_ASSERT_RETURN(stream && digit_char, PJ_EINVAL); 826 827 pj_mutex_lock(stream->jb_mutex); 828 829 if (stream->dtmf_count+digit_char->slen >= 830 PJ_ARRAY_SIZE(stream->dtmf_queue)) 831 { 832 status = PJ_ETOOMANY; 833 } else { 834 int i; 835 836 /* convert ASCII digits into payload type first, to make sure 837 * that all digits are valid. 838 */ 839 for (i=0; i<digit_char->slen; ++i) { 840 unsigned pt; 841 842 if (digit_char->ptr[i] >= '0' && 843 digit_char->ptr[i] <= '9') 844 { 845 pt = digit_char->ptr[i] - '0'; 846 } 847 else if (pj_tolower(digit_char->ptr[i]) >= 'a' && 848 pj_tolower(digit_char->ptr[i]) <= 'd') 849 { 850 pt = pj_tolower(digit_char->ptr[i]) - 'a' + 12; 851 } 852 else if (digit_char->ptr[i] == '*') 853 { 854 pt = 10; 855 } 856 else if (digit_char->ptr[i] == '#') 857 { 858 pt = 11; 859 } 860 else 861 { 862 status = PJMEDIA_RTP_EINDTMF; 863 break; 864 } 865 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; 872 } 873 874 if (status != PJ_SUCCESS) 875 goto on_return; 876 877 if (stream->dtmf_count ==0) { 878 pj_uint32_t start_ts; 879 880 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; 883 } 884 885 /* Increment digit count only if all digits are valid. */ 886 stream->dtmf_count += digit_char->slen; 887 888 } 889 890 on_return: 891 pj_mutex_unlock(stream->jb_mutex); 892 893 return status; 894 } 895
Note: See TracChangeset
for help on using the changeset viewer.