Beispiel #1
0
        void PlaybackFromJitter(uint timeNow32)
        {
          //  if (_stream.Stream.Debug) _subtLocalPeer.WriteToLog($">> PlaybackFromJitter count={_jitterBuffer.Count}");
            if (_jitterBuffer.Count != 0)
            {
                // simulate playback from JB		
                var newestTimestampInSimulatedJitterBuffer = _jitterBuffer.Last.Value.timestamp32;

                // determine TS value of currently played frame
                var maxAllowedTimestampInSimulatedJitterBuffer = unchecked(newestTimestampInSimulatedJitterBuffer - SubtLogicConfiguration.JitterBufferLengthTicks);

               // if (_stream.Stream.Debug) Debugger.Break();

                // remove oldest frames which are being played
                for (;;)
                {
                    var oldestItem = _jitterBuffer.First;
                    if (oldestItem == null)
                        break;
                    if (MiscProcedures.TimeStamp1IsLess(oldestItem.Value.timestamp32, maxAllowedTimestampInSimulatedJitterBuffer) == false)
                    {
                  //      if (_stream.Stream.Debug) _subtLocalPeer.WriteToLog(
                  //          $"<< PlaybackFromJitter count={_jitterBuffer.Count} oldestTS={oldestItem.Value.timestamp32}, maxAllowedTimestampInSimulatedJitterBuffer={maxAllowedTimestampInSimulatedJitterBuffer}, newestTimestamp={newestTimestampInSimulatedJitterBuffer}");
                        break;
                    }

                    OnPlayed(oldestItem.Value, timeNow32);
                    _jitterBuffer.RemoveFirst();
                }
            }
        }
Beispiel #2
0
        void SendStatusIfNeeded(uint timestamp32)
        {
            if (_lastTimeSentStatus == null ||
                MiscProcedures.TimeStamp1IsLess(_lastTimeSentStatus.Value + SubtLogicConfiguration.RxMeasurementsTransmissionIntervalTicks, timestamp32)
                )
            {
                _lastTimeSentStatus = timestamp32;
                var remotePeerId = SubtConnectedPeer.RemotePeerId;
                if (remotePeerId != null)
                {
                    bool iwantToIncreaseBandwidthUntilHighPacketLoss = false;
                    if (SubtLocalPeer.LocalPeer.Configuration.RoleAsUser)
                    { // initially this signal comes from user
                        iwantToIncreaseBandwidthUntilHighPacketLoss = SubtLocalPeer.Configuration.BandwidthTargetMbps == null;
                    }
                    else if (SubtLocalPeer.LocalPeer.Configuration.RoleAsSharedPassive)
                    { // and then gets reflected from sharedPassive peers
                        iwantToIncreaseBandwidthUntilHighPacketLoss = LatestRemoteStatus?.IwantToIncreaseBandwidthUntilHighPacketLoss == true;
                    }

                    var data = new SubtRemoteStatusPacket(_rxMeasurement.RecentBandwidth, _rxMeasurement.RecentPacketLoss,
                                                          this.RecentTxBandwidth,
                                                          iwantToIncreaseBandwidthUntilHighPacketLoss,
                                                          SubtLocalPeer.LocalPeer.Configuration.RoleAsSharedPassive)
                               .Encode(this);
                    _stream.SendPacket(data, data.Length);
                }
            }
        }
Beispiel #3
0
        void RetransmitBandwidthAdjustmentRequestIfNeeded(uint timestamp32) // sender thread
        {
            var p = PendingAdjustmentRequestPacketData;                     // save it to this (sender) thread

            if (p != null && _lastTimeSentBandwidthAdjustmentRequest != null &&
                MiscProcedures.TimeStamp1IsLess(_lastTimeSentBandwidthAdjustmentRequest.Value + SubtLogicConfiguration.SubtAdjustmentRequestTransmissionIntervalTicks, timestamp32)
                )
            {
                _lastTimeSentBandwidthAdjustmentRequest = timestamp32;
                _stream.SendPacket(p, p.Length);
            }
        }
