feyris-tan 30026b2b02
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 3m38s
Added functionality necessary to extract the MPEG-DASH segments on the Arsat stream.
2025-11-23 00:27:00 +01:00

209 lines
5.3 KiB
C#

using log4net;
using log4net.Repository.Hierarchy;
using skyscraper5.Skyscraper.IO.TunerInterface;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ietf.Rfc4566_SDP
{
public class SdpAttributeCollection : IEnumerable<SdpAttribute>
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private Dictionary<string, SdpAttribute> _attributes;
internal void SetHint(string args)
{
if (_attributes == null)
_attributes = new Dictionary<string, SdpAttribute>();
int indexOf = args.IndexOf(':');
string key = args.Substring(0, indexOf);
string value = args.Substring(indexOf + 1);
switch (key)
{
case "mbms-mode":
_attributes.Add(key, new MbmsMode(value));
break;
case "source-filter":
if (!_attributes.ContainsKey(key))
_attributes.Add(key, new SourceFilter());
SourceFilter sourceFilter = _attributes[key] as SourceFilter;
sourceFilter.SetHint(value);
break;
case "flute-tsi":
_attributes.Add(key, new FluteTsi(value));
break;
default:
logger.ErrorFormat("Unknown SDP Attribute: \"{0}\" - please consider sharing a sample of this stream for further analysis.", key);
break;
}
}
public IEnumerator<SdpAttribute> GetEnumerator()
{
return _attributes.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _attributes.Values.GetEnumerator();
}
}
internal class FluteTsi : SdpAttribute
{
public FluteTsi(string value) : base("flute-tsi")
{
TSI = long.Parse(value);
}
public long TSI { get; private set; }
public override string ToString()
{
return TSI.ToString();
}
}
internal class SourceFilter : SdpAttribute
{
public SourceFilter() : base("source-filter")
{
}
public void SetHint(string value)
{
if (_filterChain == null)
_filterChain = new List<SourceFilterChainLink>();
_filterChain.Add(new SourceFilterChainLink(value.Split(' ',StringSplitOptions.RemoveEmptyEntries)));
}
private List<SourceFilterChainLink> _filterChain;
class SourceFilterChainLink
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public SourceFilterChainLink(string[] args)
{
if (args[0].Equals("incl"))
{
Include = true;
}
else if (args[0].Equals("excl"))
{
Include = false;
}
else
{
logger.ErrorFormat("Unknown Filter Mode \"{0}\", assuming exclusion just to be sure.", args[0]);
}
if (!SdpNetworkType.TryParse(args[1], true, out _networkType))
{
logger.ErrorFormat("Unknown Network Type \"{0}\", assuming \"IN\" - please consider sharing a sample of this stream so this can be implemented.", args[1]);
_networkType = SdpNetworkType.IN;
}
if (!SdpAddressType.TryParse(args[2], true, out _addressType))
{
logger.ErrorFormat("Unknown Address Type \"{0}\", assuming \"IP4\" - please consider sharing a sample of this stream so this can be implemented.", args[2]);
_addressType = SdpAddressType.IP4;
}
DestinationAddress = args[3];
int numSources = args.Length - 4;
Sources = new string[numSources];
Array.Copy(args, 4, Sources, 0, numSources);
}
/// <summary>
/// If this is true, an incoming packet is accepted, if not it gets discarded.
/// </summary>
public bool Include { get; private set; }
public string[] Sources { get; private set; }
public string DestinationAddress { get; private set; }
private SdpAddressType _addressType;
public SdpAddressType AddressType
{
get => _addressType;
}
private SdpNetworkType _networkType;
public SdpNetworkType NetworkType
{
get => _networkType;
}
}
}
internal class MbmsMode : SdpAttribute
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public MbmsMode(string value)
: base("mbms-mode")
{
string[] args = value.Split(' ');
if (args[0].Equals("broadcast-mbsfn"))
{
BigInteger tmgi = BigInteger.Parse(args[1]);
this.Tmgi = tmgi.ToByteArray();
}
else if (args[0].Equals("broadcast"))
{
BigInteger tmgi = BigInteger.Parse(args[1]);
this.Tmgi = tmgi.ToByteArray();
this.MbmsCountingIndication = int.Parse(args[2]);
}
else
{
logger.ErrorFormat("Unknown MBMS Mode: {0} - please consider a sharing a sample of this stream if you'd like the developer to look further into this.", args[0]);
}
}
public int? MbmsCountingIndication { get; private set; }
public byte[] Tmgi { get; private set; }
internal enum MbmsBearerMode
{
Unknown,
Broadcast,
BroadcastMbsfn
}
public MbmsBearerMode BearerMode
{
get
{
if (Tmgi == null)
return MbmsBearerMode.Unknown;
if (MbmsCountingIndication == null)
return MbmsBearerMode.BroadcastMbsfn;
else
return MbmsBearerMode.Broadcast;
}
}
}
public abstract class SdpAttribute
{
protected SdpAttribute(string key)
{
this.SdpAttributeName = key;
}
public string SdpAttributeName { get; private set; }
}
}