[asterisk-dev] Codec change with re-invite

Julian J. M. julianjm at gmail.com
Wed Nov 28 05:44:55 CST 2007


I'm trying to force a codec change on an active SIP call. I created a
simple application that basically calls transmit_reinvite_with_sdp(),
and is forced to use the specified codec in the SDP.

exten => s,1,NoOp(Call initially uses gsm)
exten => s,n,Playback(demo-congrats)  ; 1)
exten => s,n,SipCodec(ulaw)
exten => s,n,Wait(1)  ; *********
exten => s,n,Playback(demo-congrats)  ; 2)
exten => s,n,SipCodec(gsm)
exten => s,n,NoOp(No wait)
exten => s,n,Playback(demo-congrats)   ;3)
exten => s,n,Hangup

1) Channel uses gsm codec, as expected
2) Channel uses ulaw, but audio quality is degraded compared to 1).
Asterisk changes to ulaw as soon as it receives the first ulaw RTP
packet. It's probably doing some transcoding internally.
3) Channel continues to use ulaw. It never changes to gsm if I don't
set a Wait(1) after the change. While Wait(1)ing, asterisk doesn't
send any RTP packet.

Can anyone with more asterisk internals knowledge tell me why doesn't
this work as expected? How does Sipura ATA's force a codec change to
ulaw when a fax is detected?

Below is the application code:

/*! \brief Reinvite the channel and try to change the codec */
static int sip_sipcodec(struct ast_channel *chan, void *data) {
        int fmt;
        char *arg=(char*)data;
        struct sip_pvt *p;
        int tmp;

        if (ast_strlen_zero(arg)) {
                ast_log(LOG_WARNING, "This application requires the
argument: CODEC\n");
                return 0;

        fmt = ast_getformatbyname(arg);

        if (!fmt) {
                ast_log(LOG_NOTICE, "Incorrect codec %s\n", arg);
                return 0;


        if (chan->_state != AST_STATE_UP) {
                ast_log(LOG_WARNING, "Channel is not UP. Please use
SIP_CODEC variable instead");
                return 0;

        if (chan->tech != &sip_tech && chan->tech != &sip_tech_info) {
                ast_log(LOG_WARNING, "Call this application only on
SIP incoming calls\n");
                return 0;

        p = chan->tech_pvt;
        if ( ( fmt & p->capability & p->peercapability ) != fmt) {
                ast_log(LOG_WARNING, "Selected codec not supported on
both ends.\n");
                return 0;


        /* Only our codec in the SDP */

        return 0;

Julian J. Menendez


More information about the asterisk-dev mailing list