/// <summary> /// Gets the byte section of the table. /// </summary> /// <param name="packet">The starting packet for the table.</param> /// <param name="tableId">TableId</param> /// <returns>Section of bytes.</returns> private byte[] GetEntireTable(TSPacketInfo packet, int tableId) { Ensure.IsNotNull(Log, packet, "packet is null"); if (!packet.PayloadUnitStartIndicator || !packet.HasPayload) { //throw new CustomException("The packet doesn't contain a table section."); return(null); } var pointerField = packet.GetDataByte(0); if (pointerField != 0) { //Ensure.IsZero(Log, pointerField, "pointer field must be zero."); return(null); } // TODO: move to PATSection var pTableId = packet.GetDataByte(1); if (tableId != pTableId) { //Ensure.AreEqual(Log, tableId, pTableId, "TableId is invalid."); return(null); } var sectionSyntaxIndicator = BinaryUtils.ReadBool(packet.GetDataByte(2), 0); if (!sectionSyntaxIndicator) { //Ensure.IsTrue(Log, sectionSyntaxIndicator, "sectionSyntaxIndicator is not true."); return(null); } var padding = BinaryUtils.ReadBool(packet.GetDataByte(2), 1); if (padding) { //Ensure.IsFalse(Log, padding, "padding is not false."); return(null); } var reserved = BinaryUtils.GetBits(packet.GetDataByte(2), 2, 2); if (reserved != 3) { //Ensure.AreEqual(Log, 3, reserved, "reserved is not 11b (3)."); return(null); } var sectionLen = BinaryUtils.GetBitsEx(packet.Segment, packet.DataBytePos + 2, 4, 12); sectionLen = Math.Min(4096, sectionLen) - (Constants.TSPacketSize - packet.DataBytePos - 3); // TODO: Review. var sectionData = new byte[4096]; var sectionOffset = 0; Buffer.BlockCopy(packet.Segment.Array, packet.Segment.Offset, sectionData, sectionOffset, packet.Segment.Count); sectionOffset += packet.Segment.Count; while (sectionLen > 0) { var nextPacket = this.GetPacket(); if (nextPacket == null) { continue; } if (!nextPacket.PayloadUnitStartIndicator && nextPacket.AdaptationFieldControl == AdaptationType.Payload && nextPacket.PID == packet.PID) { var len = nextPacket.Segment.Count - 4; Buffer.BlockCopy(nextPacket.Segment.Array, nextPacket.Segment.Offset + 4, sectionData, sectionOffset, len); sectionOffset += len; sectionLen -= len; } } return(sectionData); }
/// <summary> /// Parse stream and search for A / V types. /// </summary> private void ParseStream() { subStreams.Clear(); #region Looking for PAT var count = 0; var packet = GetPacket(); while (packet == null || packet.PID != 0) { packet = GetPacket(); count++; if (count > 4000) { throw new CustomException("PAT is not found."); } } #endregion #region Parse PAT (Program Association Table) var table = GetEntireTable(packet, 0x00); if (table == null) { throw new CustomException("PAT is not parsed"); } var pTable = new TSPacketInfo(table); var sectionLen = BinaryUtils.GetBitsEx(pTable.Segment, pTable.DataBytePos + 2, 4, 12); //var transportStreamId = BinaryUtils.GetBitsEx(pTable.Bytes, pTable.DataBytePos + 4, 0, 16); //var patVersion = BinaryUtils.GetBitsEx(pTable.Bytes, pTable.DataBytePos + 6, 2, 5); var infoLen = sectionLen - 5 - 4; var numOfId = infoLen / 4; var programs = new List<Tuple<long, long>>(); for (var i = 0; i < numOfId; i++) { var progNum = BinaryUtils.GetBitsEx(pTable.Segment, pTable.DataBytePos + 9 + 4 * i, 0, 16); var pid = BinaryUtils.GetBitsEx(pTable.Segment, pTable.DataBytePos + 11 + 4 * i, 3, 13); if (progNum == 0) { //var networkId = pid; } else { programs.Add(new Tuple<long, long>(progNum, pid)); } } #endregion #region Parse PMT (Program Map Table) Ensure.IsNotZero(Log, programs.Count, "No programs are found"); count = 0; //var list = new List<int>(); byte[] pmtTable; while (true) { #region GUARD (COUNT) count++; if (count > 20000) { //break; throw new CustomException("PMT is not found."); } #endregion #region SEARCH PMT var nextPacket = this.GetPacket(); if (nextPacket == null) { continue; } pmtTable = this.GetEntireTable(nextPacket, 0x02); if (pmtTable == null) { continue; } //list.Add(nextPacket.PID); //continue; #endregion #region CHECK PROGRAMS var found = false; foreach (var prog in programs) { if (prog.Second == nextPacket.PID) { found = true; break; } } if (found) { break; } #endregion } #endregion var pmtPacket = new TSPacketInfo(pmtTable); sectionLen = BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtPacket.DataBytePos + 2, 4, 12); var programInfoLen = BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtPacket.DataBytePos + 11, 4, 12); var pmtInfoLen = sectionLen - 13 - programInfoLen; var pmtStartPos = Convert.ToInt32(pmtPacket.DataBytePos + 13 + programInfoLen); while (pmtInfoLen > 0) { var streamType = BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtStartPos, 0, 8); var ePID = Convert.ToInt32(BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtStartPos + 1, 3, 13)); var eLen = Convert.ToInt32(BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtStartPos + 3, 4, 12)); SubStreamType subStreamType = SubStreamType.None; switch (streamType) { case 0x02: subStreamType = SubStreamType.VideoMP2; break; case 0x03: case 0x04: subStreamType = SubStreamType.AudioMP2; break; case 0x06: // DTS checking if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x73)) { subStreamType = SubStreamType.AudioDTS; } // Subtitle checking else if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x59)) { subStreamType = SubStreamType.Subtitle; } // AC3 checking else if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x6a)) { subStreamType = SubStreamType.AudioAC3; } // Teletext checking else if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x56)) { subStreamType = SubStreamType.Teletext; } break; case 0x0B: subStreamType = SubStreamType.Subtitle; break; case 0x0F: case 0x11: subStreamType = SubStreamType.AudioAAC; break; case 0x10: subStreamType = SubStreamType.VideoMP4; break; case 0x1b: subStreamType = SubStreamType.VideoH264; break; case 0x81: case 0x83: case 0x85: case 0x8A: subStreamType = SubStreamType.AudioAC3; break; } subStreams.Add(new Tuple<int, SubStreamType>(ePID, subStreamType)); pmtInfoLen -= (eLen + 5); pmtStartPos += (eLen + 5); } }
/// <summary> /// Parse stream and search for A / V types. /// </summary> private void ParseStream() { subStreams.Clear(); #region Looking for PAT var count = 0; var packet = GetPacket(); while (packet == null || packet.PID != 0) { packet = GetPacket(); count++; if (count > 4000) { throw new CustomException("PAT is not found."); } } #endregion #region Parse PAT (Program Association Table) var table = GetEntireTable(packet, 0x00); if (table == null) { throw new CustomException("PAT is not parsed"); } var pTable = new TSPacketInfo(table); var sectionLen = BinaryUtils.GetBitsEx(pTable.Segment, pTable.DataBytePos + 2, 4, 12); //var transportStreamId = BinaryUtils.GetBitsEx(pTable.Bytes, pTable.DataBytePos + 4, 0, 16); //var patVersion = BinaryUtils.GetBitsEx(pTable.Bytes, pTable.DataBytePos + 6, 2, 5); var infoLen = sectionLen - 5 - 4; var numOfId = infoLen / 4; var programs = new List <Tuple <long, long> >(); for (var i = 0; i < numOfId; i++) { var progNum = BinaryUtils.GetBitsEx(pTable.Segment, pTable.DataBytePos + 9 + 4 * i, 0, 16); var pid = BinaryUtils.GetBitsEx(pTable.Segment, pTable.DataBytePos + 11 + 4 * i, 3, 13); if (progNum == 0) { //var networkId = pid; } else { programs.Add(new Tuple <long, long>(progNum, pid)); } } #endregion #region Parse PMT (Program Map Table) Ensure.IsNotZero(Log, programs.Count, "No programs are found"); count = 0; //var list = new List<int>(); byte[] pmtTable; while (true) { #region GUARD (COUNT) count++; if (count > 20000) { //break; throw new CustomException("PMT is not found."); } #endregion #region SEARCH PMT var nextPacket = this.GetPacket(); if (nextPacket == null) { continue; } pmtTable = this.GetEntireTable(nextPacket, 0x02); if (pmtTable == null) { continue; } //list.Add(nextPacket.PID); //continue; #endregion #region CHECK PROGRAMS var found = false; foreach (var prog in programs) { if (prog.Second == nextPacket.PID) { found = true; break; } } if (found) { break; } #endregion } #endregion var pmtPacket = new TSPacketInfo(pmtTable); sectionLen = BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtPacket.DataBytePos + 2, 4, 12); var programInfoLen = BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtPacket.DataBytePos + 11, 4, 12); var pmtInfoLen = sectionLen - 13 - programInfoLen; var pmtStartPos = Convert.ToInt32(pmtPacket.DataBytePos + 13 + programInfoLen); while (pmtInfoLen > 0) { var streamType = BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtStartPos, 0, 8); var ePID = Convert.ToInt32(BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtStartPos + 1, 3, 13)); var eLen = Convert.ToInt32(BinaryUtils.GetBitsEx(pmtPacket.Segment, pmtStartPos + 3, 4, 12)); SubStreamType subStreamType = SubStreamType.None; switch (streamType) { case 0x02: subStreamType = SubStreamType.VideoMP2; break; case 0x03: case 0x04: subStreamType = SubStreamType.AudioMP2; break; case 0x06: // DTS checking if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x73)) { subStreamType = SubStreamType.AudioDTS; } // Subtitle checking else if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x59)) { subStreamType = SubStreamType.Subtitle; } // AC3 checking else if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x6a)) { subStreamType = SubStreamType.AudioAC3; } // Teletext checking else if (CheckDescriptorES(pmtPacket.Segment, pmtStartPos + 5, eLen, 0x56)) { subStreamType = SubStreamType.Teletext; } break; case 0x0B: subStreamType = SubStreamType.Subtitle; break; case 0x0F: case 0x11: subStreamType = SubStreamType.AudioAAC; break; case 0x10: subStreamType = SubStreamType.VideoMP4; break; case 0x1b: subStreamType = SubStreamType.VideoH264; break; case 0x81: case 0x83: case 0x85: case 0x8A: subStreamType = SubStreamType.AudioAC3; break; } subStreams.Add(new Tuple <int, SubStreamType>(ePID, subStreamType)); pmtInfoLen -= (eLen + 5); pmtStartPos += (eLen + 5); } }
/// <summary> /// Gets the byte section of the table. /// </summary> /// <param name="packet">The starting packet for the table.</param> /// <param name="tableId">TableId</param> /// <returns>Section of bytes.</returns> private byte[] GetEntireTable(TSPacketInfo packet, int tableId) { Ensure.IsNotNull(Log, packet, "packet is null"); if (!packet.PayloadUnitStartIndicator || !packet.HasPayload) { //throw new CustomException("The packet doesn't contain a table section."); return null; } var pointerField = packet.GetDataByte(0); if (pointerField != 0) { //Ensure.IsZero(Log, pointerField, "pointer field must be zero."); return null; } // TODO: move to PATSection var pTableId = packet.GetDataByte(1); if (tableId != pTableId) { //Ensure.AreEqual(Log, tableId, pTableId, "TableId is invalid."); return null; } var sectionSyntaxIndicator = BinaryUtils.ReadBool(packet.GetDataByte(2), 0); if (!sectionSyntaxIndicator) { //Ensure.IsTrue(Log, sectionSyntaxIndicator, "sectionSyntaxIndicator is not true."); return null; } var padding = BinaryUtils.ReadBool(packet.GetDataByte(2), 1); if (padding) { //Ensure.IsFalse(Log, padding, "padding is not false."); return null; } var reserved = BinaryUtils.GetBits(packet.GetDataByte(2), 2, 2); if (reserved != 3) { //Ensure.AreEqual(Log, 3, reserved, "reserved is not 11b (3)."); return null; } var sectionLen = BinaryUtils.GetBitsEx(packet.Segment, packet.DataBytePos + 2, 4, 12); sectionLen = Math.Min(4096, sectionLen) - (Constants.TSPacketSize - packet.DataBytePos - 3); // TODO: Review. var sectionData = new byte[4096]; var sectionOffset = 0; Buffer.BlockCopy(packet.Segment.Array, packet.Segment.Offset, sectionData, sectionOffset, packet.Segment.Count); sectionOffset += packet.Segment.Count; while (sectionLen > 0) { var nextPacket = this.GetPacket(); if (nextPacket == null) { continue; } if (!nextPacket.PayloadUnitStartIndicator && nextPacket.AdaptationFieldControl == AdaptationType.Payload && nextPacket.PID == packet.PID) { var len = nextPacket.Segment.Count - 4; Buffer.BlockCopy(nextPacket.Segment.Array, nextPacket.Segment.Offset + 4, sectionData, sectionOffset, len); sectionOffset += len; sectionLen -= len; } } return sectionData; }