Modifying transcoding in asterisk

Hi,

I see the following transcoding done for channel Dahdi/1-1 from alaw to slin48

Name: DAHDI/1-1

NativeFormats: (alaw)
WriteFormat: slin48
ReadFormat: slin48
WriteTranscode: Yes (slin@48000)->(slin@8000)->(alaw@8000)
ReadTranscode: Yes (alaw@8000)->(slin@8000)->(slin@48000)

I would like to suppress the transcoding altogether so that only alaw is used.

Any thoughts on how to do this? Much thanks!

We would need details of the other channel involved and the dialplan in order understand why lan48 was involved at all.

Here are the details …

This is comms between two asterisk system using IAX …

First we are going to a Dahdi channel then to asterisk. (Note: the digital audio audio when it arrives at the Dahdi channel is encoded in alaw.) In so doing, we get the following transcoding as detailed above …

Name: DAHDI/1-1

NativeFormats: (alaw)
WriteFormat: slin48
ReadFormat: slin48
WriteTranscode: Yes (slin@48000)->(slin@8000)->(alaw@8000)
ReadTranscode: Yes (alaw@8000)->(slin@8000)->(slin@48000)

From there, we go from one asterisk system to another using the opus codec and IAX. This is the transcoding that we see …

Name: IAX2/ua_vip-12603
NativeFormats: (opus)
WriteFormat: slin48
ReadFormat: slin48
WriteTranscode: Yes (slin@48000)->(opus@48000)
ReadTranscode: Yes (opus@48000)->(slin@48000)

The part of the dialplan that concerns this is straightforward:
[globals]
FEATURES_LIST=PttOn#PttOff#J7#J8#J9#J0

[general]
autofallthrough=no

[inbound]

; ask the VIP where to route calls to 4-digit extensions

_exten => _XXXX,1,Set(_DYNAMIC_FEATURES=${FEATURES_LIST})
_exten => XXXX,n,Answer()
_exten => XXXX,n,Dial(DAHDI/1)
_exten => XXXX,n,Hangup()

Finally, here are relevant parts of codecs.conf, pjsip.conf and iax.conf:

codecs.conf:

[opus8]
type=opus
signal=voice
max_playback_rate=8000
fec=yes

pjsip.conf:
;================================ TRANSPORTS ==
; Our primary transport definition for UDP communication behind NAT.
[simpletransport]
type = transport
protocol = udp
bind = 0.0.0.0
; NAT settings
;local_net = 10.0.0.0/8
;external_media_address = 203.0.113.1
;external_signaling_address = 203.0.113.1

;=================================================
; remote-dial
;=================================================
[remote-dial]
type=endpoint
context=inbound
transport=simpletransport
disallow=all
allow=opus8:60
;allow=alaw, ulaw
aors=remote-dial
ice_support=no
rtp_timeout=15

[remote-dial]
type=aor
;So that registration can happen from anywhere
remove_existing=yes
max_contacts=1

[remote-dial]
type=identify
endpoint=remote-dial
match=uav

iax.conf:
[general]
autokill=yes

; Listener Addresses
;
; Use the ‘bindaddr’ and ‘bindport’ options to specify on which address and port
; the IAX2 channel driver will listen for incoming requests.
;
;

bindport=4569 ; The default port to listen on

bindaddr=192.168.40.198

bandwidth=low

;
; You can also fine tune codecs here using “allow” and “disallow” clauses with
; specific codecs. Use “all” to represent all formats.
;
;allow=all
;disallow=g723.1
disallow=all
allow=opus8:60
;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Jitter Buffer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

jitterbuffer=yes
maxjitterbuffer=200

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; IAX2 Encryption
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; trunkfreq sets how frequently trunk messages are sent in milliseconds. This
; value is 20ms by default, which means the trunk will send all the data queued
; to it in the past 20ms. By increasing the time between sending trunk messages,
; the trunk’s payload size will increase as well. Note, depending on the size
; set by trunkmtu, messages may be sent more often than specified. For example
; if a trunk’s message size grows to the trunkmtu size before 20ms is reached
; that message will be sent immediately. Acceptable values are between 10ms and
; 1000ms.
;
trunkfreq=40 ; How frequently to send trunk msgs (in ms). This is 20ms by
_ ; default._

; Should we send timestamps for the individual sub-frames within trunk frames?
; There is a small bandwidth use for these (less than 1kbps/call), but they
; ensure that frame timestamps get sent end-to-end properly. If both ends of
; all your trunks go directly to TDM, and your trunkfreq equals the frame
; length for your codecs, you can probably suppress these. The receiver must
; also support this feature, although they do not also need to have it enabled.
;
trunktimestamps=yes

register => ground_vip:12345678@192.168.40.201

[ua_vip]
type=friend
host=192.168.40.201
trunk=yes
secret=12345678
;context=iax_incoming
context=inbound
disallow=all
allow=opus8:60

Thank you for looking into this!!!

Are you using any of originate, call files and local channels?

Pjsip for local channel…

A local channel is not the same as a pjsip channel. The reason I asked is that local channels and originate can result in the call being set up with codecs that match neither end point.

Then we are not using local channels …

We are not using originate, call files, nor local channels …

Based on your information one side is using opus and the other alaw, there has to be a transcoding path for that scenario. If that’s not the scenario then you’ll need to provide further information and clarify.

Yes, there is transcoding that is going on between alaw and opus, but with slin48000 as the intermediary encoding format.

As background info, audio enters the dahdi channel on one asterisk as alaw and then gets transcoded to slin8000 and finally to slin48000.

Then it gets sent via IAX to a second asterisk but with opus specified for the IAX trunk. So there is another transcoding … from slin48000 to opus48000.

Problem is we are limited to narrowband between the two asterisks so we need the final encoding to be opus8000.

Here are the details:
On the 1st asterisk:
Name: DAHDI/1-1
NativeFormats: (alaw)
WriteFormat: slin48
ReadFormat: slin48
WriteTranscode: Yes (slin@48000)->(slin@8000)->(alaw@8000)
ReadTranscode: Yes (alaw@8000)->(slin@8000)->(slin@48000)

From there, we go to the second asterisk via IAX and opus.
This is the transcoding that we see for the IAX trunk from the 1st asterisk.
Name: IAX2/ua_vip-12603
NativeFormats: (opus)
WriteFormat: slin48
ReadFormat: slin48
WriteTranscode: Yes (slin@48000)->(opus@48000)
ReadTranscode: Yes (opus@48000)->(slin@48000)

My questions are:
How can I prevent the transcoding from alaw to slin in the first place so that I can go directly from alaw to opus8000?

However, if the alaw format data must be transcoded to slin first, how do I stop it at slin8000 so that I can transcode from slin8000 to opus8000 (for the IAX trunk)?

Thank you for your help.

Sorry I missed the point originally.

My suspicion is that the bit rate is a constraint applied to the codec, not a different codec. I think the translation path code probably only determines translations based on the codec name, so has to assume the maximum possible settings for the codec.

Chances are that the code has been written so that it only knows how to encode Opus from 48kHz signed linear, so you would probably have to rewrite the translation code (is the Opus codec module open source?)

I wouldn’t expect there to be a direct translation form G.711 A-Law to anything other than 8kHz signed linear. That translation is going to have to be done to make the maths straightforward, when going to any of the complex codecs.

What confused me originally, and still confuses me, is why the translation is split across the bridge. I would have expected the whole translation to be done on the outgoing side for the direction. However, that doesn’t change the fact that there will be multiple steps in the translation.

The codec_opus module only supports a 48kHz output and input.

Thank you for your help David! :grinning:

Thank you jcolp! :grinning: