Esempio n. 1
0
        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);
        }