public void Enqueue(Data <TPayload> data) { long payloadPts = data.Payload.GetPts(); long payloadTime = payloadPts * Fps / 10_000_000; lock (this) { if (_version != -1 && _version != data.Version) { _next.Enqueue(data); } else if (_currentTimeTick == -1) // init { if (payloadTime != 0) { _currentTimeTick = payloadTime; } _next.Enqueue(data); } else { long bestTime = _currentTimeTick + 1; if (payloadTime < bestTime - _maxDeviation) { _payloadPool.Back(data.Payload); _statisticKeeper.Data.Dropped++; } else { long sendCount = 1; if (payloadTime > bestTime + _maxDeviation) { sendCount += payloadTime - bestTime - _maxDeviation + 1; if (sendCount > Fps * 1.5) // > 1.5 sec gap { _statisticKeeper.Data.Errors++; Core.LogWarning($"FPS filtering {Name} encountered gap of {sendCount} packets", "FPS filtering encountered gap"); } } if (_overloadController != null) { _overloadController.Increment(ref _currentTimeTick, sendCount); } else { _currentTimeTick += sendCount; } _next.Enqueue(data); } } } }
public ErrorCodes Read(Frame resultPayload, out PayloadTrace resultTrace) { long now = Core.GetCurrentTime(); _lastReadTime = now; long currentFpsTime = ToTime(_currentFpsTicks); long currentFrameDelay = now - currentFpsTime; if (currentFrameDelay > _setup.MaxDelay) //2 sec { // we too late Core.LogError($"Blender skips batch due to high delay from now {currentFrameDelay / 10_000}ms"); _currentFpsTicks = ToTicks(now - _setup.ComebackDelay); // -300 ms currentFpsTime = ToTime(_currentFpsTicks); currentFrameDelay = now - currentFpsTime; } bool runtimesReady = currentFrameDelay > 0; // don't go behind real-time. Especially relevant for cases when all _inputRuntimes are Fixed images if (currentFrameDelay > 0 && currentFrameDelay <= _delayFromRuntime) { foreach (var runtime in _inputRuntimes) { bool ok = false; if (runtime.Frames.Count > 0) { long first = ToTicks(runtime.Frames.First.Value.Payload.GetPts()); long last = ToTicks(runtime.Frames.Last.Value.Payload.GetPts()); if (_currentFpsTicks <= last) { ok = true; } } else if (runtime.FixedFrame != null) { ok = true; } if (!ok) { runtimesReady = false; break; } } } // prepare frame if (runtimesReady) { bool hasAnyContent; if (_setup.Dx == null) { hasAnyContent = RenderFFMpeg(resultPayload, out resultTrace); } else { hasAnyContent = RenderDirectX(resultPayload, out resultTrace); } if (hasAnyContent) { if (_overloadController == null) { _currentFpsTicks += 1; } else { _overloadController.Increment(ref _currentFpsTicks, 1); } return(ErrorCodes.Ok); } } resultTrace = null; return(ErrorCodes.TryAgainLater); }