Ejemplo n.º 1
0
    public void ParseMediaDescriptionUnitTest()
    {
        string testVector = @" m=audio 49230 RTP/AVP 96 97 98
            a=rtpmap:96 L8/8000
            a=rtpmap:97 L16/8000
            a=rtpmap:98 L16/11025/2";

        using (var md = new Media.Sdp.MediaDescription(testVector))
        {
            System.Diagnostics.Debug.Assert(md.Lines.Count() == 4, "MediaDescription must have 4 lines");

            //CLR not assert correctly with == ....
            //md.MediaDescriptionLine.ToString() == "m=audio 49230 RTP/AVP 96 97 98"

            System.Diagnostics.Debug.Assert(md.PayloadTypes.Count() == 3, "Could not read the Payload List");

            System.Diagnostics.Debug.Assert(md.PayloadTypes.First() == 96, "Could not read the Payload List");

            System.Diagnostics.Debug.Assert(md.PayloadTypes.ToArray()[1] == 97, "Could not read the Payload List");

            System.Diagnostics.Debug.Assert(md.PayloadTypes.Last() == 98, "Could not read the Payload List");

            System.Diagnostics.Debug.Assert(string.Compare(md.MediaDescriptionLine.ToString(), "m=audio 49230 RTP/AVP 96 97 98\r\n") == 0, "Did not handle Payload List Correct");
        }
    }
Ejemplo n.º 2
0
    public void CreateMediaDesciptionTest()
    {
        //RtpClient has the following property
        //Media.Rtp.RtpClient.AvpProfileIdentifier
        //I don't think it should be specified in the SDP Classes but I can figure out something else if desired.

        string profile = "RTP/AVP";

        Media.Sdp.MediaType mediaType = Media.Sdp.MediaType.audio;

        int mediaPort = 15000;

        //Iterate all possible byte values (should do a seperate test for the list of values?)
        for (int mediaFormat = 0; mediaFormat <= 999; ++mediaFormat)
        {
            //Create a MediaDescription
            using (var mediaDescription = new Media.Sdp.MediaDescription(mediaType, mediaPort, profile, mediaFormat))
            {
                System.Diagnostics.Debug.Assert(mediaDescription.MediaProtocol == profile, "Did not find MediaProtocol '" + profile + "'");

                System.Diagnostics.Debug.Assert(mediaDescription.PayloadTypes.Count() == 1, "Found more then 1 payload type in the PayloadTypes List");

                System.Diagnostics.Debug.Assert(mediaDescription.PayloadTypes.First() == mediaFormat, "Did not find correct MediaFormat");

                System.Diagnostics.Debug.Assert(mediaDescription.ToString() == string.Format("m={0} {1} RTP/AVP {2}\r\n", mediaType, mediaPort, mediaFormat), "Did not output correct result");
            }
        }
    }
Ejemplo n.º 3
0
        //Naming is weird, this returns the logical 0 based index of the given description within the sessionDescription's property of the same type.

        //E.g. This index can be used in GetMediaDescription(index)
        public static int GetIndexFor(this SessionDescription sdp, MediaDescription md)
        {
            if (sdp == null || md == null)
            {
                return(-1);
            }

            return(sdp.m_MediaDescriptions.IndexOf(md));
        }
Ejemplo n.º 4
0
        public MediaDescription(MediaDescription other, bool shouldDispose = true) : base(shouldDispose)
        {
            if (Common.IDisposedExtensions.IsNullOrDisposed(other))
            {
                throw new ArgumentNullException(nameof(other));
            }
            MediaDescriptionLine = other.MediaDescriptionLine;

            foreach (Sdp.SessionDescriptionLine line in other.Lines)
            {
                Add(line);
            }
        }
Ejemplo n.º 5
0
        //public SessionDescriptionLine GetLine(int index)
        //{
        //    //Some lines are backed by properties
        //}

        public void Add(MediaDescription mediaDescription, bool updateVersion = true)
        {
            if (UnderModification || mediaDescription == null)
            {
                return;
            }

            var token = BeginUpdate();

            m_MediaDescriptions.Add(mediaDescription);

            EndUpdate(token, updateVersion);
        }
