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 void DecodeElementaryStream(BitSplitter bs) { int marker = (int)bs.GetInteger(2); if (marker != 2) { throw new DemuxException("Invalid PES: first marker missing"); } ReadFlags(bs); if (bs.BitOffset != 0) { throw new DemuxException("Alignment problem in PES (internal)"); } HeaderLength = (int)bs.GetInteger(8); int head_start = bs.ByteOffset; if (HasPTS && HasDTS) { ReadDTS_PTS(bs); } else if (HasPTS) { ReadPTS(bs); } if (HasESCR) { bs.SkipBytes(6); // not currently used. } if (HasEsRate) { bs.SkipBits(24); // not currently used. } if (UsesTrickMode) { bs.SkipBytes(1); // ignored } if (MoreCopyright) { bs.SkipBytes(1); // ignored } if (HasPesCRC) { bs.SkipBytes(2); // ignored } if (HasPesExtension) { ReadExtendedHeader(bs); } // skip anything that's left int head_end = bs.ByteOffset; int to_skip = HeaderLength - (head_end - head_start); if (to_skip < 0) { throw new DemuxException("Invalid PES: declared header length did not match measured length"); } bs.SkipBytes(to_skip); // Now, the remaining bytes are data and padding int data_length = PacketLength - (HeaderLength + to_skip); if (data_length > 3) { data_length -= 3; // no idea where the '3' is coming from... } byte[] data = bs.RemainingBytes(); if (PacketLength == 0) // video is allowed to not specify { data_length = data.Length; } #if DEBUG if (data.Length < data_length) { throw new DemuxException("Invalid PES: packet shorter than described"); } if (data_length < 0) { throw new DemuxException("Invalid PES: Negative packet length"); } #else if (data.Length < data_length || data_length < 0) { data_length = 0; } #endif MemoryStream ms = new MemoryStream(data, 0, data_length); FrameData = ms.ToArray(); }
/// <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. }