Asterisk 13: Opus: No translation path

Hi,

I set up a Asterisk 13 system (13.13-cert1) from scratch. Among others, I included chan_opus.
When I start asterisk, I see that opus translation paths are missing:

CLI> core show translation paths opus
--- Translation paths SRC Codec "opus" sample rate 48000 ---
	opus:48000       To g723:8000       : No Translation Path
	opus:48000       To ulaw:8000       :
	opus:48000       To alaw:8000       :
	opus:48000       To gsm:8000        :
	opus:48000       To g726:8000       :
	opus:48000       To g726aal2:8000   :
	opus:48000       To adpcm:8000      : No Translation Path
	opus:48000       To slin:8000       :
	opus:48000       To slin:12000      : No Translation Path
	opus:48000       To slin:16000      : No Translation Path
	opus:48000       To slin:24000      : No Translation Path
	opus:48000       To slin:32000      : No Translation Path
	opus:48000       To slin:44100      : No Translation Path
	opus:48000       To slin:48000      : (opus@48000)->(slin@48000)
	opus:48000       To slin:96000      : No Translation Path
	opus:48000       To slin:192000     : No Translation Path
	opus:48000       To lpc10:8000      : No Translation Path
	opus:48000       To g729:8000       : No Translation Path
	opus:48000       To speex:8000      : No Translation Path
	opus:48000       To speex:16000     : No Translation Path
	opus:48000       To speex:32000     : No Translation Path
	opus:48000       To ilbc:8000       : No Translation Path
	opus:48000       To g722:16000      : No Translation Path
	opus:48000       To siren7:16000    : No Translation Path
	opus:48000       To siren14:32000   : No Translation Path
	opus:48000       To testlaw:8000    :
	opus:48000       To g719:48000      : No Translation Path
	opus:48000       To none:8000       : No Translation Path
	opus:48000       To silk:8000       : No Translation Path
	opus:48000       To silk:12000      : No Translation Path
	opus:48000       To silk:16000      : No Translation Path
	opus:48000       To silk:24000      : No Translation Path

The translation table is also incomplete:

*CLI> core show translation
         Translation times between formats (in microseconds) for one second of data
          Source Format (Rows) Destination Format (Columns)

           ulaw  alaw   gsm  g726 g726aal2  slin  slin testlaw  opus
     ulaw     -  9150 15000 15000    15000  9000     -   15000     -
     alaw  9150     - 15000 15000    15000  9000     -   15000     -
      gsm 15000 15000     - 15000    15000  9000     -   15000     -
     g726 15000 15000 15000     -    15000  9000     -   15000     -
 g726aal2 15000 15000 15000 15000        -  9000     -   15000     -
     slin  6000  6000  6000  6000     6000     -     -    6000     -
     slin     -     -     -     -        -     -     -       -  6000
  testlaw 15000 15000 15000 15000    15000  9000     -       -     -
     opus     -     -     -     -        -     -  9000       -     -

How can I “add” the missing translation paths?
Before switching to Asterisk 13, we ran a Asterisk 11 system (11.6-cert11) where we applied a patch to get opus support. On this system, the translation table is complete.

Thanks,
Ouss

Do you have codec_resample loaded? It is what performs downsampling/upsampling for the other rates.

Hi,

Thanks, I loaded codec_resample and the translation table looks good now!

But: I get a lot of the following errors when performing a call:

[Mar  8 17:34:35] ERROR[17714][C-00000000]: ../src/audioUtils.cpp:162 int opusMapFrameSizeToSampleRate(int): Unknown sample rate for Opus frame size 186
[Mar  8 17:34:35] ERROR[17714][C-00000000]: ../src/audioUtils.cpp:162 int opusMapFrameSizeToSampleRate(int): Unknown sample rate for Opus frame size 99
[Mar  8 17:34:35] ERROR[17714][C-00000000]: ../src/audioUtils.cpp:162 int opusMapFrameSizeToSampleRate(int): Unknown sample rate for Opus frame size 102
[Mar  8 17:34:35] ERROR[17714][C-00000000]: ../src/audioUtils.cpp:162 int opusMapFrameSizeToSampleRate(int): Unknown sample rate for Opus frame size 127
[Mar  8 17:34:35] ERROR[17714][C-00000000]: ../src/audioUtils.cpp:162 int opusMapFrameSizeToSampleRate(int): Unknown sample rate for Opus frame size 187
[Mar  8 17:34:35] ERROR[17714][C-00000000]: ../src/audioUtils.cpp:162 int opusMapFrameSizeToSampleRate(int): Unknown sample rate for Opus frame size 193
[Mar  8 17:34:35] ERROR[17714][C-00000000]: ../src/audioUtils.cpp:162 int opusMapFrameSizeToSampleRate(int): Unknown sample rate for Opus frame size 122