Beispiel #4
0
        void ThreadEntry()
        {
            var        sw           = Stopwatch.StartNew();
            var        previousTs32 = _localPeer.LocalPeer.Time32;
            const uint period32     = (uint)TimeSpan.TicksPerMillisecond * 10;
            int        counter      = 0;

            while (!_disposing)
            {
                try
                {
                    _actionsQueue.ExecuteQueued();

                    var timeNow32 = _localPeer.LocalPeer.Time32;

                    while (MiscProcedures.TimeStamp1IsLess(previousTs32, timeNow32) && !_disposing)
                    {
                        if (_debug)
                        {
                            Debugger.Break();
                        }

                        previousTs32 = unchecked (previousTs32 + period32);
                        foreach (var stream in _streams.Values)
                        {
                            stream.SendPacketsIfNeeded_10ms();
                        }
                        counter++;
                        if (counter % 10 == 0)
                        {
                            foreach (var stream in _streams.Values)
                            {
                                stream.SendPayloadPacketsIfNeeded_100ms();
                            }
                        }
                        if (counter % 100 == 0)
                        {
                            foreach (var stream in _streams.Values)
                            {
                                stream.SendPayloadPacketsIfNeeded_1s();
                            }
                        }
                    }
                }
                catch (Exception exc)
                {
                    _localPeer.HandleException(exc);
                }
                Thread.Sleep(10);
            }
        }
Beispiel #5
0
        bool TryInsertIntoJitterBuffer(JitterBufferElement jbe)
        {
            // _subtLocalPeer.WriteToLog($">> TryInsertIntoJitterBuffer strm{_stream.StreamId} count={_jitterBuffer.Count} ts={jbe.timestamp32} seq={jbe.sequence} last (newest) TS={_jitterBuffer.Last?.Value?.timestamp32}");

            if (IsNewElementOutOfSequence(jbe)) return false;

            LinkedListNode<JitterBufferElement> insertAfter = null;
            for (var item = _jitterBuffer.Last; ;)
            {
                if (item == null) break;
                var enumeratedSequence = item.Value.sequence;
                if (enumeratedSequence == jbe.sequence) return false; // duplicate packet
                if (Sequence1IsLess(enumeratedSequence, jbe.sequence))
                {
                    insertAfter = item;
                    break;
                }
                item = item.Previous;
            }

            if (insertAfter == null)
            {
                //if (_jitterBuffer.First != null)
                //{
                //    if (TimeStamp1IsLess(_jitterBuffer.First.Value.timestamp32, jbe.timestamp32))
                //    {
                //        // throw new Exception();
                //        _subtLocalPeer.WriteToLog($"strm{_stream.StreamId} count={_jitterBuffer.Count}. bad item put into JB: ts={jbe.timestamp32} seq={jbe.sequence} firstTS={_jitterBuffer.First.Value.timestamp32}  firstSeq={_jitterBuffer.First.Value.sequence} ");
                //        foreach (var item in _jitterBuffer)
                //            _subtLocalPeer.WriteToLog($"strm{_stream.StreamId} item: TS={item.timestamp32}  seq={item.sequence} ");                        
                //        return false;
                //    }
                //}
                _jitterBuffer.AddFirst(jbe);
            }
            else
            {
                if (MiscProcedures.TimeStamp1IsLess(jbe.timestamp32, insertAfter.Value.timestamp32))
                {
                    _subtLocalPeer.WriteToLog_lightPain($"JB corruption check: received {jbe}; first: {_jitterBuffer.First?.Value}; last: {_jitterBuffer.Last?.Value}");
                    return false;
                    //throw new Exception();
                }
                _jitterBuffer.AddAfter(insertAfter, jbe);
            }

          //  if (_stream.Stream.Debug)
        //        CheckJitterBuffer();

            return true;
        }
Beispiel #6
0
        void CheckJitterBuffer()
        {
            ushort? previousSeq = null;
            uint? previousTs32 = null;
            foreach (var jbe in _jitterBuffer)
            {
                if (previousSeq.HasValue && Sequence1IsLess(jbe.sequence, previousSeq.Value))
                    throw new Exception();
                if (previousTs32.HasValue && MiscProcedures.TimeStamp1IsLess(jbe.timestamp32, previousTs32.Value))
                    throw new Exception();

                previousSeq = jbe.sequence;
                previousTs32 = jbe.timestamp32;
            }
        } 
