/// <summary>
        /// Generates the SDP for an offer that can be made to a remote peer.
        /// </summary>
        public override async Task <SDP> createOffer(RTCOfferOptions options)
        {
            try
            {
                var offerSdp = await createBaseSdp().ConfigureAwait(false);

                if (offerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.audio))
                {
                    var audioAnnouncement = offerSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.audio).Single();
                    audioAnnouncement.AddExtra(SETUP_OFFER_ATTRIBUTE);
                }

                if (offerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.video))
                {
                    var videoAnnouncement = offerSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.video).Single();
                    videoAnnouncement.AddExtra(SETUP_OFFER_ATTRIBUTE);
                }

                return(offerSdp);
            }
            catch (Exception excp)
            {
                logger.LogError("Exception createOffer. " + excp);
                throw;
            }
        }
        /// <summary>
        /// Generates the SDP for an offer that can be made to a remote peer.
        /// </summary>
        /// <remarks>
        /// As specified in https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-createoffer.
        /// </remarks>
        /// <param name="options">Optional. If supplied the options will be sued to apply additional
        /// controls over the generated offer SDP.</param>
        public RTCSessionDescriptionInit createOffer(RTCOfferOptions options)
        {
            try
            {
                var audioCapabilities = AudioLocalTrack?.Capabilities;
                var videoCapabilities = VideoLocalTrack?.Capabilities;

                List <MediaStreamTrack> localTracks = GetLocalTracks();
                var offerSdp = createBaseSdp(localTracks, audioCapabilities, videoCapabilities);

                if (offerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.audio))
                {
                    var audioAnnouncement = offerSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.audio).Single();
                    audioAnnouncement.AddExtra($"{ICE_SETUP_ATTRIBUTE}{IceRole}");
                }

                if (offerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.video))
                {
                    var videoAnnouncement = offerSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.video).Single();
                    videoAnnouncement.AddExtra($"{ICE_SETUP_ATTRIBUTE}{IceRole}");
                }

                RTCSessionDescriptionInit initDescription = new RTCSessionDescriptionInit
                {
                    type = RTCSdpType.offer,
                    sdp  = offerSdp.ToString()
                };

                return(initDescription);
            }
            catch (Exception excp)
            {
                logger.LogError("Exception createOffer. " + excp);
                throw;
            }
        }