Ejemplo n.º 6
0
        public bool Remove(MediaDescription mediaDescription, bool updateVersion = true)
        {
            if (UnderModification || mediaDescription == null)
            {
                return(false);
            }

            var token = BeginUpdate();

            bool result = m_MediaDescriptions.Remove(mediaDescription);

            EndUpdate(token, updateVersion);

            return(result);
        }
Ejemplo n.º 7
0
        public bool Equals(MediaDescription other)
        {
            return(Media.Common.Extensions.EnumerableExtensions.SequenceEquals(this, other));

            //using (var one = other.GetEnumerator())
            //{
            //    using (var two = GetEnumerator())
            //    {
            //        while (one.MoveNext() && two.MoveNext())
            //        {
            //            if (one.Current.Equals(two.Current).Equals(false)) return false;
            //        }

            //        return true;
            //    }
            //}
        }
Ejemplo n.º 8
0
        public static TimeDescription GetTimeDescription(this MediaDescription mediaDescription, SessionDescription sessionDescription)
        {
            if (mediaDescription == null || sessionDescription == null)
            {
                return(null);
            }

            //Get index of mediaDescription

            //Needs a better way to get the index of the media description
            int index = sessionDescription.GetIndexFor(mediaDescription);  //Array.IndexOf(sessionDescription.MediaDescriptions.ToArray(), mediaDescription);

            if (index == -1)
            {
                return(null);
            }

            return(sessionDescription.GetTimeDescription(index));
        }
Ejemplo n.º 9
0
        public static TimeDescription GetTimeDescription(this MediaDescription mediaDescription, SessionDescription sessionDescription)
        {
            if (Common.IDisposedExtensions.IsNullOrDisposed(mediaDescription) || Common.IDisposedExtensions.IsNullOrDisposed(sessionDescription))
            {
                return(null);
            }

            //Get index of mediaDescription

            //Needs a better way to get the index of the media description
            int index = sessionDescription.GetIndexFor(mediaDescription);  //Array.IndexOf(sessionDescription.MediaDescriptions.ToArray(), mediaDescription);

            if (index == -1)
            {
                return(null);
            }

            return(sessionDescription.GetTimeDescription(index));
        }
