OSDN Git Service

implement exec() in TsRemux class in Form1.cc
[tsremuxcpp/developing01.git] / src / TsToPes.cc
1 #include "TsToPes.h"
2
3 namespace TsRemux
4 {
5 static const char PesTemplate[] = { 0x00, 0x00, 0x01, 0xbd};
6
7
8         
9 public abstract class PesFile
10 {
11                         protected PesFile(BackgroundWorker openWorker)
12                         {
13                                 fs = null;
14                                 tsior = null;
15                                 fileType = TsFileType.UNKNOWN;
16                                 startPcr = -1;
17                                 endPcr = -1;
18                                 sis = null;
19                                 pcrDelegate = null;
20                                 ptsDelegate = null;
21                                 this.openWorker = openWorker;
22                                 lastPercent = 0;
23                         }
24                         
25                         protected void ReportProgress(int percent)
26                         {
27                                 if (openWorker.CancellationPending)
28                                         {
29                                                 throw new ApplicationException("Opening file canceled");
30                                         }
31                                 if (lastPercent != percent && percent > 0 && percent <= 100)
32                                         {
33                                                 lastPercent = percent;
34                                                 openWorker.ReportProgress(percent);
35                                         }
36                         }
37                         
38                         public void SetPcrDelegate(PcrChanged pcr)
39                         {
40                                 pcrDelegate = pcr;
41                         }
42                         
43                         public Int64 StartPcr
44                         {
45                                 get { return startPcr; }
46                         }
47                         
48                         public Int64 EndPcr
49                         {
50                                 get { return endPcr; }
51                         }
52                         
53                         public void SetPtsDelegate(PtsChanged pts)
54                         {
55                                 ptsDelegate = pts;
56                         }
57                         
58                         public StreamInfo GetStreamInfo(ushort pid)
59                         {
60                                 foreach (StreamInfo si in sis)
61                 if (si.ElementaryPID == pid)
62                     return si;
63                                 return null;
64                         }
65                         
66                         private void ParseElementaryStreams()
67                         {
68                                 Seek(-1);
69                                 for (int i = 0; i < 300;)
70                                         {
71                                                 ReportProgress(50 + ((50 * i) / 300));
72                                                 PesPacket[] ppa = GetNextPesPackets();
73                                                 if(ppa == null)
74                                                         goto done;
75                                                 foreach (PesPacket pp in ppa)
76                                                 {
77                                                         if (null != pp)
78                                                                 {
79                                                                         byte[] payload = pp.GetPayload();
80                                                                         StreamInfo si = GetStreamInfo(pp.PID);
81                                                                         if (si != null)
82                                                                                 ParseStream(si, payload);
83                                                                         i++;
84                                                                 }
85                                                         else
86                                                                 goto done;
87                                                 }
88                                         }
89                         done:
90                                 Seek(-1);
91                         }
92                         
93                         private void ParseStream(StreamInfo si, byte[] payload)
94                         {
95                                 switch (si.StreamType)
96                                 {
97                                         case ElementaryStreamTypes.VIDEO_STREAM_VC1:
98                                                 if ((si.ElementaryDescriptors == null) ||
99                                                         si.FrameRate == FrameRate.Reserved ||
100                                                         si.VideoFormat == VideoFormat.Reserved ||
101                                                         si.AspectRatio == AspectRatio.Reserved)
102                                                         {
103                                                                 VC1SequenceInfo sq = new VC1SequenceInfo(payload, 0);
104                                                                 if (sq.Valid)
105                                                                         {
106                                                                                 if (sq.AspectRatio != AspectRatio.Reserved)
107                                                                                         si.AspectRatio = sq.AspectRatio;
108                                                                                 if (sq.FrameRate != FrameRate.Reserved)
109                                                                                         si.FrameRate = sq.FrameRate;
110                                                                                 if (sq.VideoFormat != VideoFormat.Reserved)
111                                                                                         si.VideoFormat = sq.VideoFormat;
112                                                                                 if (si.ElementaryDescriptors == null)
113                                                                                         si.ElementaryDescriptors = Constants.vc1_descriptor;
114                                                                         }
115                                                         }
116                                                 break;
117                                         case ElementaryStreamTypes.AUDIO_STREAM_AC3:
118                                                 if ((si.ElementaryDescriptors == null) ||
119                                                         si.AudioPresentationType == AudioPresentationType.Reserved ||
120                                                         si.SamplingFrequency == SamplingFrequency.Reserved)
121                                                         {
122                                                                 AC3Info ac3 = new AC3Info(payload, 0);
123                                                                 if (ac3.Valid)
124                                                                         {
125                                                                                 if (ac3.AudioPresentationType != AudioPresentationType.Reserved)
126                                                                                         si.AudioPresentationType = ac3.AudioPresentationType;
127                                                                                 if (ac3.SamplingFrequency != SamplingFrequency.Reserved)
128                                                                                         si.SamplingFrequency = ac3.SamplingFrequency;
129                                                                                 if (si.ElementaryDescriptors == null)
130                                                                                         si.ElementaryDescriptors = ac3.ElementaryDescriptors;
131                                                                                 if (ac3.SyntaxType == Ac3SyntaxType.Enhanced)
132                                                                                         si.StreamType = ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS;
133                                                                         }
134                                                         }
135                                                 break;
136                                         case ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS:
137                                                 if (si.AudioPresentationType == AudioPresentationType.Reserved ||
138                                                         si.SamplingFrequency == SamplingFrequency.Reserved)
139                                                         {
140                                                                 AC3Info ac3 = new AC3Info(payload, 0);
141                                                                 if (ac3.Valid)
142                                                                         {
143                                                                                 if (ac3.AudioPresentationType != AudioPresentationType.Reserved)
144                                                                                         si.AudioPresentationType = ac3.AudioPresentationType;
145                                                                                 if (ac3.SamplingFrequency != SamplingFrequency.Reserved)
146                                                                                         si.SamplingFrequency = ac3.SamplingFrequency;
147                                                                                 if (si.ElementaryDescriptors == null)
148                                                                                         si.ElementaryDescriptors = ac3.ElementaryDescriptors;
149                                                                         }
150                                                         }
151                                                 break;
152                                         case ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD:
153                                                 if (si.AudioPresentationType == AudioPresentationType.Reserved ||
154                                                         si.SamplingFrequency == SamplingFrequency.Reserved)
155                                                         {
156                                                                 MlpInfo ac3 = new MlpInfo(payload, 0);
157                                                                 if (ac3.Valid)
158                                                                         {
159                                                                                 if (ac3.AudioPresentationType != AudioPresentationType.Reserved)
160                                                                                         si.AudioPresentationType = ac3.AudioPresentationType;
161                                                                                 if (ac3.SamplingFrequency != SamplingFrequency.Reserved)
162                                                                                         si.SamplingFrequency = ac3.SamplingFrequency;
163                                                                                 if (si.ElementaryDescriptors == null)
164                                                                                         si.ElementaryDescriptors = ac3.ElementaryDescriptors;
165                                                                         }
166                                                         }
167                                                 break;
168                                         case ElementaryStreamTypes.VIDEO_STREAM_H264:
169                                                 if ((si.ElementaryDescriptors == null) ||
170                                                         si.FrameRate == FrameRate.Reserved ||
171                                                         si.VideoFormat == VideoFormat.Reserved ||
172                                                         si.AspectRatio == AspectRatio.Reserved)
173                                                         {
174                                                                 H264Info h264 = new H264Info(payload, 0);
175                                                                 if(h264.Valid)
176                                                                         {
177                                                                                 if (h264.AspectRatio != AspectRatio.Reserved)
178                                                                                         si.AspectRatio = h264.AspectRatio;
179                                                                                 if (h264.FrameRate != FrameRate.Reserved)
180                                                                                         si.FrameRate = h264.FrameRate;
181                                                                                 if (h264.VideoFormat != VideoFormat.Reserved)
182                                                                                         si.VideoFormat = h264.VideoFormat;
183                                                                                 if (si.ElementaryDescriptors == null)
184                                                                                         si.ElementaryDescriptors = h264.ElementaryDescriptors;
185                                                                         }
186                                                         }
187                                                 break;
188                                         case ElementaryStreamTypes.AUDIO_STREAM_DTS:
189                                         case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD:
190                                         case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD_MASTER_AUDIO:
191                                                 if (si.AudioPresentationType == AudioPresentationType.Reserved ||
192                                                         si.SamplingFrequency == SamplingFrequency.Reserved)
193                                                         {
194                                                                 DtsInfo dts = new DtsInfo(payload, 0);
195                                                                 if (dts.Valid)
196                                                                         {
197                                                                                 if (dts.AudioPresentationType != AudioPresentationType.Reserved)
198                                                                                         si.AudioPresentationType = dts.AudioPresentationType;
199                                                                                 if (dts.SamplingFrequency != SamplingFrequency.Reserved)
200                                                                                         si.SamplingFrequency = dts.SamplingFrequency;
201                                                                         }
202                                                         }
203                                                 break;
204                                         case ElementaryStreamTypes.VIDEO_STREAM_MPEG2:
205                                                 if ((si.ElementaryDescriptors == null) ||
206                                                         si.FrameRate == FrameRate.Reserved ||
207                                                         si.VideoFormat == VideoFormat.Reserved ||
208                                                         si.AspectRatio == AspectRatio.Reserved)
209                                                         {
210                                                                 Mpeg2Info mpeg2 = new Mpeg2Info(payload, 0);
211                                                                 if (mpeg2.Valid)
212                                                                         {
213                                                                                 if (mpeg2.AspectRatio != AspectRatio.Reserved)
214                                                                                         si.AspectRatio = mpeg2.AspectRatio;
215                                                                                 if (mpeg2.FrameRate != FrameRate.Reserved)
216                                                                                         si.FrameRate = mpeg2.FrameRate;
217                                                                                 if (mpeg2.VideoFormat != VideoFormat.Reserved)
218                                                                                         si.VideoFormat = mpeg2.VideoFormat;
219                                                                                 if (si.ElementaryDescriptors == null)
220                                                                                         si.ElementaryDescriptors = mpeg2.ElementaryDescriptors;
221                                                                         }
222                                                         }
223                                                 break;
224                                 }
225                         }
226                         
227 TsFileType PesFile::GetFileType(FileStream fs)
228 {
229         pByte inBuff = pByte(new byte[Constant::STRIDE_SIZE * 7]);
230         int offset;
231         fs.Seek(0, SeekOrigin.Begin);
232         
233         if (fs.Read(inBuff, 0, sizeof(inBuff.get())) != sizeof(inBuff.get()))
234                 throw std::invalid_argument("The specified file is too short");
235         
236         // try ts
237         for (offset = 0; offset < Constants::STRIDE_SIZE; offset++)
238         {
239                 if (inBuff[offset] == Constants::SYNC_BYTE)
240                 {
241                         if (inBuff[offset + Constants::TS_SIZE] == Constants::SYNC_BYTE &&
242                                 inBuff[offset + (Constants::TS_SIZE * 2)] == Constants::SYNC_BYTE &&
243                                 inBuff[offset + (Constants::TS_SIZE * 3)] == Constants::SYNC_BYTE &&
244                                 inBuff[offset + (Constants::TS_SIZE * 4)] == Constants::SYNC_BYTE &&
245                                 inBuff[offset + (Constants::TS_SIZE * 5)] == Constants::SYNC_BYTE)
246                                 return TsFileType::TS;
247                         else if (inBuff[offset + Constants::STRIDE_SIZE] == Constants::SYNC_BYTE &&
248                                          inBuff[offset + (Constants::STRIDE_SIZE * 2)] == Constants::SYNC_BYTE &&
249                                          inBuff[offset + (Constants::STRIDE_SIZE * 3)] == Constants::SYNC_BYTE &&
250                                          inBuff[offset + (Constants::STRIDE_SIZE * 4)] == Constants::SYNC_BYTE &&
251                                          inBuff[offset + (Constants::STRIDE_SIZE * 5)] == Constants::SYNC_BYTE)
252                                 return TsFileTyp::M2TS;
253                 }
254         }
255         // try SUP
256         if ((inBuff[0] == (byte)'P' || inBuff[0] == (byte)'p') &&
257                 (inBuff[1] == (byte)'G' || inBuff[1] == (byte)'g'))
258                 return TsFileType::SUP_ELEMENTARY;
259         // try EVOB
260         UInt32 marker = 0xffffffff;
261         int stuffing = 0;
262         bool packstart = false;
263         for (int i = 0; i < sizeof(inBuff.get()); i++)
264         {
265                 marker = marker << 8;
266                 marker &= 0xffffff00;
267                 marker += inBuff[i];
268                 if ((marker & 0xffffff00) == 0x00000100)
269                 {
270                         switch (marker & 0xff)
271                         {
272                         case 0xba:
273                                 // pack start code
274                                 if (sizeof(inBuff.get()) < i + 11)
275                                 {
276                                         i = sizeof(inBuff.get());
277                                         break;
278                                 }
279                                 i += 10;
280                                 stuffing = inBuff[i] & 0x7;
281                                 if (sizeof(inBuff.get()) < i + stuffing + 1)
282                                 {
283                                         i = sizeof(inBuff.get());
284                                         break;
285                                 }
286                                 i += stuffing;
287                                 stuffing = 0;
288                                 marker = 0xffffffff;
289                                 packstart = true;
290                                 break;
291                         default:
292                                 // other PES packet
293                                 if (sizeof(inBuff.get()) < i + 3)
294                                 {
295                                         i = sizeof(inBuff.get());
296                                         break;
297                                 }
298                                 stuffing = (inBuff[i + 1] << 8) + inBuff[i + 2];
299                                 i += 2;
300                                 if (sizeof(inBuff.get()) < i + stuffing)
301                                         {
302                                                 i = sizeof(inBuff.get());
303                                                 break;
304                                         }
305                                 i += stuffing;
306                                 stuffing = 0;
307                                 marker = 0xffffffff;
308                                 break;
309                         }
310                 }
311         }
312         if (packstart)
313                 return TsFileType::EVOB;
314         // try MKV
315         marker = 0xffffffff;
316         for (int i = 0; i < sizeof(inBuff.get()); i++)
317         {
318                 marker = marker << 8;
319                 marker &= 0xffffff00;
320                 marker += inBuff[i];
321                 if (marker == Constants::MKVFILE_START)
322                         return TsFileType::MKV;
323         }
324         throw std::invalid_argument("The specified file is not a valid TS/M2TS/EVOB/MKV file");
325 }
326                         
327 boost::shared_ptr<PesFile> PesFile::OpenFile(string path, bool useAsync, BackgroundWorker openWorker)
328 {
329         PesFile pf = null;
330         FileStream fs = null;
331         // pending
332         //      fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, Constant::DISK_BUFFER, useAsync); 
333         try
334         {
335                 TsIo tsior = new TsIo(fs, null, Constants::DISK_BUFFER ); 
336                 TsFileType fileType = GetFileType(fs);
337                 switch (fileType)
338                 {
339                 case TsFileType::EVOB:
340                         pf = new EvoPesFile(openWorker);
341                         break;
342                 case TsFileType::M2TS:
343                         pf = new TsPesFile(openWorker,4);
344                         break;
345                 case TsFileType::TS:
346                         pf = new TsPesFile(openWorker,0);
347                         break;
348                 case TsFileType::SUP_ELEMENTARY:
349                         pf = new SupPesFile(openWorker);
350                         break;
351                 case TsFileType::MKV:
352                         pf = new MkvPesFile(openWorker);
353                         break;
354                 }
355                 pf.fileType = fileType;
356                 pf.fs = fs;
357                 pf.tsior = tsior;
358                 pf.GetInitialValues();
359                 pf.ParseElementaryStreams();
360         }
361         catch (Exception)
362         {
363                 fs.Close();
364                 throw;
365         }
366         return pf;
367 }
368                         
369                         public void CloseFile()
370                         {
371                                 fs.Close();
372                                 fs = null;
373                                 tsior = null;
374                         }
375                         
376                         public void Clear()
377                         {
378                                 tsior.Clear();
379                         }
380                         
381                         public TsFileType FileType
382                         {
383                                 get { return fileType; }
384                         }
385                         
386                         public StreamInfo[] StreamInfos
387                         {
388                                 get { return sis; }
389                         }
390                         
391                         public TimeSpan VideoLength
392                         {
393                                 get
394                                 {
395                                         Int64 span = endPcr - startPcr;
396                                         if (span < 0)
397                                                 span += Constants.MAX_MPEG2TS_CLOCK;
398                                         return new TimeSpan((span * 10) / 27);
399                                 }
400                         }
401                         
402                         public abstract PesPacket[] GetNextPesPackets();
403                         public abstract void Seek(Int64 pcr);
404                         public abstract DTCP_Descriptor DtcpInfo { get; }
405                         protected abstract void GetInitialValues();
406                 }
407         
408     public class EvoPesFile : PesFile
409                 {
410                         private Dictionary<ushort, List<byte>> soundFrames;
411                         private Int64 lastPcr;
412                         
413                         public EvoPesFile(BackgroundWorker bw)
414             : base(bw)
415                         {
416                                 soundFrames = new Dictionary<ushort, List<byte>>();
417                                 lastPcr = 0 - Constants.MPEG2TS_CLOCK_RATE;
418                         }
419                         
420                         public override DTCP_Descriptor DtcpInfo
421                         {
422                                 get { return null; }
423                         }
424                         
425                         protected override void GetInitialValues()
426                         {
427                                 GetTimeStamps();
428                                 
429                                 Dictionary<byte, StreamInfo> evoStreams = new Dictionary<byte, StreamInfo>();
430                                 fs.Seek(0, SeekOrigin.Begin);
431                                 byte[] inBuff = new byte[Constants.DISK_BUFFER]; // 72MB IS TOO BIG! CAUSES FAILURE: << 2]; note this was line 463
432                                 int Length = fs.Read(inBuff, 0, inBuff.Length);
433                                 UInt32 marker = 0xffffffff;
434                                 int stuffing = 0;
435                                 for (int i = 0; i < Length; i++)
436                                         {
437                                                 ReportProgress(50 * i / Length);
438                                                 marker = marker << 8;
439                                                 marker &= 0xffffff00;
440                                                 marker += inBuff[i];
441                                                 if ((marker & 0xffffff00) == 0x00000100)
442                                                         {
443                                                                 switch (marker & 0xff)
444                                                                 {
445                                                                         case 0xba:
446                                                                                 // pack start code
447                                                                                 if (Length <= i + 10)
448                                                                                         {
449                                                                                                 i = Length;
450                                                                                                 break;
451                                                                                         }
452                                                                                 i += 10;
453                                                                                 stuffing = inBuff[i] & 0x7;
454                                                                                 if (Length <= i + stuffing)
455                                                                                         {
456                                                                                                 i = Length;
457                                                                                                 break;
458                                                                                         }
459                                                                                 i += stuffing;
460                                                                                 stuffing = 0;
461                                                                                 break;
462                                                                         default:
463                                                                                 if (inBuff[i] == Constants.PES_PRIVATE1)
464                                                                                         {
465                                                                                                 // skip to the end of the header
466                                                                                                 int endOfHeader = i + 6 + inBuff[i + 5];
467                                                                                                 if (inBuff.Length > endOfHeader + 4)
468                                                                                                         {
469                                                                                                                 if ((inBuff[endOfHeader] & 0xe0) == Constants.PES_PRIVATE_SUBTITLE)
470                                                                                                                         {
471                                                                                                                                 byte subid = inBuff[endOfHeader];
472                                                                                                                                 if (evoStreams.ContainsKey(subid) == false)
473                                                                                                                                         {
474                                                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.PRESENTATION_GRAPHICS_STREAM, subid);
475                                                                                                                                                 evoStreams.Add(subid, si);
476                                                                                                                                         }
477                                                                                                                         }
478                                                                                                                 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_AC3)
479                                                                                                                         {
480                                                                                                                                 byte subid = inBuff[endOfHeader];
481                                                                                                                                 if (evoStreams.ContainsKey(subid) == false)
482                                                                                                                                         {
483                                                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3, subid);
484                                                                                                                                                 evoStreams.Add(subid, si);
485                                                                                                                                         }
486                                                                                                                         }
487                                                                                                                 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_DTS_HD)
488                                                                                                                         {
489                                                                                                                                 byte subid = inBuff[endOfHeader];
490                                                                                                                                 if (evoStreams.ContainsKey(subid) == false)
491                                                                                                                                         {
492                                                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_DTS_HD, subid);
493                                                                                                                                                 evoStreams.Add(subid, si);
494                                                                                                                                         }
495                                                                                                                         }
496                                                                                                                 else if ((inBuff[endOfHeader] & 0xf0) == Constants.PES_PRIVATE_AC3_PLUS)
497                                                                                                                         {
498                                                                                                                                 byte subid = inBuff[endOfHeader];
499                                                                                                                                 if (evoStreams.ContainsKey(subid) == false)
500                                                                                                                                         {
501                                                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS, subid);
502                                                                                                                                                 evoStreams.Add(subid, si);
503                                                                                                                                         }
504                                                                                                                         }
505                                                                                                                 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_LPCM)
506                                                                                                                         {
507                                                                                                                                 byte subid = inBuff[endOfHeader];
508                                                                                                                                 if (evoStreams.ContainsKey(subid) == false)
509                                                                                                                                         {
510                                                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_LPCM, subid);
511                                                                                                                                                 evoStreams.Add(subid, si);
512                                                                                                                                         }
513                                                                                                                         }
514                                                                                                                 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_AC3_TRUE_HD)
515                                                                                                                         {
516                                                                                                                                 byte subid = inBuff[endOfHeader];
517                                                                                                                                 if (evoStreams.ContainsKey(subid) == false)
518                                                                                                                                         {
519                                                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD, subid);
520                                                                                                                                                 evoStreams.Add(subid, si);
521                                                                                                                                         }
522                                                                                                                         }
523                                                                                                         }
524                                                                                         }
525                                                                                 else if ((inBuff[i] & 0xe0) == Constants.PES_AUDIO_MPEG)
526                                                                                         {
527                                                                                                 byte subid = inBuff[i];
528                                                                                                 if (evoStreams.ContainsKey(subid) == false)
529                                                                                                         {
530                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_MPEG2, subid);
531                                                                                                                 evoStreams.Add(subid, si);
532                                                                                                         }
533                                                                                         }
534                                                                                 else if ((inBuff[i] & 0xf0) == Constants.PES_VIDEO)
535                                                                                         {
536                                                                                                 byte subid = inBuff[i];
537                                                                                                 if (evoStreams.ContainsKey(subid) == false)
538                                                                                                         {
539                                                                                                                 // need to differenciate between H.264 and MPEG2
540                                                                                                                 if (Length <= i + 5)
541                                                                                                                         {
542                                                                                                                                 i = Length;
543                                                                                                                                 break;
544                                                                                                                         }
545                                                                                                                 ElementaryStreamTypes videoFormat = ElementaryStreamTypes.INVALID;
546                                                                                                                 int startIndex = i + 6 + inBuff[i + 5];
547                                                                                                                 if (Length <= startIndex + 3)
548                                                                                                                         {
549                                                                                                                                 i = Length;
550                                                                                                                                 break;
551                                                                                                                         }
552                                                                                                                 UInt32 format = (UInt32)inBuff[startIndex] << 24;
553                                                                                                                 format += (UInt32)inBuff[startIndex + 1] << 16;
554                                                                                                                 format += (UInt32)inBuff[startIndex + 2] << 8;
555                                                                                                                 format += inBuff[startIndex + 3];
556                                                                                                                 if ((format & 0xffff) == 0x1)
557                                                                                                                         {
558                                                                                                                                 videoFormat = ElementaryStreamTypes.VIDEO_STREAM_H264;
559                                                                                                                                 StreamInfo si = new StreamInfo(videoFormat, subid);
560                                                                                                                                 evoStreams.Add(subid, si);
561                                                                                                                         }
562                                                                                                                 else if ((format & 0xffffff00) == 0x100)
563                                                                                                                         {
564                                                                                                                                 videoFormat = ElementaryStreamTypes.VIDEO_STREAM_MPEG2;
565                                                                                                                                 StreamInfo si = new StreamInfo(videoFormat, subid);
566                                                                                                                                 evoStreams.Add(subid, si);
567                                                                                                                         }
568                                                                                                         }
569                                                                                         }
570                                                                                 else if (inBuff[i] == Constants.PES_VIDEO_VC1)
571                                                                                         {
572                                                                                                 byte subid = GetVC1SubstreamId(inBuff, i + 3);
573                                                                                                 if (subid != 0 && evoStreams.ContainsKey(subid) == false)
574                                                                                                         {
575                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_VC1, subid);
576                                                                                                                 si.ElementaryDescriptors = Constants.vc1_descriptor;
577                                                                                                                 evoStreams.Add(subid, si);
578                                                                                                         }
579                                                                                         }
580                                                                                 
581                                                                                 // other PES packet
582                                                                                 if (Length < i + 3)
583                                                                                         {
584                                                                                                 i = Length;
585                                                                                                 break;
586                                                                                         }
587                                                                                 stuffing = (inBuff[i + 1] << 8) + inBuff[i + 2];
588                                                                                 i += 2;
589                                                                                 if (Length < i + stuffing)
590                                                                                         {
591                                                                                                 i = Length;
592                                                                                                 break;
593                                                                                         }
594                                                                                 i += stuffing;
595                                                                                 stuffing = 0;
596                                                                                 break;
597                                                                 }
598                                                                 marker = 0xffffffff;
599                                                         }
600                                         }
601                                 if (evoStreams.Count > 0)
602                                         {
603                                                 sis = new StreamInfo[evoStreams.Values.Count];
604                                                 evoStreams.Values.CopyTo(sis, 0);
605                                         }
606                         }
607                         
608                         public override PesPacket[] GetNextPesPackets()
609                         {
610                                 // there was a big optimization opportunity here:
611                                 // this method added to partial packets one byte at a time
612                                 // the calls to PesPacket.AddData used about 40% of total CPU 
613                                 byte[] inData = new byte[1];
614                                 byte[] inData2 = new byte[128]; 
615                                 int bytesRead = 0;
616                                 int bytesToRead = 0;
617                                 int bytesToGo = 0;
618                                 UInt32 marker = 0xffffffff;
619                                 PesPacket pp = null;
620                                 PesPacket partial = null;
621                                 int i = 0;
622                                 while (tsior.Read(inData, 0, inData.Length) == inData.Length)
623                                         {
624                                                 marker = marker << 8;
625                                                 marker &= 0xffffff00;
626                                                 marker += inData[0];
627                                                 if ((marker & 0xffffff00) == 0x00000100)
628                                                         {
629                                                                 if ((marker & 0xff) == Constants.PACK_ID)
630                                                                         {
631                                                                                 // pack start code
632                                                                                 UInt64 header = 0;
633                                                                                 for (i = 4; i < 10; i++)
634                                                                                         {
635                                                                                                 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
636                                                                                                         goto done;
637                                                                                                 header <<= 8;
638                                                                                                 header |= inData[0];
639                                                                                         }
640                                                                                 for (i = 10; i < 14; i++) // skip mux rate etc.
641                                                                                         {
642                                                                                                 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
643                                                                                                         goto done;
644                                                                                         }
645                                                                                 Int64 pcr = (Int64)((header & 0x380000000000) >> 13);
646                                                                                 pcr |= (Int64)((header & 0x3fff8000000) >> 12);
647                                                                                 pcr |= (Int64)((header & 0x3fff800) >> 11);
648                                                                                 pcr *= 300;
649                                                                                 pcr |= (Int64)((header & 0x3fe) >> 1);
650                                                                                 Int64 delta = pcr - lastPcr;
651                                                                                 if (delta > Constants.MPEG2TS_CLOCK_RATE / 9)
652                                                                                         {
653                                                                                                 if (pcrDelegate != null)
654                                                                                                         pcrDelegate(pcr);
655                                                                                                 lastPcr = pcr;
656                                                                                         }
657                                                                         }
658                                                                 else if (((marker & 0xff) == Constants.SYS_ID)
659                                                                                  || ((marker & 0xff) == Constants.MAP_ID)
660                                                                                  || ((marker & 0xff) == Constants.PAD_ID)
661                                                                                  || ((marker & 0xff) == Constants.DIR_ID))
662                                                                         {
663                                                                                 ushort Length = 0;
664                                                                                 for (i = 4; i < 6; i++)
665                                                                                         {
666                                                                                                 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
667                                                                                                         goto done;
668                                                                                                 Length <<= 8;
669                                                                                                 Length |= inData[0];
670                                                                                         }
671                                                                                 Length += 6;
672                                                                                 for (i = 6; i < Length; i++)
673                                                                                         {
674                                                                                                 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
675                                                                                                         goto done;
676                                                                                         }
677                                                                         }
678                                                                 else
679                                                                         {
680                                                                                 byte end = inData[0];
681                                                                                 inData[0] = 0;
682                                                                                 partial = new PesPacket(inData, 0, 1, 0);
683                                                                                 partial.AddData(inData, 0, 1);
684                                                                                 inData[0] = 1;
685                                                                                 partial.AddData(inData, 0, 1);
686                                                                                 inData[0] = end;
687                                                                                 partial.AddData(inData, 0, 1);
688                                                                                 ushort Length = 0;
689                                                                                 for (i = 4; i < 6; i++)
690                                                                                         {
691                                                                                                 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
692                                                                                                         goto done;
693                                                                                                 partial.AddData(inData, 0, 1);
694                                                                                                 Length <<= 8;
695                                                                                                 Length |= inData[0];
696                                                                                         }
697                                                                                 Length += 6;
698                                                                                 // we don't need this byte-by-byte loop here, as we have just gotten the length:
699                                                                                 /*
700                                                                                  for (i = 6; i < Length; i++)
701                                                                                  {
702                                                                                  if (tsior.Read(inData, 0, inData.Length) != inData.Length)
703                                                                                  goto done;
704                                                                                  partial.AddData(inData, 0, 1);
705                                                                                  }
706                                                                                  */
707                                                                                 bytesToGo = Length - 6;
708                                                                                 while (bytesToGo > 0)
709                                                                                         {
710                                                                                                 bytesToRead = (bytesToGo > inData2.Length) ? inData2.Length : bytesToGo;
711                                                                                                 if ((bytesRead = tsior.Read(inData2, 0, bytesToRead)) != bytesToRead)
712                                                                                                         goto done;
713                                                                                                 partial.AddData(inData2, 0, bytesRead);
714                                                                                                 bytesToGo -= bytesRead;
715                                                                                         }
716                                                                                 pp = partial;
717                                                                                 PesHeader ph = partial.GetHeader();
718                                                                                 if (partial.BaseId == Constants.PES_PRIVATE1)
719                                                                                         {
720                                                                                                 if ((partial.ExtendedId & 0xf0) == Constants.PES_PRIVATE_AC3_PLUS ||
721                                                                                                         (partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_AC3)
722                                                                                                         {
723                                                                                                                 if (soundFrames.ContainsKey(partial.ExtendedId) == false)
724                                                                                                                         soundFrames.Add(partial.ExtendedId, new List<byte>());
725                                                                                                                 byte[] tempd = partial.GetPayload();
726                                                                                                                 for (int j = 4; j < tempd.Length; j++)
727                                                                                                                         soundFrames[partial.ExtendedId].Add(tempd[j]);
728                                                                                                                 tempd = soundFrames[partial.ExtendedId].ToArray();
729                                                                                                                 int len = 0;
730                                                                                                                 ushort mk2 = 0xffff;
731                                                                                                                 if (tempd.Length > 2 && tempd[0] == (byte)(Constants.AC3_SYNC >> 8) &&
732                                                                                                                         tempd[1] == (byte)(Constants.AC3_SYNC & 0xff))
733                                                                                                                         {
734                                                                                                                                 pp = null;
735                                                                                                                                 while (tempd.Length > 2 && tempd[0] == (byte)(Constants.AC3_SYNC >> 8)
736                                                                                                                                            && tempd[1] == (byte)(Constants.AC3_SYNC & 0xff))
737                                                                                                                                         {
738                                                                                                                                                 AC3Info ac3 = new AC3Info(tempd, 0);
739                                                                                                                                                 if (ac3.Valid == false || ac3.FrameLength == 0 || tempd.Length < ac3.FrameLength)
740                                                                                                                                                         break;
741                                                                                                                                                 if (pp == null)
742                                                                                                                                                         pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
743                                                                                                                                                 pp.AddData(tempd, 0, ac3.FrameLength);
744                                                                                                                                                 soundFrames[partial.ExtendedId].RemoveRange(0, ac3.FrameLength);
745                                                                                                                                                 tempd = soundFrames[partial.ExtendedId].ToArray();
746                                                                                                                                         }
747                                                                                                                                 if (pp != null)
748                                                                                                                                         {
749                                                                                                                                                 pp.Complete = true;
750                                                                                                                                                 goto done;
751                                                                                                                                         }
752                                                                                                                         }
753                                                                                                                 for (int j = 2; j < tempd.Length; j++)
754                                                                                                                         {
755                                                                                                                                 mk2 <<= 8;
756                                                                                                                                 mk2 |= tempd[j];
757                                                                                                                                 if (mk2 == Constants.AC3_SYNC)
758                                                                                                                                         {
759                                                                                                                                                 len = j - 1;
760                                                                                                                                                 mk2 = 0xffff;
761                                                                                                                                                 break;
762                                                                                                                                         }
763                                                                                                                         }
764                                                                                                                 if (len == 0)
765                                                                                                                         len = tempd.Length;
766                                                                                                                 soundFrames[partial.ExtendedId].RemoveRange(0, len);
767                                                                                                                 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
768                                                                                                                 pp.AddData(tempd, 0, len);
769                                                                                                                 pp.Complete = true;
770                                                                                                         }
771                                                                                                 else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_AC3_TRUE_HD)
772                                                                                                         {
773                                                                                                                 if (soundFrames.ContainsKey(partial.ExtendedId) == false)
774                                                                                                                         soundFrames.Add(partial.ExtendedId, new List<byte>());
775                                                                                                                 byte[] tempd = partial.GetPayload();
776                                                                                                                 for (int j = 5; j < tempd.Length; j++)
777                                                                                                                         soundFrames[partial.ExtendedId].Add(tempd[j]);
778                                                                                                                 tempd = soundFrames[partial.ExtendedId].ToArray();
779                                                                                                                 int len = tempd.Length;
780                                                                                                                 /*
781                                                                                                                  UInt32 mk2 = 0xffffffff;
782                                                                                                                  for (int j = 5; j < tempd.Length; j++)
783                                                                                                                  {
784                                                                                                                  mk2 <<= 8;
785                                                                                                                  mk2 |= tempd[j];
786                                                                                                                  if (mk2 == Constants.MLP_SYNC)
787                                                                                                                  {
788                                                                                                                  len = j - 3;
789                                                                                                                  mk2 = 0xffffffff;
790                                                                                                                  }
791                                                                                                                  }
792                                                                                                                  if (len == 0)
793                                                                                                                  {
794                                                                                                                  len = tempd.Length;
795                                                                                                                  }
796                                                                                                                  */
797                                                                                                                 soundFrames[partial.ExtendedId].RemoveRange(0, len);
798                                                                                                                 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
799                                                                                                                 pp.AddData(tempd, 0, len);
800                                                                                                                 pp.Complete = true;
801                                                                                                         }
802                                                                                                 else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_LPCM)
803                                                                                                         {
804                                                                                                                 if (soundFrames.ContainsKey(partial.ExtendedId) == false)
805                                                                                                                         soundFrames.Add(partial.ExtendedId, new List<byte>());
806                                                                                                                 byte[] tempd = partial.GetPayload();
807                                                                                                                 for (int j = 7; j < tempd.Length; j++)
808                                                                                                                         soundFrames[partial.ExtendedId].Add(tempd[j]);
809                                                                                                                 tempd = soundFrames[partial.ExtendedId].ToArray();
810                                                                                                                 int len = tempd.Length;
811                                                                                                                 /*
812                                                                                                                  UInt32 mk2 = 0xffffffff;
813                                                                                                                  for (int j = 5; j < tempd.Length; j++)
814                                                                                                                  {
815                                                                                                                  mk2 <<= 8;
816                                                                                                                  mk2 |= tempd[j];
817                                                                                                                  if (mk2 == Constants.MLP_SYNC)
818                                                                                                                  {
819                                                                                                                  len = j - 3;
820                                                                                                                  mk2 = 0xffffffff;
821                                                                                                                  }
822                                                                                                                  }
823                                                                                                                  if (len == 0)
824                                                                                                                  {
825                                                                                                                  len = tempd.Length;
826                                                                                                                  }
827                                                                                                                  */
828                                                                                                                 soundFrames[partial.ExtendedId].RemoveRange(0, len);
829                                                                                                                 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
830                                                                                                                 pp.AddData(tempd, 0, len);
831                                                                                                                 pp.Complete = true;
832                                                                                                         }
833                                                                                                 else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_DTS_HD)
834                                                                                                         {
835                                                                                                                 if (soundFrames.ContainsKey(partial.ExtendedId) == false)
836                                                                                                                         soundFrames.Add(partial.ExtendedId, new List<byte>());
837                                                                                                                 byte[] tempd = partial.GetPayload();
838                                                                                                                 for (int j = 4; j < tempd.Length; j++)
839                                                                                                                         soundFrames[partial.ExtendedId].Add(tempd[j]);
840                                                                                                                 tempd = soundFrames[partial.ExtendedId].ToArray();
841                                                                                                                 int len = 0;
842                                                                                                                 UInt32 mk2 = 0xffffffff;
843                                                                                                                 for (int j = 4; j < tempd.Length; j++)
844                                                                                                                         {
845                                                                                                                                 mk2 <<= 8;
846                                                                                                                                 mk2 |= tempd[j];
847                                                                                                                                 if (mk2 == Constants.DTS_SYNC)
848                                                                                                                                         {
849                                                                                                                                                 len = j - 3;
850                                                                                                                                                 mk2 = 0xffffffff;
851                                                                                                                                         }
852                                                                                                                         }
853                                                                                                                 if (len == 0)
854                                                                                                                         {
855                                                                                                                                 DtsInfo dts = new DtsInfo(tempd, 0);
856                                                                                                                                 if (dts.Valid && (int)dts.FrameSize < tempd.Length &&
857                                                                                                                                         (tempd.Length - (int)dts.FrameSize < 4))
858                                                                                                                                         len = (int)dts.FrameSize;
859                                                                                                                                 else
860                                                                                                                                         len = tempd.Length;
861                                                                                                                         }
862                                                                                                                 soundFrames[partial.ExtendedId].RemoveRange(0, len);
863                                                                                                                 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
864                                                                                                                 pp.AddData(tempd, 0, len);
865                                                                                                                 pp.Complete = true;
866                                                                                                         }
867                                                                                                 else
868                                                                                                         pp.PID = pp.ExtendedId;
869                                                                                         }
870                                                                                 else if (pp.BaseId == Constants.PES_PADDING || pp.BaseId == Constants.PES_PRIVATE2)
871                                                                                         {
872                                                                                                 marker = 0xffffffff;
873                                                                                                 continue;
874                                                                                         }
875                                                                                 else if (((pp.BaseId & 0xe0) == Constants.PES_AUDIO_MPEG)
876                                                                                                  || ((pp.BaseId & 0xf0) == Constants.PES_VIDEO))
877                                                                                         pp.PID = pp.BaseId;
878                                                                                 else if (pp.BaseId == Constants.PES_VIDEO_VC1 && ph != null)
879                                                                                         pp.PID = ph.Extention2;
880                                                                                 if (ph != null && ph.HasPts)
881                                                                                         {
882                                                                                                 if (ptsDelegate != null)
883                                                                                                         ptsDelegate(ph.Pts, pp.PID);
884                                                                                         }
885                                                                                 goto done;
886                                                                         }
887                                                                 marker = 0xffffffff;
888                                                         }
889                                         }
890                         done:
891                                 if (null != pp)
892                                         {
893                                                 PesPacket[] ppa = new PesPacket[1];
894                                                 ppa[0] = pp;
895                                                 return ppa;
896                                         }
897                                 else
898                                         return null;
899                         }
900                         
901                         public override void Seek(long pcr)
902                         {
903                                 tsior.Clear();
904                                 
905                                 if (pcr == -1)
906                                         {
907                                                 fs.Seek(0, SeekOrigin.Begin);
908                                                 return;
909                                         }
910                                 
911                                 int packetSize = sizeof(byte);
912                                 Int64 span = endPcr - startPcr;
913                                 if (span < 0)
914                                         span += Constants.MAX_MPEG2TS_CLOCK;
915                                 Int64 pcrPerByte = span / fs.Length;
916                                 Int64 seek = pcr - startPcr;
917                                 if (seek < 0)
918                                         seek += Constants.MAX_MPEG2TS_CLOCK;
919                                 Int64 length = seek / pcrPerByte;
920                                 length /= packetSize;
921                                 length *= packetSize;
922                                 if (length > fs.Length)
923                                         length = fs.Length;
924                                 fs.Seek(length, SeekOrigin.Begin);
925                                 bool found = false;
926                                 
927                                 while (found == false)
928                                         {
929                                                 Int64 offset = GetCurrentPcrFromFile();
930                                                 if (-1 == offset)
931                                                         offset = endPcr;
932                                                 offset -= pcr;
933                                                 if (offset > Constants.MAX_MPEG2TS_CLOCK / 2)
934                                                         offset -= Constants.MAX_MPEG2TS_CLOCK;
935                                                 else if (offset < (0 - (Constants.MAX_MPEG2TS_CLOCK / 2)))
936                                                         offset += Constants.MAX_MPEG2TS_CLOCK;
937                                                 Int64 target = offset / Constants.MPEG2TS_CLOCK_RATE;
938                                                 if (target > 0)
939                                                         {
940                                                                 offset /= pcrPerByte;
941                                                                 offset >>= 2;
942                                                                 offset /= packetSize;
943                                                                 offset *= packetSize;
944                                                                 fs.Seek(0 - offset, SeekOrigin.Current);
945                                                         }
946                                                 else if (target < 0)
947                                                         {
948                                                                 offset /= pcrPerByte;
949                                                                 offset >>= 2;
950                                                                 offset /= packetSize;
951                                                                 offset *= packetSize;
952                                                                 fs.Seek(0 - offset, SeekOrigin.Current);
953                                                         }
954                                                 else
955                                                         break;
956                                         }
957                         }
958                         
959                         private void GetTimeStamps()
960                         {
961                                 fs.Seek(0, SeekOrigin.Begin);
962                                 UInt64 header = 0xffffffff;
963                                 byte b = 0;
964                                 int packsize_reading = -1;
965                                 for (int i = 0; i < Constants.DISK_BUFFER; i++)
966                                         {
967                                                 int ib = fs.ReadByte();
968                                                 if (ib == -1)
969                                                         throw new FormatException("The specified file is too short");
970                                                 b = (byte)(ib & 0xff);
971                                                 header <<= 8;
972                                                 header |= b;
973                                                 if ((header & 0xffffffff) == 0x000001ba)
974                                                         {
975                                                                 // pack start code
976                                                                 packsize_reading = 5;
977                                                         }
978                                                 else if (packsize_reading > 0)
979                                                         packsize_reading--;
980                                                 else if (packsize_reading == 0)
981                                                         {
982                                                                 startPcr = (Int64)((header & 0x380000000000) >> 13);
983                                                                 startPcr |= (Int64)((header & 0x3fff8000000) >> 12);
984                                                                 startPcr |= (Int64)((header & 0x3fff800) >> 11);
985                                                                 startPcr *= 300;
986                                                                 startPcr |= (Int64)((header & 0x3fe) >> 1);
987                                                                 break;
988                                                         }
989                                         }
990                                 int lseek = -15;
991                                 fs.Seek(lseek, SeekOrigin.End);
992                                 header = 0xffffffff;
993                                 b = 0;
994                                 packsize_reading = -1;
995                                 for (int i = 0; i < Constants.DISK_BUFFER; i++)
996                                         {
997                                                 for (int j = 0; j < 12; j++)
998                                                         {
999                                                                 int ib = fs.ReadByte();
1000                                                                 if (ib == -1)
1001                                                                         throw new FormatException("The specified file is too short");
1002                                                                 b = (byte)(ib & 0xff);
1003                                                                 header <<= 8;
1004                                                                 header |= b;
1005                                                                 if ((header & 0xffffffff) == 0x000001ba)
1006                                                                         {
1007                                                                                 // pack start code
1008                                                                                 packsize_reading = 5;
1009                                                                         }
1010                                                                 else if (packsize_reading > 0)
1011                                                                         packsize_reading--;
1012                                                                 else if (packsize_reading == 0)
1013                                                                         {
1014                                                                                 endPcr = (Int64)((header & 0x380000000000) >> 13);
1015                                                                                 endPcr |= (Int64)((header & 0x3fff8000000) >> 12);
1016                                                                                 endPcr |= (Int64)((header & 0x3fff800) >> 11);
1017                                                                                 endPcr *= 300;
1018                                                                                 endPcr |= (Int64)((header & 0x3fe) >> 1);
1019                                                                                 break;
1020                                                                         }
1021                                                         }
1022                                                 if (packsize_reading == 0)
1023                                                         break;
1024                                                 lseek--;
1025                                                 fs.Seek(lseek, SeekOrigin.End);
1026                                                 
1027                                         }
1028                         }
1029                         
1030                         private byte GetVC1SubstreamId(byte[] buff, int offset)
1031                         {
1032                                 if (buff.Length <= offset + 3)
1033                                         return 0;
1034                                 if ((buff[offset] & 0xc0) != 0x80)
1035                                         return 0; // first two bits must be '10'
1036                                 byte PTS_DTS_flags = (byte)(buff[offset + 1] & 0xc0);
1037                                 byte ESCR_flag = (byte)(buff[offset + 1] & 0x20);
1038                                 byte ES_rate_flag = (byte)(buff[offset + 1] & 0x10);
1039                                 byte DSM_trick_mode_flag = (byte)(buff[offset + 1] & 0x08);
1040                                 byte additional_copy_info_flag = (byte)(buff[offset + 1] & 0x04);
1041                                 byte PES_CRC_flag = (byte)(buff[offset + 1] & 0x02);
1042                                 byte PES_extension_flag = (byte)(buff[offset + 1] & 0x01);
1043                                 if (buff[offset + 2] == 0)
1044                                         return 0;
1045                                 int length = offset + buff[offset + 2] + 3;
1046                                 if (buff.Length < length)
1047                                         return 0;
1048                                 offset += 3;
1049                                 if (PTS_DTS_flags == 0x80)
1050                                         offset += 5;
1051                                 if (PTS_DTS_flags == 0xc0)
1052                                         offset += 10;
1053                                 if (ESCR_flag > 0)
1054                                         offset += 6;
1055                                 if (ES_rate_flag > 0)
1056                                         offset += 3;
1057                                 if (DSM_trick_mode_flag > 0)
1058                                         offset += 1;
1059                                 if (additional_copy_info_flag > 0)
1060                                         offset += 1;
1061                                 if (PES_CRC_flag > 0)
1062                                         offset += 2;
1063                                 if (PES_extension_flag == 0)
1064                                         return 0;
1065                                 byte PES_private_data_flag = (byte)(buff[offset] & 0x80);
1066                                 byte pack_header_field_flag = (byte)(buff[offset] & 0x40);
1067                                 byte program_packet_sequence_counter_flag = (byte)(buff[offset] & 0x20);
1068                                 byte PSTD_buffer_flag = (byte)(buff[offset] & 0x10);
1069                                 byte PES_extension_flag_2 = (byte)(buff[offset] & 0x01);
1070                                 offset++;
1071                                 if (PES_private_data_flag > 0)
1072                                         offset += 25;
1073                                 if (pack_header_field_flag > 0)
1074                                         offset += (buff[offset] + 1);
1075                                 if (program_packet_sequence_counter_flag > 0)
1076                                         offset += 2;
1077                                 if (PSTD_buffer_flag > 0)
1078                                         offset += 2;
1079                                 if (PES_extension_flag_2 == 0)
1080                                         return 0;
1081                                 if (buff[offset] != 0x81)
1082                                         return 0;
1083                                 return buff[offset + 1];
1084                         }
1085                         
1086                         private Int64 GetCurrentPcrFromFile()
1087                         {
1088                                 UInt64 header = 0xffffffff;
1089                                 byte b = 0;
1090                                 int packsize_reading = -1;
1091                                 for (int i = 0; i < Constants.DISK_BUFFER; i++)
1092                                         {
1093                                                 int ib = fs.ReadByte();
1094                                                 if (ib == -1)
1095                                                         return -1;
1096                                                 b = (byte)(ib & 0xff);
1097                                                 header <<= 8;
1098                                                 header |= b;
1099                                                 if ((header & 0xffffffff) == 0x000001ba)
1100                                                         {
1101                                                                 // pack start code
1102                                                                 packsize_reading = 5;
1103                                                         }
1104                                                 else if (packsize_reading > 0)
1105                                                         packsize_reading--;
1106                                                 else if (packsize_reading == 0)
1107                                                         {
1108                                                                 Int64 pcr = (Int64)((header & 0x380000000000) >> 13);
1109                                                                 pcr |= (Int64)((header & 0x3fff8000000) >> 12);
1110                                                                 pcr |= (Int64)((header & 0x3fff800) >> 11);
1111                                                                 pcr *= 300;
1112                                                                 pcr |= (Int64)((header & 0x3fe) >> 1);
1113                                                                 return pcr;
1114                                                         }
1115                                         }
1116                                 return -1;
1117                         }
1118                 }
1119         
1120     public class SupPesFile : PesFile
1121                 {
1122                         private static readonly byte[] PesTemplate = new byte[4] {
1123             0x00, 0x00, 0x01, 0xbd};
1124                         
1125                         public SupPesFile(BackgroundWorker bw) : base(bw) { }
1126                         
1127                         public override DTCP_Descriptor DtcpInfo
1128                         {
1129                                 get { return null; }
1130                         }
1131                         
1132                         protected override void GetInitialValues()
1133                         {
1134                                 GetTimeStamps();
1135                                 this.sis = new StreamInfo[1];
1136                                 this.sis[0] = new StreamInfo(ElementaryStreamTypes.PRESENTATION_GRAPHICS_STREAM, Constants.DEFAULT_PRESENTATION_GRAPHICS_PID);
1137                         }
1138                         
1139                         public override PesPacket[] GetNextPesPackets()
1140                         {
1141                                 byte b0 = 0;
1142                                 byte b1 = 0;
1143                                 byte[] inData = new byte[1];
1144                                 byte[] pgHeader = new byte[3];
1145                                 
1146                                 while (tsior.Read(inData, 0, inData.Length) == inData.Length)
1147                                         {
1148                                                 b0 = b1;
1149                                                 b1 = inData[0];
1150                                                 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1151                                                         (b1 == (byte)'G' || b1 == (byte)'g'))
1152                                                         {
1153                                                                 Int64 Pts = 0;
1154                                                                 Int64 Dts = 0;
1155                                                                 ushort len = 0;
1156                                                                 for (int k = 0; k < 4; k++)
1157                                                                         {
1158                                                                                 if (0 == tsior.Read(inData, 0, inData.Length))
1159                                                                                         return null;
1160                                                                                 Pts <<= 8;
1161                                                                                 Pts |= inData[0];
1162                                                                         }
1163                                                                 Pts <<= 1;
1164                                                                 if (ptsDelegate != null)
1165                                                                         ptsDelegate(Pts, sis[0].ElementaryPID);
1166                                                                 for (int k = 0; k < 4; k++)
1167                                                                         {
1168                                                                                 if (0 == tsior.Read(inData, 0, inData.Length))
1169                                                                                         return null;
1170                                                                                 Dts <<= 8;
1171                                                                                 Dts |= inData[0];
1172                                                                         }
1173                                                                 Dts <<= 1;
1174                                                                 for (int k = 0; k < 3; k++)
1175                                                                         {
1176                                                                                 if (0 == tsior.Read(inData, 0, inData.Length))
1177                                                                                         return null;
1178                                                                                 pgHeader[k] = inData[0];
1179                                                                                 if (k > 0)
1180                                                                                         {
1181                                                                                                 len <<= 8;
1182                                                                                                 len |= inData[0];
1183                                                                                         }
1184                                                                         }
1185                                                                 byte hlen = (byte)(Dts == 0 ? 0x05 : 0x0a);
1186                                                                 ushort plen = (ushort)(6 + hlen + len);
1187                                                                 PesPacket pp = new PesPacket(PesTemplate, 0, PesTemplate.Length, sis[0].ElementaryPID);
1188                                                                 inData[0] = (byte)((plen >> 8) & 0xff);
1189                                                                 pp.AddData(inData, 0, 1);
1190                                                                 inData[0] = (byte)(plen & 0xff);
1191                                                                 pp.AddData(inData, 0, 1);
1192                                                                 inData[0] = 0x81;
1193                                                                 pp.AddData(inData, 0, 1);
1194                                                                 inData[0] = (byte)(Dts == 0 ? 0x80 : 0xc0);
1195                                                                 pp.AddData(inData, 0, 1);
1196                                                                 inData[0] = hlen;
1197                                                                 pp.AddData(inData, 0, 1);
1198                                                                 byte old = (byte)(Dts == 0 ? 0x21 : 0x31);
1199                                                                 inData[0] = (byte)(((Pts & 0x1C0000000) >> 29) | old);
1200                                                                 pp.AddData(inData, 0, 1);
1201                                                                 inData[0] = (byte)((Pts & 0x3fC00000) >> 22);
1202                                                                 pp.AddData(inData, 0, 1);
1203                                                                 inData[0] = (byte)(((Pts & 0x3f8000) >> 14) | 0x01);
1204                                                                 pp.AddData(inData, 0, 1);
1205                                                                 inData[0] = (byte)((Pts & 0x7f80) >> 7);
1206                                                                 pp.AddData(inData, 0, 1);
1207                                                                 inData[0] = (byte)(((Pts & 0x7f) << 1) | 0x01);
1208                                                                 pp.AddData(inData, 0, 1);
1209                                                                 if (Dts != 0)
1210                                                                         {
1211                                                                                 inData[0] = (byte)(((Dts & 0x1C0000000) >> 29) | 0x11);
1212                                                                                 pp.AddData(inData, 0, 1);
1213                                                                                 inData[0] = (byte)((Dts & 0x3fC00000) >> 22);
1214                                                                                 pp.AddData(inData, 0, 1);
1215                                                                                 inData[0] = (byte)(((Dts & 0x3f8000) >> 14) | 0x01);
1216                                                                                 pp.AddData(inData, 0, 1);
1217                                                                                 inData[0] = (byte)((Dts & 0x7f80) >> 7);
1218                                                                                 pp.AddData(inData, 0, 1);
1219                                                                                 inData[0] = (byte)(((Dts & 0x7f) << 1) | 0x01);
1220                                                                                 pp.AddData(inData, 0, 1);
1221                                                                         }
1222                                                                 pp.AddData(pgHeader, 0, pgHeader.Length);
1223                                                                 for (int k = 0; k < len; k++)
1224                                                                         {
1225                                                                                 if (0 == tsior.Read(inData, 0, inData.Length))
1226                                                                                         return null;
1227                                                                                 pp.AddData(inData, 0, 1);
1228                                                                         }
1229                                                                 PesPacket[] ppa = new PesPacket[1];
1230                                                                 ppa[0] = pp;
1231                                                                 return ppa;
1232                                                         }
1233                                         }
1234                                 return null;
1235                         }
1236                         
1237                         public override void Seek(long pcr)
1238                         {
1239                                 tsior.Clear();
1240                                 
1241                                 if (pcr == -1)
1242                                         {
1243                                                 fs.Seek(0, SeekOrigin.Begin);
1244                                                 return;
1245                                         }
1246                                 
1247                                 int packetSize = sizeof(byte);
1248                                 Int64 span = endPcr - startPcr;
1249                                 if (span < 0)
1250                                         span += Constants.MAX_MPEG2TS_CLOCK;
1251                                 Int64 pcrPerByte = span / fs.Length;
1252                                 Int64 seek = pcr - startPcr;
1253                                 if (seek < 0)
1254                                         seek += Constants.MAX_MPEG2TS_CLOCK;
1255                                 Int64 length = seek / pcrPerByte;
1256                                 length /= packetSize;
1257                                 length *= packetSize;
1258                                 if (length > fs.Length)
1259                                         length = fs.Length;
1260                                 fs.Seek(length, SeekOrigin.Begin);
1261                                 bool found = false;
1262                                 
1263                                 while (found == false)
1264                                         {
1265                                                 Int64 offset = GetCurrentPcrFromFile();
1266                                                 if (-1 == offset)
1267                                                         offset = endPcr;
1268                                                 offset -= pcr;
1269                                                 if (offset > Constants.MAX_MPEG2TS_CLOCK / 2)
1270                                                         offset -= Constants.MAX_MPEG2TS_CLOCK;
1271                                                 else if (offset < (0 - (Constants.MAX_MPEG2TS_CLOCK / 2)))
1272                                                         offset += Constants.MAX_MPEG2TS_CLOCK;
1273                                                 Int64 target = offset / Constants.MPEG2TS_CLOCK_RATE;
1274                                                 if (target > 0)
1275                                                         {
1276                                                                 offset /= pcrPerByte;
1277                                                                 offset >>= 2;
1278                                                                 offset /= packetSize;
1279                                                                 offset *= packetSize;
1280                                                                 fs.Seek(0 - offset, SeekOrigin.Current);
1281                                                         }
1282                                                 else if (target < 0)
1283                                                         {
1284                                                                 offset /= pcrPerByte;
1285                                                                 offset >>= 2;
1286                                                                 offset /= packetSize;
1287                                                                 offset *= packetSize;
1288                                                                 fs.Seek(0 - offset, SeekOrigin.Current);
1289                                                         }
1290                                                 else
1291                                                         break;
1292                                         }
1293                         }
1294                         
1295                         private Int64 GetCurrentPcrFromFile()
1296                         {
1297                                 byte b0 = 0;
1298                                 byte b1 = 0;
1299                                 Int64 pcr = 0;
1300                                 while (true)
1301                                         {
1302                                                 int ib = fs.ReadByte();
1303                                                 if (ib == -1)
1304                                                         return -1;
1305                                                 b0 = b1;
1306                                                 b1 = (byte)(ib & 0xff);
1307                                                 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1308                                                         (b1 == (byte)'G' || b1 == (byte)'g'))
1309                                                         {
1310                                                                 pcr = 0;
1311                                                                 for (int k = 0; k < 4; k++)
1312                                                                         {
1313                                                                                 ib = fs.ReadByte();
1314                                                                                 if (ib == -1)
1315                                                                                         return -1;
1316                                                                                 b1 = (byte)(ib & 0xff);
1317                                                                                 pcr <<= 8;
1318                                                                                 pcr |= b1;
1319                                                                         }
1320                                                                 pcr *= (Constants.MPEG2TS_CLOCK_RATE / Constants.PTS_CLOCK_RATE);
1321                                                                 break;
1322                                                         }
1323                                         }
1324                                 return pcr;
1325                         }
1326                         
1327                         private void GetTimeStamps()
1328                         {
1329                                 fs.Seek(0, SeekOrigin.Begin);
1330                                 byte b0 = 0;
1331                                 byte b1 = 0;
1332                                 for (int i = 0; i < Constants.DISK_BUFFER; i++)
1333                                         {
1334                                                 int ib = fs.ReadByte();
1335                                                 if (ib == -1)
1336                                                         throw new FormatException("The specified file is too short");
1337                                                 b0 = b1;
1338                                                 b1 = (byte)(ib & 0xff);
1339                                                 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1340                                                         (b1 == (byte)'G' || b1 == (byte)'g'))
1341                                                         {
1342                                                                 startPcr = 0;
1343                                                                 for (int k = 0; k < 4; k++)
1344                                                                         {
1345                                                                                 ib = fs.ReadByte();
1346                                                                                 if (ib == -1)
1347                                                                                         throw new FormatException("The specified file is too short");
1348                                                                                 b1 = (byte)(ib & 0xff);
1349                                                                                 startPcr <<= 8;
1350                                                                                 startPcr |= b1;
1351                                                                         }
1352                                                                 startPcr *= (Constants.MPEG2TS_CLOCK_RATE / Constants.PTS_CLOCK_RATE);
1353                                                                 break;
1354                                                         }
1355                                         }
1356                                 int lseek = -10;
1357                                 fs.Seek(lseek, SeekOrigin.End);
1358                                 b0 = b1 = 0;
1359                                 bool found = false;
1360                                 for (int i = 0; i < Constants.DISK_BUFFER; i++)
1361                                         {
1362                                                 for (int j = 0; j < 2; j++)
1363                                                         {
1364                                                                 int ib = fs.ReadByte();
1365                                                                 if (ib == -1)
1366                                                                         throw new FormatException("The specified file is too short");
1367                                                                 b0 = b1;
1368                                                                 b1 = (byte)(ib & 0xff);
1369                                                                 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1370                                                                         (b1 == (byte)'G' || b1 == (byte)'g'))
1371                                                                         {
1372                                                                                 endPcr = 0;
1373                                                                                 for (int k = 0; k < 4; k++)
1374                                                                                         {
1375                                                                                                 ib = fs.ReadByte();
1376                                                                                                 if (ib == -1)
1377                                                                                                         throw new FormatException("The specified file is too short");
1378                                                                                                 b1 = (byte)(ib & 0xff);
1379                                                                                                 endPcr <<= 8;
1380                                                                                                 endPcr |= b1;
1381                                                                                         }
1382                                                                                 endPcr *= (Constants.MPEG2TS_CLOCK_RATE / Constants.PTS_CLOCK_RATE);
1383                                                                                 found = true;
1384                                                                                 break;
1385                                                                         }
1386                                                         }
1387                                                 if (found)
1388                                                         break;
1389                                                 lseek--;
1390                                                 fs.Seek(lseek, SeekOrigin.End);
1391                                         }
1392                         }
1393                 }
1394         
1395     public class TsPesFile : PesFile
1396                 {
1397                         private int stride;
1398                         private byte[] tsPack;
1399                         TsPacket ts;
1400                         private Dictionary<ushort, PesPacket> PesPackets;
1401                         private DTCP_Descriptor dt;
1402                         private ushort pcrPID;
1403                         
1404                         public TsPesFile(BackgroundWorker bw, int offset)
1405             : base(bw)
1406                         {
1407                                 stride = offset;
1408                                 tsPack = new byte[Constants.TS_SIZE + offset];
1409                                 ts = new TsPacket();
1410                                 PesPackets = new Dictionary<ushort, PesPacket>();
1411                                 dt = null;
1412                                 pcrPID = 0xffff;
1413                         }
1414                         
1415                         public override DTCP_Descriptor DtcpInfo
1416                         {
1417                                 get { return dt; }
1418                         }
1419                         
1420                         public override PesPacket[] GetNextPesPackets()
1421                         {
1422                                 int i;
1423                                 while (true)
1424                                         {
1425                                                 for (i = tsior.Read(tsPack, 0, 1 + stride); (i > 0) && (tsPack[stride] != Constants.SYNC_BYTE); i = tsior.Read(tsPack, stride, 1))
1426                                                         ; // ensure a good sync byte
1427                                                 if (i == 0)
1428                                                         {
1429                                                                 List<PesPacket> ppa = new List<PesPacket>();
1430                                                                 foreach (ushort pd in PesPackets.Keys)
1431                                                                 {
1432                                                                         PesPacket pp = PesPackets[pd];
1433                                                                         pp.Complete = true;
1434                                                                         ppa.Add(pp);
1435                                                                 }
1436                                                                 PesPackets.Clear();
1437                                                                 if (ppa.Count == 0)
1438                                                                         return null; // end of stream
1439                                                                 else
1440                                                                         {
1441                                                                                 return ppa.ToArray();
1442                                                                         }
1443                                                         }
1444                                                 i = tsior.Read(tsPack, stride + 1, tsPack.Length - (stride + 1));
1445                                                 if (i < tsPack.Length - (stride + 1))
1446                                                         {
1447                                                                 List<PesPacket> ppa = new List<PesPacket>();
1448                                                                 foreach (ushort pd in PesPackets.Keys)
1449                                                                 {
1450                                                                         PesPacket pp = PesPackets[pd];
1451                                                                         pp.Complete = true;
1452                                                                         ppa.Add(pp);
1453                                                                 }
1454                                                                 PesPackets.Clear();
1455                                                                 if (ppa.Count == 0)
1456                                                                         return null; // end of stream
1457                                                                 else
1458                                                                         return ppa.ToArray();
1459                                                         }
1460                                                 ts.SetData(tsPack, stride);
1461                                                 ushort pid = ts.PID;
1462                                                 byte[] payload = ts.Payload;
1463                                                 if (ts.HasPcr)
1464                                                         {
1465                                                                 if (null != pcrDelegate && pcrPID == pid)
1466                                                                         pcrDelegate(ts.Pcr);
1467                                                         }
1468                                                 if (ts.HasPesHeader)
1469                                                         {
1470                                                                 if (payload != null && payload.Length > 3 && payload[0] == 0x00
1471                                                                         && payload[1] == 0x00 && payload[2] == 0x01)
1472                                                                         {
1473                                                                                 PesPacket newpp = new PesPacket(payload, 0, payload.Length, pid);
1474                                                                                 newpp.Priority = ts.Priority;
1475                                                                                 PesHeader ph = newpp.GetHeader();
1476                                                                                 if (ph != null && ph.HasPts)
1477                                                                                         {
1478                                                                                                 if (ptsDelegate != null)
1479                                                                                                         ptsDelegate(ph.Pts, pid);
1480                                                                                         }
1481                                                                                 if (PesPackets.ContainsKey(pid))
1482                                                                                         {
1483                                                                                                 PesPacket pp = PesPackets[ts.PID];
1484                                                                                                 pp.Complete = true;
1485                                                                                                 PesPackets[ts.PID] = newpp;
1486                                                                                                 PesPacket[] ppa = new PesPacket[1];
1487                                                                                                 ppa[0] = pp;
1488                                                                                                 return ppa;
1489                                                                                         }
1490                                                                                 else
1491                                                                                         {
1492                                                                                                 if (newpp.Complete == true)
1493                                                                                                         {
1494                                                                                                                 PesPacket[] ppa = new PesPacket[1];
1495                                                                                                                 ppa[0] = newpp;
1496                                                                                                                 return ppa;
1497                                                                                                         }
1498                                                                                                 PesPackets[ts.PID] = newpp;
1499                                                                                         }
1500                                                                         }
1501                                                                 else
1502                                                                         {
1503                                                                                 throw new InvalidDataException("invalid stream");
1504                                                                         }
1505                                                         }
1506                                                 else if (PesPackets.ContainsKey(pid))
1507                                                         {
1508                                                                 PesPacket pp = PesPackets[ts.PID];
1509                                                                 if (payload != null)
1510                                                                         {
1511                                                                                 pp.AddData(payload, 0, payload.Length);
1512                                                                                 if (pp.Complete)
1513                                                                                         {
1514                                                                                                 PesPackets.Remove(pid);
1515                                                                                                 PesPacket[] ppa = new PesPacket[1];
1516                                                                                                 ppa[0] = pp;
1517                                                                                                 return ppa;
1518                                                                                         }
1519                                                                         }
1520                                                         }
1521                                         }
1522                         }
1523                         
1524                         private void GetTimestamps()
1525                         {
1526                                 int i = 0;
1527                                 
1528                                 startPcr = -1;
1529                                 endPcr = -1;
1530                                 if(null != tsior)
1531                                         tsior.Clear();
1532                                 fs.Seek(0, SeekOrigin.Begin);
1533                                 
1534                                 while (true)
1535                                         {
1536                                                 for (i = tsior.Read(tsPack, 0, 1 + stride); (i > 0) && (tsPack[stride] != Constants.SYNC_BYTE); i = tsior.Read(tsPack, stride, 1))
1537                                                         ; // ensure a good sync byte
1538                                                 if (i == 0)
1539                                                         return; // end of stream
1540                                                 i = tsior.Read(tsPack, stride + 1, tsPack.Length - (stride + 1));
1541                                                 if (i < tsPack.Length - (stride + 1))
1542                                                         return; // end of stream
1543                                                 ts.SetData(tsPack, stride);
1544                                                 if (ts.HasPcr)
1545                                                         {
1546                                                                 startPcr = ts.Pcr;
1547                                                                 pcrPID = ts.PID;
1548                                                                 break;
1549                                                         }
1550                                                 if (fs.Position > (Constants.DISK_BUFFER << 1))
1551                                                         return;
1552                                         }
1553                                 tsior.Clear();
1554                                 int packSize = Constants.TS_SIZE + stride;
1555                                 fs.Seek(0, SeekOrigin.End);
1556                                 for (i = packSize; (fs.Length - fs.Position) < Constants.DISK_BUFFER; i += packSize)
1557                                         {
1558                                                 fs.Seek(0 - i, SeekOrigin.End);
1559                                                 if (fs.Read(tsPack, 0, packSize) == packSize)
1560                                                         {
1561                                                                 if (tsPack[stride] != Constants.SYNC_BYTE)
1562                                                                         {
1563                                                                                 i++;
1564                                                                                 i -= packSize;
1565                                                                                 continue;
1566                                                                         }
1567                                                                 ts.SetData(tsPack, stride);
1568                                                                 if (ts.HasPcr && pcrPID == ts.PID)
1569                                                                         {
1570                                                                                 endPcr = ts.Pcr;
1571                                                                                 Seek(-1);
1572                                                                                 return;
1573                                                                         }
1574                                                         }
1575                                                 else
1576                                                         break;
1577                                         }
1578                                 endPcr = startPcr = -1;
1579                         }
1580                         
1581                         protected override void  GetInitialValues()
1582                         {
1583                                 GetTimestamps();
1584                                 Seek(-1);
1585                                 PatPacket pp = null;
1586                                 PmtPacket pm = null;
1587                                 bool bluray = false;
1588                                 bool validPmt = false;
1589                                 ushort pmtPid = 0;
1590                                 int i = 0;
1591                                 Dictionary<ushort, StreamInfo> streams = new Dictionary<ushort, StreamInfo>();
1592                                 while (true)
1593                                         {
1594                                                 for (i = tsior.Read(tsPack, 0, 1 + stride); (i > 0) && (tsPack[stride] != Constants.SYNC_BYTE); i = tsior.Read(tsPack, stride, 1))
1595                                                         ; // ensure a good sync byte
1596                                                 if (i == 0)
1597                                                         break; // end of stream
1598                                                 i = tsior.Read(tsPack, stride + 1, tsPack.Length - (stride + 1));
1599                                                 if (i < tsPack.Length - (stride + 1))
1600                                                         break; // end of stream
1601                                                 ts.SetData(tsPack, stride);
1602                                                 if (ts.PID == Constants.PAT_PID)
1603                                                         {
1604                                                                 pp = new PatPacket(ts.GetData());
1605                                                                 ProgramInfo[] pi = pp.Programs;
1606                                                                 if (null != pi && pi.Length == 2)
1607                                                                         {
1608                                                                                 if ((pi[0].ProgramNumber == 0 && pi[0].ProgramPID == 0x001f && pi[1].ProgramNumber == 1 && pi[1].ProgramPID == 0x0100)
1609                                                                                         || (pi[1].ProgramNumber == 0 && pi[1].ProgramPID == 0x001f && pi[0].ProgramNumber == 1 && pi[0].ProgramPID == 0x0100))
1610                                                                                         {
1611                                                                                                 bluray = true;
1612                                                                                         }
1613                                                                         }
1614                                                                 else if (null != pi && pi[0] != null && pi[0].ProgramNumber == 1)
1615                                                                         pmtPid = pi[0].ProgramPID;
1616                                                         }
1617                                                 else if (bluray && ts.PID == 0x0100)
1618                                                         {
1619                                                                 if (pm == null)
1620                                                                         pm = new PmtPacket(ts.GetData());
1621                                                                 else if (pm.Complete == false)
1622                                                                         pm.AddData(ts.Payload, 0, ts.Payload.Length);
1623                                                                 if (pm.Complete)
1624                                                                         {
1625                                                                                 sis = pm.ElementaryStreams;
1626                                                                                 dt = pm.DtcpInfo;
1627                                                                                 return;
1628                                                                         }
1629                                                         }
1630                                                 else if (ts.PID == pmtPid)
1631                                                         {
1632                                                                 pm = new PmtPacket(ts.GetData());
1633                                                                 sis = pm.ElementaryStreams;
1634                                                                 dt = pm.DtcpInfo;
1635                                                         }
1636                                                 else if (streams.ContainsKey(ts.PID) == false && ts.HasPesHeader)
1637                                                         {
1638                                                                 byte[] payload = ts.Payload;
1639                                                                 PesHeader ph = new PesHeader(ts.Payload);
1640                                                                 PesPacket pes = new PesPacket(payload, 0, payload.Length, ts.PID);
1641                                                                 if (ph.StreamId == Constants.PES_PRIVATE1)
1642                                                                         {
1643                                                                                 byte[] audio = pes.GetPayload();
1644                                                                                 AC3Info ac3 = new AC3Info(audio, 0);
1645                                                                                 DtsInfo dts = new DtsInfo(audio, 0);
1646                                                                                 MlpInfo mlp = new MlpInfo(audio, 0);
1647                                                                                 if (ac3.Valid)
1648                                                                                         {
1649                                                                                                 if (ac3.SyntaxType == Ac3SyntaxType.Standard || ac3.SyntaxType == Ac3SyntaxType.Alternative)
1650                                                                                                         {
1651                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3, ts.PID);
1652                                                                                                                 streams.Add(ts.PID, si);
1653                                                                                                         }
1654                                                                                                 else if (ac3.SyntaxType == Ac3SyntaxType.Enhanced)
1655                                                                                                         {
1656                                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS, ts.PID);
1657                                                                                                                 streams.Add(ts.PID, si);
1658                                                                                                         }
1659                                                                                         }
1660                                                                                 else if (dts.Valid)
1661                                                                                         {
1662                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_DTS_HD, ts.PID);
1663                                                                                                 streams.Add(ts.PID, si);
1664                                                                                         }
1665                                                                                 else if (mlp.Valid)
1666                                                                                         {
1667                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD, ts.PID);
1668                                                                                                 streams.Add(ts.PID, si);
1669                                                                                         }
1670                                                                                 else if ((pes.ExtendedId & 0xf8) == Constants.PES_PRIVATE_LPCM)
1671                                                                                         {
1672                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_LPCM, ts.PID);
1673                                                                                                 streams.Add(ts.PID, si);
1674                                                                                         }
1675                                                                         }
1676                                                                 else if ((ph.StreamId & 0xe0) == Constants.PES_AUDIO_MPEG)
1677                                                                         {
1678                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_MPEG2, ts.PID);
1679                                                                                 streams.Add(ts.PID, si);
1680                                                                         }
1681                                                                 else if ((ph.StreamId & 0xf0) == Constants.PES_VIDEO)
1682                                                                         {
1683                                                                                 UInt32 format = pes.ExtendedType;
1684                                                                                 if ((format & 0xffff) == 0x1)
1685                                                                                         {
1686                                                                                         }
1687                                                                                 else if ((format & 0xffffff00) == 0x100)
1688                                                                                         {
1689                                                                                         }
1690                                                                                 
1691                                                                                 H264Info h264 = new H264Info(payload, 0);
1692                                                                                 Mpeg2Info mpg2 = new Mpeg2Info(payload, 0);
1693                                                                                 if (h264.Valid)
1694                                                                                         {
1695                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_H264, ts.PID);
1696                                                                                                 streams.Add(ts.PID, si);
1697                                                                                         }
1698                                                                                 else if (mpg2.Valid)
1699                                                                                         {
1700                                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_MPEG2, ts.PID);
1701                                                                                                 streams.Add(ts.PID, si);
1702                                                                                         }
1703                                                                         }
1704                                                                 else if (ph.StreamId == Constants.PES_VIDEO_VC1)
1705                                                                         {
1706                                                                                 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_VC1, ts.PID);
1707                                                                                 streams.Add(ts.PID, si);
1708                                                                         }
1709                                                         }
1710                                                 if (sis != null)
1711                                                         {
1712                                                                 validPmt = true;
1713                                                                 foreach (StreamInfo si in sis)
1714                                                                 {
1715                                                                         if (streams.ContainsKey(si.ElementaryPID) == false)
1716                                                                                 {
1717                                                                                         validPmt = false;
1718                                                                                         break;
1719                                                                                 }
1720                                                                 }
1721                                                                 if (validPmt)
1722                                                                         return;
1723                                                         }
1724                                                 if (fs.Position > (Constants.DISK_BUFFER << 1))
1725                                                         break;
1726                                         }
1727                                 sis = new StreamInfo[streams.Values.Count];
1728                                 streams.Values.CopyTo(sis, 0);
1729                         }
1730                         
1731                         private Int64 GetCurrentPcrFromFile()
1732                         {
1733                                 int packetSize = 0;
1734                                 if (fileType == TsFileType.TS)
1735                                         packetSize = Constants.TS_SIZE;
1736                                 else if (fileType == TsFileType.M2TS)
1737                                         packetSize = Constants.STRIDE_SIZE;
1738                                 byte[] inBuff = new byte[packetSize];
1739                                 TsPacket tp = new TsPacket();
1740                                 Int64 filePos = fs.Position;
1741                                 
1742                                 while (fs.Read(inBuff, 0, packetSize) == packetSize && fs.Position < (filePos + 1000000))
1743                                         {
1744                                                 if (packetSize == Constants.STRIDE_SIZE)
1745                                                         tp.SetData(inBuff, 4);
1746                                                 else if (packetSize == Constants.TS_SIZE)
1747                                                         tp.SetData(inBuff, 0);
1748                                                 if (tp.HasPcr)
1749                                                         {
1750                                                                 fs.Seek(filePos, SeekOrigin.Begin);
1751                                                                 return tp.Pcr;
1752                                                         }
1753                                         }
1754                                 return -1;
1755                         }
1756                         
1757                         public override void Seek(Int64 pcr)
1758                         {
1759                                 tsior.Clear();
1760                                 PesPackets.Clear();
1761                                 
1762                                 if (pcr == -1)
1763                                         {
1764                                                 fs.Seek(0, SeekOrigin.Begin);
1765                                                 return;
1766                                         }
1767                                 
1768                                 int packetSize = 0;
1769                                 if (fileType == TsFileType.TS)
1770                                         packetSize = Constants.TS_SIZE;
1771                                 else if (fileType == TsFileType.M2TS)
1772                                         packetSize = Constants.STRIDE_SIZE;
1773                                 else
1774                                         packetSize = sizeof(byte);
1775                                 Int64 span = endPcr - startPcr;
1776                                 if (span < 0)
1777                                         span += Constants.MAX_MPEG2TS_CLOCK;
1778                                 Int64 pcrPerByte = span / fs.Length;
1779                                 Int64 seek = pcr - startPcr;
1780                                 if (seek < 0)
1781                                         seek += Constants.MAX_MPEG2TS_CLOCK;
1782                                 Int64 length = seek / pcrPerByte;
1783                                 length /= packetSize;
1784                                 length *= packetSize;
1785                                 if (length > fs.Length)
1786                                         length = fs.Length;
1787                                 fs.Seek(length, SeekOrigin.Begin);
1788                                 
1789                                 for(int i = 0; i < 100; i++)
1790                                         {
1791                                                 Int64 offset = GetCurrentPcrFromFile();
1792                                                 if (-1 == offset)
1793                                                         offset = endPcr;
1794                                                 offset -= pcr;
1795                                                 if (offset > Constants.MAX_MPEG2TS_CLOCK / 2)
1796                                                         offset -= Constants.MAX_MPEG2TS_CLOCK;
1797                                                 else if (offset < (0 - (Constants.MAX_MPEG2TS_CLOCK / 2)))
1798                                                         offset += Constants.MAX_MPEG2TS_CLOCK;
1799                                                 Int64 target = offset / Constants.MPEG2TS_CLOCK_RATE;
1800                                                 if (target > 0)
1801                                                         {
1802                                                                 offset /= pcrPerByte;
1803                                                                 offset >>= 2;
1804                                                                 offset /= packetSize;
1805                                                                 offset *= packetSize;
1806                                                                 fs.Seek(0 - offset, SeekOrigin.Current);
1807                                                         }
1808                                                 else if (target < 0)
1809                                                         {
1810                                                                 offset /= pcrPerByte;
1811                                                                 offset >>= 2;
1812                                                                 offset /= packetSize;
1813                                                                 offset *= packetSize;
1814                                                                 fs.Seek(0 - offset, SeekOrigin.Current);
1815                                                         }
1816                                                 else
1817                                                         break;
1818                                         }
1819                         }
1820                 }
1821         
1822 public class TsIo
1823 {
1824 TsIo::TsIo(FileStream read, FileStream write)
1825 {
1826         init(read, write, Constants::DISK_BUFFER);
1827 }
1828                         
1829 TsIo::TsIo(FileStream read, FileStream write, int buffsize)
1830 {
1831         init(read, write, buffsize);
1832 }
1833                         
1834 TsIo::init(FileStream read, FileStream write, int buffsize)
1835 {
1836         fsr = read;
1837         fsw = write;
1838         if (fsr != null)
1839         {
1840                 ReadBuffer1 = pByte(new byte[buffsize]);
1841                 ReadBuffer2 = pByte(new byte[buffsize]);
1842                 ReadBuffer = ReadBuffer1;
1843         }
1844         else
1845         {
1846                 ReadBuffer.reset();
1847                 ReadBuffer1.reset();
1848                 ReadBuffer2.reset();
1849         }
1850         if (fsw != null)
1851         {
1852                 WriteBuffer1 = pByte(new byte[buffsize]);
1853                 WriteBuffer2 = pByte(new byte[buffsize]);
1854                 WriteBuffer = WriteBuffer1;
1855         }
1856         else
1857         {
1858                 WriteBuffer.reset();
1859                 WriteBuffer1.reset();
1860                 WriteBuffer2.reset();
1861         }
1862         readIndex = 0;
1863         readSize = 0;
1864         writeIndex = 0;
1865         asyncRead = null;
1866         asyncWrite = null;
1867 }
1868                         
1869 int TsIo::Read(byte[] target, int offset, int count)
1870                         {
1871                                 if (readIndex == readSize)
1872                                         {
1873                                                 // this buffer is finished, get next one
1874                                                 if (asyncRead != null)
1875                                                         {
1876                                                                 if (asyncRead.IsCompleted == false)
1877                                                                         GC.Collect(); // garbage collection during spare cycles
1878                                                                 readSize = fsr.EndRead(asyncRead);
1879                                                                 if (ReadBuffer == ReadBuffer1)
1880                                                                         ReadBuffer = ReadBuffer2;
1881                                                                 else ReadBuffer = ReadBuffer1;
1882                                                                 readIndex = 0;
1883                                                                 if (readSize == 0)
1884                                                                         {
1885                                                                                 asyncRead = null;
1886                                                                                 return 0; // end of file
1887                                                                         }
1888                                                         }
1889                                                 else
1890                                                         {
1891                                                                 // one time init - prepopulate buffer
1892                                                                 readSize = fsr.Read(ReadBuffer, 0, ReadBuffer.Length);
1893                                                                 if (readSize == 0)
1894                                                                         return 0;
1895                                                                 readIndex = 0;
1896                                                         }
1897                                                 if (ReadBuffer == ReadBuffer1)
1898                                                         asyncRead = fsr.BeginRead(ReadBuffer2, 0, ReadBuffer2.Length, null, null);
1899                                                 else
1900                                                         asyncRead = fsr.BeginRead(ReadBuffer1, 0, ReadBuffer1.Length, null, null);
1901                                         }
1902                                 if (readIndex < readSize)
1903                                         {
1904                                                 int len = count;
1905                                                 while (len > (readSize - readIndex))
1906                                                         {
1907                                                                 int ret = Read(target, offset, (int)(readSize - readIndex));
1908                                                                 offset += ret;
1909                                                                 len -= ret;
1910                                                                 if (ret == 0)
1911                                                                         break;
1912                                                         }
1913                                                 if (len <= (readSize - readIndex))
1914                                                         {
1915                                                                 // this optimization saves a LOT of time in PS files
1916                                                                 if (len == 1)
1917                                                                         target[offset] = ReadBuffer[readIndex];
1918                                                                 else
1919                                                                         Array.Copy(ReadBuffer, readIndex, target, offset, len);
1920                                                                 readIndex += len;
1921                                                                 return count;
1922                                                         }
1923                                                 else
1924                                                         {
1925                                                                 return count - len;
1926                                                         }
1927                                         }
1928                                 throw new ArgumentException("read index out of bounds");
1929                         }
1930                         
1931                         public void Write(byte[] target, int offset, int count)
1932                         {
1933                                 if (writeIndex == WriteBuffer.Length)
1934                                         {
1935                                                 // this buffer is finished, get next one
1936                                                 if (asyncWrite != null)
1937                                                         {
1938                                                                 if (asyncWrite.IsCompleted == false)
1939                                                                         GC.Collect(); // garbage collection during spare cycles
1940                                                                 fsw.EndWrite(asyncWrite);
1941                                                         }
1942                                                 asyncWrite = fsw.BeginWrite(WriteBuffer, 0, WriteBuffer.Length, null, null);
1943                                                 if (WriteBuffer == WriteBuffer1)
1944                                                         WriteBuffer = WriteBuffer2;
1945                                                 else
1946                                                         WriteBuffer = WriteBuffer1;
1947                                                 writeIndex = 0;
1948                                         }
1949                                 if (writeIndex < WriteBuffer.Length)
1950                                         {
1951                                                 while (count > (int)(WriteBuffer.Length - writeIndex))
1952                                                         {
1953                                                                 int diff = (int)(WriteBuffer.Length - writeIndex);
1954                                                                 Write(target, offset, diff);
1955                                                                 offset += diff;
1956                                                                 count -= diff;
1957                                                         }
1958                                                 Array.Copy(target, offset, WriteBuffer, writeIndex, count);
1959                                                 writeIndex += count;
1960                                                 return;
1961                                         }
1962                                 throw new ArgumentException("write index out of bounds");
1963                         }
1964                         
1965                         public void Flush()
1966                         {
1967                                 if (asyncWrite != null)
1968                                         {
1969                                                 fsw.EndWrite(asyncWrite);
1970                                                 asyncWrite = null;
1971                                         }
1972                                 if (writeIndex > 0)
1973                                         {
1974                                                 fsw.Write(WriteBuffer, 0, (int)writeIndex);
1975                                                 writeIndex = 0;
1976                                         }
1977                         }
1978                         
1979                         public void Clear()
1980                         {
1981                                 if (asyncRead != null)
1982                                         {
1983                                                 fsr.EndRead(asyncRead);
1984                                                 asyncRead = null;
1985                                         }
1986                                 readIndex = readSize = 0;
1987                         }
1988                 }
1989 }
1990                                                                                                                                 
1991 }
1992