Different codecs for different VSP

Support zone
davidnewton
Posts: 179
Joined: Thu Aug 27, 2009 3:00 am

Different codecs for different VSP

Post by davidnewton » Tue Nov 16, 2010 8:50 pm

I am trying to figure out if it is possible in SS to use different codecs for different VSPs. My scenario is: I would like to use G726 for the calls between SS accounts without VSP, while use G711u for voip.ms to call PSTN (voip.ms does not support G726). Right now, if I set my ATA's preferred codec as G726 on both ends, there is no problem for calls between SS accounts, but there is sound quality problem when I call PSTN using voip.ms. I am wondering if it is possible to specify the codec in the Dial() method or other methods in the dialplan. Thanks.

Aaron
Site Admin
Posts: 4652
Joined: Thu Jul 12, 2007 12:13 am

Re: Different codecs for different VSP

Post by Aaron » Tue Nov 16, 2010 10:19 pm

It's sort of possible as the SDP from your ATA is exposed in the dialplan. However you'd really need to be a bit of a regular expression whiz to fiddle with it.

I'll be doing a little bit of work in that area over the coming week or two so I'll see what can be done about adding a more user friendly dialplan function to manipulate codecs.

davidnewton
Posts: 179
Joined: Thu Aug 27, 2009 3:00 am

Re: Different codecs for different VSP

Post by davidnewton » Wed Nov 17, 2010 5:41 am

Aaron: Thanks for the reply. It will be very helpful to choose codecs in the dialplan. Do you have any quick sample dialplan for this purpose, or tell me which function could accept the codec as arguments in the Ruby dialplan script?

Best Regards,
David

xur17
Posts: 2
Joined: Mon Aug 16, 2010 9:57 pm

Re: Different codecs for different VSP

Post by xur17 » Wed Nov 17, 2010 7:27 pm

The ability to manipulate codecs on sipsorcery's side (to change the order of codecs, re-encode) would be very useful to me. My device automatically uses one of the higher bandwidth codecs. Changing the codec preferences on my device doesn't work (its buggy), but if I could either remove or reorder the codecs sent to the device, this could fix the issue for me.

Aaron
Site Admin
Posts: 4652
Joined: Thu Jul 12, 2007 12:13 am

Re: Different codecs for different VSP

Post by Aaron » Wed Nov 17, 2010 10:54 pm

davidnewton wrote:Aaron: Thanks for the reply. It will be very helpful to choose codecs in the dialplan. Do you have any quick sample dialplan for this purpose, or tell me which function could accept the codec as arguments in the Ruby dialplan script?

Best Regards,
David
I don't have any smaples but the dialplan method you can use to set a custom SDP packet is:

Code: Select all

sys.SetCustomContent(string sdp)
You can get the oriingal SDP from req.Body. So the suggested approach would be:

Code: Select all

customSDP = req.Body
#Do some fancy manipulations on the customSDP string.
sys.SetCustomContent(customSDP)
sys.Dial("1234@somewhere.com")

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Re: Different codecs for different VSP

Post by MikeTelis » Thu Nov 18, 2010 8:17 am

Aaron wrote:customSDP = req.Body
#Do some fancy manipulations on the customSDP string.
sys.SetCustomContent(customSDP)
Probably it would be easier to split SDP into lines and then rebuild again:

Code: Select all

