最近帮同事解决掉2个既存的问题,一个是linphone通话后双方没声音问题。另一个是多次呼叫时喇叭不出振铃音问题。
今天先来说明第一个问题的解决思路。
两方通话没声音问题存在多个版本的app都存在。因为再现率不高,一直被忽略。直到最近新的壁挂设备出来,这个问题
突然再现率高起来,到了必须解决的节点了。
一开始app开发人员对音频解码,消混音和静音处理做了调查,没发现问题点。app开发人员怀疑是系统网络问题。
当我着手问题时,第一项还是对问题进行再现。通过问题出现时的现象确定并不是系统网络的问题。
因为当问题发生时,只是通话两方只是没有语音,但视频却是流畅的。这时候同事发现当问题发生时有一条异常log重复出现。
异常log说明语音收发都不能成功。sendto()和recvfrom()返回的errno分别是9和88。这时候我adb shell进入到系统里面,通过
netstat -nuat查看端口的情况。通过对端口的查看发现当通话发起时语音端口7076(RTP)和7077(RTPC)都是存在的。但接通后
会出现7076(RTP)端口关闭消失的情况。看来是通信端口的问题导致的语音包无法正常收发。
然后下一步就是根据异常的Log信息进行准确的代码定位,分析这一部分异常log为什么出来。
根据对代码的分析确认,程序中应该关闭了标准输入,导致了文件描述符0处于空闲状态。这样当
fd=socket()获取文件描述符时获取到的文件描述符就是0.当对0的文件描述符进行sendto()和recvfrom()时就很容易出现问题了。
到了这一步应该app开发人员去调查程序里面怎么操作了系统的标准输入文件描述符。但app开发人员对文件操作了解不多,我
对部分文件进行了代码走读。看到linphone中有一段代码,
#ifdef __ios
/*hack for iOS and non-working socket because of background mode*/
if (errnum==ENOTCONN){
//if (errnum==ENOTCONN){
/*re-create new sockets */
rtp_session_set_local_addr(session,session->rtp.gs.sockfamily==AF_INET ? "0.0.0.0" : "::0",session->rtp.gs.loc_port,session->rtcp.gs.loc_port);
}
#endif
这段代码的作用就是当发现rtp链接出现异常时,重新建立rtp链接。只不过默认这段处理是被关闭的。既然通过既存的处理可以屏蔽这个问题,那就直接打开屏蔽开关吧,哈哈
至此问题解决!