/// <summary>
/// Digest a packet payload into structured table. Payload should be from the pointer field onward.
/// Does not yet handle multi-packet tables
/// </summary>
public PMT(byte[] RawPayload)
{
BitSplitter bs = new BitSplitter(RawPayload);
Map = new Dictionary<int, int>();
ReverseMap = new Dictionary<StreamType, int>();
ValidateTable(bs);
bs.SkipBits(2);
SectionLength = (int)bs.GetInteger(12); // total length after this, in bytes; includes 4 byte CRC.
ProgramNumber = (int)bs.GetInteger(16);
bs.SkipBits(2);
Version = (int)bs.GetInteger(5);
IsCurrent = bs.GetFlag();
SectionNumber = (int)bs.GetInteger(8);
LastSection = (int)bs.GetInteger(8);
bs.SkipBits(3);
PCR_PID = (int)bs.GetInteger(13); // Either the PID of a channel timecode stream, or 0x1FFF for none.
bs.SkipBits(4);
ProgInfoLength = (int)bs.GetInteger(12); // number of bytes of descriptors.
if (bs.BitOffset != 0) throw new DemuxException("Byte alignment error (internal)");
bs.SkipBytes(ProgInfoLength); // ignore descriptors.
int info_bytes = (SectionLength - ProgInfoLength) - 13; // bytes of descriptor.
while (info_bytes > 0) { // descriptions can be variable length
int stream_type = (int)bs.GetInteger(8);
bs.SkipBits(3);
int pid = (int)bs.GetInteger(13);
bs.SkipBits(4);
if (!Map.ContainsKey(pid)) Map.Add(pid, stream_type); // more complete map of pid types
else throw new DemuxException("Invalid PMT: PID specified more than once");
StreamType st = DecodeStreamType(stream_type);
if (!ReverseMap.ContainsKey(st)) ReverseMap.Add(st, pid); // store first pid of each type
int es_info_length = (int)bs.GetInteger(12);
bs.SkipBytes(es_info_length);
info_bytes -= 5 + es_info_length;
}
if (bs.BitOffset != 0) throw new DemuxException("Invalid PMT: program info length didn't match data");
// ignoring CRC.
}