using System; using System.IO; namespace Nikse.SubtitleEdit.Core.VobSub { /// /// http://www.mpucoder.com/DVD/pes-hdr.html /// public class PacketizedElementaryStream { public const int HeaderLength = 6; public readonly UInt32 StartCode; public readonly int StreamId; public readonly int Length; public readonly int ScramblingControl; public readonly int Priority; public readonly int DataAlignmentIndicator; public readonly int Copyright; public readonly int OriginalOrCopy; public readonly int PresentationTimestampDecodeTimestampFlags; public readonly int ElementaryStreamClockReferenceFlag; public readonly int EsRateFlag; public readonly int DsmTrickModeFlag; public readonly int AdditionalCopyInfoFlag; public readonly int CrcFlag; public readonly int ExtensionFlag; public readonly int HeaderDataLength; public readonly UInt64? PresentationTimestamp; public readonly UInt64? DecodeTimestamp; public readonly int? SubPictureStreamId; private readonly byte[] _dataBuffer; public PacketizedElementaryStream(byte[] buffer, int index) { StartCode = Helper.GetEndian(buffer, index + 0, 3); StreamId = buffer[index + 3]; Length = Helper.GetEndianWord(buffer, index + 4); ScramblingControl = (buffer[index + 6] >> 4) & Helper.B00000011; Priority = buffer[index + 6] & Helper.B00001000; DataAlignmentIndicator = buffer[index + 6] & Helper.B00000100; Copyright = buffer[index + 6] & Helper.B00000010; OriginalOrCopy = buffer[index + 6] & Helper.B00000001; PresentationTimestampDecodeTimestampFlags = buffer[index + 7] >> 6; ElementaryStreamClockReferenceFlag = buffer[index + 7] & Helper.B00100000; EsRateFlag = buffer[index + 7] & Helper.B00010000; DsmTrickModeFlag = buffer[index + 7] & Helper.B00001000; AdditionalCopyInfoFlag = buffer[index + 7] & Helper.B00000100; CrcFlag = buffer[index + 7] & Helper.B00001000; ExtensionFlag = buffer[index + 7] & Helper.B00000010; HeaderDataLength = buffer[index + 8]; if (StreamId == 0xBD) { int id = buffer[index + 9 + HeaderDataLength]; if (id >= 0x20 && id <= 0x40) // x3f 0r x40 ? SubPictureStreamId = id; } int tempIndex = index + 9; if (PresentationTimestampDecodeTimestampFlags == Helper.B00000010 || PresentationTimestampDecodeTimestampFlags == Helper.B00000011) { PresentationTimestamp = (ulong)buffer[tempIndex + 4] >> 1; PresentationTimestamp += (ulong)buffer[tempIndex + 3] << 7; PresentationTimestamp += (ulong)(buffer[tempIndex + 2] & Helper.B11111110) << 14; PresentationTimestamp += (ulong)buffer[tempIndex + 1] << 22; PresentationTimestamp += (ulong)(buffer[tempIndex + 0] & Helper.B00001110) << 29; //string bString = Helper.GetBinaryString(buffer, tempIndex, 5); //bString = bString.Substring(4, 3) + bString.Substring(8, 15) + bString.Substring(24, 15); //PresentationTimestamp = Convert.ToUInt64(bString, 2); tempIndex += 5; } if (PresentationTimestampDecodeTimestampFlags == Helper.B00000011) { //string bString = Helper.GetBinaryString(buffer, tempIndex, 5); //bString = bString.Substring(4, 3) + bString.Substring(8, 15) + bString.Substring(24, 15); //DecodeTimestamp = Convert.ToUInt64(bString, 2); DecodeTimestamp = (ulong)buffer[tempIndex + 4] >> 1; DecodeTimestamp += (ulong)buffer[tempIndex + 3] << 7; DecodeTimestamp += (ulong)(buffer[tempIndex + 2] & Helper.B11111110) << 14; DecodeTimestamp += (ulong)buffer[tempIndex + 1] << 22; DecodeTimestamp += (ulong)(buffer[tempIndex + 0] & Helper.B00001110) << 29; } int dataIndex = index + HeaderDataLength + 24 - Mpeg2Header.Length; int dataSize = Length - (4 + HeaderDataLength); if (dataSize < 0 || (dataSize + dataIndex > buffer.Length)) // to fix bad subs... { dataSize = buffer.Length - dataIndex; if (dataSize < 0) return; } _dataBuffer = new byte[dataSize]; Buffer.BlockCopy(buffer, dataIndex, _dataBuffer, 0, dataSize); } public void WriteToStream(Stream stream) { stream.Write(_dataBuffer, 0, _dataBuffer.Length); } } }