public SectionBase(byte[] source, int offset, int pid, bool crc) { _SectionData = new byte[4096]; _DoCrc = crc; int u = source[1 + offset]; int l = source[2 + offset]; u &= 0x0f; l |= u << 8; l += 3; Array.Copy(source, offset, SectionData, 0, l); _Pid = pid; _Ptr = l; _Completed = true; _Finished = !_DoCrc || SectionCrc.Compare(_SectionData, l, 0x00000000); }
/// <summary> /// Fügt ein Paket ohne Header einem Byte[] der Section hinzu. /// </summary> /// <param name="tsPacket">MPEG Transport-Strom-Paket ohne Header</param> /// <param name="plOffset">0 wenn erste Section in dem Packet. größer 0 wenn weitere packers vorhanden.</param> /// <returns>True wenn letzte benötigte Paket eingelesen und Prüfsumme korrekt berechnet wurde.</returns> private bool AddPacket184(byte[] tsPacket, int plOffset) { if (_AllowedTables == null) { throw new InvalidOperationException("Section wurde nicht korrekt initialisiert um 184 Byte Packets aufzunehmen."); } lock (this) { if (_Finished) { return(true); } // Dann sind Daten fehlerhaft, also Neustart: if (_Completed && !_Finished) { Reset(); } int plPointer = tsPacket[0]; if (_PacketCtr == 0 && plOffset == 0) { plOffset = 1 + plPointer; } if (plOffset > 180) // dann kann was nicht stimmen. { Reset(); return(false); } if (_PacketCtr == 0) { byte tableId = tsPacket[plOffset]; bool syntax = (tsPacket[plOffset + 1] & 0x80) > 0; bool isTable = false; for (int i = 0; i < _AllowedTables.Length; i++) { if (_AllowedTables[i] == tableId) { isTable = true; break; } } if ((tableId < 0x80 && !syntax) || !isTable) { Reset(); return(false); } } int len = (184) - plOffset; int remain; if (_PacketCtr == 0) { int u = Marshal.ReadByte(tsPacket, plOffset + 1); int l = Marshal.ReadByte(tsPacket, plOffset + 2); u &= 0x0f; l |= u << 8; remain = l + 3; } else { remain = SectionSize - _Ptr; } if (remain < len) { len = remain; } if (_Ptr + len > _SectionData.Length) { len -= _SectionData.Length - _Ptr; // einkürzen, damit in Buffer passt. } if (len <= 0) { Reset(); return(false); // fehler } Array.Copy(tsPacket, plOffset, SectionData, _Ptr, len); _PacketCtr++; _Ptr += len; int size = SectionSize; _DoCrc = _SectionData[0] < 0x80; // Table ID, kein CRC auf ECM/EMM if (size > 1023) // max len = 1024 nach en300468 { Reset(); return(false); } // wenn rest vom vorherige section zu lang ist, könnte teil der Section-Length fehlen // daher immer auf size prüfen. _Completed = size > 5 && (_Ptr >= size); if (_Completed) { // dann CRC prüfen, wenn gefordert, ECMs sind z.B. ohne.: _Finished = !_DoCrc || SectionCrc.Compare(_SectionData, size, 0x00000000); if (_Finished && _SectionData[size] != 0xff) // prüfen ob weitere Sections vorhanden sind: { NextSection = new SectionBase(_Pid, _AllowedTables); NextSection.AddPacket184(tsPacket, plOffset + size); // offsetstart + Section-Länge = start nächste Section } } return(_Finished); } }
/// <summary> /// Fügt ein Paket aus einem Byte[] der Section hinzu /// </summary> /// <param name="tsPacket">MPEG Transport-Strom-Paket</param> /// <param name="plOffset">0 wenn erste Section in dem Packet. größer 0 wenn weitere packers vorhanden.</param> /// <returns>True wenn letzte benötigte Paket eingelesen und Prüfsumme korrekt berechnet wurde.</returns> private bool AddPacket(byte[] tsPacket, int plOffset) { lock (this) { if (_Finished) { return(true); } if (_Completed && !_Finished) { Reset(); } int err = tsPacket[1] & 0x80; int start = tsPacket[1] & 0x40; int prio = tsPacket[1] & 0x20; int pid = ((tsPacket[1] << 8) | tsPacket[2]) & 0x1fff; int scrambling = (tsPacket[3] & 0xc0) >> 6; int adaption = (tsPacket[3] & 0x30) >> 4; int contCtr = tsPacket[3] & 0x0f; int plPointer = tsPacket[4]; if (pid != _Pid && _Pid != -1) { return(false); } if (err != 0) { return(false); } if ((_PacketCtr == 0 && start == 0) || adaption == 0) { return(false); } if (start == 0 && _PacketCtr != 0 && ((_ContCtr + 1) & 0x0f) != contCtr) { Reset(); return(false); } if (adaption == 2) { return(false); } if (plOffset == 0 && (adaption == 3 || start != 0)) { plOffset += 1 + plPointer; } int len = (188 - 4) - plOffset; int remain; if (_PacketCtr == 0) { int u = tsPacket[4 + plOffset + 1]; int l = tsPacket[4 + plOffset + 2]; u &= 0x0f; l |= u << 8; remain = l + 3; } else { remain = SectionSize - _Ptr; } if (remain < len) { len = remain; } if (_Ptr + len > _SectionData.Length) { len -= _SectionData.Length - _Ptr; } if (len <= 0) { Reset(); return(false); } Array.Copy(tsPacket, 4 + plOffset, SectionData, _Ptr, len); _ContCtr = contCtr; _PacketCtr++; _Ptr += len; int size = SectionSize; _Completed = size > 3 && (_Ptr >= size); if (_Completed) { _Finished = !_DoCrc || SectionCrc.Compare(_SectionData, size, 0x00000000); if (_Finished && start != 0 && _SectionData[size] != 0xff) { NextSection = new SectionBase(_Pid, _DoCrc); NextSection.AddPacket(tsPacket, plOffset + size); } } return(_Finished); } }
/// <summary> /// Fügt ein Paket ohne Header der Section hinzu. /// </summary> /// <param name="tsPacket">MPEG Transport-Strom-Paket ohne Header</param> /// <param name="plOffset">0 wenn erste Section in dem Packet. größer 0 wenn weitere packers vorhanden.</param> /// <returns>True wenn letzte benötigte Paket eingelesen und Prüfsumme korrekt berechnet wurde.</returns> private bool AddPacket184(IntPtr tsPacket, int plOffset) { if (_AllowedTables == null) { throw new InvalidOperationException("Section wurde nicht korrekt initialisiert um 184 Byte Packets aufzunehmen."); } lock (this) { if (_Finished) { return(true); } // Dann sind Daten fehlerhaft, also Neustart: if (_Completed && !_Finished) { Reset(); } int plPointer = Marshal.ReadByte(tsPacket, 0); // nur von Wichtigkeit, wenn PL Start, nicht wenn plOffset gesetzt ist. // Ansonsten kann das letzte Packet auch in PL Start haben, der Start aber später erst anfängt. // PDF ISO/IEC 13818-1 : 2000 (E) Seite 19 (reader: 37) Punkt 2.4.3.3 payload_unit_start_indicator. // wenn adaption field gesetzt gilt dies auch // start des Payloads ermitteln, wenn Adaption-Field vorhanden //int plOffset = 0; // wenn != 0, dann ist das ein Nested Call für weitere Sections pro packet, z.b. bei EMM. if (_PacketCtr == 0 && plOffset == 0) { plOffset = 1 + plPointer; } if (plOffset > 180) // dann kann was nicht stimmen. { Reset(); return(false); } if (_PacketCtr == 0) { // check erlaubte Tabelle: byte tableId = Marshal.ReadByte(tsPacket, plOffset); bool syntax = (Marshal.ReadByte(tsPacket, plOffset + 1) & 0x80) > 0; bool isTable = false; for (int i = 0; i < _AllowedTables.Length; i++) { if (_AllowedTables[i] == tableId) { isTable = true; break; } } if ((tableId < 0x80 && !syntax) || !isTable) // bei ECM/EMM wird die section Syntax teilweise deaktiviert. { Reset(); return(false); } } int len = (184) - plOffset; int remain; // länge aus Header ermitteln, damit packetize später stimmt, sofern erstes packet... if (_PacketCtr == 0) { int u = Marshal.ReadByte(tsPacket, plOffset + 1); int l = Marshal.ReadByte(tsPacket, plOffset + 2); u &= 0x0f; l |= u << 8; remain = l + 3; } else { remain = SectionSize - _Ptr; } if (remain < len) { len = remain; } if (_Ptr + len > _SectionData.Length) { len -= _SectionData.Length - _Ptr; // einkürzen, damit in Buffer passt. } if (len <= 0) { Reset(); return(false); // fehler } Marshal.Copy(tsPacket + plOffset, SectionData, _Ptr, len); _PacketCtr++; _Ptr += len; int size = SectionSize; _DoCrc = _SectionData[0] < 0x80; // Table ID, kein CRC auf ECM/EMM if (size > 1023) // max len = 1024 nach en300468 { Reset(); return(false); } // wenn rest vom vorherige section zu lang ist, könnte teil der Section-Length fehlen // daher immer auf size prüfen. _Completed = size > 5 && (_Ptr >= size); if (_Completed) { // dann CRC prüfen, wenn gefordert, ECMs sind z.B. ohne.: _Finished = !_DoCrc || SectionCrc.Compare(_SectionData, size, 0x00000000); if (_Finished && _SectionData[size] != 0xff) // prüfen ob weitere Sections vorhanden sind: { NextSection = new SectionBase(_Pid, _AllowedTables); NextSection.AddPacket184(tsPacket, plOffset + size); // offsetstart + Section-Länge = start nächste Section } } return(_Finished); } }
/// <summary> /// Fügt ein Paket der Section hinzu. /// </summary> /// <param name="tsPacket">MPEG Transport-Strom-Paket</param> /// <param name="plOffset">0 wenn erste Section in dem Packet. größer 0 wenn weitere packers vorhanden.</param> /// <returns>True wenn letzte benötigte Paket eingelesen und Prüfsumme korrekt berechnet wurde.</returns> private bool AddPacket(IntPtr tsPacket, int plOffset) { lock (this) { if (_Finished) { return(true); } // Dann sind Daten fehlerhaft, also Neustart: if (_Completed && !_Finished) { Reset(); } int tmp = IPAddress.NetworkToHostOrder(Marshal.ReadInt16(tsPacket, 1)); int err = tmp & 0x8000; int start = tmp & 0x4000; int prio = tmp & 0x2000; int pid = tmp & 0x1fff; tmp = Marshal.ReadByte(tsPacket, 3); int scrambling = (tmp & 0xc0) >> 6; // 0 = unscrambled, 2 = even CW, 3 = odd cw, 1 = ? int adaption = (tmp & 0x30) >> 4; // 0 = invalid, 1 = payload only, 2 = a. only, 3 = a folow pl int contCtr = tmp & 0x0f; int plPointer = Marshal.ReadByte(tsPacket, 4); // nur von Wichtigkeit, wenn PL Start. // Ansonsten kann das letzte Packet auch in PL Start haben, der Start aber später erst anfängt. // PDF ISO/IEC 13818-1 : 2000 (E) Seite 19 (reader: 37) Punkt 2.4.3.3 payload_unit_start_indicator. // wenn adaption field gesetzt gilt dies auch // bei nicht passender Pid raus: if (pid != _Pid && _Pid != -1) { return(false); } // Bei fehlerhaften Packets raus: if (err != 0) { return(false); } // Wenn noch kein Payload-Start und kein Paket eingelesen wurde, dann raus, ebenso wenn adaption-control 0 ist. if ((_PacketCtr == 0 && start == 0) || adaption == 0) { return(false); } // wenn schon Packets vorhanden, und wieder PL Start, dann Reset, neuer Anlauf. // entfernt. Siehe oben plPointer Kommentar. //if (_PacketCtr && start) //{ // Reset(); //} // start und !_packetCtr // !start und _packetCtr <-- hier contCtr prüfen! if (start == 0 && _PacketCtr != 0 && ((_ContCtr + 1) & 0x0f) != contCtr) { // Dann fehlt ein oder mehrere packets. Reset und raus. Reset(); return(false); } // hier dürfte nun nichts falsches mehr sein. Wenn doch was schief geht, stimmt CRC am ende nicht. // nichts zu kopieren, raus: if (adaption == 2) { return(false); } // start des Payloads ermitteln, wenn Adaption-Field vorhanden //int plOffset = 0; // wenn != 0, dann ist das ein Nested Call für weitere Sections pro packet, z.b. bei EMM. if (plOffset == 0 && (adaption == 3 || start != 0)) { plOffset += 1 + plPointer; } int len = (188 - 4) - plOffset; int remain; // länge aus Header ermitteln, damit packetize später stimmt, sofern erstes packet... if (_PacketCtr == 0) { int u = Marshal.ReadByte(tsPacket, 4 + plOffset + 1); int l = Marshal.ReadByte(tsPacket, 4 + plOffset + 2); u &= 0x0f; l |= u << 8; remain = l + 3; } else { remain = SectionSize - _Ptr; } if (remain < len) { len = remain; } if (_Ptr + len > _SectionData.Length) { len -= _SectionData.Length - _Ptr; // einkürzen, damit in Buffer passt. } if (len <= 0) { Reset(); return(false); // fehler } Marshal.Copy(tsPacket + (4 + plOffset), SectionData, _Ptr, len); // zähler setzen: _ContCtr = contCtr; _PacketCtr++; _Ptr += len; int size = SectionSize; // wenn rest vom vorherige section oder adaption field zu lang ist, könnte teil der Section-Length fehlen // daher immer auf size prüfen. _Completed = size > 3 && (_Ptr >= size); if (_Completed) { // dann CRC prüfen, wenn gefordert, ECMs sind z.B. ohne.: _Finished = !_DoCrc || SectionCrc.Compare(_SectionData, size, 0x00000000); if (_Finished && start != 0 && _SectionData[size] != 0xff) // prüfen ob weitere Sections vorhanden sind: { NextSection = new SectionBase(_Pid, _DoCrc); NextSection.AddPacket(tsPacket, plOffset + size); // offsetstart + Section-Länge = start nächste Section } } return(_Finished); } }