288 lines
9.0 KiB
C#
288 lines
9.0 KiB
C#
using skyscraper5.Mpeg2;
|
|
using skyscraper5.Mpeg2.Descriptors;
|
|
using skyscraper5.Skyscraper.IO;
|
|
using skyscraper5.src.InteractionChannel.Model;
|
|
using skyscraper5.src.InteractionChannel.Model2;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace skyscraper5.src.InteractionChannel
|
|
{
|
|
internal class InteractionChannelPsiGatherer : IPsiProcessor
|
|
{
|
|
private UserDefinedDescriptor _expectedTable;
|
|
public UserDefinedDescriptor ExpectedTables
|
|
{
|
|
get => _expectedTable;
|
|
set
|
|
{
|
|
if (value.DescriptorTag != 0xa7)
|
|
{
|
|
throw new ArgumentException(String.Format("Expected a {0} descriptor.", 0xa7));
|
|
}
|
|
_expectedTable = value;
|
|
}
|
|
}
|
|
|
|
private InteractionChannelHandler _handler;
|
|
public InteractionChannelHandler Handler
|
|
{
|
|
get => _handler;
|
|
set => _handler = value;
|
|
}
|
|
|
|
public ushort? NetworkId { get; private set; }
|
|
|
|
|
|
//Maybe also check ETSI EN 301 545-2 V1.4.0 (2023-10) ?
|
|
|
|
//en_301790v010501p_RCS_Map.pdf
|
|
//page 78
|
|
public void GatherPsi(PsiSection section, int sourcePid)
|
|
{
|
|
if (_handler == null)
|
|
{
|
|
throw new NoInteractionChannelHandlerException();
|
|
}
|
|
byte[] buffer = section.GetDataCopy();
|
|
if (_expectedTable != null)
|
|
{
|
|
if (!_expectedTable.Data.Contains(buffer[0]))
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.UnexpectedTable);
|
|
return;
|
|
}
|
|
}
|
|
MemoryStream ms = new MemoryStream(buffer, false);
|
|
switch (buffer[0])
|
|
{
|
|
case 0x40: //NIT
|
|
//see ETSI EN 301 545-2
|
|
throw new NotImplementedException("NIT");
|
|
case 0x41: //RMT
|
|
Rmt rmt = new Rmt(ms);
|
|
if (!rmt.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.RmtInvalid);
|
|
return;
|
|
}
|
|
_handler.OnRcsMap(rmt);
|
|
return;
|
|
case 0x4D: //SAT
|
|
throw new NotImplementedException("SAT");
|
|
case 0x70: //TDT
|
|
throw new NotImplementedException("TDT");
|
|
case 0xA0: //SCT
|
|
InteractionChannelSiSectionHeader sctHeader = new InteractionChannelSiSectionHeader(ms);
|
|
if (!sctHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = sctHeader.InteractiveNetworkId;
|
|
Sct sct = new Sct(ms);
|
|
if (!sct.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.SctInvalid);
|
|
return;
|
|
}
|
|
Handler.OnSuperframeComposition(sctHeader.InteractiveNetworkId, sct);
|
|
return;
|
|
case 0xA1: //FCT
|
|
InteractionChannelSiSectionHeader fctHeader = new InteractionChannelSiSectionHeader(ms);
|
|
if (!fctHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = fctHeader.InteractiveNetworkId;
|
|
Fct fct = new Fct(ms);
|
|
if (!fct.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.FctInvalid);
|
|
return;
|
|
}
|
|
Handler.OnFrameComposition(fctHeader.InteractiveNetworkId, fct);
|
|
return;
|
|
case 0xA2: //TCT
|
|
InteractionChannelSiSectionHeader tctHeader = new InteractionChannelSiSectionHeader(ms);
|
|
if (!tctHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = tctHeader.InteractiveNetworkId;
|
|
Tct tct = new Tct(ms);
|
|
if (!tct.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.TctInvalid);
|
|
return;
|
|
}
|
|
Handler.OnTimeslotComposition(tctHeader.InteractiveNetworkId, tct);
|
|
return;
|
|
case 0xA3: //SPT
|
|
InteractionChannelSiSectionHeader sptHeader = new InteractionChannelSiSectionHeader(ms);
|
|
if (!sptHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError (InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = sptHeader.InteractiveNetworkId;
|
|
Spt spt = new Spt(ms);
|
|
if (!spt.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.SptInvalid);
|
|
return;
|
|
}
|
|
Handler.OnSatellitePosition(sptHeader.InteractiveNetworkId, spt);
|
|
return;
|
|
case 0xA4: //CMT
|
|
InteractionChannelSiSectionHeader cmtHeader = new InteractionChannelSiSectionHeader(ms);
|
|
if (!cmtHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = cmtHeader.InteractiveNetworkId;
|
|
Cmt cmt = new Cmt(ms);
|
|
if (!cmt.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.CmtInvalid);
|
|
return;
|
|
}
|
|
Handler.OnCorrectionMessage(cmtHeader.InteractiveNetworkId, cmt);
|
|
return;
|
|
case 0xA5: //TBTP
|
|
InteractionChannelSiSectionHeader tbtpHeader = new InteractionChannelSiSectionHeader(ms);
|
|
if (!tbtpHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = tbtpHeader.InteractiveNetworkId;
|
|
Tbtp tbtp = new Tbtp(ms);
|
|
if (!tbtp.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.TbtpInvalid);
|
|
return;
|
|
}
|
|
Handler.OnTerminalBurstTimePlan(tbtpHeader.InteractiveNetworkId, tbtp);
|
|
return;
|
|
case 0xA6: //PCR packet payload
|
|
throw new NotImplementedException("PCR packet payload");
|
|
case 0xAA: //Transmission Mode Support Table
|
|
InteractionChannelSiSectionHeader tmstHeader = new InteractionChannelSiSectionHeader(ms);
|
|
if (!tmstHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = tmstHeader.InteractiveNetworkId;
|
|
Tmst tmst = new Tmst(ms);
|
|
if (!tmst.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.TmstInvalid);
|
|
return;
|
|
}
|
|
Handler.OnTransmissionModeSupport(tmstHeader.InteractiveNetworkId, tmst);
|
|
return;
|
|
case 0xAB: //FCT2
|
|
InteractionChannelSiSectionHeader fct2Header = new InteractionChannelSiSectionHeader(ms);
|
|
if (!fct2Header.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = fct2Header.InteractiveNetworkId;
|
|
Fct2 fct2 = new Fct2(ms);
|
|
if (!fct2.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.Fct2Invalid);
|
|
return;
|
|
}
|
|
throw new NotImplementedException("FCT2");
|
|
case 0xAC: //BCT
|
|
//see en_30154502v010401p.pdf, page 49
|
|
throw new NotImplementedException("BCT");
|
|
case 0xAD: //TBTP2
|
|
InteractionChannelSiSectionHeader tbtp2Header = new InteractionChannelSiSectionHeader(ms);
|
|
if (!tbtp2Header.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = tbtp2Header.InteractiveNetworkId;
|
|
Tbtp2 tbtp2 = new Tbtp2(ms);
|
|
if (!tbtp2.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.Tbtp2Invalid);
|
|
return;
|
|
}
|
|
throw new NotImplementedException("TBTP2");
|
|
case 0xAE: //TMST2
|
|
InteractionChannelSiSectionHeader tmst2Header = new InteractionChannelSiSectionHeader(ms);
|
|
if (!tmst2Header.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
NetworkId = tmst2Header.InteractiveNetworkId;
|
|
int transmissionStandard = _handler.GetRmtTransmissionStandard(NetworkId.Value);
|
|
Tmst2 tmst2 = new Tmst2(ms,transmissionStandard);
|
|
if (!tmst2.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.Tmst2Invalid);
|
|
return;
|
|
}
|
|
if (tmst2.TransmissionModes.Length == 0)
|
|
return;
|
|
throw new NotImplementedException("TMST2");
|
|
case 0xAF: //FAT
|
|
//see en_30154502v010401p.pdf, page 49
|
|
throw new NotImplementedException("TMST2");
|
|
case 0xB0: //TIM
|
|
InteractionChannelDsmCcPrivateSectionHeader timHeader = new InteractionChannelDsmCcPrivateSectionHeader(ms);
|
|
if (!timHeader.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
|
|
return;
|
|
}
|
|
Tim tim = new Tim(ms, timHeader.IsBroadcast);
|
|
if (!tim.Valid)
|
|
{
|
|
_handler.OnInteractionChannelError(InteractionChannelErrorState.TimInvalid);
|
|
return;
|
|
}
|
|
tim.Handle(timHeader.MacAddress, NetworkId, Handler);
|
|
return;
|
|
case 0xB1: //LL_FEC_parity_data_table
|
|
throw new NotImplementedException("LL_FEC_parity_data_table");
|
|
case 0xB2: //MMT2
|
|
//see en_30154502v010401p.pdf, page 49
|
|
throw new NotImplementedException("MMT2");
|
|
default:
|
|
if (buffer[0] == 0xa7 || buffer[0] == 0xa8 || buffer[0] == 0xa9)
|
|
{
|
|
//reserved
|
|
break;
|
|
}
|
|
if (buffer[0] >= 0xb2 || buffer[0] <= 0xbf)
|
|
{
|
|
//reserved for future use
|
|
break;
|
|
}
|
|
if (buffer[0] >= 0xc0 || buffer[0] <= 0xfe)
|
|
{
|
|
//user defined
|
|
break;
|
|
}
|
|
throw new NotImplementedException(String.Format("ETSI EN 301 790 V1.5.1 0x{0:X2}", buffer[0]));
|
|
}
|
|
}
|
|
}
|
|
}
|