Пример #1
0
        private static void FileStreamWorkerThread(Stream stream)
        {
            var data    = new byte[188];
            var factory = new TsPacketFactory();

            while (stream?.Read(data, 0, 188) > 0)
            {
                try
                {
                    var tsPackets = factory.GetTsPacketsFromData(data);

                    if (tsPackets == null)
                    {
                        break;
                    }

                    _analyser.AnalysePackets(tsPackets);
                }
                catch (Exception ex)
                {
                    LogMessage($@"Unhandled exception within file streamer: {ex.Message}");
                }
            }

            _pendingExit = true;
            Thread.Sleep(250);

            Console.WriteLine("Completed reading of file - hit enter to exit!");
            Console.ReadLine();
        }
Пример #2
0
        private static void PerformUnalignedDataTest(string filename, int expectedPacketCount, int readFragmentSize)
        {
            try
            {
                var factory = new TsPacketFactory();

                //load some data from test file
                using (var stream = File.Open(filename, FileMode.Open))
                {
                    var packetCounter = 0;

                    var data = new byte[readFragmentSize];

                    var readCount = stream.Read(data, 0, readFragmentSize);

                    while (readCount > 0)
                    {
                        try
                        {
                            if (readCount < readFragmentSize)
                            {
                                var tmpArr = new byte[readCount];
                                Buffer.BlockCopy(data, 0, tmpArr, 0, readCount);
                                data = new byte[readCount];
                                Buffer.BlockCopy(tmpArr, 0, data, 0, readCount);
                            }

                            var tsPackets = factory.GetTsPacketsFromData(data);

                            if (tsPackets == null)
                            {
                                break;
                            }

                            packetCounter += tsPackets.Length;

                            if (stream.Position < stream.Length)
                            {
                                readCount = stream.Read(data, 0, readFragmentSize);
                            }
                            else
                            {
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            Assert.Fail($@"Unhandled exception reading sample file: {ex.Message}");
                        }
                    }

                    if (packetCounter != expectedPacketCount)
                    {
                        Assert.Fail($"Failed to read expected number of packets in sample file - expected {expectedPacketCount}, " +
                                    $"got {packetCounter}, blocksize: {readFragmentSize}");
                    }
                }
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }
Пример #3
0
        private void ProcessQueueWorkerThread()
        {
            var dataBuffer = new byte[12 + (188 * 7)];

            while (_pendingExit != true)
            {
                try
                {
                    lock (_ringBuffer)
                    {
                        int   dataSize;
                        ulong timestamp;

                        if (_ringBuffer.BufferFullness < 10)
                        {
                            Thread.Sleep(1);
                            continue;
                        }

                        var capacity = _ringBuffer.Remove(ref dataBuffer, out dataSize, out timestamp);

                        if (capacity > 0)
                        {
                            dataBuffer = new byte[capacity];
                            continue;
                        }

                        if (dataBuffer == null)
                        {
                            continue;
                        }

                        var packets = Factory.GetTsPacketsFromData(dataBuffer, dataSize);

                        //use decoder to register default program (muxing always happens on default program)
                        if (_mainStreamDecoder.GetSelectedPmt() == null)
                        {
                            _mainStreamDecoder.AddPackets(packets);
                        }
                        else
                        {
                            if (_mainStreamTargetPmt == null && _subStreamSourcePmt != null)
                            {
                                _mainStreamTargetPmt = _mainStreamDecoder.GetSelectedPmt();

                                var pmtSpaceNeeded = 0;
                                foreach (var esinfo in _subStreamSourcePmt.EsStreams)
                                {
                                    if (_subPids.Contains(esinfo.ElementaryPid))
                                    {
                                        pmtSpaceNeeded += esinfo.SourceData.Length;
                                    }
                                }

                                if ((_mainStreamTargetPmt.SectionLength + pmtSpaceNeeded) > (TsPacketSize - 12))
                                {
                                    throw new InvalidDataException(
                                              "Cannot add to PMT - no room (packet spanned PMT not supported)");
                                }
                            }
                        }

                        //check for any PMT packets, and adjust them to reflect the new muxed reality...
                        foreach (var packet in packets)
                        {
                            if (_mainStreamTargetPmt != null && packet.Pid == _mainStreamTargetPmt.Pid)
                            {
                                //this is the PMT for the target program on the target stream - patch in the substream PID entries
                                foreach (var esinfo in _subStreamSourcePmt.EsStreams)
                                {
                                    if (_subPids.Contains(esinfo.ElementaryPid))
                                    {
                                        //locate current SectionLength bytes in databuffer
                                        var pos = packet.SourceBufferIndex +
                                                  4;         //advance to start of PMT data structure (past TS header)
                                        var pointerField = dataBuffer[pos];
                                        pos += pointerField; //advance by pointer field
                                        var SectionLength =
                                            (short)(((dataBuffer[pos + 2] & 0x3) << 8) +
                                                    dataBuffer[pos + 3]);  //get current length

                                        //increase length value by esinfo length
                                        var extendedSectionLength =
                                            (short)(SectionLength + (short)esinfo.SourceData.Length);

                                        //set back new length into databuffer
                                        var bytes = BitConverter.GetBytes(extendedSectionLength);
                                        dataBuffer[pos + 2] =
                                            (byte)((dataBuffer[pos + 2] & 0xFC) + (byte)(bytes[1] & 0x3));
                                        dataBuffer[pos + 3] = bytes[0];

                                        //copy esinfo source data to end of program block in pmt
                                        Buffer.BlockCopy(esinfo.SourceData, 0, dataBuffer,
                                                         packet.SourceBufferIndex + 4 + pointerField + SectionLength,
                                                         esinfo.SourceData.Length);

                                        //correct CRC after each extension
                                        var crcBytes = BitConverter.GetBytes(GenerateCRC(ref dataBuffer, pos + 1,
                                                                                         extendedSectionLength - 1));
                                        dataBuffer[packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength]
                                            = crcBytes[3];
                                        dataBuffer[
                                            packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength +
                                            1] =
                                            crcBytes[2];
                                        dataBuffer[
                                            packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength +
                                            2] =
                                            crcBytes[1];
                                        dataBuffer[
                                            packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength +
                                            3] =
                                            crcBytes[0];
                                    }
                                }
                            }
                        }

                        //insert any queued filtered sub PID packets
                        if (_subPidBuffer.BufferFullness > 0)
                        {
                            foreach (var packet in packets)
                            {
                                if (packet.Pid == (short)PidType.NullPid)
                                {
                                    //candidate for wiping with any data queued up for muxing in
                                    byte[] subPidPacketBuffer = new byte[TsPacketSize];
                                    int    subPidDataSize     = 0;
                                    ulong  subPidTimeStamp    = 0;

                                    //see if there is any data waiting to get switched into the mux...
                                    lock (_subPidBuffer)
                                    {
                                        if (_subPidBuffer.BufferFullness < 1)
                                        {
                                            break; //double check here because prior check was not thread safe
                                        }
                                        var subPidPacketDataReturned = _subPidBuffer.Remove(ref subPidPacketBuffer,
                                                                                            out subPidDataSize, out subPidTimeStamp);
                                        if (subPidPacketDataReturned != 0 && subPidPacketDataReturned != TsPacketSize)
                                        {
                                            PrintToConsole("Sub PID data seems to not be size of TS packet!");
                                            return;
                                        }
                                    }

                                    if (packet.SourceBufferIndex % 188 != 0)
                                    {
                                        PrintToConsole("Misaligned packet");
                                        return;
                                    }

                                    Buffer.BlockCopy(subPidPacketBuffer, 0, dataBuffer, packet.SourceBufferIndex,
                                                     TsPacketSize);
                                }
                            }
                        }
                        var packetReadyEventArgs = new PacketReadyEventArgs();
                        packetReadyEventArgs.UdpPacketData = new byte[dataSize];
                        Buffer.BlockCopy(dataBuffer, 0, packetReadyEventArgs.UdpPacketData, 0, dataSize);
                        OnPacketReady(packetReadyEventArgs);
                    }
                }
                catch (Exception ex)
                {
                    PrintToConsole($@"Unhandled exception within network receiver: {ex.Message}");
                }
            }

            //Logger.Log(new TelemetryLogEventInfo { Level = LogLevel.Info, Message = "Stopping analysis thread due to exit request." });
        }
Пример #4
0
        private void btnScan_Click(object sender, EventArgs e)
        {
            if (lvResult.Items.Count > 0)
            {
                lvResult.Items.Clear();
            }
            //StartScanThread();
            _decoder.TableChangeDetected += _decoder_TableChangeDetected;
            var programMapTables = new List <ProgramMapTable>();

            _isScanning   = true;
            _stopScanning = false;
            SetControlPropertyThreadSafe(btnScan, "Text", "Stop Search");
            programMapTables.Clear();
            patfound  = false;
            pmtsfound = false;
            nitfound  = false;
            sdtfound  = false;
            SetControlPropertyThreadSafe(lblPat, "BackColor", Color.LightGreen);
            SetControlPropertyThreadSafe(lblPmt, "BackColor", Color.LightGreen);
            SetControlPropertyThreadSafe(lblSdt, "BackColor", Color.LightGreen);
            SetControlPropertyThreadSafe(lblNit, "BackColor", Color.LightGreen);
            if (_stopScanning)
            {
                return;
            }

            RtspStatusCode statuscode;

            if (string.IsNullOrEmpty(_device.RtspSession.SessionID))
            {
                _device.RtspSession.Options();
                _device.RtspSession.Setup(_currenttunestring, TransmissionMode.Unicast);
                _device.RtspSession.Play(_currenttunestring);
                _udpclient      = new UdpClient(_device.RtspSession.RtpPort);
                _remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                _device.RtspSession.RecieptionInfoChanged += RtspSession_RecieptionInfoChanged;
            }
            else
            {
                _device.RtspSession.Play(_currenttunestring);
            }

            /* Say the Sat>IP server we want Receives the Recieption Details SDP */
            statuscode = _device.RtspSession.Describe();

            if (_locked)
            {
                while (!patfound || !pmtsfound || !sdtfound || !nitfound)
                {
                    var receivedbytes = _udpclient.Receive(ref _remoteEndPoint);
                    var rtp           = RtpPacket.Decode(receivedbytes);
                    if (rtp.HasPayload)
                    {
                        var packets = packetFactory.GetTsPacketsFromData(rtp.Payload);

                        Logger.Write(rtp.Payload.ToHexString());
                        _decoder.AddData(receivedbytes);
                    }

                    //}
                    lock (_decoder)
                    {
                        programMapTables = _decoder?.ProgramMapTables.OrderBy(p => p.ProgramNumber).ToList();
                        foreach (var programMapTable in programMapTables)
                        {
                            short videoPid = -1;
                            short audioPid = -1;
                            short ac3pid   = -1;
                            short ttxpid   = -1;
                            short subpid   = -1;
                            var   desc     = _decoder.GetServiceDescriptorForProgramNumber(programMapTable?.ProgramNumber);
                            if (desc != null)
                            {
                                if (programMapTable?.EsStreams != null)
                                {
                                    foreach (var stream in programMapTable.EsStreams)
                                    {
                                        if (stream != null)
                                        {
                                            if (stream.Descriptors.OfType <Ac3Descriptor>().Any())
                                            {
                                                ac3pid = stream.ElementaryPid;
                                            }
                                            if (stream.Descriptors.OfType <Eac3Descriptor>().Any())
                                            {
                                                ac3pid = stream.ElementaryPid;
                                            }
                                            if (stream.Descriptors.OfType <SubtitlingDescriptor>().Any())
                                            {
                                                subpid = stream.ElementaryPid;
                                            }
                                            if (stream.Descriptors.OfType <TeletextDescriptor>().Any())
                                            {
                                                ttxpid = stream.ElementaryPid;
                                            }
                                            switch (stream.StreamType)
                                            {
                                            case 0x01: // ISO/IEC 11172-2 (MPEG-1 video) in a packetized stream
                                            case 0x02
                                                :      // ITU-T Rec. H.262 and ISO/IEC 13818-2 (MPEG-2 higher rate interlaced video) in a packetized stream
                                            case 0x1B
                                                :      // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video) in a packetized stream
                                            case 0x24
                                                :      // ITU - T Rec.H.265 and ISO/ IEC 23008 - 2(Ultra HD video) in a packetized stream
                                            {
                                                videoPid = stream.ElementaryPid;
                                                break;
                                            }

                                            case 0x03: // ISO/IEC 11172-3 (MPEG-1 audio) in a packetized stream
                                            case 0x04
                                                :      // ISO/IEC 13818-3 (MPEG-2 halved sample rate audio) in a packetized stream

                                            {
                                                audioPid = stream.ElementaryPid;
                                                break;
                                            }

                                            default:
                                            {
                                                Console.Write(stream.StreamType.ToString());
                                                break;
                                            }
                                            }
                                        }
                                    }
                                }

                                var chan = new Channel
                                {
                                    ServiceType             = desc.ServiceType,
                                    ServiceName             = desc.ServiceName.Value,
                                    ServiceProvider         = desc.ServiceProviderName.Value,
                                    ServiceId               = programMapTable.ProgramNumber,
                                    ProgramClockReferenceId = programMapTable.PcrPid,
                                    AudioPid    = audioPid,
                                    VideoPid    = videoPid,
                                    AC3Pid      = ac3pid,
                                    TTXPid      = ttxpid,
                                    SubTitlePid = subpid
                                };
                                AddResults(chan);
                            }
                        }
                    }
                }

                //Thread.Sleep(55000);
                _device.RtspSession.TearDown();
                SetControlPropertyThreadSafe(pgbSearchResult, "Value", 100);
                _isScanning = false;
                SetControlPropertyThreadSafe(btnScan, "Text", "Start Search");
            }
        }