private Data <Frame> GetRuntimeFrame(VideoBlenderInputRuntime runtime)
        {
            if (runtime.Frames.Count > 0)
            {
                long first = ToTicks(runtime.Frames.First.Value.Payload.GetPts());

                if (_currentFpsTicks < first)
                {
                    return(runtime.Frames.First.Value);
                }


                if (first + runtime.Tension >= _currentFpsTicks && runtime.Tension > -1)
                {
                    runtime.Tension--;
                }

                while (first + runtime.Tension < _currentFpsTicks && runtime.Frames.Count > 1)
                {
                    _framePool.Back(runtime.Frames.First.Value.Payload);
                    runtime.Frames.RemoveFirst();
                    first = ToTicks(runtime.Frames.First.Value.Payload.GetPts());

                    if (first + runtime.Tension < _currentFpsTicks && runtime.Tension < 1) // this is kind of shock absorber. Can have values from -1 to 1
                    {
                        // no need to remove more this cycle
                        runtime.Tension++;
                    }
                }

                if (runtime.BlackScreenDelay >= 0 && ToTime(_currentFpsTicks) - ToTime(first) > runtime.BlackScreenDelay) // to old
                {
                    //Core.LogInfo($"{Core.FormatTicks(ToTime(_currentFpsTicks))} - {Core.FormatTicks(ToTime(first))} Blend NoSignal");
                    return(GetOrCreateNoSignalFrame(runtime));
                }
                else
                {
                    //Core.LogInfo($"{Core.FormatTicks(ToTime(_currentFpsTicks))} - {Core.FormatTicks(ToTime(first))} -({runtime.Frames.Count})- {Core.FormatTicks(runtime.Frames.Last.Value.Payload.GetPts())} Blend");
                    return(runtime.Frames.First.Value);
                }
            }
            else
            {
                var now = Core.GetCurrentTime();

                if (now - runtime.StartupTime > 500_0000) // 500 ms
                {
                    return(GetOrCreateNoSignalFrame(runtime));
                }
                else
                {
                    return(null);
                }
            }
        }
 private Data <Frame> GetRuntimeOrFixedFrame(VideoBlenderInputRuntime runtime)
 {
     if (runtime.FixedFrame == null)
     {
         return(GetRuntimeFrame(runtime));
     }
     else
     {
         return(new Data <Frame>(runtime.FixedFrame.Instance.Item, 0, 0, null));
     }
 }
 private DirectXPipeline <BlendingConstantBuffer> GetPipeline(VideoBlenderInputRuntime runtime, DirectXResource canvas, DirectXResource image)
 {
     if (_directXPipelineLowRes != null)
     {
         if (runtime.Description.Ptz.Width > 0 && runtime.Description.Ptz.Height > 0)
         {
             var heightScale = runtime.Description.Rect.Height / runtime.Description.Ptz.Height;
             var widthScale  = runtime.Description.Rect.Width / runtime.Description.Ptz.Width;
             if (heightScale * canvas.Texture2D.Description.Height < 0.8 * image.Texture2D.Description.Height ||
                 widthScale * canvas.Texture2D.Description.Width < 0.8 * image.Texture2D.Description.Width)
             {
                 return(_directXPipelineLowRes);
             }
         }
     }
     return(_directXPipeline);
 }
        private void UpdatePositionInDxPipeline(VideoBlenderInputRuntime runtime, DirectXPipeline <BlendingConstantBuffer> pipeline, int width, int height)
        {
            var rect = runtime.Description.Rect;
            var ptz  = runtime.Description.Ptz;

            var currect = runtime.VertexBuffer;

            pipeline.UpdatePosition(new RectangleF((float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height),
                                    new RectangleF((float)ptz.Left, (float)ptz.Top, (float)ptz.Width, (float)ptz.Height),
                                    runtime.Description.FilterChain?.HasHFlip() == true, runtime.Description.FilterChain?.HasVFlip() == true, ref currect);
            runtime.VertexBuffer = currect;

            pipeline.SetExternalPosition(new Viewport(0, 0, _setup.Width, _setup.Height), currect);

            pipeline.SetConstantBuffer(new BlendingConstantBuffer
            {
                ViewProj         = Matrix.Identity,
                base_dimension   = new Vector2(width, height),
                base_dimension_i = new Vector2(1f / width, 1f / height),
                undistort_factor = 1.0f
            }, true);
        }