sdp = req.Body.split("\r\n")
# ... manipulate the lines
sys.SetCustomContent(sdp.join("\r\n")
Anyway, it's just a technique. Thank you very much for this tool!

Question: in order to change codec preference, is it enough to rearrange payload types in the m=* string or I also need to resort a=rtpmap lines in order as they appear in the m=* line?

AndrewZ
Posts: 19
Joined: Thu Nov 13, 2008 10:03 pm

Re: Different codecs for different VSP

Post by AndrewZ » Thu Nov 18, 2010 12:17 pm

MikeTelis wrote: Question: in order to change codec preference, is it enough to rearrange payload types in the m=* string or I also need to resort a=rtpmap lines in order as they appear in the m=* line?
Yes, it's enough.
a=rtpmap lines may be even missing in SDP if they are "describing" static payload types (per RFC4566).

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Re: Different codecs for different VSP

Post by MikeTelis » Thu Nov 18, 2010 12:51 pm

AndrewZ wrote:Yes, it's enough.
a=rtpmap lines may be even missing in SDP if they are "describing" static payload types (per RFC4566).
Unfortunately, my quick experiments proven it wrong. Here is the original SDP:

Code: Select all

o=- 141683 141683 IN IP4 192.168.1.33
s=-
c=IN IP4 192.168.1.33
t=0 0
m=audio 16480 RTP/AVP 18 0 2 4 8 96 97 98 100 101
a=rtpmap:18 G729a/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:2 G726-32/8000
a=rtpmap:4 G723/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:96 G726-40/8000
a=rtpmap:97 G726-24/8000
a=rtpmap:98 G726-16/8000
a=rtpmap:100 NSE/8000
a=fmtp:100 192-193
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=ptime:30
a=sendrecv
If I swap 18 and 0 in the m= line nothing happens, the SPA is still using G.729 code. If I remove 18 completely or rearrange a= lines so that PCMU (a=rtpmap:0) goes first, SPA connects using u-Law.

So, I believe we need to rearrange both m= and a= but... let's see what the guru (Aaron) says :)

Just in case you wish to experiment, here is my code:

Code: Select all

sdp = req.Body.split("\r\n").map do |line|
  if line =~ /^(m=audio)\s+(\d+)\s+RTP\/AVP\s+(.+)$/
    line = "#$1 #$2 RTP/AVP 0 18 2 4 8 96 97 98 100 101"
  end
  line
end.join("\r\n")

sys.SetCustomContent(sdp)

AndrewZ
Posts: 19
Joined: Thu Nov 13, 2008 10:03 pm

Re: Different codecs for different VSP

Post by AndrewZ » Thu Nov 18, 2010 2:58 pm

Try different provider.
Some VSPs are ignoring your preference order and providing connection using their own preferences but keeping in mind your capabilities.

MikeTelis
Posts: 1582
Joined: Wed Jul 30, 2008 6:48 am

Re: Different codecs for different VSP

Post by MikeTelis » Thu Nov 18, 2010 3:04 pm

I've been experimenting with Voxalot's echo test (*600).

Note what I said in my previous post: they did switch to u-Law once I changed the order of a=* lines.

Anyway, I have written a chunk of code implementing the algorithm:

Code: Select all

CRLF = "\r\n"

def set_codec_priority(sdp, order)
  lines = sdp.split(CRLF)
  pos = 0; pt = {}; codecs = {}; port = ''; m = []; newsdp = []

  lines.each_with_index do |ln, i|
    case ln
      when /^m=audio\s+(\d+)\s+RTP\/AVP\s+(.+)$/
        port = $1; m = $2.split(/\s+/).map {|x| x.to_i}; pos = i
      when /^(a=(rtpmap|fmtp):(\d+)\s+(((.+)\/.+)|.*))$/
        n = $3.to_i; pt[n] ||= [];
        pt[n] << $1; codecs[$6.upcase] = n if $6
      else newsdp << ln
    end
  end
  # Find PTs for requested codecs, remove codecs not listed in original m=*
  requested = order.gsub(/\s+/,'').split(',').map{|x| codecs[x]}.compact
  m = requested + (m-requested) # Put requested codecs in front

  ( newsdp[0,pos] + ["m=audio #{port} RTP/AVP #{m.join(' ')}"] +
    m.map {|x| pt[x]}.flatten + newsdp[pos-1,200]
  ).join(CRLF)
end

sys.SetCustomContent(set_codec_priority(req.Body, 'PCMA, PCMU, G729A, ILBC'))
The codecs in 2nd parameter must be in upper case. Critics are welcome! :)

Post Reply