diff options
author | Benny Prijono <bennylp@teluu.com> | 2007-08-13 11:53:56 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2007-08-13 11:53:56 +0000 |
commit | e98db7abda0bea7e779ab589753aaa3b9b3f148b (patch) | |
tree | 4993524aed71776aa19df9729c9caa266dc43c8c /pjmedia | |
parent | 013e1a2bfce4c8f2d02694e59cd08b0a52ae7b80 (diff) |
Fixed ticket #363: Incorrect RTP marker and timestamp in DTMF event/RFC 2833 packet (thanks Pedro Sanchez)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1416 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/src/pjmedia/stream.c | 75 |
1 files changed, 41 insertions, 34 deletions
diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c index 924d4573..4b0ca144 100644 --- a/pjmedia/src/pjmedia/stream.c +++ b/pjmedia/src/pjmedia/stream.c @@ -62,7 +62,7 @@ struct pjmedia_channel struct dtmf { int event; - pj_uint32_t start_ts; + pj_uint32_t duration; }; /** @@ -373,51 +373,48 @@ static pj_status_t get_frame( pjmedia_port *port, pjmedia_frame *frame) * Transmit DTMF */ static void create_dtmf_payload(pjmedia_stream *stream, - struct pjmedia_frame *frame_out) + struct pjmedia_frame *frame_out, + int *first, int *last) { pjmedia_rtp_dtmf_event *event; struct dtmf *digit = &stream->tx_dtmf_buf[0]; - unsigned duration; pj_uint32_t cur_ts; pj_assert(sizeof(pjmedia_rtp_dtmf_event) == 4); + *first = *last = 0; + event = (pjmedia_rtp_dtmf_event*) frame_out->buf; cur_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); - duration = cur_ts - digit->start_ts; - if (duration == 0) { + if (digit->duration == 0) { PJ_LOG(5,(stream->port.info.name.ptr, "Sending DTMF digit id %c", digitmap[digit->event])); - duration = stream->port.info.samples_per_frame; - digit->start_ts = cur_ts - duration; + *first = 1; } + digit->duration += stream->port.info.samples_per_frame; + event->event = (pj_uint8_t)digit->event; event->e_vol = 10; - event->duration = pj_htons((pj_uint16_t)duration); + event->duration = pj_htons((pj_uint16_t)digit->duration); + + + if (digit->duration >= PJMEDIA_DTMF_DURATION) { - if (duration >= PJMEDIA_DTMF_DURATION) { event->e_vol |= 0x80; + *last = 1; /* Prepare next digit. */ pj_mutex_lock(stream->jb_mutex); + pj_array_erase(stream->tx_dtmf_buf, sizeof(stream->tx_dtmf_buf[0]), stream->tx_dtmf_count, 0); --stream->tx_dtmf_count; - stream->tx_dtmf_buf[0].start_ts = cur_ts; pj_mutex_unlock(stream->jb_mutex); - - if (stream->tx_dtmf_count) { - PJ_LOG(5,(stream->port.info.name.ptr, - "Sending DTMF digit id %c", - digitmap[stream->tx_dtmf_buf[0].event])); - } - } - frame_out->size = 4; } @@ -525,7 +522,7 @@ static pj_status_t put_frame_imp( pjmedia_port *port, unsigned ts_len, samples_per_frame; void *rtphdr; int rtphdrlen; - + int inc_timestamp = 0; /* Don't do anything if stream is paused */ if (channel->paused) { @@ -554,16 +551,28 @@ static pj_status_t put_frame_imp( pjmedia_port *port, * Otherwise encode the PCM buffer. */ if (stream->tx_dtmf_count) { + int first=0, last=0; - create_dtmf_payload(stream, &frame_out); + create_dtmf_payload(stream, &frame_out, &first, &last); - /* Encapsulate. */ + /* Encapsulate into RTP packet. Note that: + * - RTP marker should be set on the beginning of a new event + * - RTP timestamp is constant for the same packet. + */ status = pjmedia_rtp_encode_rtp( &channel->rtp, - stream->tx_event_pt, 0, - frame_out.size, ts_len, + stream->tx_event_pt, first, + frame_out.size, (first?ts_len:0), (const void**)&rtphdr, &rtphdrlen); + if (last) { + /* This is the last packet for the event. + * Increment the RTP timestamp of the RTP session, for next + * RTP packets. + */ + inc_timestamp = PJMEDIA_DTMF_DURATION - ts_len; + } + } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { unsigned ts, codec_samples_per_frame; @@ -666,6 +675,14 @@ static pj_status_t put_frame_imp( pjmedia_port *port, /* Copy RTP header to the beginning of packet */ pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr)); + /* Special case for DTMF: timestamp remains constant for + * the same event, and is only updated after a complete event + * has been transmitted. + */ + if (inc_timestamp) { + pjmedia_rtp_encode_rtp( &channel->rtp, stream->tx_event_pt, 0, + 0, inc_timestamp, NULL, NULL); + } /* Set RTP marker bit if currently not streaming */ if (stream->is_streaming == PJ_FALSE) { @@ -1576,24 +1593,14 @@ PJ_DEF(pj_status_t) pjmedia_stream_dial_dtmf( pjmedia_stream *stream, } stream->tx_dtmf_buf[stream->tx_dtmf_count+i].event = pt; + stream->tx_dtmf_buf[stream->tx_dtmf_count+i].duration = 0; } if (status != PJ_SUCCESS) goto on_return; - /* Init start_ts and end_ts only for the first digit. - * Subsequent digits are initialized on the fly. - */ - if (stream->tx_dtmf_count ==0) { - pj_uint32_t start_ts; - - start_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); - stream->tx_dtmf_buf[0].start_ts = start_ts; - } - /* Increment digit count only if all digits are valid. */ stream->tx_dtmf_count += digit_char->slen; - } on_return: |