PJSIP 检测通话过程中对方手机发送过来的in-bnad DTMF(no rfc2833)按键信息

本文介绍了在PJSIP客户端如何检测通话过程中的in-band DTMF(非rfc2833)按键信息。作者遇到IMS运营商环境下的问题,并最终通过分析RTP流数据并利用Spandsp库成功实现检测。详细过程包括查阅官方FAQ、尝试多种方法失败、寻求外国开发者帮助并获得解决方案。
摘要由CSDN通过智能技术生成

最近做项目有用到在PJSIP客户端接收手机通过过程中发送过来的DTMF按键信息,刚开始查了一点资料发现pjsip有相应的方法,在pjsua_config  cfg; 这个结构体的通过设置此回调函数cfg.cb.on_call_state貌似就可以实现 ,之后就开始实践了。用pjsip客户端+freeswitch+x-lite进行试验,试验相当顺利,心情那个激动啊。但是没激动多久,当我放到正式的运营环境用我的pjsip客户端+IMS运营商+真实手机进行测试时彻底傻眼了,根本检测不出来手机的按键信息,查了资料才发现手机发送的DTMF信息应该是属于in-band DTMF no rfc2833 ,悲催的是PJSIP官方并没有支持这中DTMF格式。

还好没放弃经过一个多月的瞎折腾总算弄出点结果出来了。

PJSIP官网的FAQ有对in-band DTMF no rfc2833问题解释,我就不扯淡了,直接给链接 http://trac.pjsip.org/repos/wiki/FAQ#tone-detect  。解释到是挺简单的,看起来很容易,但是对于我这中新手,我就只能呵呵了。查了快一个月的资料到是发现三四种方法,一一去试,没一个成功的,心情郁闷啊。最后还是厚着脸皮,凭着自己一手烂英语邮件去问外国友人。还好,外国友人都是相当热情的,等了一天就有人回复了,在这里要感谢 Eize Slange 这位大哥,不仅很快就给出了回复而且也给了相应的实现代码,非常感谢啊。

参照着给出的代码来进行实现果然有效,高兴啊!!!

我就简单介绍一下他给出的示例代码吧。

要取得in-band DTMF 按键信息就要检测sip客户端接收到的RTP流数据,并对RTP数据流使用Spandsp的库分析其中的DTMF按键信息,然后就大功告成了。

代码流程如下:

1.pjsip客户端层

on_call_media_state 的回调函数中修改代码如下:

Note: pCallData / callData is some own class holding some info per call...


callback: on_call_media_state:

...
    /* Handle media status */
    switch (call_info.media_status) 
    {
      case PJSUA_CALL_MEDIA_ACTIVE:
 ...

 pj_status_t   result     = PJ_SUCCESS;
 pjmedia_port* media_port = NULL;
 unsigned      slot_port  = 0;
 pjsua_dtmfdet_config dtmf_cfg;

 // Only attach once...              
 if ( NULL == callData->dtmfData.media_port )
 {
dtmf_cfg.call_id          = call_id;
dtmf_cfg.filter_dialtone  = PJ_FALSE;
dtmf_cfg.twist            = 8;   // Twist is set to 8 dB by default.
dtmf_cfg.reverse_twist    = 4;   // Reverse twist is set to 4 dB by default. This value can be safely increased up to 6 or 7 without a significant increase in talk-off to allow DTMFs that exceed this threshold to be detected.
dtmf_cfg.threshold        =-42;  // Threshold is set to -42 dBm0 by default.
dtmf_cfg.cb.on_dtmf_digit = &on_ib_dtmf_callback;    

log_writer(SLL_EVENT, "StackDll:on_call_media_state: Attach INBAND DTMF detection");
result =  pjsua_attach_inband_dtmf_detector( call_id,
 app_config.media_cfg.clock_rate, 
app_config.media_cfg.channel_count,
160,      // samples per frame
 16,       // bits per sample
&dtmf_cfg,
PJ_FALSE, // because this called from pjsua-callback
&media_port,
&slot_port );

if ( PJ_SUCCESS == result )
{
 callData->dtmfData.media_port = media_port;
 callData->dtmfData.slot_port  = slot_port;
}
...


 
callback: on_stream_destroyed::

...
    // Release/reset Inband DTMF
    pCallData = CallGetCallData(call_id);
    if ( NULL != pCallData )
    {
      if ( NULL != pCallData->dtmfData.media_port )
      {
        log_writer(SLL_LEVEL_2, "StackDll:on_stream_destroyed> Detach INBAND detector...");
        pjsua_detach_inband_dtmf_detector( pCallData->dtmfData.media_port,
                                           pCallData->dtmfData.slot_port,
                                           PJ_FALSE); // because called from callback
      }

      pCallData->dtmfData.detectedOutbound = PJ_FALSE;
      pCallData->dtmfData.lastDigit        = -1;
      pCallData->dtmfData.media_port       = NULL;
      pCallData->dtmfData.slot_port        = 0;
    }
...
static void on_ib_dtmf_callback(pjsua_call_id call_id, int dtmf)
{
  // Your callback code when inband DTMF digit has been detected.
  // Note: this is the same callback prototype as the normal DMTF callback of PJSIP,
  //       but to distinguish between RFC2833 DTMF and this inband a dedicated
  //       callback can be created.
}


2.在pjsua.h新增如下:
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值