public Packet(byte[] packetBuffer) { TransportErrorIndicator = 1 == packetBuffer[1] >> 7; // Set by demodulator if can't correct errors in the stream, to tell the demultiplexer that the packet has an uncorrectable error PayloadUnitStartIndicator = 1 == ((packetBuffer[1] & 64) >> 6); // and with 01000000 to get second byte - 1 means start of PES data or PSI otherwise zero TransportPriority = 1 == ((packetBuffer[1] & 32) >> 5); // and with 00100000 to get third byte - 1 means higher priority than other packets with the same PID PacketId = (packetBuffer[1] & 31) * 256 + packetBuffer[2]; // and with 00011111 to get last 5 bytes ScramblingControl = packetBuffer[3] >> 6; // '00' = Not scrambled. The following per DVB spec:[12] '01' = Reserved for future use, '10' = Scrambled with even key, '11' = Scrambled with odd key AdaptationFieldControl = (packetBuffer[3] & 48) >> 4; // and with 00110000, 01 = no adaptation fields (payload only), 10 = adaptation field only, 11 = adaptation field and payload ContinuityCounter = packetBuffer[3] & 15; AdaptionFieldLength = AdaptationFieldControl > 1 ? (0xFF & packetBuffer[4]) + 1 : 0; if (AdaptationFieldControl == Helper.B00000010 || AdaptationFieldControl == Helper.B00000011) { AdaptationField = new AdaptationField(packetBuffer); } if (AdaptationFieldControl == Helper.B00000001 || AdaptationFieldControl == Helper.B00000011) // Payload exists - binary '01' || '11' { int payloadStart = 4; if (AdaptationField != null) { payloadStart += (1 + AdaptationField.Length); } if (PacketId == ProgramAssociationTablePacketId) // PAT = Program Association Table: lists all programs available in the transport stream. { ProgramAssociationTable = new ProgramAssociationTable(packetBuffer, payloadStart + 1); // TODO: What index? } // Save payload Payload = new byte[packetBuffer.Length - payloadStart]; Buffer.BlockCopy(packetBuffer, payloadStart, Payload, 0, Payload.Length); } }
public Packet(byte[] packetBuffer) { TransportErrorIndicator = 1 == packetBuffer[1] >> 7; // Set by demodulator if can't correct errors in the stream, to tell the demultiplexer that the packet has an uncorrectable error PayloadUnitStartIndicator = 1 == ((packetBuffer[1] & 64) >> 6); // and with 01000000 to get second byte - 1 means start of PES data or PSI otherwise zero TransportPriority = 1 == ((packetBuffer[1] & 32) >> 5); // and with 00100000 to get third byte - 1 means higher priority than other packets with the same PID PacketId = (packetBuffer[1] & 31) * 256 + packetBuffer[2];// and with 00011111 to get last 5 bytes ScramblingControl = packetBuffer[3] >> 6; // '00' = Not scrambled. The following per DVB spec:[12] '01' = Reserved for future use, '10' = Scrambled with even key, '11' = Scrambled with odd key AdaptationFieldControl = (packetBuffer[3] & 48) >> 4; // and with 00110000, 01 = no adaptation fields (payload only), 10 = adaptation field only, 11 = adaptation field and payload ContinuityCounter = packetBuffer[3] & 15; AdaptionFieldLength = AdaptationFieldControl > 1 ? (0xFF & packetBuffer[4]) + 1 : 0; if (AdaptationFieldControl == Helper.B00000010 || AdaptationFieldControl == Helper.B00000011) AdaptationField = new AdaptationField(packetBuffer); if (AdaptationFieldControl == Helper.B00000001 || AdaptationFieldControl == Helper.B00000011) // Payload exists - binary '01' || '11' { int payloadStart = 4; if (AdaptationField != null) payloadStart += (1 + AdaptationField.Length); if (PacketId == ProgramAssociationTablePacketId) // PAT = Program Association Table: lists all programs available in the transport stream. { ProgramAssociationTable = new ProgramAssociationTable(packetBuffer, payloadStart + 1); // TODO: What index? } // Save payload Payload = new byte[packetBuffer.Length - payloadStart]; Buffer.BlockCopy(packetBuffer, payloadStart, Payload, 0, Payload.Length); } }
/// <summary> /// Get Program Map Tables for a Transport Stream, especially language for subtitle tracks /// </summary> /// <param name="ms">Input stream</param> public void Parse(Stream ms) { try { ms.Position = 0; const int packetLength = 188; var isM2TransportStream = TransportStreamParser.IsM3TransportStream(ms); var packetBuffer = new byte[packetLength]; var m2TsTimeCodeBuffer = new byte[4]; long position = 0; // check for Topfield .rec file ms.Seek(position, SeekOrigin.Begin); ms.Read(m2TsTimeCodeBuffer, 0, 3); if (m2TsTimeCodeBuffer[0] == 0x54 && m2TsTimeCodeBuffer[1] == 0x46 && m2TsTimeCodeBuffer[2] == 0x72) { position = 3760; } var pmtPids = new List <int>(); _programMapTables = new List <ProgramMapTable>(); long transportStreamLength = ms.Length; var max = Math.Min(transportStreamLength, MaxScanSize + position); while (position < max) { ms.Seek(position, SeekOrigin.Begin); if (isM2TransportStream) { ms.Read(m2TsTimeCodeBuffer, 0, m2TsTimeCodeBuffer.Length); position += m2TsTimeCodeBuffer.Length; } ms.Read(packetBuffer, 0, packetLength); if (packetBuffer[0] == Packet.SynchronizationByte) { var packet = new Packet(packetBuffer); if (pmtPids.Contains(packet.PacketId)) { var pmt = new ProgramMapTable(packet.Payload, 0); _programMapTables.Add(pmt); } else if (packet.IsProgramAssociationTable) { var pat = new ProgramAssociationTable(packet.Payload, 0); pmtPids.AddRange(pat.ProgramIds.Where(p => !pmtPids.Contains(p))); } position += packetLength; } else { position++; } } } catch (Exception e) { Exception = e; } }