hawkeye camera support(not tested)
This commit is contained in:
77
framework/Inspectron.HawkEye/RTSP/Sdp/Attribut.cs
Normal file
77
framework/Inspectron.HawkEye/RTSP/Sdp/Attribut.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class Attribut
|
||||
{
|
||||
private static readonly Dictionary<string, Type> attributMap = new Dictionary<string, Type>()
|
||||
{
|
||||
{AttributRtpMap.NAME,typeof(AttributRtpMap)},
|
||||
{AttributFmtp.NAME,typeof(AttributFmtp)},
|
||||
};
|
||||
|
||||
|
||||
public virtual string Key { get; private set; }
|
||||
public virtual string Value { get; protected set; }
|
||||
|
||||
public static void RegisterNewAttributeType(string key, Type attributType)
|
||||
{
|
||||
if(!attributType.IsSubclassOf(typeof(Attribut)))
|
||||
throw new ArgumentException("Type must be subclass of Rtsp.Sdp.Attribut","attributType");
|
||||
|
||||
attributMap[key] = attributType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Attribut()
|
||||
{
|
||||
}
|
||||
|
||||
public Attribut(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
|
||||
public static Attribut ParseInvariant(string value)
|
||||
{
|
||||
if(value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
Contract.EndContractBlock();
|
||||
|
||||
var listValues = value.Split(new char[] {':'}, 2);
|
||||
|
||||
|
||||
Attribut returnValue;
|
||||
|
||||
// Call parser of child type
|
||||
Type childType;
|
||||
attributMap.TryGetValue(listValues[0], out childType);
|
||||
if (childType != null)
|
||||
{
|
||||
var defaultContructor = childType.GetConstructor(Type.EmptyTypes);
|
||||
returnValue = defaultContructor.Invoke(Type.EmptyTypes) as Attribut;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = new Attribut(listValues[0]);
|
||||
}
|
||||
// Parse the value. Note most attributes have a value but recvonly does not have a value
|
||||
if (listValues.Count() > 1) returnValue.ParseValue(listValues[1]);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
protected virtual void ParseValue(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
75
framework/Inspectron.HawkEye/RTSP/Sdp/AttributFmtp.cs
Normal file
75
framework/Inspectron.HawkEye/RTSP/Sdp/AttributFmtp.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class AttributFmtp : Attribut
|
||||
{
|
||||
public const string NAME = "fmtp";
|
||||
|
||||
private Dictionary<String, String> parameters = new Dictionary<string, string>();
|
||||
|
||||
public AttributFmtp()
|
||||
{
|
||||
}
|
||||
|
||||
public override string Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("{0} {1}", PayloadNumber, FormatParameter);
|
||||
}
|
||||
protected set
|
||||
{
|
||||
ParseValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public int PayloadNumber { get; set; }
|
||||
|
||||
// temporary aatibute to store remaning data not parsed
|
||||
public string FormatParameter { get; set; }
|
||||
|
||||
|
||||
// Extract the Payload Number and the Format Parameters
|
||||
protected override void ParseValue(string value)
|
||||
{
|
||||
var parts = value.Split(new char[] { ' ' }, 2);
|
||||
|
||||
int payloadNumber;
|
||||
if(int.TryParse(parts[0], out payloadNumber))
|
||||
{
|
||||
this.PayloadNumber = payloadNumber;
|
||||
}
|
||||
if(parts.Length > 1)
|
||||
{
|
||||
FormatParameter = parts[1];
|
||||
|
||||
// Split on ';' to get a list of items.
|
||||
// Then Trim each item and then Split on the first '='
|
||||
// Add them to the dictionary
|
||||
parameters.Clear();
|
||||
foreach (var pair in parts[1].Split(';').Select(x => x.Trim().Split(new char[] { '=' }, 2))) {
|
||||
if (!string.IsNullOrWhiteSpace(pair[0]))
|
||||
parameters[pair[0]] = pair.Length > 1 ? pair[1] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String GetParameter(String index)
|
||||
{
|
||||
if (parameters.ContainsKey(index)) return parameters[index];
|
||||
else return "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
76
framework/Inspectron.HawkEye/RTSP/Sdp/AttributRtpMap.cs
Normal file
76
framework/Inspectron.HawkEye/RTSP/Sdp/AttributRtpMap.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class AttributRtpMap : Attribut
|
||||
{
|
||||
// Format
|
||||
// rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
|
||||
// Examples
|
||||
// rtpmap:96 H264/90000
|
||||
// rtpmap:8 PCMA/8000
|
||||
|
||||
public const string NAME = "rtpmap";
|
||||
|
||||
public AttributRtpMap()
|
||||
{
|
||||
}
|
||||
|
||||
public override string Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if(string.IsNullOrEmpty(EncodingParameters))
|
||||
{
|
||||
return string.Format("{0} {1}/{2}", PayloadNumber, EncodingName, ClockRate);
|
||||
} else {
|
||||
return string.Format("{0} {1}/{2}/{3}", PayloadNumber, EncodingName, ClockRate, EncodingParameters);
|
||||
}
|
||||
}
|
||||
protected set
|
||||
{
|
||||
ParseValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public int PayloadNumber { get; set; }
|
||||
public String EncodingName { get; set; }
|
||||
public String ClockRate { get; set; }
|
||||
public String EncodingParameters { get; set; }
|
||||
|
||||
protected override void ParseValue(string value)
|
||||
{
|
||||
var parts = value.Split(new char[] { ' ', '/' });
|
||||
|
||||
if (parts.Length >= 1) {
|
||||
int tmp_payloadNumber;
|
||||
if (int.TryParse(parts[0], out tmp_payloadNumber))
|
||||
{
|
||||
PayloadNumber = tmp_payloadNumber;
|
||||
}
|
||||
}
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
EncodingName = parts[1];
|
||||
}
|
||||
if (parts.Length >= 3)
|
||||
{
|
||||
ClockRate = parts[2];
|
||||
}
|
||||
if (parts.Length >= 4)
|
||||
{
|
||||
EncodingParameters = parts[3];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
framework/Inspectron.HawkEye/RTSP/Sdp/Bandwidth.cs
Normal file
15
framework/Inspectron.HawkEye/RTSP/Sdp/Bandwidth.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class Bandwidth
|
||||
{
|
||||
public Bandwidth()
|
||||
{
|
||||
}
|
||||
|
||||
internal static Bandwidth Parse(string value)
|
||||
{
|
||||
//TODO really parse.
|
||||
return new Bandwidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
48
framework/Inspectron.HawkEye/RTSP/Sdp/Connection.cs
Normal file
48
framework/Inspectron.HawkEye/RTSP/Sdp/Connection.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public abstract class Connection
|
||||
{
|
||||
public Connection()
|
||||
{
|
||||
//Default value from spec
|
||||
NumberOfAddress = 1;
|
||||
}
|
||||
|
||||
public string Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of address specifed in connection.
|
||||
/// </summary>
|
||||
/// <value>The number of address.</value>
|
||||
//TODO handle it a different way (list of adress ?)
|
||||
public int NumberOfAddress { get; set; }
|
||||
|
||||
public static Connection Parse(string value)
|
||||
{
|
||||
if(value ==null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
string[] parts = value.Split(' ');
|
||||
|
||||
if (parts.Length != 3)
|
||||
throw new FormatException("Value do not contain 3 parts as needed.");
|
||||
|
||||
if (parts[0] != "IN")
|
||||
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Net type {0} not suported", parts[0]));
|
||||
|
||||
switch (parts[1])
|
||||
{
|
||||
case "IP4":
|
||||
return ConnectionIP4.Parse(parts[2]);
|
||||
case "IP6":
|
||||
return ConnectionIP6.Parse(parts[2]);
|
||||
default:
|
||||
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Address type {0} not suported", parts[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
40
framework/Inspectron.HawkEye/RTSP/Sdp/ConnectionIP4.cs
Normal file
40
framework/Inspectron.HawkEye/RTSP/Sdp/ConnectionIP4.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class ConnectionIP4 : Connection
|
||||
{
|
||||
|
||||
public int Ttl { get; set; }
|
||||
|
||||
internal new static ConnectionIP4 Parse(string ipAddress)
|
||||
{
|
||||
string[] parts = ipAddress.Split('/');
|
||||
|
||||
if (parts.Length > 3)
|
||||
throw new FormatException("Too much address subpart in " + ipAddress);
|
||||
|
||||
ConnectionIP4 result = new ConnectionIP4();
|
||||
|
||||
result.Host = parts[0];
|
||||
|
||||
int ttl;
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
if (!int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out ttl))
|
||||
throw new FormatException("Invalid TTL format : " + parts[1]);
|
||||
result.Ttl = ttl;
|
||||
}
|
||||
int numberOfAddress;
|
||||
if (parts.Length > 2)
|
||||
{
|
||||
if (!int.TryParse(parts[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out numberOfAddress))
|
||||
throw new FormatException("Invalid number of address : " + parts[2]);
|
||||
result.NumberOfAddress = numberOfAddress;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
framework/Inspectron.HawkEye/RTSP/Sdp/ConnectionIP6.cs
Normal file
31
framework/Inspectron.HawkEye/RTSP/Sdp/ConnectionIP6.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class ConnectionIP6 : Connection
|
||||
{
|
||||
internal new static ConnectionIP6 Parse(string ipAddress)
|
||||
{
|
||||
string[] parts = ipAddress.Split('/');
|
||||
|
||||
if (parts.Length > 2)
|
||||
throw new FormatException("Too much address subpart in " + ipAddress);
|
||||
|
||||
ConnectionIP6 result = new ConnectionIP6();
|
||||
|
||||
result.Host = parts[0];
|
||||
|
||||
int numberOfAddress;
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
if (!int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out numberOfAddress))
|
||||
throw new FormatException("Invalid number of address : " + parts[1]);
|
||||
result.NumberOfAddress = numberOfAddress;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
22
framework/Inspectron.HawkEye/RTSP/Sdp/EncriptionKey.cs
Normal file
22
framework/Inspectron.HawkEye/RTSP/Sdp/EncriptionKey.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class EncriptionKey
|
||||
{
|
||||
public EncriptionKey(string p)
|
||||
{
|
||||
}
|
||||
|
||||
public static EncriptionKey ParseInvariant(string value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
Contract.EndContractBlock();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
136
framework/Inspectron.HawkEye/RTSP/Sdp/H264Parameter.cs
Normal file
136
framework/Inspectron.HawkEye/RTSP/Sdp/H264Parameter.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class H264Parameters : IDictionary<String, String>
|
||||
{
|
||||
private readonly Dictionary<String, String> parameters = new Dictionary<string, string>();
|
||||
|
||||
public List<byte[]> SpropParameterSets
|
||||
{
|
||||
get
|
||||
{
|
||||
List<byte[]> result = new List<byte[]>();
|
||||
|
||||
if (ContainsKey("sprop-parameter-sets")&& this["sprop-parameter-sets"] != null)
|
||||
{
|
||||
result.AddRange(this["sprop-parameter-sets"].Split(',').Select(x => Convert.FromBase64String(x)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static H264Parameters Parse(String parameterString)
|
||||
{
|
||||
var result = new H264Parameters();
|
||||
foreach (var pair in parameterString.Split(';').Select(x => x.Trim().Split(new char[] { '=' }, 2)))
|
||||
{
|
||||
if(!string.IsNullOrWhiteSpace(pair[0]))
|
||||
result[pair[0]] = pair.Length > 1 ? pair[1] : null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return parameters.Select(p => p.Key + (p.Value != null ? "=" + p.Value : string.Empty)).Aggregate((x, y) => x + ";" + y);
|
||||
}
|
||||
|
||||
public String this[String index]
|
||||
{
|
||||
get { return parameters[index]; }
|
||||
set { parameters[index] = value; }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return parameters.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).IsReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<string> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Keys;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<string> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Values;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, string> item)
|
||||
{
|
||||
((IDictionary<string, string>)parameters).Add(item);
|
||||
}
|
||||
|
||||
public void Add(string key, string value)
|
||||
{
|
||||
parameters.Add(key, value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
parameters.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, string> item)
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Contains(item);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return parameters.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
|
||||
{
|
||||
((IDictionary<string, string>)parameters).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).GetEnumerator();
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, string> item)
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Remove(item);
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
return parameters.Remove(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out string value)
|
||||
{
|
||||
return parameters.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
149
framework/Inspectron.HawkEye/RTSP/Sdp/H265Parameter.cs
Normal file
149
framework/Inspectron.HawkEye/RTSP/Sdp/H265Parameter.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
// Parse 'fmtp' attribute in SDP
|
||||
// Extract H265 fields
|
||||
// By Roger Hardiman, RJH Technical Consultancy Ltd
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class H265Parameters : IDictionary<String, String>
|
||||
{
|
||||
private readonly Dictionary<String, String> parameters = new Dictionary<string, string>();
|
||||
|
||||
public List<byte[]> SpropParameterSets
|
||||
{
|
||||
get
|
||||
{
|
||||
List<byte[]> result = new List<byte[]>();
|
||||
|
||||
if (ContainsKey("sprop-vps")&& this["sprop-vps"] != null)
|
||||
{
|
||||
result.AddRange(this["sprop-vps"].Split(',').Select(x => Convert.FromBase64String(x)));
|
||||
}
|
||||
|
||||
if (ContainsKey("sprop-sps") && this["sprop-sps"] != null)
|
||||
{
|
||||
result.AddRange(this["sprop-sps"].Split(',').Select(x => Convert.FromBase64String(x)));
|
||||
}
|
||||
|
||||
if (ContainsKey("sprop-pps") && this["sprop-pps"] != null)
|
||||
{
|
||||
result.AddRange(this["sprop-pps"].Split(',').Select(x => Convert.FromBase64String(x)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static H265Parameters Parse(String parameterString)
|
||||
{
|
||||
var result = new H265Parameters();
|
||||
foreach (var pair in parameterString.Split(';').Select(x => x.Trim().Split(new char[] { '=' }, 2)))
|
||||
{
|
||||
if(!string.IsNullOrWhiteSpace(pair[0]))
|
||||
result[pair[0]] = pair.Length > 1 ? pair[1] : null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return parameters.Select(p => p.Key + (p.Value != null ? "=" + p.Value : string.Empty)).Aggregate((x, y) => x + ";" + y);
|
||||
}
|
||||
|
||||
public String this[String index]
|
||||
{
|
||||
get { return parameters[index]; }
|
||||
set { parameters[index] = value; }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return parameters.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).IsReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<string> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Keys;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<string> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Values;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, string> item)
|
||||
{
|
||||
((IDictionary<string, string>)parameters).Add(item);
|
||||
}
|
||||
|
||||
public void Add(string key, string value)
|
||||
{
|
||||
parameters.Add(key, value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
parameters.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, string> item)
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Contains(item);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return parameters.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
|
||||
{
|
||||
((IDictionary<string, string>)parameters).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).GetEnumerator();
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, string> item)
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).Remove(item);
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
return parameters.Remove(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out string value)
|
||||
{
|
||||
return parameters.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IDictionary<string, string>)parameters).GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
60
framework/Inspectron.HawkEye/RTSP/Sdp/Media.cs
Normal file
60
framework/Inspectron.HawkEye/RTSP/Sdp/Media.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class Media
|
||||
{
|
||||
private string mediaString;
|
||||
|
||||
public Media(string mediaString)
|
||||
{
|
||||
// Example is 'video 0 RTP/AVP 26;
|
||||
this.mediaString = mediaString;
|
||||
|
||||
var parts = mediaString.Split(new char[] { ' ' } , 4);
|
||||
|
||||
if (parts.Count() >= 1) {
|
||||
if (parts[0].Equals("video")) MediaType = MediaTypes.video;
|
||||
else if (parts[0].Equals("audio")) MediaType = MediaTypes.audio;
|
||||
else if (parts[0].Equals("text")) MediaType = MediaTypes.text;
|
||||
else if (parts[0].Equals("application")) MediaType = MediaTypes.application;
|
||||
else if (parts[0].Equals("message")) MediaType = MediaTypes.message;
|
||||
else MediaType = MediaTypes.unknown; // standard does allow for future types to be defined
|
||||
}
|
||||
|
||||
int pt;
|
||||
if (parts.Count() >= 4) {
|
||||
if(int.TryParse(parts[3], out pt))
|
||||
{
|
||||
PayloadType = pt;
|
||||
} else {
|
||||
PayloadType = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RFC4566 Media Types
|
||||
public enum MediaTypes { video, audio, text, application, message, unknown };
|
||||
|
||||
public Connection Connection { get; set; }
|
||||
|
||||
public Bandwidth Bandwidth { get; set; }
|
||||
|
||||
public EncriptionKey EncriptionKey { get; set; }
|
||||
|
||||
public MediaTypes MediaType { get; set; }
|
||||
|
||||
public int PayloadType { get; set; }
|
||||
|
||||
private readonly List<Attribut> attributs = new List<Attribut>();
|
||||
|
||||
public IList<Attribut> Attributs
|
||||
{
|
||||
get
|
||||
{
|
||||
return attributs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
framework/Inspectron.HawkEye/RTSP/Sdp/Origin.cs
Normal file
101
framework/Inspectron.HawkEye/RTSP/Sdp/Origin.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
/// <summary>
|
||||
/// Object ot represent orgin in an Session Description Protocol
|
||||
/// </summary>
|
||||
public class Origin
|
||||
{
|
||||
public Origin()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the specified origin string.
|
||||
/// </summary>
|
||||
/// <param name="originString">The string to convert to origin object.</param>
|
||||
/// <returns></returns>
|
||||
public static Origin Parse(string originString)
|
||||
{
|
||||
if (originString == null)
|
||||
throw new ArgumentNullException("originString");
|
||||
|
||||
string[] parts = originString.Split(' ');
|
||||
|
||||
if (parts.Length != 6)
|
||||
throw new FormatException("Number of element invalid in origin string.");
|
||||
|
||||
Origin result = new Origin();
|
||||
result.Username = parts[0];
|
||||
result.SessionId = parts[1];
|
||||
result.SessionVersion = parts[2];
|
||||
result.NetType = parts[3];
|
||||
result.AddressType = parts[4];
|
||||
result.UnicastAddress = parts[5];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
/// <remarks>It is the user's login on the originating host, or it is "-"
|
||||
/// if the originating host does not support the concept of user IDs.
|
||||
/// This MUST NOT contain spaces</remarks>
|
||||
/// <value>The username.</value>
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session id.
|
||||
/// </summary>
|
||||
/// <remarks>It is a numeric string such that the tuple of <see cref="Username"/>,
|
||||
/// <see cref="SessionId"/>, <see cref="NetType"/>, <see cref="AddressType"/>, and <see cref="UnicastAddress"/> forms a
|
||||
/// globally unique identifier for the session. The method of
|
||||
/// <see cref="SessionId"/> allocation is up to the creating tool, but it has been
|
||||
/// suggested that a Network Time Protocol (NTP) format timestamp be
|
||||
/// used to ensure uniqueness</remarks>
|
||||
/// <value>The session id.</value>
|
||||
public string SessionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session version.
|
||||
/// </summary>
|
||||
/// <value>The session version.</value>
|
||||
public string SessionVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the net.
|
||||
/// </summary>
|
||||
/// <value>The type of the net.</value>
|
||||
public string NetType { get; set; }
|
||||
|
||||
/// <see cref="SessionId"/><summary>
|
||||
/// Gets or sets the type of the address.
|
||||
/// </summary>
|
||||
/// <value>The type of the address.</value>
|
||||
public string AddressType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the unicast address (IP or FDQN).
|
||||
/// </summary>
|
||||
/// <value>The unicast address.</value>
|
||||
public string UnicastAddress { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Join(" ",
|
||||
new string[]
|
||||
{
|
||||
Username,
|
||||
SessionId,
|
||||
SessionVersion.ToString(CultureInfo.InvariantCulture),
|
||||
NetType,
|
||||
AddressType,
|
||||
UnicastAddress,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
267
framework/Inspectron.HawkEye/RTSP/Sdp/SdpFile.cs
Normal file
267
framework/Inspectron.HawkEye/RTSP/Sdp/SdpFile.cs
Normal file
@@ -0,0 +1,267 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class SdpFile
|
||||
{
|
||||
private static KeyValuePair<string, string> GetKeyValue(TextReader sdpStream)
|
||||
{
|
||||
string line = sdpStream.ReadLine();
|
||||
|
||||
// end of file ?
|
||||
if(string.IsNullOrEmpty(line))
|
||||
return new KeyValuePair<string, string>(null, null);
|
||||
|
||||
|
||||
string[] parts = line.Split(new char[] { '=' }, 2);
|
||||
if (parts.Length != 2)
|
||||
throw new InvalidDataException();
|
||||
if (parts[0].Length != 1)
|
||||
throw new InvalidDataException();
|
||||
|
||||
KeyValuePair<string, string> value = new KeyValuePair<string, string>(parts[0], parts[1]);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the specified SDP stream.
|
||||
/// As define in RFC 4566
|
||||
/// </summary>
|
||||
/// <param name="sdpStream">The SDP stream.</param>
|
||||
/// <returns></returns>
|
||||
public static SdpFile Read(TextReader sdpStream)
|
||||
{
|
||||
SdpFile returnValue = new SdpFile();
|
||||
KeyValuePair<string, string> value = GetKeyValue(sdpStream);
|
||||
|
||||
// Version mandatory
|
||||
if (value.Key == "v")
|
||||
{
|
||||
returnValue.Version = int.Parse(value.Value, CultureInfo.InvariantCulture);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
else {
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
|
||||
// Origin mandatory
|
||||
if (value.Key == "o")
|
||||
{
|
||||
returnValue.Origin = Origin.Parse(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
else {
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
|
||||
// Session mandatory.
|
||||
// However the MuxLab HDMI Encoder (TX-500762) Firmware 1.0.6
|
||||
// does not include the 'Session' so supress InvalidDatarException
|
||||
if (value.Key == "s")
|
||||
{
|
||||
returnValue.Session = value.Value;
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
else {
|
||||
// throw new InvalidDataException(); // we should throw, but instead we just ignore the error
|
||||
}
|
||||
|
||||
// Session Information optional
|
||||
if (value.Key == "i")
|
||||
{
|
||||
returnValue.SessionInformation = value.Value;
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Uri optional
|
||||
if (value.Key == "u")
|
||||
{
|
||||
returnValue.Url = new Uri(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Email optional
|
||||
if (value.Key == "e")
|
||||
{
|
||||
returnValue.Email = value.Value;
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Phone optional
|
||||
if (value.Key == "p")
|
||||
{
|
||||
returnValue.Phone = value.Value;
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Connection optional
|
||||
if (value.Key == "c")
|
||||
{
|
||||
returnValue.Connection = Connection.Parse(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// bandwidth optional
|
||||
if (value.Key == "b")
|
||||
{
|
||||
returnValue.Bandwidth = Bandwidth.Parse(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Timing mandatory
|
||||
while (value.Key == "t")
|
||||
{
|
||||
string timing = value.Value;
|
||||
string repeat = string.Empty;
|
||||
value = GetKeyValue(sdpStream);
|
||||
if (value.Key == "r")
|
||||
{
|
||||
repeat = value.Value;
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
returnValue.Timings.Add(new Timing(timing, repeat));
|
||||
}
|
||||
|
||||
// timezone optional
|
||||
if (value.Key == "z")
|
||||
{
|
||||
|
||||
returnValue.TimeZone = SdpTimeZone.ParseInvariant(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// encryption key optional
|
||||
if (value.Key == "k")
|
||||
{
|
||||
|
||||
returnValue.EncriptionKey = EncriptionKey.ParseInvariant(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
//Attribute optional multiple
|
||||
while (value.Key == "a")
|
||||
{
|
||||
returnValue.Attributs.Add(Attribut.ParseInvariant(value.Value));
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Hack for MuxLab HDMI Encoder (TX-500762) Firmware 1.0.6
|
||||
// Skip over all other Key/Value pairs until the 'm=' key
|
||||
while (value.Key != "m") {
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Media
|
||||
while (value.Key == "m")
|
||||
{
|
||||
Media newMedia = ReadMedia(sdpStream, ref value);
|
||||
returnValue.Medias.Add(newMedia);
|
||||
}
|
||||
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private static Media ReadMedia(TextReader sdpStream, ref KeyValuePair<string, string> value)
|
||||
{
|
||||
Media returnValue = new Media(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
|
||||
// Media title
|
||||
if (value.Key == "i")
|
||||
{
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// Connexion optional
|
||||
if (value.Key == "c")
|
||||
{
|
||||
returnValue.Connection = Connection.Parse(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// bandwidth optional
|
||||
if (value.Key == "b")
|
||||
{
|
||||
returnValue.Bandwidth = Bandwidth.Parse(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
// enkription key optional
|
||||
if (value.Key == "k")
|
||||
{
|
||||
|
||||
returnValue.EncriptionKey = EncriptionKey.ParseInvariant(value.Value);
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
//Attribut optional multiple
|
||||
while (value.Key == "a")
|
||||
{
|
||||
returnValue.Attributs.Add(Attribut.ParseInvariant(value.Value));
|
||||
value = GetKeyValue(sdpStream);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
|
||||
public Origin Origin { get; set; }
|
||||
|
||||
public string Session { get; set; }
|
||||
|
||||
public string SessionInformation { get; set; }
|
||||
|
||||
public Uri Url { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
|
||||
public string Phone { get; set; }
|
||||
|
||||
public Connection Connection { get; set; }
|
||||
|
||||
public Bandwidth Bandwidth { get; set; }
|
||||
|
||||
private readonly List<Timing> timingList = new List<Timing>();
|
||||
|
||||
public IList<Timing> Timings
|
||||
{
|
||||
get
|
||||
{
|
||||
return timingList;
|
||||
}
|
||||
}
|
||||
|
||||
public SdpTimeZone TimeZone { get; set; }
|
||||
|
||||
public EncriptionKey EncriptionKey { get; set; }
|
||||
|
||||
private readonly List<Attribut> attributs = new List<Attribut>();
|
||||
|
||||
public IList<Attribut> Attributs
|
||||
{
|
||||
get
|
||||
{
|
||||
return attributs;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Media> medias = new List<Media>();
|
||||
|
||||
public IList<Media> Medias
|
||||
{
|
||||
get
|
||||
{
|
||||
return medias;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
26
framework/Inspectron.HawkEye/RTSP/Sdp/SdpTimeZone.cs
Normal file
26
framework/Inspectron.HawkEye/RTSP/Sdp/SdpTimeZone.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class SdpTimeZone
|
||||
{
|
||||
public SdpTimeZone()
|
||||
{
|
||||
}
|
||||
|
||||
public static SdpTimeZone ParseInvariant(string value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
Contract.EndContractBlock();
|
||||
|
||||
SdpTimeZone returnValue = new SdpTimeZone();
|
||||
|
||||
throw new NotImplementedException();
|
||||
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
framework/Inspectron.HawkEye/RTSP/Sdp/Timing.cs
Normal file
15
framework/Inspectron.HawkEye/RTSP/Sdp/Timing.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Sdp
|
||||
{
|
||||
public class Timing
|
||||
{
|
||||
private string timing;
|
||||
private string repeat;
|
||||
|
||||
public Timing(string timing, string repeat)
|
||||
{
|
||||
// TODO: Complete member initialization
|
||||
this.timing = timing;
|
||||
this.repeat = repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user