Implemented ATSC 3 L1BasicSignalling and L1DetailSignalling
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 44s
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 44s
This commit is contained in:
parent
f4193297d2
commit
ef903cba96
@ -1,4 +1,5 @@
|
|||||||
using skyscraper5.Skyscraper.IO;
|
using skyscraper5.Ietf.Rfc971;
|
||||||
|
using skyscraper5.Skyscraper.IO;
|
||||||
using skyscraper8.Atsc.A330;
|
using skyscraper8.Atsc.A330;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -103,7 +104,8 @@ namespace skyscraper8.Atsc.A322
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Concatenation Header not yet implemented.");
|
stateMachineState = 7;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stateMachineState = 4;
|
stateMachineState = 4;
|
||||||
@ -125,6 +127,45 @@ namespace skyscraper8.Atsc.A322
|
|||||||
DeliverPacket(currentAlpPacket, neededBuffer);
|
DeliverPacket(currentAlpPacket, neededBuffer);
|
||||||
stateMachineState = 1;
|
stateMachineState = 1;
|
||||||
break;
|
break;
|
||||||
|
case 7: //Read Concatenation Header first byte.
|
||||||
|
byte[] concatHeaderFirstByteBuffer = new byte[1];
|
||||||
|
int readResult = ms.Read(concatHeaderFirstByteBuffer, 0, 1);
|
||||||
|
if (readResult == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
currentAlpPacket.ConcatLengthMsb = (concatHeaderFirstByteBuffer[0] & 0xf0) >> 4;
|
||||||
|
currentAlpPacket.Count = (concatHeaderFirstByteBuffer[0] & 0x0e) >> 1;
|
||||||
|
currentAlpPacket.SIF = (concatHeaderFirstByteBuffer[0] & 0x01) != 0;
|
||||||
|
|
||||||
|
int neededLength = 12 * currentAlpPacket.Count;
|
||||||
|
if ((currentAlpPacket.Count & 1) == 0)
|
||||||
|
neededLength += 4;
|
||||||
|
neededLength /= 8;
|
||||||
|
|
||||||
|
neededBufferOffset = 0;
|
||||||
|
stateMachineState = 8;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 8: //Get Concatenation Header Lengths
|
||||||
|
int readSuccesful3 = ms.Read(neededBuffer, neededBufferOffset, neededBuffer.Length - neededBufferOffset);
|
||||||
|
neededBufferOffset += readSuccesful3;
|
||||||
|
if (neededBufferOffset == neededBuffer.Length)
|
||||||
|
{
|
||||||
|
stateMachineState = 9;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 9: //Parse Concatenation Header Lengths
|
||||||
|
currentAlpPacket.ParseConcatenationHeaderLengths(neededBuffer);
|
||||||
|
if (currentAlpPacket.PacketType == AlpPacketType.LinkLayerSignalling)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Concatenated Link Layer Signalling Packets in ATSC 3.0 not yet supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAlpPacket.Length2 = (currentAlpPacket.ConcatLengthMsb << 11) | currentAlpPacket.Length;
|
||||||
|
neededBufferOffset = 0;
|
||||||
|
neededBuffer = new byte[currentAlpPacket.Length2];
|
||||||
|
stateMachineState = 5;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException(String.Format("ATSC PLP Baseband Parser State machine state #{0}", stateMachineState));
|
throw new NotImplementedException(String.Format("ATSC PLP Baseband Parser State machine state #{0}", stateMachineState));
|
||||||
}
|
}
|
||||||
@ -133,7 +174,7 @@ namespace skyscraper8.Atsc.A322
|
|||||||
|
|
||||||
private void DeliverPacket(AlpPacket? currentAlpPacket, byte[]? neededBuffer)
|
private void DeliverPacket(AlpPacket? currentAlpPacket, byte[]? neededBuffer)
|
||||||
{
|
{
|
||||||
Console.WriteLine("PacketType = {0} \t Length = {1}", currentAlpPacket.PacketType, neededBuffer.Length);
|
Console.WriteLine("PacketType = {0} \t Length = {1} (first bytes = {2:X2},{3:X2},{4:X2})", currentAlpPacket.PacketType, neededBuffer.Length, neededBuffer[0], neededBuffer[1], neededBuffer[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnSyncLoss()
|
internal void OnSyncLoss()
|
||||||
@ -145,6 +186,7 @@ namespace skyscraper8.Atsc.A322
|
|||||||
private int stateMachineState;
|
private int stateMachineState;
|
||||||
private byte[] neededBuffer;
|
private byte[] neededBuffer;
|
||||||
private int neededBufferOffset;
|
private int neededBufferOffset;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum OfiDescription
|
internal enum OfiDescription
|
||||||
|
|||||||
@ -39,8 +39,8 @@ namespace skyscraper8.Atsc.A322
|
|||||||
L1DetailAdditionalParityMode = bitstream.ReadBitsAsByte(2);
|
L1DetailAdditionalParityMode = bitstream.ReadBitsAsByte(2);
|
||||||
L1DetailTotalCells = bitstream.ReadBitsAsUint(19);
|
L1DetailTotalCells = bitstream.ReadBitsAsUint(19);
|
||||||
FirstSubMimo = bitstream.ReadBitAsBoolean();
|
FirstSubMimo = bitstream.ReadBitAsBoolean();
|
||||||
FirstSubMiso = bitstream.ReadBitsAsByte(2);
|
FirstSubMiso = (MisoSignallingFormat)bitstream.ReadBitsAsByte(2);
|
||||||
FirstSubFftSize = bitstream.ReadBitsAsByte(2);
|
FirstSubFftSize = (FftSizeSignallingFormat)bitstream.ReadBitsAsByte(2);
|
||||||
FirstSubReducedCarries = bitstream.ReadBitsAsByte(3);
|
FirstSubReducedCarries = bitstream.ReadBitsAsByte(3);
|
||||||
FirstSubGuardInterval = bitstream.ReadBitsAsByte(4);
|
FirstSubGuardInterval = bitstream.ReadBitsAsByte(4);
|
||||||
FirstSubNumOfdmSymbols = bitstream.ReadBitsAsUint(11);
|
FirstSubNumOfdmSymbols = bitstream.ReadBitsAsUint(11);
|
||||||
@ -49,6 +49,9 @@ namespace skyscraper8.Atsc.A322
|
|||||||
FirstSubSbsFirst = bitstream.ReadBitAsBoolean();
|
FirstSubSbsFirst = bitstream.ReadBitAsBoolean();
|
||||||
FirstSubSbsLast = bitstream.ReadBitAsBoolean();
|
FirstSubSbsLast = bitstream.ReadBitAsBoolean();
|
||||||
FirstSubMimoMixed = bitstream.ReadBitAsBoolean();
|
FirstSubMimoMixed = bitstream.ReadBitAsBoolean();
|
||||||
|
|
||||||
|
byte[] bytes = bitstream.ReadBitsAsByteArray(47); //reserved
|
||||||
|
uint crc = bitstream.ReadBitsAsUint(32);
|
||||||
Valid = true;
|
Valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,8 +74,8 @@ namespace skyscraper8.Atsc.A322
|
|||||||
public byte L1DetailAdditionalParityMode { get; }
|
public byte L1DetailAdditionalParityMode { get; }
|
||||||
public uint L1DetailTotalCells { get; }
|
public uint L1DetailTotalCells { get; }
|
||||||
public bool FirstSubMimo { get; }
|
public bool FirstSubMimo { get; }
|
||||||
public byte FirstSubMiso { get; }
|
public MisoSignallingFormat FirstSubMiso { get; }
|
||||||
public byte FirstSubFftSize { get; }
|
public FftSizeSignallingFormat FirstSubFftSize { get; }
|
||||||
public byte FirstSubReducedCarries { get; }
|
public byte FirstSubReducedCarries { get; }
|
||||||
public byte FirstSubGuardInterval { get; private set; }
|
public byte FirstSubGuardInterval { get; private set; }
|
||||||
public uint FirstSubNumOfdmSymbols { get; }
|
public uint FirstSubNumOfdmSymbols { get; }
|
||||||
@ -98,4 +101,5 @@ namespace skyscraper8.Atsc.A322
|
|||||||
AceOnly,
|
AceOnly,
|
||||||
TrAndAce
|
TrAndAce
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using skyscraper5.Skyscraper;
|
using skyscraper5.Skyscraper;
|
||||||
|
using skyscraper5.Skyscraper.IO;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -9,8 +10,307 @@ namespace skyscraper8.Atsc.A322
|
|||||||
{
|
{
|
||||||
internal class L1DetailSignalling : Validatable
|
internal class L1DetailSignalling : Validatable
|
||||||
{
|
{
|
||||||
public L1DetailSignalling(byte[] bytes)
|
public L1DetailSignalling(byte[] bytes, L1BasicSignalling basicSignalling)
|
||||||
{
|
{
|
||||||
|
InBitStream bitStream = new InBitStream(bytes);
|
||||||
|
this.Version = new Version(bitStream.ReadBitsAsByte(4), 0);
|
||||||
|
|
||||||
|
byte numRf = bitStream.ReadBitsAsByte(3);
|
||||||
|
RfIds = new ushort[numRf];
|
||||||
|
for (int i = 1; i < numRf; i++)
|
||||||
|
{
|
||||||
|
RfIds[i] = bitStream.ReadBitsAsUInt16(16);
|
||||||
|
bitStream.ReadBitsAsByte(3); //reserved
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (basicSignalling.TimeInfoFlag != 0)
|
||||||
|
{
|
||||||
|
uint secs = 0;
|
||||||
|
int msecs = 0;
|
||||||
|
int microsecs = 0;
|
||||||
|
int nanosecs = 0;
|
||||||
|
secs = bitStream.ReadBitsAsUint(32);
|
||||||
|
msecs = bitStream.ReadBitsAsUInt16(10);
|
||||||
|
if ((int)basicSignalling.TimeInfoFlag != 1)
|
||||||
|
{
|
||||||
|
microsecs = bitStream.ReadBitsAsUInt16(10);
|
||||||
|
if ((int)basicSignalling.TimeInfoFlag != 2)
|
||||||
|
{
|
||||||
|
nanosecs = bitStream.ReadBitsAsUInt16(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Subframes = new L1Subframe[basicSignalling.NumSubframes];
|
||||||
|
for (int i = 0; i < basicSignalling.NumSubframes; i++)
|
||||||
|
{
|
||||||
|
L1Subframe child = new L1Subframe();
|
||||||
|
Subframes[i] = child;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
child.Mimo = bitStream.ReadBitAsBoolean();
|
||||||
|
child.Miso = (MisoSignallingFormat)bitStream.ReadBitsAsByte(2);
|
||||||
|
child.FftSize = (FftSizeSignallingFormat)bitStream.ReadBitsAsByte(2);
|
||||||
|
child.ReducedCarriers = bitStream.ReadBitsAsByte(3);
|
||||||
|
child.GuardInterval = bitStream.ReadBitsAsByte(3);
|
||||||
|
child.NumOfdmSymbols = bitStream.ReadBitsAsUInt16(11);
|
||||||
|
child.ScatteredPilotPatern = bitStream.ReadBitsAsByte(5);
|
||||||
|
child.ScatteredPilotBoost = bitStream.ReadBitsAsByte(3);
|
||||||
|
child.SbsFirst = bitStream.ReadBitAsBoolean();
|
||||||
|
child.SbsLast = bitStream.ReadBitAsBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basicSignalling.NumSubframes > 0)
|
||||||
|
{
|
||||||
|
child.SubframeMultiplex = bitStream.ReadBitAsBoolean();
|
||||||
|
}
|
||||||
|
child.FrequencyInterleaver = bitStream.ReadBitAsBoolean();
|
||||||
|
|
||||||
|
if (((i == 0) && (basicSignalling.FirstSubSbsFirst || basicSignalling.FirstSubSbsLast)) || ((i > 0) && (child.SbsFirst | child.SbsLast)))
|
||||||
|
{
|
||||||
|
child.SbsNullCells = bitStream.ReadBitsAsUInt16(13);
|
||||||
|
}
|
||||||
|
byte numPlp = bitStream.ReadBitsAsByte(6);
|
||||||
|
child.Plps = new L1SubframePlp[numPlp];
|
||||||
|
|
||||||
|
for (int j = 0; j < numPlp; j++)
|
||||||
|
{
|
||||||
|
L1SubframePlp plp = new L1SubframePlp();
|
||||||
|
child.Plps[j] = plp;
|
||||||
|
|
||||||
|
plp.Id = bitStream.ReadBitsAsByte(6);
|
||||||
|
plp.LlsFlag = bitStream.ReadBitAsBoolean();
|
||||||
|
plp.Layer = bitStream.ReadBitsAsByte(2);
|
||||||
|
plp.Start = bitStream.ReadBitsAsUint(24);
|
||||||
|
plp.Size = bitStream.ReadBitsAsUint(24);
|
||||||
|
plp.ScramblerType = bitStream.ReadBitsAsByte(2);
|
||||||
|
plp.FecType = (PlpFecTypeSignallingFormat)bitStream.ReadBitsAsByte(4);
|
||||||
|
if (plp.NeedModCod())
|
||||||
|
{
|
||||||
|
plp.Mod = (PlpModSignallingFormat)bitStream.ReadBitsAsByte(4);
|
||||||
|
plp.Cod = (PlpCodSignallingFormat)bitStream.ReadBitsAsByte(4);
|
||||||
|
}
|
||||||
|
plp.TiMode = (PlpTiModeSignallingFormat)bitStream.ReadBitsAsByte(2);
|
||||||
|
if (plp.TiMode == PlpTiModeSignallingFormat.NoTimeInterleaving)
|
||||||
|
{
|
||||||
|
plp.FecBlockStart = bitStream.ReadBitsAsUInt16(15);
|
||||||
|
}
|
||||||
|
else if (plp.TiMode == PlpTiModeSignallingFormat.ConvolutionalTimeInterleaving)
|
||||||
|
{
|
||||||
|
plp.CtiFecBlockStart = bitStream.ReadBitsAsUint(22);
|
||||||
|
}
|
||||||
|
if (numRf > 0)
|
||||||
|
{
|
||||||
|
byte numChannelBonded = bitStream.ReadBitsAsByte(3);
|
||||||
|
if (numChannelBonded > 0)
|
||||||
|
{
|
||||||
|
plp.ChannelBondingFormat = (PlpChannelBondingFormatSignallingFormat)bitStream.ReadBitsAsByte(2);
|
||||||
|
plp.BondedRfId = new byte[numChannelBonded];
|
||||||
|
for (byte k = 0; k < numChannelBonded; k++)
|
||||||
|
{
|
||||||
|
plp.BondedRfId[k] = bitStream.ReadBitsAsByte(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((i == 0 && basicSignalling.FirstSubMimo) || (i > 0 && child.Mimo))
|
||||||
|
{
|
||||||
|
plp.MimoStreamCombining = bitStream.ReadBitAsBoolean();
|
||||||
|
plp.MimoIqInterleaving = bitStream.ReadBitAsBoolean();
|
||||||
|
plp.MimoPh = bitStream.ReadBitAsBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plp.Layer == 0)
|
||||||
|
{
|
||||||
|
plp.Type = bitStream.ReadBitAsBoolean();
|
||||||
|
if (plp.Type)
|
||||||
|
{
|
||||||
|
plp.NumSubslices = bitStream.ReadBitsAsUInt16(14);
|
||||||
|
plp.SubsliceInterval = bitStream.ReadBitsAsUint(24);
|
||||||
|
}
|
||||||
|
if (((plp.TiMode == PlpTiModeSignallingFormat.ConvolutionalTimeInterleaving) || (plp.TiMode == PlpTiModeSignallingFormat.HybridTimeInterleaving) && (plp.Mod == 0)))
|
||||||
|
{
|
||||||
|
plp.TiExtendedInterleaving = bitStream.ReadBitAsBoolean();
|
||||||
|
}
|
||||||
|
if (plp.TiMode == PlpTiModeSignallingFormat.ConvolutionalTimeInterleaving)
|
||||||
|
{
|
||||||
|
plp.CtiDepth = bitStream.ReadBitsAsByte(3);
|
||||||
|
plp.CtiStartRow = bitStream.ReadBitsAsUInt16(11);
|
||||||
|
}
|
||||||
|
else if (plp.TiMode == PlpTiModeSignallingFormat.HybridTimeInterleaving)
|
||||||
|
{
|
||||||
|
plp.HtiInterSubframe = bitStream.ReadBitAsBoolean();
|
||||||
|
byte htiNumTiBlocks = bitStream.ReadBitsAsByte(4);
|
||||||
|
plp.HtiNumFecBlocksMax = bitStream.ReadBitsAsUInt16(12);
|
||||||
|
if (!plp.HtiInterSubframe)
|
||||||
|
{
|
||||||
|
plp.HtiNumFecBlocksMax = bitStream.ReadBitsAsUInt16(12);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plp.HtiNumFecBlocks = new ushort[htiNumTiBlocks];
|
||||||
|
for (byte k = 0; k < htiNumTiBlocks; k++)
|
||||||
|
{
|
||||||
|
plp.HtiNumFecBlocks[k] = bitStream.ReadBitsAsUInt16(12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plp.HtiCellInterleaver = bitStream.ReadBitAsBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plp.LdmInjectionLevel = bitStream.ReadBitsAsByte(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Bsid = bitStream.ReadBitsAsUInt16(16);
|
||||||
|
for (int i = 0; i < basicSignalling.NumSubframes; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
Subframes[i].MimoMixed = bitStream.ReadBitAsBoolean();
|
||||||
|
}
|
||||||
|
if ((i == 0 && basicSignalling.FirstSubMimoMixed) || (i > 0 || Subframes[i].MimoMixed))
|
||||||
|
{
|
||||||
|
for (int j = 0; j < Subframes[i].Plps.Length; j++)
|
||||||
|
{
|
||||||
|
Subframes[i].Plps[j].Mimo = bitStream.ReadBitAsBoolean();
|
||||||
|
if (Subframes[i].Plps[j].Mimo)
|
||||||
|
{
|
||||||
|
Subframes[i].Plps[j].MimoStreamCombining = bitStream.ReadBitAsBoolean();
|
||||||
|
Subframes[i].Plps[j].MimoIqInterleaving = bitStream.ReadBitAsBoolean();
|
||||||
|
Subframes[i].Plps[j].MimoPh = bitStream.ReadBitAsBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Version Version { get; }
|
||||||
|
public ushort[] RfIds { get; private set; }
|
||||||
|
public L1Subframe[] Subframes { get; private set; }
|
||||||
|
public ushort Bsid { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class L1SubframePlp
|
||||||
|
{
|
||||||
|
public byte Id { get; internal set; }
|
||||||
|
public bool LlsFlag { get; internal set; }
|
||||||
|
public byte Layer { get; internal set; }
|
||||||
|
public uint Start { get; internal set; }
|
||||||
|
public uint Size { get; internal set; }
|
||||||
|
public byte ScramblerType { get; internal set; }
|
||||||
|
public PlpFecTypeSignallingFormat FecType { get; internal set; }
|
||||||
|
public PlpModSignallingFormat Mod { get; internal set; }
|
||||||
|
public PlpCodSignallingFormat Cod { get; internal set; }
|
||||||
|
public PlpTiModeSignallingFormat TiMode { get; internal set; }
|
||||||
|
public ushort FecBlockStart { get; internal set; }
|
||||||
|
public uint CtiFecBlockStart { get; internal set; }
|
||||||
|
public PlpChannelBondingFormatSignallingFormat ChannelBondingFormat { get; internal set; }
|
||||||
|
public byte[] BondedRfId { get; internal set; }
|
||||||
|
public bool MimoStreamCombining { get; internal set; }
|
||||||
|
public bool MimoIqInterleaving { get; internal set; }
|
||||||
|
public bool MimoPh { get; internal set; }
|
||||||
|
public bool Type { get; internal set; }
|
||||||
|
public ushort NumSubslices { get; internal set; }
|
||||||
|
public uint SubsliceInterval { get; internal set; }
|
||||||
|
public bool TiExtendedInterleaving { get; internal set; }
|
||||||
|
public byte CtiDepth { get; internal set; }
|
||||||
|
public ushort CtiStartRow { get; internal set; }
|
||||||
|
public bool HtiInterSubframe { get; internal set; }
|
||||||
|
public ushort HtiNumFecBlocksMax { get; internal set; }
|
||||||
|
public ushort[] HtiNumFecBlocks { get; internal set; }
|
||||||
|
public bool HtiCellInterleaver { get; internal set; }
|
||||||
|
public byte LdmInjectionLevel { get; internal set; }
|
||||||
|
public bool Mimo { get; internal set; }
|
||||||
|
|
||||||
|
internal bool NeedModCod()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class L1Subframe
|
||||||
|
{
|
||||||
|
public bool Mimo { get; internal set; }
|
||||||
|
public MisoSignallingFormat Miso { get; internal set; }
|
||||||
|
public FftSizeSignallingFormat FftSize { get; internal set; }
|
||||||
|
public byte ReducedCarriers { get; internal set; }
|
||||||
|
public byte GuardInterval { get; internal set; }
|
||||||
|
public ushort NumOfdmSymbols { get; internal set; }
|
||||||
|
public byte ScatteredPilotPatern { get; internal set; }
|
||||||
|
public byte ScatteredPilotBoost { get; internal set; }
|
||||||
|
public bool SbsFirst { get; internal set; }
|
||||||
|
public bool SbsLast { get; internal set; }
|
||||||
|
public bool SubframeMultiplex { get; internal set; }
|
||||||
|
public bool FrequencyInterleaver { get; internal set; }
|
||||||
|
public ushort SbsNullCells { get; internal set; }
|
||||||
|
public L1SubframePlp[] Plps { get; internal set; }
|
||||||
|
public bool MimoMixed { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MisoSignallingFormat
|
||||||
|
{
|
||||||
|
NoMiso,
|
||||||
|
_64Coefficients,
|
||||||
|
_256Coefficients,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FftSizeSignallingFormat
|
||||||
|
{
|
||||||
|
_8k,
|
||||||
|
_16k,
|
||||||
|
_32k,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlpFecTypeSignallingFormat
|
||||||
|
{
|
||||||
|
Bch16kLdpc,
|
||||||
|
Bch64kLdpc,
|
||||||
|
Crc16kLdpc,
|
||||||
|
Crc64kLdpc,
|
||||||
|
_16kLdpc,
|
||||||
|
_64kLdpc,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlpModSignallingFormat
|
||||||
|
{
|
||||||
|
Qpsk,
|
||||||
|
_16QAM,
|
||||||
|
_64QAM,
|
||||||
|
_256QAM,
|
||||||
|
_1024QAM,
|
||||||
|
_4096Q
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlpCodSignallingFormat
|
||||||
|
{
|
||||||
|
_2_15,
|
||||||
|
_3_15,
|
||||||
|
_4_15,
|
||||||
|
_5_15,
|
||||||
|
_6_15,
|
||||||
|
_7_15,
|
||||||
|
_8_15,
|
||||||
|
_9_15,
|
||||||
|
_10_15,
|
||||||
|
_11_15,
|
||||||
|
_12_15,
|
||||||
|
_13_15,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlpTiModeSignallingFormat
|
||||||
|
{
|
||||||
|
NoTimeInterleaving,
|
||||||
|
ConvolutionalTimeInterleaving,
|
||||||
|
HybridTimeInterleaving
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlpChannelBondingFormatSignallingFormat
|
||||||
|
{
|
||||||
|
PlainChannelBonding,
|
||||||
|
SnrAveragedChannelBonding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -115,7 +115,7 @@ namespace skyscraper8.Atsc.A324
|
|||||||
}
|
}
|
||||||
else if (plp == 65)
|
else if (plp == 65)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("desynced timing and management");
|
DesyncTimingAndManagement();
|
||||||
}
|
}
|
||||||
else if (plp <= 63)
|
else if (plp <= 63)
|
||||||
{
|
{
|
||||||
@ -126,7 +126,18 @@ namespace skyscraper8.Atsc.A324
|
|||||||
throw new NotImplementedException(String.Format("Unknown PLP: {0}", plp));
|
throw new NotImplementedException(String.Format("Unknown PLP: {0}", plp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
plpSequenceNumbers[plp] = rtpPacket.RtpSequenceNumber;
|
||||||
|
plpSequenceNumbers[plp]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimingAndManagementPacket timingAndManagement;
|
||||||
|
|
||||||
|
private void DesyncTimingAndManagement()
|
||||||
|
{
|
||||||
|
if (timingAndManagement != null)
|
||||||
|
{
|
||||||
|
timingAndManagement.Valid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DesyncPreamble()
|
private void DesyncPreamble()
|
||||||
@ -153,7 +164,7 @@ namespace skyscraper8.Atsc.A324
|
|||||||
|
|
||||||
private void HandleTimingAndManagementData(byte[] rtpPayload)
|
private void HandleTimingAndManagementData(byte[] rtpPayload)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
timingAndManagement = new TimingAndManagementPacket(rtpPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PreambleData preambleData;
|
private PreambleData preambleData;
|
||||||
|
|||||||
@ -30,7 +30,7 @@ namespace skyscraper8.Atsc.A324
|
|||||||
}
|
}
|
||||||
|
|
||||||
long detailLength = expectedLength - 25;
|
long detailLength = expectedLength - 25;
|
||||||
DetailSignalling = new L1DetailSignalling(ms.ReadBytes(detailLength));
|
DetailSignalling = new L1DetailSignalling(ms.ReadBytes(detailLength), BasicSignalling);
|
||||||
Valid = DetailSignalling.Valid;
|
Valid = DetailSignalling.Valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
128
skyscraper8/Atsc/A324/TImingAndManagementPacket.cs
Normal file
128
skyscraper8/Atsc/A324/TImingAndManagementPacket.cs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
using skyscraper5.Skyscraper;
|
||||||
|
using skyscraper5.Skyscraper.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.Atsc.A324
|
||||||
|
{
|
||||||
|
internal class TimingAndManagementPacket : Validatable
|
||||||
|
{
|
||||||
|
public TimingAndManagementPacket(byte[] rtpPayload)
|
||||||
|
{
|
||||||
|
//STRUCTURE DATA
|
||||||
|
InBitStream bitStream = new InBitStream(rtpPayload);
|
||||||
|
ushort length = bitStream.ReadBitsAsUInt16(16);
|
||||||
|
if (length != rtpPayload.Length)
|
||||||
|
{
|
||||||
|
Valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte versionMajor = bitStream.ReadBitsAsByte(4);
|
||||||
|
byte versionMinor = bitStream.ReadBitsAsByte(4);
|
||||||
|
this.Version = new Version(versionMajor, versionMinor);
|
||||||
|
|
||||||
|
MajLogRepCntPre = bitStream.ReadBitsAsByte(4);
|
||||||
|
MajLogRepCntTim = bitStream.ReadBitsAsByte(4);
|
||||||
|
|
||||||
|
byte bootstrapMajor = bitStream.ReadBitsAsByte(4);
|
||||||
|
byte bootstrapMinor = bitStream.ReadBitsAsByte(4);
|
||||||
|
this.Bootstrap = new Version(bootstrapMajor, bootstrapMinor);
|
||||||
|
|
||||||
|
MinTimeToNext = bitStream.ReadBitsAsByte(5);
|
||||||
|
SystemBandwidth = bitStream.ReadBitsAsByte(2);
|
||||||
|
BsrCoefficient = bitStream.ReadBitsAsByte(7);
|
||||||
|
PreambleStructure = bitStream.ReadBitsAsByte(8);
|
||||||
|
EaWakeup = bitStream.ReadBitsAsByte(2);
|
||||||
|
byte numEmissionTim = bitStream.ReadBitsAsByte(6);
|
||||||
|
byte numXmtrsInGroupMinus1 = bitStream.ReadBitsAsByte(6);
|
||||||
|
XmtrGroupNum = bitStream.ReadBitsAsByte(7);
|
||||||
|
MajLogOverride = bitStream.ReadBitsAsByte(3);
|
||||||
|
NumMisoFiltCodes = bitStream.ReadBitsAsByte(2);
|
||||||
|
TxCarrierOffset = bitStream.ReadBitsAsByte(2);
|
||||||
|
MimoFlag = bitStream.ReadBitAsBoolean();
|
||||||
|
bitStream.ReadBitsAsByte(6); //reserved
|
||||||
|
|
||||||
|
//BOOTSTRAP TIMING DATA
|
||||||
|
EmissionTim = new TimeSpan[numEmissionTim];
|
||||||
|
for (int i = 0; i < numEmissionTim; i++)
|
||||||
|
{
|
||||||
|
uint seconds = bitStream.ReadBitsAsUint(32);
|
||||||
|
uint nanoseconds = bitStream.ReadBitsAsUint(32);
|
||||||
|
long microsecs = nanoseconds / 1000;
|
||||||
|
EmissionTim[i] = new TimeSpan(0, 0, 0, (int)seconds, 0, (int)microsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//PER TRANSMITTER DATA
|
||||||
|
for (int i = 0; i <= numXmtrsInGroupMinus1; i++)
|
||||||
|
{
|
||||||
|
int intMimoFlag = MimoFlag ? 1 : 0;
|
||||||
|
for (int j = 0; j <= intMimoFlag; j++)
|
||||||
|
{
|
||||||
|
if (PerTransmitterData == null)
|
||||||
|
PerTransmitterData = new PerTransmitPolarizationData[numXmtrsInGroupMinus1 + 1][];
|
||||||
|
if (PerTransmitterData[i] == null)
|
||||||
|
PerTransmitterData[i] = new PerTransmitPolarizationData[intMimoFlag + 1];
|
||||||
|
|
||||||
|
PerTransmitPolarizationData child = new PerTransmitPolarizationData();
|
||||||
|
PerTransmitterData[i][j] = child;
|
||||||
|
|
||||||
|
child.XmtrId = bitStream.ReadBitsAsUInt16(13);
|
||||||
|
if (j == 0)
|
||||||
|
{
|
||||||
|
child.TxTimeOffset = bitStream.ReadBitsAsUInt16(16);
|
||||||
|
}
|
||||||
|
child.TxIdInjectionLevel = bitStream.ReadBitsAsUint(4);
|
||||||
|
child.MisoFiltCodeIndex = bitStream.ReadBitsAsByte(2);
|
||||||
|
}
|
||||||
|
if (!MimoFlag)
|
||||||
|
{
|
||||||
|
bitStream.ReadBitsAsUint(29);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitStream.ReadBitsAsUint(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//PACKET RELEASE TIME
|
||||||
|
byte pktRlsSeconds = bitStream.ReadBitsAsByte(4);
|
||||||
|
ushort pktRlsAMilliseconds = bitStream.ReadBitsAsUInt16(10);
|
||||||
|
PktRls = new TimeSpan(0, 0, 0, pktRlsSeconds, pktRlsAMilliseconds);
|
||||||
|
bitStream.SkipBits(2);
|
||||||
|
|
||||||
|
//ERROR CHECK DATA
|
||||||
|
ushort crc16 = bitStream.ReadBitsAsUInt16(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Version Version { get; }
|
||||||
|
public byte MajLogRepCntPre { get; }
|
||||||
|
public byte MajLogRepCntTim { get; }
|
||||||
|
public Version Bootstrap { get; }
|
||||||
|
public byte MinTimeToNext { get; }
|
||||||
|
public byte SystemBandwidth { get; }
|
||||||
|
public byte BsrCoefficient { get; }
|
||||||
|
public byte PreambleStructure { get; }
|
||||||
|
public byte EaWakeup { get; }
|
||||||
|
public byte XmtrGroupNum { get; }
|
||||||
|
public byte MajLogOverride { get; }
|
||||||
|
public byte NumMisoFiltCodes { get; }
|
||||||
|
public byte TxCarrierOffset { get; }
|
||||||
|
public bool MimoFlag { get; }
|
||||||
|
public TimeSpan[] EmissionTim { get; }
|
||||||
|
|
||||||
|
public PerTransmitPolarizationData[][] PerTransmitterData { get; }
|
||||||
|
public TimeSpan PktRls { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PerTransmitPolarizationData
|
||||||
|
{
|
||||||
|
public ushort XmtrId { get; internal set; }
|
||||||
|
public ushort TxTimeOffset { get; internal set; }
|
||||||
|
public uint TxIdInjectionLevel { get; internal set; }
|
||||||
|
public byte MisoFiltCodeIndex { get; internal set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,6 +32,15 @@ namespace skyscraper8.Atsc.A330
|
|||||||
public bool? HeaderMode { get; }
|
public bool? HeaderMode { get; }
|
||||||
public bool? SegmentationConcatenation { get; }
|
public bool? SegmentationConcatenation { get; }
|
||||||
public int Length { get; }
|
public int Length { get; }
|
||||||
|
public int ConcatLengthMsb { get; internal set; }
|
||||||
|
public int Count { get; internal set; }
|
||||||
|
public bool SIF { get; internal set; }
|
||||||
|
public int Length2 { get; internal set; }
|
||||||
|
|
||||||
|
internal void ParseConcatenationHeaderLengths(byte[]? neededBuffer)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AlpPacketType
|
enum AlpPacketType
|
||||||
|
|||||||
@ -110,12 +110,12 @@ namespace skyscraper5.Skyscraper.IO
|
|||||||
|
|
||||||
public byte[] ReadBitsAsByteArray(uint v)
|
public byte[] ReadBitsAsByteArray(uint v)
|
||||||
{
|
{
|
||||||
byte[] result = new byte[v / 8];
|
byte[] result = new byte[(v / 8) + 1];
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
while (v > 0)
|
while (v > 0)
|
||||||
{
|
{
|
||||||
uint nextSize = Math.Min(8, v);
|
byte nextSize = Math.Min((byte)8, (byte)v);
|
||||||
result[offset++] = ReadBitsAsByte(8);
|
result[offset++] = ReadBitsAsByte(nextSize);
|
||||||
v -= nextSize;
|
v -= nextSize;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -125,7 +125,7 @@ namespace skyscraper5.Skyscraper.IO
|
|||||||
|
|
||||||
public long GetBitsAvailable()
|
public long GetBitsAvailable()
|
||||||
{
|
{
|
||||||
long result = _wrapped.GetAvailableBytes();
|
long result = _wrapped.GetAvailableBytes() * 8;
|
||||||
result += (8 - bitPointer);
|
result += (8 - bitPointer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user