Summary:ASTERISK-20461: channel originate Local/foo * forces translation via slin
Reporter:Jaco Kroon (jkroon)Labels:
Date Opened:2012-09-21 18:59:18Date Closed:
Status:Open/NewComponents:Applications/app_originate Channels/chan_local
Versions: 13.18.4 Frequency of
is related toASTERISK-28785 chan_local: Unnecessary transcoding for Originate (local channels)
Environment:Attachments:( 0) asterisk-chan_local_g729.patch
( 1) asterisk-originate-with-all.patch
( 2) asterisk-originate-with-g729.patch
( 3) slin.txt
( 4) trace.txt
Description:The simplest example of this is with a SIP and an IAX2 endpoint available, eg SIP/102 and IAX2/upstream, both configured with disallow=all; allow=g729 with codecs from digium loaded.

cli> originate Local/102@aanswer Dial IAX2/upstream/number

once connected a g729 show licenses will show that two encoders and two decoders are in use.

Comments:By: Jaco Kroon (jkroon) 2012-09-21 19:03:16.859-0500

CLI output from a relatively simple example.

I suspect the issue stem from the fact that normally a Local/ channel will derivc it's format from the channel creating it (parent channel?), which will then just end up doing a simple pass-through.

However, since app_originate originates the channel using SLINEAR format, this prevents to the end-points from negotating the format to use properly and ends up forcing translation via slin, even when the two formats on either side of the Local channel are the same.

In my opinion the Local channel should adopt whatever format gets set up for leg1 of the Local channel in this case, and not SLINEAR.

If someone can push me in a direction I'll be happy to try and cook a patch, however, I have no idea where to start with this.

By: Matt Jordan (mjordan) 2012-09-26 16:09:57.660-0500

I'm fine with this as an improvement to local channels, but I don't think this is a bug.  Having the Local channel infer its codec based on the ;1 leg would be possible, but there are certain scenarios that would have to be worked, such as optimized/non-optimized Local channel chains, and if the ;1 isn't bridged to a channel but an application.

By: Jaco Kroon (jkroon) 2012-09-27 00:45:16.004-0500

Thanks Matt, that answer is truly short and sweet.  Allow me to throw around a few more ideas.

Interesting note about ;1 being connected to an application.

Here is two alternate ideas I had since logging the issue:

(1)  Whenever ;1 or ;2 gets bridged to a new destination (be it another channel or an application) recheck the Local internal format and see if there is perhaps a better format available?

(2)  Or, just don't have an internal format and use the bridged channel/applications format on ;1 for ;2, and vice versa?  If not bridged, then support all formats and /dev/null the written audio (or don't support any formats at all)?  This should be OK, consider for example Playback() on ;1, if ;2 isn't bridged to *something*, what's the point of generating media (timing perhaps?)?

What worries me somewhat about 1 is if  ;1 is in dialplan or an application when bridging on ;2 occurs then it may be holding the format fixed, and adopting the format from ;2 might be better, at the same time the opposite is also true.

As it stands currently I think SLINEAR is a good choice in the cases where translation has to happen via slin anyway, but a "bad" choice if the formats on either side of Local is the same, or can be transcoded natively.

I need to make note that I don't think there is an issue with optimized/non-optimized channels, either way we should attempt to transcode directly between the formats for ;1 and ;2 and not force transcoding via slin.

By: Jaco Kroon (jkroon) 2012-09-27 00:46:17.918-0500

Still wanted to state - please push me in a direction of where to get started on any of the solutions, and which would technically be the best solution (ie, which should I aim for)?

By: Matt Jordan (mjordan) 2012-09-27 12:13:18.747-0500

Just curious: if both sides on the Local channel have the same format, why are you using an non-optimizing Local channel?  I would expect in such cases you would create the Local channel without the {{\n}} option, at which point once both sides have answered, it would optimize itself away and the two sides - which have the same format - would be made compatible and no transcoding would occur.

If that isn't happening, then that's interesting.

If the Local channel isn't optimized away and we wanted to inspect the formats, I would imagine you would do it in {{local_call}}, which has both 'sides' of the channels that the Local channel owns.  The two channel halves should be populated after the call to {{awesome_locking}}, at which point you could inspect their format capabilities and find out if one is common.  You could then set that as the preferred format on the Local channel.

By: Jaco Kroon (jkroon) 2012-09-28 22:47:07.311-0500


That isn't happening.  That's where we first picked it up, I then messed around with both optimizing and non-optimizing in an attempt to get it to work.  There was one or two other options that also looked interesting but also made to difference.

By: Matt Jordan (mjordan) 2012-10-02 17:01:22.657-0500


It may not be happening because technically, both sides have "Answered".  This means Asterisk should have already negotiated the formats for both endpoints.  Assuming that you ended up with format_a for phone_a and format_b for phone_b, after the Local channel gets optimized away, you would end up having to re-INVITE to both phones to renegotiate the codecs.

It may actually be undesirable to have that happen, since I know some folks are rather keen on having as few re-INVITEs get sent around as possible.

