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);
        }
Beispiel #2
0
        private void CheckPmt(TsPacket tsPacket)
        {
            if (ProgramAssociationTable == null)
            {
                return;
            }

            if (tsPacket.Pid == (short)PidType.NitPid)
            {
                _nitFactory.AddPacket(tsPacket);
                return;
            }

            // CheckPcr(tsPacket);

            var contains = false;

            foreach (var pid in ProgramAssociationTable.Pids)
            {
                if (pid != tsPacket.Pid)
                {
                    continue;
                }
                contains = true;
                break;
            }

            if (!contains)
            {
                return;
            }

            ProgramMapTableFactory selectedPmt = null;

            foreach (var t in _pmtFactories)
            {
                if (t.TablePid != tsPacket.Pid)
                {
                    continue;
                }
                selectedPmt = t;
                break;
            }

            if (selectedPmt == null)
            {
                selectedPmt = new ProgramMapTableFactory();
                selectedPmt.TableChangeDetected += _pmtFactory_TableChangeDetected;
                _pmtFactories?.Add(selectedPmt);
            }

            selectedPmt.AddPacket(tsPacket);
        }
        protected virtual void OnTsPacketReadyDetected(TsPacket tsPacket)
        {
            var handler = TsPacketReady;

            if (handler == null)
            {
                return;
            }
            var args = new TsPacketReadyEventArgs {
                TsPacket = tsPacket
            };

            handler(this, args);
        }
        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);
        }
