private void ValidateTable(BitSplitter bs) { int pointer = (int)bs.GetInteger(8); if (pointer != 0) { throw new DemuxException("Non-zero pointers are not currently supported"); } int table_id = (int)bs.GetInteger(8); if (table_id != 0x02) { throw new DemuxException("Wrong table ID for PMT"); } SectionSyntax = bs.GetFlag(); if (!SectionSyntax) { throw new DemuxException("Invalid PMT: incorrect section syntax"); } bool zero = bs.GetFlag(); if (zero) { throw new DemuxException("Invalid PMT: zero bit wasn't zero"); } }
private void ReadTransportHeader(BitSplitter bs) { bs.SkipToNextByte(); // Sync byte Error = bs.GetFlag(); StartIndicator = bs.GetFlag(); HighPriority = bs.GetFlag(); PID = (int)bs.GetInteger(13); ScrambleCode = (int)bs.GetInteger(2); HasAdaptionField = bs.GetFlag(); HasPayload = bs.GetFlag(); Counter = (int)bs.GetInteger(4); }
private void CheckAdaptionField(BitSplitter bs) { if (HasAdaptionField) { int adaption_end = (int)bs.GetInteger(8); adaption_end += bs.ByteOffset; Discont = bs.GetFlag(); KeyFrame = bs.GetFlag(); ES_Prio = bs.GetFlag(); HasPCR = bs.GetFlag(); HasOPCR = bs.GetFlag(); HasSplice = bs.GetFlag(); PrivateFlag = bs.GetFlag(); AdapExtFlag = bs.GetFlag(); if (bs.BitOffset != 0) { throw new Exception("bit align problem"); } if (HasPCR) { PCR = (long)bs.GetInteger(33); bs.SkipBits(15); // throw away useless sync stuff. } if (HasOPCR) { bs.SkipBits(48); // throw away useless "old" timecode } if (HasSplice) { bs.SkipBits(8); // throw away splice counter } if (PrivateFlag) { int priv_len = (int)bs.GetInteger(8); bs.SkipBytes(priv_len); // skip private data } // ignore the rest of the adaption field (it's mostly to support stuff we ignore) int skip_len = adaption_end - bs.ByteOffset; bs.SkipBytes(skip_len); } }
private int SectionNumber, LastSection; // should always be zero /// <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 PAT(byte[] RawPayload) { Map = new Dictionary <int, int>(); BitSplitter bs = new BitSplitter(RawPayload); ValidateTable(bs); bs.SkipBits(2); // reserved; SectionLength = (int)bs.GetInteger(12); TransportID = (int)bs.GetInteger(16); bs.SkipBits(2); // reserved Version = (int)bs.GetInteger(5); IsCurrent = bs.GetFlag(); SectionNumber = (int)bs.GetInteger(8); LastSection = (int)bs.GetInteger(8); int bits_left = (SectionLength - 5) - 4; // remaining length in bytes, excluding CRC int items = bits_left / 4; for (int i = 0; i < items; i++) { int prog = (int)bs.GetInteger(16); bs.SkipBits(3); int pid = (int)bs.GetInteger(13); if (!Map.ContainsKey(prog)) { Map.Add(prog, pid); } else { throw new DemuxException("Invalid PAT: program number specified more than once (" + prog + ")"); } } // Ignoring CRC. }
/// <summary> /// Reads the long list of flags in the default PES header. /// </summary> private void ReadFlags(BitSplitter bs) { ScrambleControl = (int)bs.GetInteger(2); HighPriority = bs.GetFlag(); HasAlignment = bs.GetFlag(); IsCopyright = bs.GetFlag(); IsOriginal = bs.GetFlag(); HasPTS = bs.GetFlag(); HasDTS = bs.GetFlag(); if (HasDTS && !HasPTS) { throw new DemuxException("Invalid PES: DTS without PTS is not allowed"); } HasESCR = bs.GetFlag(); HasEsRate = bs.GetFlag(); UsesTrickMode = bs.GetFlag(); MoreCopyright = bs.GetFlag(); HasPesCRC = bs.GetFlag(); HasPesExtension = bs.GetFlag(); }
/// <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. }