ladendirekt / pjsip4net

A wrapper library exposing the pjsip library to the .NET world in a OO-friendly way.
71 stars 42 forks source link

Echo on outgoing calls #104

Closed rndthoughts closed 5 years ago

rndthoughts commented 5 years ago

Describe the bug When making outgoing calls, the caller can hear themselves speaking a second or so after they have spoken. When calling in from an external device (e.g. mobile phone) this echo does not happen.

To Reproduce Steps to reproduce the behavior:

  1. Dial an outgoing number.
  2. Callee picks up.
  3. Caller can hear their own voice repeated back down the audio output channel.

Expected behavior Caller should not be able to hear themselves played back down the audio channel

Screenshots N/A

Environment (please complete the following information):

App configuration (please complete the following information):

  <sipua srtp="Disabled" secureSignaling="0" logMessages="true" logLevel="5" traceAndDebug="false" autoAnswer="false" autoRecording="false" autoConference="false" maxCalls="5">
    <sipTransport type="udp" Port="5080" />
    <networkSettings natInSDP="true" forceLooseRoute="false">
      <turn enabled="false" server="" type="udp" userName="" password="" realm="" />
      <ice enabled="false" noRTCP="false" />
    </networkSettings>
    <media isVADEnabled="true" />
  </sipua>

Additional context Only happens when the caller is calling out using this library to either an external or internal number.

siniypin commented 5 years ago

Hi, did you play around with Echo Canceller options that are controlled with MediaConfig?

You can set it with values found in pjmedia_echo_flag enum. Give a PJMEDIA_ECHO_SPEEX a try.

More info here: https://www.pjsip.org/docs/latest-1/pjsip/docs/html/structpjsua__media__config.htm#a734653d7e5d075984b9a51f053ded879
and here: https://trac.pjsip.org/repos/wiki/sound-problems

siniypin commented 5 years ago

Also try increasing EcTailLen

rndthoughts commented 5 years ago

When i set either of those two properties (e.g. ecOptions):

<media isVADEnabled="true" ecOptions="1" />

It results in:

image

siniypin commented 5 years ago
  1. It seems unrelated as there is smth running on one of the ports you app is using.
  2. I don't think you can set ecOptions with xml config. It simply is not there: https://github.com/siniypin/pjsip4net/blob/master/pjsip4net/Configuration/MediaConfigurationElement.cs#L30
siniypin commented 5 years ago

For some reason I think setting EcTailLen to 500 ms may solve the problem.

rndthoughts commented 5 years ago

Thanks for the pointers - I think the error is misleading me because of the missing automapped properties not existing. When the configuration is loaded and ecOptions is being mapped to a non-existant property it throws:

System.Configuration.ConfigurationErrorsException: 'Unrecognized attribute 'ecOptions'. Note that attribute names are case-sensitive.

This then causes configuration loading to fail hence the PjsipErrorException.

siniypin commented 5 years ago

Yep, you can manipulate config props that aren't available with xml .config during a creation of user agent as in the following example: https://gist.github.com/siniypin/7860386

rndthoughts commented 5 years ago

OK - setting either of those properties doesn't fix the problem. It always affects the outgoing caller. We have managed to run our application a couple of times in between without the echo occurring but after another call it returns.

We are setting the active audio devices using. Is there anything else to be aware of? Could it be something to do with the Windows Wave Mapper?

UserAgent.MediaManager.SetSoundDevices(playbackId, captureId)

rndthoughts commented 5 years ago

Narrowed it down further, it's always the first outgoing call that experiences echo. If that call is hung up then subsequent calls do not experience the problem

siniypin commented 5 years ago

Hmm, that sounds fishy. Can you collect SIP trace as well as library logs? First thing I'd check would be SDP headers to see what are the clients negotiating upon.

rndthoughts commented 5 years ago

Could you point me at some documentation as to how to capture the trace? Do you mean use the logging library in pjsip4net?

siniypin commented 5 years ago

Yes, you need to set the following props in config:

logMessages="true" logLevel="5" traceAndDebug="true"

and route your logs anywhere you like, e.g. to a file with log4net

rndthoughts commented 5 years ago

I've copied the configuration but when running I get -

An error occurred creating the configuration section handler for common/logging: Unable to create type 'Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net'
siniypin commented 5 years ago

A tiny bit more info here: https://github.com/siniypin/pjsip4net#logging

siniypin commented 5 years ago

Make sure all necessary libraries are there, e.g. log4net.

rndthoughts commented 5 years ago

To get it to run, I had to reference Common.Logging.Log4Net208 to match the log4net version I was running or it couldnt find the adapter. It now runs and should be writing logs to log.txt - presumably in the bin folder, but nothing is output?

rndthoughts commented 5 years ago

Further info - this is only happening when i run the app i've built on two different machines making an internal call. If i mute the sound devices on the callee's app then the caller can still hear their own voice played back to them. So it must be happening on the caller's app.

rndthoughts commented 5 years ago

Found it! I had miscoded what happens when the anwering party picks up and interconnected two slots together twice!

siniypin commented 5 years ago

Hey, glad you've nailed it! Lessons learned? Should pjsip4net raise an exception or at least log a warning when someone tries to interconnect the same port?

rndthoughts commented 5 years ago

I think it's just down to my misunderstanding of how pjsip works in regards to the conference slots. A warning would be good but I never got the logging to work - I just couldnt seem to configure NLog properly and didnt get any text output.

What would be really useful is an example of answering a call in the testing console application as that's what's missing.

I'm aware I've still got an outstanding PR to make on another issue!

siniypin commented 5 years ago

What would be really useful is an example of answering a call in the testing console application as that's what's missing.

That's a good idea, thanks!