//readonly SctpParameters _sctpParameters;
        //readonly PlainRtpParameters _plainRtpParameters;
        //readonly Mid _mid;
        //readonly MediaKind _kind;
        //RtpParameters

        public OfferMediaSection(
            IceParameters iceParameters,
            IceCandidate[] iceCandidates,
            DtlsParameters dtlsParameters,
            SctpParameters sctpParameters,
            PlainRtpParameters plainRtpParameters,
            bool planB,
            Mid mid,
            MediaKind kind,
            RtpParameters offerRtpParameters,
            string streamId,
            string trackId,
            bool oldDataChannelSpec) : base(iceParameters, iceCandidates, dtlsParameters, planB)
        {
            _mediaObject.MediaDescription.Attributes.Mid = mid;
            _mediaObject.MediaDescription.Media          = kind.ToSdp();

            if (plainRtpParameters is null)
            {
                _mediaObject.MediaDescription.ConnectionData = new ConnectionData
                {
                    NetType           = NetType.Internet,
                    AddrType          = AddrType.Ip4,
                    ConnectionAddress = "127.0.0.1"
                };
                if (sctpParameters is null)
                {
                    _mediaObject.MediaDescription.Proto = "UDP/TLS/RTP/SAVPF";
                }
                else
                {
                    _mediaObject.MediaDescription.Proto = "UDP/DTLS/SCTP";
                }
                _mediaObject.MediaDescription.Port = 7;
            }
            else
            {
                _mediaObject.MediaDescription.ConnectionData = new ConnectionData
                {
                    NetType           = NetType.Internet,
                    AddrType          = plainRtpParameters.IpVersion,
                    ConnectionAddress = plainRtpParameters.Ip
                };
                _mediaObject.MediaDescription.Proto = "RTP/AVP";
                _mediaObject.MediaDescription.Port  = plainRtpParameters.Port;
            }

            switch (kind)
            {
            case MediaKind.Audio:
            case MediaKind.Video:
            {
                _mediaObject.MediaDescription.Attributes.SendOnly = true;
                _mediaObject.MediaDescription.Attributes.Rtpmaps  = new List <Rtpmap>();
                _mediaObject.MediaDescription.Attributes.RtcpFbs  = new List <RtcpFb>();
                _mediaObject.MediaDescription.Attributes.Fmtps    = new List <Fmtp>();

                if (!_planB)
                {
                    _mediaObject.MediaDescription.Attributes.Msid = new()
                    {
                        Id      = streamId ?? "-",
                        AppData = trackId
                    }
                }
                ;

                foreach (var codec in offerRtpParameters.Codecs)
                {
                    Rtpmap rtpmap = new()
                    {
                        PayloadType  = codec.PayloadType,
                        EncodingName = GetCodecName(codec),
                        ClockRate    = codec.ClockRate,
                        Channels     = codec.Channels > 1 ? codec.Channels : null
                    };
                    _mediaObject.MediaDescription.Attributes.Rtpmaps.Add(rtpmap);

                    Fmtp fmtp = codec.Parameters.ToFmtp(codec.PayloadType);
                    if (!string.IsNullOrEmpty(fmtp.Value))
                    {
                        _mediaObject.MediaDescription.Attributes.Fmtps.Add(fmtp);
                    }

                    foreach (var fb in codec.RtcpFeedback)
                    {
                        RtcpFb rtcpFb = new()
                        {
                            PayloadType = codec.PayloadType,
                            Type        = fb.Type,
                            SubType     = fb.Parameter
                        };
                        _mediaObject.MediaDescription.Attributes.RtcpFbs.Add(rtcpFb);
                    }
                }

                _mediaObject.MediaDescription.Fmts ??= new List <string>();
                ((List <string>)_mediaObject.MediaDescription.Fmts).AddRange(offerRtpParameters.Codecs
                                                                             .Select(codec => codec.PayloadType.ToString()));


                _mediaObject.MediaDescription.Attributes.Extmaps = new List <Extmap>();
                foreach (var headerExtension in offerRtpParameters.HeaderExtensions)
                {
                    Extmap ext = new()
                    {
                        Uri   = new Uri(headerExtension.Uri),
                        Value = headerExtension.Id
                    };
                    _mediaObject.MediaDescription.Attributes.Extmaps.Add(ext);
                }

                _mediaObject.MediaDescription.Attributes.RtcpMux   = true;
                _mediaObject.MediaDescription.Attributes.RtcpRsize = true;

                var encoding = offerRtpParameters.Encodings[0];
                var ssrc     = encoding.Ssrc;
                var rtxSsrc  = (encoding.Rtx is not null && encoding.Rtx.Ssrc.HasValue) ?
                               encoding.Rtx.Ssrc : null;

                _mediaObject.MediaDescription.Attributes.Ssrcs      = new List <Ssrc>();
                _mediaObject.MediaDescription.Attributes.SsrcGroups = new List <SsrcGroup>();
                if (offerRtpParameters.Rtcp.Cname is not null)
                {
                    _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                        {
                            Id        = (uint)ssrc,
                            Attribute = "cname",
                            Value     = offerRtpParameters.Rtcp.Cname
                        });
                }

                if (_planB)
                {
                    _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                        {
                            Id        = (uint)ssrc,
                            Attribute = "msid",
                            Value     = $"{streamId ?? "-"} {trackId}"
                        });
                }

                if (rtxSsrc.HasValue)
                {
                    if (offerRtpParameters.Rtcp.Cname is not null)
                    {
                        _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                            {
                                Id        = (uint)rtxSsrc,
                                Attribute = "cname",
                                Value     = offerRtpParameters.Rtcp.Cname
                            });
                    }

                    if (_planB)
                    {
                        _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                            {
                                Id        = (uint)rtxSsrc,
                                Attribute = "msid",
                                Value     = $"{streamId ?? "-"} {trackId}"
                            });
                    }

                    // Associate original and retransmission SSRCs.
                    _mediaObject.MediaDescription.Attributes.SsrcGroups.Add(new SsrcGroup
                        {
                            Semantics = "FID",
                            SsrcIds   = new string[] { $"{ssrc} {rtxSsrc}" }
                        });
                }

                break;
            }

            case MediaKind.Application:
            {
                // New spec.
                if (!oldDataChannelSpec)
                {
                    _mediaObject.MediaDescription.Fmts = new List <string> {
                        "webrtc-datachannel"
                    };
                    _mediaObject.MediaDescription.Attributes.SctpPort = new SctpPort
                    {
                        Port = sctpParameters.Port
                    };
                    _mediaObject.MediaDescription.Attributes.MaxMessageSize = new MaxMessageSize
                    {
                        Size = sctpParameters.MaxMessageSize
                    };
                }
                // Old spec.
                else
                {
                    _mediaObject.MediaDescription.Fmts = new List <string> {
                        sctpParameters.Port.ToString()
                    };
                    _mediaObject.SctpMap = new()
                    {
                        App            = "webrtc-datachannel",
                        SctpMapNumber  = sctpParameters.Port,
                        MaxMessageSize = sctpParameters.MaxMessageSize
                    };
                }

                break;
            }
            }
        }

        void PlanBReceive(RtpParameters offerRtpParameters, string streamId, IMediaStream trackId)
        {
            var encoding = offerRtpParameters.Encodings[0];
            var ssrc     = encoding.Ssrc;
            var rtxSsrc  = (encoding.Rtx is not null && encoding.Rtx.Ssrc.HasValue) ?
                           encoding.Rtx.Ssrc : null;
            var payloads = _mediaObject.MediaDescription.Fmts.ToArray();


            foreach (var codec in offerRtpParameters.Codecs)
            {
                if (payloads.Any(payload => payload.Contains(codec.PayloadType.ToString())))
                {
                    continue;
                }

                Rtpmap rtpmap = new()
                {
                    PayloadType  = codec.PayloadType,
                    EncodingName = GetCodecName(codec),
                    ClockRate    = codec.ClockRate,
                    Channels     = codec.Channels > 1 ? codec.Channels : null
                };
                _mediaObject.MediaDescription.Attributes.Rtpmaps.Add(rtpmap);

                Fmtp fmtp = codec.Parameters.ToFmtp(codec.PayloadType);
                if (!string.IsNullOrEmpty(fmtp.Value))
                {
                    _mediaObject.MediaDescription.Attributes.Fmtps.Add(fmtp);
                }

                foreach (var fb in codec.RtcpFeedback)
                {
                    RtcpFb rtcpFb = new()
                    {
                        PayloadType = codec.PayloadType,
                        Type        = fb.Type,
                        SubType     = fb.Parameter
                    };
                    _mediaObject.MediaDescription.Attributes.RtcpFbs.Add(rtcpFb);
                }
            }

            ((List <string>)_mediaObject.MediaDescription.Fmts).AddRange(offerRtpParameters.Codecs
                                                                         .Select(codec => codec.PayloadType.ToString()));


            if (offerRtpParameters.Rtcp.Cname is not null)
            {
                _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                {
                    Id        = (uint)ssrc,
                    Attribute = "cname",
                    Value     = offerRtpParameters.Rtcp.Cname
                });
            }

            _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
            {
                Id        = (uint)ssrc,
                Attribute = "msid",
                Value     = $"{streamId ?? "-"} {trackId}"
            });

            if (rtxSsrc.HasValue)
            {
                if (offerRtpParameters.Rtcp.Cname is not null)
                {
                    _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                    {
                        Id        = (uint)rtxSsrc,
                        Attribute = "cname",
                        Value     = offerRtpParameters.Rtcp.Cname
                    });
                }

                _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                {
                    Id        = (uint)rtxSsrc,
                    Attribute = "msid",
                    Value     = $"{streamId ?? "-"} {trackId}"
                });

                // Associate original and retransmission SSRCs.
                _mediaObject.MediaDescription.Attributes.SsrcGroups.Add(new SsrcGroup
                {
                    Semantics = "FID",
                    SsrcIds   = new string[] { $"{ssrc} {rtxSsrc}" }
                });
            }
        }

        public void PlanBReceive(RtpParameters offerRtpParameters, string streamId, string trackId)
        {
            var encoding = offerRtpParameters.Encodings[0];
            var ssrc     = encoding.Ssrc;
            var rtxSsrc  = (encoding.Rtx is not null && encoding.Rtx.Ssrc.HasValue)
                ? encoding.Rtx.Ssrc
                : null;
            var payloads = _mediaObject.MediaDescription.Fmts.ToArray();

            foreach (var codec in offerRtpParameters.Codecs)
            {
                if (payloads.Contains(codec.PayloadType.ToString()))
                {
                    continue;
                }

                Rtpmap rtpmap = new()
                {
                    PayloadType  = codec.PayloadType,
                    EncodingName = GetCodecName(codec),
                    ClockRate    = codec.ClockRate,
                    Channels     = codec.Channels > 1 ? codec.Channels : null
                };
                _mediaObject.MediaDescription.Attributes.Rtpmaps.Add(rtpmap);

                Fmtp fmtp = codec.Parameters.ToFmtp(codec.PayloadType);

                if (!string.IsNullOrEmpty(fmtp.Value))
                {
                    _mediaObject.MediaDescription.Attributes.Fmtps.Add(fmtp);
                }

                foreach (var fb in codec.RtcpFeedback)
                {
                    _mediaObject.MediaDescription.Attributes.RtcpFbs.Add(new RtcpFb
                    {
                        PayloadType = codec.PayloadType,
                        Type        = fb.Type,
                        SubType     = fb.Parameter
                    });
                }
            }

            ((List <string>)_mediaObject.MediaDescription.Fmts).AddRange(offerRtpParameters.Codecs
                                                                         .Where(codec => !_mediaObject.MediaDescription.Fmts.Contains(codec.PayloadType.ToString()))
                                                                         .Select(codec => codec.PayloadType.ToString())
                                                                         .ToArray());

            if (offerRtpParameters.Rtcp.Cname is not null)
            {
                _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                {
                    Id        = (uint)ssrc,
                    Attribute = "cname",
                    Value     = offerRtpParameters.Rtcp.Cname
                });
            }

            _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
            {
                Id        = (uint)ssrc,
                Attribute = "msid",
                Value     = $"{ streamId ?? "-"} { trackId}"
            });

            if (rtxSsrc is not null)
            {
                if (offerRtpParameters.Rtcp.Cname is not null)
                {
                    _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                    {
                        Id        = (uint)rtxSsrc,
                        Attribute = "cname",
                        Value     = offerRtpParameters.Rtcp.Cname
                    });
                }

                _mediaObject.MediaDescription.Attributes.Ssrcs.Add(new Ssrc
                {
                    Id        = (uint)rtxSsrc,
                    Attribute = "msid",
                    Value     = $"{ streamId ?? "-"} {trackId}"
                });

                // Associate original and retransmission SSRCs.
                _mediaObject.MediaDescription.Attributes.SsrcGroups.Add(new SsrcGroup
                {
                    Semantics = "FID",
                    SsrcIds   = new string[] { $"{ ssrc }${rtxSsrc}" }
                });
            }
        }

        void PlanBStopReceiving(RtpParameters offerRtpParameters)
        {
            var encoding = offerRtpParameters.Encodings[0];
            var ssrc     = encoding.Ssrc;
            var rtxSsrc  = (encoding.Rtx is not null && encoding.Rtx.Ssrc.HasValue) ?
                           encoding.Rtx.Ssrc : null;

            ((List <Ssrc>)_mediaObject.MediaDescription.Attributes.Ssrcs).RemoveAll(s => s.Id != ssrc && s.Id != rtxSsrc);

            if (rtxSsrc is not null)
            {
                ((List <SsrcGroup>)_mediaObject.MediaDescription.Attributes.SsrcGroups).RemoveAll(g => g.SsrcIds.Any(id => id != $"{ssrc} {rtxSsrc}"));
            }
        }

        public override void SetDtlsRole(DtlsRole?dtlsRole)