I see in the translation path above that the opus sample rate is 48000. Do you have any idea why it is unknown to Asterisk (Unknown sample rate for Opus)?
I could not find any hints googling the problem.

Thanks,
Ouss

That message is coming from the Opus library itself. What device or client are you using?

Hi,

The connecting device is an iPhone running an proprietary app. The app uses opus 1.1 (opus-codec.org).
Note that I see this problem only if we transcode (i.e. when calling from “our app” (using opus) to a regular SIP phone without opus). On the other hand, if we perform calls between our apps (using opus), the problem does not occur.

Best regards,
Ouss

We give the Opus library a frame and it decodes information from it, such as the sample rate (while Opus is 48KHz internally it can be a different sample rate). I’ve seen no other reports of this problem, so it’s likely something specific to your environment. Without transcoding we would just pass the data between each side - so provided each side was doing the same thing, it’d work. What is the output of “rtp set debug on” with packets flowing? Are you adding extra data to each frame?

Hi,

We do not add extra data to each frame.
“rtp set debug on” prints nothing, but I guess this is because of our setup: the iPhone client calls a number which shall play back a gsm file (i.e. no SIP call involved). In the dialplan:

exten => _5113,1,Answer()
exten => _5113,n,Wait(3)
exten => _5113,n,Playback(you-are-caller-num)
exten => _5113,n,Wait(1)

The following shall happen: the client connects to our backend which creates an Asterisk channel (read/write format: ast_format_opus) and starts the call. Asterisk figures out in the dialplan that the you-are-caller-num must be played back. Because the file is in gsm format, Asterisk will transcode to opus and hand the data back to the created channel. We take the data from the channel and send it to our iPhone client which decodes opus.

I read about the Asterisk opus configuration here and added the following configuration (in /etc/asterisk/codecs.conf):

[opus]
type=opus
signal=voice
application=voip
sample_rate=8000
max_bandwidth=narrow
max_playback_rate=16000
bitrate=auto
cbr=true

Note that the client expects a sample rate of 8000 and a constant bit rate (cbr=true).

Now, when Asterisk calls the write callback on the channel to provide a frame, I see that the value of frame->framelen is changing with each callback invocation (99, 118, 111, 101, etc.), but frame->framelen should have a constant value: 28 (for a sample rate of 8000).

Looks to me like the cbr=true and sample_rate=8000 are ignored.

In the opus configuration link above, there is the following hint:

These custom format types can then be specified in the “allow” line of an endpoint.

So I added

opus=allow

in sip.conf. But this did not improve the situation.

It looks to me like something is wrong with the opus configuration, but I do not see what it is.

Best regards,
Ouss

I don’t understand how you are using things. Are you using your own channel driver? How is media being transported?

Yes, we are using our own channel driver.

The data (opus encoded) is transported via UDP between the client and the backend (channel driver).

The frames given to the translator should originate from your channel driver, so the problem is likely somewhere there. I can’t support that as a result. I can say, though, that it works fine with PJSIP and RTP.

I use chan_sip and not PJSIP. May this be a problem?

You just said you use your own channel driver and transport media your own way. If media from that is what is being fed into the decoder, then the problem points to there.

Right.

What I do not understand is the following: in the scenario described above (play back of you-are-caller-num), Asterisk encodes the sound file to opus and gives the data back to our channel driver (via ast_channel_tech's write() callback). Why is the frame size constantly changing even though I configured opus with cbr=true and a sample rate of 8000 which shall result in a constant frame size of 28? Does the configuration in codecs.conf only apply to proper SIP calls? How can I enforce my settings?

Thanks,
Ouss

It would be allow=opus in the sip.conf which should work. Looking at the codec_opus code it does use those from the format so it should work, but there may be a case where it isn’t.

Ok, this was a typo, I actually used allow=opus in sip.conf without success.

I cannot find codec_opus.c in my Asterisk code base (asterisk-certified-13.13-cert1). It this dynamically added/compiled?

The codec_opus module is a binary module. Issues for it can be filed on the issue tracker[1].

[1] https://issues.asterisk.org/jira

Ok, thanks for the explanation.

I found a copy of codec_opus.c in the Internet and stumbled over this:

if (cbr) {
    opus_encoder_ctl(enc->enc, OPUS_SET_VBR_CONSTRAINT(cbr));
}

Looking at the libopus documentation, OPUS_SET_VBR_CONSTRAINT() does not set the encoder to a constant bit rate, but OPUS_SET_VBR(0) would.

Thanks,
Ouss

Our implementation is not based on that and does not use OPUS_SET_VBR_CONSTRAINT.