Beispiel #7
0
        /// <summary>
        /// if this procedure is used - "OnTimePassed" must not be called externally
        /// </summary>
        public void OnTimeObserved(uint timeNow32)
        {
            if (_latestTimeObserved.HasValue)
            {
                if (MiscProcedures.TimeStamp1IsLess(timeNow32, _latestTimeObserved.Value))
                {
                    // can happen if 2 threads use this class instance in parallel, and each thread calls this procedure.  it is normal situation, when "timeNow32" is a 'little bit' less than "_latestTimeObserved"
                    //  todo event for developer  in case of "high" jumps?
                    return;
                }

                OnTimePassed(unchecked (timeNow32 - _latestTimeObserved.Value));
            }
            _latestTimeObserved = timeNow32;
        }
Beispiel #8
0
 void SendStatusIfNeeded(uint timestamp32) // sender thread
 {
     if (_lastTimeSentStatus == null ||
         MiscProcedures.TimeStamp1IsLess(_lastTimeSentStatus.Value + SubtLogicConfiguration.SubtRemoteStatusPacketTransmissionIntervalTicks, timestamp32)
         )
     {
         _lastTimeSentStatus = timestamp32;
         var remotePeerId = SubtConnectedPeer.RemotePeerId;
         if (remotePeerId != null)
         {
             var statusPacket = new SubtRemoteStatusPacket(_rxMeasurement.RecentBandwidth, _rxMeasurement.RecentPacketLoss,
                                                           this.RecentTxBandwidth,
                                                           SubtLocalPeer.LocalPeer.Configuration.RoleAsSharedPassive,
                                                           SubtLocalPeer.ImHealthyAndReadyFor100kbpsU2uSymbiosis
                                                           );
             var data = statusPacket.Encode(this);
             _stream.SendPacket(data, data.Length);
         }
     }
 }
        void SendStatusIfNeeded(uint timestamp32) // sender thread
        {
            if (_lastTimeSentStatus == null ||
                MiscProcedures.TimeStamp1IsLess(_lastTimeSentStatus.Value + SubtLogicConfiguration.SubtRemoteStatusPacketTransmissionIntervalTicks, timestamp32)
                )
            {
                _lastTimeSentStatus = timestamp32;
                var remotePeerId = SubtConnectedPeer.RemotePeerId;
                if (remotePeerId != null)
                {
                    bool samePacketAlreadySent = false;
                    if (_lastSentSubtStatusPacket != null)
                    {
                        if (_lastSentSubtStatusPacket.ImHealthyAndReadyFor100kbpsU2uSymbiosis == SubtLocalPeer.ImHealthyAndReadyFor100kbpsU2uSymbiosis &&
                            _lastSentSubtStatusPacket.RecentTxBandwidth == this.RecentTxBandwidth &&
                            _lastSentSubtStatusPacket.RecentRxBandwidth == _rxMeasurement.RecentBandwidth)
                        {
                            samePacketAlreadySent = true;
                        }
                    }

                    if (!samePacketAlreadySent)
                    {
                        var statusPacket = new SubtRemoteStatusPacket(_rxMeasurement.RecentBandwidth, _rxMeasurement.RecentPacketLoss,
                                                                      this.RecentTxBandwidth,
                                                                      SubtLocalPeer.LocalPeer.Configuration.RoleAsSharedPassive,
                                                                      SubtLocalPeer.ImHealthyAndReadyFor100kbpsU2uSymbiosis
                                                                      );
                        //  SubtLocalPeer.WriteToLog_deepDetail($"sending SUBT status packet: {statusPacket} to peer {SubtConnectedPeer.RemotePeerId}");
                        var data = statusPacket.Encode(this);
                        _stream.SendPacket(data, data.Length);
                        _lastSentSubtStatusPacket = statusPacket;
                    }
                }
            }
        }