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: Mike
Subject: RE: [Linphone-developers] DTMF issues with oRTP
Date: Mon, 14 Apr 2008 13:20:55 -0400

Thanks Vadim,

 

It looks like your changes did indeed make it into the tree- this code looks exactly (other than some of the obvious g* types and functions, and a few changes made after this, adjusting the timestamp and sequence number) like the code I’m using from the linphone distribution.

 

This code looks fairly straight forward- I can’t see any obvious reason why I would get the results I’m getting.

 

I do also have a trace from wireshark that shows this output if that helps?

 

Is there anywhere else in the code that deals with events? Or that might re-send packets for some reason?

 

Thanks,


Mike

 

From: Vadim Lebedev [mailto:address@hidden
Sent: Monday, April 14, 2008 6:32 AM
To: Mike
Cc: address@hidden
Subject: Re: [Linphone-developers] DTMF issues with oRTP

 

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]