概述
使用kamailio+rtpengine的过程中,发现一个DTMF传输的问题,会造成DTMF传送错误。
主要原因是AB路的rfc2833的payload有差异造成的,可以通过kamailio的配置逻辑来修复。
环境
CentOS 7.9
kamailio:5.8.3-bullseye docker
rtpengine:mr13.1.1.6-4 docker
问题
kamailio 5.8.3 + rtpengine 13.1.1.6,媒体代理模式。
A路invite的sdp中dtmf参数如下。
m=audio 45540 RTP/AVP 8 18 97
a=rtpmap:97 telephone-event/8000
a=fmtp:97 0-15
经过kamailio转发后的invite的sdp。
m=audio 33088 RTP/AVP 8 18 97
a=rtpmap:97 telephone-event/8000
a=fmtp:97 0-15
B路响应的200OK的sdp中dtmf参数如下。
m=audio 16394 RTP/AVP 8 101
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
经过kamailio转发后的200OK。
m=audio 31724 RTP/AVP 8
A路sdp中dtmf的payload为97,kaimailio正常透传,B路响应sdp中dtmf的payload为101,经过kamailio+rtpengine处理后,sdp中的dtmf编码被删除了。
通话接通后,A路按键发送DTMF码,采用inband波形模式,B路无法正常识别。
修复
问题的本质是B路响应的sdp中dtmf的payload被删除了,但是媒体通道并没有受影响,媒体转发也没有任何问题,所以最直接的办法就是在kamailio的cfg配置中再把payload加回去。
修改kamailio.cfg文件,主要修改如下。
...
modparam("rtpengine", "write_sdp_pv", "$avp(sdp)")
...
route[RESET_DTMF]{
	xinfo("route[RESET_DTMF]\n");
	# reset DTMF payload
	if(search_body("telephone-event/8000") && !search_str($avp(sdp), "telephone-event/8000")) 
	{
		xinfo("Added DTMF 101 payload to SDP\n");
		$avp(sdp) = $(avp(sdp){re.subst,/^(m=audio.* 8)/\1 101/});
		$avp(sdp) = $(avp(sdp){re.subst,/^(a=rtpmap:8 PCMA.*)$/\1\na=rtpmap:101 telephone-event\/8000\na=fmtp:101 0-15/});
		set_body("$avp(sdp)", "application/sdp");
	}
	else {
		xinfo("DTMF 101 payload already exists in SDP\n");
		set_body("$avp(sdp)", "application/sdp");
	}
	return;
}
route[RTPENGINE] {
	xinfo("route[RTPENGINE]\n");
	# check if have sdp
	if (!has_body("application/sdp"))
	{
		xinfo("!has_body(application/sdp)\n");
		return;
	}
	if(ds_is_from_list("3060") || ds_is_from_list("3061"))
	{
		xinfo("route[RTPENGINE], 3060|3061\n");
		# from pub, to priv
		rtpengine_manage("replace-origin replace-session-connection direction=pub direction=priv ");
		set_body("$avp(sdp)", "application/sdp");
	}
	else if(ds_is_from_list("5060"))
	{
		xinfo("route[RTPENGINE], 5060\n");
		# from priv, to pub
		rtpengine_manage("replace-origin replace-session-connection direction=priv direction=pub ");
		route(RESET_DTMF);
	}
	return;
}思路就是针对AB路会有不同payload的场景,调用route(RESET_DTMF),在PCMA编码的后面加上payload=101的编码。
测试
重启kamailio,发起呼叫。
从信令中看到,经过kamailio处理后的200OK的sdp中增加了payload=101的dtmf编码。
A路按键测试,可以看到rtpengine正常转发了dtmf码。
总结
kamailio+rtpengine作为媒体代理的方式简单易用,转发效率高,不会修改媒体包的内容,rtp和rtcp都可以正常透传转发。
空空如常
求真得真