summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-08-13 11:53:56 +0000
committerBenny Prijono <bennylp@teluu.com>2007-08-13 11:53:56 +0000
commite98db7abda0bea7e779ab589753aaa3b9b3f148b (patch)
tree4993524aed71776aa19df9729c9caa266dc43c8c
parent013e1a2bfce4c8f2d02694e59cd08b0a52ae7b80 (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
-rw-r--r--pjmedia/src/pjmedia/stream.c75
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: