buildG711Answer function

String buildG711Answer({
  1. required String username,
  2. required String localHost,
  3. required int localPort,
  4. required SdpAudio remoteOffer,
  5. int? rtcpPort,
  6. SdpDirection direction = SdpDirection.sendrecv,
  7. int? sessionId,
  8. int? sessionVersion,
})

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';
}