예제 #1
0
        public void AddPacket(TsPacket newPacket)
        {
            try
            {
                if (newPacket.Pid != Pid)
                    throw new InvalidOperationException("Cannot add TS Packet from different pid to a metric!");

                if (newPacket.TransportErrorIndicator)
                {
                    OnTransportErrorIndicatorDetected(newPacket.Pid);
                }
                else
                {
                    CheckCcContinuity(newPacket);
                    LastCc = newPacket.ContinuityCounter;
                }

                PacketCount++;
                _periodPacketCount++;
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception generated within AddPacket method: " + ex.Message);
            }
        }
예제 #2
0
파일: PES.cs 프로젝트: Cinegy/TsAnalyser
        public Pes(TsPacket packet)
        {
            PacketStartCodePrefix = (uint)((packet.PesHeader.Payload[0] << 16) + (packet.PesHeader.Payload[1] << 8) + packet.PesHeader.Payload[2]);
            StreamId = packet.PesHeader.Payload[3];
            PesPacketLength = (ushort)((packet.PesHeader.Payload[4] << 8) + packet.PesHeader.Payload[5]);
            _data = new byte[PesPacketLength + 6];

            Buffer.BlockCopy(packet.PesHeader.Payload, 0, _data, _pesBytes, packet.PesHeader.Payload.Length);
            _pesBytes += (ushort)(packet.PesHeader.Payload.Length);
            Buffer.BlockCopy(packet.Payload, 0, _data, _pesBytes, packet.Payload.Length);
            _pesBytes += (ushort)(packet.Payload.Length);
        }
        public void AddPacket(TsPacket packet)
        {
            CheckPid(packet.Pid);

            if (!packet.PayloadUnitStartIndicator) return;

            InProgressTable = new ProgramAssociationTable {PointerField = packet.Payload[0]};
            
            if (InProgressTable.PointerField > packet.Payload.Length)
            {
                Debug.Assert(true, "Program Association TableOld has packet pointer outside the packet.");
            }

            var pos = 1 + InProgressTable.PointerField;

            InProgressTable.VersionNumber = (byte) (packet.Payload[pos + 5] & 0x3E);
        
            if (ProgramAssociationTable != null &&
                ProgramAssociationTable.VersionNumber == InProgressTable.VersionNumber)
            {
                InProgressTable = null;
                return;
            }

            InProgressTable.TableId = packet.Payload[pos];
            InProgressTable.SectionLength = (short)(((packet.Payload[pos + 1] & 0x3) << 8) + packet.Payload[pos + 2]);
            InProgressTable.TransportStreamId = (short)((packet.Payload[pos + 3] << 8) + packet.Payload[pos + 4]);

            InProgressTable.CurrentNextIndicator = (packet.Payload[pos + 5] & 0x1) != 0;
            InProgressTable.SectionNumber = packet.Payload[pos + 6];
            InProgressTable.LastSectionNumber = packet.Payload[pos + 7];

            InProgressTable.ProgramNumbers = new short[(InProgressTable.SectionLength - 9)/4];
            InProgressTable.Pids = new short[(InProgressTable.SectionLength - 9)/4];
            var programStart = pos + 8;

            for (var i = 0; i < (InProgressTable.SectionLength - 9)/4; i++)
            {
                InProgressTable.ProgramNumbers[i] =
                    (short)
                        ((packet.Payload[programStart + (i*4)] << 8) + packet.Payload[programStart + 1 + (i*4)]);
                InProgressTable.Pids[i] =
                    (short)
                        (((packet.Payload[programStart + 2 + (i*4)] & 0x1F) << 8) +
                         packet.Payload[programStart + 3 + (i*4)]);      
            }

            ProgramAssociationTable = InProgressTable;

            OnTableChangeDetected();

        }