Ejemplo n.º 10
0
        //Should have a date when or should return the date playable, which would then be used by another method to compare against a time.
        public static bool IsPlayable(this MediaDescription mediaDescription, SessionDescription sessionDescription) //, DateTime? check = null) ,TimeSpan within = TimeSpan.Zero
        {
            if (mediaDescription == null || sessionDescription == null)
            {
                return(false);
            }

            //Get index of mediaDesription

            //Check TimeDescription @ index.

            TimeDescription td = GetTimeDescription(mediaDescription, sessionDescription);

            if (td == null)
            {
                return(true);
            }

            //Unbound start and end ?
            if (td.IsPermanent)
            {
                return(true);
            }

            //Notes multiple calls to UtcNow... (avoid with a within parameter)?
            try
            {
                //Ensure not a bounded end and that the end time is less than now
                if (td.StopTime != 0
                    &&
                    td.NtpStopDateTime >= DateTime.UtcNow)
                {
                    return(false);
                }

                //Ensure start time is not bounded and that the start time is greater than now
                if (td.StartTime != 0
                    &&
                    td.NtpStartDateTime > DateTime.UtcNow)
                {
                    return(false);
                }

                //Check repeat times.

                //td.RepeatTimes;
            }
            catch
            {
                //Out of range values for conversion, assume true if end is unbounded
                if (td.StopTime != 0)
                {
                    return(false);
                }
            }
            finally
            {
                td = null;
            }

            return(true);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Parses the <see cref="MediaDescription.ControlLine"/> and if present
        /// </summary>
        /// <param name="mediaDescription"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Uri GetAbsoluteControlUri(this MediaDescription mediaDescription, Uri source, SessionDescription sessionDescription = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (mediaDescription == null)
            {
                return(source);
            }

            if (false == source.IsAbsoluteUri)
            {
                throw new InvalidOperationException("source.IsAbsoluteUri must be true.");
            }

            SessionDescriptionLine controlLine = mediaDescription.ControlLine;

            //If there is a control line in the SDP it contains the URI used to setup and control the media
            if (controlLine != null)
            {
                //Todo, make typed line for controlLine
                // GC: Rewrote this somewhat because it was destroying valid absolute URL provided by AXIS media server in the MediaDescription Control field.
                //     This make break media servers which use a relative path. TODO: Test with other servers.
                string controlPart = "";
                if (controlLine.Parts.Count() > 2)
                {
                    foreach (string part in controlLine.Parts)
                    {
                        if (part == "control")
                        {
                        }
                        else if (part == "rtsp")
                        {
                            controlPart += part + ":";
                        }
                        else
                        {
                            controlPart += part;
                        }
                    }
                }
                else
                {
                    controlPart = controlLine.Parts.Last();
                }

                //If there is a controlPart in the controlLine
                if (false == string.IsNullOrWhiteSpace(controlPart))
                {
                    //Prepare the part
                    // GC: Commented this out because it was destroying valid absolute URL provided by AXIS media server in the MediaDescription Control field.
                    //     This make break media servers which use a relative path. TODO: Test with other servers.
                    //controlPart = controlPart.Split(Media.Sdp.SessionDescription.ColonSplit, 2, StringSplitOptions.RemoveEmptyEntries).Last();

                    //Create a uri
                    Uri controlUri = new Uri(controlPart, UriKind.RelativeOrAbsolute);

                    //Determine if its a Absolute Uri
                    if (controlUri.IsAbsoluteUri)
                    {
                        return(controlUri);
                    }

                    //Return a new uri using the original string and the controlUri relative path.
                    //Hopefully the direction of the braces matched..

                    //string.Join(source.OriginalString, controlUri.OriginalString);

                    return(new Uri(source.OriginalString.EndsWith(SessionDescription.ForwardSlashString) ? source.OriginalString + controlUri.OriginalString : string.Join(SessionDescription.ForwardSlashString, source.OriginalString, controlUri.OriginalString)));

                    //Todo, ensure that any parameters have also been restored...

                    #region Explination

                    //I wonder if Mr./(Dr) Fielding is happy...
                    //Let source =
                    //rtsp://alt1.v7.cache3.c.youtube.com/CigLENy73wIaHwmddh2T-s8niRMYDSANFEgGUgx1c2VyX3VwbG9hZHMM/0/0/0/1/video.3gp/trackID=0
                    //Call
                    //return new Uri(source, controlUri);
                    //Result =
                    //rtsp://alt1.v7.cache3.c.youtube.com/CigLENy73wIaHwmddh2T-s8niRMYDSANFEgGUgx1c2VyX3VwbG9hZHMM/0/0/0/1/trackID=0


                    //Useless when the source doesn't end with '/', e.g. same problem with Uri constructor.

                    //System.UriBuilder builder = new UriBuilder(source);
                    //builder.Path += controlUri.ToString();

                    //"rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov/trackID=1"

                    #endregion
                }
            }

            //Try to take the session level control uri
            Uri sessionControlUri;

            //If there was a session description given and it supports aggregate media control then return that uri
            if (sessionDescription != null && sessionDescription.SupportsAggregateMediaControl(out sessionControlUri, source))
            {
                return(sessionControlUri);
            }

            //There is no control line, just return the source.
            return(source);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Parses the <see cref="MediaDescription.ControlLine"/> and if present
        /// </summary>
        /// <param name="mediaDescription"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Uri GetAbsoluteControlUri(this MediaDescription mediaDescription, Uri source, SessionDescription sessionDescription = null)
        {
            if (object.ReferenceEquals(source, null))
            {
                throw new ArgumentNullException("source");
            }

            if (Common.IDisposedExtensions.IsNullOrDisposed(mediaDescription))
            {
                return(source);
            }

            if (source.IsAbsoluteUri.Equals(false))
            {
                throw new InvalidOperationException("source.IsAbsoluteUri must be true.");
            }

            SessionDescriptionLine controlLine = mediaDescription.ControlLine;

            //If there is a control line in the SDP it contains the URI used to setup and control the media
            if (object.ReferenceEquals(controlLine, null).Equals(false))
            {
                //Todo, make typed line for controlLine
                string controlPart = controlLine.Parts.Last(); //controlLine.Parts.Where(p => p.StartsWith(AttributeFields.Control)).FirstOrDefault();

                //If there is a controlPart in the controlLine
                if (string.IsNullOrWhiteSpace(controlPart).Equals(false))
                {
                    //Prepare the part
                    controlPart = controlPart.Split(Media.Sdp.SessionDescription.ColonSplit, 2, StringSplitOptions.RemoveEmptyEntries).Last();

                    //Create a uri
                    Uri controlUri = new Uri(controlPart, UriKind.RelativeOrAbsolute);

                    //Determine if its a Absolute Uri
                    if (controlUri.IsAbsoluteUri)
                    {
                        return(controlUri);
                    }

                    //Return a new uri using the original string and the controlUri relative path.
                    //Hopefully the direction of the braces matched..

                    //string.Join(source.OriginalString, controlUri.OriginalString);

                    return(new Uri(source.OriginalString.EndsWith(SessionDescription.ForwardSlashString) ? source.OriginalString + controlUri.OriginalString : string.Join(SessionDescription.ForwardSlashString, source.OriginalString, controlUri.OriginalString)));

                    //Todo, ensure that any parameters have also been restored...

                    #region Explination

                    //I wonder if Mr./(Dr) Fielding is happy...
                    //Let source =
                    //rtsp://alt1.v7.cache3.c.youtube.com/CigLENy73wIaHwmddh2T-s8niRMYDSANFEgGUgx1c2VyX3VwbG9hZHMM/0/0/0/1/video.3gp/trackID=0
                    //Call
                    //return new Uri(source, controlUri);
                    //Result =
                    //rtsp://alt1.v7.cache3.c.youtube.com/CigLENy73wIaHwmddh2T-s8niRMYDSANFEgGUgx1c2VyX3VwbG9hZHMM/0/0/0/1/trackID=0


                    //Useless when the source doesn't end with '/', e.g. same problem with Uri constructor.

                    //System.UriBuilder builder = new UriBuilder(source);
                    //builder.Path += controlUri.ToString();

                    //"rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov/trackID=1"

                    #endregion
                }
            }

            //Try to take the session level control uri
            Uri sessionControlUri;

            //If there was a session description given and it supports aggregate media control then return that uri
            if (Common.IDisposedExtensions.IsNullOrDisposed(sessionDescription).Equals(false) && sessionDescription.SupportsAggregateMediaControl(out sessionControlUri, source))
            {
                return(sessionControlUri);
            }

            //There is no control line, just return the source.
            return(source);
        }
Ejemplo n.º 13
0
        //Should have a date when or should return the date playable, which would then be used by another method to compare against a time.
        public static bool IsPlayable(this MediaDescription mediaDescription, SessionDescription sessionDescription) //, DateTime? check = null) ,TimeSpan within = TimeSpan.Zero
        {
            if (Common.IDisposedExtensions.IsNullOrDisposed(mediaDescription) || Common.IDisposedExtensions.IsNullOrDisposed(sessionDescription))
            {
                return(false);
            }

            //Get index of mediaDesription

            //Check TimeDescription @ index.

            TimeDescription td = GetTimeDescription(mediaDescription, sessionDescription);

            //Assume true
            if (Common.IDisposedExtensions.IsNullOrDisposed(td))
            {
                return(true);
            }

            //Unbound start and end ?
            if (td.IsPermanent)
            {
                return(true);
            }

            //Notes multiple calls to UtcNow... (avoid with a within parameter)?
            try
            {
                //Ensure not a bounded end and that the end time is less than now
                if (false.Equals(td.StopTime.Equals(0))
                    &&
                    td.NtpStopDateTime >= DateTime.UtcNow)
                {
                    return(false);
                }

                //Ensure start time is not bounded and that the start time is greater than now
                if (false.Equals(td.StartTime.Equals(0))
                    &&
                    td.NtpStartDateTime > DateTime.UtcNow)
                {
                    return(false);
                }

                //Check repeat times.

                //td.RepeatTimes;
            }
            //Todo, should not access property again during exception especially when out of range is potential.
            catch
            {
                //Out of range values for conversion, assume true if end is unbounded
                if (false.Equals(td.StopTime.Equals(0)))
                {
                    return(false);
                }
            }
            finally
            {
                td = null;
            }

            return(true);
        }