TsStream.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Text;
  7. using MatrixIO.IO.MpegTs.Tables;
  8. using MatrixIO.IO.MpegTs.Streams;
  9. namespace MatrixIO.IO.MpegTs
  10. {
  11. public enum StreamType : byte
  12. {
  13. Unknown = 0x00, // ITU-T | IOS/IEC Reserved
  14. MPEG1_Video = 0x01, // ISO/IEC 11172-2 Video, MPEG1
  15. MPEG2_Video = 0x02, // ITU-T Rec H.262, ISO/IEC 13818-2 Video, MPEG2 or ISO/IEC 11172-2 constrained parameter video stream
  16. MPEG1_Audio = 0x03, // ISO/IEC 11172 Audio
  17. MPEG2_Audio = 0x04, // ISO/IEC 13818-3 Audio, MPEG2 Part 3 Audio
  18. MPEG2_PrivateSections = 0x05, // ITU-T Rec. H.222.0, ISO/IEC 13818-1 private_sections, MPEG2 Part 1 Private Sections
  19. MPEG2_PrivateData = 0x06, // ITU-T Rec. H.222.0, ISO/IEC 13818-1 PES packets containing private data
  20. MHEG_MultiMedia = 0x07, // ISO/IEC 13522 MHEG
  21. MPEG2_AnnexA_DSM_CC = 0x08, // ITU-T Rec. H.222.0, ISO/IEC 13818-1 Annex A DSM-CC
  22. H222_1 = 0x09, // ITU-T Rec. H.222.1
  23. MPEG2_TypeA = 0x0A, // MPEG2 Part 6 Type A, ISO/IEC 13818-6 Type A
  24. MPEG2_TypeB = 0x0B, // MPEG2 Part 6 Type B, ISO/IEC 13818-6 Type B
  25. MPEG2_TypeC = 0x0C, // MPEG2 Part 6 Type C, ISO/IEC 13818-6 Type C
  26. MPEG2_TypeD = 0x0D, // MPEG2 Part 6 Type D, ISO/IEC 13818-6 Type D
  27. MPEG2_Auxiliary = 0x0E, // ITU-T Rec. H.220.0, ISO/IEC 13818-1 auxiliary, MPEG2 Part 1 Auxiliary
  28. MPEG4_AAC = 0x0F, // MPEG4 Part 7 AAC, ISO/IEC 13818-7:1997 AAC
  29. MPEG4_Visual = 0x10, // MPEG4 Part 2 Visual a.k.a DivX/XviD, ISO/IEC 14496-2
  30. MPEG4_Audio = 0x11, // MPEG4 Part 3 Audio with Amendment 1 LATM Syntax, ISO/IEC 14496-3, ISO/IEC 1
  31. MPEG4_FlexMuxPES = 0x12, // ISO/IEC 14496-1 SL-packetized stream of FlexMux stream carried in PES Packets, MPEG4 Part 1
  32. MPEG4_FlexMuxSections = 0x13, // ISO/IEC 14496-1 SL-packetized stream of FlexMux stream carried in ISO/IEC 14496_sections, MPEG4 Part 1
  33. SDP = 0x14, // ISO/IEC 13818-6 Synchronized Download Protocol
  34. METADATA_PES = 0x15, // Metadata carried in PES packets
  35. METADATA_Sections = 0x16, // Metadata carried in metadata_sections
  36. METADATA_DataCarousel = 0x17, // Metadata carried in ISO/IEC 13818-6 Data Carousel
  37. METADATA_ObjectCarousel = 0x18,// Metadata carried in ISO/IEC 13818-6 Object Carousel
  38. METADATA_SDP = 0x19, // Metadata carried in ISO/IEC 13818-6 Synchronized Download Protocol
  39. IPMP = 0x1A, // IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP)
  40. MPEG4_AVC = 0x1B, // ITU-T h.264, MPEG4 Part 10 AVC, ISO/IEC 14496-10 AVC
  41. // 0x1C - 0x7F ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved
  42. // 0x7f is sometimes used for IPMP streams as well.
  43. // 0x80 - 0xFF USER PRIVATE
  44. // Blu-Ray BDAV specific types
  45. // TODO: I'm not sure these are in the correct order or what the 3 numbered ones are. AC3 and VC1 are the only one I've verified.
  46. BDAV_Audio_LPCM = 0x80,
  47. BDAV_Audio_AC3 = 0x81,
  48. BDAV_Audio_DDPlus = 0x82,
  49. BDAV_Audio_DolbyLossless = 0x83,
  50. BDAV_Audio_DTS = 0x84,
  51. BDAV_Audio_DTSHD = 0x85,
  52. BDAV_Audio_7 = 0x86,
  53. BDAV_Audio_8 = 0xA1,
  54. BDAV_Audio_9 = 0xA2,
  55. BDAV_VIDEO_VC1 = 0xEA, // Defined for Blu-Ray
  56. }
  57. public abstract class TsStream : INotifyPropertyChanged
  58. {
  59. public event EventHandler<TsStreamEventArgs> UnitReceived;
  60. public void OnUnitReceived(TsStreamEventArgs e)
  61. {
  62. if (UnitReceived != null)
  63. UnitReceived(this, e);
  64. }
  65. private ushort _packetIdentifier;
  66. public ushort PacketIdentifier
  67. {
  68. get { return _packetIdentifier; }
  69. set { _packetIdentifier = value; OnPropertyChanged("PacketIdentifier"); }
  70. }
  71. private StreamType _type;
  72. public StreamType Type
  73. {
  74. get { return _type; }
  75. set { _type = value; OnPropertyChanged("Type"); }
  76. }
  77. private IList<TsDescriptor> _info;
  78. public IList<TsDescriptor> Info
  79. {
  80. get { return _info; }
  81. set { _info = value; OnPropertyChanged("Info"); }
  82. }
  83. private long _droppedPackets;
  84. public long DroppedPackets
  85. {
  86. get { return _droppedPackets; }
  87. protected set { _droppedPackets = value; OnPropertyChanged("DroppedPackets"); }
  88. }
  89. private long _skippedPackets;
  90. public long SkippedPackets
  91. {
  92. get { return _skippedPackets; }
  93. protected set { _skippedPackets = value; OnPropertyChanged("SkippedPackets"); }
  94. }
  95. public abstract void ProcessInput(TsPacket packet);
  96. protected static int EstimateDroppedPackets(int lastCounter, int currentCounter)
  97. {
  98. if (lastCounter < currentCounter) return currentCounter - lastCounter - 1;
  99. if (lastCounter > currentCounter) return 15 - lastCounter + currentCounter;
  100. return 0;
  101. }
  102. public override string ToString()
  103. {
  104. return Type + " (PID " + PacketIdentifier + ")";
  105. }
  106. #region INotifyPropertyChanged Implementation
  107. public event PropertyChangedEventHandler PropertyChanged;
  108. protected void OnPropertyChanged(string propertyName)
  109. {
  110. if (PropertyChanged != null)
  111. Portability.DispatchAction(() => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)));
  112. }
  113. #endregion
  114. public static Dictionary<StreamType, Type> StreamTypes = new Dictionary<StreamType,Type>()
  115. {
  116. { StreamType.MPEG1_Video, typeof(PacketizedElementalStream) },
  117. { StreamType.MPEG2_Video, typeof(PacketizedElementalStream) },
  118. { StreamType.MPEG1_Audio, typeof(PacketizedElementalStream) },
  119. { StreamType.MPEG2_Audio, typeof(PacketizedElementalStream) },
  120. { StreamType.MPEG2_PrivateSections, typeof(ByteStream) }, // Are these related to Table Sections?
  121. { StreamType.MPEG2_PrivateData, typeof(PacketizedElementalStream) },
  122. { StreamType.MHEG_MultiMedia, typeof(ByteStream) }, // ?
  123. { StreamType.MPEG2_AnnexA_DSM_CC, typeof(ByteStream) }, // ?
  124. { StreamType.H222_1, typeof(ByteStream) }, // ?
  125. { StreamType.MPEG2_TypeA, typeof(ByteStream) }, // ?
  126. { StreamType.MPEG2_TypeB, typeof(ByteStream) }, // ?
  127. { StreamType.MPEG2_TypeC, typeof(ByteStream) }, // ?
  128. { StreamType.MPEG2_TypeD, typeof(ByteStream) }, // ?
  129. { StreamType.MPEG2_Auxiliary, typeof(ByteStream) }, // ?
  130. { StreamType.MPEG4_AAC, typeof(PacketizedElementalStream) }, // ?
  131. { StreamType.MPEG4_Visual, typeof(ByteStream) }, // ?
  132. { StreamType.MPEG4_Audio, typeof(ByteStream) }, // ?
  133. { StreamType.MPEG4_FlexMuxPES, typeof(ByteStream) }, // ?
  134. { StreamType.MPEG4_FlexMuxSections, typeof(ByteStream) }, // ?
  135. { StreamType.SDP, typeof(ByteStream) }, // ?
  136. { StreamType.MPEG4_AVC, typeof(PacketizedElementalStream) }, // ?
  137. };
  138. }
  139. public abstract class TsStream<T> : TsStream
  140. where T: class
  141. {
  142. private byte _lastContinuityCounter;
  143. private bool _unitInProgress;
  144. private long _unitCount;
  145. private TsUnit _currentUnit = new TsUnit();
  146. public override void ProcessInput(TsPacket packet)
  147. {
  148. byte expectedContinuityCounter = packet.Payload != null ? (byte)(_lastContinuityCounter + 1) : _lastContinuityCounter;
  149. if (expectedContinuityCounter > 15) expectedContinuityCounter -= 16;
  150. if (packet.PayloadUnitStartIndicator)
  151. {
  152. if (_unitInProgress)
  153. {
  154. #if DEBUG
  155. var adaptationfields = (from p in _currentUnit.Packets where p.AdaptationField != null select p.AdaptationField).Count();
  156. Debug.WriteLine("### Completed unit for PID " + (PacketIdentifier) PacketIdentifier + " with " +
  157. _currentUnit.Packets.Count
  158. + " packets, " + _currentUnit.Payload.Count + " bytes of payload and " +
  159. adaptationfields + " adaptation fields.");
  160. #endif
  161. var unit = ProcessUnit(_currentUnit);
  162. if(unit!=null) OnUnitReceived(new TsStreamEventArgs<T>(PacketIdentifier, _currentUnit, unit));
  163. _unitInProgress = false;
  164. _currentUnit = new TsUnit();
  165. }
  166. _currentUnit.Packets.Add(packet);
  167. if (_unitCount > 0 && packet.ContinuityCounter != expectedContinuityCounter)
  168. {
  169. int droppedPackets = EstimateDroppedPackets(_lastContinuityCounter, packet.ContinuityCounter);
  170. Debug.WriteLine("*** Discontinuity (0) - Dropped " + droppedPackets + " packets. ***");
  171. }
  172. _lastContinuityCounter = packet.ContinuityCounter;
  173. _unitInProgress = true;
  174. _unitCount++;
  175. }
  176. else if (_unitInProgress)
  177. {
  178. if (packet.ContinuityCounter == expectedContinuityCounter)
  179. {
  180. _currentUnit.Packets.Add(packet);
  181. _lastContinuityCounter = packet.ContinuityCounter;
  182. if (packet.Payload != null) _lastContinuityCounter = packet.ContinuityCounter;
  183. // Check to see if this is the last packet
  184. }
  185. else
  186. {
  187. var droppedPackets = EstimateDroppedPackets(_lastContinuityCounter, packet.ContinuityCounter);
  188. DroppedPackets += droppedPackets;
  189. Debug.WriteLine("*** Discontinuity (1) - Dropped " + droppedPackets + " packets. ***");
  190. _unitInProgress = false;
  191. _currentUnit.Packets.Clear();
  192. }
  193. }
  194. else if (_unitCount > 0)
  195. {
  196. // This should be the result of a prior Discontinuity (1) as we just have to
  197. // drop the remaining packets until the next unit start packet.
  198. SkippedPackets++;
  199. Debug.WriteLine("*** Skipping packet due to prior discontinuity. ***");
  200. }
  201. else
  202. {
  203. // Silently drop any packets that arrive before our first unit start packet.
  204. SkippedPackets++;
  205. Debug.WriteLine("*** Skipping initial packet before first Unit Start. ***");
  206. }
  207. }
  208. protected abstract T ProcessUnit(TsUnit unit);
  209. public void OnUnitReceived(TsStreamEventArgs<T> e)
  210. {
  211. base.OnUnitReceived(e);
  212. }
  213. }
  214. public class TsStreamEventArgs : EventArgs
  215. {
  216. public ushort PacketIdentifier { get; private set; }
  217. public TsUnit Unit { get; private set; }
  218. public TsStreamEventArgs(ushort packetIdentifier, TsUnit unit)
  219. {
  220. PacketIdentifier = packetIdentifier;
  221. Unit = unit;
  222. }
  223. }
  224. public class TsStreamEventArgs<T> : TsStreamEventArgs
  225. {
  226. public T DecodedUnit { get; private set; }
  227. public TsStreamEventArgs(ushort packetIdentifier, TsUnit unit, T decodedUnit) : base(packetIdentifier, unit)
  228. {
  229. DecodedUnit = decodedUnit;
  230. }
  231. }
  232. }