예제 #4
0
        public void AddPacket(TsPacket packet)
        {
            CheckPid(packet.Pid);

            if (packet.PayloadUnitStartIndicator)
            {
                InProgressTable = new ProgramMapTable { Pid = packet.Pid, PointerField = packet.Payload[0] };

                if (InProgressTable.PointerField > packet.Payload.Length)
                {
                    Debug.Assert(true, "Program Map Table has packet pointer outside the packet.");
                }

                var pos = 1 + InProgressTable.PointerField;

                InProgressTable.VersionNumber = (byte)(packet.Payload[pos + 5] & 0x3E);

                if (ProgramMapTable?.VersionNumber == InProgressTable.VersionNumber)
                {
                    InProgressTable = null;
                    return;
                }

                InProgressTable.TableId = packet.Payload[pos];
                InProgressTable.SectionLength =
                    (short)(((packet.Payload[pos + 1] & 0x3) << 8) + packet.Payload[pos + 2]);
                InProgressTable.ProgramNumber = (ushort)((packet.Payload[pos + 3] << 8) + packet.Payload[pos + 4]);
                InProgressTable.CurrentNextIndicator = (packet.Payload[pos + 5] & 0x1) != 0;
                InProgressTable.SectionNumber = packet.Payload[pos + 6];
                InProgressTable.LastSectionNumber = packet.Payload[pos + 7];
                InProgressTable.PcrPid = (ushort)(((packet.Payload[pos + 8] & 0x1f) << 8) + packet.Payload[pos + 9]);
                InProgressTable.ProgramInfoLength =
                    (ushort)(((packet.Payload[pos + 10] & 0x3) << 8) + packet.Payload[pos + 11]);

            }

            if (InProgressTable == null) return;

            AddData(packet);

            if (!HasAllBytes()) return;

            var startOfNextField = GetDescriptors(InProgressTable.ProgramInfoLength, InProgressTable.PointerField + 13);

            InProgressTable.EsStreams = ReadEsInfoElements(InProgressTable.SectionLength, startOfNextField);

            ProgramMapTable = InProgressTable;

            OnTableChangeDetected();
        }
예제 #5
0
        private void CheckCcContinuity(TsPacket newPacket)
        {
            try
            {
                if (PacketCount == 0)
                {
                    //fresh metric, first packet - so no possible error yet...
                    return;
                }

                if (newPacket.Pid == 0x1fff)
                    return;

                if (LastCc == newPacket.ContinuityCounter)
                {
                    if (newPacket.ContainsPayload)
                    {
                        CcErrorCount++;
                        _periodCcErrorCount++;
                    }

                    //special case of no data... ignore for now
                    //TODO: check for no data flag in original packet
                    Debug.Assert(true, "Special CC repeated case - requires investigation!");
                    return;
                }

                if (LastCc != 15)
                {
                    if (LastCc + 1 != newPacket.ContinuityCounter)
                    {
                        CcErrorCount++;
                        _periodCcErrorCount++;
                        OnDiscontinuityDetected(newPacket.Pid);
                        return;
                    }
                }

                if (LastCc != 15 || newPacket.ContinuityCounter == 0) return;

                CcErrorCount++;
                _periodCcErrorCount++;
                OnDiscontinuityDetected(newPacket.Pid);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception generated within CheckCcContinuity method: " + ex.Message);
            }
        }
예제 #6
0
파일: PES.cs 프로젝트: Cinegy/TsAnalyser
        public bool Add(TsPacket packet)
        {
            if (packet.PayloadUnitStartIndicator) return false;

            if ((PesPacketLength + 6 - _pesBytes) > packet.Payload.Length)
            {
                Buffer.BlockCopy(packet.Payload, 0, _data, _pesBytes, packet.Payload.Length);
                _pesBytes += (ushort)(packet.Payload.Length);
            }
            else
            {
                Buffer.BlockCopy(packet.Payload, 0, _data, _pesBytes, (PesPacketLength + 6 - _pesBytes));
                _pesBytes += (ushort)(PesPacketLength + 6 - _pesBytes);
            }

            return true;
        }
예제 #7
0
        protected void AddData(TsPacket packet)
        {
            CheckPid(packet.Pid);

            if (packet.PayloadUnitStartIndicator)
            {
                Data = new byte[InProgressTable.SectionLength + 3];
                _tableBytes = 0;
            }

            if ((InProgressTable.SectionLength + 3 - _tableBytes) > packet.Payload.Length)
            {
                Buffer.BlockCopy(packet.Payload, 0, Data, _tableBytes, packet.Payload.Length);
                _tableBytes += (ushort)(packet.Payload.Length);
            }
            else
            {
                Buffer.BlockCopy(packet.Payload, 0, Data, _tableBytes, (InProgressTable.SectionLength + 3 - _tableBytes));
                _tableBytes += (ushort)(InProgressTable.SectionLength + 3 - _tableBytes);
            }
        }
