TsPacket.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Text;
  6. namespace MatrixIO.IO.MpegTs
  7. {
  8. public enum ScramblingControl : byte
  9. {
  10. NotScambled = 0,
  11. Reserved = 1,
  12. ScrambledWithEvenKey = 2,
  13. ScambledWithOddKey = 3,
  14. }
  15. public enum PacketIdentifier : ushort
  16. {
  17. ProgramAssociationTable = 0x0000, // TID 0x00
  18. ConditionalAccessTable = 0x0001, // TID 0x01
  19. TsDescriptionTable = 0x0002, // TID 0x03
  20. // 0x03 to 0x0F RESERVED
  21. NetworkInformationTable = 0x0010, // TID 0x40 (current) & 0x41 (other)
  22. ServiceDescriptionTable = 0x0011, // TID 0x42,0x46 (ServiceDescription) & 0x4A (BouquetAssociation)
  23. EventInformationTable = 0x0012,
  24. RunningStatusTable = 0x0013,
  25. TimeTables = 0x0014, // TID 0x70 (TimeAndDate) & 0x73 (TimeOffset)
  26. NetworkSynchronization = 0x0015,
  27. ResolutionNotificationTable = 0x0016,
  28. // 0x0017 to 0x001B RESERVED
  29. InbandSignalling = 0x001C,
  30. Measurement = 0x001D,
  31. DiscontinuityInformation = 0x001E,
  32. SectionIformation = 0x001F,
  33. // USER DEFINED
  34. NullPacket = 0x1FFF,
  35. }
  36. public class TsPacket
  37. {
  38. public const int Length = 188;
  39. internal const byte SyncByte = 0x47;
  40. private ushort _header1;
  41. private byte _header2;
  42. public bool TransportErrorIndicator
  43. {
  44. get { return (_header1 & 0x8000) != 0; }
  45. set { if (value) _header1 |= 0x8000; else _header1 &= 0x7FFF; }
  46. }
  47. public bool PayloadUnitStartIndicator
  48. {
  49. get { return (_header1 & 0x4000) != 0; }
  50. set { if (value) _header1 |= 0x4000; else _header1 &= 0xBFFF; }
  51. }
  52. public bool TransportPriority
  53. {
  54. get { return (_header1 & 0x2000) != 0; }
  55. set { if (value) _header1 |= 0x2000; else _header1 &= 0xDFFF; }
  56. }
  57. /// <summary>
  58. /// 13 bit identifier. Valid values are 0 to 8191.
  59. /// </summary>
  60. public ushort PacketIdentifier
  61. {
  62. get { return (ushort)(_header1 & 0x1FFF); }
  63. set
  64. {
  65. Debug.Assert(value < 8192, "PacketIdentifier must be in the range of 0 to 8191.");
  66. _header1 = (ushort)((_header1 & 0xE000) | (value & 0x1FFF));
  67. }
  68. }
  69. public ScramblingControl ScramblingControl
  70. {
  71. get { return (ScramblingControl)((_header2 & 0xC0) >> 6); }
  72. set
  73. {
  74. Debug.Assert((int)value < 4, "ScramblingControl must be in the range of 0 to 3.");
  75. _header2 = (byte)((_header2 & 0x3F) | (((byte)value << 6) & 0xC0));
  76. }
  77. }
  78. private bool HasAdaptationField
  79. {
  80. get { return (_header2 & 0x20) != 0; }
  81. set { if (value) _header2 |= 0x20; else _header2 &= 0xDF; }
  82. }
  83. private bool HasPayload
  84. {
  85. get { return (_header2 & 0x10) != 0; }
  86. set { if (value) _header2 |= 0x10; else _header2 &= 0xEF; }
  87. }
  88. /// <summary>
  89. /// 4 bit counter. Valid values are 0 to 15.
  90. /// </summary>
  91. public byte ContinuityCounter
  92. {
  93. get { return (byte)(_header2 & 0x0F); }
  94. set
  95. {
  96. Debug.Assert((int) value < 16, "ContinuityCounter must be in the range of 0 to 15.");
  97. _header2 = (byte)((_header2 & 0xF0) | (value & 0x0F));
  98. }
  99. }
  100. private AdaptationField _adaptationField;
  101. public AdaptationField AdaptationField
  102. {
  103. get
  104. {
  105. return HasAdaptationField ? _adaptationField : null;
  106. }
  107. set
  108. {
  109. _adaptationField = value;
  110. HasAdaptationField = (value != null);
  111. }
  112. }
  113. private byte[] _payload;
  114. public byte[] Payload
  115. {
  116. get { return HasPayload ? _payload : null; }
  117. set
  118. {
  119. _payload = value;
  120. HasPayload = (value != null);
  121. }
  122. }
  123. public byte[] Stuffing { get; set; }
  124. public TsPacket(byte[] buffer, int offset=0)
  125. {
  126. int position = offset;
  127. if (buffer.Length - offset < Length)
  128. throw new ArgumentOutOfRangeException("Buffer must contain at least " + Length + " bytes.");
  129. if (buffer[position++] != SyncByte)
  130. throw new ArgumentException("Packet does not begin with 0x" + SyncByte.ToString("X2") + " sync byte.");
  131. _header1 = (ushort)((buffer[position++] << 8) | buffer[position++]);
  132. _header2 = buffer[position++];
  133. if(HasAdaptationField)
  134. {
  135. _adaptationField = new AdaptationField(buffer, position);
  136. position += AdaptationField.Length + 1;
  137. }
  138. if (HasPayload)
  139. {
  140. int payloadLength = Length - (position - offset);
  141. _payload = new byte[payloadLength];
  142. Buffer.BlockCopy(buffer, position, _payload, 0, payloadLength);
  143. position += payloadLength;
  144. }
  145. int stuffingLength = Length - (position - offset);
  146. if (stuffingLength > 0)
  147. {
  148. Debug.WriteLine("Has " + stuffingLength + " bytes of Transport Packet stuffing.");
  149. Stuffing = new byte[stuffingLength];
  150. }
  151. }
  152. }
  153. }