Beispiel #5
0
        public void AddPacket(TsPacket newPacket)
        {
            try
            {
                if (newPacket.TransportErrorIndicator)
                {
                    return;
                }

                switch (newPacket.Pid)
                {
                case (short)PidType.PatPid:
                    _patFactory.AddPacket(newPacket);
                    break;

                case (short)PidType.SdtPid:
                    _sdtFactory.AddPacket(newPacket);
                    break;

                case (short)PidType.EitPid:
                    _eitFactory.AddPacket(newPacket);
                    break;

                case 2048:
                    _sitFactory.AddPacket(newPacket);
                    break;

                default:
                    CheckPmt(newPacket);
                    break;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception generated within AddPacket method: " + ex.Message);
            }
        }
        /// <summary>
        /// Returns TsPackets for any input data. If data ends with incomplete packet, this is stored and prepended to next call.
        /// If data stream is restarted, prior buffer will be skipped as sync will not be acknowledged - but any restarts should being with first byte as sync to avoid possible merging with prior data if lengths coincide.
        /// </summary>
        /// <param name="data">Aligned or unaligned data buffer containing TS packets. Aligned is more efficient if possible.</param>
        /// <param name="dataSize">Optional length parameter to limit amount of data read from referenced array.</param>
        /// <param name="retainPayload">Optional parameter to trigger any resulting TS payload to be copied into the returned structure</param>
        /// <param name="preserveSourceData">Optional parameter to trigger complete copy of source data for TS packet to be held in array for quick access</param>
        /// <returns>Complete TS packets from this data and any prior partial data rolled over.</returns>
        public TsPacket[] GetTsPacketsFromData(byte[] data, int dataSize = 0, bool retainPayload = true, bool preserveSourceData = false)
        {
            try
            {
                if (dataSize == 0)
                {
                    dataSize = data.Length;
                }

                if (_residualData != null)
                {
                    var tempArray = new byte[dataSize];
                    Buffer.BlockCopy(data, 0, tempArray, 0, dataSize);
                    data = new byte[_residualData.Length + tempArray.Length];
                    Buffer.BlockCopy(_residualData, 0, data, 0, _residualData.Length);
                    Buffer.BlockCopy(tempArray, 0, data, _residualData.Length, tempArray.Length);
                    dataSize = data.Length;
                }

                var maxPackets = (dataSize) / TsPacketFixedSize;
                var tsPackets  = new TsPacket[maxPackets];

                var packetCounter = 0;

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

                while (start >= 0 && ((dataSize - start) >= TsPacketFixedSize))
                {
                    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),
                        SourceBufferIndex         = start
                    };

                    if (preserveSourceData)
                    {
                        tsPacket.SourceData = new byte[TsPacketFixedSize];
                        Buffer.BlockCopy(data, start, tsPacket.SourceData, 0, TsPacketFixedSize);
                    }

                    //skip packets with error indicators or on the null PID
                    if (!tsPacket.TransportErrorIndicator && (tsPacket.Pid != (short)PidType.NullPid))
                    {
                        var payloadOffs = start + 4;
                        var payloadSize = TsPacketFixedSize - 4;

                        if (tsPacket.AdaptationFieldExists)
                        {
                            tsPacket.AdaptationField = new AdaptationField()
                            {
                                FieldSize = data[start + 4],
                                DiscontinuityIndicator            = (data[start + 5] & 0x80) != 0,
                                RandomAccessIndicator             = (data[start + 5] & 0x40) != 0,
                                ElementaryStreamPriorityIndicator = (data[start + 5] & 0x20) != 0,
                                PcrFlag                      = (data[start + 5] & 0x10) != 0,
                                OpcrFlag                     = (data[start + 5] & 0x8) != 0,
                                SplicingPointFlag            = (data[start + 5] & 0x4) != 0,
                                TransportPrivateDataFlag     = (data[start + 5] & 0x2) != 0,
                                AdaptationFieldExtensionFlag = (data[start + 5] & 0x1) != 0
                            };

                            if (tsPacket.AdaptationField.FieldSize >= payloadSize)
                            {
#if DEBUG
                                Debug.WriteLine("TS packet data adaptationFieldSize >= payloadSize");
#endif
                                return(null);
                            }

                            if (tsPacket.AdaptationField.PcrFlag && tsPacket.AdaptationField.FieldSize > 0)
                            {
                                //Packet has PCR
                                tsPacket.AdaptationField.Pcr = (((uint)(data[start + 6]) << 24) +
                                                                ((uint)(data[start + 7] << 16)) +
                                                                ((uint)(data[start + 8] << 8)) + (data[start + 9]));

                                tsPacket.AdaptationField.Pcr <<= 1;

                                if ((data[start + 10] & 0x80) == 1)
                                {
                                    tsPacket.AdaptationField.Pcr |= 1;
                                }

                                tsPacket.AdaptationField.Pcr *= 300;
                                var iLow = (uint)((data[start + 10] & 1) << 8) + data[start + 11];
                                tsPacket.AdaptationField.Pcr += iLow;


                                if (_lastPcr == 0)
                                {
                                    _lastPcr = tsPacket.AdaptationField.Pcr;
                                }
                            }


                            payloadSize -= tsPacket.AdaptationField.FieldSize;
                            payloadOffs += tsPacket.AdaptationField.FieldSize;
                        }

                        if (tsPacket.ContainsPayload && tsPacket.PayloadUnitStartIndicator)
                        {
                            if (payloadOffs > (dataSize - 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    = (uint)((data[payloadOffs] << 16) + (data[payloadOffs + 1] << 8) + data[payloadOffs + 2]),
                                    StreamId     = data[payloadOffs + 3],
                                    PacketLength = (ushort)((data[payloadOffs + 4] << 8) + data[payloadOffs + 5]),
                                    Pts          = -1,
                                    Dts          = -1
                                };

                                tsPacket.PesHeader.HeaderLength = (byte)tsPacket.PesHeader.PacketLength;

                                var stmrId = tsPacket.PesHeader.StreamId; //just copying to small name to make code less huge and slightly faster...

                                if ((stmrId != (uint)PesStreamTypes.ProgramStreamMap) &&
                                    (stmrId != (uint)PesStreamTypes.PaddingStream) &&
                                    (stmrId != (uint)PesStreamTypes.PrivateStream2) &&
                                    (stmrId != (uint)PesStreamTypes.ECMStream) &&
                                    (stmrId != (uint)PesStreamTypes.EMMStream) &&
                                    (stmrId != (uint)PesStreamTypes.ProgramStreamDirectory) &&
                                    (stmrId != (uint)PesStreamTypes.DSMCCStream) &&
                                    (stmrId != (uint)PesStreamTypes.H2221TypeEStream))
                                {
                                    var ptsDtsFlag = data[payloadOffs + 7] >> 6;

                                    tsPacket.PesHeader.HeaderLength = (byte)(9 + data[payloadOffs + 8]);

                                    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");
                                    }
                                }

                                tsPacket.PesHeader.Payload = new byte[tsPacket.PesHeader.HeaderLength];
                                Buffer.BlockCopy(data, payloadOffs, tsPacket.PesHeader.Payload, 0, tsPacket.PesHeader.HeaderLength);

                                payloadOffs += tsPacket.PesHeader.HeaderLength;
                                payloadSize -= tsPacket.PesHeader.HeaderLength;
                            }
                        }

                        if (payloadSize > 1 && retainPayload)
                        {
                            tsPacket.Payload = new byte[payloadSize];
                            Buffer.BlockCopy(data, payloadOffs, tsPacket.Payload, 0, payloadSize);
                        }
                    }

                    tsPackets[packetCounter++] = tsPacket;

                    start += TsPacketFixedSize;

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

                if ((start + TsPacketFixedSize) != dataSize)
                {
                    //we have 'residual' data to carry over to next call
                    _residualData = new byte[dataSize - start];
                    Buffer.BlockCopy(data, start, _residualData, 0, dataSize - start);
                }

                return(tsPackets);
            }

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

            return(null);
        }