예제 #8
0
        public void AddPacket(TsDecoder.TransportStream.TsDecoder tsDecoder, TsPacket tsPacket)
        {
            if (_currentTeletextDescriptor == null)
            {
                Setup(tsDecoder);

                if (_currentTeletextDescriptor != null)
                {
                    Debug.WriteLine($"Locked onto teletext PID for {TeletextPid} ");
                }
            }

            if (tsPacket.Pid != TeletextPid) return;

            if (tsPacket.PayloadUnitStartIndicator)
            {
                if (_currentTeletextPes != null)
                {
                    if (_currentTeletextPes.HasAllBytes())
                    {
                        _currentTeletextPes.Decode();
                        foreach (var key in _teletextSubtitlePage.Keys)
                        {
                            _teletextSubtitlePage[key].DecodeTeletextData(_currentTeletextPes);
                        }
                    }
                }

                _currentTeletextPes = new Pes(tsPacket);
            }
            else
            {
                _currentTeletextPes?.Add(tsPacket);
            }
        }
        public void AddPacket(TsPacket packet)
        {
            CheckPid(packet.Pid);

            if (packet.PayloadUnitStartIndicator)
            {
                InProgressTable = new ServiceDescriptionTable { Pid = packet.Pid, PointerField = packet.Payload[0] };

                if (InProgressTable.PointerField > packet.Payload.Length)
                {
                    Debug.Assert(true, "Service Description Table has packet pointer outside the packet.");
                }

                var pos = 1 + InProgressTable.PointerField;

                InProgressTable.VersionNumber = (byte)(packet.Payload[pos + 5] & 0x3E);
                
                InProgressTable.TableId = packet.Payload[pos];

                //TODO: Refactor with enum for well-known table IDs, and add option below as filter
                if (InProgressTable.TableId != 0x42)
                {
                    InProgressTable = null;
                    return;
                }

                if (ServiceDescriptionTable?.VersionNumber != InProgressTable.VersionNumber)
                {
                    //if the version number of any section jumps, we need to refresh
                    _sectionsCompleted = new HashSet<int>();
                    ServiceDescriptionItems = new List<ServiceDescriptionItem>();
                }

                InProgressTable.SectionLength =
                    (short)(((packet.Payload[pos + 1] & 0x3) << 8) + packet.Payload[pos + 2]);
                
                InProgressTable.TransportStreamId = (ushort)((packet.Payload[pos + 3] << 8) + packet.Payload[pos + 4]);
                InProgressTable.CurrentNextIndicator = (packet.Payload[pos + 5] & 0x1) != 0;
                InProgressTable.SectionNumber = packet.Payload[pos + 6];
                InProgressTable.LastSectionNumber = packet.Payload[pos + 7];
                InProgressTable.OriginalNetworkId = (ushort)((packet.Payload[pos + 8] << 8) + packet.Payload[pos + 9]);
            }
            
            if (InProgressTable == null) return;

            if (_sectionsCompleted.Contains(InProgressTable.SectionNumber))
            {
                InProgressTable = null;
                return;
            }

            AddData(packet);

            if (!HasAllBytes()) return;

            var startOfNextField = (ushort)(InProgressTable.PointerField + 12);

            var transportStreamLoopEnd = (ushort)(InProgressTable.SectionLength - 4);

            var items = new List<ServiceDescriptionItem>();

            while (startOfNextField < transportStreamLoopEnd)
            {
                var item = new ServiceDescriptionItem
                {
                    ServiceId = (ushort)((Data[startOfNextField] << 8) + Data[startOfNextField + 1]),
                    EitScheduleFlag = ((Data[startOfNextField + 2]) & 0x02) == 0x02,
                    EitPresentFollowingFlag = ((Data[startOfNextField + 2]) & 0x01) == 0x01,
                    RunningStatus = (byte)((Data[startOfNextField + 3] >> 5) & 0x07),
                    FreeCaMode = (Data[startOfNextField + 3] & 0x10) == 0x10,
                    DescriptorsLoopLength =
                        (ushort)(((Data[startOfNextField + 3] & 0xf) << 8) + Data[startOfNextField + 4])
                };

                var descriptors = new List<Descriptor>();

                startOfNextField = (ushort)(startOfNextField + 5);
                var endOfDescriptors = (ushort)(startOfNextField + item.DescriptorsLoopLength);

                if (endOfDescriptors > Data.Length)
                {
                    throw new InvalidDataException("Descriptor data in Service Description is marked beyond available data");
                }

                while (startOfNextField < endOfDescriptors)
                {
                    var des = DescriptorFactory.DescriptorFromData(Data, startOfNextField);
                    descriptors.Add(des);
                    startOfNextField += (ushort)(des.DescriptorLength + 2);
                }
                item.Descriptors = descriptors;
                items.Add(item);
            }

            InProgressTable.Items = items;
            
            ServiceDescriptionItems.AddRange(items);

            ServiceDescriptionTable = InProgressTable;
            _sectionsCompleted.Add(InProgressTable.SectionNumber);

            OnTableChangeDetected();
        }
