linphone-developers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Linphone-developers] DTMF issues with oRTP


From: Vadim Lebedev
Subject: Re: [Linphone-developers] DTMF issues with oRTP
Date: Mon, 14 Apr 2008 12:31:45 +0200
User-agent: Thunderbird 2.0.0.12 (X11/20080227)

Mike wrote:

Hello,

 

I’ve developed a custom SIP application (using my own SIP library), and oRTP for the media channel.

 

Everything seems to work great, other than some occasional DTMF issues (RFC2833 using the rtp_session_send_dtmf() function in oRTP).

 

If I run wireshark (ethereal) on the interface, and I send out a DTMF tone, normally I see five packets (three packets, then the third repeated two more times for reliability)- which correlates exactly with the code in telephonyevents.c. The maximum duration gets to 480.

 

But, occasionally, I’ll send a DTMF tone, and see hundreds of packets (the last test I did, sent out 200 packets), and the duration keeps incrementing (the last test incremented up to 32160). It does also send the last packet three times as in the first case for reliability.

 

Because of  the long duration, this obviously translates into a long tone on the receiving end, which is causing me some issues with some termination providers (some deal with it fine).

 

Does anybody have any thoughts on where these extra packets are coming from?

 

I’ve downloaded the CVS version of oRTP from the linphone distribution; I saw there was some changes related to the sequence number and timestamp, but it didn’t seem to resolve this issue.

 

Any help would be greatly appreciated,

 

Mike

  
A Lot time ago i've fixed oRTP DTMF generating  code,  i don't remember if my code finally made it's way to maing oRTP tree...


Here it goes:

=======================
/**
 *rtp_session_create_telephone_event_packet:
 address@hidden: a rtp session.
 address@hidden:    boolean to indicate if the marker bit should be set.
 *
 *    Allocates a new rtp packet to be used to add named telephony events. The application can use
 *    then rtp_session_add_telephone_event() to add named events to the packet.
 *    Finally the packet has to be sent with rtp_session_sendm_with_ts().
 *
 *Returns: a message block containing the rtp packet if successfull, NULL if the rtp session
 *cannot support telephony event (because the rtp profile it is bound to does not include
 *a telephony event payload type).
**/
mblk_t    *rtp_session_create_telephone_event_packet(RtpSession *session, int start)
{
    mblk_t *mp;
    rtp_header_t *rtp;
   
    g_return_val_if_fail(session->snd.telephone_events_pt!=-1,NULL);
   
    mp=allocb(RTP_FIXED_HEADER_SIZE+TELEPHONY_EVENTS_ALLOCATED_SIZE,BPRI_MED);
    if (mp==NULL) return NULL;
    rtp=(rtp_header_t*)mp->b_rptr;
    rtp->version = 2;
    rtp->markbit=start;
    rtp->padbit = 0;
    rtp->extbit = 0;
    rtp->cc = 0;
    rtp->ssrc = session->local.ssrc;
    /* timestamp set later, when packet is sended */
    /*seq number set later, when packet is sended */
   
    /*set the payload type */
    rtp->paytype=session->snd.telephone_events_pt;
   
    /*copy the payload */
    mp->b_wptr+=RTP_FIXED_HEADER_SIZE;
    return mp;
}

/**
 *rtp_session_send_dtmf:
 address@hidden    : a rtp session
 address@hidden        : a character meaning the dtmf (ex: '1', '#' , '9' ...)
 address@hidden    : the timestamp
 *
 *    This functions creates telephony events packets for @dtmf and sends them.
 *    It uses rtp_session_create_telephone_event_packet() and
 *    rtp_session_add_telephone_event() to create them and finally
 *    rtp_session_sendm_with_ts() to send them.
 *
 *Returns:    0 if successfull, -1 if the session cannot support telephony events or if the dtmf
 *    given as argument is not valid.
**/
gint rtp_session_send_dtmf(RtpSession *session, gchar dtmf, guint32 userts)
{
  return rtp_session_send_dtmf2(session, dtmf, userts, 480);
}

gint rtp_session_send_dtmf2(RtpSession *session, gchar dtmf, guint32 userts, int duration)
{
    mblk_t *m1,*m2,*m3;
    int tev_type;
    int durationtier = duration/3;

    /* create the first telephony event packet */
    switch (dtmf){
        case '1':
            tev_type=TEV_DTMF_1;
        break;
        case '2':
            tev_type=TEV_DTMF_2;
        break;
        case '3':
            tev_type=TEV_DTMF_3;
        break;
        case '4':
            tev_type=TEV_DTMF_4;
        break;
        case '5':
            tev_type=TEV_DTMF_5;
        break;
        case '6':
            tev_type=TEV_DTMF_6;
        break;
        case '7':
            tev_type=TEV_DTMF_7;
        break;
        case '8':
            tev_type=TEV_DTMF_8;
        break;
        case '9':
            tev_type=TEV_DTMF_9;
        break;
        case '*':
            tev_type=TEV_DTMF_STAR;
        break;
        case '0':
            tev_type=TEV_DTMF_0;
        break;
        case '#':
            tev_type=TEV_DTMF_POUND;
        break;

        case 'A':
        case 'a':
          tev_type=TEV_DTMF_A;
          break;


        case 'B':
        case 'b':
          tev_type=TEV_DTMF_B;
          break;

        case 'C':
        case 'c':
          tev_type=TEV_DTMF_C;
          break;

        case 'D':
        case 'd':
          tev_type=TEV_DTMF_A;
          break;

        case '!':
          tev_type=TEV_FLASH;
          break;


        default:
        g_warning("Bad dtmf: %c.",dtmf);
        return -1;
    }

    m1=rtp_session_create_telephone_event_packet(session,1);
    if (m1==NULL) return -1;
    rtp_session_add_telephone_event(session,m1,tev_type,0,10,durationtier);
    /* create a second packet */
    m2=rtp_session_create_telephone_event_packet(session,0);
    if (m2==NULL) return -1;
    rtp_session_add_telephone_event(session,m2,tev_type,0,10, durationtier+durationtier);
       
    /* create a third and final packet */
    m3=rtp_session_create_telephone_event_packet(session,0);
    if (m3==NULL) return -1;
    rtp_session_add_telephone_event(session,m3,tev_type,1,10,duration);
   
    /* and now sends them */
    rtp_session_sendm_with_ts(session,m1,userts);
    rtp_session_sendm_with_ts(session,m2,userts+durationtier);
    /* the last packet is sent three times in order to improve reliability*/
    m1=copymsg(m3);
    m2=copymsg(m3);
    /*            NOTE:            */
    /* we need to copymsg() instead of dupmsg() because the buffers are modified when
    the packet is sended because of the host-to-network conversion of timestamp,ssrc, csrc, and
    seq number.
    It could be avoided by making a copy of the buffer when sending physically the packet, but
    it add one more copy for every buffer.
    Using iomapped socket, it is possible to avoid the user to kernel copy.
    */
    rtp_session_sendm_with_ts(session,m3,userts+durationtier+durationtier);
    rtp_session_sendm_with_ts(session,m1,userts+durationtier+durationtier);
    rtp_session_sendm_with_ts(session,m2,userts+durationtier+durationtier);
    return 0;
}























_______________________________________________ Linphone-developers mailing list address@hidden http://lists.nongnu.org/mailman/listinfo/linphone-developers


reply via email to

[Prev in Thread] Current Thread [Next in Thread]