ngraziano / SharpRTSP

A RTSP handling library
Other
557 stars 182 forks source link

SdpFile.ReadLoose Implementation #121

Closed pedrosbanioles closed 2 months ago

pedrosbanioles commented 6 months ago

We have a Hikvision DVR that is returning the following connection parameter in the Describe message:

IN c=IN IP4 0.0.0.0

This is causing a FormatException to be thrown. I would like the ability to override the default implementation of the Parse method, in order to add support for the DVR but it looks like I cannot.

I also don't have the ability to change this response from the Hikvision DVR. Would it be possible to add a static getter / setter for the function?

Perhaps something like this:


    public abstract class Connection
    {
        private static Connection ParseConnection(string value)
        {
            string[] strArray = value != null ? value.Split(' ') : throw new ArgumentNullException(nameof (value));
            if (strArray.Length != 3)
                throw new FormatException("Value do not contain 3 parts as needed.");
            if (!string.Equals(strArray[0], "IN", StringComparison.Ordinal))
                throw new NotSupportedException(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "Net type {0} not suported", (object) strArray[0]));
            switch (strArray[1])
            {
                case "IP4":
                    return (Connection) ConnectionIP4.Parse(strArray[2]);
                case "IP6":
                    return (Connection) ConnectionIP6.Parse(strArray[2]);
                default:
                    throw new NotSupportedException(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "Address type {0} not suported", (object) strArray[1]));
            }
        }

        public static Func<string, Connection> ConnectionParser { get; set; } = ParseConnection;

        public string Host { get; set; } = string.Empty;

        public int NumberOfAddress { get; set; } = 1;

        public static Connection Parse(string value) => ConnectionParser?.Invoke(value) ?? ParseConnection(value);
    }

That way we could change the way the connection is parsed. This would probably be the easiest way to facilitate the customization without a massive rework to support an IConnectionProvider interface and injection process

ngraziano commented 6 months ago

Hi, I have try to make SdpFile.ReadLoose accept more error in the sdp file.

Can you send me the SDP that generate the error so I can test ?

I prefer not to add the static method for parsing now, maybe I will refactor with some injection process for all the subpart parsing. I will think about something.

pedrosbanioles commented 6 months ago

Sure, here is the sample i have for testing based on a Hik DVR we are using:

    public static class HikvisionSDPSample
    {
        private const string _version = "v=0";
        private const string _origin = "o=- 1109162014219182 0 IN IP4 0.0.0.0";
        private const string _session = "s=HIK Media Server V3.0.2";
        private const string _sessionInformation = "i=HIK Media Server Session Description : standard";
        private const string _email = "e=NONE";
        private const string _connection = "c=IN c=IN IP4 0.0.0.0";
        private const string _timing = "t=0 0";
        private const string _attribute1 = "a=control:*";
        private const string _attribute2 = "a=range:npt=now-";
        private const string _mediaAttr1 = "m=video 0 RTP/AVP 96";
        private const string _attribute3 = "a=rtpmap:96 H264/90000";
        private const string _attribute4 = "a=fmtp:96 profile-level-id=4D0014;packetization-mode=0;sprop-parameter-sets=Z2QAFK2EAQwgCGEAQwgCGEAQwgCEK3Cw/QgAAOpgAAr8hCA=,aO48sA==";
        private const string _attribute5 = "a=control:trackID=video";
        private const string _attribute6 = "a=Media_header:MEDIAINFO=494D4B48010100000400000100000000000000000000000000000000000000000000000000000000;";
        private const string _attribute7 = "a=appversion:1.0";

        public static string Default = $"{_version}\r\n{_origin}\r\n{_session}\r\n{_sessionInformation}\r\n{_email}\r\n{_connection}\r\n{_timing}\r\n{_attribute1}\r\n{_attribute2}\r\n{_mediaAttr1}\r\n{_attribute3}\r\n{_attribute4}\r\n{_attribute5}\r\n{_attribute6}\r\n{_attribute7}\r\n";

    }

Or here is format for your test#.sdp files

v=0
o=- 1109162014219182 0 IN IP4 0.0.0.0
s=HIK Media Server V3.0.2
i=HIK Media Server Session Description : standard
e=NONE
c=IN c=IN IP4 0.0.0.0
t=0 0
a=control:*
a=range:npt=now-
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=4D0014;packetization-mode=0;sprop-parameter-sets=Z2QAFK2EAQwgCGEAQwgCGEAQwgCEK3Cw/QgAAOpgAAr8hCA=,aO48sA==
a=control:trackID=video
a=Media_header:MEDIAINFO=494D4B48010100000400000100000000000000000000000000000000000000000000000000000000;
a=appversion:1.0
pedrosbanioles commented 6 months ago

123 Submitted for replacing the method for validating with using regex, it should at least match 1 type and return the first instance or then throw a format exception if no good connection exists