예제 #10
0
        public static TsPacket[] GetTsPacketsFromData(byte[] data)
        {
            try
            {
                var maxPackets = (data.Length) / TsPacketSize;
                var tsPackets = new TsPacket[maxPackets];

                var start = FindSync(data, 0);
                var packetCounter = 0;

                while (start >= 0)
                {
                    var tsPacket = new TsPacket
                    {
                        SyncByte = data[start],
                        Pid = (short)(((data[start + 1] & 0x1F) << 8) + (data[start + 2])),
                        TransportErrorIndicator = (data[start + 1] & 0x80) != 0,
                        PayloadUnitStartIndicator = (data[start + 1] & 0x40) != 0,
                        TransportPriority = (data[start + 1] & 0x20) != 0,
                        ScramblingControl = (short)(data[start + 3] >> 6),
                        AdaptationFieldExists = (data[start + 3] & 0x20) != 0,
                        ContainsPayload = (data[start + 3] & 0x10) != 0,
                        ContinuityCounter = (short)(data[start + 3] & 0xF)
                    };

                    if (tsPacket.ContainsPayload && !tsPacket.TransportErrorIndicator)
                    {
                        var payloadOffs = start + 4;
                        var payloadSize = TsPacketSize - 4;

                        if (tsPacket.AdaptationFieldExists)
                        {
                            var adaptationFieldSize = 1 + data[payloadOffs];

                            if (adaptationFieldSize >= payloadSize)
                                throw new Exception("adaptationFieldSize >= payloadSize");

                            //todo: actually read adaptationfield here

                            payloadSize -= adaptationFieldSize;
                            payloadOffs += adaptationFieldSize;
                        }

                        if (tsPacket.PayloadUnitStartIndicator)
                        {
                            if (payloadOffs > (data.Length - 2) || data[payloadOffs] != 0 || data[payloadOffs + 1] != 0 || data[payloadOffs + 2] != 1)
                            {
#if DEBUG
                            //    Debug.WriteLine("PES syntax error: no PES startcode found, or payload offset exceeds boundary of data");
#endif
                            }
                            else
                            {
                                tsPacket.PesHeader = new PesHdr
                                {
                                    StartCode = 0x100 + data[payloadOffs + 3],
                                    Pts = -1,
                                    Dts = -1
                                };

                                var ptsDtsFlag = data[payloadOffs + 7] >> 6;

                                switch (ptsDtsFlag)
                                {
                                    case 2:
                                        tsPacket.PesHeader.Pts = Get_TimeStamp(2, data, payloadOffs + 9);
                                        break;
                                    case 3:
                                        tsPacket.PesHeader.Pts = Get_TimeStamp(3, data, payloadOffs + 9);
                                        tsPacket.PesHeader.Dts = Get_TimeStamp(1, data, payloadOffs + 14);
                                        break;
                                    case 1:
                                        throw new Exception("PES Syntax error: pts_dts_flag = 1");
                                }

                                var pesLength = 9 + data[payloadOffs + 8];
                                tsPacket.PesHeader.Payload = new byte[pesLength];
                                Buffer.BlockCopy(data, payloadOffs, tsPacket.PesHeader.Payload, 0, pesLength);

                                payloadOffs += pesLength;
                                payloadSize -= pesLength;
                            }
                        }

                        if (payloadSize < 1)
                        {
                            tsPacket.TransportErrorIndicator = true;
                        }
                        else
                        {
                            tsPacket.Payload = new byte[payloadSize];
                            Buffer.BlockCopy(data, payloadOffs, tsPacket.Payload, 0, payloadSize);
                        }
                    }

                    tsPackets[packetCounter++] = tsPacket;

                    start += TsPacketSize;

                    if (start >= data.Length)
                        break;
                    if (data[start] != SyncByte)
                        break;  // but this is strange!
                }

                return tsPackets;
            }

            catch (Exception ex)
            {
                Debug.WriteLine("Exception within GetTsPacketsFromData method: " + ex.Message);
            }

            return null;
        }