That leads back to your first point, however: it'd be nice if you could set the format on the Local channel, which would then hopefully force the other channels to negotiate when they first get set up.  I'm not sure how that'd be configured, however, or if - as you suggested - you use whatever is on the end of ;1 (if its a channel) to determine what the codec should be.

It might be a bit intrusive for a release branch, but this sounds like an improvement that could be made in trunk.

By: Jaco Kroon (jkroon) 2012-10-23 04:33:17.016-0500


These attachments are some of my debug patches.  The originate-with-g729 (which I expected to work) doesn't, I had to drill down all the way into chan_local and had to change the format there to get g729 pass-through to work as expected.

This is extremely counter-intuitive for me and I don't understand why the first patch doesn't work.

Neither of these patches are intended for production!!  They were intended as shortcuts to get one of my clients that urgently needed this up and running.  Starting to run into this on a large scale on other systems (utilizing other codecs as well) too, and am going to need to start work on this again.

Would appreciate help on this issue.

By: Jaco Kroon (jkroon) 2012-10-23 05:14:56.828-0500

Also, regarding the "both sides have answered", surely this statement isn't quite accurate.

At the time when ;1 gets bridged ;2 isn't even in the dialplan yet (at least, not in my scenario).  In my scenario when ;1 is in dialplan we really don't care about the codec, but once ;1 gets answered we should probably switch to it's codec directly.  Ie, probably discard the existing transcoding chain (if there are no listeners - eg Monitor()) and attach the IO for the bridged channel of ;1 directly to ;2?

Not sure if my explanation makes sense but I sincerely hope it does.

Is there any scenarios that I'm missing here?  The only other case I can currently think of is Dial(Local/number@context), in which case the same strategy will probably hold too, since ;2 enters into the dialplan directly, there is no reason why we can't use the IO channels for whatever ;1 is connected to on ;2 ??

I really am a little stumped as to the best way to deal with this from a code perspective.

By: Jaco Kroon (jkroon) 2013-06-30 13:28:44.371-0500


Just tested this on asterisk 11.4.0 - and the same issue remains.  Except, this time a simple patch to app_originate.c doesn't seem to be so simple ...

Even removing all the SLINEAR capabilities and adding only G729A does not have the desired effect and the behaviour remains exactly the same.

Will attach some sample CLI output in a moment.

By: Jaco Kroon (jkroon) 2013-06-30 13:43:35.555-0500

output from CLI showing translation ...

By: Jaco Kroon (jkroon) 2013-06-30 14:41:57.073-0500

So I've been staring at a much simpler version of app_originate in 11.X compared to 1.8.X - and something did eventually raise a few question marks, specifically we're adding capabilities for various incarnations of SLINEAR, but surely the Local/ chan is able to pass-through pretty much ANY format?  Including video, text, t38 and others, so (keeping in mind that I would not consider myself an expert in any definition of the word when it comes to asterisk code) why do we only add capability for slinear?  Why not simply use ast_format_cap_add_all() for adding all capabilities and being done with it?

Then I realized that trying to just swap this to G729A didn't fix my use-case any more.  And went looking and found three locations for "updating" this:

1.  apps/app_originate.c
2.  main/manager.c (does this belong here?!)
3.  res/res_clioriginate.c

Surely that would (should) allow for a more appropriate native format being negotiated when ;1 answers and allow for passing that through to ;2 resulting in direct pass-through instead of transcoding via slin?  But this too doesn't actually work (will attach patch for reference anyway, perhaps it can spark an idea in someone else - it seems to aim for SLINEAR192 for some reason and then transcode path gets even worse - ie, g729 => slinear => slinear192 => slinear => g729).

WriteTranscode: Yes (slin192)->(slin)->(g729)
 ReadTranscode: Yes (g729)->(slin)->(slin192)

For the moment I once more reverted to just adding AST_FORMAT_G729A as the only capability instead of SLINEAR, which solves my use-case but most certainly does not cover the generic case.

By: laszlovl (lvl) 2020-04-02 02:56:10.304-0500

As Joshua found, I created a ticket that's pretty much a duplicate of this case in ASTERISK-28785. For anyone interested, more information can be found there.

>  at which point once both sides have answered, it would optimize itself away and the two sides - which have the same format - would be made compatible and no transcoding would occur.

An interesting fact that wasn't mentioned in this ticket yet, is that this does in fact work properly _sometimes_ in _some Asterisk versions_.

I have a reproduction testcase that automatically detects whether the unnecessary transcoding is performed (manager originate without any codecs, both SIP clients only configured with g722):

In Asterisk 15.3 it fails pretty much 50% of the time

4 fails, 6 succeeds

In Asterisk 16.3 and 16.8 it fails 100% of the time

10 fails, 0 succeeds

In Asterisk 16.3 with commit https://github.com/asterisk/asterisk/commit/a46fcaca7bcb019a1a2b29d3c9a528da637840d7 reverted it's back to only failing about 50% of the time

4 fails, 6 succeeds

I have no clue why commit a46fcaca7bcb019a1a2b29d3c9a528da637840d7 is a culprit here, I found it using bisect. I guess it subtly changes the timing which causes the bridge reconfiguration to fail.