I have a small asterisk setup with an external SIP trunk and few local agents. When a client calls he is answered by an agent and everything works flawlessly. Sound quality is great. I want the agents to start using ‘hold’ in their phones (Jitsi softphone). However the MOH which plays when client is put on hold using ‘hold’ button in softphone is extremely choppy and garbled. I’m using the default MOH sounds.
The ‘hold’ button in Jitsi works by sending a SIP INVITE from agent to asterisk with ‘sendonly’ flag, this indicates to asterisk that it should start MOH to the client.
It works, but the music is broken:
– Started music on hold, class ‘default’, on channel ‘SIP/uplink24-0000000e’
> Locally RTP bridged ‘SIP/uplink24-0000000e’ and ‘SIP/108-0000000f’ in stack
I tried starting MOH using three other methods:
using Answer + MusicOnHold app in dialplan (instead of Dial, just to test it) - works fine, music is always clear
using Dial with ‘m’ flag (without Answer), this works as well because my SIP provider allows early-media, music is always clear
using AGI and Parking the call with it:
Action: Park
Channel: SIP/uplink24-00000008
Timeout: 0
The client is parked, MOH starts playing clearly and without any issues. Agent leg is obviously dropped. I can resume the call later with AGI Redirect and continue in the call.
In all cases I’m using g722 codec. I have used the standard music in gsm format (which resulted in real-time transcoding) and also manually transcoded it to g722 so there is no real-time transcoding needed. Always same results.
Also I have to add that when I call between two agents and one puts the other one on hold using the ‘hold’ button the music is fine. So this looks to be related just to the uplink SIP peer and only when using the ‘hold’ button.
Why is the MOH choppy and unbearable when put on hold using softphone ‘hold’ button and it works just fine with any of the other three methods?
When running wireshark I noticed that Jitsi still sends RTP packets when the call is on hold. I noticed in the ‘hold’ INVITE packet there is ‘sendonly’ keyword. Apparently this is done so that Jitsi can send some MoH. However Jitsi does not send anything but white noise. The hold is therefore not bidirectional but unidirectional. Then I applied iptables filter to block those RTP packets during one-way hold and the MoH which asterisk sends to client improved to 100% quality - no more stuttering.
My view is that asterisk is somehow trying to mix the white noise Jitsi is sending with the MoH which asterisk is sending (maybe preferring the noise from Jitsi) and that causes breaks. When I blocked the RTP packets from Jitsi the problem went away.
I couldn’t think of easy way how to automate blocking of the RTP packets so instead I looked in the source code of asterisk and I modified the one-way hold to become two-way hold. Very simply said - if one side sends ‘sendonly’ in SDP then I forced asterisk to consider it as ‘inactive’ which means two-way hold. I know this is extremely bad solution but it solves my problem. I can’t modify Jitsi code to not send the white noise or to send ‘inactive’ instead of ‘sendonly’ in SDP.
I’m not proposing to include this in asterisk. This is VERY BAD, but it works. However maybe adding an per peer option to force all one-way holds to be two-way holds? Or adding another option to Dial() to do the same thing?
I believe chan_pjsip has an option to accept the sendonly stream, rather than trying to replace it.
Also, as far as I can remember, you only get problems if the sendonly stream is being sent as direct media, in which case it the final destination that gets the mixed streams. I can’t remember if chan_sip reinvites the media back during a hold.
The underlying problem is that sendonly is used as a signal for hold, as well as for a true sendonly stream, and when normal phones signal hold, they don’t provide media, so having Asterisk provide media works best when dealing with typical phones.