示例#1
0
        private void ParseFormatParametersAttribute(SdpMediaDescription mediaDescription, string value)
        {
            var separatorIdx     = value.IndexOf(' ');
            var payloadType      = int.Parse(value.Substring(0, separatorIdx));
            var formatParameters = value.Substring(separatorIdx + 1);
            var mfd = mediaDescription.MediaFormatDescriptions[payloadType];

            mfd.FormatParameters = formatParameters;
        }
示例#2
0
        private void ParseRtpMapAttribute(SdpMediaDescription mediaDescription, string value)
        {
            var separatorIdx  = value.IndexOf(' ');
            var payloadType   = int.Parse(value.Substring(0, separatorIdx));
            var encoding      = value.Substring(separatorIdx + 1);
            var encodingParts = encoding.Split('/');
            var mfd           = mediaDescription.MediaFormatDescriptions[payloadType];

            mfd.EncodingName = encodingParts[0];
            if (int.TryParse(TryGet(encodingParts, 1), out var clockRate))
            {
                mfd.ClockRate = clockRate;
            }

            mfd.EncodingParameters = TryGet(encodingParts, 2);
        }
示例#3
0
        /// <summary>
        /// https://tools.ietf.org/html/rfc4566#section-5.14
        ///
        /// m=&lt;media&gt; &lt;port&gt; &lt;proto&gt; &lt;fmt&gt; ...
        ///
        /// A session description may contain a number of media descriptions.
        /// Each media description starts with an "m=" field and is terminated by
        /// either the next "m=" field or by the end of the session description.
        /// A media field has several sub-fields:
        /// </summary>
        /// <param name="mediaId">
        /// Used for identifying media streams within a
        /// session description.
        ///
        /// https://tools.ietf.org/html/rfc5888#section-4
        /// </param>
        /// <param name="media">
        /// &lt;media&gt; is the media type.  Currently defined media are "audio",
        /// "video", "text", "application", and "message", although this list
        /// may be extended in the future (see Section 8).
        /// </param>
        /// <param name="port">
        /// &lt;port&gt; is the transport port to which the media stream is sent.  The
        /// meaning of the transport port depends on the network being used as
        /// specified in the relevant "c=" field, and on the transport
        /// protocol defined in the &lt;proto&gt; sub-field of the media field.
        /// Other ports used by the media application (such as the RTP Control
        /// Protocol (RTCP) port [19]) MAY be derived algorithmically from the
        /// base media port or MAY be specified in a separate attribute (for
        /// example, "a=rtcp:" as defined in [22]).
        /// </param>
        /// <param name="protocol">
        /// &lt;proto&gt; is the transport protocol.  The meaning of the transport
        /// protocol is dependent on the address type field in the relevant
        /// "c=" field.  Thus a "c=" field of IP4 indicates that the transport
        /// protocol runs over IP4.
        /// </param>
        public SdpMediaDescriptionBuilder AddMediaDescription(string mediaId, string media, int port, string protocol = "UDP/TLS/RTP/SAVPF")
        {
            var sdpMediaDescription = new SdpMediaDescription
            {
                MediaId  = mediaId,
                Media    = media,
                Port     = port,
                Protocol = protocol
            };

            _sessionDescription.MediaDescriptions.Add(sdpMediaDescription);
            var mediaDescriptionBuilder = new SdpMediaDescriptionBuilder(sdpMediaDescription, this);

            _mediaLineBuilders.Add(mediaDescriptionBuilder);

            return(mediaDescriptionBuilder);
        }
示例#4
0
        private void ParseSsrcAttribute(SdpMediaDescription mediaDescription, string value)
        {
            var parts           = value.Split(' ');
            var mediaAttributes = mediaDescription.MediaSourceAttributes;

            mediaAttributes.Ssrc = uint.Parse(TryGet(parts, 0));
            var ssrcParam = TryGet(parts, 1);

            switch (ssrcParam)
            {
            case "cname":
                mediaAttributes.CName = ssrcParam;
                break;

            case "msid":
                mediaAttributes.MsId        = ssrcParam;
                mediaAttributes.MsIdAppData = TryGet(parts, 2);
                break;
            }
        }
