Fixed ticket #363: Incorrect RTP marker and timestamp in DTMF event/RFC 2833 packet (thanks Pedro Sanchez)

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1416 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Benny Prijono 2007-08-13 11:53:56 +00:00
parent 2d3aea2e0a
commit 742ed7d4a8
1 changed files with 41 additions and 34 deletions

View File

@ -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: