【问题标题】:Android Java Pjsip - one way audio after reinviteAndroid Java Pjsip - 重新邀请后的单向音频
【发布时间】:2020-11-13 00:19:31
【问题描述】:

我们在尝试重新邀请通话时遇到问题。

案例 1 - 工作:当 A 呼叫 B,B 接听电话,然后 A 暂停 - 在 B 侧播放 pjsip 音乐,在 A 取消暂停呼叫后,音频是双向传输——通话正常。

案例 2 - 不工作: A 呼叫 B,B 接听电话,然后如果 B 保持通话,则 A 侧不会播放 pjsip 音乐以通知用户通话暂停。此外,当 B 决定取消保持通话时,有一种方式从 A -> B 传输音频,例如 ptt(A 听不到 B)。 搁置后,我们得到了几个相同的错误,如下所示,不像取消搁置后我们不断收到每个传输包的错误,例如:srtp0x55a4c04d70 Failed to unprotect SRTP, pkt size=49, err=authentication failure

所以,我检查了日志,如果 B 在接听后立即将呼叫置于保持状态然后取消保持 - 他正在发送包裹,但 A 方没有收到它。 (通话结束时登录)

我们使用的是 pjsip 2.10。 (最新),opus 1.3.1(最新),openSSL 1.1.1g,还有 TLS over UDP。我们尝试在没有 opus 的情况下构建 pjsip lib,我们在互联网上找到了一些 pjsip 构建,但出现了同样的问题。我们不能禁用 TLS,因为它是连接到服务器(Asterisk 13.14.0)的强制性要求。 在 GSM @8kHz 上建立呼叫。如果我们在服务器上为某些用户启用 opus 并在 opus 编解码器上建立呼叫,我们会遇到相同的 PTT(单向音频)行为。 实现是在 Flutter 移动应用程序中,但 pjsip 部分是在本机 Java 端完成的。 PjsipPlugin.java

public void holdCall() {
    CallOpParam prm = new CallOpParam(true);
    mFirstCall.setHold(prm);
}

 public void unHoldCall() {
    CallOpParam prm = new CallOpParam(true);
    prm.getOpt().setFlag(pjsua_call_flag.PJSUA_CALL_UNHOLD);
    prm.getOpt().setAudioCount(1);
    mFirstCall.reinvite(prm);
}

MyCall.java

@Override
public void onCallMediaState(OnCallMediaStateParam prm)
  {
    CallInfo callInfo;
    try
    {
      callInfo = getInfo();
    } catch (Exception e)
    {
      Log.e(TAG,"Exception occurred in onCallMediaState: getInfo: " + e.getMessage());
      return;
}

CallMediaInfoVector mediaInfoVector = callInfo.getMedia();

for (int i = 0; i < mediaInfoVector.size(); i++)
{
  CallMediaInfo mediaInfo = mediaInfoVector.get(i);
  int type = mediaInfo.getType();
  int status = mediaInfo.getStatus();

  if (type == pjmedia_type.PJMEDIA_TYPE_AUDIO
          && (status == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE
          || status == pjsua_call_media_status.PJSUA_CALL_MEDIA_REMOTE_HOLD))
  {
    try
    {
      Media media = getAudioMedia(i);//getMedia(i);
      AudioMedia am = AudioMedia.typecastFromMedia(media);

      PjSipManager.mEndPoint.audDevManager().getCaptureDevMedia().startTransmit(am);
      am.startTransmit(PjSipManager.mEndPoint.audDevManager().getPlaybackDevMedia());
    } catch (Exception e)
    {
     // e.printStackTrace();
      Log.e(TAG,"Exception occurred in onCallMediaState: " + e.getMessage());
    }
  }

}

PjSipManager.observer.notifyCallMediaState(this);}

【问题讨论】:

标签: java android openssl pjsip opus


【解决方案1】:

我只是处于相同的情况,使用与您的情况相同的环境。

实际上这不是一个答案,但也许可以帮助您检查自己的行为,因为我认为该代码是有效的,但是应该设置一些特定的配置,并且在 pjsip 页面上描述得不是很好(来自我的观点)。

我尝试了许多不同的配置组合并找到了原因(就我而言),但仍然不知道如何解决问题。 您能否在您的系统上尝试这种组合并确认行为。 有问题的一点是,当两个客户端都使用 SRTP 的配置时。 那么我们直接上代码吧:

客户端 A 和客户端 B 将 srtp 的使用设置为强制/可选

mAccountConfig.getMediaConfig().setSrtpUse(pjmedia_srtp_use.PJMEDIA_SRTP_MANDATORY);
mAccountConfig.getMediaConfig().setSrtpSecureSignaling(0);

在这种情况下,您将得到预期的行为,您可以从 A 向 B 拨打电话,B 可以接听,在 B 侧设置保持 -> 并且会得到很多“无法取消保护 SRTP”消息,当您从 B 处取消保留时,由于 A 方解密失败,呼叫者 A 听不到任何声音。 --> 所以这实际上是这里的问题。

好的,在代码中尝试了一些不同的组合,在客户端 A 上使用 SRTP,在 B 客户端上使用 DISABLED SRTP 标志 --> 有效

客户 A:

mAccountConfig.getMediaConfig().setSrtpUse(pjmedia_srtp_use.**PJMEDIA_SRTP_MANDATORY**);
mAccountConfig.getMediaConfig().setSrtpSecureSignaling(0);

客户 B:

mAccountConfig.getMediaConfig().setSrtpUse(pjmedia_srtp_use.**PJMEDIA_SRTP_DISABLED**);
mAccountConfig.getMediaConfig().setSrtpSecureSignaling(0);

所以,我仍在努力寻找 pjsip 的最佳参数组合,以便在双方都使用相同的配置..

另外,当我尝试为两个客户端使用配置以使用 DISABLED srtp 配置时,我可以在 pjsip 库的日志中看到收到了邀请,但它没有传播到 java 处理程序,所以我无法捕捉到事件(奇怪的行为)来获取早期/调用事件状态,.. 我不想使用禁用 srtp 的客户端,但这也是我尝试过的组合,有点奇怪。

我会尝试一些其他的组合,如果我发现一些其他有用的信息会做一些更新..

【讨论】:

  • 感谢分享信息。我也尝试过这种组合,我可以说我的行为和你一样,奇怪......肯定会朝那个方向进一步调查。如果您发现了其他信息或工作场景,请分享:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-08
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多