Beispiel #7
0
        public void AddPacket(TsPacket newPacket)
        {
            try
            {
                //if (newPacket.Pid == 16)
                //{
                //    Console.WriteLine("NIT");
                //}


                //if (newPacket.Pid == 17)
                //{
                //    Console.WriteLine("SDT");
                //}

                if (newPacket.TransportErrorIndicator)
                {
                    return;
                }

                switch (newPacket.Pid)
                {
                case (short)PidType.PatPid:
                    _patFactory.AddPacket(newPacket);
                    break;

                case (short)PidType.SdtPid:
                    _sdtFactory.AddPacket(newPacket);
                    break;

                //case (short)PidType.EitPid:
                //    _eitFactory.AddPacket(newPacket);
                //    break;
                case 2048:
                    _sitFactory.AddPacket(newPacket);
                    break;

                case (short)PidType.TdtPid:
                    _tdtFactory.AddPacket(newPacket);
                    break;

                default:
                    CheckPmt(newPacket);
                    break;
                }

                if (newPacket.Pid == 0x1929)
                {
                    if (!_dsmccDictionary.ContainsKey(newPacket.Pid))
                    {
                        _dsmccDictionary[newPacket.Pid] = new DsmccFactory();
                    }

                    Console.WriteLine("Arqiva test carousel PayloadUnitStartIndicator = " + newPacket.PayloadUnitStartIndicator.ToString() + ", ContainsPayload = " + newPacket.ContainsPayload.ToString());
                    _dsmccDictionary[newPacket.Pid].AddPacket(newPacket);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
                Debug.WriteLine("Exception generated within AddPacket method: " + ex.Message);
            }
        }
Beispiel #8
0
        /// <summary>
        ///     Returns TsPackets for any input data. If data ends with incomplete packet, this is stored and prepended to next
        ///     call.
        ///     If data stream is restarted, prior buffer will be skipped as sync will not be acknowledged - but any restarts
        ///     should being with first byte as sync to avoid possible merging with prior data if lengths coincide.
        /// </summary>
        /// <param name="data">Aligned or unaligned data buffer containing TS packets. Aligned is more efficient if possible.</param>
        /// <returns>Complete TS packets from this data and any prior partial data rolled over.</returns>
        public TsPacket[] GetTsPacketsFromData(byte[] data)
        {
            try
            {
                if (_residualData != null)
                {
                    var tempArray = new byte[data.Length];
                    Buffer.BlockCopy(data, 0, tempArray, 0, data.Length);
                    data = new byte[_residualData.Length + tempArray.Length];
                    Buffer.BlockCopy(_residualData, 0, data, 0, _residualData.Length);
                    Buffer.BlockCopy(tempArray, 0, data, _residualData.Length, tempArray.Length);
                }

                var maxPackets = data.Length / TsPacketSize;
                var tsPackets  = new TsPacket[maxPackets];

                var packetCounter = 0;

                var start = FindSync(data, 0);

                while (start >= 0 && data.Length - start >= TsPacketSize)
                {
                    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)
                    };

                    //skip packets with error indicators or on the null PID
                    if (!tsPacket.TransportErrorIndicator && tsPacket.Pid != (short)PidType.NullPid)
                    {
                        var payloadOffs = start + 4;
                        var payloadSize = TsPacketSize - 4;

                        if (tsPacket.AdaptationFieldExists)
                        {
                            tsPacket.AdaptationField = new AdaptationField
                            {
                                FieldSize = data[start + 4],
                                DiscontinuityIndicator            = (data[start + 5] & 0x80) != 0,
                                RandomAccessIndicator             = (data[start + 5] & 0x40) != 0,
                                ElementaryStreamPriorityIndicator = (data[start + 5] & 0x20) != 0,
                                PcrFlag                      = (data[start + 5] & 0x10) != 0,
                                OpcrFlag                     = (data[start + 5] & 0x8) != 0,
                                SplicingPointFlag            = (data[start + 5] & 0x4) != 0,
                                TransportPrivateDataFlag     = (data[start + 5] & 0x2) != 0,
                                AdaptationFieldExtensionFlag = (data[start + 5] & 0x1) != 0
                            };

                            if (tsPacket.AdaptationField.FieldSize >= payloadSize)
                            {
#if DEBUG
                                Debug.WriteLine("TS packet data adaptationFieldSize >= payloadSize");
#endif
                                return(null);
                            }

                            if (tsPacket.AdaptationField.PcrFlag && tsPacket.AdaptationField.FieldSize > 0)
                            {
                                //Packet has PCR
                                tsPacket.AdaptationField.Pcr = ((uint)data[start + 6] << 24) +
                                                               (uint)(data[start + 7] << 16) +
                                                               (uint)(data[start + 8] << 8) + data[start + 9];

                                tsPacket.AdaptationField.Pcr <<= 1;

                                if ((data[start + 10] & 0x80) == 1)
                                {
                                    tsPacket.AdaptationField.Pcr |= 1;
                                }

                                tsPacket.AdaptationField.Pcr *= 300;
                                var iLow = (uint)((data[start + 10] & 1) << 8) + data[start + 11];
                                tsPacket.AdaptationField.Pcr += iLow;


                                if (_lastPcr == 0)
                                {
                                    _lastPcr = tsPacket.AdaptationField.Pcr;
                                }
                            }


                            payloadSize -= tsPacket.AdaptationField.FieldSize;
                            payloadOffs += tsPacket.AdaptationField.FieldSize;
                        }

                        if (tsPacket.ContainsPayload && 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");
                                }

                                //if (tsPacket.AdaptationField.PcrFlag && ptsDtsFlag > 1)
                                //{
                                //    var ts = new TimeSpan((long)(((long)tsPacket.AdaptationField.Pcr - tsPacket.PesHeader.Pts * 300)/2.7));
                                //    Debug.WriteLine($"PCR: {tsPacket.AdaptationField.Pcr}, PTS: {tsPacket.PesHeader.Pts}, Delta = {ts}");
                                //}

                                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.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!
                    }
                }

                if (start + TsPacketSize != data.Length)
                {
                    //we have 'residual' data to carry over to next call
                    _residualData = new byte[data.Length - start];
                    Buffer.BlockCopy(data, start, _residualData, 0, data.Length - start);
                }

                return(tsPackets);
            }

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

            return(null);
        }