public void AddPacket(TsPacket newPacket) { try { if (newPacket.Pid != Pid) throw new InvalidOperationException("Cannot add TS Packet from different pid to a metric!"); if (newPacket.TransportErrorIndicator) { OnTransportErrorIndicatorDetected(newPacket.Pid); } else { CheckCcContinuity(newPacket); LastCc = newPacket.ContinuityCounter; } PacketCount++; _periodPacketCount++; } catch (Exception ex) { Debug.WriteLine("Exception generated within AddPacket method: " + ex.Message); } }
public Pes(TsPacket packet) { PacketStartCodePrefix = (uint)((packet.PesHeader.Payload[0] << 16) + (packet.PesHeader.Payload[1] << 8) + packet.PesHeader.Payload[2]); StreamId = packet.PesHeader.Payload[3]; PesPacketLength = (ushort)((packet.PesHeader.Payload[4] << 8) + packet.PesHeader.Payload[5]); _data = new byte[PesPacketLength + 6]; Buffer.BlockCopy(packet.PesHeader.Payload, 0, _data, _pesBytes, packet.PesHeader.Payload.Length); _pesBytes += (ushort)(packet.PesHeader.Payload.Length); Buffer.BlockCopy(packet.Payload, 0, _data, _pesBytes, packet.Payload.Length); _pesBytes += (ushort)(packet.Payload.Length); }
public void AddPacket(TsPacket packet) { CheckPid(packet.Pid); if (!packet.PayloadUnitStartIndicator) return; InProgressTable = new ProgramAssociationTable {PointerField = packet.Payload[0]}; if (InProgressTable.PointerField > packet.Payload.Length) { Debug.Assert(true, "Program Association TableOld has packet pointer outside the packet."); } var pos = 1 + InProgressTable.PointerField; InProgressTable.VersionNumber = (byte) (packet.Payload[pos + 5] & 0x3E); if (ProgramAssociationTable != null && ProgramAssociationTable.VersionNumber == InProgressTable.VersionNumber) { InProgressTable = null; return; } InProgressTable.TableId = packet.Payload[pos]; InProgressTable.SectionLength = (short)(((packet.Payload[pos + 1] & 0x3) << 8) + packet.Payload[pos + 2]); InProgressTable.TransportStreamId = (short)((packet.Payload[pos + 3] << 8) + packet.Payload[pos + 4]); InProgressTable.CurrentNextIndicator = (packet.Payload[pos + 5] & 0x1) != 0; InProgressTable.SectionNumber = packet.Payload[pos + 6]; InProgressTable.LastSectionNumber = packet.Payload[pos + 7]; InProgressTable.ProgramNumbers = new short[(InProgressTable.SectionLength - 9)/4]; InProgressTable.Pids = new short[(InProgressTable.SectionLength - 9)/4]; var programStart = pos + 8; for (var i = 0; i < (InProgressTable.SectionLength - 9)/4; i++) { InProgressTable.ProgramNumbers[i] = (short) ((packet.Payload[programStart + (i*4)] << 8) + packet.Payload[programStart + 1 + (i*4)]); InProgressTable.Pids[i] = (short) (((packet.Payload[programStart + 2 + (i*4)] & 0x1F) << 8) + packet.Payload[programStart + 3 + (i*4)]); } ProgramAssociationTable = InProgressTable; OnTableChangeDetected(); }
public void AddPacket(TsPacket packet) { CheckPid(packet.Pid); if (packet.PayloadUnitStartIndicator) { InProgressTable = new ProgramMapTable { Pid = packet.Pid, PointerField = packet.Payload[0] }; if (InProgressTable.PointerField > packet.Payload.Length) { Debug.Assert(true, "Program Map Table has packet pointer outside the packet."); } var pos = 1 + InProgressTable.PointerField; InProgressTable.VersionNumber = (byte)(packet.Payload[pos + 5] & 0x3E); if (ProgramMapTable?.VersionNumber == InProgressTable.VersionNumber) { InProgressTable = null; return; } InProgressTable.TableId = packet.Payload[pos]; InProgressTable.SectionLength = (short)(((packet.Payload[pos + 1] & 0x3) << 8) + packet.Payload[pos + 2]); InProgressTable.ProgramNumber = (ushort)((packet.Payload[pos + 3] << 8) + packet.Payload[pos + 4]); InProgressTable.CurrentNextIndicator = (packet.Payload[pos + 5] & 0x1) != 0; InProgressTable.SectionNumber = packet.Payload[pos + 6]; InProgressTable.LastSectionNumber = packet.Payload[pos + 7]; InProgressTable.PcrPid = (ushort)(((packet.Payload[pos + 8] & 0x1f) << 8) + packet.Payload[pos + 9]); InProgressTable.ProgramInfoLength = (ushort)(((packet.Payload[pos + 10] & 0x3) << 8) + packet.Payload[pos + 11]); } if (InProgressTable == null) return; AddData(packet); if (!HasAllBytes()) return; var startOfNextField = GetDescriptors(InProgressTable.ProgramInfoLength, InProgressTable.PointerField + 13); InProgressTable.EsStreams = ReadEsInfoElements(InProgressTable.SectionLength, startOfNextField); ProgramMapTable = InProgressTable; OnTableChangeDetected(); }
private void CheckCcContinuity(TsPacket newPacket) { try { if (PacketCount == 0) { //fresh metric, first packet - so no possible error yet... return; } if (newPacket.Pid == 0x1fff) return; if (LastCc == newPacket.ContinuityCounter) { if (newPacket.ContainsPayload) { CcErrorCount++; _periodCcErrorCount++; } //special case of no data... ignore for now //TODO: check for no data flag in original packet Debug.Assert(true, "Special CC repeated case - requires investigation!"); return; } if (LastCc != 15) { if (LastCc + 1 != newPacket.ContinuityCounter) { CcErrorCount++; _periodCcErrorCount++; OnDiscontinuityDetected(newPacket.Pid); return; } } if (LastCc != 15 || newPacket.ContinuityCounter == 0) return; CcErrorCount++; _periodCcErrorCount++; OnDiscontinuityDetected(newPacket.Pid); } catch (Exception ex) { Debug.WriteLine("Exception generated within CheckCcContinuity method: " + ex.Message); } }
public bool Add(TsPacket packet) { if (packet.PayloadUnitStartIndicator) return false; if ((PesPacketLength + 6 - _pesBytes) > packet.Payload.Length) { Buffer.BlockCopy(packet.Payload, 0, _data, _pesBytes, packet.Payload.Length); _pesBytes += (ushort)(packet.Payload.Length); } else { Buffer.BlockCopy(packet.Payload, 0, _data, _pesBytes, (PesPacketLength + 6 - _pesBytes)); _pesBytes += (ushort)(PesPacketLength + 6 - _pesBytes); } return true; }
protected void AddData(TsPacket packet) { CheckPid(packet.Pid); if (packet.PayloadUnitStartIndicator) { Data = new byte[InProgressTable.SectionLength + 3]; _tableBytes = 0; } if ((InProgressTable.SectionLength + 3 - _tableBytes) > packet.Payload.Length) { Buffer.BlockCopy(packet.Payload, 0, Data, _tableBytes, packet.Payload.Length); _tableBytes += (ushort)(packet.Payload.Length); } else { Buffer.BlockCopy(packet.Payload, 0, Data, _tableBytes, (InProgressTable.SectionLength + 3 - _tableBytes)); _tableBytes += (ushort)(InProgressTable.SectionLength + 3 - _tableBytes); } }
public void AddPacket(TsDecoder.TransportStream.TsDecoder tsDecoder, TsPacket tsPacket) { if (_currentTeletextDescriptor == null) { Setup(tsDecoder); if (_currentTeletextDescriptor != null) { Debug.WriteLine($"Locked onto teletext PID for {TeletextPid} "); } } if (tsPacket.Pid != TeletextPid) return; if (tsPacket.PayloadUnitStartIndicator) { if (_currentTeletextPes != null) { if (_currentTeletextPes.HasAllBytes()) { _currentTeletextPes.Decode(); foreach (var key in _teletextSubtitlePage.Keys) { _teletextSubtitlePage[key].DecodeTeletextData(_currentTeletextPes); } } } _currentTeletextPes = new Pes(tsPacket); } else { _currentTeletextPes?.Add(tsPacket); } }
public void AddPacket(TsPacket packet) { CheckPid(packet.Pid); if (packet.PayloadUnitStartIndicator) { InProgressTable = new ServiceDescriptionTable { Pid = packet.Pid, PointerField = packet.Payload[0] }; if (InProgressTable.PointerField > packet.Payload.Length) { Debug.Assert(true, "Service Description Table has packet pointer outside the packet."); } var pos = 1 + InProgressTable.PointerField; InProgressTable.VersionNumber = (byte)(packet.Payload[pos + 5] & 0x3E); InProgressTable.TableId = packet.Payload[pos]; //TODO: Refactor with enum for well-known table IDs, and add option below as filter if (InProgressTable.TableId != 0x42) { InProgressTable = null; return; } if (ServiceDescriptionTable?.VersionNumber != InProgressTable.VersionNumber) { //if the version number of any section jumps, we need to refresh _sectionsCompleted = new HashSet<int>(); ServiceDescriptionItems = new List<ServiceDescriptionItem>(); } InProgressTable.SectionLength = (short)(((packet.Payload[pos + 1] & 0x3) << 8) + packet.Payload[pos + 2]); InProgressTable.TransportStreamId = (ushort)((packet.Payload[pos + 3] << 8) + packet.Payload[pos + 4]); InProgressTable.CurrentNextIndicator = (packet.Payload[pos + 5] & 0x1) != 0; InProgressTable.SectionNumber = packet.Payload[pos + 6]; InProgressTable.LastSectionNumber = packet.Payload[pos + 7]; InProgressTable.OriginalNetworkId = (ushort)((packet.Payload[pos + 8] << 8) + packet.Payload[pos + 9]); } if (InProgressTable == null) return; if (_sectionsCompleted.Contains(InProgressTable.SectionNumber)) { InProgressTable = null; return; } AddData(packet); if (!HasAllBytes()) return; var startOfNextField = (ushort)(InProgressTable.PointerField + 12); var transportStreamLoopEnd = (ushort)(InProgressTable.SectionLength - 4); var items = new List<ServiceDescriptionItem>(); while (startOfNextField < transportStreamLoopEnd) { var item = new ServiceDescriptionItem { ServiceId = (ushort)((Data[startOfNextField] << 8) + Data[startOfNextField + 1]), EitScheduleFlag = ((Data[startOfNextField + 2]) & 0x02) == 0x02, EitPresentFollowingFlag = ((Data[startOfNextField + 2]) & 0x01) == 0x01, RunningStatus = (byte)((Data[startOfNextField + 3] >> 5) & 0x07), FreeCaMode = (Data[startOfNextField + 3] & 0x10) == 0x10, DescriptorsLoopLength = (ushort)(((Data[startOfNextField + 3] & 0xf) << 8) + Data[startOfNextField + 4]) }; var descriptors = new List<Descriptor>(); startOfNextField = (ushort)(startOfNextField + 5); var endOfDescriptors = (ushort)(startOfNextField + item.DescriptorsLoopLength); if (endOfDescriptors > Data.Length) { throw new InvalidDataException("Descriptor data in Service Description is marked beyond available data"); } while (startOfNextField < endOfDescriptors) { var des = DescriptorFactory.DescriptorFromData(Data, startOfNextField); descriptors.Add(des); startOfNextField += (ushort)(des.DescriptorLength + 2); } item.Descriptors = descriptors; items.Add(item); } InProgressTable.Items = items; ServiceDescriptionItems.AddRange(items); ServiceDescriptionTable = InProgressTable; _sectionsCompleted.Add(InProgressTable.SectionNumber); OnTableChangeDetected(); }
public static TsPacket[] GetTsPacketsFromData(byte[] data) { try { var maxPackets = (data.Length) / TsPacketSize; var tsPackets = new TsPacket[maxPackets]; var start = FindSync(data, 0); var packetCounter = 0; while (start >= 0) { var tsPacket = new TsPacket { SyncByte = data[start], Pid = (short)(((data[start + 1] & 0x1F) << 8) + (data[start + 2])), TransportErrorIndicator = (data[start + 1] & 0x80) != 0, PayloadUnitStartIndicator = (data[start + 1] & 0x40) != 0, TransportPriority = (data[start + 1] & 0x20) != 0, ScramblingControl = (short)(data[start + 3] >> 6), AdaptationFieldExists = (data[start + 3] & 0x20) != 0, ContainsPayload = (data[start + 3] & 0x10) != 0, ContinuityCounter = (short)(data[start + 3] & 0xF) }; if (tsPacket.ContainsPayload && !tsPacket.TransportErrorIndicator) { var payloadOffs = start + 4; var payloadSize = TsPacketSize - 4; if (tsPacket.AdaptationFieldExists) { var adaptationFieldSize = 1 + data[payloadOffs]; if (adaptationFieldSize >= payloadSize) throw new Exception("adaptationFieldSize >= payloadSize"); //todo: actually read adaptationfield here payloadSize -= adaptationFieldSize; payloadOffs += adaptationFieldSize; } if (tsPacket.PayloadUnitStartIndicator) { if (payloadOffs > (data.Length - 2) || data[payloadOffs] != 0 || data[payloadOffs + 1] != 0 || data[payloadOffs + 2] != 1) { #if DEBUG // Debug.WriteLine("PES syntax error: no PES startcode found, or payload offset exceeds boundary of data"); #endif } else { tsPacket.PesHeader = new PesHdr { StartCode = 0x100 + data[payloadOffs + 3], Pts = -1, Dts = -1 }; var ptsDtsFlag = data[payloadOffs + 7] >> 6; switch (ptsDtsFlag) { case 2: tsPacket.PesHeader.Pts = Get_TimeStamp(2, data, payloadOffs + 9); break; case 3: tsPacket.PesHeader.Pts = Get_TimeStamp(3, data, payloadOffs + 9); tsPacket.PesHeader.Dts = Get_TimeStamp(1, data, payloadOffs + 14); break; case 1: throw new Exception("PES Syntax error: pts_dts_flag = 1"); } var pesLength = 9 + data[payloadOffs + 8]; tsPacket.PesHeader.Payload = new byte[pesLength]; Buffer.BlockCopy(data, payloadOffs, tsPacket.PesHeader.Payload, 0, pesLength); payloadOffs += pesLength; payloadSize -= pesLength; } } if (payloadSize < 1) { tsPacket.TransportErrorIndicator = true; } else { tsPacket.Payload = new byte[payloadSize]; Buffer.BlockCopy(data, payloadOffs, tsPacket.Payload, 0, payloadSize); } } tsPackets[packetCounter++] = tsPacket; start += TsPacketSize; if (start >= data.Length) break; if (data[start] != SyncByte) break; // but this is strange! } return tsPackets; } catch (Exception ex) { Debug.WriteLine("Exception within GetTsPacketsFromData method: " + ex.Message); } return null; }