private void UpdateTrace(Data <Frame> frameData, ref PayloadTrace trace) { if (frameData.Trace != null) { if (trace == null) { trace = PayloadTrace.Create(_name, frameData.Trace, 0); } else { trace.AddPrevious(frameData.Trace); } } }
private bool RenderFFMpeg(Frame resultPayload, out PayloadTrace trace) { bool first = true; trace = null; var frames = _inputRuntimesSorted.Where(s => s.Description.Visible). Select(s => new { runtime = s, frameData = GetRuntimeOrFixedFrame(s) }). Where(s => s.frameData != null).ToList(); if (frames.Count == 1) { resultPayload.CopyContentFromAndSetPts(frames[0].frameData.Payload, _currentFpsTicks); } else if (frames.Count > 1) { Frame frameMainCopy = null; foreach (var s in frames) { var frameData = s.frameData; var runtime = s.runtime; var frame = frameData.Payload; UpdateTrace(frameData, ref trace); if (first) { frameMainCopy = _framePool.Rent(); frameMainCopy.CopyContentFrom(frame); _helper.Init(frameMainCopy, _setup.WeakOptions.PixelFormatGroup.BlendType); first = false; } else { if (frame.Properties.Height != runtime.SlicesHeight) { runtime.SlicesHeight = frame.Properties.Height; runtime.Slices = GetSlices(runtime, frame.Properties.Height); } int x = (int)(runtime.Description.Rect.Left * _setup.Width); int y = (int)(runtime.Description.Rect.Top * _setup.Height); if (runtime.Slices == null) { _helper.Add(frame, x, y, 0, frame.Properties.Height); } else { Task.WhenAll(runtime.Slices.Select(s => Task.Run(() => _helper.Add(frame, x, y, s.yOffset, s.yCount))).ToArray()).Wait(); } } } _helper.Get(resultPayload, _currentFpsTicks); _framePool.Back(frameMainCopy); } if (frames.Count > 0) { if (trace != null) { trace = PayloadTrace.Create(_name, trace); } if (resultPayload.Properties.Width != _setup.Width || resultPayload.Properties.Height != _setup.Height || resultPayload.Properties.Format != _setup.OutputPixelFormat) { Core.LogWarning($"Ignoring wrongly blended packet " + $"{resultPayload.Properties.Width}x{resultPayload.Properties.Height}x{resultPayload.Properties.Format} != Setup({_setup.Width}x{_setup.Height}x{_setup.OutputPixelFormat})"); return(false); } return(true); } return(false); }
private bool RenderDirectX(Frame resultPayload, out PayloadTrace trace) { trace = null; bool hasAnyContent = false; var dx = _setup.Dx; try { if (dx.IsBrokenAndLog("Blender")) { return(false); } var texture = dx.Pool.Get("Blender", DirectXResource.Desc(_setup.Width, _setup.Height, SharpDX.DXGI.Format.B8G8R8A8_UNorm, BindFlags.ShaderResource | BindFlags.RenderTarget, ResourceUsage.Default, ResourceOptionFlags.None)); _defferedContext = _defferedContext ?? new DeviceContext(dx.Device); //using using (var rtv = texture.GetRenderTargetView()) { int counter = 0; foreach (var runtime in _inputRuntimesSorted) { var frameData = GetRuntimeOrFixedFrame(runtime); if (frameData != null && runtime.Description.Visible) { hasAnyContent = true; UpdateTrace(frameData, ref trace); var xResource = frameData.Payload.DirectXResourceRef.Instance; if (xResource.CommandList != null) { _defferedContext.ExecuteCommandList(xResource.CommandList, false); xResource.CommandList.Dispose(); xResource.CommandList = null; } var pipeline = GetPipeline(runtime, texture, xResource); SetDebugColor(pipeline, counter++); UpdatePositionInDxPipeline(runtime, pipeline, xResource.Texture2D.Description.Width, xResource.Texture2D.Description.Height); var filteredResource = runtime.DirectXFilterRuntime.Render(dx, runtime.Description.FilterChain, _defferedContext, xResource); if (ReferenceEquals(filteredResource, xResource)) { using (var srv = filteredResource.GetShaderResourceView()) pipeline.Render(_defferedContext, rtv, srv); dx.Flush(_defferedContext, "Blender Flush All"); } else { dx.Flush(_defferedContext, "Blender Flush All"); using (var srvFiltered = filteredResource.GetShaderResourceView()) pipeline.Render(_defferedContext, rtv, srvFiltered); dx.Flush(_defferedContext, "Blender Flush All"); filteredResource.Dispose(); } } } } if (hasAnyContent) { if (trace != null) { trace = PayloadTrace.Create(_name, trace); } dx.Flush(_defferedContext, "Blender Flush All"); var allFilteredResource = _dxFilterRuntime.Render(dx, _setup.WeakOptions.FilterChain, _defferedContext, texture); dx.Flush(_defferedContext, "Blender Flush All"); resultPayload.InitFromDirectX(allFilteredResource, _currentFpsTicks); if (allFilteredResource != texture) { dx.Pool.Back(texture); } } } catch (Exception e) { dx.Broken(e); } return(hasAnyContent); }
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); }
protected override void ProcessData(Data <Frame> data, ContextVersion <IEncoderContext, EncoderSetup, Packet> currentVersion) { _statisticKeeper.Data.InFrames++; //unsafe, but ok lock (this) { if (currentVersion == null || currentVersion.Context == null) { Streamer.FramePool.Back(data.Payload); return; } data.Trace?.Received(Name); bool enforceIFrame = false; if (_makeIFrameNextPacket == data.Version && currentVersion.ContextSetup.SupportsEnforcingIFrame) { Core.LogInfo("Trying to enforce IFrame on encoder"); _makeIFrameNextPacket = 0; enforceIFrame = true; } int writeRes = currentVersion.Context.Instance.Write(data.Payload, enforceIFrame); Streamer.FramePool.Back(data.Payload); if (Core.IsFailed(writeRes)) { _statisticKeeper.Data.Errors++; Core.LogError($"Write to {Name}: {Core.GetErrorMessage(writeRes)}", "write to node failed"); return; } while (!currentVersion.IsInterrupted) { var resultPayload = Streamer.PacketPool.Rent(); var readRes = currentVersion.Context.Instance.Read(resultPayload); if (readRes == ErrorCodes.TryAgainLater) { Streamer.PacketPool.Back(resultPayload); break; } else if (Core.IsFailed(readRes)) { _statisticKeeper.Data.Errors++; Streamer.PacketPool.Back(resultPayload); Core.LogError($"Read from {Name}: {Core.GetErrorMessage(writeRes)}", "read from node failed"); break; } else // success { _statisticKeeper.Data.OutFrames++; //unsafe, but ok currentVersion.OutputQueue.Enqueue(new Data <Packet>(resultPayload, currentVersion.Version, data.SequenceNumber, PayloadTrace.Create(Name, data.Trace))); } } } }
protected override void ProcessData(Data <Frame> data, ContextVersion <IFilterContext, FilterSetup, Frame> currentVersion) { //if (Name.Name == "FMix" && data.Payload != null) //{ // Core.LogInfo($"--------------------------------In {Name} {data.SourceId} {data.Payload.Properties.Pts}"); //} _statisticKeeper.Data.InFrames++; //unsafe, but ok if (currentVersion == null) { Streamer.FramePool.Back(data.Payload); return; } data.Trace?.Received(Name); var instance = currentVersion.Context.Instance; //using var mem = new TimeMeasurer($"Filter '{Name}'"); int writeRes = instance.Write(data.Payload, data.SourceId); if (writeRes == (int)ErrorCodes.NullFilter) { _statisticKeeper.Data.OutFrames++; //unsafe, but ok currentVersion.OutputQueue.Enqueue(data); return; } Streamer.FramePool.Back(data.Payload); if (Core.IsFailed(writeRes)) { _statisticKeeper.Data.Errors++; Core.LogError($"Write to {Name} (sid:{data.SourceId}): {Core.GetErrorMessage(writeRes)}", "write to node failed"); return; } while (!currentVersion.IsInterrupted) { var resultPayload = Streamer.FramePool.Rent(); var readRes = instance.Read(resultPayload); if (readRes == ErrorCodes.TryAgainLater) { Streamer.FramePool.Back(resultPayload); break; } else if (Core.IsFailed(readRes)) { _statisticKeeper.Data.Errors++; Streamer.FramePool.Back(resultPayload); Core.LogError($"Read from {Name}: {Core.GetErrorMessage((int)readRes)}", "read from node failed"); break; } else // success { //if (Name.Name == "FMix" && data.Payload != null) //{ // Core.LogInfo($"----------------------------------Out {Name} - {resultPayload.Properties.Pts}"); //} _statisticKeeper.Data.OutFrames++; //unsafe, but ok currentVersion.OutputQueue.Enqueue(new Data <Frame>(resultPayload, currentVersion.Version, data.SequenceNumber, PayloadTrace.Create(Name, data.Trace))); } } }
protected override void ProcessData(Data <Packet> data, ContextVersion <IDecoderContext, DecoderSetup, Frame> currentVersion) { _statisticKeeper.Data.InFrames++; //unsafe, but ok if (currentVersion == null) { Streamer.PacketPool.Back(data.Payload); return; } data.Trace?.Received(Name); int writeRes = currentVersion.Context.Instance.Write(data.Payload); Streamer.PacketPool.Back(data.Payload); if (Core.IsFailed(writeRes)) { _statisticKeeper.Data.Errors++; Core.LogError($"Write to {Name}: {Core.GetErrorMessage(writeRes)}", "write to node failed"); return; } while (!currentVersion.IsInterrupted) { var resultPayload = Streamer.FramePool.Rent(); var readRes = currentVersion.Context.Instance.Read(resultPayload); if (readRes == ErrorCodes.TryAgainLater) { Streamer.FramePool.Back(resultPayload); break; } else if (Core.IsFailed(readRes)) { _statisticKeeper.Data.Errors++; Streamer.FramePool.Back(resultPayload); Core.LogError($"Read from {Name}: {Core.GetErrorMessage(writeRes)}", "read from node failed"); break; } else // success { _statisticKeeper.Data.OutFrames++; //unsafe, but ok currentVersion.OutputQueue.Enqueue(new Data <Frame>(resultPayload, currentVersion.Version, data.SequenceNumber, PayloadTrace.Create(Name, data.Trace))); } } }