示例#5
0
        private void ParseMediaDescription(SdpSessionDescription sessionDescription, string medialine, TextReader stringReader)
        {
            var mediaDescription = new SdpMediaDescription();

            var parts = medialine.Split(' ');

            mediaDescription.Media    = TryGet(parts, 0);
            mediaDescription.Port     = int.Parse(TryGet(parts, 1));
            mediaDescription.Protocol = TryGet(parts, 2);
            mediaDescription.MediaFormatDescriptions = parts.Skip(3)
                                                       .Select(int.Parse)
                                                       .ToDictionary(pt => pt, pt => new SdpMediaFormatDescription
            {
                PayloadType = pt
            });

            var line = stringReader.ReadLine();

            while (line != null)
            {
                ParseSdpLine(line, out var key, out var value);
                switch (key)
                {
                case "c":
                    mediaDescription.Connection = ParseConnectionLine(value);
                    break;

                case "a":
                    ParseMediaDescriptionAttribute(mediaDescription, value);
                    break;

                case "m":
                    ParseMediaDescription(sessionDescription, value, stringReader);
                    break;
                }

                line = stringReader.ReadLine();
            }

            sessionDescription.MediaDescriptions.Add(mediaDescription);
        }
示例#6
0
        private static void ParseRtcpFeedbackCapabilityAttribute(SdpMediaDescription mediaDescription, string value)
        {
            var separatorIdx   = value.IndexOf(' ');
            var payloadTypeStr = value.Substring(0, separatorIdx);
            var cap            = value.Substring(separatorIdx + 1);

            if (payloadTypeStr == "*")
            {
                foreach (var mfd in mediaDescription.MediaFormatDescriptions.Values)
                {
                    mfd.RtcpFeedbackCapability.Add(cap);
                }
            }
            else
            {
                var payloadType = int.Parse(payloadTypeStr);
                var mfd         = mediaDescription.MediaFormatDescriptions[payloadType];

                mfd.RtcpFeedbackCapability.Add(cap);
            }
        }
 public SdpMediaDescriptionBuilder(SdpMediaDescription sdpMediaDescription, SdpBuilder sdpBuilder)
 {
     _sdpMediaDescription = sdpMediaDescription;
     _sdpBuilder          = sdpBuilder;
 }
示例#8
0
        private void ParseMediaDescriptionAttribute(SdpMediaDescription mediaDescription, string attribute)
        {
            ParseAttributeKeyValue(attribute, out var key, out var value);

            switch (key)
            {
            case "control":
                mediaDescription.RtspControlUrl = new Uri(value, UriKind.RelativeOrAbsolute);
                break;

            case "framerate":
                mediaDescription.Framerate = decimal.Parse(value);
                break;

            case "sendrecv":
                mediaDescription.SendReceiveMode = SendReceiveMode.SendRecv;
                break;

            case "sendonly":
                mediaDescription.SendReceiveMode = SendReceiveMode.SendOnly;
                break;

            case "recvonly":
                mediaDescription.SendReceiveMode = SendReceiveMode.RecvOnly;
                break;

            case "inactive":
                mediaDescription.SendReceiveMode = SendReceiveMode.Inactive;
                break;

            case "mid":
                mediaDescription.MediaId = value;
                break;

            case "ice-ufrag":
                mediaDescription.IceAttributes.UsernameFragment = value;
                break;

            case "ice-pwd":
                mediaDescription.IceAttributes.Password = value;
                break;

            case "ice-options":
                mediaDescription.IceAttributes.Options = value;
                break;

            case "fingerprint":
                var fingerprintParts = value.Split(' ');
                mediaDescription.DtlsAttributes.HashFunc    = TryGet(fingerprintParts, 0);
                mediaDescription.DtlsAttributes.Fingerprint = TryGet(fingerprintParts, 1);
                break;

            case "setup":
                mediaDescription.DtlsAttributes.Setup = value;
                break;

            case "rtpmap":
                ParseRtpMapAttribute(mediaDescription, value);
                break;

            case "fmtp":
                ParseFormatParametersAttribute(mediaDescription, value);
                break;

            case "rtcp-fb":
                ParseRtcpFeedbackCapabilityAttribute(mediaDescription, value);
                break;

            case "ssrc":
                ParseSsrcAttribute(mediaDescription, value);
                break;

            case "candidate":
                var parts           = value.Split(' ');
                var sdpIceCandidate = new SdpIceCandidate();

                sdpIceCandidate.Foundation        = long.Parse(TryGet(parts, 0));
                sdpIceCandidate.ComponentId       = byte.Parse(TryGet(parts, 1));
                sdpIceCandidate.Transport         = TryGet(parts, 2);
                sdpIceCandidate.Priority          = uint.Parse(TryGet(parts, 3));
                sdpIceCandidate.ConnectionAddress = TryGet(parts, 4);
                sdpIceCandidate.Port          = ushort.Parse(TryGet(parts, 5));
                sdpIceCandidate.CandidateType = TryGet(parts, 7);

                mediaDescription.IceCandidates.Add(sdpIceCandidate);
                break;

            case "end-of-candidates":
                break;
            }
        }