buildG711Answer function
Build an SDP answer for a G.711 audio offer, per RFC 3264 §6.
Unlike buildG711Offer, the resulting m=audio line lists only the
codec we agreed to use plus (optionally) the peer's telephone-event
payload type — not a fresh full menu. That matters for peers that
pick the first PT from our answer instead of intersecting again.
Implementation
String buildG711Answer({
required String username,
required String localHost,
required int localPort,
required SdpAudio remoteOffer,
int? rtcpPort,
SdpDirection direction = SdpDirection.sendrecv,
int? sessionId,
int? sessionVersion,
}) {
final sid = sessionId ?? DateTime.now().millisecondsSinceEpoch ~/ 1000;
final ver = sessionVersion ?? sid;
final codec = remoteOffer.codec;
final dtmfPt = remoteOffer.telephoneEventPt;
final dtmfRange = remoteOffer.telephoneEventRange ?? '0-15';
final ptNumbers = <int>[codec.payloadType, if (dtmfPt != null) dtmfPt];
final lines = <String>[
'v=0',
'o=$username $sid $ver IN IP4 $localHost',
's=flutter_sip_ua',
'c=IN IP4 $localHost',
't=0 0',
'm=audio $localPort RTP/AVP ${ptNumbers.join(' ')}',
'a=rtpmap:${codec.payloadType} ${codec.rtpmap}/8000',
if (dtmfPt != null) ...[
'a=rtpmap:$dtmfPt telephone-event/8000',
'a=fmtp:$dtmfPt $dtmfRange',
],
if (rtcpPort != null) 'a=rtcp:$rtcpPort',
'a=ptime:20',
'a=${_directionToken(direction)}',
];
return '${lines.join('\r\n')}\r\n';
}