コード例 #1
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." });
        }
コード例 #2
0
        protected virtual void OnPacketReady(PacketReadyEventArgs e)
        {
            var handler = PacketReady;

            handler?.Invoke(this, e);
        }