5 static const char PesTemplate[] = { 0x00, 0x00, 0x01, 0xbd};
9 public abstract class PesFile
11 protected PesFile(BackgroundWorker openWorker)
15 fileType = TsFileType.UNKNOWN;
21 this.openWorker = openWorker;
25 protected void ReportProgress(int percent)
27 if (openWorker.CancellationPending)
29 throw new ApplicationException("Opening file canceled");
31 if (lastPercent != percent && percent > 0 && percent <= 100)
33 lastPercent = percent;
34 openWorker.ReportProgress(percent);
38 public void SetPcrDelegate(PcrChanged pcr)
45 get { return startPcr; }
50 get { return endPcr; }
53 public void SetPtsDelegate(PtsChanged pts)
58 public StreamInfo GetStreamInfo(ushort pid)
60 foreach (StreamInfo si in sis)
61 if (si.ElementaryPID == pid)
66 private void ParseElementaryStreams()
69 for (int i = 0; i < 300;)
71 ReportProgress(50 + ((50 * i) / 300));
72 PesPacket[] ppa = GetNextPesPackets();
75 foreach (PesPacket pp in ppa)
79 byte[] payload = pp.GetPayload();
80 StreamInfo si = GetStreamInfo(pp.PID);
82 ParseStream(si, payload);
93 private void ParseStream(StreamInfo si, byte[] payload)
95 switch (si.StreamType)
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)
103 VC1SequenceInfo sq = new VC1SequenceInfo(payload, 0);
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;
117 case ElementaryStreamTypes.AUDIO_STREAM_AC3:
118 if ((si.ElementaryDescriptors == null) ||
119 si.AudioPresentationType == AudioPresentationType.Reserved ||
120 si.SamplingFrequency == SamplingFrequency.Reserved)
122 AC3Info ac3 = new AC3Info(payload, 0);
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;
136 case ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS:
137 if (si.AudioPresentationType == AudioPresentationType.Reserved ||
138 si.SamplingFrequency == SamplingFrequency.Reserved)
140 AC3Info ac3 = new AC3Info(payload, 0);
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;
152 case ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD:
153 if (si.AudioPresentationType == AudioPresentationType.Reserved ||
154 si.SamplingFrequency == SamplingFrequency.Reserved)
156 MlpInfo ac3 = new MlpInfo(payload, 0);
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;
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)
174 H264Info h264 = new H264Info(payload, 0);
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;
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)
194 DtsInfo dts = new DtsInfo(payload, 0);
197 if (dts.AudioPresentationType != AudioPresentationType.Reserved)
198 si.AudioPresentationType = dts.AudioPresentationType;
199 if (dts.SamplingFrequency != SamplingFrequency.Reserved)
200 si.SamplingFrequency = dts.SamplingFrequency;
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)
210 Mpeg2Info mpeg2 = new Mpeg2Info(payload, 0);
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;
227 TsFileType PesFile::GetFileType(FileStream fs)
229 pByte inBuff = pByte(new byte[Constant::STRIDE_SIZE * 7]);
231 fs.Seek(0, SeekOrigin.Begin);
233 if (fs.Read(inBuff, 0, sizeof(inBuff.get())) != sizeof(inBuff.get()))
234 throw std::invalid_argument("The specified file is too short");
237 for (offset = 0; offset < Constants::STRIDE_SIZE; offset++)
239 if (inBuff[offset] == Constants::SYNC_BYTE)
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;
256 if ((inBuff[0] == (byte)'P' || inBuff[0] == (byte)'p') &&
257 (inBuff[1] == (byte)'G' || inBuff[1] == (byte)'g'))
258 return TsFileType::SUP_ELEMENTARY;
260 UInt32 marker = 0xffffffff;
262 bool packstart = false;
263 for (int i = 0; i < sizeof(inBuff.get()); i++)
265 marker = marker << 8;
266 marker &= 0xffffff00;
268 if ((marker & 0xffffff00) == 0x00000100)
270 switch (marker & 0xff)
274 if (sizeof(inBuff.get()) < i + 11)
276 i = sizeof(inBuff.get());
280 stuffing = inBuff[i] & 0x7;
281 if (sizeof(inBuff.get()) < i + stuffing + 1)
283 i = sizeof(inBuff.get());
293 if (sizeof(inBuff.get()) < i + 3)
295 i = sizeof(inBuff.get());
298 stuffing = (inBuff[i + 1] << 8) + inBuff[i + 2];
300 if (sizeof(inBuff.get()) < i + stuffing)
302 i = sizeof(inBuff.get());
313 return TsFileType::EVOB;
316 for (int i = 0; i < sizeof(inBuff.get()); i++)
318 marker = marker << 8;
319 marker &= 0xffffff00;
321 if (marker == Constants::MKVFILE_START)
322 return TsFileType::MKV;
324 throw std::invalid_argument("The specified file is not a valid TS/M2TS/EVOB/MKV file");
327 boost::shared_ptr<PesFile> PesFile::OpenFile(string path, bool useAsync, BackgroundWorker openWorker)
330 FileStream fs = null;
332 // fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, Constant::DISK_BUFFER, useAsync);
335 TsIo tsior = new TsIo(fs, null, Constants::DISK_BUFFER );
336 TsFileType fileType = GetFileType(fs);
339 case TsFileType::EVOB:
340 pf = new EvoPesFile(openWorker);
342 case TsFileType::M2TS:
343 pf = new TsPesFile(openWorker,4);
346 pf = new TsPesFile(openWorker,0);
348 case TsFileType::SUP_ELEMENTARY:
349 pf = new SupPesFile(openWorker);
351 case TsFileType::MKV:
352 pf = new MkvPesFile(openWorker);
355 pf.fileType = fileType;
358 pf.GetInitialValues();
359 pf.ParseElementaryStreams();
369 public void CloseFile()
381 public TsFileType FileType
383 get { return fileType; }
386 public StreamInfo[] StreamInfos
391 public TimeSpan VideoLength
395 Int64 span = endPcr - startPcr;
397 span += Constants.MAX_MPEG2TS_CLOCK;
398 return new TimeSpan((span * 10) / 27);
402 public abstract PesPacket[] GetNextPesPackets();
403 public abstract void Seek(Int64 pcr);
404 public abstract DTCP_Descriptor DtcpInfo { get; }
405 protected abstract void GetInitialValues();
408 public class EvoPesFile : PesFile
410 private Dictionary<ushort, List<byte>> soundFrames;
411 private Int64 lastPcr;
413 public EvoPesFile(BackgroundWorker bw)
416 soundFrames = new Dictionary<ushort, List<byte>>();
417 lastPcr = 0 - Constants.MPEG2TS_CLOCK_RATE;
420 public override DTCP_Descriptor DtcpInfo
425 protected override void GetInitialValues()
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;
435 for (int i = 0; i < Length; i++)
437 ReportProgress(50 * i / Length);
438 marker = marker << 8;
439 marker &= 0xffffff00;
441 if ((marker & 0xffffff00) == 0x00000100)
443 switch (marker & 0xff)
447 if (Length <= i + 10)
453 stuffing = inBuff[i] & 0x7;
454 if (Length <= i + stuffing)
463 if (inBuff[i] == Constants.PES_PRIVATE1)
465 // skip to the end of the header
466 int endOfHeader = i + 6 + inBuff[i + 5];
467 if (inBuff.Length > endOfHeader + 4)
469 if ((inBuff[endOfHeader] & 0xe0) == Constants.PES_PRIVATE_SUBTITLE)
471 byte subid = inBuff[endOfHeader];
472 if (evoStreams.ContainsKey(subid) == false)
474 StreamInfo si = new StreamInfo(ElementaryStreamTypes.PRESENTATION_GRAPHICS_STREAM, subid);
475 evoStreams.Add(subid, si);
478 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_AC3)
480 byte subid = inBuff[endOfHeader];
481 if (evoStreams.ContainsKey(subid) == false)
483 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3, subid);
484 evoStreams.Add(subid, si);
487 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_DTS_HD)
489 byte subid = inBuff[endOfHeader];
490 if (evoStreams.ContainsKey(subid) == false)
492 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_DTS_HD, subid);
493 evoStreams.Add(subid, si);
496 else if ((inBuff[endOfHeader] & 0xf0) == Constants.PES_PRIVATE_AC3_PLUS)
498 byte subid = inBuff[endOfHeader];
499 if (evoStreams.ContainsKey(subid) == false)
501 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS, subid);
502 evoStreams.Add(subid, si);
505 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_LPCM)
507 byte subid = inBuff[endOfHeader];
508 if (evoStreams.ContainsKey(subid) == false)
510 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_LPCM, subid);
511 evoStreams.Add(subid, si);
514 else if ((inBuff[endOfHeader] & 0xf8) == Constants.PES_PRIVATE_AC3_TRUE_HD)
516 byte subid = inBuff[endOfHeader];
517 if (evoStreams.ContainsKey(subid) == false)
519 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD, subid);
520 evoStreams.Add(subid, si);
525 else if ((inBuff[i] & 0xe0) == Constants.PES_AUDIO_MPEG)
527 byte subid = inBuff[i];
528 if (evoStreams.ContainsKey(subid) == false)
530 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_MPEG2, subid);
531 evoStreams.Add(subid, si);
534 else if ((inBuff[i] & 0xf0) == Constants.PES_VIDEO)
536 byte subid = inBuff[i];
537 if (evoStreams.ContainsKey(subid) == false)
539 // need to differenciate between H.264 and MPEG2
545 ElementaryStreamTypes videoFormat = ElementaryStreamTypes.INVALID;
546 int startIndex = i + 6 + inBuff[i + 5];
547 if (Length <= startIndex + 3)
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)
558 videoFormat = ElementaryStreamTypes.VIDEO_STREAM_H264;
559 StreamInfo si = new StreamInfo(videoFormat, subid);
560 evoStreams.Add(subid, si);
562 else if ((format & 0xffffff00) == 0x100)
564 videoFormat = ElementaryStreamTypes.VIDEO_STREAM_MPEG2;
565 StreamInfo si = new StreamInfo(videoFormat, subid);
566 evoStreams.Add(subid, si);
570 else if (inBuff[i] == Constants.PES_VIDEO_VC1)
572 byte subid = GetVC1SubstreamId(inBuff, i + 3);
573 if (subid != 0 && evoStreams.ContainsKey(subid) == false)
575 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_VC1, subid);
576 si.ElementaryDescriptors = Constants.vc1_descriptor;
577 evoStreams.Add(subid, si);
587 stuffing = (inBuff[i + 1] << 8) + inBuff[i + 2];
589 if (Length < i + stuffing)
601 if (evoStreams.Count > 0)
603 sis = new StreamInfo[evoStreams.Values.Count];
604 evoStreams.Values.CopyTo(sis, 0);
608 public override PesPacket[] GetNextPesPackets()
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];
618 UInt32 marker = 0xffffffff;
620 PesPacket partial = null;
622 while (tsior.Read(inData, 0, inData.Length) == inData.Length)
624 marker = marker << 8;
625 marker &= 0xffffff00;
627 if ((marker & 0xffffff00) == 0x00000100)
629 if ((marker & 0xff) == Constants.PACK_ID)
633 for (i = 4; i < 10; i++)
635 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
640 for (i = 10; i < 14; i++) // skip mux rate etc.
642 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
645 Int64 pcr = (Int64)((header & 0x380000000000) >> 13);
646 pcr |= (Int64)((header & 0x3fff8000000) >> 12);
647 pcr |= (Int64)((header & 0x3fff800) >> 11);
649 pcr |= (Int64)((header & 0x3fe) >> 1);
650 Int64 delta = pcr - lastPcr;
651 if (delta > Constants.MPEG2TS_CLOCK_RATE / 9)
653 if (pcrDelegate != null)
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))
664 for (i = 4; i < 6; i++)
666 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
672 for (i = 6; i < Length; i++)
674 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
680 byte end = inData[0];
682 partial = new PesPacket(inData, 0, 1, 0);
683 partial.AddData(inData, 0, 1);
685 partial.AddData(inData, 0, 1);
687 partial.AddData(inData, 0, 1);
689 for (i = 4; i < 6; i++)
691 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
693 partial.AddData(inData, 0, 1);
698 // we don't need this byte-by-byte loop here, as we have just gotten the length:
700 for (i = 6; i < Length; i++)
702 if (tsior.Read(inData, 0, inData.Length) != inData.Length)
704 partial.AddData(inData, 0, 1);
707 bytesToGo = Length - 6;
708 while (bytesToGo > 0)
710 bytesToRead = (bytesToGo > inData2.Length) ? inData2.Length : bytesToGo;
711 if ((bytesRead = tsior.Read(inData2, 0, bytesToRead)) != bytesToRead)
713 partial.AddData(inData2, 0, bytesRead);
714 bytesToGo -= bytesRead;
717 PesHeader ph = partial.GetHeader();
718 if (partial.BaseId == Constants.PES_PRIVATE1)
720 if ((partial.ExtendedId & 0xf0) == Constants.PES_PRIVATE_AC3_PLUS ||
721 (partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_AC3)
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();
731 if (tempd.Length > 2 && tempd[0] == (byte)(Constants.AC3_SYNC >> 8) &&
732 tempd[1] == (byte)(Constants.AC3_SYNC & 0xff))
735 while (tempd.Length > 2 && tempd[0] == (byte)(Constants.AC3_SYNC >> 8)
736 && tempd[1] == (byte)(Constants.AC3_SYNC & 0xff))
738 AC3Info ac3 = new AC3Info(tempd, 0);
739 if (ac3.Valid == false || ac3.FrameLength == 0 || tempd.Length < ac3.FrameLength)
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();
753 for (int j = 2; j < tempd.Length; j++)
757 if (mk2 == Constants.AC3_SYNC)
766 soundFrames[partial.ExtendedId].RemoveRange(0, len);
767 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
768 pp.AddData(tempd, 0, len);
771 else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_AC3_TRUE_HD)
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;
781 UInt32 mk2 = 0xffffffff;
782 for (int j = 5; j < tempd.Length; j++)
786 if (mk2 == Constants.MLP_SYNC)
797 soundFrames[partial.ExtendedId].RemoveRange(0, len);
798 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
799 pp.AddData(tempd, 0, len);
802 else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_LPCM)
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;
812 UInt32 mk2 = 0xffffffff;
813 for (int j = 5; j < tempd.Length; j++)
817 if (mk2 == Constants.MLP_SYNC)
828 soundFrames[partial.ExtendedId].RemoveRange(0, len);
829 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
830 pp.AddData(tempd, 0, len);
833 else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_DTS_HD)
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();
842 UInt32 mk2 = 0xffffffff;
843 for (int j = 4; j < tempd.Length; j++)
847 if (mk2 == Constants.DTS_SYNC)
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;
862 soundFrames[partial.ExtendedId].RemoveRange(0, len);
863 pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId);
864 pp.AddData(tempd, 0, len);
868 pp.PID = pp.ExtendedId;
870 else if (pp.BaseId == Constants.PES_PADDING || pp.BaseId == Constants.PES_PRIVATE2)
875 else if (((pp.BaseId & 0xe0) == Constants.PES_AUDIO_MPEG)
876 || ((pp.BaseId & 0xf0) == Constants.PES_VIDEO))
878 else if (pp.BaseId == Constants.PES_VIDEO_VC1 && ph != null)
879 pp.PID = ph.Extention2;
880 if (ph != null && ph.HasPts)
882 if (ptsDelegate != null)
883 ptsDelegate(ph.Pts, pp.PID);
893 PesPacket[] ppa = new PesPacket[1];
901 public override void Seek(long pcr)
907 fs.Seek(0, SeekOrigin.Begin);
911 int packetSize = sizeof(byte);
912 Int64 span = endPcr - startPcr;
914 span += Constants.MAX_MPEG2TS_CLOCK;
915 Int64 pcrPerByte = span / fs.Length;
916 Int64 seek = pcr - startPcr;
918 seek += Constants.MAX_MPEG2TS_CLOCK;
919 Int64 length = seek / pcrPerByte;
920 length /= packetSize;
921 length *= packetSize;
922 if (length > fs.Length)
924 fs.Seek(length, SeekOrigin.Begin);
927 while (found == false)
929 Int64 offset = GetCurrentPcrFromFile();
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;
940 offset /= pcrPerByte;
942 offset /= packetSize;
943 offset *= packetSize;
944 fs.Seek(0 - offset, SeekOrigin.Current);
948 offset /= pcrPerByte;
950 offset /= packetSize;
951 offset *= packetSize;
952 fs.Seek(0 - offset, SeekOrigin.Current);
959 private void GetTimeStamps()
961 fs.Seek(0, SeekOrigin.Begin);
962 UInt64 header = 0xffffffff;
964 int packsize_reading = -1;
965 for (int i = 0; i < Constants.DISK_BUFFER; i++)
967 int ib = fs.ReadByte();
969 throw new FormatException("The specified file is too short");
970 b = (byte)(ib & 0xff);
973 if ((header & 0xffffffff) == 0x000001ba)
976 packsize_reading = 5;
978 else if (packsize_reading > 0)
980 else if (packsize_reading == 0)
982 startPcr = (Int64)((header & 0x380000000000) >> 13);
983 startPcr |= (Int64)((header & 0x3fff8000000) >> 12);
984 startPcr |= (Int64)((header & 0x3fff800) >> 11);
986 startPcr |= (Int64)((header & 0x3fe) >> 1);
991 fs.Seek(lseek, SeekOrigin.End);
994 packsize_reading = -1;
995 for (int i = 0; i < Constants.DISK_BUFFER; i++)
997 for (int j = 0; j < 12; j++)
999 int ib = fs.ReadByte();
1001 throw new FormatException("The specified file is too short");
1002 b = (byte)(ib & 0xff);
1005 if ((header & 0xffffffff) == 0x000001ba)
1008 packsize_reading = 5;
1010 else if (packsize_reading > 0)
1012 else if (packsize_reading == 0)
1014 endPcr = (Int64)((header & 0x380000000000) >> 13);
1015 endPcr |= (Int64)((header & 0x3fff8000000) >> 12);
1016 endPcr |= (Int64)((header & 0x3fff800) >> 11);
1018 endPcr |= (Int64)((header & 0x3fe) >> 1);
1022 if (packsize_reading == 0)
1025 fs.Seek(lseek, SeekOrigin.End);
1030 private byte GetVC1SubstreamId(byte[] buff, int offset)
1032 if (buff.Length <= offset + 3)
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)
1045 int length = offset + buff[offset + 2] + 3;
1046 if (buff.Length < length)
1049 if (PTS_DTS_flags == 0x80)
1051 if (PTS_DTS_flags == 0xc0)
1055 if (ES_rate_flag > 0)
1057 if (DSM_trick_mode_flag > 0)
1059 if (additional_copy_info_flag > 0)
1061 if (PES_CRC_flag > 0)
1063 if (PES_extension_flag == 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);
1071 if (PES_private_data_flag > 0)
1073 if (pack_header_field_flag > 0)
1074 offset += (buff[offset] + 1);
1075 if (program_packet_sequence_counter_flag > 0)
1077 if (PSTD_buffer_flag > 0)
1079 if (PES_extension_flag_2 == 0)
1081 if (buff[offset] != 0x81)
1083 return buff[offset + 1];
1086 private Int64 GetCurrentPcrFromFile()
1088 UInt64 header = 0xffffffff;
1090 int packsize_reading = -1;
1091 for (int i = 0; i < Constants.DISK_BUFFER; i++)
1093 int ib = fs.ReadByte();
1096 b = (byte)(ib & 0xff);
1099 if ((header & 0xffffffff) == 0x000001ba)
1102 packsize_reading = 5;
1104 else if (packsize_reading > 0)
1106 else if (packsize_reading == 0)
1108 Int64 pcr = (Int64)((header & 0x380000000000) >> 13);
1109 pcr |= (Int64)((header & 0x3fff8000000) >> 12);
1110 pcr |= (Int64)((header & 0x3fff800) >> 11);
1112 pcr |= (Int64)((header & 0x3fe) >> 1);
1120 public class SupPesFile : PesFile
1122 private static readonly byte[] PesTemplate = new byte[4] {
1123 0x00, 0x00, 0x01, 0xbd};
1125 public SupPesFile(BackgroundWorker bw) : base(bw) { }
1127 public override DTCP_Descriptor DtcpInfo
1129 get { return null; }
1132 protected override void GetInitialValues()
1135 this.sis = new StreamInfo[1];
1136 this.sis[0] = new StreamInfo(ElementaryStreamTypes.PRESENTATION_GRAPHICS_STREAM, Constants.DEFAULT_PRESENTATION_GRAPHICS_PID);
1139 public override PesPacket[] GetNextPesPackets()
1143 byte[] inData = new byte[1];
1144 byte[] pgHeader = new byte[3];
1146 while (tsior.Read(inData, 0, inData.Length) == inData.Length)
1150 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1151 (b1 == (byte)'G' || b1 == (byte)'g'))
1156 for (int k = 0; k < 4; k++)
1158 if (0 == tsior.Read(inData, 0, inData.Length))
1164 if (ptsDelegate != null)
1165 ptsDelegate(Pts, sis[0].ElementaryPID);
1166 for (int k = 0; k < 4; k++)
1168 if (0 == tsior.Read(inData, 0, inData.Length))
1174 for (int k = 0; k < 3; k++)
1176 if (0 == tsior.Read(inData, 0, inData.Length))
1178 pgHeader[k] = inData[0];
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);
1193 pp.AddData(inData, 0, 1);
1194 inData[0] = (byte)(Dts == 0 ? 0x80 : 0xc0);
1195 pp.AddData(inData, 0, 1);
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);
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);
1222 pp.AddData(pgHeader, 0, pgHeader.Length);
1223 for (int k = 0; k < len; k++)
1225 if (0 == tsior.Read(inData, 0, inData.Length))
1227 pp.AddData(inData, 0, 1);
1229 PesPacket[] ppa = new PesPacket[1];
1237 public override void Seek(long pcr)
1243 fs.Seek(0, SeekOrigin.Begin);
1247 int packetSize = sizeof(byte);
1248 Int64 span = endPcr - startPcr;
1250 span += Constants.MAX_MPEG2TS_CLOCK;
1251 Int64 pcrPerByte = span / fs.Length;
1252 Int64 seek = pcr - startPcr;
1254 seek += Constants.MAX_MPEG2TS_CLOCK;
1255 Int64 length = seek / pcrPerByte;
1256 length /= packetSize;
1257 length *= packetSize;
1258 if (length > fs.Length)
1260 fs.Seek(length, SeekOrigin.Begin);
1263 while (found == false)
1265 Int64 offset = GetCurrentPcrFromFile();
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;
1276 offset /= pcrPerByte;
1278 offset /= packetSize;
1279 offset *= packetSize;
1280 fs.Seek(0 - offset, SeekOrigin.Current);
1282 else if (target < 0)
1284 offset /= pcrPerByte;
1286 offset /= packetSize;
1287 offset *= packetSize;
1288 fs.Seek(0 - offset, SeekOrigin.Current);
1295 private Int64 GetCurrentPcrFromFile()
1302 int ib = fs.ReadByte();
1306 b1 = (byte)(ib & 0xff);
1307 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1308 (b1 == (byte)'G' || b1 == (byte)'g'))
1311 for (int k = 0; k < 4; k++)
1316 b1 = (byte)(ib & 0xff);
1320 pcr *= (Constants.MPEG2TS_CLOCK_RATE / Constants.PTS_CLOCK_RATE);
1327 private void GetTimeStamps()
1329 fs.Seek(0, SeekOrigin.Begin);
1332 for (int i = 0; i < Constants.DISK_BUFFER; i++)
1334 int ib = fs.ReadByte();
1336 throw new FormatException("The specified file is too short");
1338 b1 = (byte)(ib & 0xff);
1339 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1340 (b1 == (byte)'G' || b1 == (byte)'g'))
1343 for (int k = 0; k < 4; k++)
1347 throw new FormatException("The specified file is too short");
1348 b1 = (byte)(ib & 0xff);
1352 startPcr *= (Constants.MPEG2TS_CLOCK_RATE / Constants.PTS_CLOCK_RATE);
1357 fs.Seek(lseek, SeekOrigin.End);
1360 for (int i = 0; i < Constants.DISK_BUFFER; i++)
1362 for (int j = 0; j < 2; j++)
1364 int ib = fs.ReadByte();
1366 throw new FormatException("The specified file is too short");
1368 b1 = (byte)(ib & 0xff);
1369 if ((b0 == (byte)'P' || b0 == (byte)'p') &&
1370 (b1 == (byte)'G' || b1 == (byte)'g'))
1373 for (int k = 0; k < 4; k++)
1377 throw new FormatException("The specified file is too short");
1378 b1 = (byte)(ib & 0xff);
1382 endPcr *= (Constants.MPEG2TS_CLOCK_RATE / Constants.PTS_CLOCK_RATE);
1390 fs.Seek(lseek, SeekOrigin.End);
1395 public class TsPesFile : PesFile
1398 private byte[] tsPack;
1400 private Dictionary<ushort, PesPacket> PesPackets;
1401 private DTCP_Descriptor dt;
1402 private ushort pcrPID;
1404 public TsPesFile(BackgroundWorker bw, int offset)
1408 tsPack = new byte[Constants.TS_SIZE + offset];
1409 ts = new TsPacket();
1410 PesPackets = new Dictionary<ushort, PesPacket>();
1415 public override DTCP_Descriptor DtcpInfo
1420 public override PesPacket[] GetNextPesPackets()
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
1429 List<PesPacket> ppa = new List<PesPacket>();
1430 foreach (ushort pd in PesPackets.Keys)
1432 PesPacket pp = PesPackets[pd];
1438 return null; // end of stream
1441 return ppa.ToArray();
1444 i = tsior.Read(tsPack, stride + 1, tsPack.Length - (stride + 1));
1445 if (i < tsPack.Length - (stride + 1))
1447 List<PesPacket> ppa = new List<PesPacket>();
1448 foreach (ushort pd in PesPackets.Keys)
1450 PesPacket pp = PesPackets[pd];
1456 return null; // end of stream
1458 return ppa.ToArray();
1460 ts.SetData(tsPack, stride);
1461 ushort pid = ts.PID;
1462 byte[] payload = ts.Payload;
1465 if (null != pcrDelegate && pcrPID == pid)
1466 pcrDelegate(ts.Pcr);
1468 if (ts.HasPesHeader)
1470 if (payload != null && payload.Length > 3 && payload[0] == 0x00
1471 && payload[1] == 0x00 && payload[2] == 0x01)
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)
1478 if (ptsDelegate != null)
1479 ptsDelegate(ph.Pts, pid);
1481 if (PesPackets.ContainsKey(pid))
1483 PesPacket pp = PesPackets[ts.PID];
1485 PesPackets[ts.PID] = newpp;
1486 PesPacket[] ppa = new PesPacket[1];
1492 if (newpp.Complete == true)
1494 PesPacket[] ppa = new PesPacket[1];
1498 PesPackets[ts.PID] = newpp;
1503 throw new InvalidDataException("invalid stream");
1506 else if (PesPackets.ContainsKey(pid))
1508 PesPacket pp = PesPackets[ts.PID];
1509 if (payload != null)
1511 pp.AddData(payload, 0, payload.Length);
1514 PesPackets.Remove(pid);
1515 PesPacket[] ppa = new PesPacket[1];
1524 private void GetTimestamps()
1532 fs.Seek(0, SeekOrigin.Begin);
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
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);
1550 if (fs.Position > (Constants.DISK_BUFFER << 1))
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)
1558 fs.Seek(0 - i, SeekOrigin.End);
1559 if (fs.Read(tsPack, 0, packSize) == packSize)
1561 if (tsPack[stride] != Constants.SYNC_BYTE)
1567 ts.SetData(tsPack, stride);
1568 if (ts.HasPcr && pcrPID == ts.PID)
1578 endPcr = startPcr = -1;
1581 protected override void GetInitialValues()
1585 PatPacket pp = null;
1586 PmtPacket pm = null;
1587 bool bluray = false;
1588 bool validPmt = false;
1591 Dictionary<ushort, StreamInfo> streams = new Dictionary<ushort, StreamInfo>();
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
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)
1604 pp = new PatPacket(ts.GetData());
1605 ProgramInfo[] pi = pp.Programs;
1606 if (null != pi && pi.Length == 2)
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))
1614 else if (null != pi && pi[0] != null && pi[0].ProgramNumber == 1)
1615 pmtPid = pi[0].ProgramPID;
1617 else if (bluray && ts.PID == 0x0100)
1620 pm = new PmtPacket(ts.GetData());
1621 else if (pm.Complete == false)
1622 pm.AddData(ts.Payload, 0, ts.Payload.Length);
1625 sis = pm.ElementaryStreams;
1630 else if (ts.PID == pmtPid)
1632 pm = new PmtPacket(ts.GetData());
1633 sis = pm.ElementaryStreams;
1636 else if (streams.ContainsKey(ts.PID) == false && ts.HasPesHeader)
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)
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);
1649 if (ac3.SyntaxType == Ac3SyntaxType.Standard || ac3.SyntaxType == Ac3SyntaxType.Alternative)
1651 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3, ts.PID);
1652 streams.Add(ts.PID, si);
1654 else if (ac3.SyntaxType == Ac3SyntaxType.Enhanced)
1656 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS, ts.PID);
1657 streams.Add(ts.PID, si);
1662 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_DTS_HD, ts.PID);
1663 streams.Add(ts.PID, si);
1667 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD, ts.PID);
1668 streams.Add(ts.PID, si);
1670 else if ((pes.ExtendedId & 0xf8) == Constants.PES_PRIVATE_LPCM)
1672 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_LPCM, ts.PID);
1673 streams.Add(ts.PID, si);
1676 else if ((ph.StreamId & 0xe0) == Constants.PES_AUDIO_MPEG)
1678 StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_MPEG2, ts.PID);
1679 streams.Add(ts.PID, si);
1681 else if ((ph.StreamId & 0xf0) == Constants.PES_VIDEO)
1683 UInt32 format = pes.ExtendedType;
1684 if ((format & 0xffff) == 0x1)
1687 else if ((format & 0xffffff00) == 0x100)
1691 H264Info h264 = new H264Info(payload, 0);
1692 Mpeg2Info mpg2 = new Mpeg2Info(payload, 0);
1695 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_H264, ts.PID);
1696 streams.Add(ts.PID, si);
1698 else if (mpg2.Valid)
1700 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_MPEG2, ts.PID);
1701 streams.Add(ts.PID, si);
1704 else if (ph.StreamId == Constants.PES_VIDEO_VC1)
1706 StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_VC1, ts.PID);
1707 streams.Add(ts.PID, si);
1713 foreach (StreamInfo si in sis)
1715 if (streams.ContainsKey(si.ElementaryPID) == false)
1724 if (fs.Position > (Constants.DISK_BUFFER << 1))
1727 sis = new StreamInfo[streams.Values.Count];
1728 streams.Values.CopyTo(sis, 0);
1731 private Int64 GetCurrentPcrFromFile()
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;
1742 while (fs.Read(inBuff, 0, packetSize) == packetSize && fs.Position < (filePos + 1000000))
1744 if (packetSize == Constants.STRIDE_SIZE)
1745 tp.SetData(inBuff, 4);
1746 else if (packetSize == Constants.TS_SIZE)
1747 tp.SetData(inBuff, 0);
1750 fs.Seek(filePos, SeekOrigin.Begin);
1757 public override void Seek(Int64 pcr)
1764 fs.Seek(0, SeekOrigin.Begin);
1769 if (fileType == TsFileType.TS)
1770 packetSize = Constants.TS_SIZE;
1771 else if (fileType == TsFileType.M2TS)
1772 packetSize = Constants.STRIDE_SIZE;
1774 packetSize = sizeof(byte);
1775 Int64 span = endPcr - startPcr;
1777 span += Constants.MAX_MPEG2TS_CLOCK;
1778 Int64 pcrPerByte = span / fs.Length;
1779 Int64 seek = pcr - startPcr;
1781 seek += Constants.MAX_MPEG2TS_CLOCK;
1782 Int64 length = seek / pcrPerByte;
1783 length /= packetSize;
1784 length *= packetSize;
1785 if (length > fs.Length)
1787 fs.Seek(length, SeekOrigin.Begin);
1789 for(int i = 0; i < 100; i++)
1791 Int64 offset = GetCurrentPcrFromFile();
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;
1802 offset /= pcrPerByte;
1804 offset /= packetSize;
1805 offset *= packetSize;
1806 fs.Seek(0 - offset, SeekOrigin.Current);
1808 else if (target < 0)
1810 offset /= pcrPerByte;
1812 offset /= packetSize;
1813 offset *= packetSize;
1814 fs.Seek(0 - offset, SeekOrigin.Current);
1824 TsIo::TsIo(FileStream read, FileStream write)
1826 init(read, write, Constants::DISK_BUFFER);
1829 TsIo::TsIo(FileStream read, FileStream write, int buffsize)
1831 init(read, write, buffsize);
1834 TsIo::init(FileStream read, FileStream write, int buffsize)
1840 ReadBuffer1 = pByte(new byte[buffsize]);
1841 ReadBuffer2 = pByte(new byte[buffsize]);
1842 ReadBuffer = ReadBuffer1;
1847 ReadBuffer1.reset();
1848 ReadBuffer2.reset();
1852 WriteBuffer1 = pByte(new byte[buffsize]);
1853 WriteBuffer2 = pByte(new byte[buffsize]);
1854 WriteBuffer = WriteBuffer1;
1858 WriteBuffer.reset();
1859 WriteBuffer1.reset();
1860 WriteBuffer2.reset();
1869 int TsIo::Read(byte[] target, int offset, int count)
1871 if (readIndex == readSize)
1873 // this buffer is finished, get next one
1874 if (asyncRead != null)
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;
1886 return 0; // end of file
1891 // one time init - prepopulate buffer
1892 readSize = fsr.Read(ReadBuffer, 0, ReadBuffer.Length);
1897 if (ReadBuffer == ReadBuffer1)
1898 asyncRead = fsr.BeginRead(ReadBuffer2, 0, ReadBuffer2.Length, null, null);
1900 asyncRead = fsr.BeginRead(ReadBuffer1, 0, ReadBuffer1.Length, null, null);
1902 if (readIndex < readSize)
1905 while (len > (readSize - readIndex))
1907 int ret = Read(target, offset, (int)(readSize - readIndex));
1913 if (len <= (readSize - readIndex))
1915 // this optimization saves a LOT of time in PS files
1917 target[offset] = ReadBuffer[readIndex];
1919 Array.Copy(ReadBuffer, readIndex, target, offset, len);
1928 throw new ArgumentException("read index out of bounds");
1931 public void Write(byte[] target, int offset, int count)
1933 if (writeIndex == WriteBuffer.Length)
1935 // this buffer is finished, get next one
1936 if (asyncWrite != null)
1938 if (asyncWrite.IsCompleted == false)
1939 GC.Collect(); // garbage collection during spare cycles
1940 fsw.EndWrite(asyncWrite);
1942 asyncWrite = fsw.BeginWrite(WriteBuffer, 0, WriteBuffer.Length, null, null);
1943 if (WriteBuffer == WriteBuffer1)
1944 WriteBuffer = WriteBuffer2;
1946 WriteBuffer = WriteBuffer1;
1949 if (writeIndex < WriteBuffer.Length)
1951 while (count > (int)(WriteBuffer.Length - writeIndex))
1953 int diff = (int)(WriteBuffer.Length - writeIndex);
1954 Write(target, offset, diff);
1958 Array.Copy(target, offset, WriteBuffer, writeIndex, count);
1959 writeIndex += count;
1962 throw new ArgumentException("write index out of bounds");
1967 if (asyncWrite != null)
1969 fsw.EndWrite(asyncWrite);
1974 fsw.Write(WriteBuffer, 0, (int)writeIndex);
1981 if (asyncRead != null)
1983 fsr.EndRead(asyncRead);
1986 readIndex = readSize = 0;